|
@@ -26,7 +26,7 @@ unit narmset;
|
|
|
interface
|
|
|
|
|
|
uses
|
|
|
- globtype,
|
|
|
+ globtype,constexp,
|
|
|
symtype,
|
|
|
cgbase,
|
|
|
node,nset,pass_1,ncgset;
|
|
@@ -45,13 +45,14 @@ interface
|
|
|
function has_jumptable : boolean;override;
|
|
|
procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
|
|
|
procedure genlinearlist(hp : pcaselabel);override;
|
|
|
+ procedure genjmptreeentry(p : pcaselabel;parentvalue : TConstExprInt);override;
|
|
|
end;
|
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
uses
|
|
|
- verbose,globals,constexp,defutil,systems,
|
|
|
+ verbose,globals,defutil,systems,
|
|
|
aasmbase,aasmtai,aasmdata,aasmcpu,
|
|
|
cpubase,cpuinfo,
|
|
|
cgutils,cgobj,ncgutil,
|
|
@@ -244,14 +245,14 @@ implementation
|
|
|
reference_reset(href,0,[]);
|
|
|
href.base:=basereg;
|
|
|
href.index:=indexreg;
|
|
|
-
|
|
|
+
|
|
|
tmpreg:=cg.getintregister(current_asmdata.CurrAsmList, OS_ADDR);
|
|
|
cg.a_load_ref_reg(current_asmdata.CurrAsmList, OS_ADDR, OS_ADDR, href, tmpreg);
|
|
|
-
|
|
|
+
|
|
|
{ do not use BX here to avoid switching into arm mode }
|
|
|
current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_MOV, NR_PC, tmpreg));
|
|
|
|
|
|
- current_asmdata.CurrAsmList.Concat(tai_align.Create(4));
|
|
|
+ current_asmdata.CurrAsmList.Concat(tai_align.Create(4));
|
|
|
cg.a_label(current_asmdata.CurrAsmList,tablelabel);
|
|
|
{ generate jump table }
|
|
|
last:=min_;
|
|
@@ -394,6 +395,69 @@ implementation
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
+
|
|
|
+ procedure tarmcasenode.genjmptreeentry(p : pcaselabel;parentvalue : TConstExprInt);
|
|
|
+ var
|
|
|
+ lesslabel,greaterlabel : tasmlabel;
|
|
|
+ less,greater : pcaselabel;
|
|
|
+ cond_gt: TResFlags;
|
|
|
+ cmplow : Boolean;
|
|
|
+ begin
|
|
|
+ if with_sign then
|
|
|
+ cond_gt:=F_GT
|
|
|
+ else
|
|
|
+ cond_gt:=F_HI;
|
|
|
+ current_asmdata.CurrAsmList.concat(cai_align.Create(current_settings.alignment.jumpalign));
|
|
|
+ cg.a_label(current_asmdata.CurrAsmList,p^.labellabel);
|
|
|
+
|
|
|
+ { calculate labels for left and right }
|
|
|
+ if p^.less=nil then
|
|
|
+ lesslabel:=elselabel
|
|
|
+ else
|
|
|
+ lesslabel:=p^.less^.labellabel;
|
|
|
+ if p^.greater=nil then
|
|
|
+ greaterlabel:=elselabel
|
|
|
+ else
|
|
|
+ greaterlabel:=p^.greater^.labellabel;
|
|
|
+
|
|
|
+ { calculate labels for left and right }
|
|
|
+ { no range label: }
|
|
|
+ if p^._low=p^._high then
|
|
|
+ begin
|
|
|
+ if greaterlabel=lesslabel then
|
|
|
+ begin
|
|
|
+ if p^._low-1<>parentvalue then
|
|
|
+ hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_NE,p^._low,hregister,lesslabel);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ cmplow:=p^._low-1<>parentvalue;
|
|
|
+ if cmplow then
|
|
|
+ hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_lt,p^._low,hregister,lesslabel);
|
|
|
+ if p^._high+1<>parentvalue then
|
|
|
+ begin
|
|
|
+ if cmplow then
|
|
|
+ hlcg.a_jmp_flags(current_asmdata.CurrAsmList,cond_gt,greaterlabel)
|
|
|
+ else
|
|
|
+ hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_gt,p^._low,hregister,greaterlabel);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ hlcg.a_jmp_always(current_asmdata.CurrAsmList,blocklabel(p^.blockid));
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ if p^._low-1<>parentvalue then
|
|
|
+ hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_lt,p^._low,hregister,lesslabel);
|
|
|
+ if p^._high+1<>parentvalue then
|
|
|
+ hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_gt,p^._high,hregister,greaterlabel);
|
|
|
+ hlcg.a_jmp_always(current_asmdata.CurrAsmList,blocklabel(p^.blockid));
|
|
|
+ end;
|
|
|
+ if assigned(p^.less) then
|
|
|
+ genjmptreeentry(p^.less,p^._low);
|
|
|
+ if assigned(p^.greater) then
|
|
|
+ genjmptreeentry(p^.greater,p^._high);
|
|
|
+ end;
|
|
|
+
|
|
|
begin
|
|
|
cinnode:=tarminnode;
|
|
|
ccasenode:=tarmcasenode;
|