m68k: for cdecls with the SVR4 ABI return results both in A0 and D0

git-svn-id: trunk@36588 -
This commit is contained in:
Károly Balogh 2017-06-23 19:21:20 +00:00
parent bc53a908c9
commit b481129f4e
4 changed files with 62 additions and 9 deletions

View File

@ -1876,11 +1876,11 @@ unit cgcpu;
{ point to nowhere! }
{ Instead of doing a slow copy of the return address while trying }
{ to feed it to the RTS instruction, load the PC to A0 (scratch reg) }
{ then free up the stack allocated for paras, then use a JMP (A0) to }
{ to feed it to the RTS instruction, load the PC to A1 (scratch reg) }
{ then free up the stack allocated for paras, then use a JMP (A1) to }
{ return to the caller with the paras freed. (KB) }
hregister:=NR_A0;
hregister:=NR_A1;
cg.a_reg_alloc(list,hregister);
reference_reset_base(ref,NR_STACK_POINTER_REG,0,4,[]);
list.concat(taicpu.op_ref_reg(A_MOVE,S_L,ref,hregister));

View File

@ -279,8 +279,8 @@ unit cpubase;
{ TODO: FIX ME!!! pic offset reg conflicts with frame pointer?}
NR_PIC_OFFSET_REG = NR_A5;
{ Return address for DWARF }
{ TODO: just a guess!}
NR_RETURN_ADDRESS_REG = NR_A0;
RS_RETURN_ADDRESS_REG = RS_A0;
{ Results are returned in this register (32-bit values) }
NR_FUNCTION_RETURN_REG = NR_D0;
RS_FUNCTION_RETURN_REG = RS_D0;

View File

@ -168,8 +168,9 @@ unit cpupara;
function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
var
paraloc : pcgparalocation;
paraloc : pcgparalocation;
retcgsize : tcgsize;
retregtype : tregistertype;
begin
if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
exit;
@ -223,10 +224,39 @@ unit cpupara;
paraloc^.loc:=LOC_REGISTER;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
if side=callerside then
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
{ GCC (and SVR4 in general maybe?) requires a pointer result on the A0
register, as well as D0. So we init the result to be A0, then copy
it also to D0 in hlcg.gen_load_loc_function_result. This is not pretty,
but we don't really have an architecture for funcretlocs in two
separate locations.
We also have to figure out a better switch for this, because this is
now compiler and platform specific... (KB) }
if (tprocdef(p).proccalloption in [pocall_cdecl,pocall_cppdecl]) and
(target_info.system in [system_m68k_linux]) and
assigned(result.def) and
(result.def.typ in [stringdef,pointerdef,classrefdef,objectdef,
procvardef,procdef,arraydef,formaldef]) then
retregtype:=R_ADDRESSREGISTER
else
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
retregtype:=R_INTREGISTER;
if retregtype = R_ADDRESSREGISTER then
begin
if side=callerside then
paraloc^.register:=newreg(R_ADDRESSREGISTER,RS_RETURN_ADDRESS_REG,cgsize2subreg(R_ADDRESSREGISTER,retcgsize))
else
paraloc^.register:=newreg(R_ADDRESSREGISTER,RS_RETURN_ADDRESS_REG,cgsize2subreg(R_ADDRESSREGISTER,retcgsize));
end
else
begin
if side=callerside then
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
else
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
end;
end;
end;
end;

View File

@ -43,6 +43,8 @@ interface
procedure a_bit_set_reg_ref(list: TAsmList; doset: boolean; fromsize, tosize: tdef; bitnumber: tregister; const ref: treference); override;
procedure a_bit_set_const_ref(list: TAsmList; doset: boolean; destsize: tdef; bitnumber: tcgint; const ref: treference); override;
procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
procedure gen_load_loc_function_result(list: TAsmList; vardef: tdef; const l: tlocation);override;
end;
procedure create_hlcodegen;
@ -55,7 +57,8 @@ implementation
aasmtai, aasmcpu,
defutil,
hlcgobj,
cpuinfo, cgobj, cpubase, cgcpu;
cpuinfo, cgobj, cpubase, cgcpu,
parabase, procinfo;
@ -241,6 +244,26 @@ implementation
end;
procedure thlcgcpu.gen_load_loc_function_result(list: TAsmList; vardef: tdef; const l: tlocation);
var
cgpara: tcgpara;
begin
inherited;
{ Kludge:
GCC (and SVR4 in general maybe?) requires a pointer
result on the A0 register, as well as D0. So when we
have a result in A0, also copy it to D0. See the decision
making code in tcpuparamanager.get_funcretloc (KB) }
cgpara:=current_procinfo.procdef.funcretloc[calleeside];
if ((cgpara.location^.loc = LOC_REGISTER) and
(isaddressregister(cgpara.location^.register))) then
begin
cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_RETURN_ADDRESS_REG,NR_FUNCTION_RESULT_REG);
end;
end;
procedure create_hlcodegen;
begin
hlcg:=thlcgcpu.create;