mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 17:47:56 +02:00
* m68k: Fixed parameter passing to conform to ABI:
* records are passed by value * records with size of 1,2 or 4 are returned in registers * parameters with size<4 are justified on the stack according to big-endian target Now everything except floating-point parameters is compatible with C code compiled with "-malign-int -mrtd". Compatibility with "-mno-align-int" is achievable by changing target_info.maxCrecordalign to 2, but doings so causes a lot more troubles because RTL (incorrectly) assumes that records declared with {$PACKRECORDS C} are aligned to pointer size. + Reuse parameter locations. Since everything is passed on stack, it reduces code size quite a bit. - tm68kparamanager.getintparaloc removed, generic implementation has been tested and works as expected. git-svn-id: trunk@28083 -
This commit is contained in:
parent
140ce2a880
commit
acd3ea8750
@ -815,17 +815,14 @@ unit cgcpu;
|
||||
|
||||
procedure tcg68k.a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
|
||||
var
|
||||
href : treference;
|
||||
size : tcgsize;
|
||||
href : treference;
|
||||
begin
|
||||
href := ref;
|
||||
fixref(list,href);
|
||||
if tcgsize2size[fromsize]<tcgsize2size[tosize] then
|
||||
size:=fromsize
|
||||
else
|
||||
size:=tosize;
|
||||
a_load_reg_reg(list,fromsize,tosize,register,register);
|
||||
{ move to destination reference }
|
||||
list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[size],register,href));
|
||||
list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[tosize],register,href));
|
||||
end;
|
||||
|
||||
|
||||
@ -1506,7 +1503,6 @@ unit cgcpu;
|
||||
hp2 : treference;
|
||||
hl : tasmlabel;
|
||||
srcref,dstref : treference;
|
||||
alignsize : tcgsize;
|
||||
orglen : tcgint;
|
||||
begin
|
||||
hregister := getintregister(list,OS_INT);
|
||||
@ -1530,14 +1526,7 @@ unit cgcpu;
|
||||
{ move a word }
|
||||
if len>1 then
|
||||
begin
|
||||
if (orglen<sizeof(aint)) and
|
||||
(source.base=NR_FRAME_POINTER_REG) and
|
||||
(source.offset>0) then
|
||||
{ copy of param to local location }
|
||||
alignsize:=OS_INT
|
||||
else
|
||||
alignsize:=OS_16;
|
||||
a_load_ref_reg(list,alignsize,alignsize,srcref,hregister);
|
||||
a_load_ref_reg(list,OS_16,OS_16,srcref,hregister);
|
||||
a_load_reg_ref(list,OS_16,OS_16,hregister,dstref);
|
||||
inc(srcref.offset,2);
|
||||
inc(dstref.offset,2);
|
||||
@ -1546,14 +1535,7 @@ unit cgcpu;
|
||||
{ move a single byte }
|
||||
if len>0 then
|
||||
begin
|
||||
if (orglen<sizeof(aint)) and
|
||||
(source.base=NR_FRAME_POINTER_REG) and
|
||||
(source.offset>0) then
|
||||
{ copy of param to local location }
|
||||
alignsize:=OS_INT
|
||||
else
|
||||
alignsize:=OS_8;
|
||||
a_load_ref_reg(list,alignsize,alignsize,srcref,hregister);
|
||||
a_load_ref_reg(list,OS_8,OS_8,srcref,hregister);
|
||||
a_load_reg_ref(list,OS_8,OS_8,hregister,dstref);
|
||||
end
|
||||
end
|
||||
|
@ -39,7 +39,8 @@ unit cpupara;
|
||||
rtl are used.
|
||||
}
|
||||
tm68kparamanager = class(tparamanager)
|
||||
procedure getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
|
||||
function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
|
||||
function param_use_paraloc(const cgpara:tcgpara):boolean;override;
|
||||
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
|
||||
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
|
||||
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
|
||||
@ -80,35 +81,24 @@ unit cpupara;
|
||||
end;
|
||||
|
||||
|
||||
procedure tm68kparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
|
||||
function tm68kparamanager.param_use_paraloc(const cgpara:tcgpara):boolean;
|
||||
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
|
||||
{ warning : THIS ONLY WORKS WITH INTERNAL ROUTINES,
|
||||
WHICH MUST ALWAYS PASS 4-BYTE PARAMETERS!!
|
||||
}
|
||||
loc:=LOC_REFERENCE;
|
||||
reference.index:=NR_STACK_POINTER_REG;
|
||||
reference.offset:=target_info.first_parm_offset+nr*4;
|
||||
size:=def_cgsize(pdef);
|
||||
def:=pdef;
|
||||
end;
|
||||
if not assigned(cgpara.location) then
|
||||
internalerror(200410102);
|
||||
result:=true;
|
||||
{ All locations are LOC_REFERENCE }
|
||||
paraloc:=cgpara.location;
|
||||
while assigned(paraloc) do
|
||||
begin
|
||||
if (paraloc^.loc<>LOC_REFERENCE) then
|
||||
begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
paraloc:=paraloc^.next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
@ -127,7 +117,7 @@ unit cpupara;
|
||||
formaldef :
|
||||
result:=true;
|
||||
recorddef:
|
||||
result:=true;
|
||||
result:=false;
|
||||
arraydef:
|
||||
result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
|
||||
is_open_array(def) or
|
||||
@ -140,7 +130,8 @@ unit cpupara;
|
||||
stringdef :
|
||||
result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
|
||||
procvardef :
|
||||
result:=po_methodpointer in tprocvardef(def).procoptions;
|
||||
{ Handling of methods must match that of records }
|
||||
result:=false;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -151,6 +142,24 @@ unit cpupara;
|
||||
curfloatreg:=RS_FP0;
|
||||
end;
|
||||
|
||||
|
||||
function tm68kparamanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
|
||||
begin
|
||||
if handle_common_ret_in_param(def,pd,result) then
|
||||
exit;
|
||||
|
||||
case def.typ of
|
||||
recorddef:
|
||||
if def.size in [1,2,4] then
|
||||
begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
result:=inherited ret_in_param(def,pd);
|
||||
end;
|
||||
|
||||
|
||||
function tm68kparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
|
||||
var
|
||||
paraloc : pcgparalocation;
|
||||
@ -286,7 +295,7 @@ unit cpupara;
|
||||
|
||||
paracgsize:=def_cgsize(paradef);
|
||||
{ for things like formaldef }
|
||||
if (paracgsize=OS_NO) then
|
||||
if (paracgsize=OS_NO) and (paradef.typ<>recorddef) then
|
||||
begin
|
||||
paracgsize:=OS_ADDR;
|
||||
paralen := tcgsize2size[OS_ADDR];
|
||||
@ -314,17 +323,21 @@ unit cpupara;
|
||||
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
paraloc^.def:=get_paraloc_def(paradef,paralen,firstparaloc);
|
||||
if paradef.typ<>orddef then
|
||||
paracgsize:=int_cgsize(paralen);
|
||||
if paracgsize=OS_NO then
|
||||
paraloc^.size:=OS_INT
|
||||
if (paradef.typ=floatdef) then
|
||||
paraloc^.size:=int_float_cgsize(paralen)
|
||||
else
|
||||
paraloc^.size:=paracgsize;
|
||||
paraloc^.size:=int_cgsize(paralen);
|
||||
|
||||
paraloc^.reference.offset:=stack_offset;
|
||||
if (side = callerside) then
|
||||
paraloc^.reference.index:=NR_STACK_POINTER_REG
|
||||
else
|
||||
paraloc^.reference.index:=NR_FRAME_POINTER_REG;
|
||||
paraloc^.reference.offset:=stack_offset;
|
||||
begin
|
||||
paraloc^.reference.index:=NR_FRAME_POINTER_REG;
|
||||
{ M68K is a big-endian target }
|
||||
if (paralen<tcgsize2size[OS_INT]) then
|
||||
inc(paraloc^.reference.offset,4-paralen);
|
||||
end;
|
||||
inc(stack_offset,align(paralen,4));
|
||||
paralen := 0;
|
||||
|
||||
|
@ -91,9 +91,7 @@ procedure FillChar(var x; count : longint; value : byte); assembler;
|
||||
asm
|
||||
move.l x, a0 { destination }
|
||||
move.l count, d1 { number of bytes to fill }
|
||||
{ FIXME: this should be move.b, but everything is pushed as long on
|
||||
the stack ATM (KB) }
|
||||
move.l value, d0 { fill data }
|
||||
move.b value, d0 { fill data }
|
||||
tst.l d1 { anything to fill at all? }
|
||||
ble @LMEMSET5
|
||||
{$ifdef CPUM68K_HAS_DBRA}
|
||||
@ -321,9 +319,7 @@ procedure FillWord(var x; count : longint; value : word); assembler;
|
||||
asm
|
||||
move.l x, a0 { destination }
|
||||
move.l count, d1 { number of bytes to fill }
|
||||
{ FIXME: this should be move.w, but everything is pushed as long on
|
||||
the stack ATM (KB) }
|
||||
move.l value, d0 { fill data }
|
||||
move.w value, d0 { fill data }
|
||||
tst.l d1 { anything to fill at all? }
|
||||
ble @LMEMSET3
|
||||
bra @LMEMSET21
|
||||
|
Loading…
Reference in New Issue
Block a user