mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-07 00:38:42 +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,
|
r7offset,
|
||||||
stackmisalignment : pint;
|
stackmisalignment : pint;
|
||||||
postfix: toppostfix;
|
postfix: toppostfix;
|
||||||
|
registerarea,
|
||||||
imm1, imm2: DWord;
|
imm1, imm2: DWord;
|
||||||
|
stack_parameters: Boolean;
|
||||||
begin
|
begin
|
||||||
|
stack_parameters:=current_procinfo.procdef.stack_tainting_parameter(calleeside);
|
||||||
LocalSize:=align(LocalSize,4);
|
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 }
|
{ call instruction does not put anything on the stack }
|
||||||
stackmisalignment:=0;
|
stackmisalignment:=0;
|
||||||
if not(nostackframe) then
|
if not(nostackframe) then
|
||||||
@ -3418,32 +3415,57 @@ unit cgcpu;
|
|||||||
if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
|
if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
|
||||||
regs:=regs+[RS_R7,RS_R14]
|
regs:=regs+[RS_R7,RS_R14]
|
||||||
else
|
else
|
||||||
if (regs<>[]) or (pi_do_call in current_procinfo.flags) then
|
// if (regs<>[]) or (pi_do_call in current_procinfo.flags) then
|
||||||
include(regs,RS_R14);
|
include(regs,RS_R14);
|
||||||
|
|
||||||
{ safely estimate stack size }
|
{ safely estimate stack size }
|
||||||
if localsize+current_settings.alignment.localalignmax>508 then
|
if localsize+current_settings.alignment.localalignmax+4>508 then
|
||||||
include(regs,RS_R4);
|
begin
|
||||||
|
include(rg[R_INTREGISTER].used_in_proc,RS_R4);
|
||||||
|
include(regs,RS_R4);
|
||||||
|
end;
|
||||||
|
|
||||||
|
registerarea:=0;
|
||||||
if regs<>[] then
|
if regs<>[] then
|
||||||
begin
|
begin
|
||||||
for r:=RS_R0 to RS_R15 do
|
for r:=RS_R0 to RS_R15 do
|
||||||
if r in regs then
|
if r in regs then
|
||||||
inc(stackmisalignment,4);
|
inc(registerarea,4);
|
||||||
list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,regs));
|
list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,regs));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
stackmisalignment:=stackmisalignment mod current_settings.alignment.localalignmax;
|
stackmisalignment:=registerarea mod current_settings.alignment.localalignmax;
|
||||||
if (LocalSize<>0) or
|
|
||||||
|
if stack_parameters or (LocalSize<>0) or
|
||||||
((stackmisalignment<>0) and
|
((stackmisalignment<>0) and
|
||||||
((pi_do_call in current_procinfo.flags) or
|
((pi_do_call in current_procinfo.flags) or
|
||||||
(po_assembler in current_procinfo.procdef.procoptions))) then
|
(po_assembler in current_procinfo.procdef.procoptions))) then
|
||||||
begin
|
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
|
if localsize<508 then
|
||||||
begin
|
begin
|
||||||
list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
|
list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
|
||||||
end
|
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
|
else
|
||||||
begin
|
begin
|
||||||
a_load_const_reg(list,OS_ADDR,-localsize,NR_R4);
|
a_load_const_reg(list,OS_ADDR,-localsize,NR_R4);
|
||||||
@ -3485,7 +3507,7 @@ unit cgcpu;
|
|||||||
include(regs,RS_R15);
|
include(regs,RS_R15);
|
||||||
|
|
||||||
if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
|
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
|
for r:=RS_R0 to RS_R15 do
|
||||||
if r in regs then
|
if r in regs then
|
||||||
@ -3501,19 +3523,20 @@ unit cgcpu;
|
|||||||
((pi_do_call in current_procinfo.flags) or
|
((pi_do_call in current_procinfo.flags) or
|
||||||
(po_assembler in current_procinfo.procdef.procoptions))) then
|
(po_assembler in current_procinfo.procdef.procoptions))) then
|
||||||
begin
|
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))
|
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
|
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,508));
|
||||||
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,localsize-508));
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
a_reg_alloc(list,NR_R12);
|
a_reg_alloc(list,NR_R3);
|
||||||
a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
|
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_R12));
|
list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R3));
|
||||||
a_reg_dealloc(list,NR_R12);
|
a_reg_dealloc(list,NR_R3);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3525,28 +3548,7 @@ unit cgcpu;
|
|||||||
list.concat(taicpu.op_reg(A_BX,NR_R14))
|
list.concat(taicpu.op_reg(A_BX,NR_R14))
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,regs));
|
||||||
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));
|
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else if not(CPUARM_HAS_BX in cpu_capabilities[current_settings.cputype]) then
|
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;
|
procedure set_first_temp_offset;override;
|
||||||
function calc_stackframe_size:longint;override;
|
function calc_stackframe_size:longint;override;
|
||||||
procedure init_framepointer; override;
|
procedure init_framepointer; override;
|
||||||
|
procedure generate_parameter_info;override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -137,50 +138,55 @@ unit cpupi;
|
|||||||
floatsavesize : aword;
|
floatsavesize : aword;
|
||||||
regs: tcpuregisterset;
|
regs: tcpuregisterset;
|
||||||
begin
|
begin
|
||||||
maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
|
if current_settings.cputype in cpu_thumb then
|
||||||
floatsavesize:=0;
|
result:=stackframesize
|
||||||
case current_settings.fputype of
|
else
|
||||||
fpu_fpa,
|
begin
|
||||||
fpu_fpa10,
|
maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
|
||||||
fpu_fpa11:
|
floatsavesize:=0;
|
||||||
begin
|
case current_settings.fputype of
|
||||||
{ save floating point registers? }
|
fpu_fpa,
|
||||||
firstfloatreg:=RS_NO;
|
fpu_fpa10,
|
||||||
regs:=cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
|
fpu_fpa11:
|
||||||
for r:=RS_F0 to RS_F7 do
|
begin
|
||||||
if r in regs then
|
{ save floating point registers? }
|
||||||
begin
|
firstfloatreg:=RS_NO;
|
||||||
if firstfloatreg=RS_NO then
|
regs:=cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
|
||||||
firstfloatreg:=r;
|
for r:=RS_F0 to RS_F7 do
|
||||||
lastfloatreg:=r;
|
if r in regs then
|
||||||
end;
|
begin
|
||||||
if firstfloatreg<>RS_NO then
|
if firstfloatreg=RS_NO then
|
||||||
floatsavesize:=(lastfloatreg-firstfloatreg+1)*12;
|
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;
|
end;
|
||||||
fpu_vfpv2,
|
floatsavesize:=align(floatsavesize,max(current_settings.alignment.localalignmin,4));
|
||||||
fpu_vfpv3,
|
result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize+aint(floatsavesize);
|
||||||
fpu_vfpv3_d16:
|
floatregstart:=tg.direction*result+maxpushedparasize;
|
||||||
begin
|
if tg.direction=1 then
|
||||||
floatsavesize:=0;
|
dec(floatregstart,floatsavesize);
|
||||||
regs:=cg.rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
|
end;
|
||||||
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);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -199,6 +205,13 @@ unit cpupi;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure tarmprocinfo.generate_parameter_info;
|
||||||
|
begin
|
||||||
|
procdef.total_stackframe_size:=stackframesize;
|
||||||
|
inherited generate_parameter_info;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
cprocinfo:=tarmprocinfo;
|
cprocinfo:=tarmprocinfo;
|
||||||
end.
|
end.
|
||||||
|
@ -625,6 +625,12 @@ interface
|
|||||||
{$ifdef i386}
|
{$ifdef i386}
|
||||||
fpu_used : byte;
|
fpu_used : byte;
|
||||||
{$endif i386}
|
{$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}
|
{$ifdef mips}
|
||||||
{ needed for stabs debugging }
|
{ needed for stabs debugging }
|
||||||
total_local_size : longint;
|
total_local_size : longint;
|
||||||
|
Loading…
Reference in New Issue
Block a user