* 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:
florian 2013-04-07 21:01:15 +00:00
parent f9ef8e90da
commit 7ba197a221
3 changed files with 109 additions and 88 deletions

View File

@ -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

View File

@ -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.

View File

@ -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;