mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-12 18:31:53 +02:00
+ 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:
parent
70c2414daa
commit
335bc9fd46
@ -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 }
|
||||
|
@ -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
|
||||
*****************************************************************************}
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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);
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user