* 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 -
This commit is contained in:
florian 2013-05-03 20:45:26 +00:00
parent 1f8192b6da
commit cec28ef512
2 changed files with 88 additions and 52 deletions

View File

@ -488,6 +488,9 @@ interface
{ set to true when the label has been moved by insertpcrelativedata to the correct location { set to true when the label has been moved by insertpcrelativedata to the correct location
so one label can be used multiple times } so one label can be used multiple times }
moved : boolean; 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} {$endif arm}
constructor Create(_labsym : tasmlabel); constructor Create(_labsym : tasmlabel);
constructor ppuload(t:taitype;ppufile:tcompilerppufile);override; constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
@ -1945,7 +1948,7 @@ implementation
TAI_LABEL TAI_LABEL
****************************************************************************} ****************************************************************************}
constructor tai_label.create(_labsym : tasmlabel); constructor tai_label.Create(_labsym : tasmlabel);
begin begin
inherited Create; inherited Create;
typ:=ait_label; typ:=ait_label;
@ -1976,7 +1979,6 @@ implementation
labsym.is_set:=true; labsym.is_set:=true;
end; end;
{**************************************************************************** {****************************************************************************
tai_comment comment to be inserted in the assembler file tai_comment comment to be inserted in the assembler file
****************************************************************************} ****************************************************************************}

View File

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