diff --git a/compiler/avr/cgcpu.pas b/compiler/avr/cgcpu.pas index b5eeeb863b..698c231357 100644 --- a/compiler/avr/cgcpu.pas +++ b/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); var + countreg, tmpreg: tregister; i : integer; instr : taicpu; paraloc1,paraloc2,paraloc3 : TCGPara; + l1,l2 : tasmlabel; begin case op of OP_ADD: @@ -488,7 +490,69 @@ unit cgcpu; OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR: 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; OP_AND,OP_OR,OP_XOR: diff --git a/compiler/avr/cpubase.pas b/compiler/avr/cpubase.pas index 50c902e376..94ab41a06b 100644 --- a/compiler/avr/cpubase.pas +++ b/compiler/avr/cpubase.pas @@ -44,7 +44,7 @@ unit cpubase; type 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_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, @@ -343,6 +343,11 @@ unit cpubase; { returns the next virtual register } 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 uses @@ -471,4 +476,16 @@ unit cpubase; result:=TRegister(longint(r)+1); 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. diff --git a/compiler/avr/itcpugas.pas b/compiler/avr/itcpugas.pas index 0b2d49d92a..6af73515c7 100644 --- a/compiler/avr/itcpugas.pas +++ b/compiler/avr/itcpugas.pas @@ -35,7 +35,7 @@ interface processor manufacturer. } 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', 'ser','mul','muls','fmul','fmuls','fmulsu','rjmp','ijmp', 'eijmp','jmp','rcall','icall','eicall','call','ret','reti','cpse', diff --git a/compiler/ncgmat.pas b/compiler/ncgmat.pas index ddf211afe0..2d47e78ec4 100644 --- a/compiler/ncgmat.pas +++ b/compiler/ncgmat.pas @@ -410,11 +410,16 @@ implementation shln: op:=OP_SHL; shrn: op:=OP_SHR; end; +{$ifdef cpunodefaultint} + opsize:=left.location.size; +{$else cpunodefaultint} { load left operators in a register } if is_signed(left.resultdef) then opsize:=OS_SINT else opsize:=OS_INT; +{$endif cpunodefaultint} + location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true); location_reset(location,LOC_REGISTER,opsize); location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize); diff --git a/compiler/nmat.pas b/compiler/nmat.pas index 82fb005c9f..ce9d0f3b9f 100644 --- a/compiler/nmat.pas +++ b/compiler/nmat.pas @@ -483,6 +483,7 @@ implementation function tshlshrnode.pass_typecheck:tnode; var t : tnode; + nd : tdef; begin result:=nil; typecheckpass(left); @@ -508,6 +509,14 @@ implementation exit; 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 32 bit for backwards compatibility. That way 'shl 33' is the same as 'shl 1'. It's ugly but compatible with delphi/tp/gcc } @@ -516,12 +525,26 @@ implementation begin { keep singness of orignal type } if is_signed(left.resultdef) then +{$ifdef cpunodefaultint} + inserttypeconv(left,nd) +{$else cpunodefaultint} inserttypeconv(left,s32inttype) +{$endif cpunodefaultint} else - inserttypeconv(left,u32inttype); + begin +{$ifdef cpunodefaultint} + inserttypeconv(left,nd) +{$else cpunodefaultint} + inserttypeconv(left,u32inttype); +{$endif cpunodefaultint} + end end; +{$ifdef cpunodefaultint} + inserttypeconv(right,nd); +{$else cpunodefaultint} inserttypeconv(right,sinttype); +{$endif cpunodefaultint} resultdef:=left.resultdef; end;