mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-07 03:30:37 +02:00
+ implementation of shifting operations for avr
* handle shl/shr operand size correctly git-svn-id: branches/avr@17109 -
This commit is contained in:
parent
f5694da7bc
commit
8d960cb608
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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',
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user