Re: [fpc-pascal] Converting 32bit intel asm to Pascal or 64bit att asm

2011-03-10 Thread Andrew Haines
On 03/09/11 14:18, Thomas Schatzl wrote:
 On Wed, 09 Mar 2011 13:23:55 -0500, Andrew Haines wrote:
 On 03/09/11 12:26, Thomas Schatzl wrote:

 FYL2X calculates the log to the base 2 of tmp, not log to the base e of
 tmp? Just a guess.


 I originally used log2(Tmp) but switched to ln to check if it was
 correct. Thanks for noticing that, I changed it back to log2.


 
 Suffixes for gas for floating point are (from
 http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax)
 
 -s 32 bit/single
 -l 64 bit/double
 -t 80 bit/extended

Thank you this is useful!

 
 I will write a bug report.


Thank you for writing that bug report.

I finally got the plain pascal version to work properly! My major
problem was I accidentally used the sqr function instead of sqrt. Here's
the final product:


  var
LogBase  : Double;
i: Integer;
Tmp: Double;
  begin
SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide,
exOverflow, exUnderflow, exPrecision]);

LogBase:=1.0/(ln(10)/ln(2));

for i := DataSize-1 downto 0 do
begin
  Tmp := sqrt(sqr(InData[i].Im) + sqr(InData[i].Re));
  if Tmp  0.0 then
Tmp := (ln(Tmp)/ln(2))*LogBase+Shift
  else
Tmp := 0.0;

  OutData[i] := Tmp;
end;
  end;

In case anyone is interested, this generates 45 lines of assembly. The
handwritten asm code is 40 lines. (not including the procedure pre and
post asm for either method) I cheated a little and copied the log2 code
directly to avoid the function calls, this resulted in the compiler
doing the math ahead of time.

Regards,

Andrew Haines
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Converting 32bit intel asm to Pascal or 64bit att asm

2011-03-09 Thread Andrew Haines
On 03/08/11 19:58, Andrew Haines wrote:
 Hi,
 
 I'm trying to convert the following 32bit asm to pascal so it's
 portable. Also to 64bit asm.
 
 It's from ACS audio component suite.
 
 What am I doing wrong?
 

For anyone who's interested I fixed the 64bit assembly version which is
good enough for me but I had hoped to write pascal code for the function.

I converted the intel32 asm to att32 asm which showed my first problem
FDIVP on intel becomes FDIVRP but on att it stays the same which
causes a different result. Beyond that, there wern't many problems. I
had some fun wondering why the RCX register wasn't a reasonable value
until I realized I was copying 64bits from a 32bit variable.

The following is my result. The 32bit and 64bit asm work but the pascal
still does not. Any suggestions are welcome.

 procedure LgMagnitude(InData : PACSComplex; OutData : PDouble;
DataSize, Shift : Integer);
  {$IFDEF CPUI386}
  var
LogBase  : Double;
  begin
asm
FLD1;
FLDL2T;
FDIVrP;
FSTPQ LogBase;
MOVL DataSize, %ecx;
MOVL OutData, %edi;
MOVL InData, %esi;
  .Ltest:   DEC %ecx
JZ .Lout;
FLDQ (%esi);
FMULQ %ST(0), %ST(0);
ADDL $8, %esi;
FLDQ (%esi);
FMULQ %ST(0), %ST(0);
FADDP;
FSQRTQ;
FTSTQ;
FSTSW %AX;

SAHF;
JE .Lskip;

FLDQ LogBase;
FXCH;
FYL2X;
FIADDL Shift;
FTSTQ;
FSTSW %AX;

SAHF;
JAE .Lskip;

FSTPQ (%edi);
FLDZ;
  .Lskip:
ADDL $8, %esi;
FSTPQ (%edi);
ADDL $8, %edi;
JMP .Ltest;
  .Lout: ;
end;
  end;
  {$ELSE} {$IFDEF CPUX86_64}
  var
LogBase  : Double;
  begin
SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide,
exOverflow, exUnderflow, exPrecision]);
asm
FLD1;
FLDL2T;
FDIVrP;
FSTPQ   LogBase;
MOV DataSize, %ecx;
MOV OutData,  %rdi;
MOV InData,   %rsi;
  .Ltest:   DEC %ecx
JZ .Lout;
FLDL(%rsi);
FMUL%ST(0),   %ST(0);
ADD $8,   %rsi;
FLDL(%rsi);
FMUL%ST(0),   %ST(0);
FADDP;
FSQRT;
FTST;
FSTSW   %AX;

// SAHF is not available on all x86_64 processors so
this is the workaround
bt  $14,  %ax; // // copy fpu C3 flag to cpu
carry flag
JC .Lskip;

FLD LogBase;
FXCH;
FYL2X;
FIADDL  Shift;
FTST;
FSTSW   %AX;

// SAHF is not available on all x86_64 processors so
this is the workaround
bt  $8,%ax // copy fpu C0 flag to cpu carry flag
JNC .Lskip

FSTPL   (%rdi);
FLDZ;
  .Lskip:
ADDL$8,%rsi;
FSTPL   (%rdi);
ADDL$8,%rdi;
JMP .Ltest;
  .Lout: ;
end;
  end;
  {$ELSE}
  {$ERROR LgMagnitude Unimplemented}
  // the following is not correct but was my best effort at pascalizing
the asm code
  var
LogBase  : Double;
i: Integer;
Im, Re: Double;
Tmp: Double;
  begin
asm
  FLD1;
  FLDL2T;
  FDIVRP;
  FSTP LogBase;
end;
for i := 0 to DataSize-1 do
begin
  Im := InData[i].Im*InData[i].Im;
  Re := InData[i].Re*InData[i].Re;
  Tmp := sqr(Im+Re);

  if Tmp  Im then
  begin
//Tmp := ln(Tmp)*LogBase+Shift; // same as the following asm proc?
asm
  FLD LogBase;
  FLD Tmp;
  FYL2X;
  FIADD Shift;
  FSTP Tmp;
end;
if Tmp  0.0 then
begin
  if 0.0 = Tmp then
  begin
Tmp := 0;
  end;
end;
  end;
  OutData[i] := Tmp;
end;
  end;
  {$ENDIF CPUX86_64}
  {$ENDIF CPUI386}
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Converting 32bit intel asm to Pascal or 64bit att asm

2011-03-09 Thread Thomas Schatzl

Hi,

On Wed, 09 Mar 2011 11:58:08 -0500, Andrew Haines wrote:

  if Tmp  Im then
  begin
//Tmp := ln(Tmp)*LogBase+Shift; // same as the following asm 
proc?

asm
  FLD LogBase;
  FLD Tmp;
  FYL2X;


FYL2X calculates the log to the base 2 of tmp, not log to the base e of 
tmp? Just a guess.


Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Converting 32bit intel asm to Pascal or 64bit att asm

2011-03-09 Thread Andrew Haines
On 03/09/11 12:26, Thomas Schatzl wrote:
 Hi,
 
 On Wed, 09 Mar 2011 11:58:08 -0500, Andrew Haines wrote:
   if Tmp  Im then
   begin
 //Tmp := ln(Tmp)*LogBase+Shift; // same as the following asm
 proc?
 asm
   FLD LogBase;
   FLD Tmp;
   FYL2X;
 
 FYL2X calculates the log to the base 2 of tmp, not log to the base e of
 tmp? Just a guess.
 
 Thomas
 

I originally used log2(Tmp) but switched to ln to check if it was
correct. Thanks for noticing that, I changed it back to log2.

The current output with the pascal code looks like it did when FLDS was
used instead of FLDL to load (%rdi). The intel code was FLD QWORD[EDI]
I changed this to FLDQ (%edi). on x32 it became FLDL and on x64 it
became FLDS. changing the line to FLDL (%rdi) on x86_64 fixed the last
problem I had with the asm translation.

It's all very confusing. Is fldl loading a 32bit floating number? The
variable at (%rdi) is a double. flds makes me think it's loading a single.

Andrew

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Converting 32bit intel asm to Pascal or 64bit att asm

2011-03-09 Thread Thomas Schatzl

On Wed, 09 Mar 2011 13:23:55 -0500, Andrew Haines wrote:

On 03/09/11 12:26, Thomas Schatzl wrote:

Hi,

On Wed, 09 Mar 2011 11:58:08 -0500, Andrew Haines wrote:

  if Tmp  Im then
  begin
//Tmp := ln(Tmp)*LogBase+Shift; // same as the following 
asm

proc?
asm
  FLD LogBase;
  FLD Tmp;
  FYL2X;


FYL2X calculates the log to the base 2 of tmp, not log to the base e 
of

tmp? Just a guess.

Thomas



I originally used log2(Tmp) but switched to ln to check if it was
correct. Thanks for noticing that, I changed it back to log2.

The current output with the pascal code looks like it did when FLDS 
was
used instead of FLDL to load (%rdi). The intel code was FLD 
QWORD[EDI]

I changed this to FLDQ (%edi). on x32 it became FLDL and on x64 it
became FLDS. changing the line to FLDL (%rdi) on x86_64 fixed the 
last

problem I had with the asm translation.


Suffixes for gas for floating point are (from 
http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax)


-s 32 bit/single
-l 64 bit/double
-t 80 bit/extended

With Intel syntax you can only hope that the compiler guesses 
correctly, or add an explicit override.


So you suggest that the assembler changes an inlined fldq (%edi) into 
flds (%edi) on x86-64? This looks like a bug if true - it should 
reject the q suffix for floating point operations.
At least gas 2.19 on solaris x64 rejects fldq; actually the 2.4.2 
release compiler transforms fldq into fld here, which gas rejects 
too :)


I will write a bug report.

Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


[fpc-pascal] Converting 32bit intel asm to Pascal or 64bit att asm

2011-03-08 Thread Andrew Haines
Hi,

I'm trying to convert the following 32bit asm to pascal so it's
portable. Also to 64bit asm.

It's from ACS audio component suite.

What am I doing wrong?

I tested my Pascal code with linux 32bit but the output differs from the
32bit asm. In 64bit linux it differs further but this could be from the
ACS indicator component.

I attached screenshots of the various configurations.

I am using fpc 2.5.1 for 32bit and 64bit.

Regards,

Andrew

TACSComplex = record
  Im, Re: Double;
end;


original code

procedure LgMagnitude(InData : PACSComplex; OutData : PDouble; DataSize,
Shift : Integer);
  var
LogBase  : Double;
  begin
asm
FLD1;
FLDL2T;
FDIVP;
FSTP LogBase;
MOV EDX, DataSize;
SHL EDX, 3;
MOV ECX, OutData;
ADD EDX, ECX;
MOV EAX, InData;
  @test:CMP EDX, ECX;
JE @out;
FLD QWORD[EAX];
FMUL ST(0), ST(0);
ADD EAX, 8;
FLD QWORD[EAX];
FMUL ST(0), ST(0);
FADDP;
FSQRT;
FTST;
PUSH EAX;
FSTSW AX;
SAHF;
JE @skip;
FLD LogBase;
FXCH;
FYL2X;
FIADD Shift;
FTST;
FSTSW AX;
SAHF;
JAE @skip;
FSTP QWORD[ECX];
FLDZ;
  @skip:POP EAX;
ADD EAX, 8;
FSTP QWORD[ECX];
ADD ECX, 8;
JMP @test;
  @out: ;
end;
  end;
end;

/original code

pascal code
  var
LogBase  : Double;
i: Integer;
Im, Re: Double;
Tmp: Double;
  begin
asm
  FLD1;
  FLDL2T;
  FDIVP;
  FSTP LogBase;
end;
for i := 0 to DataSize-1 do
begin
  Im := InData[i].Im*InData[i].Im;
  Re := InData[i].Re*InData[i].Re;
  Tmp := sqr(Im+Re);

  if Tmp  Im then
  begin
//Tmp := log2(Tmp)*LogBase+Shift; // is this the same as the
following asm code?
asm
  FLD LogBase;
  FLD Tmp;
  FYL2X;
  FIADD Shift;
  FSTP Tmp;
end;
if Tmp  0.0 then
begin
  if 0.0 = Tmp then
  begin
Tmp := 0;
  end;
end;
  end;
  OutData[i] := Tmp;
end;
  end;
end;
/pascal code

64bit asm
 SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide,
   exOverflow, exUnderflow, exPrecision]);
asm
FLD1;
FLDL2T;
FDIVP;
FSTP LogBase;
MOV DataSize,  %RDX;
SHL $3,%RDX;
MOV OutData,   %RCX;
ADD %RCX,  %RDX;
MOV InData,%RAX;
MOV Shift, %rsi;
  .Ltest:   CMP %RCX,  %RDX;
JE .Lout;
FLD  (%RAX); //FLD QWORD[%EAX];
FMUL %st(0), %st(0);
ADD $8,%RAX;
FLD (%RAX);//FLD QWORD[EAX]; // sigsegv here with fpu
exceptions off. only happens after many iterations but seems immediate
in real time.
FMUL %st(0), %st(0);
FADDP;
FSQRT;
FTST;
PUSH %RAX;
FSTSW %AX; //with fpu exceptions enabled I get a FPU
exception here after some iterations but again it is immediate in realtime.

//SAHF; // not available in amd64!
//JE .Lskip;
bt $14, %ax; // // copy fpu C3 flag to cpu carry flag
JC .Lskip;

FLD LogBase;
FXCH;
FYL2X;
FIADD Shift;
FTST;
FSTSW %AX;

//SAHF; // not available in amd64!
//JAE .Lskip;
bt $8, %ax // copy fpu C0 flag to cpu carry flag
JNC .Lskip

FSTP (%RCX);//FSTP QWORD[ECX];
FLDZ;
  .Lskip:   POP %RAX;
ADD $8,%RAX;
FSTP (%RCX);//FSTP QWORD[RCX];
ADD $8, %RCX;
JMP .Ltest;
  .Lout: ;
end;
end;
/64bit asm
attachment: 32bit-orig-asm.pngattachment: 32bit-pascal.pngattachment: 64bit-pascal.png___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal