Recent

Author Topic: [Solved] Pascal and Assembler  (Read 915 times)

MountainQ

  • New Member
  • *
  • Posts: 46
[Solved] Pascal and Assembler
« on: September 12, 2019, 12:19:31 pm »
Greetings everyone,

I came across an approximation to calculating the log of an number (to about 6 digits in precision):
https://stackoverflow.com/questions/39821367/very-fast-approximate-logarithm-natural-log-function-in-c
A straightforward pascal implementation shows that it is about twice as fast as using the built-in log function.
Code: Pascal  [Select]
  1. function fasterlog(a: single): single;  // 6 digits acc
  2. type
  3.   TFI = packed record
  4.   case Integer of
  5.     0: (FloatAccess: single);
  6.     1: (IntAccess: int32);
  7. end;
  8. var
  9.   m, r, s, t, f, i: single;
  10.   e, g: Int32;
  11. begin
  12.   e := (TFI(a).IntAccess - $3f2aaaab) and $ff800000;
  13.   g := TFI(a).IntAccess-e;
  14.   m := TFI(g).FloatAccess;
  15.   i := e * 1.19209290E-7;
  16.  
  17.   f := m - 1.0;
  18.   s := f * f;
  19.   // Compute log1p(f) for f in [-1/3, 1/3]
  20.   r := 0.230836749*f-0.279208571;
  21.   t := 0.331826031*f-0.498910338;
  22.   //r := FMASingle(r,s,t);
  23.   r := r*s+t;
  24.   r := r*s+f;
  25.   Result := i*0.693147182+r;
  26. end;    
As explained in the link the algorithm splits the number in mantissa and exponent and adds the logarithm of both; in the former case an approximation is used.
To do this efficiently some bit manipulation is used.
A few question arose for me:
- Can a typecast be also executed on an expression (effectively getting rid of the variable g in the above code); something like:
Code: Pascal  [Select]
  1. m := TFI(TFI(a).IntAccess-e).FloatAccess;
- I wanted to utilize the FMA function (fused multiplication and addition) as used in the original code; the compiler however raised: "..Error: The function used, is not supported by the selected instruction set: FMA"; the CPU on my computer (as probably most) should allow the usage, yet there is no 'FMA' option  in the fpu compiler settings.
- Is there an introduction how to use assembler within the pascal code? Is there any restrictions on which registers can be used; is the compiler capable of using more advanced instructions such as the equivalent of the above FMA command?

If some light could be shed on these question, it would be highly appreciated.

Best to everyone.
« Last Edit: September 16, 2019, 08:40:30 am by MountainQ »

jamie

  • Hero Member
  • *****
  • Posts: 1990
Re: Pascal and Assembler
« Reply #1 on: September 12, 2019, 02:16:53 pm »
Don't know which target you are pointing to but, with 64 bit the FPU isn't used but with
32 bit it is, this could make a difference.

Also there are two different assemblers to work with, INTEL an AT&T

so maybe that will help you some ?


MountainQ

  • New Member
  • *
  • Posts: 46
Re: Pascal and Assembler
« Reply #2 on: September 12, 2019, 02:38:29 pm »
@jamie: i am using a 64-bit OS/CPU; does that imply that FMA is not used at all?
I am aware that there are two assembler settings; I am however unsure of their significance: is this merely a syntax choice?
Thanks for your reply

jamie

  • Hero Member
  • *****
  • Posts: 1990
Re: Pascal and Assembler
« Reply #3 on: September 12, 2019, 05:16:34 pm »
Your CPU has the FPU but fpc wants to use the registered version of processing math instructions instead of using the FPU.

 You should try the 32 bit target, I have both 32 and 64 Laz installed as separated IDE's, I have it better that way..

PascalDragon

  • Hero Member
  • *****
  • Posts: 623
  • Compiler Developer
Re: Pascal and Assembler
« Reply #4 on: September 13, 2019, 09:40:25 am »
Your CPU has the FPU but fpc wants to use the registered version of processing math instructions instead of using the FPU.
FMA is part of the SSE-based extensions, so if it all it would work on Win64 by default (which uses SSE by default), but not on other x86 targets (both 32-bit and 64-bit) as those use the x87 FPU by default.

- I wanted to utilize the FMA function (fused multiplication and addition) as used in the original code; the compiler however raised: "..Error: The function used, is not supported by the selected instruction set: FMA"; the CPU on my computer (as probably most) should allow the usage, yet there is no 'FMA' option  in the fpu compiler settings.
You need to enable the use of the FMA instruction set by setting the CPU type to CoreAVX2. Please note however that the other calculations are probably done on the x87 FPU except if you're on Win64.

- Is there an introduction how to use assembler within the pascal code? Is there any restrictions on which registers can be used; is the compiler capable of using more advanced instructions such as the equivalent of the above FMA command?
The syntax for assembler blocks is mentioned here. As long as you mention the changed registers in the register list the compiler will handle them correctly. On x86 platforms you can use either Intel or AT&T syntax which you can change using the $ASMMODE directive.

MountainQ

  • New Member
  • *
  • Posts: 46
Re: Pascal and Assembler
« Reply #5 on: September 13, 2019, 10:59:30 am »
@PacalDragon
Thanks for your reply;
I tried to set the the cpu optimization (-OpCOREAVX2) was that correct?; yet the compiler still complaines:
"Error: The function used, is not supported by the selected instruction set: FMA"
However, I successfully managed to convert the code into assembler (because we can) and could successfully run the equivalent command (to FMASingle):
Code: Pascal  [Select]
  1.   vfmadd132ss %xmm4, %xmm5, %xmm0
Another question arose: according to the documentation using assembler routines allows the usage of variables;
https://www.freepascal.org/docs-html/current/prog/progse9.html#x144-1450003.1
However the following code raises an error:
Code: Pascal  [Select]
  1. function fasterlog(a: single): single; assembler; // 6 digits acc
  2. asm
  3.   mov a, %eax
  4.   movss %xmm3, Result
  5. end ['rax';
Whereas this one does not
Code: Pascal  [Select]
  1. function fasterlog(a: single): single;  // 6 digits acc
  2. begin
  3. asm
  4.   mov a, %eax
  5.   movss %xmm3, Result
  6. end ['rax'];
  7. end;
What am I missing?
In the assembler file generated by the compiler %xmm0 is used as 'a'; I can access that, however I do not know whether that can change

And lastly: does the register list have to include the extended registers (here %xmm0...)?

Thanks for your effort; I hope these are not too many questions.
Best to everyone




marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7441
Re: Pascal and Assembler
« Reply #6 on: September 13, 2019, 11:48:13 am »
There are multiple types of FMA. Afaik the number of arguments sets them apart.   Search for FMA3(AMD's original FMA, aka XOP FMA) (FMA4 Intel and later AMD FMA)

avra

  • Hero Member
  • *****
  • Posts: 1687
    • Additional info
Re: Pascal and Assembler
« Reply #7 on: September 13, 2019, 01:35:15 pm »
However the following code raises an error:
Code: Pascal  [Select]
  1. function fasterlog(a: single): single; assembler; // 6 digits acc
  2. asm
  3.   mov a, %eax
  4.   movss %xmm3, Result
  5. end ['rax';
Did you forget to close the bracket?
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

MountainQ

  • New Member
  • *
  • Posts: 46
Re: Pascal and Assembler
« Reply #8 on: September 13, 2019, 01:50:43 pm »
@marcov: according to wikipedia there are differing versions of FMA... however nothing appears in the -Cf settings (same as 'fpc -if')

@avra: you are right; however in the actual code the bracket was there. The actula error message is "Asm: [mov reg32,xmmreg] invalid combination of opcode and operands"; this message does not appear if the function is not declared an assembler function

Oleary

  • Newbie
  • Posts: 1
Re: Pascal and Assembler
« Reply #9 on: September 13, 2019, 02:58:49 pm »
Could wikipedia be wrong about that? Wouldn't be the first time...

ASerge

  • Hero Member
  • *****
  • Posts: 1408
Re: Pascal and Assembler
« Reply #10 on: September 13, 2019, 04:30:16 pm »
However the following code raises an error:
Code: Pascal  [Select]
  1. function fasterlog(a: single): single; assembler; // 6 digits acc
  2. asm
  3.   mov a, %eax
  4.   movss %xmm3, Result
  5. end ['rax';
Whereas this one does not
Code: Pascal  [Select]
  1. function fasterlog(a: single): single;  // 6 digits acc
  2. begin
  3. asm
  4.   mov a, %eax
  5.   movss %xmm3, Result
  6. end ['rax'];
  7. end;
What am I missing?
In first case a equal %xmm0, so code movl %xmm0, %eax is invalid.
In second case compiler add stack frame, and a(%xmm0) stored on stack, so later in asm block used movl -8(%rbp),%eax.

MountainQ

  • New Member
  • *
  • Posts: 46
Re: Pascal and Assembler
« Reply #11 on: September 13, 2019, 08:42:37 pm »
Whoa hey! Thanks Aserge, that is the missing information.
Does that imply that a float is always passed via %xmm0? And where would I find related information regarding the interplay of pascal and assembler? The pascal wiki and the general documentation are rather sparse.
Thanks again

Kays

  • Full Member
  • ***
  • Posts: 182
  • Whasup!?
    • KaiBurghardt.de
Re: Pascal and Assembler
« Reply #12 on: September 13, 2019, 09:51:57 pm »
[…] And where would I find related information regarding the interplay of pascal and assembler? […]
Jonas referred me to these resources regarding interfacing Pascal procedure/function vs. assembly language.
« Last Edit: September 13, 2019, 09:54:05 pm by Kays »
Yours Sincerely
Kai Burghardt

PascalDragon

  • Hero Member
  • *****
  • Posts: 623
  • Compiler Developer
Re: Pascal and Assembler
« Reply #13 on: September 14, 2019, 11:06:21 am »
@PacalDragon
Thanks for your reply;
I tried to set the the cpu optimization (-OpCOREAVX2) was that correct?; yet the compiler still complaines:
"Error: The function used, is not supported by the selected instruction set: FMA"
As the name says that is the optimization processor. You need to set the code generation processor using -CpCOREAVX2.

MountainQ

  • New Member
  • *
  • Posts: 46
Re: Pascal and Assembler
« Reply #14 on: September 16, 2019, 08:40:14 am »
@PascalDragon: It works (perfectly), thanks for your patience

@Kays: thank you I had a brief look; it is certainly helpful.

I can close the subject based on that.
Thanks all for your help.