From cec28ef512d5f57e7bfd97402097e02f2668b4ba Mon Sep 17 00:00:00 2001 From: florian Date: Fri, 3 May 2013 20:45:26 +0000 Subject: [PATCH] * 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 - --- compiler/aasmtai.pas | 6 +- compiler/arm/aasmcpu.pas | 134 ++++++++++++++++++++++++--------------- 2 files changed, 88 insertions(+), 52 deletions(-) diff --git a/compiler/aasmtai.pas b/compiler/aasmtai.pas index 94b1d60141..a6aef1eb5a 100644 --- a/compiler/aasmtai.pas +++ b/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 ****************************************************************************} diff --git a/compiler/arm/aasmcpu.pas b/compiler/arm/aasmcpu.pas index 7738c86480..5f9fa3a7d9 100644 --- a/compiler/arm/aasmcpu.pas +++ b/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