[fpc-pascal] Converting 32bit intel asm to Pascal or 64bit at&t asm

Andrew Haines AndrewD207 at aol.com
Wed Mar 9 17:58:08 CET 2011


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}



More information about the fpc-pascal mailing list