Recent

Author Topic: Multiply operation for xtensa (lx6/esp32)  (Read 3879 times)

irfanbagus

  • Jr. Member
  • **
  • Posts: 73
Multiply operation for xtensa (lx6/esp32)
« on: August 07, 2020, 05:58:57 pm »
I try this code

Code: Pascal  [Select][+][-]
  1. function TestSmallInt(A,B: SmallInt): SmallInt;
  2. begin
  3.   Result:= SmallInt(5)+A*B;
  4. end;  

and i get this assembly code

Code: Pascal  [Select][+][-]
  1. # [90] begin
  2.         entry   a1,64
  3.         mov             a10,a2
  4. # Var A located in register a10
  5.         mov             a11,a3
  6. # Var B located in register a11
  7. # Var B located in register a11
  8. # Var A located in register a10
  9. # [91] Result:= SmallInt(5)+A*B;
  10.         call8   fpc_mul_longint
  11.         addi    a2,a10,5
  12.         sext    a2,a2,15
  13. # Var $result located in register a2
  14. # [92] end;
  15.         sext    a2,a2,15
  16.         retw

i have almost zero knowledge in this xtensa cpu. Is there any reason why fpc does not generate MUL* instruction, instead calling multiply helper function?  missing native MUL instruction perhaps?

ccrause

  • Hero Member
  • *****
  • Posts: 845
Re: Multiply operation for xtensa (lx6/esp32)
« Reply #1 on: August 07, 2020, 09:02:01 pm »
...
i have almost zero knowledge in this xtensa cpu. Is there any reason why fpc does not generate MUL* instruction, instead calling multiply helper function?  missing native MUL instruction perhaps?
The both ESP32 and ESP8266 have hardware MULL and MUL16 type instructions.  The necessary code to generate the CPU specific instructions hasn't been implemented yet [1] - this target is relatively new so not much time has been invested yet into optimizing the generated code.

Edit: [1] Not quite true, there is actually some code that can generate a hardware MULL instruction, but it is disabled by default (probably because it lacks error checking).
« Last Edit: August 07, 2020, 10:14:03 pm by ccrause »

irfanbagus

  • Jr. Member
  • **
  • Posts: 73
Re: Multiply operation for xtensa (lx6/esp32)
« Reply #2 on: August 08, 2020, 03:16:06 am »
...
Edit: [1] Not quite true, there is actually some code that can generate a hardware MULL instruction, but it is disabled by default (probably because it lacks error checking).

is this what you mean (see my attachment) ?

ccrause

  • Hero Member
  • *****
  • Posts: 845
Re: Multiply operation for xtensa (lx6/esp32)
« Reply #3 on: August 08, 2020, 09:21:10 am »
Yes.  Since the MUL instructions are optional, I would rather follow the m68k example and declare a capability in cpuinfo.pas and check if this capability exists for the selected subarch. taddnode.use_mul_helper can be overridden to perform this check.  See attached patch.

Note that the generated code does not check for overflow, this still needs to be implemented.  Test example:
Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. procedure vTaskDelay(xTicksToDelay: uint32); external;
  4.  
  5. var
  6.   a, b, c: uint32;
  7.  
  8. begin
  9.   for a := $FFFF to $7FFFFF do
  10.     for b := $FFF0 to $7FFFFF do
  11.     begin
  12.       c := a * b;
  13.       writeln(a, ' x ', b, ' = ', c);
  14.       vTaskDelay(100);
  15.     end;
  16.   repeat until false;
  17. end.
  18.  

Code: ASM  [Select][+][-]
  1. # [12] c := a * b;
  2.         l32r    a2,.Lj13
  3.         l32i    a3,a2,0
  4.         l32r    a2,.Lj14
  5.         l32i    a2,a2,0
  6.         mull    a2,a2,a3
  7.         l32r    a3,.Lj15
  8.         s32i    a2,a3,0
  9. .Ll5:

And the output with overflow checking enabled:
Code: Text  [Select][+][-]
  1. 65535 x 65535 = 4294836225
  2. 65535 x 65536 = 4294901760
  3. 65535 x 65537 = 4294967295
  4. 65535 x 65538 = 65534
  5. 65535 x 65539 = 131069
  6. 65535 x 65540 = 196604

 

TinyPortal © 2005-2018