mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 04:39:38 +02:00
* assembler procedures now again get a stackframe if they have local
variables. No space is reserved for a function result however. Also, the register parameters aren't automatically saved on the stack anymore in assembler procedures.
This commit is contained in:
parent
fd1056c621
commit
56132c1a9c
@ -1357,27 +1357,37 @@ function returns in a register and the caller receives it in an other one}
|
||||
{ for now the pointer to the result can't be a register }
|
||||
if not(paramanager.ret_in_reg(aktprocdef.rettype.def,aktprocdef.proccalloption)) then
|
||||
begin
|
||||
paraloc:=paramanager.getfuncretparaloc(aktprocdef);
|
||||
reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
|
||||
case paraloc.loc of
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
if not(paraloc.size in [OS_64,OS_S64]) then
|
||||
cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href)
|
||||
else
|
||||
cg64.a_load64_reg_ref(list,paraloc.register64,href);
|
||||
LOC_CFPUREGISTER,
|
||||
LOC_FPUREGISTER:
|
||||
cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href);
|
||||
LOC_CMMREGISTER,
|
||||
LOC_MMREGISTER:
|
||||
cg.a_loadmm_reg_ref(list,paraloc.register,href);
|
||||
end;
|
||||
{$ifdef powerpc}
|
||||
{ no stack space is allocated in this case -> can't save the result reg on the stack }
|
||||
if not(po_assembler in aktprocdef.procoptions) then
|
||||
{$endif powerpc}
|
||||
begin
|
||||
paraloc:=paramanager.getfuncretparaloc(aktprocdef);
|
||||
reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
|
||||
case paraloc.loc of
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
if not(paraloc.size in [OS_64,OS_S64]) then
|
||||
cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href)
|
||||
else
|
||||
cg64.a_load64_reg_ref(list,paraloc.register64,href);
|
||||
LOC_CFPUREGISTER,
|
||||
LOC_FPUREGISTER:
|
||||
cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href);
|
||||
LOC_CMMREGISTER,
|
||||
LOC_MMREGISTER:
|
||||
cg.a_loadmm_reg_ref(list,paraloc.register,href);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ initialize return value }
|
||||
if (aktprocdef.rettype.def.needs_inittable) then
|
||||
begin
|
||||
{$ifdef powerpc}
|
||||
if (po_assembler in aktprocdef.procoptions) then
|
||||
internalerror(200304161);
|
||||
{$endif powerpc}
|
||||
if (cs_implicit_exceptions in aktmoduleswitches) then
|
||||
procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
|
||||
reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
|
||||
@ -1413,47 +1423,50 @@ function returns in a register and the caller receives it in an other one}
|
||||
begin
|
||||
aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
|
||||
|
||||
{ move register parameters which aren't regable into memory }
|
||||
{ we do this after init_paras because it saves some code in init_paras if parameters are in register }
|
||||
{ instead in memory }
|
||||
hp:=tparaitem(procinfo.procdef.para.first);
|
||||
while assigned(hp) do
|
||||
if not (po_assembler in aktprocdef.procoptions) then
|
||||
begin
|
||||
if Tvarsym(hp.parasym).reg.enum>lastreg then
|
||||
internalerror(200301081);
|
||||
if (tvarsym(hp.parasym).reg.enum<>R_NO) then
|
||||
case hp.paraloc.loc of
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
{ move register parameters which aren't regable into memory }
|
||||
{ we do this after init_paras because it saves some code in init_paras if parameters are in register }
|
||||
{ instead in memory }
|
||||
hp:=tparaitem(procinfo.procdef.para.first);
|
||||
while assigned(hp) do
|
||||
begin
|
||||
if Tvarsym(hp.parasym).reg.enum>lastreg then
|
||||
internalerror(200301081);
|
||||
if (tvarsym(hp.parasym).reg.enum<>R_NO) then
|
||||
case hp.paraloc.loc of
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
// if not(hp.paraloc.size in [OS_S64,OS_64]) then
|
||||
cg.a_load_reg_reg(list,hp.paraloc.size,OS_32,hp.paraloc.register,tvarsym(hp.parasym).reg);
|
||||
cg.a_load_reg_reg(list,hp.paraloc.size,OS_32,hp.paraloc.register,tvarsym(hp.parasym).reg);
|
||||
// else
|
||||
// cg64.a_load64_reg_reg(list,hp.paraloc.register64,tvarsym(hp.parasym).reg);
|
||||
LOC_CFPUREGISTER,
|
||||
LOC_FPUREGISTER:
|
||||
cg.a_loadfpu_reg_reg(list,hp.paraloc.register,tvarsym(hp.parasym).reg);
|
||||
end
|
||||
else if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER,
|
||||
LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER]) and
|
||||
(tvarsym(hp.parasym).reg.enum=R_NO) then
|
||||
begin
|
||||
reference_reset_base(href,procinfo.framepointer,tvarsym(hp.parasym).address+
|
||||
tvarsym(hp.parasym).owner.address_fixup);
|
||||
case hp.paraloc.loc of
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
if not(hp.paraloc.size in [OS_S64,OS_64]) then
|
||||
cg.a_load_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href)
|
||||
LOC_CFPUREGISTER,
|
||||
LOC_FPUREGISTER:
|
||||
cg.a_loadfpu_reg_reg(list,hp.paraloc.register,tvarsym(hp.parasym).reg);
|
||||
end
|
||||
else if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER,
|
||||
LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER]) and
|
||||
(tvarsym(hp.parasym).reg.enum=R_NO) then
|
||||
begin
|
||||
reference_reset_base(href,procinfo.framepointer,tvarsym(hp.parasym).address+
|
||||
tvarsym(hp.parasym).owner.address_fixup);
|
||||
case hp.paraloc.loc of
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
if not(hp.paraloc.size in [OS_S64,OS_64]) then
|
||||
cg.a_load_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href)
|
||||
else
|
||||
cg64.a_load64_reg_ref(list,hp.paraloc.register64,href);
|
||||
LOC_FPUREGISTER,
|
||||
LOC_CFPUREGISTER:
|
||||
cg.a_loadfpu_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href);
|
||||
else
|
||||
cg64.a_load64_reg_ref(list,hp.paraloc.register64,href);
|
||||
LOC_FPUREGISTER,
|
||||
LOC_CFPUREGISTER:
|
||||
cg.a_loadfpu_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href);
|
||||
else
|
||||
internalerror(2002081302);
|
||||
internalerror(2002081302);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
hp:=tparaitem(hp.next);
|
||||
hp:=tparaitem(hp.next);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -2005,7 +2018,13 @@ function returns in a register and the caller receives it in an other one}
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.83 2003-04-06 21:11:23 olle
|
||||
Revision 1.84 2003-04-16 09:26:55 jonas
|
||||
* assembler procedures now again get a stackframe if they have local
|
||||
variables. No space is reserved for a function result however.
|
||||
Also, the register parameters aren't automatically saved on the stack
|
||||
anymore in assembler procedures.
|
||||
|
||||
Revision 1.83 2003/04/06 21:11:23 olle
|
||||
* changed newasmsymbol to newasmsymboldata for data symbols
|
||||
|
||||
Revision 1.82 2003/03/30 20:59:07 peter
|
||||
|
@ -913,11 +913,6 @@ const
|
||||
procedure tcgppc.g_stackframe_entry(list : taasmoutput;localsize : longint);
|
||||
|
||||
begin
|
||||
{ if you program in assembler, you have to take care of everything }
|
||||
{ yourself. Some things just don't work otherwise (e.g. the linux }
|
||||
{ syscall code) (JM) }
|
||||
if (po_assembler in aktprocdef.procoptions) then
|
||||
exit;
|
||||
case target_info.system of
|
||||
system_powerpc_macos:
|
||||
g_stackframe_entry_mac(list,localsize);
|
||||
@ -931,14 +926,6 @@ const
|
||||
procedure tcgppc.g_return_from_proc(list : taasmoutput;parasize : aword);
|
||||
|
||||
begin
|
||||
{ if you program in assembler, you have to take care of everything }
|
||||
{ yourself. Some things just don't work otherwise (e.g. the linux }
|
||||
{ syscall code) (JM) }
|
||||
if (po_assembler in aktprocdef.procoptions) then
|
||||
begin
|
||||
list.concat(taicpu.op_none(A_BLR));
|
||||
exit;
|
||||
end;
|
||||
case target_info.system of
|
||||
system_powerpc_macos:
|
||||
g_return_from_proc_mac(list,parasize);
|
||||
@ -985,38 +972,41 @@ const
|
||||
end;
|
||||
|
||||
usesfpr:=false;
|
||||
for regcounter.enum:=R_F14 to R_F31 do
|
||||
if regcounter.enum in rg.usedbyproc then
|
||||
begin
|
||||
usesfpr:=true;
|
||||
firstregfpu:=regcounter;
|
||||
break;
|
||||
end;
|
||||
if not (po_assembler in aktprocdef.procoptions) then
|
||||
for regcounter.enum:=R_F14 to R_F31 do
|
||||
if regcounter.enum in rg.usedbyproc then
|
||||
begin
|
||||
usesfpr:= true;
|
||||
firstregfpu:=regcounter;
|
||||
break;
|
||||
end;
|
||||
|
||||
usesgpr:=false;
|
||||
for regcounter2:=RS_R14 to RS_R31 do
|
||||
begin
|
||||
if regcounter2 in rg.usedintbyproc then
|
||||
begin
|
||||
usesgpr:=true;
|
||||
firstreggpr.enum := R_INTREGISTER;
|
||||
firstreggpr.number := regcounter2 shl 8;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if not (po_assembler in aktprocdef.procoptions) then
|
||||
for regcounter2:=RS_R14 to RS_R31 do
|
||||
begin
|
||||
if regcounter2 in rg.usedintbyproc then
|
||||
begin
|
||||
usesgpr:=true;
|
||||
firstreggpr.enum := R_INTREGISTER;
|
||||
firstreggpr.number := regcounter2 shl 8;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ save link register? }
|
||||
if (procinfo.flags and pi_do_call)<>0 then
|
||||
begin
|
||||
{ save return address... }
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_R0;
|
||||
list.concat(taicpu.op_reg(A_MFLR,r));
|
||||
{ ... in caller's rframe }
|
||||
reference_reset_base(href,rsp,4);
|
||||
list.concat(taicpu.op_reg_ref(A_STW,r,href));
|
||||
a_reg_dealloc(list,r);
|
||||
end;
|
||||
if not (po_assembler in aktprocdef.procoptions) then
|
||||
if (procinfo.flags and pi_do_call)<>0 then
|
||||
begin
|
||||
{ save return address... }
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_R0;
|
||||
list.concat(taicpu.op_reg(A_MFLR,r));
|
||||
{ ... in caller's rframe }
|
||||
reference_reset_base(href,rsp,4);
|
||||
list.concat(taicpu.op_reg_ref(A_STW,r,href));
|
||||
a_reg_dealloc(list,r);
|
||||
end;
|
||||
|
||||
if usesfpr or usesgpr then
|
||||
begin
|
||||
@ -1042,10 +1032,13 @@ const
|
||||
|
||||
tppcprocinfo(procinfo).localsize:=localsize;
|
||||
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_STACK_POINTER_REG;
|
||||
reference_reset_base(href,r,-localsize);
|
||||
a_load_store(list,A_STWU,r,href);
|
||||
if (localsize <> 0) then
|
||||
begin
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_STACK_POINTER_REG;
|
||||
reference_reset_base(href,r,-localsize);
|
||||
a_load_store(list,A_STWU,r,href);
|
||||
end;
|
||||
|
||||
{ no GOT pointer loaded yet }
|
||||
gotgot:=false;
|
||||
@ -1142,25 +1135,27 @@ const
|
||||
{ AltiVec context restore, not yet implemented !!! }
|
||||
|
||||
usesfpr:=false;
|
||||
for regcounter.enum:=R_F14 to R_F31 do
|
||||
if regcounter.enum in rg.usedbyproc then
|
||||
begin
|
||||
usesfpr:=true;
|
||||
firstregfpu:=regcounter;
|
||||
break;
|
||||
end;
|
||||
|
||||
usesgpr:=false;
|
||||
for regcounter2:=RS_R14 to RS_R30 do
|
||||
begin
|
||||
if regcounter2 in rg.usedintbyproc then
|
||||
if not (po_assembler in aktprocdef.procoptions) then
|
||||
for regcounter.enum:=R_F14 to R_F31 do
|
||||
if regcounter.enum in rg.usedbyproc then
|
||||
begin
|
||||
usesgpr:=true;
|
||||
firstreggpr.enum:=R_INTREGISTER;
|
||||
firstreggpr.number:=regcounter2 shl 8;
|
||||
usesfpr:=true;
|
||||
firstregfpu:=regcounter;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
usesgpr:=false;
|
||||
if not (po_assembler in aktprocdef.procoptions) then
|
||||
for regcounter2:=RS_R14 to RS_R30 do
|
||||
begin
|
||||
if regcounter2 in rg.usedintbyproc then
|
||||
begin
|
||||
usesgpr:=true;
|
||||
firstreggpr.enum:=R_INTREGISTER;
|
||||
firstreggpr.number:=regcounter2 shl 8;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ no return (blr) generated yet }
|
||||
genret:=true;
|
||||
@ -1211,16 +1206,17 @@ const
|
||||
r.number:=NR_R1;
|
||||
a_op_const_reg(list,OP_ADD,tppcprocinfo(procinfo).localsize,r);
|
||||
{ load link register? }
|
||||
if (procinfo.flags and pi_do_call)<>0 then
|
||||
begin
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_STACK_POINTER_REG;
|
||||
reference_reset_base(href,r,4);
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_R0;
|
||||
list.concat(taicpu.op_reg_ref(A_LWZ,r,href));
|
||||
list.concat(taicpu.op_reg(A_MTLR,r));
|
||||
end;
|
||||
if not (po_assembler in aktprocdef.procoptions) then
|
||||
if (procinfo.flags and pi_do_call)<>0 then
|
||||
begin
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_STACK_POINTER_REG;
|
||||
reference_reset_base(href,r,4);
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_R0;
|
||||
list.concat(taicpu.op_reg_ref(A_LWZ,r,href));
|
||||
list.concat(taicpu.op_reg(A_MTLR,r));
|
||||
end;
|
||||
list.concat(taicpu.op_none(A_BLR));
|
||||
end;
|
||||
end;
|
||||
@ -1239,25 +1235,27 @@ const
|
||||
|
||||
begin
|
||||
usesfpr:=false;
|
||||
for regcounter.enum:=R_F14 to R_F31 do
|
||||
if regcounter.enum in rg.usedbyproc then
|
||||
begin
|
||||
usesfpr:=true;
|
||||
firstregfpu:=regcounter;
|
||||
break;
|
||||
end;
|
||||
|
||||
usesgpr:=false;
|
||||
for regcounter2:=RS_R13 to RS_R31 do
|
||||
begin
|
||||
if regcounter2 in rg.usedintbyproc then
|
||||
if not (po_assembler in aktprocdef.procoptions) then
|
||||
for regcounter.enum:=R_F14 to R_F31 do
|
||||
if regcounter.enum in rg.usedbyproc then
|
||||
begin
|
||||
usesgpr:=true;
|
||||
firstreggpr.enum:=R_INTREGISTER;
|
||||
firstreggpr.number:=regcounter2 shl 8;
|
||||
usesfpr:=true;
|
||||
firstregfpu:=regcounter;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
usesgpr:=false;
|
||||
if not (po_assembler in aktprocdef.procoptions) then
|
||||
for regcounter2:=RS_R13 to RS_R31 do
|
||||
begin
|
||||
if regcounter2 in rg.usedintbyproc then
|
||||
begin
|
||||
usesgpr:=true;
|
||||
firstreggpr.enum:=R_INTREGISTER;
|
||||
firstreggpr.number:=regcounter2 shl 8;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
offset:= 0;
|
||||
|
||||
{ save floating-point registers }
|
||||
@ -1316,26 +1314,28 @@ const
|
||||
|
||||
begin
|
||||
usesfpr:=false;
|
||||
for regcounter.enum:=R_F14 to R_F31 do
|
||||
if regcounter.enum in rg.usedbyproc then
|
||||
begin
|
||||
usesfpr:=true;
|
||||
firstregfpu:=regcounter;
|
||||
break;
|
||||
end;
|
||||
|
||||
usesgpr:=false;
|
||||
for regcounter2:=RS_R13 to RS_R31 do
|
||||
begin
|
||||
if regcounter2 in rg.usedintbyproc then
|
||||
if not (po_assembler in aktprocdef.procoptions) then
|
||||
for regcounter.enum:=R_F14 to R_F31 do
|
||||
if regcounter.enum in rg.usedbyproc then
|
||||
begin
|
||||
usesgpr:=true;
|
||||
firstreggpr.enum:=R_INTREGISTER;
|
||||
firstreggpr.number:=regcounter2 shl 8;
|
||||
usesfpr:=true;
|
||||
firstregfpu:=regcounter;
|
||||
break;
|
||||
end;
|
||||
inc(r.number,NR_R1-NR_R0);
|
||||
end;
|
||||
|
||||
usesgpr:=false;
|
||||
if not (po_assembler in aktprocdef.procoptions) then
|
||||
for regcounter2:=RS_R13 to RS_R31 do
|
||||
begin
|
||||
if regcounter2 in rg.usedintbyproc then
|
||||
begin
|
||||
usesgpr:=true;
|
||||
firstreggpr.enum:=R_INTREGISTER;
|
||||
firstreggpr.number:=regcounter2 shl 8;
|
||||
break;
|
||||
end;
|
||||
inc(r.number,NR_R1-NR_R0);
|
||||
end;
|
||||
|
||||
offset:= 0;
|
||||
|
||||
@ -1464,11 +1464,14 @@ const
|
||||
localsize:=align(localsize,16);
|
||||
tppcprocinfo(procinfo).localsize:=localsize;
|
||||
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_STACK_POINTER_REG;
|
||||
reference_reset_base(href,r,-localsize);
|
||||
a_load_store(list,A_STWU,r,href);
|
||||
{ this also stores the old stack pointer in the new stack frame }
|
||||
if (localsize <> 0) then
|
||||
begin
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_STACK_POINTER_REG;
|
||||
reference_reset_base(href,r,-localsize);
|
||||
a_load_store(list,A_STWU,r,href);
|
||||
{ this also stores the old stack pointer in the new stack frame }
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure tcgppc.g_return_from_proc_mac(list : taasmoutput;parasize : aword);
|
||||
@ -2212,7 +2215,13 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.77 2003-04-06 16:39:11 jonas
|
||||
Revision 1.78 2003-04-16 09:26:55 jonas
|
||||
* assembler procedures now again get a stackframe if they have local
|
||||
variables. No space is reserved for a function result however.
|
||||
Also, the register parameters aren't automatically saved on the stack
|
||||
anymore in assembler procedures.
|
||||
|
||||
Revision 1.77 2003/04/06 16:39:11 jonas
|
||||
* don't generate entry/exit code for assembler procedures
|
||||
|
||||
Revision 1.76 2003/03/22 18:01:13 jonas
|
||||
|
@ -113,8 +113,15 @@ implementation
|
||||
akttokenpos:=aktprocsym.fileinfo;
|
||||
aktprocdef.funcretsym:=tfuncretsym.create(aktprocsym.name,aktprocdef.rettype);
|
||||
{ insert in local symtable }
|
||||
symtablestack.insert(aktprocdef.funcretsym);
|
||||
symtablestack.insertvardata(aktprocdef.funcretsym);
|
||||
{$ifdef powerpc}
|
||||
{ this requires us to setup a stack frame, which gives problem in the linux syscall helpers (JM) }
|
||||
if not(po_assembler in aktprocdef.procoptions) or
|
||||
not(paramanager.ret_in_reg(aktprocdef.rettype.def,aktprocdef.proccalloption)) then
|
||||
{$endif powerpc}
|
||||
begin
|
||||
symtablestack.insert(aktprocdef.funcretsym);
|
||||
symtablestack.insertvardata(aktprocdef.funcretsym);
|
||||
end;
|
||||
akttokenpos:=storepos;
|
||||
|
||||
(* already done by
|
||||
@ -857,7 +864,13 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.96 2003-04-05 21:09:31 jonas
|
||||
Revision 1.97 2003-04-16 09:26:55 jonas
|
||||
* assembler procedures now again get a stackframe if they have local
|
||||
variables. No space is reserved for a function result however.
|
||||
Also, the register parameters aren't automatically saved on the stack
|
||||
anymore in assembler procedures.
|
||||
|
||||
Revision 1.96 2003/04/05 21:09:31 jonas
|
||||
* several ppc/generic result offset related fixes. The "normal" result
|
||||
offset seems now to be calculated correctly and a lot of duplicate
|
||||
calculations have been removed. Nested functions accessing the parent's
|
||||
|
Loading…
Reference in New Issue
Block a user