* ARM: Do not use R9 as a fixed GOT register.
authoryury <yury@3ad0048d-3df7-0310-abae-a5850022a9f2>
Wed, 16 Sep 2015 13:52:15 +0000 (13:52 +0000)
committerGraham Inggs <ginggs@debian.org>
Wed, 8 Feb 2017 09:53:35 +0000 (09:53 +0000)
git-svn-id: http://svn.freepascal.org/svn/ fpc/trunk@31712 3ad0048d-3df7-0310-abae-a5850022a9f2

Gbp-Pq: Name ARM-Do-not-use-R9-as-a-fixed-GOT-register.patch

fpcsrc/compiler/arm/cgcpu.pas
fpcsrc/compiler/arm/cpupi.pas

index 68177fe69ada94afadc05e00d813310ba49b5830..d174743a43565abba95238a15e48c7ce80682fde 100644 (file)
@@ -2273,20 +2273,31 @@ unit cgcpu;
            (pi_needs_got in current_procinfo.flags) and
            (tf_pic_uses_got in target_info.flags) then
           begin
-            a_reg_alloc(list,current_procinfo.got);  // Alloc PIC register
-            if getsupreg(current_procinfo.got) < first_int_imreg then
-              include(rg[R_INTREGISTER].used_in_proc,getsupreg(current_procinfo.got));
             reference_reset(ref,4);
             current_asmdata.getdatalabel(l);
             cg.a_label(current_procinfo.aktlocaldata,l);
             ref.symbol:=l;
             ref.base:=NR_PC;
             ref.symboldata:=current_procinfo.aktlocaldata.last;
-            list.concat(Taicpu.op_reg_ref(A_LDR,current_procinfo.got,ref));
+            a_reg_alloc(list,NR_R12);
+            list.concat(Taicpu.op_reg_ref(A_LDR,NR_R12,ref));
             current_asmdata.getaddrlabel(l);
             current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_32bit,l,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),-8));
             cg.a_label(list,l);
-            list.concat(Taicpu.op_reg_reg_reg(A_ADD,current_procinfo.got,NR_PC,current_procinfo.got));
+            if cs_opt_regvar in current_settings.optimizerswitches then
+              begin
+                {
+                  When regvars are used, it is needed to perform GOT calculations using the scratch register R12
+                  and then MOV the result to the GOT register. Otherwise the register allocator will use
+                  register R0 as temp to perform calculations in case if a procedure uses all available registers.
+                  It leads to corruption of R0 which is normally holds a value of the first procedure parameter.
+                }
+                list.concat(Taicpu.op_reg_reg_reg(A_ADD,NR_R12,NR_PC,NR_R12));
+                list.concat(Taicpu.op_reg_reg(A_MOV,current_procinfo.got,NR_R12));
+              end
+            else
+              list.concat(Taicpu.op_reg_reg_reg(A_ADD,current_procinfo.got,NR_PC,NR_R12));
+            a_reg_dealloc(list,NR_R12);
           end;
       end;
 
index 3d69b85da013edd9fab82f18f928531abc604f76..30cd892d116f701877dfd097baa843ec4d2b25cb 100644 (file)
@@ -265,7 +265,7 @@ unit cpupi;
       begin
         { darwin doesn't use a got }
         if tf_pic_uses_got in target_info.flags then
-          got := NR_PIC_OFFSET_REG;
+          got := cg.getaddressregister(list);
       end;