* AVR: fixes pushing and handling of stack passed parameters

git-svn-id: trunk@43983 -
This commit is contained in:
florian 2020-01-19 15:55:21 +00:00
parent 6f434b6751
commit 96a4cda03b
4 changed files with 70 additions and 101 deletions

View File

@ -202,8 +202,12 @@ unit cgcpu;
a_load_reg_reg(list,paraloc^.size,paraloc^.size,r,paraloc^.register);
LOC_REFERENCE,LOC_CREFERENCE:
begin
reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,2,[]);
a_load_reg_ref(list,paraloc^.size,paraloc^.size,r,ref);
reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,2,[]);
if ref.base<>NR_STACK_POINTER_REG then
Internalerror(2020011801);
{ as AVR allows no stack indirect addressing, everything else than a push makes no sense }
list.concat(taicpu.op_reg(A_PUSH,r));
end;
else
internalerror(2002071004);
@ -215,91 +219,49 @@ unit cgcpu;
hp : PCGParaLocation;
begin
{ if use_push(cgpara) then
begin
if tcgsize2size[cgpara.Size] > 2 then
begin
if tcgsize2size[cgpara.Size] <> 4 then
internalerror(2013031101);
if cgpara.location^.Next = nil then
begin
if tcgsize2size[cgpara.location^.size] <> 4 then
internalerror(2013031101);
end
else
begin
if tcgsize2size[cgpara.location^.size] <> 2 then
internalerror(2013031101);
if tcgsize2size[cgpara.location^.Next^.size] <> 2 then
internalerror(2013031101);
if cgpara.location^.Next^.Next <> nil then
internalerror(2013031101);
end;
if not(tcgsize2size[cgpara.Size] in [1..4]) then
internalerror(2014011101);
if tcgsize2size[cgpara.size]>cgpara.alignment then
pushsize:=cgpara.size
else
pushsize:=int_cgsize(cgpara.alignment);
pushsize2 := int_cgsize(tcgsize2size[pushsize] - 2);
list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize2],makeregsize(list,GetNextReg(r),pushsize2)));
list.concat(taicpu.op_reg(A_PUSH,S_W,makeregsize(list,r,OS_16)));
hp:=cgpara.location;
i:=0;
while i<tcgsize2size[cgpara.Size] do
begin
if not(assigned(hp)) then
internalerror(2014011102);
inc(i, tcgsize2size[hp^.Size]);
if hp^.Loc=LOC_REGISTER then
begin
load_para_loc(r,hp);
hp:=hp^.Next;
{ check if we are not in the last iteration to avoid an internalerror in GetNextReg }
if i<tcgsize2size[cgpara.Size] then
r:=GetNextReg(r);
end
else
begin
cgpara.check_simple_location;
if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
pushsize:=cgpara.location^.size
else
pushsize:=int_cgsize(cgpara.alignment);
list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
load_para_loc(r,hp);
if i<tcgsize2size[cgpara.Size] then
for i2:=1 to tcgsize2size[hp^.Size] do
r:=GetNextReg(r);
hp:=hp^.Next;
end;
end
else }
begin
if not(tcgsize2size[cgpara.Size] in [1..4]) then
internalerror(2014011101);
hp:=cgpara.location;
i:=0;
while i<tcgsize2size[cgpara.Size] do
begin
if not(assigned(hp)) then
internalerror(2014011102);
inc(i, tcgsize2size[hp^.Size]);
if hp^.Loc=LOC_REGISTER then
begin
load_para_loc(r,hp);
hp:=hp^.Next;
{ check if we are not in the last iteration to avoid an internalerror in GetNextReg }
if i<tcgsize2size[cgpara.Size] then
r:=GetNextReg(r);
end
else
begin
load_para_loc(r,hp);
if i<tcgsize2size[cgpara.Size] then
for i2:=1 to tcgsize2size[hp^.Size] do
r:=GetNextReg(r);
hp:=hp^.Next;
end;
end;
if assigned(hp) then
internalerror(2014011103);
end;
if assigned(hp) then
internalerror(2014011103);
end;
procedure tcgavr.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);
var
i : longint;
i,j : longint;
hp : PCGParaLocation;
ref: treference;
tmpreg: TRegister;
begin
if not(tcgsize2size[paraloc.Size] in [1..4]) then
internalerror(2014011101);
@ -325,11 +287,13 @@ unit cgcpu;
end;
LOC_REFERENCE,LOC_CREFERENCE:
begin
reference_reset(ref,paraloc.alignment,[]);
ref.base:=hp^.reference.index;
ref.offset:=hp^.reference.offset;
a_load_const_ref(list,hp^.size,a shr (8*(i-1)),ref);
for j:=1 to tcgsize2size[hp^.size] do
begin
tmpreg:=getintregister(list,OS_8);
a_load_const_reg(list,OS_8,(a shr (8*(i-1+j-1))) and $ff,tmpreg);
{ as AVR allows no stack indirect addressing, everything else than a push makes no sense }
list.concat(taicpu.op_reg(A_PUSH,tmpreg));
end;
inc(i,tcgsize2size[hp^.size]);
hp:=hp^.Next;
end;
@ -345,6 +309,8 @@ unit cgcpu;
tmpref, ref: treference;
location: pcgparalocation;
sizeleft: tcgint;
i: Integer;
tmpreg: TRegister;
begin
location := paraloc.location;
tmpref := r;
@ -357,15 +323,14 @@ unit cgcpu;
a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
LOC_REFERENCE:
begin
reference_reset_base(ref,location^.reference.index,location^.reference.offset,ctempposinvalid,paraloc.alignment,[]);
{ doubles in softemu mode have a strange order of registers and references }
if location^.size=OS_32 then
g_concatcopy(list,tmpref,ref,4)
else
ref:=tmpref;
for i:=1 to sizeleft do
begin
g_concatcopy(list,tmpref,ref,sizeleft);
if assigned(location^.next) then
internalerror(2005010710);
tmpreg:=getintregister(list,OS_8);
a_load_ref_reg(list,OS_8,OS_8,tmpref,tmpreg);
{ as AVR allows no stack indirect addressing, everything else than a push makes no sense }
list.concat(taicpu.op_reg(A_PUSH,tmpreg));
inc(tmpref.offset);
end;
end;
LOC_VOID:

View File

@ -229,8 +229,8 @@ unit cpubase;
*****************************************************************************}
{ Stack pointer register }
NR_STACK_POINTER_REG = NR_R13;
RS_STACK_POINTER_REG = RS_R13;
NR_STACK_POINTER_REG = NR_INVALID;
RS_STACK_POINTER_REG = RS_INVALID;
{ Frame pointer register }
RS_FRAME_POINTER_REG = RS_R28;
NR_FRAME_POINTER_REG = NR_R28;

View File

@ -355,19 +355,19 @@ unit cpupara;
begin
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paraloc^.size:=OS_ADDR;
paraloc^.def:=cpointerdef.getreusable_no_free(paradef);
assignintreg
end
paraloc^.size:=OS_ADDR;
paraloc^.def:=cpointerdef.getreusable_no_free(paradef);
assignintreg;
end
else
begin
paraloc^.def:=hp.vardef;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
inc(stack_offset,hp.vardef.size);
end;
dec(paralen,hp.vardef.size);
paraloc^.def:=hp.vardef;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
inc(stack_offset,paralen);
end;
paralen:=0;
end;
else
internalerror(2002071002);

View File

@ -1597,7 +1597,11 @@ unit rgobj;
{ FIXME: temp variable r is needed here to avoid Internal error 20060521 }
{ while compiling the compiler. }
tmpr:=NR_STACK_POINTER_REG;
if regtype=getregtype(tmpr) then
{ e.g. AVR does not have a stack pointer register }
{$push}{$warnings off}
if (RS_STACK_POINTER_REG<>RS_INVALID) and
{$pop}
(regtype=getregtype(tmpr)) then
include(adj_colours,RS_STACK_POINTER_REG);
{Assume a spill by default...}
found:=false;