diff --git a/compiler/arm/cgcpu.pas b/compiler/arm/cgcpu.pas index 0a1500a785..f646bef9b0 100644 --- a/compiler/arm/cgcpu.pas +++ b/compiler/arm/cgcpu.pas @@ -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 diff --git a/compiler/arm/cpupi.pas b/compiler/arm/cpupi.pas index b35bbd6ee3..011fa79148 100644 --- a/compiler/arm/cpupi.pas +++ b/compiler/arm/cpupi.pas @@ -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. diff --git a/compiler/symdef.pas b/compiler/symdef.pas index 36df275191..b1f04b5367 100644 --- a/compiler/symdef.pas +++ b/compiler/symdef.pas @@ -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;