|
@@ -61,9 +61,13 @@ unit cgppc;
|
|
procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
|
|
procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
|
|
|
|
|
|
procedure g_maybe_got_init(list: TAsmList); override;
|
|
procedure g_maybe_got_init(list: TAsmList); override;
|
|
|
|
+
|
|
|
|
+ function g_indirect_sym_load(list:TAsmList;const symname: string; const flags: tindsymflags): tregister; override;
|
|
{ Transform unsupported methods into Internal errors }
|
|
{ Transform unsupported methods into Internal errors }
|
|
procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
|
|
procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
|
|
procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
|
|
procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
|
|
|
|
+
|
|
|
|
+ function get_aix_toc_sym(const symname: string; const flags: tindsymflags):tasmsymbol;
|
|
protected
|
|
protected
|
|
function get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
|
|
function get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
|
|
procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override;
|
|
procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override;
|
|
@@ -89,7 +93,7 @@ unit cgppc;
|
|
|
|
|
|
function save_lr_in_prologue: boolean;
|
|
function save_lr_in_prologue: boolean;
|
|
|
|
|
|
- function load_got_symbol(list : TAsmList; symbol : string) : tregister;
|
|
|
|
|
|
+ function load_got_symbol(list : TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
|
|
end;
|
|
end;
|
|
|
|
|
|
const
|
|
const
|
|
@@ -251,6 +255,18 @@ unit cgppc;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
+ function tcgppcgen.g_indirect_sym_load(list: TAsmList; const symname: string; const flags: tindsymflags): tregister;
|
|
|
|
+ begin
|
|
|
|
+ case target_info.system of
|
|
|
|
+ system_powerpc_aix,
|
|
|
|
+ system_powerpc64_aix:
|
|
|
|
+ result:=load_got_symbol(list,symname,flags);
|
|
|
|
+ else
|
|
|
|
+ result:=inherited;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
function tcgppcgen.get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
|
|
function tcgppcgen.get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
|
|
var
|
|
var
|
|
stubname: string;
|
|
stubname: string;
|
|
@@ -351,13 +367,8 @@ unit cgppc;
|
|
tmpref.base := NR_RTOC;
|
|
tmpref.base := NR_RTOC;
|
|
list.concat(taicpu.op_reg_ref(A_LWZ,r,tmpref));
|
|
list.concat(taicpu.op_reg_ref(A_LWZ,r,tmpref));
|
|
|
|
|
|
- if ref2.offset <> 0 then
|
|
|
|
- begin
|
|
|
|
- reference_reset(tmpref,ref2.alignment);
|
|
|
|
- tmpref.offset := ref2.offset;
|
|
|
|
- tmpref.base:= r;
|
|
|
|
- list.concat(taicpu.op_reg_ref(A_LA,r,tmpref));
|
|
|
|
- end;
|
|
|
|
|
|
+ if ref2.offset<>0 then
|
|
|
|
+ a_op_const_reg(list,OP_ADD,OS_ADDR,ref2.offset,r);
|
|
end;
|
|
end;
|
|
|
|
|
|
if ref2.base <> NR_NO then
|
|
if ref2.base <> NR_NO then
|
|
@@ -686,14 +697,14 @@ unit cgppc;
|
|
href.offset := smallint(href.offset and $ffff);
|
|
href.offset := smallint(href.offset and $ffff);
|
|
end;
|
|
end;
|
|
a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11);
|
|
a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11);
|
|
- if (target_info.system = system_powerpc64_linux) then
|
|
|
|
|
|
+ if (target_info.system in ([system_powerpc64_linux]+systems_aix)) then
|
|
begin
|
|
begin
|
|
reference_reset_base(href, NR_R11, 0, sizeof(pint));
|
|
reference_reset_base(href, NR_R11, 0, sizeof(pint));
|
|
a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R11);
|
|
a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R11);
|
|
end;
|
|
end;
|
|
list.concat(taicpu.op_reg(A_MTCTR,NR_R11));
|
|
list.concat(taicpu.op_reg(A_MTCTR,NR_R11));
|
|
list.concat(taicpu.op_none(A_BCTR));
|
|
list.concat(taicpu.op_none(A_BCTR));
|
|
- if (target_info.system = system_powerpc64_linux) then
|
|
|
|
|
|
+ if (target_info.system in ([system_powerpc64_linux]+systems_aix)) then
|
|
list.concat(taicpu.op_none(A_NOP));
|
|
list.concat(taicpu.op_none(A_NOP));
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -747,24 +758,25 @@ unit cgppc;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
- function tcgppcgen.load_got_symbol(list: TAsmList; symbol : string) : tregister;
|
|
|
|
|
|
+ function tcgppcgen.load_got_symbol(list: TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
|
|
var
|
|
var
|
|
l: tasmsymbol;
|
|
l: tasmsymbol;
|
|
ref: treference;
|
|
ref: treference;
|
|
begin
|
|
begin
|
|
- if (target_info.system <> system_powerpc64_linux) then
|
|
|
|
|
|
+ if target_info.system=system_powerpc64_linux then
|
|
|
|
+ l:=current_asmdata.getasmsymbol(symbol)
|
|
|
|
+ else if target_info.system in systems_aix then
|
|
|
|
+ l:=get_aix_toc_sym(symbol,flags)
|
|
|
|
+ else
|
|
internalerror(2007102010);
|
|
internalerror(2007102010);
|
|
- l:=current_asmdata.getasmsymbol(symbol);
|
|
|
|
reference_reset_symbol(ref,l,0,sizeof(pint));
|
|
reference_reset_symbol(ref,l,0,sizeof(pint));
|
|
- 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);
|
|
|
|
|
|
+ ref.base:=NR_RTOC;
|
|
|
|
+ if target_info.system in systems_aix then
|
|
|
|
+ ref.refaddr:=addr_pic_no_got
|
|
|
|
+ else
|
|
|
|
+ ref.refaddr:=addr_pic;
|
|
|
|
|
|
|
|
+ result := getaddressregister(list);
|
|
{$ifdef cpu64bitaddr}
|
|
{$ifdef cpu64bitaddr}
|
|
list.concat(taicpu.op_reg_ref(A_LD, result, ref));
|
|
list.concat(taicpu.op_reg_ref(A_LD, result, ref));
|
|
{$else cpu64bitaddr}
|
|
{$else cpu64bitaddr}
|
|
@@ -773,6 +785,34 @@ unit cgppc;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
+ function tcgppcgen.get_aix_toc_sym(const symname: string; const flags: tindsymflags): tasmsymbol;
|
|
|
|
+ var
|
|
|
|
+ nlsymname: string;
|
|
|
|
+ newsymname: ansistring;
|
|
|
|
+ begin
|
|
|
|
+ { all global symbol accesses always must be done via the TOC }
|
|
|
|
+ nlsymname:='LC..'+symname;
|
|
|
|
+ result:=current_asmdata.getasmsymbol(nlsymname);
|
|
|
|
+ if not assigned(result) then
|
|
|
|
+ begin
|
|
|
|
+ new_section(current_asmdata.AsmLists[al_picdata],sec_toc,'',sizeof(pint));
|
|
|
|
+ result:=current_asmdata.DefineAsmSymbol(nlsymname,AB_LOCAL,AT_DATA);
|
|
|
|
+ current_asmdata.asmlists[al_picdata].concat(tai_symbol.create(result,0));
|
|
|
|
+ { do not assign the result of these statements to result: the access
|
|
|
|
+ must be done via the LC..symname symbol; these are just to define
|
|
|
|
+ the symbol that's being accessed as either weak or not }
|
|
|
|
+ if not(is_weak in flags) then
|
|
|
|
+ current_asmdata.RefAsmSymbol(symname)
|
|
|
|
+ else if is_data in flags then
|
|
|
|
+ current_asmdata.WeakRefAsmSymbol(symname)
|
|
|
|
+ else
|
|
|
|
+ current_asmdata.WeakRefAsmSymbol('.'+symname);
|
|
|
|
+ newsymname:=ReplaceForbiddenChars(symname);
|
|
|
|
+ current_asmdata.asmlists[al_picdata].concat(tai_directive.Create(asd_toc_entry,newsymname+'[TC],'+newsymname));
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
function tcgppcgen.fixref(list: TAsmList; var ref: treference): boolean;
|
|
function tcgppcgen.fixref(list: TAsmList; var ref: treference): boolean;
|
|
var
|
|
var
|
|
tmpreg: tregister;
|
|
tmpreg: tregister;
|
|
@@ -780,7 +820,7 @@ unit cgppc;
|
|
result := false;
|
|
result := false;
|
|
|
|
|
|
{ Avoid recursion. }
|
|
{ Avoid recursion. }
|
|
- if (ref.refaddr = addr_pic) then
|
|
|
|
|
|
+ if (ref.refaddr in [addr_pic,addr_pic_no_got]) then
|
|
exit;
|
|
exit;
|
|
|
|
|
|
{$IFDEF EXTDEBUG}
|
|
{$IFDEF EXTDEBUG}
|
|
@@ -796,7 +836,7 @@ unit cgppc;
|
|
((cs_create_pic in current_settings.moduleswitches) and
|
|
((cs_create_pic in current_settings.moduleswitches) and
|
|
(ref.symbol.bind in [AB_COMMON,AB_GLOBAL,AB_PRIVATE_EXTERN])) then
|
|
(ref.symbol.bind in [AB_COMMON,AB_GLOBAL,AB_PRIVATE_EXTERN])) then
|
|
begin
|
|
begin
|
|
- tmpreg := g_indirect_sym_load(list,ref.symbol.name,ref.symbol.bind=AB_WEAK_EXTERNAL);
|
|
|
|
|
|
+ tmpreg := g_indirect_sym_load(list,ref.symbol.name,asmsym2indsymflags(ref.symbol));
|
|
ref.symbol:=nil;
|
|
ref.symbol:=nil;
|
|
end
|
|
end
|
|
else
|
|
else
|
|
@@ -819,11 +859,12 @@ unit cgppc;
|
|
end;
|
|
end;
|
|
|
|
|
|
{ if we have to create PIC, add the symbol to the TOC/GOT }
|
|
{ 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
|
|
|
|
|
|
+ if (((target_info.system = system_powerpc64_linux) and
|
|
|
|
+ (cs_create_pic in current_settings.moduleswitches)) or
|
|
|
|
+ (target_info.system in systems_aix)) and
|
|
(assigned(ref.symbol)) then
|
|
(assigned(ref.symbol)) then
|
|
begin
|
|
begin
|
|
- tmpreg := load_got_symbol(list, ref.symbol.name);
|
|
|
|
|
|
+ tmpreg := load_got_symbol(list, ref.symbol.name, asmsym2indsymflags(ref.symbol));
|
|
if (ref.base = NR_NO) then
|
|
if (ref.base = NR_NO) then
|
|
ref.base := tmpreg
|
|
ref.base := tmpreg
|
|
else if (ref.index = NR_NO) then
|
|
else if (ref.index = NR_NO) then
|
|
@@ -871,6 +912,9 @@ unit cgppc;
|
|
|
|
|
|
var
|
|
var
|
|
tmpreg: tregister;
|
|
tmpreg: tregister;
|
|
|
|
+{$ifdef cpu64bitaddr}
|
|
|
|
+ tmpreg2: tregister;
|
|
|
|
+{$endif cpu64bitaddr}
|
|
tmpref: treference;
|
|
tmpref: treference;
|
|
largeOffset: Boolean;
|
|
largeOffset: Boolean;
|
|
|
|
|
|
@@ -878,38 +922,57 @@ unit cgppc;
|
|
tmpreg := NR_NO;
|
|
tmpreg := NR_NO;
|
|
largeOffset:= hasLargeOffset(ref);
|
|
largeOffset:= hasLargeOffset(ref);
|
|
|
|
|
|
- if target_info.system = system_powerpc_macos then
|
|
|
|
|
|
+ if target_info.system in ([system_powerpc_macos]+systems_aix) then
|
|
begin
|
|
begin
|
|
|
|
|
|
- if assigned(ref.symbol) then
|
|
|
|
|
|
+ if assigned(ref.symbol) and
|
|
|
|
+ (ref.refaddr<>addr_pic_no_got) then
|
|
begin {Load symbol's value}
|
|
begin {Load symbol's value}
|
|
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
|
|
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
|
|
|
|
|
|
reference_reset(tmpref,sizeof(pint));
|
|
reference_reset(tmpref,sizeof(pint));
|
|
tmpref.symbol := ref.symbol;
|
|
tmpref.symbol := ref.symbol;
|
|
tmpref.base := NR_RTOC;
|
|
tmpref.base := NR_RTOC;
|
|
|
|
+ tmpref.refaddr := addr_pic_no_got;
|
|
|
|
|
|
if macos_direct_globals then
|
|
if macos_direct_globals then
|
|
list.concat(taicpu.op_reg_ref(A_LA,tmpreg,tmpref))
|
|
list.concat(taicpu.op_reg_ref(A_LA,tmpreg,tmpref))
|
|
else
|
|
else
|
|
|
|
+{$ifdef cpu64bitaddr}
|
|
|
|
+ list.concat(taicpu.op_reg_ref(A_LD,tmpreg,tmpref));
|
|
|
|
+{$else cpu64bitaddr}
|
|
list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref));
|
|
list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref));
|
|
|
|
+{$endif cpu64bitaddr}
|
|
end;
|
|
end;
|
|
|
|
|
|
if largeOffset then
|
|
if largeOffset then
|
|
begin {Add hi part of offset}
|
|
begin {Add hi part of offset}
|
|
reference_reset(tmpref,ref.alignment);
|
|
reference_reset(tmpref,ref.alignment);
|
|
|
|
|
|
- if Smallint(Lo(ref.offset)) < 0 then
|
|
|
|
- tmpref.offset := Hi(ref.offset) + 1 {Compensate when lo part is negative}
|
|
|
|
- else
|
|
|
|
- tmpref.offset := Hi(ref.offset);
|
|
|
|
|
|
+{$ifdef cpu64bitaddr}
|
|
|
|
+ if (ref.offset < low(longint)) or
|
|
|
|
+ (ref.offset > high(longint)) then
|
|
|
|
+ begin
|
|
|
|
+ { load upper 32 bits of the offset, adjusted for adding
|
|
|
|
+ the lower 32 bits later }
|
|
|
|
+ tmpreg2:=getintregister(list,OS_ADDR);
|
|
|
|
+ a_load_const_reg(list,OS_ADDR,(ref.offset and $ffffffff00000000) + ord(longint(ref.offset)<0),tmpreg2);
|
|
|
|
+ if tmpreg=NR_NO then
|
|
|
|
+ tmpreg:=tmpreg2
|
|
|
|
+ else
|
|
|
|
+ a_op_reg_reg(list,OP_ADD,OS_ADDR,tmpreg2,tmpreg);
|
|
|
|
+ ref.offset:=longint(ref.offset);
|
|
|
|
+ end;
|
|
|
|
+{$endif cpu64bitaddr}
|
|
|
|
+ {Compensate when lo part is negative}
|
|
|
|
+ tmpref.offset := Smallint(ref.offset >> 16) + ord(Smallint(ref.offset) < 0);
|
|
|
|
|
|
if (tmpreg <> NR_NO) then
|
|
if (tmpreg <> NR_NO) then
|
|
- list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg, tmpreg,tmpref))
|
|
|
|
|
|
+ list.concat(taicpu.op_reg_reg_const(A_ADDIS,tmpreg, tmpreg,tmpref.offset))
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
- tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
|
|
|
|
- list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
|
|
|
|
|
|
+ tmpreg := getintregister(list,OS_ADDR);
|
|
|
|
+ list.concat(taicpu.op_reg_const(A_LIS,tmpreg,tmpref.offset));
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -924,7 +987,7 @@ unit cgppc;
|
|
ref.symbol:= nil;
|
|
ref.symbol:= nil;
|
|
ref.base:= tmpreg;
|
|
ref.base:= tmpreg;
|
|
if largeOffset then
|
|
if largeOffset then
|
|
- ref.offset := Smallint(Lo(ref.offset));
|
|
|
|
|
|
+ ref.offset := Smallint(ref.offset);
|
|
|
|
|
|
list.concat(taicpu.op_reg_ref(op,reg,ref));
|
|
list.concat(taicpu.op_reg_ref(op,reg,ref));
|
|
//list.concat(tai_comment.create(strpnew('*** a_load_store indirect global')));
|
|
//list.concat(tai_comment.create(strpnew('*** a_load_store indirect global')));
|
|
@@ -937,6 +1000,7 @@ unit cgppc;
|
|
if assigned(ref.symbol) or
|
|
if assigned(ref.symbol) or
|
|
largeOffset then
|
|
largeOffset then
|
|
begin
|
|
begin
|
|
|
|
+ // TODO: offsets > 32 bit
|
|
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
|
|
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
|
|
reference_reset(tmpref,ref.alignment);
|
|
reference_reset(tmpref,ref.alignment);
|
|
tmpref.symbol := ref.symbol;
|
|
tmpref.symbol := ref.symbol;
|