* * *

Author Topic: asm: how to work with FPU  (Read 1523 times)

Kays

  • Full Member
  • ***
  • Posts: 112
  • Whasup!?
    • KaiBurghardt.de
asm: how to work with FPU
« on: May 16, 2018, 11:32:42 am »
Hi,

how do I work with the FPU: How do I retrieve a real parameter in my function into the FPU's stack? See attached program source.

Also, why does
Code: ASM  [Select]
  1.         fst __result.surfaceArea
and
Code: ASM  [Select]
  1.         fst __result.volume
translate into the same opcode? They both become
Code: ASM  [Select]
  1.         fstpl   -16(%rbp)
I use FPC 3.0.4. This syntax for accessing record fields is allowed, is it not? I can't convince the compiler to do the same with {$asmMode intel} selected.
Yours Sincerely
Kai Burghardt

ASerge

  • Hero Member
  • *****
  • Posts: 862
Re: asm: how to work with FPU
« Reply #1 on: May 16, 2018, 09:36:14 pm »
{$ifdef CPUx86_64} assumes a 64 bit compiler. Windows FPC x64 uses SSE2 (xmms) instead of FPU.
And the compiler can calculate PI:
Code: Pascal  [Select]
  1. const
  2.   FourPi: ValReal = 4.0 * Pi;
  3.   FourThirdsPi: ValReal = 4.0 / 3.0 * Pi;

Kays

  • Full Member
  • ***
  • Posts: 112
  • Whasup!?
    • KaiBurghardt.de
Re: asm: how to work with FPU
« Reply #2 on: May 17, 2018, 11:32:39 am »
Yeah, I know. I'd like to do it anyway. Like in my example to directly work with intermediate results.
Yours Sincerely
Kai Burghardt

ASerge

  • Hero Member
  • *****
  • Posts: 862
Re: asm: how to work with FPU
« Reply #3 on: May 17, 2018, 05:01:14 pm »
I'd like to do it anyway.
OK. The Radius parameter is passed through the register xmm0. And you want it to push it to the FPU stack. Your example doesn't even compile!

Thaddy

  • Hero Member
  • *****
  • Posts: 6548
Re: asm: how to work with FPU
« Reply #4 on: May 17, 2018, 05:10:28 pm »
The SSE+ family of registers takes the same addressing as the (old school) FPU and you can't use both at the same time. AFAIK it can be done to switch them however, there are examples for this but not in Pascal inline assembler. I could not find an example for Windows x86_64, though. For *nix x86_64 there are plenty. But it is either/or! not both.
Note as far as I can tell this needs to be done in plain assembler anyway: MSWindows x86_64 is rather strict. It can be it isn't even possible in inline assembler. Or even prohibited, but I am not quite sure, since it can be done on other platforms with pure assembler.
« Last Edit: May 17, 2018, 05:16:46 pm by Thaddy »
Ada's daddy wrote this:"Fools are my theme, let satire be my song."

Kays

  • Full Member
  • ***
  • Posts: 112
  • Whasup!?
    • KaiBurghardt.de
Re: asm: how to work with FPU
« Reply #5 on: May 17, 2018, 06:55:20 pm »
I know the FPU registers are shared by SSE, yes. But I want to learn handling the FPU before dealing with even more complex systems.

The two questions remain.
  • Why, or how do I access record fields, without calculating them on my own?
  • How am I supposed to interpret or accept parameters within my assembler function?

[…] The Radius parameter is passed through the register xmm0. And you want it to push it to the FPU stack. Your example doesn't even compile!
Essentially, yes. That's why I'm asking. How do I interpret xmm0?
How do I turn off parameter passing in xmm0, so I can use my FPU stack without problems?
« Last Edit: May 17, 2018, 07:00:15 pm by Kays »
Yours Sincerely
Kai Burghardt

ASerge

  • Hero Member
  • *****
  • Posts: 862
Re: asm: how to work with FPU
« Reply #6 on: May 17, 2018, 08:35:59 pm »
The two questions remain.
  • Why, or how do I access record fields, without calculating them on my own?
  • How am I supposed to interpret or accept parameters within my assembler function?
Code: Pascal  [Select]
  1. {$MODE OBJFPC}
  2. {$APPTYPE CONSOLE}
  3. program Project1;
  4.  
  5. type
  6.   TSomeRec = record
  7.     Square: ValReal;
  8.     Cube: ValReal;
  9.   end;
  10.  
  11. function Calc(const Param: ValReal): TSomeRec;
  12. {$IFDEF CPUX86_64}
  13. assembler;
  14. {$ASMMODE INTEL}
  15. var
  16.   LRadius: ValReal;
  17. asm
  18.   pextrq LRadius,Param,0
  19.   fld LRadius
  20.   fmul LRadius
  21.   mov rax, @Result
  22.   fst [rax].TSomeRec.Square
  23.   fmul LRadius
  24.   fst [rax].TSomeRec.Cube
  25. end;
  26. {$ELSE}
  27. begin
  28.   Result.Square := Sqr(Param);
  29.   Result.Cube := Sqr(Param) * Param;
  30. end;
  31. {$ENDIF}
  32.  
  33. var
  34.   X: TSomeRec;
  35. begin
  36.   X := Calc(1.5);
  37.   Writeln('Square=', X.Square:0:4, ' Cube=', X.Cube:0:4);
  38.   Readln;
  39. end.

Kays

  • Full Member
  • ***
  • Posts: 112
  • Whasup!?
    • KaiBurghardt.de
Re: asm: how to work with FPU
« Reply #7 on: May 20, 2018, 12:33:24 pm »
[…]
Code: Pascal  [Select]
  1.   []
  2.   fst [rax].TSomeRec.Square
  3.   []
  4.   fst [rax].TSomeRec.Cube
  5.   []

Thank you very much.

I apparently have to go via the stack, eh. First copy xmm0 to some memory location using pextrq, and then load it back again with fld (because fld only accepts memory operands). There is no chance in turning off parameter passing in xmm0 (except for calling the function on my own [using another inline-asm-block]).

For some weird reason my @result is zero (nil) now, causing a 216 RTE. Oh gosh, can't it just work? After nexting
Code: [Select]
0x4001d1 <SPHERE+17>    mov    rax,QWORD PTR [rbp-0x10]gdb(1) reports rax to be 0x0.
Yours Sincerely
Kai Burghardt

ASerge

  • Hero Member
  • *****
  • Posts: 862
Re: asm: how to work with FPU
« Reply #8 on: May 20, 2018, 12:51:38 pm »
For some weird reason my @result is zero (nil) now, causing a 216 RTE.
Need the source. My example works.

Kays

  • Full Member
  • ***
  • Posts: 112
  • Whasup!?
    • KaiBurghardt.de
Re: asm: how to work with FPU
« Reply #9 on: May 20, 2018, 01:03:12 pm »
Need the source.
It's just the six lines that are different.

My example works.
Even your example doesn't for work me:
Code: [Select]
Free Pascal Compiler version 3.0.4+dfsg-11 [2017/12/30] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling project1.pas
project1.pas(2,2) Warning: APPTYPE is not supported by the target OS
project1.pas(18,3) Error: Asm: [pextrq mem??,mem??,imm??] invalid combination of opcode and operands
project1.pas(20,3) Error: Asm: [fmul mem??] invalid combination of opcode and operands
project1.pas(22,3) Error: Asm: [fst mem??] invalid combination of opcode and operands
project1.pas(23,3) Error: Asm: [fmul mem??] invalid combination of opcode and operands
project1.pas(24,3) Error: Asm: [fst mem??] invalid combination of opcode and operands
project1.pas(40) Fatal: There were 5 errors compiling module, stopping
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode
Yours Sincerely
Kai Burghardt

ASerge

  • Hero Member
  • *****
  • Posts: 862
Re: asm: how to work with FPU
« Reply #10 on: May 20, 2018, 01:18:46 pm »
Even your example doesn't for work me:
This is weird. Everything works in Windows:
Code: [Select]
...>d:fpc.exe project1.lpr
Free Pascal Compiler version 3.0.4 [2018/02/25] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Win64 for x64
Compiling project1.lpr
Linking project1.exe
38 lines compiled, 0.0 sec, 37984 bytes code, 1876 bytes data

...>type project1.lpr
{$MODE OBJFPC}
{$APPTYPE CONSOLE}
program Project1;

type
  TSomeRec = record
    Square: ValReal;
    Cube: ValReal;
  end;

function Calc(const Param: ValReal): TSomeRec;
{$IFDEF CPUX86_64}
assembler;
{$ASMMODE INTEL}
var
  LRadius: ValReal;
asm
  pextrq LRadius,Param,0
  fld LRadius
  fmul LRadius
  mov rax, @Result
  fst [rax].TSomeRec.Square
  fmul LRadius
  fst [rax].TSomeRec.Cube
end;
{$ELSE}
begin
  Result.Square := Sqr(Param);
  Result.Cube := Sqr(Param) * Param;
end;
{$ENDIF}

var
  X: TSomeRec;
begin
  X := Calc(1.5);
  Writeln('Square=', X.Square:0:4, ' Cube=', X.Cube:0:4);
  Readln;
end.
Your example compiled with warnings:
Quote
project1.lpr(29,2) Warning: fmulp without operand translated into fmulpP
project1.lpr(32,2) Warning: fmulp without operand translated into fmulpP
project1.lpr(33,2) Warning: fmulp without operand translated into fmulpP
project1.lpr(35,2) Warning: fmulp without operand translated into fmulpP
project1.lpr(37,2) Warning: "fdivrp" without operand translated into "fdivrp %st,%st(1)"
project1.lpr(52,0) Warning: Object file "project1.o" contains 32-bit absolute relocation to symbol ".data.n_tc_$p$functiondemo$_$sphere$real$$bodyattributes_$$_four".
project1.lpr(52,0) Warning: Object file "project1.o" contains 32-bit absolute relocation to symbol ".data.n_tc_$p$functiondemo$_$sphere$real$$bodyattributes_$$_three".
Result is 1.0294370807283034E+005

Kays

  • Full Member
  • ***
  • Posts: 112
  • Whasup!?
    • KaiBurghardt.de
Re: asm: how to work with FPU
« Reply #11 on: May 20, 2018, 01:46:14 pm »
[…] Your example compiled with warnings: […]
Those auto-completion warnings are fine, but the last two are not.

Result is 1.0294370807283034E+005
Uhm, I hope not. Did I …? Err, after ning the first fild instruction the stack top has 4 loaded, has it not?
Code: [Select]
(gdb) info register st0
st0            4        (raw 0x40018000000000000000)
Anyway, that's a different story.

I want to know, why (the content at) result is nil. I did use result before, successfully, but with simple types.

As far as I know, if the function results' type is not an integral value or does not fit into the accumulator register, they are allocated on the stack (and result holds the address).

My result type is not a ^bodyAttributes (a pointer to my bodyAttributes record), but the record itself, so …

I don't know. I can't make anything of it.
« Last Edit: May 20, 2018, 01:52:30 pm by Kays »
Yours Sincerely
Kai Burghardt

Kays

  • Full Member
  • ***
  • Posts: 112
  • Whasup!?
    • KaiBurghardt.de
Re: asm: how to work with FPU
« Reply #12 on: May 20, 2018, 11:31:27 pm »
Got it! This
[…]
Code: Pascal  [Select]
  1.   []
  2.   mov rax, @Result
  3.   []
is supposed to read
Code: ASM  [Select]
  1.   lea rax, @result
then the address is loaded.

[…]

For some weird reason my @result is zero (nil) now, […] After nexting
Code: [Select]
0x4001d1 <SPHERE+17>    mov    rax,QWORD PTR [rbp-0x10]gdb(1) reports rax to be 0x0.
Yeah, of course: the pointer is followed. What I see is the default value. >sigh<

Now the program runs without problems and the result is correct. Huzzah!  :-*
Yours Sincerely
Kai Burghardt

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus