mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 15:47:53 +02:00
* some fixes for parameter handling on avr
git-svn-id: trunk@26425 -
This commit is contained in:
parent
19d71655eb
commit
cb48c2afca
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user