瀏覽代碼

+ introduce tcgobj.a_loadfpu_reg_intreg
+ make use of it in tcgtypeconvnode.second_nothing
+ Xtensa: implementation of a_tcgcpu.a_loadfpu_intreg_reg and tcgcpu.a_loadfpu_reg_intreg

git-svn-id: trunk@46858 -

florian 4 年之前
父節點
當前提交
d7fe9914a7
共有 5 個文件被更改,包括 55 次插入16 次删除
  1. 19 1
      compiler/cgobj.pas
  2. 1 0
      compiler/fpcdefs.inc
  3. 1 13
      compiler/hlcg2ll.pas
  4. 13 2
      compiler/ncgcnv.pas
  5. 21 0
      compiler/xtensa/cgcpu.pas

+ 19 - 1
compiler/cgobj.pas

@@ -282,6 +282,7 @@ unit cgobj;
           procedure a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const cgpara : TCGPara);virtual;
 
           procedure a_loadfpu_intreg_reg(list: TAsmList; fromsize, tosize : tcgsize; intreg, fpureg: tregister); virtual;
+          procedure a_loadfpu_reg_intreg(list: TAsmList; fromsize, tosize: tcgsize; fpureg, intreg: tregister); virtual;
 
           { vector register move instructions }
           procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle); virtual;
@@ -1437,7 +1438,9 @@ implementation
              begin
                case getregtype(reg) of
                  R_FPUREGISTER:
-                   a_loadfpu_reg_reg(list,paraloc.size,regsize,paraloc.register,reg)
+                   a_loadfpu_reg_reg(list,paraloc.size,regsize,paraloc.register,reg);
+                 R_INTREGISTER:
+                   a_loadfpu_reg_intreg(list,paraloc.size,regsize,paraloc.register,reg);
                  else
                    internalerror(2015031401);
                  end;
@@ -1974,6 +1977,21 @@ implementation
       end;
 
 
+    procedure tcg.a_loadfpu_reg_intreg(list : TAsmList; fromsize,tosize : tcgsize; fpureg,intreg : tregister);
+      var
+        tmpref: treference;
+      begin
+        if not(tcgsize2size[fromsize] in [4,8]) or
+           not(tcgsize2size[tosize] in [4,8]) or
+           (tcgsize2size[fromsize]<>tcgsize2size[tosize]) then
+          internalerror(2020091201);
+        tg.gettemp(list,tcgsize2size[fromsize],tcgsize2size[fromsize],tt_normal,tmpref);
+        a_loadfpu_reg_ref(list,fromsize,fromsize,fpureg,tmpref);
+        a_load_ref_reg(list,tosize,tosize,tmpref,intreg);
+        tg.ungettemp(list,tmpref);
+      end;
+
+
     procedure tcg.a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference);
       var
         tmpreg : tregister;

+ 1 - 0
compiler/fpcdefs.inc

@@ -341,6 +341,7 @@
   {$define cpuneedsdivhelper}
   {$define cpucapabilities}
   {$define cpurequiresproperalignment}
+  {$define cpufloatintregmov}
 {$endif xtensa}
 
 { Stabs is not officially supported on 64 bit targets by gdb, except on Mac OS X

+ 1 - 13
compiler/hlcg2ll.pas

@@ -2019,19 +2019,7 @@ implementation
                   begin
                     unget_para(paraloc^);
                     gen_alloc_regloc(list,destloc,vardef);
-                    { we can't directly move regular registers into fpu
-                      registers }
-                    if getregtype(paraloc^.register)=R_FPUREGISTER then
-                      begin
-                        { store everything first to memory, then load it in
-                          destloc }
-                        tg.gettemp(list,tcgsize2size[paraloc^.size],para.intsize,tt_persistent,tempref);
-                        cg.a_load_cgparaloc_ref(list,paraloc^,tempref,tcgsize2size[paraloc^.size],tempref.alignment);
-                        cg.a_load_ref_reg(list,int_cgsize(tcgsize2size[paraloc^.size]),destloc.size,tempref,destloc.register);
-                        tg.ungettemp(list,tempref);
-                      end
-                    else
-                      cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,sizeof(aint));
+                    cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,sizeof(aint));
                   end;
               end;
           end;

+ 13 - 2
compiler/ncgcnv.pas

@@ -806,8 +806,19 @@ interface
             (location.loc=LOC_CONSTANT)
            ) or
            ((resultdef.typ=floatdef) xor (location.loc in [LOC_CFPUREGISTER,LOC_FPUREGISTER,LOC_CMMREGISTER,LOC_MMREGISTER])) then
-          hlcg.location_force_mem(current_asmdata.CurrAsmList,location,left.resultdef);
-
+          begin
+            { check if the CPU supports direct moves between int and fpu registers and take advantage of it }
+{$ifdef cpufloatintregmov}
+            if (resultdef.typ<>floatdef) and (location.loc in [LOC_CFPUREGISTER,LOC_FPUREGISTER]) then
+              begin
+                location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+                location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+                cg.a_loadfpu_reg_intreg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register);
+              end
+            else
+{$endif cpufloatintregmov}
+              hlcg.location_force_mem(current_asmdata.CurrAsmList,location,left.resultdef);
+          end;
         { but use the new size, but we don't know the size of all arrays }
         newsize:=def_cgsize(resultdef);
         location.size:=newsize;

+ 21 - 0
compiler/xtensa/cgcpu.pas

@@ -77,6 +77,9 @@ interface
         procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);override;
         procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);override;
 
+        procedure a_loadfpu_intreg_reg(list: TAsmList; fromsize, tosize: tcgsize; intreg, fpureg: tregister);override;
+        procedure a_loadfpu_reg_intreg(list: TAsmList; fromsize, tosize: tcgsize; fpureg, intreg: tregister);override;
+
         procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
 
         procedure g_overflowcheck(list: TAsmList; const Loc:tlocation; def:tdef);override;
@@ -1196,6 +1199,24 @@ implementation
        end;
 
 
+    procedure tcgcpu.a_loadfpu_intreg_reg(list : TAsmList; fromsize,tosize : tcgsize; intreg,fpureg : tregister);
+      begin
+        if not(tcgsize2size[fromsize]=4) or
+           not(tcgsize2size[tosize]=4) then
+          internalerror(2020091102);
+        list.concat(taicpu.op_reg_reg(A_WFR,fpureg,intreg));
+      end;
+
+
+    procedure tcgcpu.a_loadfpu_reg_intreg(list : TAsmList; fromsize,tosize : tcgsize; fpureg,intreg : tregister);
+      begin
+        if not(tcgsize2size[fromsize]=4) or
+           not(tcgsize2size[tosize]=4) then
+          internalerror(2020091202);
+        list.concat(taicpu.op_reg_reg(A_RFR,intreg,fpureg));
+      end;
+
+
     procedure tcgcpu.maybeadjustresult(list : TAsmList; op : TOpCg; size : tcgsize; dst : tregister);
       const
         overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NEG];