+ PIC support for darwin/ppc32 (-Cg works now, no regressions in test

suite compiled with -Cg compared to without -Cg)
  + support for using a virtual register as PIC/got base register
  * moved got loading code from ncgutil to cgobj/cgcpu (can't test whether
    it didn't break anything under linux/i386, because "make cycle OPT=-Cg"
    was already broken due to the *prt*.as -> si_*.pp changes)

git-svn-id: trunk@8651 -
This commit is contained in:
Jonas Maebe 2007-09-26 16:41:32 +00:00
parent 70c2414daa
commit 335bc9fd46
13 changed files with 357 additions and 138 deletions

View File

@ -376,7 +376,10 @@ implementation
{ they don't work and gcc doesn't use them either... }
system_powerpc_darwin,
system_powerpc64_darwin:
AsmWriteln('__TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16');
if (cs_create_pic in current_settings.moduleswitches) then
AsmWriteln('__TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32')
else
AsmWriteln('__TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16');
system_i386_darwin:
AsmWriteln('__IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5');
{ darwin/x86-64 uses RIP-based GOT addressing }

View File

@ -70,7 +70,7 @@ unit cgobj;
{# Clean up the register allocators needed for the codegenerator.}
procedure done_register_allocators;virtual;
{# Set whether live_start or live_end should be updated when allocating registers, needed when e.g. generating initcode after the rest of the code. }
procedure set_regalloc_extend_backwards(b: boolean);
procedure set_regalloc_live_range_direction(dir: TRADirection);
{$ifdef flowgraph}
procedure init_flowgraph;
@ -479,6 +479,9 @@ unit cgobj;
The default implementation issues a jump instruction to the external name. }
procedure g_external_wrapper(list : TAsmList; procdef: tprocdef; const externalname: string); virtual;
{ initialize the pic/got register }
procedure g_maybe_got_init(list: TAsmList); virtual;
protected
procedure get_subsetref_load_info(const sref: tsubsetreference; out loadsize: tcgsize; out extra_load: boolean);
procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); virtual;
@ -769,14 +772,14 @@ implementation
end;
procedure tcg.set_regalloc_extend_backwards(b: boolean);
procedure tcg.set_regalloc_live_range_direction(dir: TRADirection);
var
rt : tregistertype;
begin
for rt:=low(rg) to high(rg) do
begin
if assigned(rg[rt]) then
rg[rt].extend_live_range_backwards := b;
rg[rt].live_range_direction:=dir;
end;
end;
@ -3733,7 +3736,7 @@ implementation
l:=current_asmdata.getasmsymbol('L'+symname+'$non_lazy_ptr');
if not(assigned(l)) then
begin
l:=current_asmdata.DefineAsmSymbol('L'+symname+'$non_lazy_ptr',AB_COMMON,AT_DATA);
l:=current_asmdata.DefineAsmSymbol('L'+symname+'$non_lazy_ptr',AB_LOCAL,AT_DATA);
current_asmdata.asmlists[al_picdata].concat(tai_symbol.create(l,0));
current_asmdata.asmlists[al_picdata].concat(tai_const.create_indirect_sym(current_asmdata.RefAsmSymbol(symname)));
{$ifdef cpu64bit}
@ -3752,6 +3755,10 @@ implementation
end;
procedure tcg.g_maybe_got_init(list: TAsmList);
begin
end;
{*****************************************************************************
TCG64
*****************************************************************************}

View File

@ -345,6 +345,10 @@ interface
s64comp,s64currency,s128real
);
type
{ register allocator live range extension direction }
TRADirection = (rad_forward, rad_backwards, rad_backwards_reinit);
type
TIDString = string[maxidlen];

View File

@ -52,6 +52,7 @@ unit cgcpu;
procedure g_exception_reason_save_const(list : TAsmList; const href : treference; a: aint);override;
procedure g_exception_reason_load(list : TAsmList; const href : treference);override;
procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
procedure g_maybe_got_init(list: TAsmList); override;
end;
tcg64f386 = class(tcg64f32)
@ -485,6 +486,23 @@ unit cgcpu;
end;
procedure g_maybe_got_init(list: TAsmList);
begin
{ allocate PIC register }
if (cs_create_pic in current_settings.moduleswitches) and
(tf_pic_uses_got in target_info.flags) and
(pi_needs_got in current_procinfo.flags) and
not(po_kylixlocal in current_procinfo.procdef.procoptions) then
begin
current_module.requires_ebx_pic_helper:=true;
cg.a_call_name_static(list,'fpc_geteipasebx');
list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),0,NR_PIC_OFFSET_REG));
list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil));
{ ecx could be used in leave procedures }
current_procinfo.got:=NR_EBX;
end;
end;
procedure tcg386.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
{

View File

@ -150,7 +150,6 @@ interface
function getprocalign : shortint;
procedure gen_pic_helpers(list : TAsmList);
procedure gen_got_load(list : TAsmList);
implementation
@ -2142,27 +2141,6 @@ implementation
end;
procedure gen_got_load(list : TAsmList);
begin
{ if loading got is necessary for more cpus, it can be moved
to the cg }
{$ifdef i386}
{ allocate PIC register }
if (cs_create_pic in current_settings.moduleswitches) and
(tf_pic_uses_got in target_info.flags) and
(pi_needs_got in current_procinfo.flags) and
not(po_kylixlocal in current_procinfo.procdef.procoptions) then
begin
current_module.requires_ebx_pic_helper:=true;
cg.a_call_name_static(list,'fpc_geteipasebx');
list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),0,NR_PIC_OFFSET_REG));
list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil));
{ ecx could be used in leave procedures }
current_procinfo.got:=NR_EBX;
end;
{$endif i386}
end;
{****************************************************************************
External handling
****************************************************************************}
@ -2786,7 +2764,7 @@ implementation
href : treference;
{$endif i386}
begin
{ if other cpus require such helpers as well, it can be solved more cleaner }
{ if other cpus require such helpers as well, it can be solved more cleanly }
{$ifdef i386}
if current_module.requires_ebx_pic_helper then
begin

View File

@ -889,9 +889,7 @@ const
var regcounter,firstregfpu,firstregint: TSuperRegister;
href : treference;
usesfpr,usesgpr,gotgot : boolean;
{ cond : tasmcond;
instr : taicpu; }
usesfpr,usesgpr : boolean;
begin
{ CR and LR only have to be saved in case they are modified by the current }
@ -905,8 +903,7 @@ const
if not(po_assembler in current_procinfo.procdef.procoptions) then
begin
{ save link register? }
if (pi_do_call in current_procinfo.flags) or
([cs_lineinfo,cs_debuginfo,cs_profile] * current_settings.moduleswitches <> []) then
if save_lr_in_prologue then
begin
a_reg_alloc(list,NR_R0);
{ save return address... }
@ -950,20 +947,8 @@ const
end;
end;
{ no GOT pointer loaded yet }
gotgot:=false;
if usesfpr then
begin
{ save floating-point registers
if (cs_create_pic in current_settings.moduleswitches) and not(usesgpr) then
begin
a_call_name(current_asmdata.RefAsmSymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)+'_g'));
gotgot:=true;
end
else
a_call_name(current_asmdata.RefAsmSymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)));
}
reference_reset_base(href,NR_R1,-8);
for regcounter:=firstregfpu to RS_F31 do
begin
@ -980,15 +965,6 @@ const
{ save gprs and fetch GOT pointer }
if usesgpr then
begin
{
if cs_create_pic in current_settings.moduleswitches then
begin
a_call_name(current_asmdata.RefAsmSymbol('_savegpr_'+tostr(ord(firstreggpr)-ord(R_14)+14)+'_g'));
gotgot:=true;
end
else
a_call_name(current_asmdata.RefAsmSymbol('_savegpr_'+tostr(ord(firstreggpr)-ord(R_14)+14)))
}
if (firstregint <= RS_R22) or
((cs_opt_size in current_settings.optimizerswitches) and
{ with RS_R30 it's also already smaller, but too big a speed trade-off to make }
@ -1010,34 +986,6 @@ const
{ if (tppcprocinfo(current_procinfo).needs_frame_pointer) then }
{ a_reg_dealloc(list,NR_R12); }
{ if we didn't get the GOT pointer till now, we've to calculate it now }
(*
if not(gotgot) and (pi_needs_got in current_procinfo.flags) then
case target_info.system of
system_powerpc_darwin:
begin
list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_LR));
fillchar(cond,sizeof(cond),0);
cond.simple:=false;
cond.bo:=20;
cond.bi:=31;
instr:=taicpu.op_sym(A_BCL,current_procinfo.CurrGOTLabel);
instr.setcondition(cond);
list.concat(instr);
a_label(list,current_procinfo.CurrGOTLabel);
list.concat(taicpu.op_reg_reg(A_MFSPR,current_procinfo.got,NR_LR));
list.concat(taicpu.op_reg_reg(A_MTSPR,NR_LR,NR_R0));
end;
else
begin
a_reg_alloc(list,NR_R31);
{ place GOT ptr in r31 }
list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R31,NR_LR));
end;
end;
*)
if (not nostackframe) and
tppcprocinfo(current_procinfo).needstackframe and
(localsize <> 0) then
@ -1052,9 +1000,17 @@ const
reference_reset_base(href,NR_STACK_POINTER_REG,0);
{ can't use getregisterint here, the register colouring }
{ is already done when we get here }
href.index := NR_R11;
{ R12 may hold previous stack pointer, R11 may be in }
{ use as got => use R0 (but then we can't use }
{ a_load_const_reg) }
href.index := NR_R0;
a_reg_alloc(list,href.index);
a_load_const_reg(list,OS_S32,-localsize,href.index);
list.concat(taicpu.op_reg_const(A_LI,NR_R0,smallint((-localsize) and $ffff)));
if (smallint((-localsize) and $ffff) < 0) then
{ upper 16 bits are now $ffff -> xor with inverse }
list.concat(taicpu.op_reg_reg_const(A_XORIS,NR_R0,NR_R0,word(not(((-localsize) shr 16) and $ffff))))
else
list.concat(taicpu.op_reg_reg_const(A_ORIS,NR_R0,NR_R0,word(((-localsize) shr 16) and $ffff)));
a_load_store(list,A_STWUX,NR_STACK_POINTER_REG,href);
a_reg_dealloc(list,href.index);
end;
@ -1709,9 +1665,25 @@ const
if (target_info.system = system_powerpc_darwin) and
assigned(ref.symbol) and
(ref.symbol.bind = AB_EXTERNAL) then
not assigned(ref.relsymbol) and
((ref.symbol.bind = AB_EXTERNAL) or
(cs_create_pic in current_settings.moduleswitches))then
begin
tmpreg := g_indirect_sym_load(list,ref.symbol.name);
if (ref.symbol.bind = AB_EXTERNAL) or
((cs_create_pic in current_settings.moduleswitches) and
(ref.symbol.bind in [AB_COMMON,AB_GLOBAL])) then
begin
tmpreg := g_indirect_sym_load(list,ref.symbol.name);
ref.symbol:=nil;
end
else
begin
include(current_procinfo.flags,pi_needs_got);
tmpreg := current_procinfo.got;
if assigned(ref.relsymbol) then
internalerror(2007093501);
ref.relsymbol := current_procinfo.CurrGOTLabel;
end;
if (ref.base = NR_NO) then
ref.base := tmpreg
else if (ref.index = NR_NO) then
@ -1721,7 +1693,6 @@ const
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
ref.base := tmpreg;
end;
ref.symbol := nil;
end;
if (ref.base = NR_NO) then

View File

@ -29,7 +29,7 @@ unit cpupi;
uses
cutils,globtype,
cgbase,
cgbase,aasmdata,
procinfo,cpuinfo,psub;
type
@ -43,6 +43,7 @@ unit cpupi;
function calc_stackframe_size:longint;override;
function uses_stack_temps: boolean;
procedure allocate_got_register(list: TAsmList);override;
private
first_save_int_reg, first_save_fpu_reg: tsuperregister;
public
@ -58,7 +59,7 @@ unit cpupi;
uses
globals,systems,
cpubase,
aasmtai,aasmdata,
aasmtai,
tgobj,cgobj,
symconst,symsym,paramgr,symutil,symtable,
verbose;
@ -184,7 +185,17 @@ unit cpupi;
else
begin
result := align(tg.lasttemp,16);
needstackframe:=result<>0;
needstackframe := result<>0;
end;
end;
procedure tppcprocinfo.allocate_got_register(list: TAsmList);
begin
if (target_info.system = system_powerpc_darwin) and
(cs_create_pic in current_settings.moduleswitches) then
begin
got := cg.getaddressregister(list);
end;
end;

View File

@ -140,6 +140,8 @@ Unit rappcgas;
var
l : aint;
relsym: string;
asmsymtyp: tasmsymtype;
begin
Consume(AS_LPAREN);
@ -195,21 +197,51 @@ Unit rappcgas;
AS_ID:
Begin
ReadSym(oper);
{ add a constant expression? }
if (actasmtoken=AS_PLUS) then
begin
l:=BuildConstExpression(true,true);
case oper.opr.typ of
OPR_CONSTANT :
inc(oper.opr.val,l);
OPR_LOCAL :
inc(oper.opr.localsymofs,l);
OPR_REFERENCE :
inc(oper.opr.ref.offset,l);
else
internalerror(200309202);
end;
end;
case actasmtoken of
AS_PLUS:
begin
{ add a constant expression? }
l:=BuildConstExpression(true,true);
case oper.opr.typ of
OPR_CONSTANT :
inc(oper.opr.val,l);
OPR_LOCAL :
inc(oper.opr.localsymofs,l);
OPR_REFERENCE :
inc(oper.opr.ref.offset,l);
else
internalerror(200309202);
end;
end;
AS_MINUS:
begin
Consume(AS_MINUS);
BuildConstSymbolExpression(false,true,false,l,relsym,asmsymtyp);
if (relsym<>'') then
begin
if (oper.opr.typ = OPR_REFERENCE) then
oper.opr.ref.relsymbol:=current_asmdata.RefAsmSymbol(relsym)
else
begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end
end
else
begin
case oper.opr.typ of
OPR_CONSTANT :
dec(oper.opr.val,l);
OPR_LOCAL :
dec(oper.opr.localsymofs,l);
OPR_REFERENCE :
dec(oper.opr.ref.offset,l);
else
internalerror(2007092601);
end;
end;
end;
end;
Consume(AS_RPAREN);
if actasmtoken=AS_AT then
ReadAt(oper);

View File

@ -61,6 +61,8 @@ unit cgppc;
procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
procedure g_maybe_got_init(list: TAsmList); override;
protected
function get_darwin_call_stub(const s: string): tasmsymbol;
procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override;
@ -77,6 +79,8 @@ unit cgppc;
{ represented by a 16 bit immediate as required by some PowerPC }
{ instructions }
function hasLargeOffset(const ref : TReference) : Boolean; inline;
function save_lr_in_prologue: boolean;
end;
const
@ -98,6 +102,14 @@ unit cgppc;
end;
function tcgppcgen.save_lr_in_prologue: boolean;
begin
result:=
((pi_do_call in current_procinfo.flags) or
([cs_lineinfo,cs_debuginfo,cs_profile] * current_settings.moduleswitches <> []));
end;
procedure tcgppcgen.a_param_const(list: TAsmList; size: tcgsize; a: aint; const
paraloc: tcgpara);
var
@ -145,11 +157,49 @@ unit cgppc;
end;
procedure tcgppcgen.g_maybe_got_init(list: TAsmList);
var
instr: taicpu;
cond: tasmcond;
savedlr: boolean;
begin
if not(po_assembler in current_procinfo.procdef.procoptions) then
begin
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
case target_info.system of
system_powerpc_darwin:
begin
savedlr:=save_lr_in_prologue;
if not savedlr then
list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_LR));
fillchar(cond,sizeof(cond),0);
cond.simple:=false;
cond.bo:=20;
cond.bi:=31;
instr:=taicpu.op_sym(A_BCL,current_procinfo.CurrGOTLabel);
instr.setcondition(cond);
list.concat(instr);
a_label(list,current_procinfo.CurrGOTLabel);
a_reg_alloc(list,current_procinfo.got);
list.concat(taicpu.op_reg_reg(A_MFSPR,current_procinfo.got,NR_LR));
if not savedlr then
list.concat(taicpu.op_reg_reg(A_MTSPR,NR_LR,NR_R0));
end;
end;
end;
end;
function tcgppcgen.get_darwin_call_stub(const s: string): tasmsymbol;
var
stubname: string;
instr: taicpu;
href: treference;
l1: tasmsymbol;
localgotlab: tasmlabel;
cond: tasmcond;
stubalign: byte;
begin
{ function declared in the current unit? }
{ doesn't work correctly, because this will also return a hit if we }
@ -164,14 +214,36 @@ unit cgppc;
current_asmdata.asmlists[al_imports]:=TAsmList.create;
current_asmdata.asmlists[al_imports].concat(Tai_section.create(sec_stub,'',0));
current_asmdata.asmlists[al_imports].concat(Tai_align.Create(16));
if (cs_create_pic in current_settings.moduleswitches) then
stubalign:=32
else
stubalign:=16;
current_asmdata.asmlists[al_imports].concat(Tai_align.Create(stubalign));
result := current_asmdata.RefAsmSymbol(stubname);
current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(result,0));
current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
l1 := current_asmdata.RefAsmSymbol('L'+s+'$lazy_ptr');
reference_reset_symbol(href,l1,0);
href.refaddr := addr_higha;
current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LIS,NR_R11,href));
if (cs_create_pic in current_settings.moduleswitches) then
begin
current_asmdata.getjumplabel(localgotlab);
href.relsymbol:=localgotlab;
fillchar(cond,sizeof(cond),0);
cond.simple:=false;
cond.bo:=20;
cond.bi:=31;
current_asmdata.asmlists[al_imports].concat(taicpu.op_reg(A_MFLR,NR_R0));
instr:=taicpu.op_sym(A_BCL,localgotlab);
instr.setcondition(cond);
current_asmdata.asmlists[al_imports].concat(instr);
a_label(current_asmdata.asmlists[al_imports],localgotlab);
current_asmdata.asmlists[al_imports].concat(taicpu.op_reg(A_MFLR,NR_R11));
current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_reg_ref(A_ADDIS,NR_R11,NR_R11,href));
current_asmdata.asmlists[al_imports].concat(taicpu.op_reg(A_MTLR,NR_R0));
end
else
current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LIS,NR_R11,href));
href.refaddr := addr_low;
href.base := NR_R11;
{$ifndef cpu64bit}

View File

@ -116,6 +116,9 @@ unit procinfo;
{ Generate parameter information }
procedure generate_parameter_info;virtual;
{ Allocate got register }
procedure allocate_got_register(list: TAsmList);virtual;
end;
tcprocinfo = class of tprocinfo;
@ -194,4 +197,10 @@ implementation
end;
procedure tprocinfo.allocate_got_register(list: TAsmList);
begin
{ most os/cpu combo's don't use this yet, so not yet abstract }
end;
end.

View File

@ -872,6 +872,9 @@ implementation
set_first_temp_offset;
generate_parameter_info;
{ allocate got register if needed }
current_procinfo.allocate_got_register(aktproccode);
{ Allocate space in temp/registers for parast and localst }
current_filepos:=entrypos;
gen_alloc_symtable(aktproccode,procdef.parast);
@ -891,9 +894,10 @@ implementation
current_filepos:=entrypos;
{ record which registers are allocated here, since all code }
{ allocating registers comes after it }
cg.set_regalloc_extend_backwards(true);
cg.set_regalloc_live_range_direction(rad_backwards);
gen_load_para_value(templist);
cg.set_regalloc_extend_backwards(false);
cg.set_regalloc_live_range_direction(rad_forward);
{ caller paraloc info is also necessary in the stackframe_entry
code of the ppc (and possibly other processors) }
@ -918,7 +922,7 @@ implementation
current_filepos:=entrypos;
current_settings.localswitches:=entryswitches;
cg.set_regalloc_extend_backwards(true);
cg.set_regalloc_live_range_direction(rad_backwards);
gen_entry_code(templist);
aktproccode.insertlistafter(entry_asmnode.currenttai,templist);
@ -930,7 +934,7 @@ implementation
current_filepos:=exitpos;
current_settings.localswitches:=exitswitches;
cg.set_regalloc_extend_backwards(false);
cg.set_regalloc_live_range_direction(rad_forward);
gen_finalize_code(templist);
{ the finalcode must be concated if there was no position available,
@ -973,6 +977,14 @@ implementation
{ Free space in temp/registers for parast and localst, must be
done after gen_entry_code }
current_filepos:=exitpos;
{ make sure the got/pic register doesn't get freed in the }
{ middle of a loop }
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) and
(current_procinfo.got<>NR_NO) then
cg.a_reg_sync(aktproccode,current_procinfo.got);
gen_free_symtable(aktproccode,procdef.localst);
gen_free_symtable(aktproccode,procdef.parast);
@ -993,13 +1005,27 @@ implementation
aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist)
end;
{ load got if necessary }
cg.set_regalloc_extend_backwards(true);
{ this code (got loading) comes before everything which has }
{ already been generated, so reset the info about already }
{ backwards extended registers (so their live range can be }
{ extended backwards even further if needed) }
{ This code must be }
{ a) generated after do_secondpass has been called }
{ (because pi_needs_got may be set there) }
{ b) generated before register allocation, because the }
{ got/pic register can be a virtual one }
{ c) inserted before the entry code, because the entry }
{ code may need global symbols such as init rtti }
{ d) inserted after the stackframe allocation, because }
{ this register may have to be spilled }
cg.set_regalloc_live_range_direction(rad_backwards_reinit);
current_filepos:=entrypos;
gen_got_load(templist);
{ load got if necessary }
cg.g_maybe_got_init(templist);
aktproccode.insertlistafter(headertai,templist);
cg.set_regalloc_extend_backwards(false);
cg.set_regalloc_live_range_direction(rad_forward);
{ The procedure body is finished, we can now
allocate the registers }
@ -1011,6 +1037,10 @@ implementation
maintain location lists }
current_procinfo.procdef.parast.SymList.ForEachCall(@translate_registers,templist);
current_procinfo.procdef.localst.SymList.ForEachCall(@translate_registers,templist);
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) and
not(cs_no_regalloc in current_settings.globalswitches) then
cg.translate_register(current_procinfo.got);
{ Add save and restore of used registers }
current_filepos:=entrypos;

View File

@ -175,7 +175,7 @@ unit rgobj;
const r:Tsuperregisterset;
const spilltemplist:Tspill_temp_list): boolean;virtual;
private
do_extend_live_range_backwards: boolean;
int_live_range_direction: TRADirection;
{# First imaginary register.}
first_imaginary : Tsuperregister;
{# Highest register allocated until now.}
@ -236,9 +236,9 @@ unit rgobj;
procedure select_spill;
procedure assign_colours;
procedure clear_interferences(u:Tsuperregister);
procedure set_live_range_backwards(b: boolean);
procedure set_live_range_direction(dir: TRADirection);
public
property extend_live_range_backwards: boolean read do_extend_live_range_backwards write set_live_range_backwards;
property live_range_direction: TRADirection read int_live_range_direction write set_live_range_direction;
end;
const
@ -370,8 +370,9 @@ unit rgobj;
{ empty super register sets can cause very strange problems }
if high(Ausable)=-1 then
internalerror(200210181);
extend_live_range_backwards := false;
live_range_direction:=rad_forward;
supregset_reset(extended_backwards,false,high(tsuperregister));
supregset_reset(backwards_was_first,false,high(tsuperregister));
first_imaginary:=Afirst_imaginary;
maxreg:=Afirst_imaginary;
regtype:=Aregtype;
@ -678,16 +679,18 @@ unit rgobj;
end;
procedure trgobj.set_live_range_backwards(b: boolean);
procedure trgobj.set_live_range_direction(dir: TRADirection);
begin
if (b) then
if (dir in [rad_backwards,rad_backwards_reinit]) then
begin
if (dir=rad_backwards_reinit) then
supregset_reset(extended_backwards,false,high(tsuperregister));
int_live_range_direction:=rad_backwards;
{ new registers may be allocated }
supregset_reset(backwards_was_first,false,high(tsuperregister));
do_extend_live_range_backwards := true;
end
else
do_extend_live_range_backwards := false;
int_live_range_direction:=rad_forward;
end;
@ -704,7 +707,7 @@ unit rgobj;
if supreg>=first_imaginary then
with reginfo[supreg] do
begin
if not(extend_live_range_backwards) then
if (live_range_direction=rad_forward) then
begin
if not assigned(live_start) then
live_start:=instr;

View File

@ -75,12 +75,26 @@ const
fabs f1,f1
// load 2^32 in f2
{$ifndef macos}
{$ifdef FPC_PIC}
{$ifdef darwin}
mflr r0
bcl 20,31,.Lpiclab
.Lpiclab:
mflr r5
mtlr r0
addis r4,r5,(factor-.Lpiclab)@ha
lfd f2,(factor-.Lpiclab)@l(r4)
{$else darwin}
{$error Add pic code for linux/ppc32}
{$endif darwin}
{$else FPC_PIC}
lis r4,factor@ha
lfd f2,factor@l(r4)
{$else}
{$endif FPC_PIC}
{$else not macos}
lwz r4,factor(r2)
lfd f2,0(r4)
{$endif}
{$endif not macos}
// check if value is < 0
// f3 := d / 2^32;
fdiv f3,f1,f2
@ -96,12 +110,21 @@ const
xoris r0,r3,0x8000
stw r0,temp+4
{$ifndef macos}
{$ifdef FPC_PIC}
{$ifdef darwin}
addis r4,r5,(longint_to_real_helper-.Lpiclab)@ha
lfd f0,(longint_to_real_helper-.Lpiclab)@l(r4)
{$else darwin}
{$error Add pic code for linux/ppc32}
{$endif darwin}
{$else FPC_PIC}
lis r4,longint_to_real_helper@ha
lfd f0,longint_to_real_helper@l(r4)
{$else}
{$endif FPC_PIC}
{$else not macos}
lwz r4,longint_to_real_helper(r2)
lfd f0,0(r4)
{$endif}
{$endif not macos}
lfd f3,temp
fsub f3,f3,f0
@ -113,12 +136,21 @@ const
// load 2^31 in f2
{$ifndef macos}
{$ifdef FPC_PIC}
{$ifdef darwin}
addis r4,r5,(factor2-.Lpiclab)@ha
lfd f2,(factor2-.Lpiclab)@l(r4)
{$else darwin}
{$error Add pic code for linux/ppc32}
{$endif darwin}
{$else FPC_PIC}
lis r4,factor2@ha
lfd f2,factor2@l(r4)
{$else}
{$endif FPC_PIC}
{$else not macos}
lwz r4,factor2(r2)
lfd f2,0(r4)
{$endif}
{$endif not macos}
// subtract 2^31
fsub f3,f4,f2
@ -261,28 +293,54 @@ asm
xoris r3,r3,0x8000
stw r3,temp+4
{$ifndef macos}
{$ifdef FPC_PIC}
{$ifdef darwin}
mflr r0
bcl 20,31,.Lpiclab
.Lpiclab:
mflr r5
mtlr r0
addis r3,r5,(longint_to_real_helper-.Lpiclab)@ha
lfd f1,(longint_to_real_helper-.Lpiclab)@l(r3)
{$else darwin}
{$error Add pic code for linux/ppc32}
{$endif darwin}
{$else FPC_PIC}
lis r3,longint_to_real_helper@ha
lfd f1,longint_to_real_helper@l(r3)
{$else}
{$endif FPC_PIC}
{$else not macos}
lwz r3,longint_to_real_helper(r2)
lfd f1,0(r3)
{$endif}
{$endif not mac os}
lfd f0,temp
stw r4,temp+4
fsub f0,f0,f1
{$ifndef macos}
{$ifdef FPC_PIC}
{$ifdef darwin}
addis r4,r5,(cardinal_to_real_helper-.Lpiclab)@ha
lfd f1,(cardinal_to_real_helper-.Lpiclab)@l(r4)
addis r4,r5,(int_to_real_factor-.Lpiclab)@ha
lfd f3,temp
lfd f2,(int_to_real_factor-.Lpiclab)@l(r4)
{$else darwin}
{$error Add pic code for linux/ppc32}
{$endif darwin}
{$else FPC_PIC}
lis r4,cardinal_to_real_helper@ha
lfd f1,cardinal_to_real_helper@l(r4)
lis r4,int_to_real_factor@ha
lfd f3,temp
lfd f2,int_to_real_factor@l(r4)
{$else}
{$endif FPC_PIC}
{$else not macos}
lwz r4,cardinal_to_real_helper(r2)
lwz r3,int_to_real_factor(r2)
lfd f3,temp
lfd f1,0(r4)
lfd f2,0(r3)
{$endif}
{$endif not macos}
fsub f3,f3,f1
fmadd f1,f0,f2,f3
end;
@ -305,22 +363,45 @@ asm
stw r3,temp+4
lfd f0,temp
{$ifndef macos}
{$ifdef FPC_PIC}
{$ifdef darwin}
mflr r0
bcl 20,31,.Lpiclab
.Lpiclab:
mflr r5
mtlr r0
addis r3,r5,(cardinal_to_real_helper-.Lpiclab)@ha
lfd f1,(cardinal_to_real_helper-.Lpiclab)@l(r3)
{$else darwin}
{$error Add pic code for linux/ppc32}
{$endif darwin}
{$else FPC_PIC}
lis r3,cardinal_to_real_helper@ha
lfd f1,cardinal_to_real_helper@l(r3)
{$else}
{$endif FPC_PIC}
{$else not macos}
lwz r3,longint_to_real_helper(r2)
lfd f1,0(r3)
{$endif}
{$endif not macos}
stw r4,temp+4
fsub f0,f0,f1
lfd f3,temp
{$ifndef macos}
{$ifdef FPC_PIC}
{$ifdef darwin}
addis r4,r5,(int_to_real_factor-.Lpiclab)@ha
lfd f2,(int_to_real_factor-.Lpiclab)@l(r4)
{$else darwin}
{$error Add pic code for linux/ppc32}
{$endif darwin}
{$else FPC_PIC}
lis r4,int_to_real_factor@ha
lfd f2,int_to_real_factor@l(r4)
{$else}
{$endif FPC_PIC}
{$else not macos}
lwz r4,int_to_real_factor(r2)
lfd f2,0(r4)
{$endif}
{$endif not macos}
fsub f3,f3,f1
fmadd f1,f0,f2,f3
end;