mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-02 08:50:56 +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/ncpuinl.pas svneol=native#text/plain
|
||||||
compiler/aarch64/ncpumat.pas svneol=native#text/plain
|
compiler/aarch64/ncpumat.pas svneol=native#text/plain
|
||||||
compiler/aarch64/ncpumem.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/ra64con.inc svneol=native#text/plain
|
||||||
compiler/aarch64/ra64dwa.inc svneol=native#text/plain
|
compiler/aarch64/ra64dwa.inc svneol=native#text/plain
|
||||||
compiler/aarch64/ra64nor.inc svneol=native#text/plain
|
compiler/aarch64/ra64nor.inc svneol=native#text/plain
|
||||||
|
@ -31,7 +31,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
ncgbas,ncgflw,ncgcal,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,ncgobjc,
|
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 }
|
{ this not really a node }
|
||||||
rgcpu,
|
rgcpu,
|
||||||
{ symtable }
|
{ 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 }
|
{ for Jasmin }
|
||||||
asd_jclass,asd_jinterface,asd_jsuper,asd_jfield,asd_jlimit,asd_jline,
|
asd_jclass,asd_jinterface,asd_jsuper,asd_jfield,asd_jlimit,asd_jline,
|
||||||
{ .ent/.end for MIPS and Alpha }
|
{ .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=(
|
TAsmSehDirective=(
|
||||||
@ -385,7 +387,9 @@ interface
|
|||||||
{ for Jasmin }
|
{ for Jasmin }
|
||||||
'class','interface','super','field','limit','line',
|
'class','interface','super','field','limit','line',
|
||||||
{ .ent/.end for MIPS and Alpha }
|
{ .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]=(
|
sehdirectivestr : array[TAsmSehDirective] of string[16]=(
|
||||||
'.seh_proc','.seh_endproc',
|
'.seh_proc','.seh_endproc',
|
||||||
|
Loading…
Reference in New Issue
Block a user