用于检查精度的FPU指令

时间:2014-12-23 17:30:44

标签: delphi x86 fpu x87

使用fldcw指令可以将FPU单元的精度更改为24位或更多位。然而,经过一些测试后,我开始认为很少有x87操作实际上使用该设置。

我还没有对所有操作进行测试,但到目前为止,在这台测试机器上看起来只有fdiv和fsqrt停止以所选精度计算,并且所有其他操作(fadd fsub fmul ...)总是计算完全扩展精度。

如果是这种情况我会期望它是因为那些2条指令(fdiv和fsqrt)比大多数其他x87 FPU指令慢得多,所以当精度较低时,它可以加速它们,但是实际上,我只是想知道是否一直都是这种情况,或者它是否是我测试机中最近使用的处理器的一个怪癖。

编辑:这里显示的delphi代码

program Project1;

uses
  windows,dialogs,sysutils;

{$R *.res}

const
 test_mul:single=1234567890.0987654321;

var
 i:longint;
 s:single absolute i;
 s1,s2,s3:single;

procedure test_24;
asm
 mov word([esp-2]),$103f  // 24bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s1]
end;

procedure test_53;
asm
 mov word([esp-2]),$123f  // 53bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s2]
end;

procedure test_64;
asm
 mov word([esp-2]),$133f  // 64bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s3]
end;

begin
 i:=0;
 repeat
  test_24;
  test_53;
  test_64;

  if (s1<>s2) or (s2<>s3) then begin
   showmessage('Error at step:'+inttostr(i));
   break;
  end;

  inc(i);
 until i=0;
 showmessage('No difference found between precisions');
end.

edit2:误报,我错了,我存储的是单个而不是扩展,所以无法发现差异,这里是一个固定的测试,感谢hans passant来捕捉我的错误:

program Project1;

uses
  windows,dialogs,sysutils;

{$R *.res}

const
 test_mul:single=1234567890.0987654321;

var
 i:longint;
 errors:cardinal;
 s:single absolute i;
 s1,s2,s3:extended;

procedure test_24;
asm
 mov word([esp-2]),$103f  // 24bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s1]
end;

procedure test_53;
asm
 mov word([esp-2]),$123f  // 53bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s2]
end;

procedure test_64;
asm
 mov word([esp-2]),$133f  // 64bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s3]
end;

begin
 errors:=0;
 i:=0;
 repeat
  test_24;
  test_53;
  test_64;

  if (s1<>s2) or (s2<>s3) then begin
   inc(errors);
  end;

  inc(i);
 until i=0;
 showmessage('Number of differences between precisions: '+inttostr(errors));
end.

0 个答案:

没有答案