فهرست منبع

* don't generate dec for case nodes of unsigned types because dec does not set the carry flag, resolves #23503

git-svn-id: trunk@23229 -
florian 12 سال پیش
والد
کامیت
feefcb6d3d
3فایلهای تغییر یافته به همراه35 افزوده شده و 6 حذف شده
  1. 1 0
      .gitattributes
  2. 17 6
      compiler/x86/nx86set.pas
  3. 17 0
      tests/webtbs/tw23503.pp

+ 1 - 0
.gitattributes

@@ -13085,6 +13085,7 @@ tests/webtbs/tw2332.pp svneol=native#text/plain
 tests/webtbs/tw23342.pp svneol=native#text/pascal
 tests/webtbs/tw23436.pp svneol=native#text/plain
 tests/webtbs/tw23447.pp svneol=native#text/pascal
+tests/webtbs/tw23503.pp svneol=native#text/pascal
 tests/webtbs/tw2351.pp svneol=native#text/plain
 tests/webtbs/tw2363.pp svneol=native#text/plain
 tests/webtbs/tw2377.pp svneol=native#text/plain

+ 17 - 6
compiler/x86/nx86set.pas

@@ -182,16 +182,27 @@ implementation
                       { 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, opcgsize, aint(t^._low.svalue-last.svalue), hregister);
-                      { no jump necessary here if the new range starts at }
-                      { at the value following the previous one           }
+                      { we need to use A_SUB, if cond_lt uses the carry flags
+                        because A_DEC does not set the correct flags, therefor
+                        using a_op_const_reg(OP_SUB) is not possible }
+                      if (cond_lt in [F_C,F_NC,F_A,F_AE,F_B,F_BE]) and (aint(t^._low.svalue-last.svalue)=1) then
+                        emit_const_reg(A_SUB,TCGSize2OpSize[opcgsize],aint(t^._low.svalue-last.svalue),hregister)
+                      else
+                        cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opcgsize, 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[opcgsize],aint(t^._high.svalue-t^._low.svalue),hregister);
+                  { we need to use A_SUB, if cond_le uses the carry flags
+                    because A_DEC does not set the correct flags, therefor
+                    using a_op_const_reg(OP_SUB) is not possible }
+                  if (cond_le in [F_C,F_NC,F_A,F_AE,F_B,F_BE]) and (aint(t^._high.svalue-t^._low.svalue)=1) then
+                    emit_const_reg(A_SUB,TCGSize2OpSize[opcgsize],aint(t^._high.svalue-t^._low.svalue),hregister)
+                  else
+                    cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opcgsize, 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;

+ 17 - 0
tests/webtbs/tw23503.pp

@@ -0,0 +1,17 @@
+{ %cpu=x86_64,i386 }
+var c: 1..3;
+begin
+	c := 2;
+	asm
+		stc
+	end;
+ 	case c of
+		1: writeln('1');
+        	2,3: writeln('2 or 3');
+		otherwise
+                  begin
+                    writeln ('Bug!');
+                    halt(1);
+                  end;
+	end;
+end.