소스 검색

+ implementation of shifting operations for avr
* handle shl/shr operand size correctly

git-svn-id: branches/avr@17109 -

florian 14 년 전
부모
커밋
8d960cb608
5개의 변경된 파일113개의 추가작업 그리고 4개의 파일을 삭제
  1. 65 1
      compiler/avr/cgcpu.pas
  2. 18 1
      compiler/avr/cpubase.pas
  3. 1 1
      compiler/avr/itcpugas.pas
  4. 5 0
      compiler/ncgmat.pas
  5. 24 1
      compiler/nmat.pas

+ 65 - 1
compiler/avr/cgcpu.pas

@@ -378,10 +378,12 @@ unit cgcpu;
 
 
      procedure tcgavr.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
      procedure tcgavr.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
        var
        var
+         countreg,
          tmpreg: tregister;
          tmpreg: tregister;
          i : integer;
          i : integer;
          instr : taicpu;
          instr : taicpu;
          paraloc1,paraloc2,paraloc3 : TCGPara;
          paraloc1,paraloc2,paraloc3 : TCGPara;
+         l1,l2 : tasmlabel;
       begin
       begin
          case op of
          case op of
            OP_ADD:
            OP_ADD:
@@ -488,7 +490,69 @@ unit cgcpu;
 
 
            OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
            OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
              begin
              begin
-               { TODO : Shift operators }
+               current_asmdata.getjumplabel(l1);
+               current_asmdata.getjumplabel(l2);
+               countreg:=getintregister(list,OS_8);
+               a_load_reg_reg(list,size,OS_8,src,countreg);
+               list.concat(taicpu.op_reg_const(A_CP,countreg,0));
+               a_jmp_flags(list,F_EQ,l2);
+               cg.a_label(list,l1);
+               case op of
+                 OP_SHR:
+                   list.concat(taicpu.op_reg(A_LSR,GetOffsetReg(dst,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)));
+                 OP_ROR:
+                   begin
+                     { load carry? }
+                     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,src,0));
+                         list.concat(taicpu.op_none(A_SEC));
+                       end;
+                     list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-1)));
+                   end;
+                 OP_ROL:
+                   begin
+                     { load carry? }
+                     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_none(A_SEC));
+                       end;
+                     list.concat(taicpu.op_reg(A_ROL,dst))
+                   end;
+                 else
+                   internalerror(2011030901);
+               end;
+               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
+                       case op of
+                         OP_ROR,
+                         OP_SHR:
+                           list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i)));
+                         OP_ROL,
+                         OP_SHL:
+                           list.concat(taicpu.op_reg(A_ROL,GetOffsetReg(dst,i-1)));
+                         OP_SAR:
+                           list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i)));
+                         else
+                           internalerror(2011030902);
+                       end;
+                   end;
+                 end;
+
+               a_op_const_reg(list,OP_SUB,OS_8,1,countreg);
+               a_jmp_flags(list,F_NE,l1);
+               // keep registers alive
+               list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
+               cg.a_label(list,l2);
              end;
              end;
 
 
            OP_AND,OP_OR,OP_XOR:
            OP_AND,OP_OR,OP_XOR:

+ 18 - 1
compiler/avr/cpubase.pas

@@ -44,7 +44,7 @@ unit cpubase;
 
 
     type
     type
       TAsmOp=(A_None,
       TAsmOp=(A_None,
-        A_ADD,A_ADC,A_ADIW,A_SUB,A_SUBI,A_SBC,A_SBCI,A_SBRC,A_SBRS,A_SBIW,A_AND,A_ANDI,
+        A_ADD,A_ADC,A_ADIW,A_SUB,A_SUBI,A_SBC,A_SBCI,A_SBRC,A_SBRS,A_CLC,A_SEC,A_SBIW,A_AND,A_ANDI,
         A_OR,A_ORI,A_EOR,A_COM,A_NEG,A_SBR,A_CBR,A_INC,A_DEC,A_TST,A_CLR,
         A_OR,A_ORI,A_EOR,A_COM,A_NEG,A_SBR,A_CBR,A_INC,A_DEC,A_TST,A_CLR,
         A_SER,A_MUL,A_MULS,A_FMUL,A_FMULS,A_FMULSU,A_RJMP,A_IJMP,
         A_SER,A_MUL,A_MULS,A_FMUL,A_FMULS,A_FMULSU,A_RJMP,A_IJMP,
         A_EIJMP,A_JMP,A_RCALL,A_ICALL,R_EICALL,A_CALL,A_RET,A_RETI,A_CPSE,
         A_EIJMP,A_JMP,A_RCALL,A_ICALL,R_EICALL,A_CALL,A_RET,A_RETI,A_CPSE,
@@ -343,6 +343,11 @@ unit cpubase;
     { returns the next virtual register }
     { returns the next virtual register }
     function GetNextReg(const r : TRegister) : TRegister;
     function GetNextReg(const r : TRegister) : TRegister;
 
 
+    { returns the last virtual register }
+    function GetLastReg(const r : TRegister) : TRegister;
+
+    function GetOffsetReg(const r : TRegister;ofs : shortint) : TRegister;
+
   implementation
   implementation
 
 
     uses
     uses
@@ -471,4 +476,16 @@ unit cpubase;
         result:=TRegister(longint(r)+1);
         result:=TRegister(longint(r)+1);
       end;
       end;
 
 
+
+    function GetLastReg(const r: TRegister): TRegister;
+      begin
+        result:=TRegister(longint(r)-1);
+      end;
+
+
+    function GetOffsetReg(const r: TRegister;ofs : shortint): TRegister;
+      begin
+        result:=TRegister(longint(r)+ofs);
+      end;
+
 end.
 end.

+ 1 - 1
compiler/avr/itcpugas.pas

@@ -35,7 +35,7 @@ interface
       processor manufacturer.
       processor manufacturer.
     }
     }
     gas_op2str : op2strtable = ('',
     gas_op2str : op2strtable = ('',
-        'add','adc','adiw','sub','subi','sbc','sbci','sbrc','sbrs','sbiw','and','andi',
+        'add','adc','adiw','sub','subi','sbc','sbci','sbrc','sbrs','clc','sec','sbiw','and','andi',
         'or','ori','eor','com','neg','sbr','cbr','inc','dec','tst','clr',
         'or','ori','eor','com','neg','sbr','cbr','inc','dec','tst','clr',
         'ser','mul','muls','fmul','fmuls','fmulsu','rjmp','ijmp',
         'ser','mul','muls','fmul','fmuls','fmulsu','rjmp','ijmp',
         'eijmp','jmp','rcall','icall','eicall','call','ret','reti','cpse',
         'eijmp','jmp','rcall','icall','eicall','call','ret','reti','cpse',

+ 5 - 0
compiler/ncgmat.pas

@@ -410,11 +410,16 @@ implementation
            shln: op:=OP_SHL;
            shln: op:=OP_SHL;
            shrn: op:=OP_SHR;
            shrn: op:=OP_SHR;
          end;
          end;
+{$ifdef cpunodefaultint}
+        opsize:=left.location.size;
+{$else cpunodefaultint}
          { load left operators in a register }
          { load left operators in a register }
          if is_signed(left.resultdef) then
          if is_signed(left.resultdef) then
            opsize:=OS_SINT
            opsize:=OS_SINT
          else
          else
            opsize:=OS_INT;
            opsize:=OS_INT;
+{$endif cpunodefaultint}
+
          location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
          location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
          location_reset(location,LOC_REGISTER,opsize);
          location_reset(location,LOC_REGISTER,opsize);
          location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
          location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);

+ 24 - 1
compiler/nmat.pas

@@ -483,6 +483,7 @@ implementation
     function tshlshrnode.pass_typecheck:tnode;
     function tshlshrnode.pass_typecheck:tnode;
       var
       var
          t : tnode;
          t : tnode;
+         nd : tdef;
       begin
       begin
          result:=nil;
          result:=nil;
          typecheckpass(left);
          typecheckpass(left);
@@ -508,6 +509,14 @@ implementation
               exit;
               exit;
            end;
            end;
 
 
+{$ifdef cpunodefaultint}
+         { for small cpus we use the smallest common type }
+         if (left.resultdef.typ=orddef) and (right.resultdef.typ=orddef) then
+           nd:=get_common_intdef(torddef(left.resultdef),torddef(right.resultdef),false)
+         else
+           nd:=s32inttype;
+{$endif cpunodefaultint}
+
          { calculations for ordinals < 32 bit have to be done in
          { calculations for ordinals < 32 bit have to be done in
            32 bit for backwards compatibility. That way 'shl 33' is
            32 bit for backwards compatibility. That way 'shl 33' is
            the same as 'shl 1'. It's ugly but compatible with delphi/tp/gcc }
            the same as 'shl 1'. It's ugly but compatible with delphi/tp/gcc }
@@ -516,12 +525,26 @@ implementation
            begin
            begin
              { keep singness of orignal type }
              { keep singness of orignal type }
              if is_signed(left.resultdef) then
              if is_signed(left.resultdef) then
+{$ifdef cpunodefaultint}
+               inserttypeconv(left,nd)
+{$else cpunodefaultint}
                inserttypeconv(left,s32inttype)
                inserttypeconv(left,s32inttype)
+{$endif cpunodefaultint}
              else
              else
-               inserttypeconv(left,u32inttype);
+               begin
+{$ifdef cpunodefaultint}
+                 inserttypeconv(left,nd)
+{$else cpunodefaultint}
+                 inserttypeconv(left,u32inttype);
+{$endif cpunodefaultint}
+               end
            end;
            end;
 
 
+{$ifdef cpunodefaultint}
+         inserttypeconv(right,nd);
+{$else cpunodefaultint}
          inserttypeconv(right,sinttype);
          inserttypeconv(right,sinttype);
+{$endif cpunodefaultint}
 
 
          resultdef:=left.resultdef;
          resultdef:=left.resultdef;
       end;
       end;