mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-12 22:32:29 +02:00
+ ppc jumptable support for case statements (by Thomas Schatzl)
git-svn-id: trunk@911 -
This commit is contained in:
parent
abeeb43ae7
commit
97a8ea2e6d
@ -26,12 +26,13 @@ unit nppcset;
|
||||
interface
|
||||
|
||||
uses
|
||||
node,nset,ncgset,cpubase,cgbase,cgobj,aasmbase,aasmtai;
|
||||
node,nset,ncgset,cpubase,cgbase,cgobj,aasmbase,aasmtai,globtype;
|
||||
|
||||
type
|
||||
|
||||
tppccasenode = class(tcgcasenode)
|
||||
protected
|
||||
function has_jumptable : boolean;override;
|
||||
procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
|
||||
procedure genlinearlist(hp : pcaselabel); override;
|
||||
end;
|
||||
|
||||
@ -39,22 +40,90 @@ interface
|
||||
implementation
|
||||
|
||||
uses
|
||||
globtype,systems,
|
||||
systems,
|
||||
verbose,globals,
|
||||
symconst,symdef,defutil,
|
||||
paramgr,
|
||||
cpuinfo,
|
||||
pass_2,cgcpu,
|
||||
ncon,
|
||||
tgobj,ncgutil,regvars,rgobj,aasmcpu;
|
||||
|
||||
|
||||
tgobj,ncgutil,regvars,rgobj,aasmcpu,
|
||||
procinfo,
|
||||
cgutils;
|
||||
|
||||
{*****************************************************************************
|
||||
TCGCASENODE
|
||||
*****************************************************************************}
|
||||
|
||||
|
||||
function tppccasenode.has_jumptable : boolean;
|
||||
begin
|
||||
has_jumptable:=true;
|
||||
end;
|
||||
|
||||
|
||||
procedure tppccasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
|
||||
var
|
||||
table : tasmlabel;
|
||||
last : TConstExprInt;
|
||||
indexreg : tregister;
|
||||
href : treference;
|
||||
jumpsegment : TAAsmOutput;
|
||||
|
||||
procedure genitem(t : pcaselabel);
|
||||
var
|
||||
i : aint;
|
||||
begin
|
||||
if assigned(t^.less) then
|
||||
genitem(t^.less);
|
||||
{ fill possible hole }
|
||||
for i:=last+1 to t^._low-1 do
|
||||
jumpSegment.concat(Tai_const.Create_sym(elselabel));
|
||||
for i:=t^._low to t^._high do
|
||||
jumpSegment.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
|
||||
last:=t^._high;
|
||||
if assigned(t^.greater) then
|
||||
genitem(t^.greater);
|
||||
end;
|
||||
|
||||
begin
|
||||
if (cs_create_smart in aktmoduleswitches) or
|
||||
(af_smartlink_sections in target_asm.flags) then
|
||||
jumpsegment:=current_procinfo.aktlocaldata
|
||||
else
|
||||
jumpsegment:=asmlist[al_data];
|
||||
if not(jumptable_no_range) then
|
||||
begin
|
||||
{ case expr less than min_ => goto elselabel }
|
||||
cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_lt,aint(min_),hregister,elselabel);
|
||||
{ case expr greater than max_ => goto elselabel }
|
||||
cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_gt,aint(max_),hregister,elselabel);
|
||||
end;
|
||||
objectlibrary.getlabel(table);
|
||||
{ make it a 32bit register }
|
||||
// allocate base and index registers register
|
||||
indexreg:= cg.makeregsize(exprasmlist, hregister, OS_INT);
|
||||
{ indexreg := hregister; }
|
||||
cg.a_load_reg_reg(exprasmlist, opsize, OS_INT, hregister, indexreg);
|
||||
{ create reference, indexreg := indexreg * sizeof(OS_ADDR) }
|
||||
cg.a_op_const_reg(exprasmlist, OP_MUL, OS_INT, tcgsize2size[OS_ADDR], indexreg);
|
||||
reference_reset_symbol(href, table, (-aint(min_)) * tcgsize2size[OS_ADDR]);
|
||||
href.index := indexreg;
|
||||
|
||||
cg.a_load_ref_reg(exprasmlist, OS_INT, OS_INT, href, indexreg);
|
||||
|
||||
exprasmlist.concat(taicpu.op_reg(A_MTCTR, indexreg));
|
||||
exprasmlist.concat(taicpu.op_none(A_BCTR));
|
||||
|
||||
{ generate jump table }
|
||||
if not(cs_littlesize in aktglobalswitches) then
|
||||
jumpSegment.concat(Tai_Align.Create_Op(4, 0));
|
||||
jumpSegment.concat(Tai_label.Create(table));
|
||||
last:=min_;
|
||||
genitem(hp);
|
||||
end;
|
||||
|
||||
|
||||
procedure tppccasenode.genlinearlist(hp : pcaselabel);
|
||||
|
||||
var
|
||||
|
Loading…
Reference in New Issue
Block a user