+ PIC support for darwin/ppc64

* added {$PIC+} for darwin to all library tests

git-svn-id: trunk@8868 -
This commit is contained in:
Jonas Maebe 2007-10-20 20:14:45 +00:00
parent c77267e01f
commit 45b7358d81
10 changed files with 235 additions and 201 deletions

View File

@ -100,14 +100,6 @@ unit cgcpu;
{ the upper 24/16 bits of a register after an operation }
procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
{ Make sure ref is a valid reference for the PowerPC and sets the }
{ base to the value of the index if (base = R_NO). }
{ Returns true if the reference contained a base, index and an }
{ offset or symbol, in which case the base will have been changed }
{ to a tempreg (which has to be freed by the caller) containing }
{ the sum of part of the original reference }
function fixref(list: TAsmList; var ref: treference): boolean; override;
{ returns whether a reference can be used immediately in a powerpc }
{ instruction }
function issimpleref(const ref: treference): boolean;
@ -1656,69 +1648,6 @@ const
end;
function tcgppc.fixref(list: TAsmList; var ref: treference): boolean;
var
tmpreg: tregister;
begin
result := false;
if (target_info.system = system_powerpc_darwin) and
assigned(ref.symbol) and
not assigned(ref.relsymbol) and
((ref.symbol.bind = AB_EXTERNAL) or
(cs_create_pic in current_settings.moduleswitches))then
begin
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
ref.index := tmpreg
else
begin
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
ref.base := tmpreg;
end;
end;
if (ref.base = NR_NO) then
begin
ref.base := ref.index;
ref.index := NR_NO;
end;
if (ref.base <> NR_NO) then
begin
if (ref.index <> NR_NO) and
((ref.offset <> 0) or assigned(ref.symbol)) then
begin
result := true;
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
list.concat(taicpu.op_reg_reg_reg(
A_ADD,tmpreg,ref.base,ref.index));
ref.index := NR_NO;
ref.base := tmpreg;
end
end
else
if ref.index <> NR_NO then
internalerror(200208102);
end;
{ find out whether a is of the form 11..00..11b or 00..11...00. If }
{ that's the case, we can use rlwinm to do an AND operation }
function tcgppc.get_rlwi_const(a: aint; var l1, l2: longint): boolean;

View File

@ -107,16 +107,6 @@ type
procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
{ Make sure ref is a valid reference for the PowerPC and sets the }
{ base to the value of the index if (base = R_NO). }
{ Returns true if the reference contained a base, index and an }
{ offset or symbol, in which case the base will have been changed }
{ to a tempreg (which has to be freed by the caller) containing }
{ the sum of part of the original reference }
function fixref(list: TAsmList; var ref: treference): boolean; override;
function load_got_symbol(list : TAsmList; symbol : string) : tregister;
{ returns whether a reference can be used immediately in a powerpc }
{ instruction }
function issimpleref(const ref: treference): boolean;
@ -1397,7 +1387,8 @@ var
{ there are two ways to do this: manually, by generating a few "std" instructions,
or via the restore helper functions. The latter are selected by the -Og switch,
i.e. "optimize for size" }
if (cs_opt_size in current_settings.optimizerswitches) then begin
if (cs_opt_size in current_settings.optimizerswitches) and
(target_info.system <> system_powerpc64_darwin) then begin
mayNeedLRStore := false;
if ((fprcount > 0) and (gprcount > 0)) then begin
a_op_const_reg_reg(list, OP_SUB, OS_INT, 8 * fprcount, NR_R1, NR_R12);
@ -1450,10 +1441,10 @@ begin
{ determine whether we need to save the link register }
needslinkreg :=
not(nostackframe) and
(((not (po_assembler in current_procinfo.procdef.procoptions)) and
((pi_do_call in current_procinfo.flags) or (cs_profile in init_settings.moduleswitches))) or
((cs_opt_size in current_settings.optimizerswitches) and ((fprcount > 0) or (gprcount > 0))) or
([cs_lineinfo, cs_debuginfo] * current_settings.moduleswitches <> []));
(save_lr_in_prologue or
((cs_opt_size in current_settings.optimizerswitches) and
((fprcount > 0) or
(gprcount > 0))));
a_reg_alloc(list, NR_STACK_POINTER_REG);
a_reg_alloc(list, NR_R0);
@ -1944,93 +1935,6 @@ begin
(ref.offset = 0)));
end;
function tcgppc.load_got_symbol(list: TAsmList; symbol : string) : tregister;
var
l: tasmsymbol;
ref: treference;
symname : string;
begin
l:=current_asmdata.getasmsymbol(symbol);
reference_reset_symbol(ref,l,0);
ref.base := NR_R2;
ref.refaddr := addr_pic;
result := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
{$IFDEF EXTDEBUG}
list.concat(tai_comment.create(strpnew('loading got reference for ' + symbol)));
{$ENDIF EXTDEBUG}
// cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result);
list.concat(taicpu.op_reg_ref(A_LD, result, ref));
end;
function tcgppc.fixref(list: TAsmList; var ref: treference): boolean;
var
tmpreg: tregister;
name : string;
begin
result := false;
{ Avoids recursion. }
if (ref.refaddr = addr_pic) then exit;
{$IFDEF EXTDEBUG}
list.concat(tai_comment.create(strpnew('fixref0 ' + ref2string(ref))));
{$ENDIF EXTDEBUG}
if (target_info.system = system_powerpc64_darwin) and
assigned(ref.symbol) and
(ref.symbol.bind = AB_EXTERNAL) then
begin
tmpreg := g_indirect_sym_load(list,ref.symbol.name);
if (ref.base = NR_NO) then
ref.base := tmpreg
else if (ref.index = NR_NO) then
ref.index := tmpreg
else
begin
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
ref.base := tmpreg;
end;
ref.symbol := nil;
end;
{ if we have to create PIC, add the symbol to the TOC/GOT }
if (target_info.system <> system_powerpc64_darwin) and
(cs_create_pic in current_settings.moduleswitches) and
(assigned(ref.symbol)) then begin
tmpreg := load_got_symbol(list, ref.symbol.name);
if (ref.base = NR_NO) then
ref.base := tmpreg
else if (ref.index = NR_NO) then
ref.index := tmpreg
else begin
a_op_reg_reg_reg(list, OP_ADD, OS_ADDR, ref.base, tmpreg, tmpreg);
ref.base := tmpreg;
end;
ref.symbol := nil;
{$IFDEF EXTDEBUG}
list.concat(tai_comment.create(strpnew('fixref-pic ' + ref2string(ref))));
{$ENDIF EXTDEBUG}
end;
if (ref.base = NR_NO) then begin
ref.base := ref.index;
ref.index := NR_NO;
end;
if (ref.base <> NR_NO) and (ref.index <> NR_NO) and
((ref.offset <> 0) or assigned(ref.symbol)) then begin
result := true;
tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
a_op_reg_reg_reg(list, OP_ADD, OS_ADDR, ref.base, ref.index, tmpreg);
ref.base := tmpreg;
ref.index := NR_NO;
end;
if (ref.index <> NR_NO) and (assigned(ref.symbol) or (ref.offset <> 0)) then
internalerror(2006010506);
{$IFDEF EXTDEBUG}
list.concat(tai_comment.create(strpnew('fixref1 ' + ref2string(ref))));
{$ENDIF EXTDEBUG}
end;
procedure tcgppc.a_load_store(list: TAsmList; op: tasmop; reg: tregister;
ref: treference);

View File

@ -28,7 +28,7 @@ unit cpupi;
interface
uses
cutils,
cutils,aasmdata,
procinfo, cpuinfo, psub;
type
@ -43,6 +43,8 @@ type
function calc_stackframe_size(numgpr, numfpr : longint): longint;
needs_frame_pointer : boolean;
procedure allocate_got_register(list: TAsmList); override;
end;
implementation
@ -50,8 +52,8 @@ implementation
uses
globtype, globals, systems,
cpubase, cgbase,
aasmtai,aasmdata,
tgobj,
aasmtai,
tgobj,cgobj,
symconst, symsym, paramgr, symutil, symtable,
verbose;
@ -111,6 +113,16 @@ begin
end;
end;
procedure tppcprocinfo.allocate_got_register(list: TAsmList);
begin
if (target_info.system = system_powerpc64_darwin) and
(cs_create_pic in current_settings.moduleswitches) then
begin
got := cg.getaddressregister(list);
end;
end;
begin
cprocinfo := tppcprocinfo;
end.

View File

@ -151,6 +151,8 @@ procedure tppcattreader.BuildReference(oper: tppcoperand);
var
l: aint;
relsym: string;
asmsymtyp: tasmsymtype;
begin
Consume(AS_LPAREN);
@ -207,20 +209,50 @@ begin
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;
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

View File

@ -66,7 +66,13 @@ unit cgppc;
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;
function fixref(list: TAsmList; var ref: treference): boolean; virtual; abstract;
{ Make sure ref is a valid reference for the PowerPC and sets the }
{ base to the value of the index if (base = R_NO). }
{ Returns true if the reference contained a base, index and an }
{ offset or symbol, in which case the base will have been changed }
{ to a tempreg (which has to be freed by the caller) containing }
{ the sum of part of the original reference }
function fixref(list: TAsmList; var ref: treference): boolean;
{ contains the common code of a_load_reg_ref and a_load_ref_reg }
procedure a_load_store(list:TAsmList;op: tasmop;reg:tregister;ref: treference);virtual;
@ -81,6 +87,8 @@ unit cgppc;
function hasLargeOffset(const ref : TReference) : Boolean; inline;
function save_lr_in_prologue: boolean;
function load_got_symbol(list : TAsmList; symbol : string) : tregister;
end;
const
@ -105,8 +113,10 @@ unit cgppc;
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 <> []));
(not (po_assembler in current_procinfo.procdef.procoptions) and
((pi_do_call in current_procinfo.flags) or
(cs_profile in init_settings.moduleswitches))) or
([cs_lineinfo,cs_debuginfo] * current_settings.moduleswitches <> []);
end;
@ -168,7 +178,8 @@ unit cgppc;
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:
system_powerpc_darwin,
system_powerpc64_darwin:
begin
savedlr:=save_lr_in_prologue;
if not savedlr then
@ -185,7 +196,7 @@ unit cgppc;
list.concat(taicpu.op_reg_reg(A_MFSPR,current_procinfo.got,NR_LR));
if not savedlr or
{ in the following case lr is saved, but not restored }
{ (happens e.g. when generating debug info for leaf }
{ (happens e.g. when generating debug info for leaf }
{ procedures) }
not(pi_do_call in current_procinfo.flags) then
list.concat(taicpu.op_reg_reg(A_MTSPR,NR_LR,NR_R0));
@ -687,6 +698,125 @@ unit cgppc;
end;
function tcgppcgen.load_got_symbol(list: TAsmList; symbol : string) : tregister;
var
l: tasmsymbol;
ref: treference;
begin
if (target_info.system <> system_powerpc64_linux) then
internalerror(2007102010);
l:=current_asmdata.getasmsymbol(symbol);
reference_reset_symbol(ref,l,0);
ref.base := NR_R2;
ref.refaddr := addr_pic;
result := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
{$IFDEF EXTDEBUG}
list.concat(tai_comment.create(strpnew('loading got reference for ' + symbol)));
{$ENDIF EXTDEBUG}
// cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result);
{$ifdef cpu64bit}
list.concat(taicpu.op_reg_ref(A_LD, result, ref));
{$else cpu64bit}
list.concat(taicpu.op_reg_ref(A_LWZ, result, ref));
{$endif cpu64bit}
end;
function tcgppcgen.fixref(list: TAsmList; var ref: treference): boolean;
var
tmpreg: tregister;
begin
result := false;
{ Avoid recursion. }
if (ref.refaddr = addr_pic) then
exit;
{$IFDEF EXTDEBUG}
list.concat(tai_comment.create(strpnew('fixref0 ' + ref2string(ref))));
{$ENDIF EXTDEBUG}
if (target_info.system in [system_powerpc_darwin,system_powerpc64_darwin]) and
assigned(ref.symbol) and
not assigned(ref.relsymbol) and
((ref.symbol.bind = AB_EXTERNAL) or
(cs_create_pic in current_settings.moduleswitches))then
begin
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
ref.index := tmpreg
else
begin
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
ref.base := tmpreg;
end;
end;
{ if we have to create PIC, add the symbol to the TOC/GOT }
if (target_info.system = system_powerpc64_linux) and
(cs_create_pic in current_settings.moduleswitches) and
(assigned(ref.symbol)) then
begin
tmpreg := load_got_symbol(list, ref.symbol.name);
if (ref.base = NR_NO) then
ref.base := tmpreg
else if (ref.index = NR_NO) then
ref.index := tmpreg
else begin
a_op_reg_reg_reg(list, OP_ADD, OS_ADDR, ref.base, tmpreg, tmpreg);
ref.base := tmpreg;
end;
ref.symbol := nil;
{$IFDEF EXTDEBUG}
list.concat(tai_comment.create(strpnew('fixref-pic ' + ref2string(ref))));
{$ENDIF EXTDEBUG}
end;
if (ref.base = NR_NO) then
begin
ref.base := ref.index;
ref.index := NR_NO;
end;
if (ref.base <> NR_NO) then
begin
if (ref.index <> NR_NO) and
((ref.offset <> 0) or assigned(ref.symbol)) then
begin
result := true;
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
list.concat(taicpu.op_reg_reg_reg(
A_ADD,tmpreg,ref.base,ref.index));
ref.index := NR_NO;
ref.base := tmpreg;
end
end;
if (ref.index <> NR_NO) and
(assigned(ref.symbol) or
(ref.offset <> 0)) then
internalerror(200208102);
{$IFDEF EXTDEBUG}
list.concat(tai_comment.create(strpnew('fixref1 ' + ref2string(ref))));
{$ENDIF EXTDEBUG}
end;
procedure tcgppcgen.a_load_store(list:TAsmList;op: tasmop;reg:tregister;
ref: treference);

View File

@ -99,11 +99,21 @@ asm
ori r4, r4, longint_to_real_helper@highera
sldi r4, r4, 32
oris r4, r4, longint_to_real_helper@ha
{$else darwin}
lis r4, longint_to_real_helper@ha
{$endif darwin}
lfd f4, longint_to_real_helper@l(r4)
{$else not darwin}
{$ifdef FPC_PIC}
mflr r0
bcl 20,31,.Lpiclab
.Lpiclab:
mflr r5
mtlr r0
addis r4,r5,(longint_to_real_helper-.Lpiclab)@ha
lfd f2,(longint_to_real_helper-.Lpiclab)@l(r4)
{$else FPC_PIC}
lis r4, longint_to_real_helper@ha
lfd f4, longint_to_real_helper@l(r4)
{$endif FPC_PIC}
{$endif not darwin}
rldicl r4,r3,32,32 // isolate high half
rldicl r0,r3,0,32 // isolate low half
std r4,temp1 // store dword both
@ -114,4 +124,4 @@ asm
fcfid f0,f0 // fpu int (no rnd)
fmadd f0,f4,f2,f0 // (2**32)*high+low (only add can rnd)
end;

View File

@ -1,6 +1,10 @@
{ %NORUN }
{ %SKIPTARGET=macos }
{$ifdef darwin}
{$PIC+}
{$endif darwin}
{$ifdef CPUX86_64}
{$ifndef WINDOWS}
{$PIC+}
@ -32,7 +36,7 @@ const
procedure Test;export;
begin
// writeln('Hoi');
writeln('Hoi');
end;
exports

View File

@ -1,6 +1,10 @@
{ %NORUN }
{ %SKIPTARGET=macos, win64 }
{$ifdef darwin}
{$PIC+}
{$endif darwin}
{$ifdef CPUX86_64}
{$ifndef WINDOWS}
{$PIC+}

View File

@ -2,6 +2,11 @@
{ %cpu=x86_64,i386,powerpc,sparc}
{ %skiptarget = go32v2,macos }
{ execute this test only on reasonable fast cpus }
{$ifdef darwin}
{$PIC+}
{$endif darwin}
library lib;
const
s =

View File

@ -4,6 +4,10 @@
{$ifdef fpc}{$mode delphi}{$endif}
{$ifdef darwin}
{$PIC+}
{$endif darwin}
resourcestring
wurst = 'jo' deprecated;