cleaned up g_proc_exit, optimized generated code and also added some comments about possible ABI variations. the changes also fix two tests on my system related to cdecl procedures

git-svn-id: trunk@26918 -
This commit is contained in:
Károly Balogh 2014-03-01 23:52:00 +00:00
parent 65fe978b71
commit 8730b1bf45

View File

@ -1670,65 +1670,57 @@ unit cgcpu;
end; end;
end; end;
{ procedure tcg68k.g_restore_frame_pointer(list : TAsmList);
var
r:Tregister;
begin
r:=NR_FRAME_POINTER_REG;
list.concat(taicpu.op_reg(A_UNLK,S_NO,r));
end;
}
procedure tcg68k.g_proc_exit(list : TAsmList; parasize: longint; nostackframe: boolean); procedure tcg68k.g_proc_exit(list : TAsmList; parasize: longint; nostackframe: boolean);
var var
r,hregister : TRegister; r,hregister : TRegister;
localsize: tcgint;
spr : TRegister; spr : TRegister;
fpr : TRegister; fpr : TRegister;
ref : TReference; ref : TReference;
begin begin
if not nostackframe then if not nostackframe then
begin begin
localsize := current_procinfo.calc_stackframe_size;
list.concat(taicpu.op_reg(A_UNLK,S_NO,NR_FRAME_POINTER_REG)); list.concat(taicpu.op_reg(A_UNLK,S_NO,NR_FRAME_POINTER_REG));
parasize := parasize - target_info.first_parm_offset; { i'm still not 100% confident that this is parasize := parasize - target_info.first_parm_offset; { i'm still not 100% confident that this is
correct here, but at least it looks less correct here, but at least it looks less
hacky, and makes some sense (KB) } hacky, and makes some sense (KB) }
if (parasize<>0) then
{ if parasize is less than zero here, we probably have a cdecl function.
According to the info here: http://www.makestuff.eu/wordpress/gcc-68000-abi/
68k GCC uses two different methods to free the stack, depending if the target
architecture supports RTD or not, and one does callee side, the other does
caller side free, which looks like a PITA to support. We have to figure this
out later. More info welcomed. (KB) }
if (parasize > 0) then
begin begin
{ only 68020+ supports RTD, so this needs another code path
for 68000 and Coldfire (KB) }
{ TODO: 68020+ only code generation, without fallback}
if current_settings.cputype=cpu_mc68020 then if current_settings.cputype=cpu_mc68020 then
list.concat(taicpu.op_const(A_RTD,S_NO,parasize)) list.concat(taicpu.op_const(A_RTD,S_NO,parasize))
else else
begin begin
{ We must pull the PC Counter from the stack, before } { We must pull the PC Counter from the stack, before }
{ restoring the stack pointer, otherwise the PC would } { restoring the stack pointer, otherwise the PC would }
{ point to nowhere! } { point to nowhere! }
{ save the PC counter (pop it from the stack) } { Instead of doing a slow copy of the return address while trying }
{ use A0 for this which is defined as a scratch } { to feed it to the RTS instruction, load the PC to A0 (scratch reg) }
{ register } { then free up the stack allocated for paras, then use a JMP (A0) to }
{ return to the caller with the paras freed. (KB) }
hregister:=NR_A0; hregister:=NR_A0;
cg.a_reg_alloc(list,hregister); cg.a_reg_alloc(list,hregister);
reference_reset_base(ref,NR_STACK_POINTER_REG,0,4); reference_reset_base(ref,NR_STACK_POINTER_REG,0,4);
ref.direction:=dir_inc; ref.direction:=dir_inc;
list.concat(taicpu.op_ref_reg(A_MOVE,S_L,ref,hregister)); list.concat(taicpu.op_ref_reg(A_MOVE,S_L,ref,hregister));
{ can we do a quick addition ... }
r:=NR_SP; r:=NR_SP;
{ can we do a quick addition ... }
if (parasize > 0) and (parasize < 9) then if (parasize > 0) and (parasize < 9) then
list.concat(taicpu.op_const_reg(A_ADDQ,S_L,parasize,r)) list.concat(taicpu.op_const_reg(A_ADDQ,S_L,parasize,r))
else { nope ... } else { nope ... }
list.concat(taicpu.op_const_reg(A_ADD,S_L,parasize,r)); list.concat(taicpu.op_const_reg(A_ADD,S_L,parasize,r));
{ restore the PC counter (push it on the stack) } reference_reset_base(ref,hregister,0,4);
reference_reset_base(ref,NR_STACK_POINTER_REG,0,4); list.concat(taicpu.op_ref(A_JMP,S_NO,ref));
ref.direction:=dir_dec;
cg.a_reg_alloc(list,hregister);
list.concat(taicpu.op_reg_ref(A_MOVE,S_L,hregister,ref));
list.concat(taicpu.op_none(A_RTS,S_NO));
end; end;
end end
else else
@ -1739,9 +1731,9 @@ unit cgcpu;
list.concat(taicpu.op_none(A_RTS,S_NO)); list.concat(taicpu.op_none(A_RTS,S_NO));
end; end;
// writeln('g_proc_exit');
{ Routines with the poclearstack flag set use only a ret. { Routines with the poclearstack flag set use only a ret.
also routines with parasize=0 } also routines with parasize=0 }
{ TODO: figure out if these are still relevant to us (KB) }
(* (*
if current_procinfo.procdef.proccalloption in clearstack_pocalls then if current_procinfo.procdef.proccalloption in clearstack_pocalls then
begin begin
@ -1756,40 +1748,6 @@ unit cgcpu;
list.concat(taicpu.op_none(A_RTS,S_NO)); list.concat(taicpu.op_none(A_RTS,S_NO));
end end
else else
begin
{ return with immediate size possible here
signed!
RTD is not supported on the coldfire }
if (current_settings.cputype=cpu_MC68020) and (parasize<$7FFF) then
list.concat(taicpu.op_const(A_RTD,S_NO,parasize))
{ manually restore the stack }
else
begin
{ We must pull the PC Counter from the stack, before }
{ restoring the stack pointer, otherwise the PC would }
{ point to nowhere! }
{ save the PC counter (pop it from the stack) }
hregister:=NR_A3;
cg.a_reg_alloc(list,hregister);
reference_reset_base(ref,NR_STACK_POINTER_REG,0);
ref.direction:=dir_inc;
list.concat(taicpu.op_ref_reg(A_MOVE,S_L,ref,hregister));
{ can we do a quick addition ... }
r:=NR_SP;
if (parasize > 0) and (parasize < 9) then
list.concat(taicpu.op_const_reg(A_ADDQ,S_L,parasize,r))
else { nope ... }
list.concat(taicpu.op_const_reg(A_ADD,S_L,parasize,r));
{ restore the PC counter (push it on the stack) }
reference_reset_base(ref,NR_STACK_POINTER_REG,0);
ref.direction:=dir_dec;
cg.a_reg_alloc(list,hregister);
list.concat(taicpu.op_reg_ref(A_MOVE,S_L,hregister,ref));
list.concat(taicpu.op_none(A_RTS,S_NO));
end;
end;
*) *)
end; end;