Browse Source

* avr directly encodes constant shifts of 64 bit values

git-svn-id: trunk@43348 -
(cherry picked from commit f61207f1cc24fd547353895c8b83154527b0be64)
florian 5 years ago
parent
commit
b241fec17b
2 changed files with 77 additions and 18 deletions
  1. 32 14
      compiler/avr/cgcpu.pas
  2. 45 4
      compiler/avr/navrmat.pas

+ 32 - 14
compiler/avr/cgcpu.pas

@@ -114,6 +114,8 @@ unit cgcpu;
 
         procedure gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean; var ovloc: tlocation);
 
+      private
+       procedure a_op_const_reg_reg_internal(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, srchi, dst, dsthi: tregister);
       protected
         procedure a_op_reg_reg_internal(list: TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
         procedure a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister);
@@ -123,6 +125,7 @@ unit cgcpu;
       tcg64favr = class(tcg64f32)
         procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
         procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
+        procedure a_op64_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; value: int64;src,dst: tregister64);override;
       end;
 
     procedure create_codegen;
@@ -438,6 +441,12 @@ unit cgcpu;
 
 
      procedure tcgavr.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister);
+       begin
+         a_op_const_reg_reg_internal(list,op,size,a,src,NR_NO,dst,NR_NO);
+       end;
+
+
+     procedure tcgavr.a_op_const_reg_reg_internal(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src,srchi,dst,dsthi: tregister);
        var
          tmpSrc, tmpDst, countreg: TRegister;
          b, b2, i, j: byte;
@@ -478,12 +487,12 @@ unit cgcpu;
                for i:=0 to (tcgsize2size[size]-b-1) do
                  if op=OP_SHL then
                    a_load_reg_reg(list,OS_8,OS_8,
-                     GetOffsetReg64(src,NR_NO,i),
-                     GetOffsetReg64(dst,NR_NO,i+b))
+                     GetOffsetReg64(src,srchi,i),
+                     GetOffsetReg64(dst,dsthi,i+b))
                  else
                    a_load_reg_reg(list,OS_8,OS_8,
-                     GetOffsetReg64(src,NR_NO,i+b),
-                     GetOffsetReg64(dst,NR_NO,i));
+                     GetOffsetReg64(src,srchi,i+b),
+                     GetOffsetReg64(dst,dsthi,i));
 
              { remaining bit shifts }
              if b2 > 0 then
@@ -503,17 +512,17 @@ unit cgcpu;
                      a_load_const_reg(list,OS_8,b2,countreg);
                      cg.a_label(list,l1);
                      if op=OP_SHL then
-                       list.concat(taicpu.op_reg(A_LSL,GetOffsetReg64(dst,NR_NO,b)))
+                       list.concat(taicpu.op_reg(A_LSL,GetOffsetReg64(dst,dsthi,b)))
                      else
-                       list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,NR_NO,tcgsize2size[size]-1-b)));
+                       list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1-b)));
 
                      if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
                        begin
                          for i:=2+b to tcgsize2size[size] do
                            if op=OP_SHL then
-                             list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,NR_NO,i-1)))
+                             list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1)))
                            else
-                             list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,NR_NO,tcgsize2size[size]-i)));
+                             list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
                        end;
                      list.concat(taicpu.op_reg(A_DEC,countreg));
                      a_jmp_flags(list,F_NE,l1);
@@ -527,19 +536,19 @@ unit cgcpu;
                      begin
                        if op=OP_SHL then
                          list.concat(taicpu.op_reg(A_LSL,
-                         GetOffsetReg64(dst,NR_NO,b)))
+                         GetOffsetReg64(dst,dsthi,b)))
                        else
                          list.concat(taicpu.op_reg(A_LSR,
-                           GetOffsetReg64(dst,NR_NO,tcgsize2size[size]-b-1)));
+                           GetOffsetReg64(dst,dsthi,tcgsize2size[size]-b-1)));
 
                        if not(size in [OS_8,OS_S8]) then
                          for i:=2 to tcgsize2size[size]-b do
                            if op=OP_SHL then
                              list.concat(taicpu.op_reg(A_ROL,
-                               GetOffsetReg64(dst,NR_NO,b+i-1)))
+                               GetOffsetReg64(dst,dsthi,b+i-1)))
                            else
                              list.concat(taicpu.op_reg(A_ROR,
-                               GetOffsetReg64(dst,NR_NO,tcgsize2size[size]-b-i)));
+                               GetOffsetReg64(dst,dsthi,tcgsize2size[size]-b-i)));
                      end;
                    end;
                end;
@@ -548,9 +557,9 @@ unit cgcpu;
                  Do last,then optimizer can optimize register moves }
                for i:=1 to b do
                  if op=OP_SHL then
-                   emit_mov(list,GetOffsetReg64(dst,NR_NO,i-1),NR_R1)
+                   emit_mov(list,GetOffsetReg64(dst,dsthi,i-1),NR_R1)
                  else
-                   emit_mov(list,GetOffsetReg64(dst,NR_NO,tcgsize2size[size]-i),NR_R1);
+                   emit_mov(list,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i),NR_R1);
            end
          else
            inherited a_op_const_reg_reg(list,op,size,a,src,dst);
@@ -2849,6 +2858,15 @@ unit cgcpu;
       end;
 
 
+   procedure tcg64favr.a_op64_const_reg_reg(list: TAsmList; op: TOpCg;size: tcgsize;value: int64;src,dst : tregister64);
+      begin
+        if op in [OP_SHL,OP_SHR] then
+          tcgavr(cg).a_op_const_reg_reg_internal(list,Op,size,value,src.reglo,src.reghi,dst.reglo,dst.reghi)
+        else
+          Inherited a_op64_const_reg_reg(list,op,size,value,src,dst);
+      end;
+
+
     procedure create_codegen;
       begin
         cg:=tcgavr.create;

+ 45 - 4
compiler/avr/navrmat.pas

@@ -34,7 +34,9 @@ interface
       end;
 
       tavrshlshrnode = class(tcgshlshrnode)
+        function pass_1: tnode;override;
         procedure second_integer;override;
+        procedure second_64bit;override;
       end;
 
 implementation
@@ -46,7 +48,7 @@ implementation
       aasmbase,aasmcpu,aasmtai,aasmdata,
       defutil,
       cgbase,cgobj,hlcgobj,cgutils,
-      pass_2,procinfo,
+      pass_1,pass_2,procinfo,
       ncon,
       cpubase,
       ncgutil,cgcpu;
@@ -129,6 +131,28 @@ implementation
       end;
 
 
+{*****************************************************************************
+                             TAVRSHLSHRNODE
+*****************************************************************************}
+
+    function tavrshlshrnode.pass_1 : tnode;
+      begin
+        { the avr code generator can handle 64 bit shifts by constants directly }
+        if is_constintnode(right) and is_64bit(resultdef) then
+          begin
+            result:=nil;
+            firstpass(left);
+            firstpass(right);
+            if codegenerror then
+              exit;
+
+            expectloc:=LOC_REGISTER;
+          end
+        else
+          Result:=inherited pass_1;
+      end;
+
+
     procedure tavrshlshrnode.second_integer;
       var
          op : topcg;
@@ -152,7 +176,13 @@ implementation
           (left.location.size<>opsize) then
           hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true);
         location_reset(location,LOC_REGISTER,opsize);
-        location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+        if is_64bit(resultdef) then
+          begin
+            location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+            location.registerhi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+          end
+        else
+          location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
 
         { shifting by a constant directly coded: }
         if (right.nodetype=ordconstn) then
@@ -164,8 +194,12 @@ implementation
                shiftval:=tordconstnode(right).value.uvalue and 31
              else
                shiftval:=tordconstnode(right).value.uvalue and 63;
-             hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,opdef,
-               shiftval,left.location.register,location.register);
+             if is_64bit(resultdef) then
+               cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,op,location.size,
+                 shiftval,left.location.register64,location.register64)
+             else
+               hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,opdef,
+                 shiftval,left.location.register,location.register);
           end
         else
           begin
@@ -186,6 +220,13 @@ implementation
           end;
       end;
 
+
+    procedure tavrshlshrnode.second_64bit;
+      begin
+        second_integer;
+        // inherited second_64bit;
+      end;
+
 begin
   cnotnode:=tavrnotnode;
   cshlshrnode:=tavrshlshrnode;