Re: [fpc-pascal] Converting 32bit intel asm to Pascal or 64bit att asm
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
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
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
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
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
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