mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-05 15:18:32 +02:00
* fix stack parameter handling for arm thumb
* fix entry/exit code generation for arm thumb git-svn-id: trunk@24197 -
This commit is contained in:
parent
f9ef8e90da
commit
7ba197a221
@ -3383,15 +3383,12 @@ unit cgcpu;
|
||||
r7offset,
|
||||
stackmisalignment : pint;
|
||||
postfix: toppostfix;
|
||||
registerarea,
|
||||
imm1, imm2: DWord;
|
||||
stack_parameters: Boolean;
|
||||
begin
|
||||
stack_parameters:=current_procinfo.procdef.stack_tainting_parameter(calleeside);
|
||||
LocalSize:=align(LocalSize,4);
|
||||
if localsize>tarmprocinfo(current_procinfo).stackframesize then
|
||||
begin
|
||||
writeln(localsize);
|
||||
writeln(tarmprocinfo(current_procinfo).stackframesize);
|
||||
internalerror(2013040101);
|
||||
end;
|
||||
{ call instruction does not put anything on the stack }
|
||||
stackmisalignment:=0;
|
||||
if not(nostackframe) then
|
||||
@ -3418,32 +3415,57 @@ unit cgcpu;
|
||||
if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
|
||||
regs:=regs+[RS_R7,RS_R14]
|
||||
else
|
||||
if (regs<>[]) or (pi_do_call in current_procinfo.flags) then
|
||||
include(regs,RS_R14);
|
||||
// if (regs<>[]) or (pi_do_call in current_procinfo.flags) then
|
||||
include(regs,RS_R14);
|
||||
|
||||
{ safely estimate stack size }
|
||||
if localsize+current_settings.alignment.localalignmax>508 then
|
||||
include(regs,RS_R4);
|
||||
if localsize+current_settings.alignment.localalignmax+4>508 then
|
||||
begin
|
||||
include(rg[R_INTREGISTER].used_in_proc,RS_R4);
|
||||
include(regs,RS_R4);
|
||||
end;
|
||||
|
||||
registerarea:=0;
|
||||
if regs<>[] then
|
||||
begin
|
||||
for r:=RS_R0 to RS_R15 do
|
||||
if r in regs then
|
||||
inc(stackmisalignment,4);
|
||||
inc(registerarea,4);
|
||||
list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,regs));
|
||||
end;
|
||||
|
||||
stackmisalignment:=stackmisalignment mod current_settings.alignment.localalignmax;
|
||||
if (LocalSize<>0) or
|
||||
stackmisalignment:=registerarea mod current_settings.alignment.localalignmax;
|
||||
|
||||
if stack_parameters or (LocalSize<>0) or
|
||||
((stackmisalignment<>0) and
|
||||
((pi_do_call in current_procinfo.flags) or
|
||||
(po_assembler in current_procinfo.procdef.procoptions))) then
|
||||
begin
|
||||
localsize:=align(localsize+stackmisalignment,current_settings.alignment.localalignmax)-stackmisalignment;
|
||||
{ do we access stack parameters?
|
||||
if yes, the previously estimated stacksize must be used }
|
||||
if stack_parameters then
|
||||
begin
|
||||
if localsize>tarmprocinfo(current_procinfo).stackframesize then
|
||||
begin
|
||||
writeln(localsize);
|
||||
writeln(tarmprocinfo(current_procinfo).stackframesize);
|
||||
internalerror(2013040601);
|
||||
end
|
||||
else
|
||||
localsize:=tarmprocinfo(current_procinfo).stackframesize-registerarea;
|
||||
end
|
||||
else
|
||||
localsize:=align(localsize+stackmisalignment,current_settings.alignment.localalignmax)-stackmisalignment;
|
||||
|
||||
if localsize<508 then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
|
||||
end
|
||||
else if localsize<=1016 then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,508));
|
||||
list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize-508));
|
||||
end
|
||||
else
|
||||
begin
|
||||
a_load_const_reg(list,OS_ADDR,-localsize,NR_R4);
|
||||
@ -3485,7 +3507,7 @@ unit cgcpu;
|
||||
include(regs,RS_R15);
|
||||
|
||||
if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
|
||||
regs:=regs+[getsupreg(current_procinfo.framepointer)];
|
||||
include(regs,getsupreg(current_procinfo.framepointer));
|
||||
|
||||
for r:=RS_R0 to RS_R15 do
|
||||
if r in regs then
|
||||
@ -3501,19 +3523,20 @@ unit cgcpu;
|
||||
((pi_do_call in current_procinfo.flags) or
|
||||
(po_assembler in current_procinfo.procdef.procoptions))) then
|
||||
begin
|
||||
if is_shifter_const(LocalSize,shift) then
|
||||
if LocalSize=0 then
|
||||
else if LocalSize<=508 then
|
||||
list.concat(taicpu.op_reg_reg_const(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize))
|
||||
else if split_into_shifter_const(localsize, imm1, imm2) then
|
||||
else if LocalSize<=1016 then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_reg_const(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,imm1));
|
||||
list.concat(taicpu.op_reg_reg_const(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,imm2));
|
||||
list.concat(taicpu.op_reg_reg_const(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,508));
|
||||
list.concat(taicpu.op_reg_reg_const(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,localsize-508));
|
||||
end
|
||||
else
|
||||
begin
|
||||
a_reg_alloc(list,NR_R12);
|
||||
a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
|
||||
a_reg_dealloc(list,NR_R12);
|
||||
a_reg_alloc(list,NR_R3);
|
||||
a_load_const_reg(list,OS_ADDR,LocalSize,NR_R3);
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R3));
|
||||
a_reg_dealloc(list,NR_R3);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -3525,28 +3548,7 @@ unit cgcpu;
|
||||
list.concat(taicpu.op_reg(A_BX,NR_R14))
|
||||
end
|
||||
else
|
||||
begin
|
||||
reference_reset(ref,4);
|
||||
ref.index:=NR_STACK_POINTER_REG;
|
||||
ref.addressmode:=AM_PREINDEXED;
|
||||
list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,regs));
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
list.concat(taicpu.op_reg_reg(A_MOV,NR_STACK_POINTER_REG,current_procinfo.framepointer));
|
||||
if localsize<=508 then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_reg_const(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
|
||||
end
|
||||
else
|
||||
begin
|
||||
a_load_const_reg(list,OS_ADDR,localsize,current_procinfo.framepointer);
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,current_procinfo.framepointer));
|
||||
end;
|
||||
|
||||
{ restore int registers and return }
|
||||
list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,regs));
|
||||
list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,regs));
|
||||
end;
|
||||
end
|
||||
else if not(CPUARM_HAS_BX in cpu_capabilities[current_settings.cputype]) then
|
||||
|
@ -44,6 +44,7 @@ unit cpupi;
|
||||
procedure set_first_temp_offset;override;
|
||||
function calc_stackframe_size:longint;override;
|
||||
procedure init_framepointer; override;
|
||||
procedure generate_parameter_info;override;
|
||||
end;
|
||||
|
||||
|
||||
@ -137,50 +138,55 @@ unit cpupi;
|
||||
floatsavesize : aword;
|
||||
regs: tcpuregisterset;
|
||||
begin
|
||||
maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
|
||||
floatsavesize:=0;
|
||||
case current_settings.fputype of
|
||||
fpu_fpa,
|
||||
fpu_fpa10,
|
||||
fpu_fpa11:
|
||||
begin
|
||||
{ save floating point registers? }
|
||||
firstfloatreg:=RS_NO;
|
||||
regs:=cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
|
||||
for r:=RS_F0 to RS_F7 do
|
||||
if r in regs then
|
||||
begin
|
||||
if firstfloatreg=RS_NO then
|
||||
firstfloatreg:=r;
|
||||
lastfloatreg:=r;
|
||||
end;
|
||||
if firstfloatreg<>RS_NO then
|
||||
floatsavesize:=(lastfloatreg-firstfloatreg+1)*12;
|
||||
if current_settings.cputype in cpu_thumb then
|
||||
result:=stackframesize
|
||||
else
|
||||
begin
|
||||
maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
|
||||
floatsavesize:=0;
|
||||
case current_settings.fputype of
|
||||
fpu_fpa,
|
||||
fpu_fpa10,
|
||||
fpu_fpa11:
|
||||
begin
|
||||
{ save floating point registers? }
|
||||
firstfloatreg:=RS_NO;
|
||||
regs:=cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
|
||||
for r:=RS_F0 to RS_F7 do
|
||||
if r in regs then
|
||||
begin
|
||||
if firstfloatreg=RS_NO then
|
||||
firstfloatreg:=r;
|
||||
lastfloatreg:=r;
|
||||
end;
|
||||
if firstfloatreg<>RS_NO then
|
||||
floatsavesize:=(lastfloatreg-firstfloatreg+1)*12;
|
||||
end;
|
||||
fpu_vfpv2,
|
||||
fpu_vfpv3,
|
||||
fpu_vfpv3_d16:
|
||||
begin
|
||||
floatsavesize:=0;
|
||||
regs:=cg.rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
|
||||
for r:=RS_D0 to RS_D31 do
|
||||
if r in regs then
|
||||
inc(floatsavesize,8);
|
||||
end;
|
||||
fpu_fpv4_s16:
|
||||
begin
|
||||
floatsavesize:=0;
|
||||
regs:=cg.rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
|
||||
for r:=RS_D0 to RS_D15 do
|
||||
if r in regs then
|
||||
inc(floatsavesize,8);
|
||||
end;
|
||||
end;
|
||||
fpu_vfpv2,
|
||||
fpu_vfpv3,
|
||||
fpu_vfpv3_d16:
|
||||
begin
|
||||
floatsavesize:=0;
|
||||
regs:=cg.rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
|
||||
for r:=RS_D0 to RS_D31 do
|
||||
if r in regs then
|
||||
inc(floatsavesize,8);
|
||||
end;
|
||||
fpu_fpv4_s16:
|
||||
begin
|
||||
floatsavesize:=0;
|
||||
regs:=cg.rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
|
||||
for r:=RS_D0 to RS_D15 do
|
||||
if r in regs then
|
||||
inc(floatsavesize,8);
|
||||
end;
|
||||
end;
|
||||
floatsavesize:=align(floatsavesize,max(current_settings.alignment.localalignmin,4));
|
||||
result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize+aint(floatsavesize);
|
||||
floatregstart:=tg.direction*result+maxpushedparasize;
|
||||
if tg.direction=1 then
|
||||
dec(floatregstart,floatsavesize);
|
||||
floatsavesize:=align(floatsavesize,max(current_settings.alignment.localalignmin,4));
|
||||
result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize+aint(floatsavesize);
|
||||
floatregstart:=tg.direction*result+maxpushedparasize;
|
||||
if tg.direction=1 then
|
||||
dec(floatregstart,floatsavesize);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
@ -199,6 +205,13 @@ unit cpupi;
|
||||
end;
|
||||
|
||||
|
||||
procedure tarmprocinfo.generate_parameter_info;
|
||||
begin
|
||||
procdef.total_stackframe_size:=stackframesize;
|
||||
inherited generate_parameter_info;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
cprocinfo:=tarmprocinfo;
|
||||
end.
|
||||
|
@ -625,6 +625,12 @@ interface
|
||||
{$ifdef i386}
|
||||
fpu_used : byte;
|
||||
{$endif i386}
|
||||
{$if defined(arm)}
|
||||
{ the arm paramanager might need to know the total size of the stackframe
|
||||
to avoid cyclic unit dependencies or global variables, this infomatation is
|
||||
stored in total_stackframe_size }
|
||||
total_stackframe_size : aint;
|
||||
{$endif defined(arm)}
|
||||
{$ifdef mips}
|
||||
{ needed for stabs debugging }
|
||||
total_local_size : longint;
|
||||
|
Loading…
Reference in New Issue
Block a user