浏览代码

* when inserting pc relative data blocks on arm thumb, avoid negative pc offsets, if needed, the data is copied
a short test with the rtl shows that this happens exactly once in the rtl, so it is feasible to do so

git-svn-id: trunk@24413 -

florian 12 年之前
父节点
当前提交
cec28ef512
共有 2 个文件被更改,包括 88 次插入52 次删除
  1. 4 2
      compiler/aasmtai.pas
  2. 84 50
      compiler/arm/aasmcpu.pas

+ 4 - 2
compiler/aasmtai.pas

@@ -488,6 +488,9 @@ interface
           { set to true when the label has been moved by insertpcrelativedata to the correct location
             so one label can be used multiple times }
           moved     : boolean;
+          { true, if a label has been already inserted, this is important for arm thumb where no negative
+            pc relative offsets are allowed }
+          inserted  : boolean;
 {$endif arm}
           constructor Create(_labsym : tasmlabel);
           constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
@@ -1945,7 +1948,7 @@ implementation
                                TAI_LABEL
  ****************************************************************************}
 
-    constructor tai_label.create(_labsym : tasmlabel);
+        constructor tai_label.Create(_labsym : tasmlabel);
       begin
         inherited Create;
         typ:=ait_label;
@@ -1976,7 +1979,6 @@ implementation
         labsym.is_set:=true;
       end;
 
-
 {****************************************************************************
           tai_comment  comment to be inserted in the assembler file
  ****************************************************************************}

+ 84 - 50
compiler/arm/aasmcpu.pas

@@ -873,6 +873,7 @@ implementation
         limit: longint;
         curop : longint;
         curtai : tai;
+        ai_label : tai_label;
         curdatatai,hp,hp2 : tai;
         curdata : TAsmList;
         l : tasmlabel;
@@ -910,67 +911,88 @@ implementation
                         begin
                           { pc relative symbol? }
                           curdatatai:=tai(taicpu(curtai).oper[curop]^.ref^.symboldata);
-                          if assigned(curdatatai) and
-                            { move only if we're at the first reference of a label }
-                            not(tai_label(curdatatai).moved) then
+                          if assigned(curdatatai) then
                             begin
-                              tai_label(curdatatai).moved:=true;
-                              { check if symbol already used. }
-                              { if yes, reuse the symbol }
-                              hp:=tai(curdatatai.next);
-                              removeref:=false;
-                              if assigned(hp) then
+                              { create a new copy of a data entry on arm thumb if the entry has been inserted already
+                                before because arm thumb does not allow pc relative negative offsets }
+                              if (current_settings.cputype in cpu_thumb) and
+                                tai_label(curdatatai).inserted then
                                 begin
-                                  case hp.typ of
-                                    ait_const:
-                                      begin
-                                        if (tai_const(hp).consttype=aitconst_64bit) then
-                                          inc(extradataoffset,multiplier);
-                                      end;
-                                    ait_comp_64bit,
-                                    ait_real_64bit:
-                                      begin
-                                        inc(extradataoffset,multiplier);
-                                      end;
-                                    ait_real_80bit:
-                                      begin
-                                        inc(extradataoffset,2*multiplier);
-                                      end;
-                                  end;
-                                  if (hp.typ=ait_const) then
+                                  current_asmdata.getjumplabel(l);
+                                  hp:=tai_label.create(l);
+                                  listtoinsert.Concat(hp);
+                                  hp2:=tai(curdatatai.Next.GetCopy);
+                                  hp2.Next:=nil;
+                                  hp2.Previous:=nil;
+                                  listtoinsert.Concat(hp2);
+                                  taicpu(curtai).oper[curop]^.ref^.symboldata:=hp;
+                                  taicpu(curtai).oper[curop]^.ref^.symbol:=l;
+                                  curdatatai:=hp;
+                                end;
+
+                              { move only if we're at the first reference of a label }
+                              if not(tai_label(curdatatai).moved) then
+                                begin
+                                  tai_label(curdatatai).moved:=true;
+                                  { check if symbol already used. }
+
+                                  { if yes, reuse the symbol }
+                                  hp:=tai(curdatatai.next);
+                                  removeref:=false;
+                                  if assigned(hp) then
                                     begin
-                                      hp2:=tai(curdata.first);
-                                      while assigned(hp2) do
+                                      case hp.typ of
+                                        ait_const:
+                                          begin
+                                            if (tai_const(hp).consttype=aitconst_64bit) then
+                                              inc(extradataoffset,multiplier);
+                                          end;
+                                        ait_comp_64bit,
+                                        ait_real_64bit:
+                                          begin
+                                            inc(extradataoffset,multiplier);
+                                          end;
+                                        ait_real_80bit:
+                                          begin
+                                            inc(extradataoffset,2*multiplier);
+                                          end;
+                                      end;
+                                      { check if the same constant has been already inserted into the currently handled list,
+                                        if yes, reuse it }
+                                      if (hp.typ=ait_const) then
                                         begin
-    {                                      if armconstequal(hp2,hp) then }
-                                          if (hp2.typ=ait_const) and (tai_const(hp2).sym=tai_const(hp).sym)
-                                            and (tai_const(hp2).value=tai_const(hp).value) and (tai(hp2.previous).typ=ait_label)
-                                          then
+                                          hp2:=tai(curdata.first);
+                                          while assigned(hp2) do
                                             begin
-                                              with taicpu(curtai).oper[curop]^.ref^ do
+                                              if (hp2.typ=ait_const) and (tai_const(hp2).sym=tai_const(hp).sym)
+                                                and (tai_const(hp2).value=tai_const(hp).value) and (tai(hp2.previous).typ=ait_label)
+                                              then
                                                 begin
-                                                  symboldata:=hp2.previous;
-                                                  symbol:=tai_label(hp2.previous).labsym;
+                                                  with taicpu(curtai).oper[curop]^.ref^ do
+                                                    begin
+                                                      symboldata:=hp2.previous;
+                                                      symbol:=tai_label(hp2.previous).labsym;
+                                                    end;
+                                                  removeref:=true;
+                                                  break;
                                                 end;
-                                              removeref:=true;
-                                              break;
+                                              hp2:=tai(hp2.next);
                                             end;
-                                          hp2:=tai(hp2.next);
                                         end;
                                     end;
+                                  { move or remove symbol reference }
+                                  repeat
+                                    hp:=tai(curdatatai.next);
+                                    listtoinsert.remove(curdatatai);
+                                    if removeref then
+                                      curdatatai.free
+                                    else
+                                      curdata.concat(curdatatai);
+                                    curdatatai:=hp;
+                                  until (curdatatai=nil) or (curdatatai.typ=ait_label);
+                                  if lastinspos=-1 then
+                                    lastinspos:=curinspos;
                                 end;
-                              { move or remove symbol reference }
-                              repeat
-                                hp:=tai(curdatatai.next);
-                                listtoinsert.remove(curdatatai);
-                                if removeref then
-                                  curdatatai.free
-                                else
-                                  curdata.concat(curdatatai);
-                                curdatatai:=hp;
-                              until (curdatatai=nil) or (curdatatai.typ=ait_label);
-                              if lastinspos=-1 then
-                                lastinspos:=curinspos;
                             end;
                         end;
                     end;
@@ -1065,6 +1087,18 @@ implementation
                   curdata.Insert(tai_align.Create(4));
                 curdata.insert(taicpu.op_sym(A_B,l));
                 curdata.concat(tai_label.create(l));
+
+                { mark all labels as inserted, arm thumb
+                  needs this, so data referencing an already inserted label can be
+                  duplicated because arm thumb does not allow negative pc relative offset }
+                hp2:=tai(curdata.first);
+                while assigned(hp2) do
+                  begin
+                    if hp2.typ=ait_label then
+                      tai_label(hp2).inserted:=true;
+                    hp2:=tai(hp2.next);
+                  end;
+
                 list.insertlistafter(curtai,curdata);
                 curtai:=hp;
               end