diff --git a/compiler/i386/n386set.pas b/compiler/i386/n386set.pas index 47f04ead05..e5ee719752 100644 --- a/compiler/i386/n386set.pas +++ b/compiler/i386/n386set.pas @@ -32,7 +32,6 @@ interface type ti386casenode = class(tx86casenode) procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override; - procedure genlinearlist(hp : pcaselabel);override; end; @@ -68,93 +67,6 @@ implementation end; - procedure ti386casenode.genlinearlist(hp : pcaselabel); - var - first : boolean; - lastrange : boolean; - last : TConstExprInt; - cond_lt,cond_le : tresflags; - - procedure genitem(t : pcaselabel); - begin - if assigned(t^.less) then - genitem(t^.less); - { need we to test the first value } - if first and (t^._low>get_min_value(left.resultdef)) then - begin - cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_lt,aint(t^._low.svalue),hregister,elselabel); - end; - if t^._low=t^._high then - begin - if t^._low-last=0 then - cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_EQ,0,hregister,blocklabel(t^.blockid)) - else - begin - cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(t^._low.svalue-last.svalue), hregister); - cg.a_jmp_flags(current_asmdata.CurrAsmList,F_E,blocklabel(t^.blockid)); - end; - last:=t^._low; - lastrange:=false; - end - else - begin - { it begins with the smallest label, if the value } - { is even smaller then jump immediately to the } - { ELSE-label } - if first then - begin - { have we to ajust the first value ? } - if (t^._low>get_min_value(left.resultdef)) or (get_min_value(left.resultdef)<>0) then - cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(t^._low.svalue), hregister); - end - else - begin - { if there is no unused label between the last and the } - { present label then the lower limit can be checked } - { immediately. else check the range in between: } - - cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(t^._low.svalue-last.svalue), hregister); - { no jump necessary here if the new range starts at } - { at the value following the previous one } - if ((t^._low-last) <> 1) or - (not lastrange) then - cg.a_jmp_flags(current_asmdata.CurrAsmList,cond_lt,elselabel); - end; - {we need to use A_SUB, because A_DEC does not set the correct flags, therefor - using a_op_const_reg(OP_SUB) is not possible } - emit_const_reg(A_SUB,TCGSize2OpSize[opsize],aint(t^._high.svalue-t^._low.svalue),hregister); - cg.a_jmp_flags(current_asmdata.CurrAsmList,cond_le,blocklabel(t^.blockid)); - last:=t^._high; - lastrange:=true; - end; - first:=false; - if assigned(t^.greater) then - genitem(t^.greater); - end; - - begin - if with_sign then - begin - cond_lt:=F_L; - cond_le:=F_LE; - end - else - begin - cond_lt:=F_B; - cond_le:=F_BE; - end; - { do we need to generate cmps? } - if (with_sign and (min_label<0)) then - genlinearcmplist(hp) - else - begin - last:=0; - lastrange:=false; - first:=true; - genitem(hp); - cg.a_jmp_always(current_asmdata.CurrAsmList,elselabel); - end; - end; begin ccasenode:=ti386casenode; diff --git a/compiler/x86/nx86set.pas b/compiler/x86/nx86set.pas index d16151a1df..9a8f5c3b2b 100644 --- a/compiler/x86/nx86set.pas +++ b/compiler/x86/nx86set.pas @@ -38,6 +38,7 @@ interface tx86casenode = class(tcgcasenode) function has_jumptable : boolean;override; procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override; + procedure genlinearlist(hp : pcaselabel);override; end; implementation @@ -55,22 +56,9 @@ implementation procinfo; {***************************************************************************** - TX86INNODE + TX86CASENODE *****************************************************************************} - function tx86innode.pass_1 : tnode; - begin - result:=nil; - { this is the only difference from the generic version } - expectloc:=LOC_FLAGS; - - firstpass(right); - firstpass(left); - if codegenerror then - exit; - end; - - function tx86casenode.has_jumptable : boolean; begin {$ifdef i386} @@ -150,6 +138,109 @@ implementation genitem(jtlist,hp); end; + procedure tx86casenode.genlinearlist(hp : pcaselabel); + var + first : boolean; + lastrange : boolean; + last : TConstExprInt; + cond_lt,cond_le : tresflags; + + procedure genitem(t : pcaselabel); + begin + if assigned(t^.less) then + genitem(t^.less); + { need we to test the first value } + if first and (t^._low>get_min_value(left.resultdef)) then + begin + cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_lt,aint(t^._low.svalue),hregister,elselabel); + end; + if t^._low=t^._high then + begin + if t^._low-last=0 then + cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_EQ,0,hregister,blocklabel(t^.blockid)) + else + begin + cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(t^._low.svalue-last.svalue), hregister); + cg.a_jmp_flags(current_asmdata.CurrAsmList,F_E,blocklabel(t^.blockid)); + end; + last:=t^._low; + lastrange:=false; + end + else + begin + { it begins with the smallest label, if the value } + { is even smaller then jump immediately to the } + { ELSE-label } + if first then + begin + { have we to ajust the first value ? } + if (t^._low>get_min_value(left.resultdef)) or (get_min_value(left.resultdef)<>0) then + cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(t^._low.svalue), hregister); + end + else + begin + { if there is no unused label between the last and the } + { present label then the lower limit can be checked } + { immediately. else check the range in between: } + + cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(t^._low.svalue-last.svalue), hregister); + { no jump necessary here if the new range starts at } + { at the value following the previous one } + if ((t^._low-last) <> 1) or + (not lastrange) then + cg.a_jmp_flags(current_asmdata.CurrAsmList,cond_lt,elselabel); + end; + {we need to use A_SUB, because A_DEC does not set the correct flags, therefor + using a_op_const_reg(OP_SUB) is not possible } + emit_const_reg(A_SUB,TCGSize2OpSize[opsize],aint(t^._high.svalue-t^._low.svalue),hregister); + cg.a_jmp_flags(current_asmdata.CurrAsmList,cond_le,blocklabel(t^.blockid)); + last:=t^._high; + lastrange:=true; + end; + first:=false; + if assigned(t^.greater) then + genitem(t^.greater); + end; + + begin + if with_sign then + begin + cond_lt:=F_L; + cond_le:=F_LE; + end + else + begin + cond_lt:=F_B; + cond_le:=F_BE; + end; + { do we need to generate cmps? } + if (with_sign and (min_label<0)) then + genlinearcmplist(hp) + else + begin + last:=0; + lastrange:=false; + first:=true; + genitem(hp); + cg.a_jmp_always(current_asmdata.CurrAsmList,elselabel); + end; + end; + +{***************************************************************************** + TX86INNODE +*****************************************************************************} + + function tx86innode.pass_1 : tnode; + begin + result:=nil; + { this is the only difference from the generic version } + expectloc:=LOC_FLAGS; + + firstpass(right); + firstpass(left); + if codegenerror then + exit; + end; procedure tx86innode.pass_generate_code; type