mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-02 07:09:38 +01:00
+ basic support for pic on arm-linux
git-svn-id: trunk@25297 -
This commit is contained in:
parent
7ac3647ff2
commit
6606955b88
@ -140,7 +140,8 @@ interface
|
||||
aitconst_32bit_unaligned,
|
||||
aitconst_64bit_unaligned,
|
||||
{ i8086 far pointer; emits: 'DW symbol, SEG symbol' }
|
||||
aitconst_farptr
|
||||
aitconst_farptr,
|
||||
aitconst_got
|
||||
);
|
||||
|
||||
const
|
||||
@ -572,7 +573,9 @@ interface
|
||||
constructor Create_sym(_sym:tasmsymbol);
|
||||
constructor Create_type_sym(_typ:taiconst_type;_sym:tasmsymbol);
|
||||
constructor Create_sym_offset(_sym:tasmsymbol;ofs:aint);
|
||||
constructor Create_type_sym_offset(_typ:taiconst_type;_sym:tasmsymbol;ofs:aint);
|
||||
constructor Create_rel_sym(_typ:taiconst_type;_sym,_endsym:tasmsymbol);
|
||||
constructor Create_rel_sym_offset(_typ : taiconst_type; _sym,_endsym : tasmsymbol; _ofs : int64);
|
||||
constructor Create_rva_sym(_sym:tasmsymbol);
|
||||
constructor Createname(const name:string;ofs:aint);
|
||||
constructor Createname(const name:string;_symtyp:Tasmsymtype;ofs:aint);
|
||||
@ -1684,6 +1687,24 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
constructor tai_const.Create_type_sym_offset(_typ : taiconst_type;_sym : tasmsymbol; ofs : aint);
|
||||
begin
|
||||
inherited Create;
|
||||
typ:=ait_const;
|
||||
consttype:=_typ;
|
||||
{ sym is allowed to be nil, this is used to write nil pointers }
|
||||
sym:=_sym;
|
||||
endsym:=nil;
|
||||
{ store the original offset in symofs so that we can recalculate the
|
||||
value field in the assembler }
|
||||
symofs:=ofs;
|
||||
value:=ofs;
|
||||
{ update sym info }
|
||||
if assigned(sym) then
|
||||
sym.increfs;
|
||||
end;
|
||||
|
||||
|
||||
constructor tai_const.Create_rel_sym(_typ:taiconst_type;_sym,_endsym:tasmsymbol);
|
||||
begin
|
||||
self.create_sym_offset(_sym,0);
|
||||
@ -1693,6 +1714,15 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
constructor tai_const.Create_rel_sym_offset(_typ: taiconst_type; _sym,_endsym: tasmsymbol; _ofs: int64);
|
||||
begin
|
||||
self.create_sym_offset(_sym,_ofs);
|
||||
consttype:=_typ;
|
||||
endsym:=_endsym;
|
||||
endsym.increfs;
|
||||
end;
|
||||
|
||||
|
||||
constructor tai_const.Create_rva_sym(_sym:tasmsymbol);
|
||||
begin
|
||||
self.create_sym_offset(_sym,0);
|
||||
|
||||
@ -956,6 +956,11 @@ implementation
|
||||
AsmLn;
|
||||
end;
|
||||
{$endif cpu64bitaddr}
|
||||
aitconst_got:
|
||||
begin
|
||||
AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(GOT)');
|
||||
Asmln;
|
||||
end;
|
||||
aitconst_uleb128bit,
|
||||
aitconst_sleb128bit,
|
||||
{$ifdef cpu64bitaddr}
|
||||
|
||||
@ -164,10 +164,10 @@ unit agarmgas;
|
||||
if (base<>NR_NO) and not(is_pc(base)) then
|
||||
internalerror(200309011);
|
||||
s:=symbol.name;
|
||||
if offset<0 then
|
||||
s:=s+tostr(offset)
|
||||
else if offset>0 then
|
||||
s:=s+'+'+tostr(offset);
|
||||
if offset<>0 then
|
||||
s:=s+tostr_with_plus(offset);
|
||||
if refaddr=addr_pic then
|
||||
s:=s+'(PLT)';
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
@ -74,6 +74,7 @@ unit cgcpu;
|
||||
|
||||
procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
|
||||
procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
|
||||
procedure g_maybe_got_init(list : TAsmList); override;
|
||||
|
||||
procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
|
||||
|
||||
@ -624,6 +625,8 @@ unit cgcpu;
|
||||
procedure tbasecgarm.a_call_name(list : TAsmList;const s : string; weak: boolean);
|
||||
var
|
||||
branchopcode: tasmop;
|
||||
r : treference;
|
||||
sym : TAsmSymbol;
|
||||
begin
|
||||
{ check not really correct: should only be used for non-Thumb cpus }
|
||||
if CPUARM_HAS_BLX_LABEL in cpu_capabilities[current_settings.cputype] then
|
||||
@ -631,10 +634,23 @@ unit cgcpu;
|
||||
else
|
||||
branchopcode:=A_BL;
|
||||
if target_info.system<>system_arm_darwin then
|
||||
if not weak then
|
||||
list.concat(taicpu.op_sym(branchopcode,current_asmdata.RefAsmSymbol(s)))
|
||||
else
|
||||
list.concat(taicpu.op_sym(branchopcode,current_asmdata.WeakRefAsmSymbol(s)))
|
||||
begin
|
||||
if not(weak) then
|
||||
sym:=current_asmdata.RefAsmSymbol(s)
|
||||
else
|
||||
sym:=current_asmdata.WeakRefAsmSymbol(s);
|
||||
reference_reset_symbol(r,sym,0,sizeof(pint));
|
||||
|
||||
if cs_create_pic in current_settings.moduleswitches then
|
||||
begin
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
r.refaddr:=addr_pic
|
||||
end
|
||||
else
|
||||
r.refaddr:=addr_full;
|
||||
|
||||
list.concat(taicpu.op_ref(branchopcode,r));
|
||||
end
|
||||
else
|
||||
list.concat(taicpu.op_sym(branchopcode,get_darwin_call_stub(s,weak)));
|
||||
{
|
||||
@ -2104,6 +2120,29 @@ unit cgcpu;
|
||||
end;
|
||||
|
||||
|
||||
procedure tbasecgarm.g_maybe_got_init(list : TAsmList);
|
||||
var
|
||||
ref : treference;
|
||||
l : TAsmLabel;
|
||||
begin
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
(pi_needs_got in current_procinfo.flags) then
|
||||
begin
|
||||
reference_reset(ref,4);
|
||||
current_asmdata.getdatalabel(l);
|
||||
cg.a_label(current_procinfo.aktlocaldata,l);
|
||||
ref.symbol:=l;
|
||||
ref.base:=NR_PC;
|
||||
ref.symboldata:=current_procinfo.aktlocaldata.last;
|
||||
list.concat(Taicpu.op_reg_ref(A_LDR,current_procinfo.got,ref));
|
||||
current_asmdata.getaddrlabel(l);
|
||||
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_32bit,l,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),-8));
|
||||
cg.a_label(list,l);
|
||||
list.concat(Taicpu.op_reg_reg_reg(A_ADD,current_procinfo.got,NR_PC,current_procinfo.got));
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tbasecgarm.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
|
||||
var
|
||||
b : byte;
|
||||
@ -2197,7 +2236,11 @@ unit cgcpu;
|
||||
indirection_done:=true;
|
||||
end
|
||||
else
|
||||
current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
(tf_pic_uses_got in target_info.flags) then
|
||||
current_procinfo.aktlocaldata.concat(tai_const.Create_type_sym_offset(aitconst_got,ref.symbol,ref.offset))
|
||||
else
|
||||
current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
|
||||
end
|
||||
else
|
||||
current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
|
||||
@ -2209,6 +2252,16 @@ unit cgcpu;
|
||||
tmpref.symbol:=l;
|
||||
tmpref.base:=NR_PC;
|
||||
list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
|
||||
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
(tf_pic_uses_got in target_info.flags) and
|
||||
assigned(ref.symbol) then
|
||||
begin
|
||||
reference_reset(tmpref,4);
|
||||
tmpref.base:=current_procinfo.got;
|
||||
tmpref.index:=tmpreg;
|
||||
list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
|
||||
end;
|
||||
end;
|
||||
|
||||
{ This routine can be called with PC as base/index in case the offset
|
||||
|
||||
@ -29,7 +29,8 @@ unit cpupi;
|
||||
|
||||
uses
|
||||
globtype,cutils,
|
||||
procinfo,cpuinfo,psub;
|
||||
procinfo,cpuinfo,psub,
|
||||
aasmdata;
|
||||
|
||||
type
|
||||
tarmprocinfo = class(tcgprocinfo)
|
||||
@ -45,6 +46,7 @@ unit cpupi;
|
||||
function calc_stackframe_size:longint;override;
|
||||
procedure init_framepointer; override;
|
||||
procedure generate_parameter_info;override;
|
||||
procedure allocate_got_register(list : TAsmList);override;
|
||||
end;
|
||||
|
||||
|
||||
@ -212,6 +214,12 @@ unit cpupi;
|
||||
end;
|
||||
|
||||
|
||||
procedure tarmprocinfo.allocate_got_register(list: TAsmList);
|
||||
begin
|
||||
got := cg.getaddressregister(list);
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
cprocinfo:=tarmprocinfo;
|
||||
end.
|
||||
|
||||
@ -553,7 +553,8 @@ unit i_linux;
|
||||
shortname : 'Linux';
|
||||
flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
|
||||
tf_requires_proper_alignment,
|
||||
tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
|
||||
tf_smartlink_sections,tf_smartlink_library,tf_pic_uses_got,
|
||||
tf_has_winlike_resources];
|
||||
cpu : cpu_arm;
|
||||
unit_env : 'LINUXUNITS';
|
||||
extradefines : 'UNIX;HASUNIX;CPUARMHF';
|
||||
@ -618,7 +619,8 @@ unit i_linux;
|
||||
shortname : 'Linux';
|
||||
flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
|
||||
tf_requires_proper_alignment,
|
||||
tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
|
||||
tf_smartlink_sections,tf_smartlink_library,tf_pic_uses_got,
|
||||
tf_has_winlike_resources];
|
||||
cpu : cpu_arm;
|
||||
unit_env : 'LINUXUNITS';
|
||||
extradefines : 'UNIX;HASUNIX;CPUARMEL';
|
||||
@ -683,7 +685,8 @@ unit i_linux;
|
||||
shortname : 'Linux';
|
||||
flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
|
||||
tf_requires_proper_alignment,
|
||||
tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
|
||||
tf_smartlink_sections,tf_smartlink_library,tf_pic_uses_got,
|
||||
tf_has_winlike_resources];
|
||||
cpu : cpu_arm;
|
||||
unit_env : 'LINUXUNITS';
|
||||
extradefines : 'UNIX;HASUNIX;CPUARMEB';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user