* some fixes for parameter handling on avr

git-svn-id: trunk@26425 -
This commit is contained in:
florian 2014-01-11 17:02:34 +00:00
parent 19d71655eb
commit cb48c2afca
2 changed files with 122 additions and 79 deletions

View File

@ -50,6 +50,7 @@ unit cgcpu;
procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);override;
procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
procedure a_load_reg_cgpara(list : TAsmList; size : tcgsize;r : tregister; const cgpara : tcgpara);override;
procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
procedure a_call_reg(list : TAsmList;reg: tregister);override;
@ -205,25 +206,124 @@ unit cgcpu;
end;
procedure tcgavr.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);
procedure load_para_loc(r : TRegister;paraloc : PCGParaLocation);
var
ref : treference;
begin
paramanager.allocparaloc(list,paraloc);
case paraloc^.loc of
LOC_REGISTER,LOC_CREGISTER:
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,2);
a_load_reg_ref(list,paraloc^.size,paraloc^.size,r,ref);
end;
else
internalerror(2002071004);
end;
end;
var
i : longint;
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 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)));
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)));
end;
end
else }
begin
if not(tcgsize2size[cgpara.Size] in [1..4]) then
internalerror(2014011101);
hp:=cgpara.location;
for i:=1 to tcgsize2size[cgpara.Size] do
begin
if not(assigned(hp)) or
(tcgsize2size[hp^.size]<>1) or
(hp^.shiftval<>0) then
internalerror(2014011102);
load_para_loc(r,hp);
hp:=hp^.Next;
r:=GetNextReg(r);
end;
if assigned(hp) then
internalerror(2014011103);
end;
end;
procedure tcgavr.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);
var
ref: treference;
i : longint;
hp : PCGParaLocation;
begin
paraloc.check_simple_location;
paramanager.allocparaloc(list,paraloc.location);
case paraloc.location^.loc of
LOC_REGISTER,LOC_CREGISTER:
a_load_const_reg(list,size,a,paraloc.location^.register);
LOC_REFERENCE:
begin
reference_reset(ref,paraloc.alignment);
ref.base:=paraloc.location^.reference.index;
ref.offset:=paraloc.location^.reference.offset;
a_load_const_ref(list,size,a,ref);
if not(tcgsize2size[paraloc.Size] in [1..4]) then
internalerror(2014011101);
hp:=paraloc.location;
for i:=1 to tcgsize2size[paraloc.Size] do
begin
if not(assigned(hp)) or
(tcgsize2size[hp^.size]<>1) or
(hp^.shiftval<>0) then
internalerror(2014011105);
case hp^.loc of
LOC_REGISTER,LOC_CREGISTER:
a_load_const_reg(list,hp^.size,(a shr (i-1)) and $ff,hp^.register);
LOC_REFERENCE,LOC_CREFERENCE:
begin
list.concat(taicpu.op_const(A_PUSH,(a shr (i-1)) and $ff));
end;
else
internalerror(2002071004);
end;
else
internalerror(2002081101);
end;
hp:=hp^.Next;
end;
if assigned(hp) then
internalerror(2014011104);
end;
@ -271,26 +371,11 @@ unit cgcpu;
procedure tcgavr.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
var
ref: treference;
tmpreg: tregister;
begin
paraloc.check_simple_location;
paramanager.allocparaloc(list,paraloc.location);
case paraloc.location^.loc of
LOC_REGISTER,LOC_CREGISTER:
a_loadaddr_ref_reg(list,r,paraloc.location^.register);
LOC_REFERENCE:
begin
reference_reset(ref,paraloc.alignment);
ref.base := paraloc.location^.reference.index;
ref.offset := paraloc.location^.reference.offset;
tmpreg := getintregister(list,OS_ADDR);
a_loadaddr_ref_reg(list,r,tmpreg);
a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
end;
else
internalerror(2002080701);
end;
tmpreg:=getaddressregister(list);
a_loadaddr_ref_reg(list,r,tmpreg);
a_load_reg_cgpara(list,OS_ADDR,tmpreg,paraloc);
end;
@ -1175,6 +1260,7 @@ unit cgcpu;
begin
if a=0 then
begin
swapped:=false;
{ swap parameters? }
case cmp_op of
OC_GT:
@ -1195,10 +1281,8 @@ unit cgcpu;
OC_A:
begin
swapped:=true;
cmp_op:=OC_A;
cmp_op:=OC_B;
end;
else
internalerror(2013113006);
end;
if swapped then
@ -1229,6 +1313,7 @@ unit cgcpu;
tmpreg : tregister;
i : byte;
begin
swapped:=false;
{ swap parameters? }
case cmp_op of
OC_GT:
@ -1249,10 +1334,8 @@ unit cgcpu;
OC_A:
begin
swapped:=true;
cmp_op:=OC_A;
cmp_op:=OC_B;
end;
else
internalerror(2013113007);
end;
if swapped then
begin

View File

@ -38,7 +38,6 @@ unit cpupara;
function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
procedure getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
@ -68,45 +67,6 @@ unit cpupara;
end;
procedure tavrparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
psym: tparavarsym;
pdef: tdef;
begin
if nr<1 then
internalerror(2002070801);
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=getpointerdef(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=std_param_align;
cgpara.def:=pdef;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
size:=def_cgsize(pdef);
def:=pdef;
{ the four first parameters are passed into registers }
if nr<=9 then
begin
loc:=LOC_REGISTER;
register:=newreg(R_INTREGISTER,RS_R25-(nr-1)*2,R_SUBWHOLE);
end
else
begin
{ the other parameters are passed on the stack }
loc:=LOC_REFERENCE;
reference.index:=NR_STACK_POINTER_REG;
reference.offset:=(nr-10)*2;
end;
end;
end;
function getparaloc(calloption : tproccalloption; p : tdef) : tcgloc;
begin
{ Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER