Jelajahi Sumber

* fix stack parameter handling for arm thumb
* fix entry/exit code generation for arm thumb

git-svn-id: trunk@24197 -

florian 12 tahun lalu
induk
melakukan
7ba197a221
3 mengubah file dengan 109 tambahan dan 88 penghapusan
  1. 47 45
      compiler/arm/cgcpu.pas
  2. 56 43
      compiler/arm/cpupi.pas
  3. 6 0
      compiler/symdef.pas

+ 47 - 45
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

+ 56 - 43
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;
-            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);
+        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;
-        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.

+ 6 - 0
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;