+ implementation of shifting operations for avr

* handle shl/shr operand size correctly

git-svn-id: branches/avr@17109 -
This commit is contained in:
florian 2011-03-09 19:48:01 +00:00
parent f5694da7bc
commit 8d960cb608
5 changed files with 113 additions and 4 deletions

View File

@ -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:

View File

@ -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.

View File

@ -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',

View File

@ -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);

View File

@ -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;