mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-15 08:39:30 +02:00
m68k: for cdecls with the SVR4 ABI return results both in A0 and D0
git-svn-id: trunk@36588 -
This commit is contained in:
parent
bc53a908c9
commit
b481129f4e
compiler/m68k
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user