]> git.proxmox.com Git - mirror_qemu.git/commitdiff
correct eflags evaluation order for all operations - fixed important CPU state restor...
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 30 Jun 2003 23:36:57 +0000 (23:36 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 30 Jun 2003 23:36:57 +0000 (23:36 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@303 c046a42c-6fe2-441c-8c8c-71466251a162

Makefile
dyngen.c
ops_template.h
ops_template_mem.h [new file with mode: 0644]
translate-i386.c

index 6d6458eb5e485f17d843013aeba9c17160d7ec9e..0fa0fa303d1bebf48d081f85b91d97fee091891b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -174,7 +174,7 @@ op-$(TARGET_ARCH).o: op-$(TARGET_ARCH).c
 helper-$(TARGET_ARCH).o: helper-$(TARGET_ARCH).c
        $(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $<
 
-op-i386.o: op-i386.c opreg_template.h ops_template.h
+op-i386.o: op-i386.c opreg_template.h ops_template.h ops_template_mem.h
 
 op-arm.o: op-arm.c op-arm-template.h
 
index 3e846232b425ad3b2838b96ff0a0e3b683c6da82..c6c373bd1a6b9cab373a388af6adc0d1fd591184 100644 (file)
--- a/dyngen.c
+++ b/dyngen.c
@@ -1200,11 +1200,11 @@ int load_elf(const char *filename, FILE *outfile, int out_type)
     }
 
     if (out_type == OUT_INDEX_OP) {
-        fprintf(outfile, "DEF(nop1, 0, 0)\n");
-        fprintf(outfile, "DEF(nop2, 0, 0)\n");
-        fprintf(outfile, "DEF(nop3, 0, 0)\n");
-        fprintf(outfile, "DEF(nop, 0, 0)\n");
         fprintf(outfile, "DEF(end, 0, 0)\n");
+        fprintf(outfile, "DEF(nop, 0, 0)\n");
+        fprintf(outfile, "DEF(nop1, 1, 0)\n");
+        fprintf(outfile, "DEF(nop2, 2, 0)\n");
+        fprintf(outfile, "DEF(nop3, 3, 0)\n");
         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
             const char *name, *p;
             name = strtab + sym->st_name;
index c6e2b6b971584f65ae3c35ba651c40cc2511a31e..4595291e78a9b52ac584e6637beaf5ffc0dbfe55 100644 (file)
@@ -406,127 +406,6 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
 
 /* shifts */
 
-void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
-{
-    int count, src;
-    count = T1 & SHIFT_MASK;
-    if (count) {
-        CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
-        src = T0;
-        T0 &= DATA_MASK;
-        T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
-        CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
-            (T0 & CC_C);
-        CC_OP = CC_OP_EFLAGS;
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1)(void)
-{
-    int count;
-    count = T1 & SHIFT_MASK;
-    if (count) {
-        T0 &= DATA_MASK;
-        T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
-{
-    int count, src;
-    count = T1 & SHIFT_MASK;
-    if (count) {
-        CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
-        src = T0;
-        T0 &= DATA_MASK;
-        T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
-        CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
-            ((T0 >> (DATA_BITS - 1)) & CC_C);
-        CC_OP = CC_OP_EFLAGS;
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1)(void)
-{
-    int count;
-    count = T1 & SHIFT_MASK;
-    if (count) {
-        T0 &= DATA_MASK;
-        T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
-{
-    int count, res, eflags;
-    unsigned int src;
-
-    count = T1 & 0x1f;
-#if DATA_BITS == 16
-    count = rclw_table[count];
-#elif DATA_BITS == 8
-    count = rclb_table[count];
-#endif
-    if (count) {
-        eflags = cc_table[CC_OP].compute_all();
-        T0 &= DATA_MASK;
-        src = T0;
-        res = (T0 << count) | ((eflags & CC_C) << (count - 1));
-        if (count > 1)
-            res |= T0 >> (DATA_BITS + 1 - count);
-        T0 = res;
-        CC_SRC = (eflags & ~(CC_C | CC_O)) |
-            (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
-            ((src >> (DATA_BITS - count)) & CC_C);
-        CC_OP = CC_OP_EFLAGS;
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
-{
-    int count, res, eflags;
-    unsigned int src;
-
-    count = T1 & 0x1f;
-#if DATA_BITS == 16
-    count = rclw_table[count];
-#elif DATA_BITS == 8
-    count = rclb_table[count];
-#endif
-    if (count) {
-        eflags = cc_table[CC_OP].compute_all();
-        T0 &= DATA_MASK;
-        src = T0;
-        res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
-        if (count > 1)
-            res |= T0 << (DATA_BITS + 1 - count);
-        T0 = res;
-        CC_SRC = (eflags & ~(CC_C | CC_O)) |
-            (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
-            ((src >> (count - 1)) & CC_C);
-        CC_OP = CC_OP_EFLAGS;
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
-{
-    int count;
-    count = T1 & 0x1f;
-    if (count) {
-        CC_SRC = (DATA_TYPE)T0 << (count - 1);
-        T0 = T0 << count;
-        CC_DST = T0;
-        CC_OP = CC_OP_SHLB + SHIFT;
-    }
-    FORCE_RET();
-}
-
 void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void)
 {
     int count;
@@ -535,20 +414,6 @@ void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void)
     FORCE_RET();
 }
 
-void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
-{
-    int count;
-    count = T1 & 0x1f;
-    if (count) {
-        T0 &= DATA_MASK;
-        CC_SRC = T0 >> (count - 1);
-        T0 = T0 >> count;
-        CC_DST = T0;
-        CC_OP = CC_OP_SARB + SHIFT;
-    }
-    FORCE_RET();
-}
-
 void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void)
 {
     int count;
@@ -558,20 +423,6 @@ void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void)
     FORCE_RET();
 }
 
-void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
-{
-    int count, src;
-    count = T1 & 0x1f;
-    if (count) {
-        src = (DATA_STYPE)T0;
-        CC_SRC = src >> (count - 1);
-        T0 = src >> count;
-        CC_DST = T0;
-        CC_OP = CC_OP_SARB + SHIFT;
-    }
-    FORCE_RET();
-}
-
 void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void)
 {
     int count, src;
@@ -581,162 +432,11 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void)
     FORCE_RET();
 }
 
-#if DATA_BITS == 16
-/* XXX: overflow flag might be incorrect in some cases in shldw */
-void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
-{
-    int count;
-    unsigned int res;
-    count = PARAM1;
-    T1 &= 0xffff;
-    res = T1 | (T0 << 16);
-    CC_SRC = res >> (32 - count);
-    res <<= count;
-    if (count > 16)
-        res |= T1 << (count - 16);
-    T0 = res >> 16;
-    CC_DST = T0;
-}
-
-void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
-{
-    int count;
-    unsigned int res;
-    count = ECX & 0x1f;
-    if (count) {
-        T1 &= 0xffff;
-        res = T1 | (T0 << 16);
-        CC_SRC = res >> (32 - count);
-        res <<= count;
-        if (count > 16)
-          res |= T1 << (count - 16);
-        T0 = res >> 16;
-        CC_DST = T0;
-        CC_OP = CC_OP_SARB + SHIFT;
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
-{
-    int count;
-    unsigned int res;
-
-    count = PARAM1;
-    res = (T0 & 0xffff) | (T1 << 16);
-    CC_SRC = res >> (count - 1);
-    res >>= count;
-    if (count > 16)
-        res |= T1 << (32 - count);
-    T0 = res;
-    CC_DST = T0;
-}
-
-
-void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
-{
-    int count;
-    unsigned int res;
-
-    count = ECX & 0x1f;
-    if (count) {
-        res = (T0 & 0xffff) | (T1 << 16);
-        CC_SRC = res >> (count - 1);
-        res >>= count;
-        if (count > 16)
-            res |= T1 << (32 - count);
-        T0 = res;
-        CC_DST = T0;
-        CC_OP = CC_OP_SARB + SHIFT;
-    }
-    FORCE_RET();
-}
-#endif
-
-#if DATA_BITS == 32
-void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
-{
-    int count;
-    count = PARAM1;
-    T0 &= DATA_MASK;
-    T1 &= DATA_MASK;
-    CC_SRC = T0 << (count - 1);
-    T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
-    CC_DST = T0;
-}
-
-void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
-{
-    int count;
-    count = ECX & 0x1f;
-    if (count) {
-        T0 &= DATA_MASK;
-        T1 &= DATA_MASK;
-        CC_SRC = T0 << (count - 1);
-        T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
-        CC_DST = T0;
-        CC_OP = CC_OP_SHLB + SHIFT;
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
-{
-    int count;
-    count = PARAM1;
-    T0 &= DATA_MASK;
-    T1 &= DATA_MASK;
-    CC_SRC = T0 >> (count - 1);
-    T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
-    CC_DST = T0;
-}
+#undef MEM_WRITE
+#include "ops_template_mem.h"
 
-
-void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
-{
-    int count;
-    count = ECX & 0x1f;
-    if (count) {
-        T0 &= DATA_MASK;
-        T1 &= DATA_MASK;
-        CC_SRC = T0 >> (count - 1);
-        T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
-        CC_DST = T0;
-        CC_OP = CC_OP_SARB + SHIFT;
-    }
-    FORCE_RET();
-}
-#endif
-
-/* carry add/sub (we only need to set CC_OP differently) */
-
-void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
-{
-    int cf;
-    cf = cc_table[CC_OP].compute_c();
-    T0 = T0 + T1 + cf;
-    CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
-}
-
-void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
-{
-    int cf;
-    cf = cc_table[CC_OP].compute_c();
-    T0 = T0 - T1 - cf;
-    CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
-}
-
-void OPPROTO glue(glue(op_cmpxchg, SUFFIX), _T0_T1_EAX_cc)(void)
-{
-    CC_SRC = T0;
-    CC_DST = EAX - T0;
-    if ((DATA_TYPE)CC_DST == 0) {
-        T0 = T1;
-    } else {
-        EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
-    }
-    FORCE_RET();
-}
+#define MEM_WRITE
+#include "ops_template_mem.h"
 
 /* bit operations */
 #if DATA_BITS >= 16
@@ -752,7 +452,7 @@ void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
 {
     int count;
     count = T1 & SHIFT_MASK;
-    CC_SRC = T0 >> count;
+    T1 = T0 >> count;
     T0 |= (1 << count);
 }
 
@@ -760,7 +460,7 @@ void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
 {
     int count;
     count = T1 & SHIFT_MASK;
-    CC_SRC = T0 >> count;
+    T1 = T0 >> count;
     T0 &= ~(1 << count);
 }
 
@@ -768,7 +468,7 @@ void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
 {
     int count;
     count = T1 & SHIFT_MASK;
-    CC_SRC = T0 >> count;
+    T1 = T0 >> count;
     T0 ^= (1 << count);
 }
 
@@ -810,6 +510,13 @@ void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
 
 #endif
 
+#if DATA_BITS == 32
+void OPPROTO op_update_bt_cc(void)
+{
+    CC_SRC = T1;
+}
+#endif
+
 /* string operations */
 /* XXX: maybe use lower level instructions to ease 16 bit / segment handling */
 
diff --git a/ops_template_mem.h b/ops_template_mem.h
new file mode 100644 (file)
index 0000000..f1209d2
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ *  i386 micro operations (included several times to generate
+ *  different operand sizes)
+ * 
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifdef MEM_WRITE
+
+#if DATA_BITS == 8
+#define MEM_SUFFIX b_mem
+#elif DATA_BITS == 16
+#define MEM_SUFFIX w_mem
+#elif DATA_BITS == 32
+#define MEM_SUFFIX l_mem
+#endif
+
+#else
+
+#define MEM_SUFFIX SUFFIX
+
+#endif
+
+void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1_cc)(void)
+{
+    int count, src;
+    count = T1 & SHIFT_MASK;
+    if (count) {
+        src = T0;
+        T0 &= DATA_MASK;
+        T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+        CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) | 
+            (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
+            (T0 & CC_C);
+        CC_OP = CC_OP_EFLAGS;
+    }
+    FORCE_RET();
+}
+
+void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1_cc)(void)
+{
+    int count, src;
+    count = T1 & SHIFT_MASK;
+    if (count) {
+        src = T0;
+        T0 &= DATA_MASK;
+        T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+        CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) |
+            (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
+            ((T0 >> (DATA_BITS - 1)) & CC_C);
+        CC_OP = CC_OP_EFLAGS;
+    }
+    FORCE_RET();
+}
+
+void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1)(void)
+{
+    int count;
+    count = T1 & SHIFT_MASK;
+    if (count) {
+        T0 &= DATA_MASK;
+        T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+    }
+    FORCE_RET();
+}
+
+void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1)(void)
+{
+    int count;
+    count = T1 & SHIFT_MASK;
+    if (count) {
+        T0 &= DATA_MASK;
+        T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+    }
+    FORCE_RET();
+}
+
+void OPPROTO glue(glue(op_rcl, MEM_SUFFIX), _T0_T1_cc)(void)
+{
+    int count, res, eflags;
+    unsigned int src;
+
+    count = T1 & 0x1f;
+#if DATA_BITS == 16
+    count = rclw_table[count];
+#elif DATA_BITS == 8
+    count = rclb_table[count];
+#endif
+    if (count) {
+        eflags = cc_table[CC_OP].compute_all();
+        T0 &= DATA_MASK;
+        src = T0;
+        res = (T0 << count) | ((eflags & CC_C) << (count - 1));
+        if (count > 1)
+            res |= T0 >> (DATA_BITS + 1 - count);
+        T0 = res;
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+        CC_SRC = (eflags & ~(CC_C | CC_O)) |
+            (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
+            ((src >> (DATA_BITS - count)) & CC_C);
+        CC_OP = CC_OP_EFLAGS;
+    }
+    FORCE_RET();
+}
+
+void OPPROTO glue(glue(op_rcr, MEM_SUFFIX), _T0_T1_cc)(void)
+{
+    int count, res, eflags;
+    unsigned int src;
+
+    count = T1 & 0x1f;
+#if DATA_BITS == 16
+    count = rclw_table[count];
+#elif DATA_BITS == 8
+    count = rclb_table[count];
+#endif
+    if (count) {
+        eflags = cc_table[CC_OP].compute_all();
+        T0 &= DATA_MASK;
+        src = T0;
+        res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
+        if (count > 1)
+            res |= T0 << (DATA_BITS + 1 - count);
+        T0 = res;
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+        CC_SRC = (eflags & ~(CC_C | CC_O)) |
+            (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
+            ((src >> (count - 1)) & CC_C);
+        CC_OP = CC_OP_EFLAGS;
+    }
+    FORCE_RET();
+}
+
+void OPPROTO glue(glue(op_shl, MEM_SUFFIX), _T0_T1_cc)(void)
+{
+    int count, src;
+    count = T1 & 0x1f;
+    if (count) {
+        src = (DATA_TYPE)T0 << (count - 1);
+        T0 = T0 << count;
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+        CC_SRC = src;
+        CC_DST = T0;
+        CC_OP = CC_OP_SHLB + SHIFT;
+    }
+    FORCE_RET();
+}
+
+void OPPROTO glue(glue(op_shr, MEM_SUFFIX), _T0_T1_cc)(void)
+{
+    int count, src;
+    count = T1 & 0x1f;
+    if (count) {
+        T0 &= DATA_MASK;
+        src = T0 >> (count - 1);
+        T0 = T0 >> count;
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+        CC_SRC = src;
+        CC_DST = T0;
+        CC_OP = CC_OP_SARB + SHIFT;
+    }
+    FORCE_RET();
+}
+
+void OPPROTO glue(glue(op_sar, MEM_SUFFIX), _T0_T1_cc)(void)
+{
+    int count, src;
+    count = T1 & 0x1f;
+    if (count) {
+        src = (DATA_STYPE)T0;
+        T0 = src >> count;
+        src = src >> (count - 1);
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+        CC_SRC = src;
+        CC_DST = T0;
+        CC_OP = CC_OP_SARB + SHIFT;
+    }
+    FORCE_RET();
+}
+
+#if DATA_BITS == 16
+/* XXX: overflow flag might be incorrect in some cases in shldw */
+void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
+{
+    int count;
+    unsigned int res, tmp;
+    count = PARAM1;
+    T1 &= 0xffff;
+    res = T1 | (T0 << 16);
+    tmp = res >> (32 - count);
+    res <<= count;
+    if (count > 16)
+        res |= T1 << (count - 16);
+    T0 = res >> 16;
+#ifdef MEM_WRITE
+    glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+    CC_SRC = tmp;
+    CC_DST = T0;
+}
+
+void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
+{
+    int count;
+    unsigned int res, tmp;
+    count = ECX & 0x1f;
+    if (count) {
+        T1 &= 0xffff;
+        res = T1 | (T0 << 16);
+        tmp = res >> (32 - count);
+        res <<= count;
+        if (count > 16)
+          res |= T1 << (count - 16);
+        T0 = res >> 16;
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+        CC_SRC = tmp;
+        CC_DST = T0;
+        CC_OP = CC_OP_SARB + SHIFT;
+    }
+    FORCE_RET();
+}
+
+void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
+{
+    int count;
+    unsigned int res, tmp;
+
+    count = PARAM1;
+    res = (T0 & 0xffff) | (T1 << 16);
+    tmp = res >> (count - 1);
+    res >>= count;
+    if (count > 16)
+        res |= T1 << (32 - count);
+    T0 = res;
+#ifdef MEM_WRITE
+    glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+    CC_SRC = tmp;
+    CC_DST = T0;
+}
+
+
+void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
+{
+    int count;
+    unsigned int res, tmp;
+
+    count = ECX & 0x1f;
+    if (count) {
+        res = (T0 & 0xffff) | (T1 << 16);
+        tmp = res >> (count - 1);
+        res >>= count;
+        if (count > 16)
+            res |= T1 << (32 - count);
+        T0 = res;
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+        CC_SRC = tmp;
+        CC_DST = T0;
+        CC_OP = CC_OP_SARB + SHIFT;
+    }
+    FORCE_RET();
+}
+#endif
+
+#if DATA_BITS == 32
+void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
+{
+    int count, tmp;
+    count = PARAM1;
+    T0 &= DATA_MASK;
+    T1 &= DATA_MASK;
+    tmp = T0 << (count - 1);
+    T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
+#ifdef MEM_WRITE
+    glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+    CC_SRC = tmp;
+    CC_DST = T0;
+}
+
+void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
+{
+    int count, tmp;
+    count = ECX & 0x1f;
+    if (count) {
+        T0 &= DATA_MASK;
+        T1 &= DATA_MASK;
+        tmp = T0 << (count - 1);
+        T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+        CC_SRC = tmp;
+        CC_DST = T0;
+        CC_OP = CC_OP_SHLB + SHIFT;
+    }
+    FORCE_RET();
+}
+
+void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
+{
+    int count, tmp;
+    count = PARAM1;
+    T0 &= DATA_MASK;
+    T1 &= DATA_MASK;
+    tmp = T0 >> (count - 1);
+    T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
+#ifdef MEM_WRITE
+    glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+    CC_SRC = tmp;
+    CC_DST = T0;
+}
+
+
+void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
+{
+    int count, tmp;
+    count = ECX & 0x1f;
+    if (count) {
+        T0 &= DATA_MASK;
+        T1 &= DATA_MASK;
+        tmp = T0 >> (count - 1);
+        T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
+#ifdef MEM_WRITE
+        glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+        CC_SRC = tmp;
+        CC_DST = T0;
+        CC_OP = CC_OP_SARB + SHIFT;
+    }
+    FORCE_RET();
+}
+#endif
+
+/* carry add/sub (we only need to set CC_OP differently) */
+
+void OPPROTO glue(glue(op_adc, MEM_SUFFIX), _T0_T1_cc)(void)
+{
+    int cf;
+    cf = cc_table[CC_OP].compute_c();
+    T0 = T0 + T1 + cf;
+#ifdef MEM_WRITE
+    glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+    CC_SRC = T1;
+    CC_DST = T0;
+    CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
+}
+
+void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void)
+{
+    int cf;
+    cf = cc_table[CC_OP].compute_c();
+    T0 = T0 - T1 - cf;
+#ifdef MEM_WRITE
+    glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+    CC_SRC = T1;
+    CC_DST = T0;
+    CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
+}
+
+void OPPROTO glue(glue(op_cmpxchg, MEM_SUFFIX), _T0_T1_EAX_cc)(void)
+{
+    unsigned int src, dst;
+
+    src = T0;
+    dst = EAX - T0;
+    if ((DATA_TYPE)dst == 0) {
+        T0 = T1;
+    } else {
+        EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
+    }
+#ifdef MEM_WRITE
+    glue(st, SUFFIX)((uint8_t *)A0, T0);
+#endif
+    CC_SRC = src;
+    CC_DST = dst;
+    FORCE_RET();
+}
+
+#undef MEM_SUFFIX
+#undef MEM_WRITE
index 8a7147c5563ed9e19f284f861d593c2455a033af..bfc988446e0fb5f0f1e8132085928e8c16a6b911 100644 (file)
@@ -390,6 +390,21 @@ static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
     },
 };
 
+static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3][2] = {
+    [OT_BYTE] = {
+        gen_op_adcb_mem_T0_T1_cc,
+        gen_op_sbbb_mem_T0_T1_cc,
+    },
+    [OT_WORD] = {
+        gen_op_adcw_mem_T0_T1_cc,
+        gen_op_sbbw_mem_T0_T1_cc,
+    },
+    [OT_LONG] = {
+        gen_op_adcl_mem_T0_T1_cc,
+        gen_op_sbbl_mem_T0_T1_cc,
+    },
+};
+
 static const int cc_op_arithb[8] = {
     CC_OP_ADDB,
     CC_OP_LOGICB,
@@ -407,6 +422,12 @@ static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
     gen_op_cmpxchgl_T0_T1_EAX_cc,
 };
 
+static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3] = {
+    gen_op_cmpxchgb_mem_T0_T1_EAX_cc,
+    gen_op_cmpxchgw_mem_T0_T1_EAX_cc,
+    gen_op_cmpxchgl_mem_T0_T1_EAX_cc,
+};
+
 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
     [OT_BYTE] = {
         gen_op_rolb_T0_T1_cc,
@@ -440,6 +461,39 @@ static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
     },
 };
 
+static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3][8] = {
+    [OT_BYTE] = {
+        gen_op_rolb_mem_T0_T1_cc,
+        gen_op_rorb_mem_T0_T1_cc,
+        gen_op_rclb_mem_T0_T1_cc,
+        gen_op_rcrb_mem_T0_T1_cc,
+        gen_op_shlb_mem_T0_T1_cc,
+        gen_op_shrb_mem_T0_T1_cc,
+        gen_op_shlb_mem_T0_T1_cc,
+        gen_op_sarb_mem_T0_T1_cc,
+    },
+    [OT_WORD] = {
+        gen_op_rolw_mem_T0_T1_cc,
+        gen_op_rorw_mem_T0_T1_cc,
+        gen_op_rclw_mem_T0_T1_cc,
+        gen_op_rcrw_mem_T0_T1_cc,
+        gen_op_shlw_mem_T0_T1_cc,
+        gen_op_shrw_mem_T0_T1_cc,
+        gen_op_shlw_mem_T0_T1_cc,
+        gen_op_sarw_mem_T0_T1_cc,
+    },
+    [OT_LONG] = {
+        gen_op_roll_mem_T0_T1_cc,
+        gen_op_rorl_mem_T0_T1_cc,
+        gen_op_rcll_mem_T0_T1_cc,
+        gen_op_rcrl_mem_T0_T1_cc,
+        gen_op_shll_mem_T0_T1_cc,
+        gen_op_shrl_mem_T0_T1_cc,
+        gen_op_shll_mem_T0_T1_cc,
+        gen_op_sarl_mem_T0_T1_cc,
+    },
+};
+
 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
     [0] = {
         gen_op_shldw_T0_T1_im_cc,
@@ -462,6 +516,28 @@ static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
     },
 };
 
+static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[2][2] = {
+    [0] = {
+        gen_op_shldw_mem_T0_T1_im_cc,
+        gen_op_shrdw_mem_T0_T1_im_cc,
+    },
+    [1] = {
+        gen_op_shldl_mem_T0_T1_im_cc,
+        gen_op_shrdl_mem_T0_T1_im_cc,
+    },
+};
+
+static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[2][2] = {
+    [0] = {
+        gen_op_shldw_mem_T0_T1_ECX_cc,
+        gen_op_shrdw_mem_T0_T1_ECX_cc,
+    },
+    [1] = {
+        gen_op_shldl_mem_T0_T1_ECX_cc,
+        gen_op_shrdl_mem_T0_T1_ECX_cc,
+    },
+};
+
 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
     [0] = {
         gen_op_btw_T0_T1_cc,
@@ -763,11 +839,14 @@ static void gen_op(DisasContext *s1, int op, int ot, int d)
     case OP_SBBL:
         if (s1->cc_op != CC_OP_DYNAMIC)
             gen_op_set_cc_op(s1->cc_op);
-        gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
+        if (d != OR_TMP0) {
+            gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
+            gen_op_mov_reg_T0[ot][d]();
+        } else {
+            gen_op_arithc_mem_T0_T1_cc[ot][op - OP_ADCL]();
+        }
         s1->cc_op = CC_OP_DYNAMIC;
-        /* XXX: incorrect: CC_OP must also be modified AFTER memory access */
-        gen_update_cc = gen_op_update2_cc;
-        break;
+        goto the_end;
     case OP_ADDL:
         gen_op_addl_T0_T1();
         s1->cc_op = CC_OP_ADDB + ot;
@@ -802,6 +881,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d)
        exception support) */
     if (gen_update_cc)
         gen_update_cc();
+ the_end: ;
 }
 
 /* if d == OR_TMP0, it means memory operand (address in A0) */
@@ -831,14 +911,18 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
 {
     if (d != OR_TMP0)
         gen_op_mov_TN_reg[ot][0][d]();
+    else
+        gen_op_ld_T0_A0[ot]();
     if (s != OR_TMP1)
         gen_op_mov_TN_reg[ot][1][s]();
     /* for zero counts, flags are not updated, so must do it dynamically */
     if (s1->cc_op != CC_OP_DYNAMIC)
         gen_op_set_cc_op(s1->cc_op);
-
-    gen_op_shift_T0_T1_cc[ot][op]();
-
+    
+    if (d != OR_TMP0)
+        gen_op_shift_T0_T1_cc[ot][op]();
+    else
+        gen_op_shift_mem_T0_T1_cc[ot][op]();
     if (d != OR_TMP0)
         gen_op_mov_reg_T0[ot][d]();
     s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
@@ -1885,8 +1969,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
         } else {
             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
             gen_op_ld_T0_A0[ot]();
-            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
-            gen_op_st_T0_A0[ot]();
+            gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot]();
         }
         s->cc_op = CC_OP_SUBB + ot;
         break;
@@ -2264,7 +2347,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
             
             if (mod != 3) {
                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
-                gen_op_ld_T0_A0[ot]();
                 opreg = OR_TMP0;
             } else {
                 opreg = rm + OR_EAX;
@@ -2279,10 +2361,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
                 }
                 gen_shifti(s, op, ot, opreg, shift);
             }
-
-            if (mod != 3) {
-                gen_op_st_T0_A0[ot]();
-            }
         }
         break;
     case 0xd0:
@@ -2330,7 +2408,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
             val = ldub(s->pc++);
             val &= 0x1f;
             if (val) {
-                gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
+                if (mod == 3)
+                    gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
+                else
+                    gen_op_shiftd_mem_T0_T1_im_cc[ot - OT_WORD][op](val);
                 if (op == 0 && ot != OT_WORD)
                     s->cc_op = CC_OP_SHLB + ot;
                 else
@@ -2339,12 +2420,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
         } else {
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
-            gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
+            if (mod == 3)
+                gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
+            else
+                gen_op_shiftd_mem_T0_T1_ECX_cc[ot - OT_WORD][op]();
             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
         }
-        if (mod != 3) {
-            gen_op_st_T0_A0[ot]();
-        } else {
+        if (mod == 3) {
             gen_op_mov_reg_T0[ot][rm]();
         }
         break;
@@ -3202,6 +3284,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
                 gen_op_st_T0_A0[ot]();
             else
                 gen_op_mov_reg_T0[ot][rm]();
+            gen_op_update_bt_cc();
         }
         break;
     case 0x1a3: /* bt Gv, Ev */
@@ -3240,6 +3323,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
                 gen_op_st_T0_A0[ot]();
             else
                 gen_op_mov_reg_T0[ot][rm]();
+            gen_op_update_bt_cc();
         }
         break;
     case 0x1bc: /* bsf */
@@ -3640,6 +3724,13 @@ static uint16_t opc_read_flags[NB_OPS] = {
     [INDEX_op_sbbw_T0_T1_cc] = CC_C,
     [INDEX_op_sbbl_T0_T1_cc] = CC_C,
 
+    [INDEX_op_adcb_mem_T0_T1_cc] = CC_C,
+    [INDEX_op_adcw_mem_T0_T1_cc] = CC_C,
+    [INDEX_op_adcl_mem_T0_T1_cc] = CC_C,
+    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_C,
+    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_C,
+    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_C,
+
     /* subtle: due to the incl/decl implementation, C is used */
     [INDEX_op_update_inc_cc] = CC_C, 
 
@@ -3717,23 +3808,38 @@ static uint16_t opc_read_flags[NB_OPS] = {
     [INDEX_op_rcrb_T0_T1_cc] = CC_C,
     [INDEX_op_rcrw_T0_T1_cc] = CC_C,
     [INDEX_op_rcrl_T0_T1_cc] = CC_C,
+
+    [INDEX_op_rclb_mem_T0_T1_cc] = CC_C,
+    [INDEX_op_rclw_mem_T0_T1_cc] = CC_C,
+    [INDEX_op_rcll_mem_T0_T1_cc] = CC_C,
+    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_C,
+    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_C,
+    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_C,
 };
 
 /* flags written by an operation */
 static uint16_t opc_write_flags[NB_OPS] = { 
     [INDEX_op_update2_cc] = CC_OSZAPC,
     [INDEX_op_update1_cc] = CC_OSZAPC,
+    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_update_neg_cc] = CC_OSZAPC,
+    /* subtle: due to the incl/decl implementation, C is used */
+    [INDEX_op_update_inc_cc] = CC_OSZAPC, 
+    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
+
     [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
     [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
     [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
     [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
     [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
     [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
-    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
-    [INDEX_op_update_neg_cc] = CC_OSZAPC,
-    /* subtle: due to the incl/decl implementation, C is used */
-    [INDEX_op_update_inc_cc] = CC_OSZAPC, 
-    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
+
+    [INDEX_op_adcb_mem_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_adcw_mem_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_adcl_mem_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_OSZAPC,
 
     [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
     [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
@@ -3795,6 +3901,42 @@ static uint16_t opc_write_flags[NB_OPS] = {
     [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
     [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
 
+    [INDEX_op_rolb_mem_T0_T1_cc] = CC_O | CC_C,
+    [INDEX_op_rolw_mem_T0_T1_cc] = CC_O | CC_C,
+    [INDEX_op_roll_mem_T0_T1_cc] = CC_O | CC_C,
+    [INDEX_op_rorb_mem_T0_T1_cc] = CC_O | CC_C,
+    [INDEX_op_rorw_mem_T0_T1_cc] = CC_O | CC_C,
+    [INDEX_op_rorl_mem_T0_T1_cc] = CC_O | CC_C,
+
+    [INDEX_op_rclb_mem_T0_T1_cc] = CC_O | CC_C,
+    [INDEX_op_rclw_mem_T0_T1_cc] = CC_O | CC_C,
+    [INDEX_op_rcll_mem_T0_T1_cc] = CC_O | CC_C,
+    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_O | CC_C,
+    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_O | CC_C,
+    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_O | CC_C,
+
+    [INDEX_op_shlb_mem_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_shlw_mem_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_shll_mem_T0_T1_cc] = CC_OSZAPC,
+
+    [INDEX_op_shrb_mem_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_shrw_mem_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_shrl_mem_T0_T1_cc] = CC_OSZAPC,
+
+    [INDEX_op_sarb_mem_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_sarw_mem_T0_T1_cc] = CC_OSZAPC,
+    [INDEX_op_sarl_mem_T0_T1_cc] = CC_OSZAPC,
+
+    [INDEX_op_shldw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
+    [INDEX_op_shldl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
+    [INDEX_op_shldw_mem_T0_T1_im_cc] = CC_OSZAPC,
+    [INDEX_op_shldl_mem_T0_T1_im_cc] = CC_OSZAPC,
+
+    [INDEX_op_shrdw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
+    [INDEX_op_shrdl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
+    [INDEX_op_shrdw_mem_T0_T1_im_cc] = CC_OSZAPC,
+    [INDEX_op_shrdl_mem_T0_T1_im_cc] = CC_OSZAPC,
+
     [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
     [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
     [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
@@ -3832,6 +3974,10 @@ static uint16_t opc_write_flags[NB_OPS] = {
     [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
     [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
 
+    [INDEX_op_cmpxchgb_mem_T0_T1_EAX_cc] = CC_OSZAPC,
+    [INDEX_op_cmpxchgw_mem_T0_T1_EAX_cc] = CC_OSZAPC,
+    [INDEX_op_cmpxchgl_mem_T0_T1_EAX_cc] = CC_OSZAPC,
+
     [INDEX_op_cmpxchg8b] = CC_Z,
     [INDEX_op_lar] = CC_Z,
     [INDEX_op_lsl] = CC_Z,
@@ -3844,8 +3990,10 @@ static uint16_t opc_simpler[NB_OPS] = {
     [INDEX_op_update2_cc] = INDEX_op_nop,
     [INDEX_op_update1_cc] = INDEX_op_nop,
     [INDEX_op_update_neg_cc] = INDEX_op_nop,
+#if 0
+    /* broken: CC_OP logic must be rewritten */
     [INDEX_op_update_inc_cc] = INDEX_op_nop,
-
+#endif
     [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
     [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
     [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
@@ -3854,6 +4002,14 @@ static uint16_t opc_simpler[NB_OPS] = {
     [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
     [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
 
+    [INDEX_op_rolb_mem_T0_T1_cc] = INDEX_op_rolb_mem_T0_T1,
+    [INDEX_op_rolw_mem_T0_T1_cc] = INDEX_op_rolw_mem_T0_T1,
+    [INDEX_op_roll_mem_T0_T1_cc] = INDEX_op_roll_mem_T0_T1,
+
+    [INDEX_op_rorb_mem_T0_T1_cc] = INDEX_op_rorb_mem_T0_T1,
+    [INDEX_op_rorw_mem_T0_T1_cc] = INDEX_op_rorw_mem_T0_T1,
+    [INDEX_op_rorl_mem_T0_T1_cc] = INDEX_op_rorl_mem_T0_T1,
+
     [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
     [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
     [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
@@ -3971,6 +4127,10 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc
             break;
     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
              (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
+    if (!dc->tf && dc->is_jmp == DISAS_NEXT) {
+        gen_jmp(dc, ret - (unsigned long)dc->cs_base);
+    }
+
     /* we must store the eflags state if it is not already done */
     if (dc->is_jmp != DISAS_TB_JUMP) {
         if (dc->cc_op != CC_OP_DYNAMIC)
@@ -3983,12 +4143,19 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc
     if (dc->tf) {
         gen_op_raise_exception(EXCP01_SSTP);
     }
-    if (dc->is_jmp != 3) {
+    if (dc->is_jmp != DISAS_TB_JUMP) {
         /* indicate that the hash table must be used to find the next TB */
         gen_op_movl_T0_0();
     }
     *gen_opc_ptr = INDEX_op_end;
-
+    /* we don't forget to fill the last values */
+    if (search_pc) {
+        j = gen_opc_ptr - gen_opc_buf;
+        lj++;
+        while (lj <= j)
+            gen_opc_instr_start[lj++] = 0;
+    }
+        
 #ifdef DEBUG_DISAS
     if (loglevel) {
         fprintf(logfile, "----------------\n");