* 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, 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
begin
include(rg[R_INTREGISTER].used_in_proc,RS_R4);
include(regs,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
{ 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; 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,27 +3548,6 @@ 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
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;
end end

View File

@ -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;
@ -136,6 +137,10 @@ unit cpupi;
r : byte; r : byte;
floatsavesize : aword; floatsavesize : aword;
regs: tcpuregisterset; regs: tcpuregisterset;
begin
if current_settings.cputype in cpu_thumb then
result:=stackframesize
else
begin begin
maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4)); maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
floatsavesize:=0; floatsavesize:=0;
@ -182,6 +187,7 @@ unit cpupi;
if tg.direction=1 then if tg.direction=1 then
dec(floatregstart,floatsavesize); dec(floatregstart,floatsavesize);
end; end;
end;
procedure tarmprocinfo.init_framepointer; procedure tarmprocinfo.init_framepointer;
@ -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.

View File

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