Przeglądaj źródła

* prevent generation of mul/mla statements with illegal registers

git-svn-id: trunk@25343 -
florian 12 lat temu
rodzic
commit
bb73a2891b

+ 27 - 0
compiler/arm/cgcpu.pas

@@ -112,6 +112,9 @@ unit cgcpu;
         { clear out potential overflow bits from 8 or 16 bit operations  }
         { the upper 24/16 bits of a register after an operation          }
         procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+
+        { mla for thumb requires that none of the registers is equal to r13/r15, this method ensures this }
+        procedure safe_mla(list: TAsmList;op1,op2,op3,op4 : TRegister);
       end;
 
       { tcgarm is shared between normal arm and thumb-2 }
@@ -3191,6 +3194,30 @@ unit cgcpu;
       end;
 
 
+    procedure tbasecgarm.safe_mla(list : TAsmList; op1,op2,op3,op4 : TRegister);
+
+      procedure checkreg(var reg : TRegister);
+        var
+          tmpreg : TRegister;
+        begin
+          if ((current_settings.cputype in cpu_thumb+cpu_thumb2) and (getsupreg(reg)=RS_R13)) or
+            (getsupreg(reg)=RS_R15) then
+            begin
+              tmpreg:=getintregister(list,OS_INT);
+              a_load_reg_reg(list,OS_INT,OS_INT,reg,tmpreg);
+              reg:=tmpreg;
+            end;
+        end;
+
+      begin
+        checkreg(op1);
+        checkreg(op2);
+        checkreg(op3);
+        checkreg(op4);
+        list.concat(taicpu.op_reg_reg_reg_reg(A_MLA,op1,op2,op3,op4));
+      end;
+
+
     procedure tcg64farm.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
       begin
         case op of

+ 2 - 2
compiler/arm/narmadd.pas

@@ -53,7 +53,7 @@ interface
       defutil,htypechk,cgbase,cgutils,
       cpuinfo,pass_1,pass_2,procinfo,
       ncon,nadd,ncnv,ncal,nmat,
-      ncgutil,cgobj,
+      ncgutil,cgobj,cgcpu,
       hlcgobj
       ;
 
@@ -509,7 +509,7 @@ interface
             tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
             asmList.concat(taicpu.op_reg_reg_reg(A_MUL,tmpreg,ll.reglo,rl.reghi));
             asmList.concat(taicpu.op_reg_reg_reg_reg(A_UMULL,res.reglo,res.reghi,rl.reglo,ll.reglo));
-            asmList.concat(taicpu.op_reg_reg_reg_reg(A_MLA,tmpreg,rl.reglo,ll.reghi,tmpreg));
+            tbasecgarm(cg).safe_mla(asmList,tmpreg,rl.reglo,ll.reghi,tmpreg);
             asmList.concat(taicpu.op_reg_reg_reg(A_ADD,res.reghi,tmpreg,res.reghi));
           end
         else

+ 3 - 3
compiler/arm/narmmem.pas

@@ -42,7 +42,7 @@ interface
 implementation
 
     uses
-      cutils,verbose,globals,aasmdata,aasmcpu,cgobj,
+      cutils,verbose,globals,aasmdata,aasmcpu,cgobj,cgcpu,
       cpuinfo,
       cgutils,
       procinfo;
@@ -84,7 +84,7 @@ implementation
            begin
              hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
              cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_ADDR,l,hreg);
-             current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_reg(A_MLA,hreg,maybe_const_reg,hreg,location.reference.base));
+             tbasecgarm(cg).safe_mla(current_asmdata.CurrAsmList,hreg,maybe_const_reg,hreg,location.reference.base);
              location.reference.base:=hreg;
              { update alignment }
              if (location.reference.alignment=0) then
@@ -95,7 +95,7 @@ implementation
            begin
              hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
              cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_ADDR,l,hreg);
-             current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_reg(A_MLA,hreg,maybe_const_reg,hreg,location.reference.index));
+             tbasecgarm(cg).safe_mla(current_asmdata.CurrAsmList,hreg,maybe_const_reg,hreg,location.reference.index);
              location.reference.base:=hreg;
              location.reference.index:=NR_NO;
              { update alignment }

+ 27 - 2
compiler/arm/rgcpu.pas

@@ -121,6 +121,24 @@ unit rgcpu;
                         end;
                     end;
                 end;
+              A_MLA,
+              A_MUL:
+                begin
+                  if current_settings.cputype<cpu_armv6 then
+                    add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
+                   add_edge(getsupreg(taicpu(p).oper[0]^.reg),RS_R13);
+                   add_edge(getsupreg(taicpu(p).oper[0]^.reg),RS_R15);
+                   add_edge(getsupreg(taicpu(p).oper[1]^.reg),RS_R13);
+                   add_edge(getsupreg(taicpu(p).oper[1]^.reg),RS_R15);
+                   add_edge(getsupreg(taicpu(p).oper[2]^.reg),RS_R13);
+                   add_edge(getsupreg(taicpu(p).oper[2]^.reg),RS_R15);
+                   if taicpu(p).opcode=A_MLA then
+                     begin
+                       add_edge(getsupreg(taicpu(p).oper[3]^.reg),RS_R13);
+                       add_edge(getsupreg(taicpu(p).oper[3]^.reg),RS_R15);
+                     end;
+                end;
+
               A_LDRB,
               A_STRB,
               A_STR,
@@ -486,8 +504,15 @@ unit rgcpu;
             case taicpu(p).opcode of
               A_MLA,
               A_MUL:
-                if current_settings.cputype<cpu_armv6 then
-                  add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
+                begin
+                  if current_settings.cputype<cpu_armv6 then
+                    add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
+                  add_edge(getsupreg(taicpu(p).oper[0]^.reg),RS_R15);
+                  add_edge(getsupreg(taicpu(p).oper[1]^.reg),RS_R15);
+                  add_edge(getsupreg(taicpu(p).oper[2]^.reg),RS_R15);
+                  if taicpu(p).opcode=A_MLA then
+                    add_edge(getsupreg(taicpu(p).oper[3]^.reg),RS_R15);
+                end;
               A_UMULL,
               A_UMLAL,
               A_SMULL,