Browse Source

+ Xtensa: FMA support

git-svn-id: trunk@47563 -
florian 4 years ago
parent
commit
9dcf85a8ef
5 changed files with 125 additions and 0 deletions
  1. 1 0
      .gitattributes
  2. 8 0
      compiler/xtensa/ncpuadd.pas
  3. 83 0
      compiler/xtensa/ncpuinl.pas
  4. 3 0
      tests/test/tfma1.inc
  5. 30 0
      tests/test/tfma1xtensa.pp

+ 1 - 0
.gitattributes

@@ -14945,6 +14945,7 @@ tests/test/tfma1.inc svneol=native#text/plain
 tests/test/tfma1a64.pp svneol=native#text/pascal
 tests/test/tfma1a64.pp svneol=native#text/pascal
 tests/test/tfma1arm.pp svneol=native#text/pascal
 tests/test/tfma1arm.pp svneol=native#text/pascal
 tests/test/tfma1x86.pp svneol=native#text/pascal
 tests/test/tfma1x86.pp svneol=native#text/pascal
+tests/test/tfma1xtensa.pp svneol=native#text/pascal
 tests/test/tforin1.pp svneol=native#text/pascal
 tests/test/tforin1.pp svneol=native#text/pascal
 tests/test/tforin10.pp svneol=native#text/plain
 tests/test/tforin10.pp svneol=native#text/plain
 tests/test/tforin11.pp svneol=native#text/plain
 tests/test/tforin11.pp svneol=native#text/plain

+ 8 - 0
compiler/xtensa/ncpuadd.pas

@@ -47,6 +47,7 @@ interface
          procedure second_cmpfloat;override;
          procedure second_cmpfloat;override;
          procedure second_addfloat;override;
          procedure second_addfloat;override;
          procedure second_cmp;
          procedure second_cmp;
+         function use_fma: boolean;override;
        end;
        end;
 
 
   implementation
   implementation
@@ -67,6 +68,13 @@ interface
                                TCPUAddNode
                                TCPUAddNode
 *****************************************************************************}
 *****************************************************************************}
 
 
+    function TCPUAddNode.use_fma : boolean;
+      begin
+        Result:=is_single(left.resultdef) and is_single(right.resultdef) and
+          (FPUXTENSA_SINGLE in fpu_capabilities[current_settings.fputype]);
+      end;
+
+
     procedure TCPUAddNode.second_addordinal;
     procedure TCPUAddNode.second_addordinal;
       var
       var
         ophigh: tasmop;
         ophigh: tasmop;

+ 83 - 0
compiler/xtensa/ncpuinl.pas

@@ -33,6 +33,8 @@ unit ncpuinl;
         function first_abs_real: tnode; override;
         function first_abs_real: tnode; override;
         procedure second_abs_long; override;
         procedure second_abs_long; override;
         procedure second_abs_real; override;
         procedure second_abs_real; override;
+        function first_fma: tnode; override;
+        procedure second_fma; override;
       end;
       end;
 
 
   implementation
   implementation
@@ -48,6 +50,7 @@ unit ncpuinl;
       hlcgobj,
       hlcgobj,
       pass_2,
       pass_2,
       cgbase, cgobj, cgutils,
       cgbase, cgobj, cgutils,
+      ncal,
       cpubase;
       cpubase;
 
 
     procedure tcpuinlinenode.second_abs_long;
     procedure tcpuinlinenode.second_abs_long;
@@ -84,6 +87,86 @@ unit ncpuinl;
       end;
       end;
 
 
 
 
+    function tcpuinlinenode.first_fma : tnode;
+      begin
+        if is_single(resultdef) then
+          begin
+            expectloc:=LOC_FPUREGISTER;
+            Result:=nil;
+          end
+        else
+          Result:=inherited first_fma;
+      end;
+
+
+    procedure tcpuinlinenode.second_fma;
+      const
+        op : array[false..true] of TAsmOp =
+          (A_MADD,
+           A_MSUB);
+
+      var
+        paraarray : array[1..3] of tnode;
+        i : integer;
+        negproduct : boolean;
+        oppostfix : TOpPostfix;
+        ai: taicpu;
+      begin
+         if is_single(resultdef)and
+           (FPUXTENSA_SINGLE in fpu_capabilities[current_settings.fputype]) then
+           begin
+             negproduct:=false;
+             paraarray[1]:=tcallparanode(tcallparanode(tcallparanode(parameters).nextpara).nextpara).paravalue;
+             paraarray[2]:=tcallparanode(tcallparanode(parameters).nextpara).paravalue;
+             paraarray[3]:=tcallparanode(parameters).paravalue;
+
+             { check if a neg. node can be removed
+               this is possible because changing the sign of
+               a floating point number does not affect its absolute
+               value in any way
+             }
+             if paraarray[1].nodetype=unaryminusn then
+               begin
+                 paraarray[1]:=tunarynode(paraarray[1]).left;
+                 { do not release the unused unary minus node, it is kept and release together with the other nodes,
+                   only no code is generated for it }
+                 negproduct:=not(negproduct);
+               end;
+
+             if paraarray[2].nodetype=unaryminusn then
+               begin
+                 paraarray[2]:=tunarynode(paraarray[2]).left;
+                 { do not release the unused unary minus node, it is kept and release together with the other nodes,
+                   only no code is generated for it }
+                 negproduct:=not(negproduct);
+               end;
+              for i:=1 to 3 do
+               secondpass(paraarray[i]);
+
+             { no memory operand is allowed }
+             for i:=1 to 3 do
+               begin
+                 if not(paraarray[i].location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
+                   hlcg.location_force_fpureg(current_asmdata.CurrAsmList,paraarray[i].location,paraarray[i].resultdef,true);
+               end;
+
+             location_reset(location,LOC_FPUREGISTER,paraarray[1].location.size);
+             location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+
+             hlcg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,paraarray[3].resultdef,resultdef,
+               paraarray[3].location.register,location.register);
+
+             ai:=taicpu.op_reg_reg_reg(op[negproduct],
+               location.register,paraarray[1].location.register,paraarray[2].location.register);
+             ai.oppostfix:=PF_S;
+             current_asmdata.CurrAsmList.concat(ai);
+
+             cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
+           end
+         else
+           internalerror(2020112401);
+      end;
+
 
 
 begin
 begin
   cinlinenode:=tcpuinlinenode;
   cinlinenode:=tcpuinlinenode;

+ 3 - 0
tests/test/tfma1.inc

@@ -241,6 +241,7 @@ procedure testsingle;
       halt(1);
       halt(1);
   end;
   end;
 
 
+{$ifndef NODOUBLE}
 
 
 procedure testdouble;
 procedure testdouble;
   var
   var
@@ -480,3 +481,5 @@ procedure testdouble;
     if l0<>-10.0 then
     if l0<>-10.0 then
       halt(1);
       halt(1);
   end;
   end;
+
+{$endif NODOUBLE}

+ 30 - 0
tests/test/tfma1xtensa.pp

@@ -0,0 +1,30 @@
+{ %CPU=xtensa }
+
+{$define NODOUBLE}
+
+{$i tfma1.inc}
+
+begin
+  {
+  d1:=2;
+  d2:=3;
+  d3:=4;
+  d0:=FMADouble(d1,d2,d3);
+  writeln(d0);
+  if d0<>10.0 then
+    halt(1);
+  }
+
+  s1:=2;
+  s2:=3;
+  s3:=4;
+  s0:=FMASingle(s1,s2,s3);
+  writeln(s0);
+  if s0<>10.0 then
+    halt(1);
+
+  testsingle;
+  // testdouble;
+
+  writeln('ok');
+end.