mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-05 15:47:54 +02:00
806 lines
28 KiB
ObjectPascal
806 lines
28 KiB
ObjectPascal
{
|
|
Copyright (c) 1998-2002 by Florian Klaempfl
|
|
|
|
This unit the GAS asm writers for PowerPC/PowerPC64
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
****************************************************************************
|
|
}
|
|
|
|
{****************************************************************************}
|
|
{ Helper routines for Instruction Writer }
|
|
{****************************************************************************}
|
|
|
|
unit agppcgas;
|
|
|
|
{$i fpcdefs.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
systems,aasmbase,
|
|
aasmtai,aasmdata,
|
|
assemble,aggas,
|
|
cpubase,cgutils,
|
|
globtype;
|
|
|
|
type
|
|
TPPCInstrWriter=class(TCPUInstrWriter)
|
|
procedure WriteInstruction(hp : tai);override;
|
|
end;
|
|
|
|
TPPCGNUAssembler=class(TGNUassembler)
|
|
constructor CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean); override;
|
|
function MakeCmdLine: TCmdStr; override;
|
|
procedure WriteExtraHeader; override;
|
|
end;
|
|
|
|
TPPCAppleGNUAssembler=class(TAppleGNUassembler)
|
|
constructor CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean); override;
|
|
function MakeCmdLine: TCmdStr; override;
|
|
end;
|
|
|
|
TPPCAIXAssembler=class(TPPCGNUAssembler)
|
|
max_alignment : array[TAsmSectionType] of longint;
|
|
constructor CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean); override;
|
|
protected
|
|
function sectionname(atype: TAsmSectiontype; const aname: string; aorder: TAsmSectionOrder): string; override;
|
|
procedure WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder;secalign:longint;secflags:TSectionFlags=[];secprogbits:TSectionProgbits=SPB_None); override;
|
|
procedure WriteAsmList; override;
|
|
procedure WriteExtraHeader; override;
|
|
procedure WriteExtraFooter; override;
|
|
procedure WriteDirectiveName(dir: TAsmDirective); override;
|
|
end;
|
|
|
|
TPPCMacOSAssembler=class(TPPCGNUAssembler)
|
|
function sectionname(atype: TAsmSectiontype; const aname: string; aorder: TAsmSectionOrder): string; override;
|
|
end;
|
|
|
|
topstr = string[4];
|
|
|
|
function branchmode(o: tasmop): topstr;
|
|
function cond2str(op: tasmop; c: tasmcond): string;
|
|
|
|
implementation
|
|
|
|
uses
|
|
cutils,globals,verbose,
|
|
cgbase,
|
|
itcpugas,cpuinfo,
|
|
aasmcpu;
|
|
|
|
{$ifdef cpu64bitaddr}
|
|
const
|
|
refaddr2str: array[trefaddr] of string[9] = ('', '', '', '', '@l', '@h', '@higher', '@highest', '@ha', '@highera', '@highesta');
|
|
verbose_refaddrs = [addr_low, addr_high, addr_higher, addr_highest, addr_higha, addr_highera, addr_highesta];
|
|
refaddr2str_darwin: array[trefaddr] of string[4] = ('','','','','lo16', 'hi16', '@err', '@err', 'ha16', '@err', '@err');
|
|
{$else cpu64bitaddr}
|
|
const
|
|
refaddr2str: array[trefaddr] of string[3] = ('','','','','@l','@h','@ha');
|
|
refaddr2str_darwin: array[trefaddr] of string[4] = ('','','','','lo16','hi16','ha16');
|
|
verbose_refaddrs = [addr_low,addr_high,addr_higha];
|
|
{$endif cpu64bitaddr}
|
|
|
|
|
|
function getreferencestring(asminfo: pasminfo; var ref : treference) : string;
|
|
var
|
|
s : string;
|
|
begin
|
|
with ref do
|
|
begin
|
|
case refaddr of
|
|
addr_no:
|
|
begin
|
|
if (offset < -32768) or (offset > 32767) { or assigned(symbol) } then
|
|
internalerror(2006052501);
|
|
s:='';
|
|
end;
|
|
addr_pic_no_got:
|
|
begin
|
|
{ used for TOC-based loads }
|
|
if (base<>NR_RTOC) or
|
|
(index<>NR_NO) or
|
|
(offset<>0) or
|
|
not assigned(symbol) then
|
|
internalerror(2011122702);
|
|
if asminfo^.dollarsign<>'$' then
|
|
getreferencestring:=ApplyAsmSymbolRestrictions(symbol.name)+'('+gas_regname(NR_RTOC)+')'
|
|
else
|
|
getreferencestring:=symbol.name+'('+gas_regname(NR_RTOC)+')';
|
|
exit;
|
|
end
|
|
else
|
|
begin
|
|
if target_info.system in [system_powerpc_darwin,system_powerpc64_darwin] then
|
|
s := refaddr2str_darwin[refaddr]
|
|
else
|
|
s :='';
|
|
s := s+'(';
|
|
if assigned(symbol) then
|
|
begin
|
|
if asminfo^.dollarsign<>'$' then
|
|
begin
|
|
s:=s+ApplyAsmSymbolRestrictions(symbol.name);
|
|
if assigned(relsymbol) then
|
|
s:=s+'-'+ApplyAsmSymbolRestrictions(relsymbol.name)
|
|
end
|
|
else
|
|
begin
|
|
s:=s+symbol.name;
|
|
if assigned(relsymbol) then
|
|
s:=s+'-'+relsymbol.name;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
if offset<0 then
|
|
s:=s+tostr(offset)
|
|
else
|
|
if (offset>0) then
|
|
begin
|
|
if assigned(symbol) then
|
|
s:=s+'+'+tostr(offset)
|
|
else
|
|
s:=s+tostr(offset);
|
|
end;
|
|
|
|
if not(refaddr in [addr_no,addr_pic_no_got]) then
|
|
begin
|
|
s := s+')';
|
|
if (refaddr in verbose_refaddrs) and
|
|
not(target_info.system in [system_powerpc_darwin,system_powerpc64_darwin]) then
|
|
s := s+refaddr2str[refaddr];
|
|
end;
|
|
{$ifdef cpu64bitaddr}
|
|
if (refaddr=addr_pic) and
|
|
(target_info.system=system_powerpc64_linux) then
|
|
s := s + '@got';
|
|
{$endif cpu64bitaddr}
|
|
|
|
if (index=NR_NO) then
|
|
begin
|
|
if offset=0 then
|
|
begin
|
|
if not (assigned(symbol)) then
|
|
s:=s+'0';
|
|
end;
|
|
if (base<>NR_NO) then
|
|
s:=s+'('+gas_regname(base)+')'
|
|
else if not assigned(symbol) and
|
|
not(refaddr in verbose_refaddrs) then
|
|
s:=s+'(0)';
|
|
end
|
|
else if (index<>NR_NO) and (base<>NR_NO) then
|
|
begin
|
|
if (offset=0) then
|
|
s:=s+gas_regname(base)+','+gas_regname(index)
|
|
else
|
|
internalerror(2006052502);
|
|
end;
|
|
end;
|
|
getreferencestring:=s;
|
|
end;
|
|
|
|
|
|
function getopstr_jmp(asminfo: pasminfo; const o:toper) : string;
|
|
var
|
|
hs : string;
|
|
begin
|
|
case o.typ of
|
|
top_reg :
|
|
getopstr_jmp:=gas_regname(o.reg);
|
|
{ no top_ref jumping for powerpc }
|
|
top_const :
|
|
getopstr_jmp:=tostr(o.val);
|
|
top_ref :
|
|
begin
|
|
if o.ref^.refaddr<>addr_full then
|
|
internalerror(200402267);
|
|
hs:=o.ref^.symbol.name;
|
|
if asminfo^.dollarsign<>'$' then
|
|
hs:=ApplyAsmSymbolRestrictions(hs);
|
|
if o.ref^.offset>0 then
|
|
hs:=hs+'+'+tostr(o.ref^.offset)
|
|
else
|
|
if o.ref^.offset<0 then
|
|
hs:=hs+tostr(o.ref^.offset);
|
|
getopstr_jmp:=hs;
|
|
end;
|
|
top_none:
|
|
getopstr_jmp:='';
|
|
else
|
|
internalerror(2002070605);
|
|
end;
|
|
end;
|
|
|
|
|
|
function getopstr(asminfo: pasminfo; const o:toper) : string;
|
|
var
|
|
hs : string;
|
|
begin
|
|
case o.typ of
|
|
top_reg:
|
|
getopstr:=gas_regname(o.reg);
|
|
top_const:
|
|
getopstr:=tostr(longint(o.val));
|
|
top_ref:
|
|
if o.ref^.refaddr=addr_full then
|
|
begin
|
|
hs:=o.ref^.symbol.name;
|
|
if asminfo^.dollarsign<>'$' then
|
|
hs:=ApplyAsmSymbolRestrictions(hs);
|
|
if o.ref^.offset>0 then
|
|
hs:=hs+'+'+tostr(o.ref^.offset)
|
|
else
|
|
if o.ref^.offset<0 then
|
|
hs:=hs+tostr(o.ref^.offset);
|
|
getopstr:=hs;
|
|
end
|
|
else
|
|
getopstr:=getreferencestring(asminfo,o.ref^);
|
|
else
|
|
internalerror(2002070604);
|
|
end;
|
|
end;
|
|
|
|
|
|
function branchmode(o: tasmop): topstr;
|
|
var tempstr: topstr;
|
|
begin
|
|
tempstr := '';
|
|
case o of
|
|
A_BCCTR,A_BCCTRL: tempstr := 'ctr';
|
|
A_BCLR,A_BCLRL: tempstr := 'lr';
|
|
else
|
|
;
|
|
end;
|
|
case o of
|
|
A_BL,A_BLA,A_BCL,A_BCLA,A_BCCTRL,A_BCLRL: tempstr := tempstr+'l';
|
|
else
|
|
;
|
|
end;
|
|
case o of
|
|
A_BA,A_BLA,A_BCA,A_BCLA: tempstr:=tempstr+'a';
|
|
else
|
|
;
|
|
end;
|
|
branchmode := tempstr;
|
|
end;
|
|
|
|
|
|
function cond2str(op: tasmop; c: tasmcond): string;
|
|
{ note: no checking is performed whether the given combination of }
|
|
{ conditions is valid }
|
|
var
|
|
tempstr: string;
|
|
begin
|
|
tempstr:=#9;
|
|
case c.simple of
|
|
false:
|
|
begin
|
|
cond2str := tempstr+gas_op2str[op];
|
|
case c.dirhint of
|
|
DH_None:;
|
|
DH_Minus:
|
|
cond2str:=cond2str+'-';
|
|
DH_Plus:
|
|
cond2str:=cond2str+'+';
|
|
end;
|
|
cond2str:=cond2str+#9+tostr(c.bo)+','+tostr(c.bi);
|
|
end;
|
|
true:
|
|
if (op >= A_B) and (op <= A_BCLRL) then
|
|
case c.cond of
|
|
{ unconditional branch }
|
|
C_NONE:
|
|
cond2str := tempstr+gas_op2str[op];
|
|
{ bdnzt etc }
|
|
else
|
|
begin
|
|
tempstr := tempstr+'b'+asmcondflag2str[c.cond]+
|
|
branchmode(op);
|
|
case c.dirhint of
|
|
DH_None:
|
|
tempstr:=tempstr+#9;
|
|
DH_Minus:
|
|
tempstr:=tempstr+('-'+#9);
|
|
DH_Plus:
|
|
tempstr:=tempstr+('+'+#9);
|
|
end;
|
|
case c.cond of
|
|
C_LT..C_NU:
|
|
begin
|
|
if byte(c.cr)=0 then
|
|
Comment(V_error,'Wrong use of whole CR register for '+tempstr);
|
|
cond2str := tempstr+gas_regname(newreg(R_SPECIALREGISTER,c.cr,R_SUBWHOLE));
|
|
end;
|
|
C_T,C_F,C_DNZT,C_DNZF,C_DZT,C_DZF:
|
|
cond2str := tempstr+tostr(c.crbit);
|
|
else
|
|
cond2str := tempstr;
|
|
end;
|
|
end;
|
|
end
|
|
{ we have a trap instruction }
|
|
else
|
|
begin
|
|
internalerror(2002070602);
|
|
{ not yet implemented !!!!!!!!!!!!!!!!!!!!! }
|
|
{ case tempstr := 'tw';}
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
{****************************************************************************}
|
|
{ PowerPC Instruction Writer }
|
|
{****************************************************************************}
|
|
|
|
Procedure TPPCInstrWriter.WriteInstruction(hp : tai);
|
|
var op: TAsmOp;
|
|
s: string;
|
|
i: byte;
|
|
sep: string[3];
|
|
begin
|
|
op:=taicpu(hp).opcode;
|
|
if is_calljmp(op) then
|
|
begin
|
|
{ direct BO/BI in op[0] and op[1] not supported, put them in condition! }
|
|
case op of
|
|
A_B,A_BA,A_BL,A_BLA:
|
|
s:=#9+gas_op2str[op]+#9;
|
|
A_BCTR,A_BCTRL,A_BLR,A_BLRL:
|
|
s:=#9+gas_op2str[op]
|
|
else
|
|
begin
|
|
s:=cond2str(op,taicpu(hp).condition);
|
|
if (s[length(s)] <> #9) and
|
|
(taicpu(hp).ops>0) then
|
|
s := s + ',';
|
|
end;
|
|
end;
|
|
|
|
if (taicpu(hp).ops>0) and (taicpu(hp).oper[0]^.typ<>top_none) then
|
|
begin
|
|
{ first write the current contents of s, because the symbol }
|
|
{ may be 255 characters }
|
|
owner.writer.AsmWrite(s);
|
|
s:=getopstr_jmp(owner.asminfo,taicpu(hp).oper[0]^);
|
|
end;
|
|
end
|
|
else
|
|
{ process operands }
|
|
begin
|
|
s:=#9+gas_op2str[op];
|
|
if taicpu(hp).ops<>0 then
|
|
begin
|
|
{
|
|
if not is_calljmp(op) then
|
|
sep:=','
|
|
else
|
|
}
|
|
sep:=#9;
|
|
for i:=0 to taicpu(hp).ops-1 do
|
|
begin
|
|
// debug code
|
|
// writeln(s);
|
|
// writeln(taicpu(hp).fileinfo.line);
|
|
s:=s+sep+getopstr(owner.asminfo,taicpu(hp).oper[i]^);
|
|
sep:=',';
|
|
end;
|
|
end;
|
|
end;
|
|
owner.writer.AsmWriteLn(s);
|
|
end;
|
|
|
|
|
|
{****************************************************************************}
|
|
{ GNU PPC Assembler writer }
|
|
{****************************************************************************}
|
|
|
|
constructor TPPCGNUAssembler.CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean);
|
|
begin
|
|
inherited;
|
|
InstrWriter := TPPCInstrWriter.create(self);
|
|
end;
|
|
|
|
|
|
function TPPCGNUAssembler.MakeCmdLine: TCmdStr;
|
|
begin
|
|
result := inherited MakeCmdLine;
|
|
{$ifdef cpu64bitaddr}
|
|
Replace(result,'$ARCH','-a64')
|
|
{$else cpu64bitaddr}
|
|
{ MorphOS has an old 2.9.1 GNU AS, with a bunch of patches
|
|
to support the system, and it doesn't know the -a32 argument }
|
|
if target_info.system = system_powerpc_morphos then
|
|
Replace(result,'$ARCH','')
|
|
else
|
|
Replace(result,'$ARCH','-a32');
|
|
{$endif cpu64bitaddr}
|
|
end;
|
|
|
|
|
|
procedure TPPCGNUAssembler.WriteExtraHeader;
|
|
var
|
|
i : longint;
|
|
begin
|
|
if target_info.abi = abi_powerpc_elfv2 then
|
|
writer.AsmWriteln(#9'.abiversion 2');
|
|
for i:=0 to 31 do
|
|
writer.AsmWriteln(#9'.set'#9'r'+tostr(i)+','+tostr(i));
|
|
for i:=0 to 31 do
|
|
writer.AsmWriteln(#9'.set'#9'f'+tostr(i)+','+tostr(i));
|
|
end;
|
|
|
|
|
|
{****************************************************************************}
|
|
{ GNU/Apple PPC Assembler writer }
|
|
{****************************************************************************}
|
|
|
|
constructor TPPCAppleGNUAssembler.CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean);
|
|
begin
|
|
inherited;
|
|
InstrWriter := TPPCInstrWriter.create(self);
|
|
end;
|
|
|
|
|
|
function TPPCAppleGNUAssembler.MakeCmdLine: TCmdStr;
|
|
begin
|
|
result := inherited MakeCmdLine;
|
|
{$ifdef cpu64bitaddr}
|
|
Replace(result,'$ARCH','ppc64')
|
|
{$else cpu64bitaddr}
|
|
case current_settings.cputype of
|
|
cpu_PPC7400:
|
|
Replace(result,'$ARCH','ppc7400');
|
|
cpu_PPC970:
|
|
Replace(result,'$ARCH','ppc970');
|
|
else
|
|
Replace(result,'$ARCH','ppc')
|
|
end;
|
|
{$endif cpu64bitaddr}
|
|
end;
|
|
|
|
|
|
{****************************************************************************}
|
|
{ AIX PPC Assembler writer }
|
|
{****************************************************************************}
|
|
|
|
constructor TPPCAIXAssembler.CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean);
|
|
var
|
|
cur_sectype : TAsmSectionType;
|
|
begin
|
|
inherited;
|
|
InstrWriter := TPPCInstrWriter.create(self);
|
|
{ Use 8-byte alignment as default for all sections }
|
|
for cur_sectype:=low(TAsmSectionType) to high(TAsmSectionType) do
|
|
max_alignment[cur_sectype]:=8;
|
|
end;
|
|
|
|
procedure TPPCAIXAssembler.WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder;secalign:longint;
|
|
secflags:TSectionFlags=[];secprogbits:TSectionProgbits=SPB_None);
|
|
|
|
begin
|
|
secalign:=max_alignment[atype];
|
|
Inherited WriteSection(atype,aname,aorder,secalign,secflags,secprogbits);
|
|
end;
|
|
|
|
procedure TPPCAIXAssembler.WriteAsmList;
|
|
var
|
|
cur_sectype : TAsmSectionType;
|
|
hal : tasmlisttype;
|
|
hp : tai;
|
|
max_al : longint;
|
|
begin
|
|
{ Parse all asmlists to get maximum alignement used for all types }
|
|
for hal:=low(TasmlistType) to high(TasmlistType) do
|
|
begin
|
|
if not (current_asmdata.asmlists[hal].empty) then
|
|
begin
|
|
cur_sectype:=sec_none;
|
|
hp:=tai(current_asmdata.asmlists[hal].First);
|
|
while assigned(hp) do
|
|
begin
|
|
case hp.typ of
|
|
ait_align :
|
|
begin
|
|
if tai_align_abstract(hp).aligntype > max_alignment[cur_sectype] then
|
|
begin
|
|
max_alignment[cur_sectype]:=tai_align_abstract(hp).aligntype;
|
|
current_asmdata.asmlists[hal].InsertAfter(tai_comment.Create(strpnew('Alignment put to '+tostr(tai_align_abstract(hp).aligntype))),hp);
|
|
end;
|
|
end;
|
|
ait_section :
|
|
begin
|
|
cur_sectype:=tai_section(hp).sectype;
|
|
if tai_section(hp).secalign > max_alignment[cur_sectype] then
|
|
begin
|
|
max_alignment[cur_sectype]:=tai_section(hp).secalign;
|
|
current_asmdata.asmlists[hal].InsertAfter(tai_comment.Create(strpnew('Section '
|
|
+sectionname(tai_section(hp).sectype,'',secorder_default)+' alignment put to '+tostr(tai_section(hp).secalign))),hp);
|
|
end;
|
|
end;
|
|
else
|
|
;
|
|
end;
|
|
hp:=tai(hp.next);
|
|
end;
|
|
end;
|
|
end;
|
|
{ sec_data, sec_rodata and sec_bss all are converted into .data[RW],
|
|
in WriteSection below,
|
|
so we take the maximum alignment of the three }
|
|
max_al:=max_alignment[sec_data];
|
|
max_al:=max(max_al,max_alignment[sec_rodata]);
|
|
max_al:=max(max_al,max_alignment[sec_bss]);
|
|
max_alignment[sec_data]:=max_al;
|
|
max_alignment[sec_rodata]:=max_al;
|
|
max_alignment[sec_bss]:=max_al;
|
|
Inherited WriteAsmList;
|
|
end;
|
|
|
|
procedure TPPCAIXAssembler.WriteExtraHeader;
|
|
var
|
|
i: longint;
|
|
begin
|
|
inherited WriteExtraHeader;
|
|
{ map cr registers to plain numbers }
|
|
for i:=0 to 7 do
|
|
writer.AsmWriteln(#9'.set'#9'cr'+tostr(i)+','+tostr(i));
|
|
{ Ensure .data and .rodata sections are aligned to 8-byte boundary,
|
|
required for correct RTTI alignment.
|
|
AIX assembler seems to only care for the first
|
|
alignment value given }
|
|
writer.AsmWriteln(#9'.csect .data[RW],'+sectionalignment_aix(sec_data,max_alignment[sec_data]));
|
|
writer.AsmWriteln(#9'.csect _data.bss_[BS],'+sectionalignment_aix(sec_data,max_alignment[sec_data]));
|
|
{ .rodata is translated into .text[RO]
|
|
see sectionname in aggas unit. }
|
|
writer.AsmWriteln(#9'.csect .text[RO],'+sectionalignment_aix(sec_rodata_norel,max_alignment[sec_rodata_norel]));
|
|
{ make sure we always have a code and toc section,
|
|
the linker expects that }
|
|
writer.AsmWriteln(#9'.csect .text[PR],'+sectionalignment_aix(sec_code,max_alignment[sec_code]));
|
|
{ set _text_s, to be used by footer below }
|
|
writer.AsmWriteln(#9'_text_s:');
|
|
writer.AsmWriteln(#9'.toc');
|
|
end;
|
|
|
|
|
|
procedure TPPCAIXAssembler.WriteExtraFooter;
|
|
begin
|
|
inherited WriteExtraFooter;
|
|
{ link between data and text section }
|
|
writer.AsmWriteln(#9'.csect .data[RW],3');
|
|
{$ifdef cpu64bitaddr}
|
|
writer.AsmWriteln('text_pos:'#9'.llong _text_s')
|
|
{$else cpu64bitaddr}
|
|
writer.AsmWriteln('text_pos:'#9'.long _text_s')
|
|
{$endif cpu64bitaddr}
|
|
end;
|
|
|
|
|
|
procedure TPPCAIXAssembler.WriteDirectiveName(dir: TAsmDirective);
|
|
begin
|
|
case dir of
|
|
asd_reference:
|
|
writer.AsmWrite('.ref ');
|
|
asd_weak_reference,
|
|
asd_weak_definition:
|
|
writer.AsmWrite('.weak ');
|
|
else
|
|
inherited WriteDirectiveName(dir);
|
|
end;
|
|
end;
|
|
|
|
|
|
function TPPCAIXAssembler.sectionname(atype: TAsmSectiontype; const aname: string; aorder: TAsmSectionOrder): string;
|
|
begin
|
|
case atype of
|
|
sec_code:
|
|
result:='.csect .text[PR]';
|
|
sec_data,
|
|
sec_rodata,
|
|
{ don't use .bss[BS], causes relocation problems }
|
|
sec_bss:
|
|
result:='.csect .data[RW]';
|
|
sec_rodata_norel:
|
|
result:='.csect .text[RO]';
|
|
sec_fpc:
|
|
result:='.csect .fpc[RO]';
|
|
sec_toc:
|
|
result:='.toc';
|
|
{ automatically placed in the right section }
|
|
sec_stab,
|
|
sec_stabstr:
|
|
result:='';
|
|
else
|
|
internalerror(2011122601);
|
|
end;
|
|
end;
|
|
|
|
|
|
function TPPCMacOSAssembler.sectionname(atype: TAsmSectiontype; const aname: string; aorder: TAsmSectionOrder): string;
|
|
begin
|
|
case atype of
|
|
sec_code:
|
|
result:='.text[PR]';
|
|
sec_data,
|
|
sec_rodata,
|
|
{ don't use .bss[BS], causes relocation problems }
|
|
sec_bss:
|
|
result:='.data[RW]';
|
|
sec_rodata_norel:
|
|
result:='.text[RO]';
|
|
sec_fpc:
|
|
result:='.fpc[RO]';
|
|
sec_toc:
|
|
result:='.toc';
|
|
{ automatically placed in the right section }
|
|
sec_stab,
|
|
sec_stabstr:
|
|
result:='';
|
|
else
|
|
internalerror(2025010201);
|
|
end;
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
Initialize
|
|
*****************************************************************************}
|
|
|
|
const
|
|
as_ppc_gas_info : tasminfo =
|
|
(
|
|
id : as_gas;
|
|
|
|
idtxt : 'AS';
|
|
asmbin : 'as';
|
|
{$ifdef cpu64bitaddr}
|
|
asmcmd : '-a64 $ENDIAN -o $OBJ $EXTRAOPT $ASM';
|
|
{$else cpu64bitaddr}
|
|
asmcmd: '$ENDIAN -o $OBJ $EXTRAOPT $ARCH $ASM';
|
|
{$endif cpu64bitaddr}
|
|
supported_targets : [system_powerpc_linux,system_powerpc_netbsd,system_powerpc_openbsd,
|
|
system_powerpc_MorphOS,system_powerpc_Amiga,system_powerpc_wii,
|
|
system_powerpc64_linux,system_powerpc_embedded,system_powerpc64_embedded];
|
|
flags : [af_needar,af_smartlink_sections];
|
|
labelprefix : '.L';
|
|
labelmaxlen : -1;
|
|
comment : '# ';
|
|
dollarsign: '$';
|
|
);
|
|
|
|
as_ppc_gas_macosclassic_info : tasminfo =
|
|
(
|
|
id : as_powerpc_gas_macosclassic;
|
|
|
|
idtxt : 'AS-MACOS';
|
|
asmbin : 'as';
|
|
asmcmd: '-o $OBJ $EXTRAOPT $ARCH $ASM';
|
|
supported_targets : [system_powerpc_macosclassic];
|
|
flags : [af_needar,af_smartlink_sections];
|
|
labelprefix : '.L';
|
|
labelmaxlen : -1;
|
|
comment : '# ';
|
|
dollarsign: '$';
|
|
);
|
|
|
|
as_ppc_gas_legacy_info : tasminfo =
|
|
(
|
|
id : as_powerpc_gas_legacy;
|
|
|
|
idtxt : 'AS-LEGACY';
|
|
asmbin : 'as';
|
|
{$ifdef cpu64bitaddr}
|
|
asmcmd : '-a64 $ENDIAN -o $OBJ $EXTRAOPT $ASM';
|
|
{$else cpu64bitaddr}
|
|
asmcmd: '$ENDIAN -o $OBJ $EXTRAOPT $ARCH $ASM';
|
|
{$endif cpu64bitaddr}
|
|
supported_targets : [system_powerpc_morphos];
|
|
flags : [af_needar];
|
|
labelprefix : '.L';
|
|
labelmaxlen : -1;
|
|
comment : '# ';
|
|
dollarsign: '$';
|
|
);
|
|
|
|
as_ppc_gas_darwin_powerpc_info : tasminfo =
|
|
(
|
|
id : as_darwin;
|
|
|
|
idtxt : 'AS-DARWIN';
|
|
asmbin : 'as';
|
|
asmcmd : '-o $OBJ $EXTRAOPT $ASM -arch $ARCH';
|
|
supported_targets : [system_powerpc_darwin,system_powerpc64_darwin];
|
|
flags : [af_needar,af_smartlink_sections,af_supports_dwarf,af_stabs_use_function_absolute_addresses];
|
|
labelprefix : 'L';
|
|
labelmaxlen : -1;
|
|
comment : '# ';
|
|
dollarsign : '$';
|
|
);
|
|
|
|
|
|
as_ppc_aix_powerpc_info : tasminfo =
|
|
(
|
|
id : as_powerpc_xcoff;
|
|
|
|
idtxt : 'AS-AIX';
|
|
asmbin : 'as';
|
|
{ -u: allow using symbols before they are defined (when using native
|
|
AIX assembler, ignore by GNU assembler)
|
|
-mpwr5: we actually support Power3 and higher, but the AIX assembler
|
|
has no parameter to select that one (only -mpwr3 and -mpwr5) }
|
|
{$ifdef cpu64bitaddr}
|
|
asmcmd : '-a64 -u -o $OBJ $EXTRAOPT $ASM -mpwr5';
|
|
{$else cpu64bitaddr}
|
|
asmcmd : '-u -o $OBJ $EXTRAOPT $ASM -mpwr5';
|
|
{$endif cpu64bitaddr}
|
|
supported_targets : [system_powerpc_aix,system_powerpc64_aix];
|
|
flags : [af_needar,af_smartlink_sections,af_stabs_use_function_absolute_addresses];
|
|
labelprefix : 'L';
|
|
labelmaxlen : -1;
|
|
comment : '# ';
|
|
dollarsign : '.'
|
|
);
|
|
|
|
as_ppc_gas_aix_powerpc_info : tasminfo =
|
|
(
|
|
id : as_gas_powerpc_xcoff;
|
|
|
|
idtxt : 'GAS';
|
|
asmbin : 'gas';
|
|
{ -u: allow using symbols before they are defined (when using native
|
|
AIX assembler, ignore by GNU assembler)
|
|
-mpwr5: we actually support Power3 and higher, but the AIX assembler
|
|
has no parameter to select that one (only -mpwr3 and -mpwr5) }
|
|
{$ifdef cpu64bitaddr}
|
|
asmcmd : '-a64 -u -o $OBJ $EXTRAOPT $ASM -mpwr5';
|
|
{$else cpu64bitaddr}
|
|
asmcmd : '-a32 -u -o $OBJ $EXTRAOPT $ASM -mpwr5';
|
|
{$endif cpu64bitaddr}
|
|
supported_targets : [system_powerpc_aix,system_powerpc64_aix];
|
|
flags : [af_needar,af_smartlink_sections,af_stabs_use_function_absolute_addresses];
|
|
labelprefix : 'L';
|
|
labelmaxlen : -1;
|
|
comment : '# ';
|
|
dollarsign : '.'
|
|
);
|
|
|
|
as_ppc_clang_darwin_info : tasminfo =
|
|
(
|
|
id : as_clang_asdarwin;
|
|
idtxt : 'CLANG';
|
|
asmbin : 'clang';
|
|
asmcmd : '-x assembler -c -target $TRIPLET -o $OBJ $EXTRAOPT -x assembler $ASM';
|
|
supported_targets : [system_powerpc_macosclassic, system_powerpc_darwin, system_powerpc64_darwin];
|
|
flags : [af_needar,af_smartlink_sections,af_supports_dwarf,af_llvm];
|
|
labelprefix : 'L';
|
|
labelmaxlen : -1;
|
|
comment : '# ';
|
|
dollarsign: '$';
|
|
);
|
|
|
|
begin
|
|
RegisterAssembler(as_ppc_gas_info,TPPCGNUAssembler);
|
|
RegisterAssembler(as_ppc_gas_macosclassic_info,TPPCMACOsAssembler);
|
|
RegisterAssembler(as_ppc_gas_legacy_info,TPPCGNUAssembler);
|
|
RegisterAssembler(as_ppc_gas_darwin_powerpc_info,TPPCAppleGNUAssembler);
|
|
RegisterAssembler(as_ppc_clang_darwin_info,TPPCAppleGNUAssembler);
|
|
RegisterAssembler(as_ppc_aix_powerpc_info,TPPCAIXAssembler);
|
|
RegisterAssembler(as_ppc_gas_aix_powerpc_info,TPPCAIXAssembler);
|
|
end.
|