mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-13 00:09:32 +02:00
fpcdefs.inc: Set fpc_compiler_has_fixup_jmps for powerpcXX and mips CPUs.
psub.pas: Use new fpc_compiler_has_fixup_jmps conditional. mips/aasmcpu.pas: MIPS specific fixup_jmps function, The insttruction distance calculation is not exact as some pseudo-instruction can be expanded to a variable number of real instructions real calculation would only be possible if we first convert pseudo-instuctions to real instructions before calling fixup_jmps. ncgutil.pas: Revert commit r21791 ncgcon.pas: Revert commit r21786 mips/cgcpu.pas: Partial revert of commit r21798, no need to always use A_J, as fixup_jmps now handles out of range branches. git-svn-id: trunk@21822 -
This commit is contained in:
parent
3d002a13c5
commit
bc0c94c204
@ -107,6 +107,7 @@
|
||||
{$define cpumm}
|
||||
{$define cpurox}
|
||||
{$define cpurefshaveindexreg}
|
||||
{$define fpc_compiler_has_fixup_jmps}
|
||||
{$endif powerpc}
|
||||
|
||||
{$ifdef powerpc64}
|
||||
@ -117,6 +118,7 @@
|
||||
{$define cpumm}
|
||||
{$define cpurox}
|
||||
{$define cpurefshaveindexreg}
|
||||
{$define fpc_compiler_has_fixup_jmps}
|
||||
{$endif powerpc64}
|
||||
|
||||
{$ifdef arm}
|
||||
@ -195,6 +197,7 @@
|
||||
{$define cpurequiresproperalignment}
|
||||
{ define cpumm}
|
||||
{$define cpurefshaveindexreg}
|
||||
{$define fpc_compiler_has_fixup_jmps}
|
||||
{$endif mips}
|
||||
|
||||
{$ifdef jvm}
|
||||
|
@ -28,7 +28,7 @@ interface
|
||||
uses
|
||||
cclasses,
|
||||
globtype, globals, verbose,
|
||||
aasmbase, aasmsym, aasmtai,
|
||||
aasmbase, aasmdata, aasmsym, aasmtai,
|
||||
cgbase, cgutils, cpubase, cpuinfo;
|
||||
|
||||
const
|
||||
@ -78,11 +78,16 @@ type
|
||||
procedure InitAsm;
|
||||
procedure DoneAsm;
|
||||
|
||||
procedure fixup_jmps(list: TAsmList);
|
||||
|
||||
function spilling_create_load(const ref: treference; r: tregister): taicpu;
|
||||
function spilling_create_store(r: tregister; const ref: treference): taicpu;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
cutils;
|
||||
|
||||
{*****************************************************************************
|
||||
taicpu Constructors
|
||||
*****************************************************************************}
|
||||
@ -452,6 +457,146 @@ procedure DoneAsm;
|
||||
end;
|
||||
|
||||
|
||||
procedure fixup_jmps(list: TAsmList);
|
||||
var
|
||||
p,pdelayslot: tai;
|
||||
newcomment: tai_comment;
|
||||
newjmp,newnoop: taicpu;
|
||||
labelpositions: TFPList;
|
||||
instrpos: ptrint;
|
||||
l: tasmlabel;
|
||||
inserted_something: boolean;
|
||||
begin
|
||||
// if certainly not enough instructions to cause an overflow, dont bother
|
||||
if (list.count <= (high(smallint) div 4)) then
|
||||
exit;
|
||||
labelpositions := TFPList.create;
|
||||
p := tai(list.first);
|
||||
instrpos := 1;
|
||||
// record label positions
|
||||
while assigned(p) do
|
||||
begin
|
||||
if p.typ = ait_label then
|
||||
begin
|
||||
if (tai_label(p).labsym.labelnr >= labelpositions.count) then
|
||||
labelpositions.count := tai_label(p).labsym.labelnr * 2;
|
||||
labelpositions[tai_label(p).labsym.labelnr] := pointer(instrpos);
|
||||
end;
|
||||
{ ait_const is for jump tables }
|
||||
case p.typ of
|
||||
ait_instruction:
|
||||
{ probleim here: pseudo-instructions can translate into
|
||||
several CPU instructions, possibly depending on assembler options,
|
||||
to obe on safe side, let's assume a mean of two. }
|
||||
inc(instrpos,2);
|
||||
ait_const:
|
||||
begin
|
||||
if (tai_const(p).consttype<>aitconst_32bit) then
|
||||
internalerror(2008052101);
|
||||
inc(instrpos);
|
||||
end;
|
||||
end;
|
||||
p := tai(p.next);
|
||||
end;
|
||||
|
||||
{ If the number of instructions is below limit, we can't overflow either }
|
||||
if (instrpos <= (high(smallint) div 4)) then
|
||||
exit;
|
||||
// check and fix distances
|
||||
repeat
|
||||
inserted_something := false;
|
||||
p := tai(list.first);
|
||||
instrpos := 1;
|
||||
while assigned(p) do
|
||||
begin
|
||||
case p.typ of
|
||||
ait_label:
|
||||
// update labelposition in case it changed due to insertion
|
||||
// of jumps
|
||||
begin
|
||||
// can happen because of newly inserted labels
|
||||
if (tai_label(p).labsym.labelnr > labelpositions.count) then
|
||||
labelpositions.count := tai_label(p).labsym.labelnr * 2;
|
||||
labelpositions[tai_label(p).labsym.labelnr] := pointer(instrpos);
|
||||
end;
|
||||
ait_instruction:
|
||||
begin
|
||||
inc(instrpos,2);
|
||||
case taicpu(p).opcode of
|
||||
A_BA:
|
||||
if (taicpu(p).oper[0]^.typ = top_ref) and
|
||||
assigned(taicpu(p).oper[0]^.ref^.symbol) and
|
||||
(taicpu(p).oper[0]^.ref^.symbol is tasmlabel) and
|
||||
(labelpositions[tasmlabel(taicpu(p).oper[0]^.ref^.symbol).labelnr] <> NIL) and
|
||||
{$push}
|
||||
{$q-}
|
||||
(ptruint(abs(ptrint(labelpositions[tasmlabel(taicpu(p).oper[0]^.ref^.symbol).labelnr]-instrpos)) - (low(smallint) div 4)) > ptruint((high(smallint) - low(smallint)) div 4)) then
|
||||
{$pop}
|
||||
begin
|
||||
{ This is not PIC safe }
|
||||
taicpu(p).opcode:=A_J;
|
||||
newcomment:=tai_comment.create(strpnew('fixup_jmps, A_BA changed into A_J'));
|
||||
list.insertbefore(newcomment,p);
|
||||
end;
|
||||
A_BC:
|
||||
if (taicpu(p).ops=3) and (taicpu(p).oper[2]^.typ = top_ref) and
|
||||
assigned(taicpu(p).oper[2]^.ref^.symbol) and
|
||||
(taicpu(p).oper[2]^.ref^.symbol is tasmlabel) and
|
||||
(labelpositions[tasmlabel(taicpu(p).oper[2]^.ref^.symbol).labelnr] <> NIL) and
|
||||
{$push}
|
||||
{$q-}
|
||||
(ptruint(abs(ptrint(labelpositions[tasmlabel(taicpu(p).oper[2]^.ref^.symbol).labelnr]-instrpos)) - (low(smallint) div 4)) > ptruint((high(smallint) - low(smallint)) div 4)) then
|
||||
{$pop}
|
||||
begin
|
||||
// add a new label after this jump
|
||||
current_asmdata.getjumplabel(l);
|
||||
{ new label -> may have to increase array size }
|
||||
if (l.labelnr >= labelpositions.count) then
|
||||
labelpositions.count := l.labelnr + 10;
|
||||
{ newjmp will be inserted before the label, and it's inserted after }
|
||||
{ plus delay slot }
|
||||
{ the current jump -> instrpos+3 }
|
||||
labelpositions[l.labelnr] := pointer(instrpos+2*3);
|
||||
pdelayslot:=tai(p.next);
|
||||
{ We need to insert the new instruction after the delay slot instruction ! }
|
||||
while assigned(pdelayslot) and (pdelayslot.typ<>ait_instruction) do
|
||||
pdelayslot:=tai(pdelayslot.next);
|
||||
|
||||
list.insertafter(tai_label.create(l),pdelayslot);
|
||||
// add a new unconditional jump between this jump and the label
|
||||
newcomment:=tai_comment.create(strpnew('fixup_jmps, A_BXX changed into A_BNOTXX label;A_J;label:'));
|
||||
list.insertbefore(newcomment,p);
|
||||
newjmp := taicpu.op_sym(A_J,taicpu(p).oper[2]^.ref^.symbol);
|
||||
newjmp.is_jmp := true;
|
||||
newjmp.fileinfo := taicpu(p).fileinfo;
|
||||
list.insertafter(newjmp,pdelayslot);
|
||||
inc(instrpos,2);
|
||||
{ Add a delay slot for new A_J instruction }
|
||||
newnoop:=taicpu.op_none(A_NOP);
|
||||
newnoop.fileinfo := taicpu(p).fileinfo;
|
||||
list.insertafter(newnoop,newjmp);
|
||||
inc(instrpos,2);
|
||||
// change the conditional jump to point to the newly inserted label
|
||||
tasmlabel(taicpu(p).oper[2]^.ref^.symbol).decrefs;
|
||||
taicpu(p).oper[2]^.ref^.symbol := l;
|
||||
l.increfs;
|
||||
// and invert its condition code
|
||||
taicpu(p).condition := inverse_cond(taicpu(p).condition);
|
||||
// we inserted an instruction, so will have to check everything again
|
||||
inserted_something := true;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
ait_const:
|
||||
inc(instrpos);
|
||||
end;
|
||||
p := tai(p.next);
|
||||
end;
|
||||
until not inserted_something;
|
||||
labelpositions.free;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
cai_cpu := taicpu;
|
||||
cai_align := tai_align;
|
||||
|
@ -1323,12 +1323,7 @@ procedure TCGMIPS.a_jmp_always(List: tasmlist; l: TAsmLabel);
|
||||
var
|
||||
ai : Taicpu;
|
||||
begin
|
||||
{ Always use A_J instead of A_BA to avoid
|
||||
out of range error, but not for PIC code }
|
||||
if (cs_create_pic in current_settings.moduleswitches) then
|
||||
ai := taicpu.op_sym(A_BA, l)
|
||||
else
|
||||
ai := taicpu.op_sym(A_J, l);
|
||||
ai := taicpu.op_sym(A_BA, l);
|
||||
list.concat(ai);
|
||||
{ Delay slot }
|
||||
list.Concat(TAiCpu.Op_none(A_NOP));
|
||||
@ -1337,12 +1332,7 @@ end;
|
||||
|
||||
procedure TCGMIPS.a_jmp_name(list: tasmlist; const s: string);
|
||||
begin
|
||||
{ Always use A_J instead of A_BA to avoid
|
||||
out of range error, but not for PIC code }
|
||||
if (cs_create_pic in current_settings.moduleswitches) then
|
||||
List.Concat(TAiCpu.op_sym(A_BA, current_asmdata.RefAsmSymbol(s)))
|
||||
else
|
||||
List.Concat(TAiCpu.op_sym(A_J, current_asmdata.RefAsmSymbol(s)));
|
||||
List.Concat(TAiCpu.op_sym(A_BA, current_asmdata.RefAsmSymbol(s)));
|
||||
{ Delay slot }
|
||||
list.Concat(TAiCpu.Op_none(A_NOP));
|
||||
end;
|
||||
|
@ -32,12 +32,10 @@ interface
|
||||
|
||||
type
|
||||
tcgdataconstnode = class(tdataconstnode)
|
||||
function pass_1 : tnode;override;
|
||||
procedure pass_generate_code;override;
|
||||
end;
|
||||
|
||||
tcgrealconstnode = class(trealconstnode)
|
||||
function pass_1 : tnode;override;
|
||||
procedure pass_generate_code;override;
|
||||
end;
|
||||
|
||||
@ -50,12 +48,10 @@ interface
|
||||
end;
|
||||
|
||||
tcgstringconstnode = class(tstringconstnode)
|
||||
function pass_1 : tnode;override;
|
||||
procedure pass_generate_code;override;
|
||||
end;
|
||||
|
||||
tcgsetconstnode = class(tsetconstnode)
|
||||
function pass_1 : tnode;override;
|
||||
protected
|
||||
function emitvarsetconst: tasmsymbol; virtual;
|
||||
procedure handlevarsetconst;
|
||||
@ -68,7 +64,6 @@ interface
|
||||
end;
|
||||
|
||||
tcgguidconstnode = class(tguidconstnode)
|
||||
function pass_1 : tnode;override;
|
||||
procedure pass_generate_code;override;
|
||||
end;
|
||||
|
||||
@ -79,7 +74,7 @@ implementation
|
||||
globtype,widestr,systems,
|
||||
verbose,globals,cutils,
|
||||
symconst,symdef,aasmtai,aasmdata,aasmcpu,defutil,
|
||||
procinfo,cpuinfo,cpubase,
|
||||
cpuinfo,cpubase,
|
||||
cgbase,cgobj,cgutils,
|
||||
ncgutil, cclasses,asmutils,tgobj
|
||||
;
|
||||
@ -89,20 +84,6 @@ implementation
|
||||
TCGREALCONSTNODE
|
||||
*****************************************************************************}
|
||||
|
||||
|
||||
procedure needs_got_for_pic;
|
||||
begin
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
assigned(current_procinfo) then
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
end;
|
||||
|
||||
function tcgdataconstnode.pass_1 : tnode;
|
||||
begin
|
||||
pass_1:=inherited pass_1;
|
||||
needs_got_for_pic;
|
||||
end;
|
||||
|
||||
procedure tcgdataconstnode.pass_generate_code;
|
||||
var
|
||||
l : tasmlabel;
|
||||
@ -127,12 +108,6 @@ implementation
|
||||
TCGREALCONSTNODE
|
||||
*****************************************************************************}
|
||||
|
||||
function tcgrealconstnode.pass_1 : tnode;
|
||||
begin
|
||||
pass_1:=inherited pass_1;
|
||||
needs_got_for_pic;
|
||||
end;
|
||||
|
||||
procedure tcgrealconstnode.pass_generate_code;
|
||||
{ I suppose the parser/pass_1 must make sure the generated real }
|
||||
{ constants are actually supported by the target processor? (JM) }
|
||||
@ -280,12 +255,6 @@ implementation
|
||||
TCGSTRINGCONSTNODE
|
||||
*****************************************************************************}
|
||||
|
||||
function tcgstringconstnode.pass_1 : tnode;
|
||||
begin
|
||||
pass_1:=inherited pass_1;
|
||||
needs_got_for_pic;
|
||||
end;
|
||||
|
||||
procedure tcgstringconstnode.pass_generate_code;
|
||||
var
|
||||
lastlabel: tasmlabofs;
|
||||
@ -420,12 +389,6 @@ implementation
|
||||
{*****************************************************************************
|
||||
TCGSETCONSTNODE
|
||||
*****************************************************************************}
|
||||
function tcgsetconstnode.pass_1 : tnode;
|
||||
begin
|
||||
pass_1:=inherited pass_1;
|
||||
needs_got_for_pic;
|
||||
end;
|
||||
|
||||
|
||||
function tcgsetconstnode.emitvarsetconst: tasmsymbol;
|
||||
type
|
||||
@ -560,12 +523,6 @@ implementation
|
||||
TCGGUIDCONSTNODE
|
||||
*****************************************************************************}
|
||||
|
||||
function tcgguidconstnode.pass_1 : tnode;
|
||||
begin
|
||||
pass_1:=inherited pass_1;
|
||||
needs_got_for_pic;
|
||||
end;
|
||||
|
||||
procedure tcgguidconstnode.pass_generate_code;
|
||||
var
|
||||
tmplabel : TAsmLabel;
|
||||
@ -595,5 +552,4 @@ begin
|
||||
csetconstnode:=tcgsetconstnode;
|
||||
cnilnode:=tcgnilnode;
|
||||
cguidconstnode:=tcgguidconstnode;
|
||||
global_used:=@needs_got_for_pic;
|
||||
end.
|
||||
|
@ -413,9 +413,6 @@ implementation
|
||||
procedure new_exception(list:TAsmList;const t:texceptiontemps;exceptlabel:tasmlabel);
|
||||
var
|
||||
paraloc1,paraloc2,paraloc3 : tcgpara;
|
||||
{$ifdef MIPS}
|
||||
sbl : tasmlabel;
|
||||
{$endif MIPS}
|
||||
begin
|
||||
paraloc1.init;
|
||||
paraloc2.init;
|
||||
@ -443,14 +440,7 @@ implementation
|
||||
cg.alloccpuregisters(list,R_INTREGISTER,[RS_FUNCTION_RESULT_REG]);
|
||||
|
||||
cg.g_exception_reason_save(list, t.reasonbuf);
|
||||
{$ifdef MIPS}
|
||||
current_asmdata.getjumplabel(sbl);
|
||||
cg.a_cmp_const_reg_label(list,OS_S32,OC_EQ,0,cg.makeregsize(list,NR_FUNCTION_RESULT_REG,OS_S32),sbl);
|
||||
cg.a_jmp_always(list,exceptlabel);
|
||||
cg.a_label(list,sbl);
|
||||
{$else not MIPS}
|
||||
cg.a_cmp_const_reg_label(list,OS_S32,OC_NE,0,cg.makeregsize(list,NR_FUNCTION_RESULT_REG,OS_S32),exceptlabel);
|
||||
{$endif not MIPS}
|
||||
cg.a_cmp_const_reg_label(list,OS_S32,OC_NE,0,cg.makeregsize(list,NR_FUNCTION_RESULT_REG,OS_S32),exceptlabel);
|
||||
cg.dealloccpuregisters(list,R_INTREGISTER,[RS_FUNCTION_RESULT_REG]);
|
||||
paraloc1.done;
|
||||
paraloc2.done;
|
||||
|
@ -116,7 +116,7 @@ implementation
|
||||
opttail,
|
||||
optcse,optloop,
|
||||
optutils
|
||||
{$if defined(arm) or defined(powerpc) or defined(powerpc64) or defined(avr)}
|
||||
{$if defined(arm) or defined(avr) or defined(fpc_compiler_has_fixup_jmps)}
|
||||
,aasmcpu
|
||||
{$endif arm}
|
||||
{$ifndef NOOPT}
|
||||
@ -1493,7 +1493,7 @@ implementation
|
||||
current_filepos:=exitpos;
|
||||
hlcg.gen_proc_symbol_end(templist);
|
||||
aktproccode.concatlist(templist);
|
||||
{$if defined(POWERPC) or defined(POWERPC64)}
|
||||
{$ifdef fpc_compiler_has_fixup_jmps}
|
||||
fixup_jmps(aktproccode);
|
||||
{$endif}
|
||||
{ insert line debuginfo }
|
||||
|
Loading…
Reference in New Issue
Block a user