mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 04:08:06 +02:00
+ AArch64 jump table support
git-svn-id: trunk@29964 -
This commit is contained in:
parent
d4d9e361fc
commit
1de8e53edd
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -32,6 +32,7 @@ compiler/aarch64/ncpucnv.pas svneol=native#text/plain
|
||||
compiler/aarch64/ncpuinl.pas svneol=native#text/plain
|
||||
compiler/aarch64/ncpumat.pas svneol=native#text/plain
|
||||
compiler/aarch64/ncpumem.pas svneol=native#text/plain
|
||||
compiler/aarch64/ncpuset.pas svneol=native#text/plain
|
||||
compiler/aarch64/ra64con.inc svneol=native#text/plain
|
||||
compiler/aarch64/ra64dwa.inc svneol=native#text/plain
|
||||
compiler/aarch64/ra64nor.inc svneol=native#text/plain
|
||||
|
@ -31,7 +31,7 @@ implementation
|
||||
|
||||
uses
|
||||
ncgbas,ncgflw,ncgcal,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,ncgobjc,
|
||||
ncpuadd,ncpumat,ncpumem,ncpuinl,ncpucnv,{ncpuset,}
|
||||
ncpuadd,ncpumat,ncpumem,ncpuinl,ncpucnv,ncpuset,
|
||||
{ this not really a node }
|
||||
rgcpu,
|
||||
{ symtable }
|
||||
|
175
compiler/aarch64/ncpuset.pas
Normal file
175
compiler/aarch64/ncpuset.pas
Normal file
@ -0,0 +1,175 @@
|
||||
{
|
||||
Copyright (c) 2015 by Jonas Maebe
|
||||
|
||||
Generate AArch64 assembler for in set/case nodes
|
||||
|
||||
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.
|
||||
|
||||
****************************************************************************
|
||||
}
|
||||
unit ncpuset;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
node,nset,ncgset,cpubase,cgbase,cgobj,aasmbase,aasmtai,aasmdata,globtype;
|
||||
|
||||
type
|
||||
taarch64casenode = class(tcgcasenode)
|
||||
protected
|
||||
procedure optimizevalues(var max_linear_list: aint; var max_dist: aword);override;
|
||||
function has_jumptable: boolean;override;
|
||||
procedure genjumptable(hp: pcaselabel ;min_, max_: aint);override;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
systems,
|
||||
verbose,globals,constexp,
|
||||
symconst,symdef,defutil,
|
||||
paramgr,
|
||||
cpuinfo,
|
||||
pass_2,cgcpu,
|
||||
ncon,
|
||||
tgobj,ncgutil,regvars,rgobj,aasmcpu,
|
||||
procinfo,
|
||||
cgutils;
|
||||
|
||||
{*****************************************************************************
|
||||
TCGCASENODE
|
||||
*****************************************************************************}
|
||||
|
||||
|
||||
procedure taarch64casenode.optimizevalues(var max_linear_list: aint; var max_dist: aword);
|
||||
begin
|
||||
max_linear_list:=10;
|
||||
end;
|
||||
|
||||
|
||||
function taarch64casenode.has_jumptable: boolean;
|
||||
begin
|
||||
has_jumptable:=true;
|
||||
end;
|
||||
|
||||
|
||||
procedure taarch64casenode.genjumptable(hp: pcaselabel; min_, max_: aint);
|
||||
var
|
||||
last: TConstExprInt;
|
||||
tablelabel: TAsmLabel;
|
||||
basereg,indexreg,jumpreg: TRegister;
|
||||
href: TReference;
|
||||
opcgsize: tcgsize;
|
||||
sectype: TAsmSectiontype;
|
||||
jtitemconsttype: taiconst_type;
|
||||
|
||||
procedure genitem(list:TAsmList;t : pcaselabel);
|
||||
var
|
||||
i : aint;
|
||||
begin
|
||||
if assigned(t^.less) then
|
||||
genitem(list,t^.less);
|
||||
{ fill possible hole }
|
||||
i:=last.svalue+1;
|
||||
while i<=t^._low.svalue-1 do
|
||||
begin
|
||||
list.concat(Tai_const.Create_rel_sym(jtitemconsttype,tablelabel,elselabel));
|
||||
inc(i);
|
||||
end;
|
||||
i:=t^._low.svalue;
|
||||
while i<=t^._high.svalue do
|
||||
begin
|
||||
list.concat(Tai_const.Create_rel_sym(jtitemconsttype,tablelabel,blocklabel(t^.blockid)));
|
||||
inc(i);
|
||||
end;
|
||||
last:=t^._high;
|
||||
if assigned(t^.greater) then
|
||||
genitem(list,t^.greater);
|
||||
end;
|
||||
|
||||
begin
|
||||
if not(target_info.system in systems_darwin) then
|
||||
jtitemconsttype:=aitconst_32bit
|
||||
else
|
||||
{ see https://gmplib.org/list-archives/gmp-bugs/2012-December/002836.html }
|
||||
jtitemconsttype:=aitconst_darwin_dwarf_delta32;
|
||||
|
||||
last:=min_;
|
||||
opcgsize:=def_cgsize(opsize);
|
||||
{ a <= x <= b <-> unsigned(x-a) <= (b-a) }
|
||||
cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opcgsize,aint(min_),hregister);
|
||||
if not(jumptable_no_range) then
|
||||
begin
|
||||
{ case expr greater than max_ => goto elselabel }
|
||||
cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opcgsize,OC_A,aint(max_)-aint(min_),hregister,elselabel);
|
||||
min_:=0;
|
||||
end;
|
||||
{ local label in order to avoid using GOT }
|
||||
current_asmdata.getlabel(tablelabel,alt_data);
|
||||
indexreg:=cg.makeregsize(current_asmdata.CurrAsmList,hregister,OS_ADDR);
|
||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,opcgsize,OS_ADDR,hregister,indexreg);
|
||||
{ load table address }
|
||||
reference_reset_symbol(href,tablelabel,0,4);
|
||||
basereg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,basereg);
|
||||
{ load table slot, 32-bit sign extended }
|
||||
reference_reset_base(href,basereg,0,4);
|
||||
href.index:=indexreg;
|
||||
href.shiftmode:=SM_LSL;
|
||||
href.shiftimm:=2;
|
||||
jumpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_S32,OS_ADDR,href,jumpreg);
|
||||
{ add table address }
|
||||
cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,basereg,jumpreg);
|
||||
{ and finally jump }
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_BR,jumpreg));
|
||||
{ generate jump table }
|
||||
if not(target_info.system in systems_darwin) then
|
||||
sectype:=sec_rodata
|
||||
else
|
||||
begin
|
||||
{ on Mac OS X, dead code stripping ("smart linking") happens based on
|
||||
global symbols: every global/static symbol (symbols that do not
|
||||
start with "L") marks the start of a new "subsection" that is
|
||||
discarded by the linker if there are no references to this symbol.
|
||||
This means that if you put the jump table in the rodata section, it
|
||||
will become part of the block of data associated with the previous
|
||||
non-L-label in the rodata section and stay or be thrown away
|
||||
depending on whether that block of data is referenced. Therefore,
|
||||
jump tables must be added in the code section and since aktlocaldata
|
||||
is inserted right after the routine, it will become part of the
|
||||
same subsection that contains the routine's code }
|
||||
sectype:=sec_code;
|
||||
end;
|
||||
new_section(current_procinfo.aktlocaldata,sectype,current_procinfo.procdef.mangledname,4);
|
||||
if target_info.system in systems_darwin then
|
||||
begin
|
||||
{ additionally, these tables are now marked via ".data_region jt32"
|
||||
and ".end_data_region" }
|
||||
current_procinfo.aktlocaldata.concat(tai_directive.Create(asd_data_region,'jt32'));
|
||||
end;
|
||||
current_procinfo.aktlocaldata.concat(Tai_label.Create(tablelabel));
|
||||
genitem(current_procinfo.aktlocaldata,hp);
|
||||
if target_info.system in systems_darwin then
|
||||
current_procinfo.aktlocaldata.concat(tai_directive.Create(asd_end_data_region,''));
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
ccasenode:=taarch64casenode;
|
||||
end.
|
@ -356,7 +356,9 @@ interface
|
||||
{ for Jasmin }
|
||||
asd_jclass,asd_jinterface,asd_jsuper,asd_jfield,asd_jlimit,asd_jline,
|
||||
{ .ent/.end for MIPS and Alpha }
|
||||
asd_ent,asd_ent_end
|
||||
asd_ent,asd_ent_end,
|
||||
{ supported by recent clang-based assemblers for data-in-code }
|
||||
asd_data_region, asd_end_data_region
|
||||
);
|
||||
|
||||
TAsmSehDirective=(
|
||||
@ -385,7 +387,9 @@ interface
|
||||
{ for Jasmin }
|
||||
'class','interface','super','field','limit','line',
|
||||
{ .ent/.end for MIPS and Alpha }
|
||||
'ent','end'
|
||||
'ent','end',
|
||||
{ supported by recent clang-based assemblers for data-in-code }
|
||||
'data_region','end_data_region'
|
||||
);
|
||||
sehdirectivestr : array[TAsmSehDirective] of string[16]=(
|
||||
'.seh_proc','.seh_endproc',
|
||||
|
Loading…
Reference in New Issue
Block a user