浏览代码

--- Merging r30027 into '.':
U compiler/arm/aasmcpu.pas
--- Merging r30033 into '.':
U compiler/optcse.pas

# revisions: 30027,30033

git-svn-id: branches/fixes_3_0@30084 -

Jonas Maebe 10 年之前
父节点
当前提交
8c6eec12f6
共有 2 个文件被更改,包括 52 次插入13 次删除
  1. 45 12
      compiler/arm/aasmcpu.pas
  2. 7 1
      compiler/optcse.pas

+ 45 - 12
compiler/arm/aasmcpu.pas

@@ -898,6 +898,20 @@ implementation
               limit:=254;
               limit:=254;
         end;
         end;
 
 
+      function is_case_dispatch(hp: taicpu): boolean;
+        begin
+          result:=
+            ((taicpu(hp).opcode in [A_ADD,A_LDR]) and
+             not(GenerateThumbCode or GenerateThumb2Code) and
+             (taicpu(hp).oper[0]^.typ=top_reg) and
+             (taicpu(hp).oper[0]^.reg=NR_PC)) or
+             ((taicpu(hp).opcode=A_MOV) and (GenerateThumbCode) and
+              (taicpu(hp).oper[0]^.typ=top_reg) and
+              (taicpu(hp).oper[0]^.reg=NR_PC)) or
+             (taicpu(hp).opcode=A_TBH) or
+             (taicpu(hp).opcode=A_TBB);
+        end;
+
       var
       var
         curinspos,
         curinspos,
         penalty,
         penalty,
@@ -906,7 +920,8 @@ implementation
         currentsize,
         currentsize,
         extradataoffset,
         extradataoffset,
         curop : longint;
         curop : longint;
-        curtai : tai;
+        curtai,
+        inserttai : tai;
         ai_label : tai_label;
         ai_label : tai_label;
         curdatatai,hp,hp2 : tai;
         curdatatai,hp,hp2 : tai;
         curdata : TAsmList;
         curdata : TAsmList;
@@ -1066,15 +1081,11 @@ implementation
                 case taicpu(hp).opcode of
                 case taicpu(hp).opcode of
                   A_MOV,
                   A_MOV,
                   A_LDR,
                   A_LDR,
-                  A_ADD:
+                  A_ADD,
+                  A_TBH,
+                  A_TBB:
                     { approximation if we hit a case jump table }
                     { approximation if we hit a case jump table }
-                    if ((taicpu(hp).opcode in [A_ADD,A_LDR]) and not(GenerateThumbCode or GenerateThumb2Code) and
-                       (taicpu(hp).oper[0]^.typ=top_reg) and
-                      (taicpu(hp).oper[0]^.reg=NR_PC)) or
-                      ((taicpu(hp).opcode=A_MOV) and (GenerateThumbCode) and
-                       (taicpu(hp).oper[0]^.typ=top_reg) and
-                       (taicpu(hp).oper[0]^.reg=NR_PC))
-                       then
+                    if is_case_dispatch(taicpu(hp)) then
                       begin
                       begin
                         penalty:=multiplier;
                         penalty:=multiplier;
                         hp:=tai(hp.next);
                         hp:=tai(hp.next);
@@ -1168,12 +1179,34 @@ implementation
                 else
                 else
                   limit:=1016;
                   limit:=1016;
 
 
+                { if this is an add/tbh/tbb-based jumptable, go back to the
+                  previous instruction, because inserting data between the
+                  dispatch instruction and the table would mess up the
+                  addresses }
+                inserttai:=curtai;
+                if is_case_dispatch(taicpu(inserttai)) and
+                   ((taicpu(inserttai).opcode=A_ADD) or
+                    (taicpu(inserttai).opcode=A_TBH) or
+                    (taicpu(inserttai).opcode=A_TBB)) then
+                  begin
+                    repeat
+                      inserttai:=tai(inserttai.previous);
+                    until inserttai.typ=ait_instruction;
+                    { if it's an add-based jump table, then also skip the
+                      pc-relative load }
+                    if taicpu(curtai).opcode=A_ADD then
+                      repeat
+                        inserttai:=tai(inserttai.previous);
+                      until inserttai.typ=ait_instruction;
+                  end
+                else
+
                 { on arm thumb, insert the data always after all labels etc. following an instruction so it
                 { on arm thumb, insert the data always after all labels etc. following an instruction so it
                   is prevent that a bxx yyy; bl xxx; yyyy: sequence gets separated ( we never insert on arm thumb after
                   is prevent that a bxx yyy; bl xxx; yyyy: sequence gets separated ( we never insert on arm thumb after
                   bxx) and the distance of bxx gets too long }
                   bxx) and the distance of bxx gets too long }
                 if GenerateThumbCode then
                 if GenerateThumbCode then
-                  while assigned(tai(curtai.Next)) and (tai(curtai.Next).typ in SkipInstr+[ait_label]) do
-                    curtai:=tai(curtai.next);
+                  while assigned(tai(inserttai.Next)) and (tai(inserttai.Next).typ in SkipInstr+[ait_label]) do
+                    inserttai:=tai(inserttai.next);
 
 
                 doinsert:=false;
                 doinsert:=false;
                 current_asmdata.getjumplabel(l);
                 current_asmdata.getjumplabel(l);
@@ -1200,7 +1233,7 @@ implementation
                   is then equal curdata.last.previous) we could over see one
                   is then equal curdata.last.previous) we could over see one
                   instruction }
                   instruction }
                 hp:=tai(curdata.Last);
                 hp:=tai(curdata.Last);
-                list.insertlistafter(curtai,curdata);
+                list.insertlistafter(inserttai,curdata);
                 curtai:=hp;
                 curtai:=hp;
               end
               end
             else
             else

+ 7 - 1
compiler/optcse.pas

@@ -317,7 +317,13 @@ unit optcse;
                    { for sets, we can do this always }
                    { for sets, we can do this always }
                    (is_set(n.resultdef))
                    (is_set(n.resultdef))
                    ) then
                    ) then
-                  while n.nodetype=tbinarynode(n).left.nodetype do
+                  while (n.nodetype=tbinarynode(n).left.nodetype) and
+                        { the resulttypes of the operands we'll swap must be equal,
+                          required in case of a 32x32->64 multiplication, then we
+                          cannot swap out one of the 32 bit operands for a 64 bit one
+                        }
+                        (tbinarynode(tbinarynode(n).left).left.resultdef=tbinarynode(n).left.resultdef) and
+                        (tbinarynode(n).left.resultdef=tbinarynode(n).right.resultdef) do
                     begin
                     begin
                       csedomain:=true;
                       csedomain:=true;
                       foreachnodestatic(pm_postprocess,tbinarynode(n).right,@searchsubdomain,@csedomain);
                       foreachnodestatic(pm_postprocess,tbinarynode(n).right,@searchsubdomain,@csedomain);