Browse Source

+ RiscV: make use of the fmv.w.x/fmv.d.x instruction to load 0.0

florian 6 months ago
parent
commit
971d97c179

+ 3 - 2
compiler/riscv/cpubase.pas

@@ -128,9 +128,10 @@ uses
         A_FADD_S,A_FSUB_S,A_FMUL_S,A_FDIV_S,
         A_FSQRT_S,A_FSGNJ_S,A_FSGNJN_S,A_FSGNJX_S,
         A_FMIN_S,A_FMAX_S,
-        A_FMV_X_S,A_FEQ_S,A_FLT_S,A_FLE_S,A_FCLASS_S,
+        A_FMV_X_S,A_FMV_X_W,
+        A_FEQ_S,A_FLT_S,A_FLE_S,A_FCLASS_S,
         A_FCVT_W_S,A_FCVT_WU_S,A_FCVT_S_W,A_FCVT_S_WU,
-        A_FMV_S_X,
+        A_FMV_S_X,A_FMV_W_X,
         A_FRCSR,A_FRRM,A_FRFLAGS,A_FSCSR,A_FSRM,
         A_FSFLAGS,A_FSRMI,A_FSFLAGSI,
 

+ 3 - 2
compiler/riscv/itcpugas.pas

@@ -119,9 +119,10 @@ unit itcpugas;
         'fadd.s','fsub.s','fmul.s','fdiv.s',
         'fsqrt.s','fsgnj.s','fsgnjn.s','fsgnjx.s',
         'fmin.s','fmax.s',
-        'fmv.x.s','feq.s','flt.s','fle.s','fclass.s',
+        'fmv.x.s','fmv.x.w',
+        'feq.s','flt.s','fle.s','fclass.s',
         'fcvt.w.s','fcvt.wu.s','fcvt.s.w','fcvt.s.wu',
-        'fmv.s.x',
+        'fmv.s.x','fmv.w.x',
         'frcsr','frrm','frflags','fscsr','fsrm',
         'fsflags','fsrmi','fsflagsi',
 

+ 41 - 64
compiler/riscv/nrvcon.pas

@@ -26,10 +26,12 @@ unit nrvcon;
 interface
 
     uses
-      ncgcon,cpubase;
+      node,ncgcon,cpubase;
 
     type
       trvrealconstnode = class(tcgrealconstnode)
+        function pass_1 : tnode;override;
+
         procedure pass_generate_code;override;
       end;
 
@@ -40,9 +42,10 @@ implementation
       verbose,
       globtype,globals,
       cpuinfo,
-      aasmbase,aasmtai,aasmdata,symdef,
+      aasmbase,aasmtai,aasmcpu,aasmdata,
+      symdef,
       defutil,
-      cgbase,cgutils,
+      cgbase,cgobj,cgutils,
       procinfo,
       ncon;
 
@@ -50,6 +53,22 @@ implementation
                            TARMREALCONSTNODE
 *****************************************************************************}
 
+    function trvrealconstnode.pass_1 : tnode;
+      begin
+        result:=nil;
+        if is_number_float(value_real) and (value_real=0.0) and (get_real_sign(value_real)=1) and
+          (
+            is_single(resultdef)
+{$ifdef RISCV64}
+            or is_double(resultdef)
+{$endif RISCV64}
+          ) then
+           expectloc:=LOC_FPUREGISTER
+         else
+           expectloc:=LOC_CREFERENCE;
+      end;
+
+
     procedure trvrealconstnode.pass_generate_code;
       { I suppose the parser/pass_1 must make sure the generated real  }
       { constants are actually supported by the target processor? (JM) }
@@ -61,69 +80,27 @@ implementation
          realait : tairealconsttype;
 
       begin
-        location_reset_ref(location,LOC_CREFERENCE,def_cgsize(resultdef),4);
-        lastlabel:=nil;
-        realait:=floattype2ait[tfloatdef(resultdef).floattype];
-        { const already used ? }
-        if not assigned(lab_real) then
+        if is_number_float(value_real) and (value_real=0.0) and (get_real_sign(value_real)=1) and
+          (
+            is_single(resultdef)
+{$ifdef RISCV64}
+            or is_double(resultdef)
+{$endif RISCV64}
+          ) then
           begin
-            current_asmdata.getjumplabel(lastlabel);
-            lab_real:=lastlabel;
-            current_procinfo.aktlocaldata.concat(Tai_label.Create(lastlabel));
-            location.reference.symboldata:=current_procinfo.aktlocaldata.last;
-            case realait of
-              aitrealconst_s32bit :
-                begin
-                  current_procinfo.aktlocaldata.concat(tai_realconst.create_s32real(ts32real(value_real)));
-                  { range checking? }
-                  if floating_point_range_check_error and
-                    (tai_realconst(current_procinfo.aktlocaldata.last).value.s32val=MathInf.Value) then
-                    Message(parser_e_range_check_error);
-                end;
-
-              aitrealconst_s64bit :
-                begin
-                  current_procinfo.aktlocaldata.concat(tai_realconst.create_s64real(ts64real(value_real)));
-
-                  { range checking? }
-                  if floating_point_range_check_error and
-                    (tai_realconst(current_procinfo.aktlocaldata.last).value.s64val=MathInf.Value) then
-                    Message(parser_e_range_check_error);
-               end;
-
-              aitrealconst_s80bit :
-                begin
-                  current_procinfo.aktlocaldata.concat(tai_realconst.create_s80real(value_real,tfloatdef(resultdef).size));
-
-                  { range checking? }
-                  if floating_point_range_check_error and
-                    (tai_realconst(current_procinfo.aktlocaldata.last).value.s80val=MathInf.Value) then
-                    Message(parser_e_range_check_error);
-                end;
-{$ifdef cpufloat128}
-              aitrealconst_s128bit :
-                begin
-                  current_procinfo.aktlocaldata.concat(tai_realconst.create_s128real(value_real));
-
-                  { range checking? }
-                  if floating_point_range_check_error and
-                    (tai_realconst(current_procinfo.aktlocaldata.last).value.s128val=MathInf.Value) then
-                    Message(parser_e_range_check_error);
-                end;
-{$endif cpufloat128}
-
-              { the round is necessary for native compilers where comp isn't a float }
-              aitrealconst_s64comp :
-                if (value_real>9223372036854775807.0) or (value_real<-9223372036854775808.0) then
-                  message(parser_e_range_check_error)
-                else
-                  current_procinfo.aktlocaldata.concat(tai_realconst.create_s64compreal(round(value_real)));
+            location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+            location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+            if is_single(resultdef) then
+              current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg(A_FMV_W_X,location.register,NR_X0))
+{$ifdef RISCV64}
+            else if is_double(resultdef) then
+              current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg(A_FMV_D_X,location.register,NR_X0))
+{$endif RISCV64}
             else
-              internalerror(2005092401);
-            end;
-          end;
-        location.reference.symbol:=lab_real;
-        location.reference.refaddr:=addr_pcrel;
+              Internalerror(2025011103);
+          end
+        else
+          inherited pass_generate_code;
       end;
 
 begin

+ 2 - 2
compiler/riscv32/cpunode.pas

@@ -44,8 +44,8 @@ unit cpunode;
        nrvset,
        nrvinl,
        nrv32mat,
-       nrv32cnv
-//       ,nrvcon
+       nrv32cnv,
+       nrvcon
        ;
 
 end.

+ 2 - 1
compiler/riscv64/cpunode.pas

@@ -46,7 +46,8 @@ uses
   nrv64mat,
   nrv64cnv,
   nrv64ld,
-  nrvutil
+  nrvutil,
+  nrvcon
 {$else not llvm}
   llvmnode
 {$endif not llvm}