Browse Source

+ support of 64 bit operations on avr

git-svn-id: trunk@22836 -
florian 12 years ago
parent
commit
a3dff44489
1 changed files with 155 additions and 92 deletions
  1. 155 92
      compiler/avr/cgcpu.pas

+ 155 - 92
compiler/avr/cgcpu.pas

@@ -56,7 +56,7 @@ unit cgcpu;
         procedure a_call_ref(list : TAsmList;ref: treference);override;
 
         procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
-        procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+        procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister); override;
 
         { move instructions }
         procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
@@ -107,6 +107,9 @@ unit cgcpu;
         function GetStore(const ref: treference): tasmop;
 
         procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
+      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);
       end;
 
       tcg64favr = class(tcg64f32)
@@ -332,60 +335,22 @@ unit cgcpu;
 
 
      procedure tcgavr.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
-       var
-         mask : qword;
-         shift : byte;
-         i : byte;
-         tmpreg : tregister;
        begin
-         mask:=$ff;
-         shift:=0;
-         case op of
-           OP_OR:
-             begin
-               for i:=1 to tcgsize2size[size] do
-                 begin
-                   list.concat(taicpu.op_reg_const(A_ORI,reg,(a and mask) shr shift));
-                   reg:=GetNextReg(reg);
-                   mask:=mask shl 8;
-                   inc(shift,8);
-                 end;
-             end;
-           OP_AND:
-             begin
-               for i:=1 to tcgsize2size[size] do
-                 begin
-                   list.concat(taicpu.op_reg_const(A_ANDI,reg,(a and mask) shr shift));
-                   reg:=GetNextReg(reg);
-                   mask:=mask shl 8;
-                   inc(shift,8);
-                 end;
-             end;
-           OP_SUB:
-             begin
-               list.concat(taicpu.op_reg_const(A_SUBI,reg,a));
-               if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
-                 begin
-                   for i:=2 to tcgsize2size[size] do
-                     begin
-                       reg:=GetNextReg(reg);
-                       mask:=mask shl 8;
-                       inc(shift,8);
-                       list.concat(taicpu.op_reg_const(A_SBCI,reg,(a and mask) shr shift));
-                     end;
-                 end;
-             end;
-         else
-           begin
-             tmpreg:=getintregister(list,size);
-             a_load_const_reg(list,size,a,tmpreg);
-             a_op_reg_reg(list,op,size,tmpreg,reg);
-           end;
-         end;
+         if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
+           internalerror(2012102403);
+         a_op_const_reg_internal(list,Op,size,a,reg,NR_NO);
+       end;
+
+
+     procedure tcgavr.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister);
+       begin
+         if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
+           internalerror(2012102401);
+         a_op_reg_reg_internal(list,Op,size,src,NR_NO,dst,NR_NO);
        end;
 
 
-     procedure tcgavr.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+     procedure tcgavr.a_op_reg_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
        var
          countreg,
          tmpreg: tregister;
@@ -393,6 +358,30 @@ unit cgcpu;
          instr : taicpu;
          paraloc1,paraloc2,paraloc3 : TCGPara;
          l1,l2 : tasmlabel;
+
+       procedure NextSrcDst;
+         begin
+           if i=5 then
+             begin
+               dst:=dsthi;
+               src:=srchi;
+             end
+           else
+             begin
+               dst:=GetNextReg(dst);
+               src:=GetNextReg(src);
+             end;
+         end;
+
+       { iterates TmpReg through all registers of dst }
+       procedure NextTmp;
+         begin
+           if i=5 then
+             tmpreg:=dsthi
+           else
+             tmpreg:=GetNextReg(tmpreg);
+         end;
+
       begin
          case op of
            OP_ADD:
@@ -402,12 +391,10 @@ unit cgcpu;
                  begin
                    for i:=2 to tcgsize2size[size] do
                      begin
-                       dst:=GetNextReg(dst);
-                       src:=GetNextReg(src);
+                       NextSrcDst;
                        list.concat(taicpu.op_reg_reg(A_ADC,dst,src));
-                   end;
-                 end
-               else
+                     end;
+                 end;
              end;
 
            OP_SUB:
@@ -417,8 +404,7 @@ unit cgcpu;
                  begin
                    for i:=2 to tcgsize2size[size] do
                      begin
-                       dst:=GetNextReg(dst);
-                       src:=GetNextReg(src);
+                       NextSrcDst;
                        list.concat(taicpu.op_reg_reg(A_SBC,dst,src));
                      end;
                  end;
@@ -435,18 +421,16 @@ unit cgcpu;
                    for i:=2 to tcgsize2size[size] do
                      begin
                        list.concat(taicpu.op_reg(A_COM,tmpreg));
-                       tmpreg:=GetNextReg(tmpreg);
+                       NextTmp;
                      end;
                    list.concat(taicpu.op_reg(A_NEG,dst));
                    tmpreg:=GetNextReg(dst);
                    for i:=2 to tcgsize2size[size] do
                      begin
                        list.concat(taicpu.op_reg_const(A_SBCI,dst,-1));
-                       tmpreg:=GetNextReg(tmpreg);
+                       NextTmp;
                    end;
-                 end
-               else
-                 list.concat(taicpu.op_reg(A_NEG,dst));
+                 end;
              end;
 
            OP_NOT:
@@ -456,8 +440,7 @@ unit cgcpu;
                    if src<>dst then
                      a_load_reg_reg(list,OS_8,OS_8,src,dst);
                    list.concat(taicpu.op_reg(A_COM,dst));
-                   src:=GetNextReg(src);
-                   dst:=GetNextReg(dst);
+                   NextSrcDst;
                  end;
              end;
 
@@ -508,11 +491,11 @@ unit cgcpu;
                cg.a_label(list,l1);
                case op of
                  OP_SHR:
-                   list.concat(taicpu.op_reg(A_LSR,GetOffsetReg(dst,tcgsize2size[size]-1)));
+                   list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
                  OP_SHL:
                    list.concat(taicpu.op_reg(A_LSL,dst));
                  OP_SAR:
-                   list.concat(taicpu.op_reg(A_ASR,GetOffsetReg(dst,tcgsize2size[size]-1)));
+                   list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
                  OP_ROR:
                    begin
                      { load carry? }
@@ -522,7 +505,7 @@ unit cgcpu;
                          list.concat(taicpu.op_reg_const(A_SBRC,src,0));
                          list.concat(taicpu.op_none(A_SEC));
                        end;
-                     list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-1)));
+                     list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
                    end;
                  OP_ROL:
                    begin
@@ -530,7 +513,7 @@ unit cgcpu;
                      if not(size in [OS_8,OS_S8]) then
                        begin
                          list.concat(taicpu.op_none(A_CLC));
-                         list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg(dst,tcgsize2size[size]-1),7));
+                         list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1),7));
                          list.concat(taicpu.op_none(A_SEC));
                        end;
                      list.concat(taicpu.op_reg(A_ROL,dst))
@@ -545,12 +528,12 @@ unit cgcpu;
                        case op of
                          OP_ROR,
                          OP_SHR:
-                           list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i)));
+                           list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
                          OP_ROL,
                          OP_SHL:
-                           list.concat(taicpu.op_reg(A_ROL,GetOffsetReg(dst,i-1)));
+                           list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1)));
                          OP_SAR:
-                           list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i)));
+                           list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
                          else
                            internalerror(2011030902);
                        end;
@@ -569,8 +552,7 @@ unit cgcpu;
                 for i:=1 to tcgsize2size[size] do
                   begin
                     list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src));
-                    dst:=GetNextReg(dst);
-                    src:=GetNextReg(src);
+                    NextSrcDst;
                   end;
              end;
            else
@@ -578,6 +560,81 @@ unit cgcpu;
          end;
        end;
 
+     procedure tcgavr.a_op_const_reg_internal(list: TAsmList; Op: TOpCG;
+      size: TCGSize; a: tcgint; reg, reghi: TRegister);
+
+       var
+         mask : qword;
+         shift : byte;
+         i : byte;
+         tmpreg : tregister;
+         tmpreg64 : tregister64;
+
+      procedure NextReg;
+        begin
+          if i=5 then
+            reg:=reghi
+          else
+            reg:=GetNextReg(reg);
+        end;
+
+       begin
+         mask:=$ff;
+         shift:=0;
+         case op of
+           OP_OR:
+             begin
+               for i:=1 to tcgsize2size[size] do
+                 begin
+                   list.concat(taicpu.op_reg_const(A_ORI,reg,(a and mask) shr shift));
+                   NextReg;
+                   mask:=mask shl 8;
+                   inc(shift,8);
+                 end;
+             end;
+           OP_AND:
+             begin
+               for i:=1 to tcgsize2size[size] do
+                 begin
+                   list.concat(taicpu.op_reg_const(A_ANDI,reg,(a and mask) shr shift));
+                   NextReg;
+                   mask:=mask shl 8;
+                   inc(shift,8);
+                 end;
+             end;
+           OP_SUB:
+             begin
+               list.concat(taicpu.op_reg_const(A_SUBI,reg,a));
+               if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
+                 begin
+                   for i:=2 to tcgsize2size[size] do
+                     begin
+                       NextReg;
+                       mask:=mask shl 8;
+                       inc(shift,8);
+                       list.concat(taicpu.op_reg_const(A_SBCI,reg,(a and mask) shr shift));
+                     end;
+                 end;
+             end;
+         else
+           begin
+             if size in [OS_64,OS_S64] then
+               begin
+                 tmpreg64.reglo:=getintregister(list,OS_32);
+                 tmpreg64.reghi:=getintregister(list,OS_32);
+                 cg64.a_load64_const_reg(list,a,tmpreg64);
+                 cg64.a_op64_reg_reg(list,op,size,tmpreg64,joinreg64(reg,reghi));
+               end
+             else
+               begin
+                 tmpreg:=getintregister(list,size);
+                 a_load_const_reg(list,size,a,tmpreg);
+                 a_op_reg_reg(list,op,size,tmpreg,reg);
+               end;
+           end;
+       end;
+     end;
+
 
      procedure tcgavr.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
        var
@@ -1020,18 +1077,20 @@ unit cgcpu;
                  end;
                OS_S8:
                  begin
-                   { dest is always at least 16 bit at this point }
                    emit_mov(list,reg2,reg1);
 
-                   reg2:=GetNextReg(reg2);
-                   list.concat(taicpu.op_reg(A_CLR,reg2));
-                   list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
-                   list.concat(taicpu.op_reg(A_COM,reg2));
-                   tmpreg:=reg2;
-                   for i:=3 to tcgsize2size[tosize] do
+                   if tcgsize2size[tosize]>1 then
                      begin
                        reg2:=GetNextReg(reg2);
-                       emit_mov(list,reg2,tmpreg);
+                       list.concat(taicpu.op_reg(A_CLR,reg2));
+                       list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
+                       list.concat(taicpu.op_reg(A_COM,reg2));
+                       tmpreg:=reg2;
+                       for i:=3 to tcgsize2size[tosize] do
+                         begin
+                           reg2:=GetNextReg(reg2);
+                           emit_mov(list,reg2,tmpreg);
+                         end;
                      end;
                  end;
                OS_16:
@@ -1050,22 +1109,24 @@ unit cgcpu;
                  end;
                OS_S16:
                  begin
-                   { dest is always at least 32 bit at this point }
                    emit_mov(list,reg2,reg1);
 
                    reg1:=GetNextReg(reg1);
                    reg2:=GetNextReg(reg2);
                    emit_mov(list,reg2,reg1);
 
-                   reg2:=GetNextReg(reg2);
-                   list.concat(taicpu.op_reg(A_CLR,reg2));
-                   list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
-                   list.concat(taicpu.op_reg(A_COM,reg2));
-                   tmpreg:=reg2;
-                   for i:=4 to tcgsize2size[tosize] do
+                   if tcgsize2size[tosize]>2 then
                      begin
                        reg2:=GetNextReg(reg2);
-                       emit_mov(list,reg2,tmpreg);
+                       list.concat(taicpu.op_reg(A_CLR,reg2));
+                       list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
+                       list.concat(taicpu.op_reg(A_COM,reg2));
+                       tmpreg:=reg2;
+                       for i:=4 to tcgsize2size[tosize] do
+                         begin
+                           reg2:=GetNextReg(reg2);
+                           emit_mov(list,reg2,tmpreg);
+                         end;
                      end;
                  end;
                else
@@ -1733,13 +1794,15 @@ unit cgcpu;
 
     procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
       begin
-        { TODO : a_op64_reg_reg }
+         if not(size in [OS_S64,OS_64]) then
+           internalerror(2012102402);
+         tcgavr(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
       end;
 
 
     procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
       begin
-        { TODO : a_op64_const_reg }
+        tcgavr(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
       end;