qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC] M68k emulation


From: Andreas Schwab
Subject: [Qemu-devel] [RFC] M68k emulation
Date: Mon, 02 Jul 2007 13:41:01 +0200
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/22.0.97 (gnu/linux)

This patch extends the m68k emulation to include most m68k insns.  While
it is still incomplete, it is good enough to execute code generated by
gcc.  Any comments appreciated.

Andreas.

Index: target-m68k/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-m68k/cpu.h,v
retrieving revision 1.11
diff -u -a -p -r1.11 cpu.h
--- target-m68k/cpu.h   3 Jun 2007 21:02:38 -0000       1.11
+++ target-m68k/cpu.h   2 Jul 2007 11:27:58 -0000
@@ -86,7 +86,10 @@ typedef struct CPUM68KState {
     /* Temporary storage for DIV helpers.  */
     uint32_t div1;
     uint32_t div2;
-    
+
+    /* Upper 32 bits of a 64bit operand for quad MUL/DIV.  */
+    uint32_t quadh;
+
     /* MMU status.  */
     struct {
         uint32_t ar;
@@ -133,14 +136,26 @@ enum {
     CC_OP_DYNAMIC, /* Use env->cc_op  */
     CC_OP_FLAGS, /* CC_DEST = CVZN, CC_SRC = unused */
     CC_OP_LOGIC, /* CC_DEST = result, CC_SRC = unused */
+    CC_OP_ADDB,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_ADDW,  /* CC_DEST = result, CC_SRC = source */
     CC_OP_ADD,   /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBB,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBW,  /* CC_DEST = result, CC_SRC = source */
     CC_OP_SUB,   /* CC_DEST = result, CC_SRC = source */
-    CC_OP_CMPB,  /* CC_DEST = result, CC_SRC = source */
-    CC_OP_CMPW,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_ADDXB, /* CC_DEST = result, CC_SRC = source */
+    CC_OP_ADDXW, /* CC_DEST = result, CC_SRC = source */
     CC_OP_ADDX,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBXB, /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBXW, /* CC_DEST = result, CC_SRC = source */
     CC_OP_SUBX,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SHLB,  /* CC_DEST = source, CC_SRC = shift */
+    CC_OP_SHLW,  /* CC_DEST = source, CC_SRC = shift */
     CC_OP_SHL,   /* CC_DEST = source, CC_SRC = shift */
+    CC_OP_SHRB,  /* CC_DEST = source, CC_SRC = shift */
+    CC_OP_SHRW,  /* CC_DEST = source, CC_SRC = shift */
     CC_OP_SHR,   /* CC_DEST = source, CC_SRC = shift */
+    CC_OP_SARB,  /* CC_DEST = source, CC_SRC = shift */
+    CC_OP_SARW,  /* CC_DEST = source, CC_SRC = shift */
     CC_OP_SAR,   /* CC_DEST = source, CC_SRC = shift */
 };
 
@@ -189,6 +204,7 @@ void do_m68k_semihosting(CPUM68KState *e
    ISA revisions mentioned.  */
 
 enum m68k_features {
+    M68K_FEATURE_M68000,
     M68K_FEATURE_CF_ISA_A,
     M68K_FEATURE_CF_ISA_B, /* (ISA B or C).  */
     M68K_FEATURE_CF_ISA_APLUSC, /* BIT/BITREV, FF1, STRLDSR (ISA A+ or C).  */
@@ -199,7 +215,13 @@ enum m68k_features {
     M68K_FEATURE_CF_EMAC_B, /* Revision B EMAC (dual accumulate).  */
     M68K_FEATURE_USP, /* User Stack Pointer.  (ISA A+, B or C).  */
     M68K_FEATURE_EXT_FULL, /* 68020+ full extension word.  */
-    M68K_FEATURE_WORD_INDEX /* word sized address index registers.  */
+    M68K_FEATURE_WORD_INDEX, /* word sized address index registers.  */
+    M68K_FEATURE_SCALED_INDEX, /* scaled address index registers.  */
+    M68K_FEATURE_LONG_MULDIV,  /* 32 bit multiply/divide. */
+    M68K_FEATURE_QUAD_MULDIV,  /* 64 bit multiply/divide. */
+    M68K_FEATURE_BCCL,         /* Long conditional branches.  */
+    M68K_FEATURE_BITFIELD,     /* Bit field insns.  */
+    M68K_FEATURE_FPU
 };
 
 static inline int m68k_feature(CPUM68KState *env, int feature)
@@ -210,8 +232,8 @@ static inline int m68k_feature(CPUM68KSt
 void register_m68k_insns (CPUM68KState *env);
 
 #ifdef CONFIG_USER_ONLY
-/* Linux uses 8k pages.  */
-#define TARGET_PAGE_BITS 13
+/* Linux uses 4k pages.  */
+#define TARGET_PAGE_BITS 12
 #else
 /* Smallest TLB entry size is 1k.  */ 
 #define TARGET_PAGE_BITS 10
Index: target-m68k/exec.h
===================================================================
RCS file: /sources/qemu/qemu/target-m68k/exec.h,v
retrieving revision 1.3
diff -u -a -p -r1.3 exec.h
--- target-m68k/exec.h  3 Jun 2007 17:44:36 -0000       1.3
+++ target-m68k/exec.h  2 Jul 2007 11:27:58 -0000
@@ -48,6 +48,10 @@ void cpu_m68k_flush_flags(CPUM68KState *
 float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1);
 void helper_movec(CPUM68KState *env, int reg, uint32_t val);
 
+extern const uint8_t rox8_table[64];
+extern const uint8_t rox16_table[64];
+extern const uint8_t rox32_table[64];
+
 void cpu_loop_exit(void);
 
 static inline int cpu_halted(CPUState *env) {
Index: target-m68k/helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-m68k/helper.c,v
retrieving revision 1.6
diff -u -a -p -r1.6 helper.c
--- target-m68k/helper.c        3 Jun 2007 12:35:08 -0000       1.6
+++ target-m68k/helper.c        2 Jul 2007 11:27:58 -0000
@@ -27,6 +27,10 @@
 #include "exec-all.h"
 
 enum m68k_cpuid {
+    M68K_CPUID_M68000,
+    M68K_CPUID_M68020,
+    M68K_CPUID_M68040,
+    M68K_CPUID_M68060,
     M68K_CPUID_M5206,
     M68K_CPUID_M5208,
     M68K_CPUID_CFV4E,
@@ -39,6 +43,10 @@ struct m68k_def_t {
 };
 
 static m68k_def_t m68k_cpu_defs[] = {
+    {"m68000", M68K_CPUID_M68000},
+    {"m68020", M68K_CPUID_M68020},
+    {"m68040", M68K_CPUID_M68040},
+    {"m68060", M68K_CPUID_M68060},
     {"m5206", M68K_CPUID_M5206}, 
     {"m5208", M68K_CPUID_M5208}, 
     {"cfv4e", M68K_CPUID_CFV4E},
@@ -63,12 +71,45 @@ int cpu_m68k_set_model(CPUM68KState *env
         return 1;
 
     switch (def->id) {
+    case M68K_CPUID_M68000:
+       m68k_set_feature(env, M68K_FEATURE_M68000);
+       m68k_set_feature(env, M68K_FEATURE_USP);
+        m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+       break;
+    case M68K_CPUID_M68020:
+    case M68K_CPUID_M68040:
+       m68k_set_feature(env, M68K_FEATURE_M68000);
+       m68k_set_feature(env, M68K_FEATURE_USP);
+       m68k_set_feature(env, M68K_FEATURE_BRAL);
+       m68k_set_feature(env, M68K_FEATURE_BCCL);
+       m68k_set_feature(env, M68K_FEATURE_BITFIELD);
+       m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
+        m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+       m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
+       m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV);
+       m68k_set_feature(env, M68K_FEATURE_FPU);
+       break;
+    case M68K_CPUID_M68060:
+       m68k_set_feature(env, M68K_FEATURE_M68000);
+       m68k_set_feature(env, M68K_FEATURE_USP);
+       m68k_set_feature(env, M68K_FEATURE_BRAL);
+       m68k_set_feature(env, M68K_FEATURE_BCCL);
+       m68k_set_feature(env, M68K_FEATURE_BITFIELD);
+       m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
+        m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+       m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
+       m68k_set_feature(env, M68K_FEATURE_FPU);
+       break;
     case M68K_CPUID_M5206:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         break;
     case M68K_CPUID_M5208:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         m68k_set_feature(env, M68K_FEATURE_BRAL);
         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
         m68k_set_feature(env, M68K_FEATURE_USP);
@@ -76,16 +117,19 @@ int cpu_m68k_set_model(CPUM68KState *env
     case M68K_CPUID_CFV4E:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         m68k_set_feature(env, M68K_FEATURE_BRAL);
         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
         m68k_set_feature(env, M68K_FEATURE_USP);
         break;
     case M68K_CPUID_ANY:
+       m68k_set_feature(env, M68K_FEATURE_M68000);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
         m68k_set_feature(env, M68K_FEATURE_BRAL);
+        m68k_set_feature(env, M68K_FEATURE_BCCL);
         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
         /* MAC and EMAC are mututally exclusive, so pick EMAC.
            It's mostly backwards compatible.  */
@@ -93,7 +137,11 @@ int cpu_m68k_set_model(CPUM68KState *env
         m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
         m68k_set_feature(env, M68K_FEATURE_USP);
         m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+        m68k_set_feature(env, M68K_FEATURE_BITFIELD);
+       m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
+        m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV);
         break;
     }
 
@@ -102,6 +150,42 @@ int cpu_m68k_set_model(CPUM68KState *env
     return 0;
 }
 
+/* modulo 33 table */
+const uint8_t rox32_table[64] = {
+    0, 1, 2, 3, 4, 5, 6, 7, 
+    8, 9,10,11,12,13,14,15,
+   16,17,18,19,20,21,22,23,
+   24,25,26,27,28,29,30,31,
+   32, 0, 1, 2, 3, 4, 5, 6,
+    7, 8, 9,10,11,12,13,14,
+   15,16,17,18,19,20,21,22,
+   23,24,25,26,27,28,29,30,
+};
+
+/* modulo 17 table */
+const uint8_t rox16_table[64] = {
+    0, 1, 2, 3, 4, 5, 6, 7, 
+    8, 9,10,11,12,13,14,15,
+   16, 0, 1, 2, 3, 4, 5, 6,
+    7, 8, 9,10,11,12,13,14,
+   15,16, 0, 1, 2, 3, 4, 5,
+    6, 7, 8, 9,10,11,12,13,
+   14,15,16, 0, 1, 2, 3, 4,
+    5, 6, 7, 8, 9,10,11,12,
+};
+
+/* modulo 9 table */
+const uint8_t rox8_table[64] = {
+    0, 1, 2, 3, 4, 5, 6, 7, 
+    8, 0, 1, 2, 3, 4, 5, 6,
+    7, 8, 0, 1, 2, 3, 4, 5, 
+    6, 7, 8, 0, 1, 2, 3, 4,
+    5, 6, 7, 8, 0, 1, 2, 3,
+    4, 5, 6, 7, 8, 0, 1, 2,
+    3, 4, 5, 6, 7, 8, 0, 1,
+    2, 3, 4, 5, 6, 7, 8, 0,
+};
+
 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
 {
     int flags;
@@ -127,6 +211,66 @@ void cpu_m68k_flush_flags(CPUM68KState *
         flags |= CCF_V; \
     } while (0)
 
+#define SET_FLAGS_ADD(type, utype) do { \
+    SET_NZ((type)dest); \
+    if ((utype) dest < (utype) src) \
+        flags |= CCF_C; \
+    tmp = dest - src; \
+    if ((1u << (sizeof(type) * 8 - 1)) & (src ^ dest) & (tmp ^ src)) \
+        flags |= CCF_V; \
+    } while (0)
+
+#define SET_FLAGS_ADDX(type, utype) do { \
+    SET_NZ((type)dest); \
+    if ((utype) dest <= (utype) src) \
+        flags |= CCF_C; \
+    tmp = dest - src - 1; \
+    if ((1u << (sizeof(type) * 8 - 1)) & (src ^ dest) & (tmp ^ src)) \
+        flags |= CCF_V; \
+    } while (0)
+
+#define SET_FLAGS_SUBX(type, utype) do { \
+    SET_NZ((type)dest); \
+    tmp = dest + src + 1; \
+    if ((utype) dest <= (utype) src) \
+        flags |= CCF_C; \
+    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
+        flags |= CCF_V; \
+    } while (0)
+
+#define SET_FLAGS_SHL(type) do { \
+    if (src >= sizeof(type) * 8) { \
+       SET_NZ(0); \
+    } else { \
+       tmp = dest << src; \
+        SET_NZ((type)tmp); \
+    } \
+    if (src && src <= sizeof(type) * 8 && (dest & (1 << (sizeof(type) * 8 - 
src)))) \
+       flags |= CCF_C; \
+    } while (0)
+
+#define SET_FLAGS_SHR(type) do { \
+    if (src >= sizeof(type) * 8) { \
+       SET_NZ(0); \
+    } else { \
+       tmp = dest >> src; \
+        SET_NZ((type)tmp); \
+    } \
+    if (src && src <= sizeof(type) * 8 && ((dest >> (src - 1)) & 1)) \
+       flags |= CCF_C; \
+    } while (0)
+
+#define SET_FLAGS_SAR(type) do { \
+    if (src >= sizeof(type) * 8) { \
+       SET_NZ(-((type)dest < 0)); \
+    } else { \
+       tmp = dest >> src; \
+        SET_NZ((type)tmp); \
+    } \
+    if (src && src <= sizeof(type) * 8 && (((type)dest >> (src - 1)) & 1)) \
+       flags |= CCF_C; \
+    } while (0)
+
     flags = 0;
     src = env->cc_src;
     dest = env->cc_dest;
@@ -137,68 +281,68 @@ void cpu_m68k_flush_flags(CPUM68KState *
     case CC_OP_LOGIC:
         SET_NZ(dest);
         break;
+    case CC_OP_ADDB:
+        SET_FLAGS_ADD(int8_t, uint8_t);
+        break;
+    case CC_OP_ADDW:
+        SET_FLAGS_ADD(int16_t, uint16_t);
+        break;
     case CC_OP_ADD:
-        SET_NZ(dest);
-        if (dest < src)
-            flags |= CCF_C;
-        tmp = dest - src;
-        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
-            flags |= CCF_V;
+        SET_FLAGS_ADD(int32_t, uint32_t);
+        break;
+    case CC_OP_SUBB:
+        SET_FLAGS_SUB(int8_t, uint8_t);
+        break;
+    case CC_OP_SUBW:
+        SET_FLAGS_SUB(int16_t, uint16_t);
         break;
     case CC_OP_SUB:
         SET_FLAGS_SUB(int32_t, uint32_t);
         break;
-    case CC_OP_CMPB:
-        SET_FLAGS_SUB(int8_t, uint8_t);
+    case CC_OP_ADDXB:
+        SET_FLAGS_ADDX(int8_t, uint8_t);
         break;
-    case CC_OP_CMPW:
-        SET_FLAGS_SUB(int16_t, uint16_t);
+    case CC_OP_ADDXW:
+        SET_FLAGS_ADDX(int16_t, uint16_t);
         break;
     case CC_OP_ADDX:
-        SET_NZ(dest);
-        if (dest <= src)
-            flags |= CCF_C;
-        tmp = dest - src - 1;
-        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
-            flags |= CCF_V;
+        SET_FLAGS_ADDX(int32_t, uint32_t);
+        break;
+    case CC_OP_SUBXB:
+        SET_FLAGS_SUBX(int8_t, uint8_t);
+        break;
+    case CC_OP_SUBXW:
+        SET_FLAGS_SUBX(int16_t, uint16_t);
         break;
     case CC_OP_SUBX:
-        SET_NZ(dest);
-        tmp = dest + src + 1;
-        if (tmp <= src)
-            flags |= CCF_C;
-        if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
-            flags |= CCF_V;
+        SET_FLAGS_SUBX(int32_t, uint32_t);
+        break;
+    case CC_OP_SHLB:
+        SET_FLAGS_SHL(int8_t);
+        break;
+    case CC_OP_SHLW:
+        SET_FLAGS_SHL(int16_t);
         break;
     case CC_OP_SHL:
-        if (src >= 32) {
-            SET_NZ(0);
-        } else {
-            tmp = dest << src;
-            SET_NZ(tmp);
-        }
-        if (src && src <= 32 && (dest & (1 << (32 - src))))
-            flags |= CCF_C;
+        SET_FLAGS_SHL(int32_t);
+        break;
+    case CC_OP_SHRB:
+        SET_FLAGS_SHR(int8_t);
+        break;
+    case CC_OP_SHRW:
+        SET_FLAGS_SHR(int16_t);
         break;
     case CC_OP_SHR:
-        if (src >= 32) {
-            SET_NZ(0);
-        } else {
-            tmp = dest >> src;
-            SET_NZ(tmp);
-        }
-        if (src && src <= 32 && ((dest >> (src - 1)) & 1))
-            flags |= CCF_C;
+        SET_FLAGS_SHR(int32_t);
+        break;
+    case CC_OP_SARB:
+        SET_FLAGS_SAR(int8_t);
+        break;
+    case CC_OP_SARW:
+        SET_FLAGS_SAR(int16_t);
         break;
     case CC_OP_SAR:
-        if (src >= 32) {
-            SET_NZ(-1);
-        } else {
-            tmp = (int32_t)dest >> src;
-            SET_NZ(tmp);
-        }
-        if (src && src <= 32 && (((int32_t)dest >> (src - 1)) & 1))
-            flags |= CCF_C;
+        SET_FLAGS_SAR(int32_t);
         break;
     default:
         cpu_abort(env, "Bad CC_OP %d", cc_op);
Index: target-m68k/op-hacks.h
===================================================================
RCS file: /sources/qemu/qemu/target-m68k/op-hacks.h,v
retrieving revision 1.3
diff -u -a -p -r1.3 op-hacks.h
--- target-m68k/op-hacks.h      9 Jun 2007 20:50:00 -0000       1.3
+++ target-m68k/op-hacks.h      2 Jul 2007 11:27:58 -0000
@@ -89,6 +89,36 @@ static inline void gen_op_sar_im_cc(int 
     gen_op_sar_cc(val, gen_im32(shift));
 }
 
+static inline void gen_op_shl8_im_cc(int dest, int src, int shift)
+{
+    gen_op_shl8_cc(dest, src, gen_im32(shift));
+}
+
+static inline void gen_op_shr8_im_cc(int dest, int src, int shift)
+{
+    gen_op_shr8_cc(dest, src, gen_im32(shift));
+}
+
+static inline void gen_op_sar8_im_cc(int dest, int src, int shift)
+{
+    gen_op_sar8_cc(dest, src, gen_im32(shift));
+}
+
+static inline void gen_op_shl16_im_cc(int dest, int src, int shift)
+{
+    gen_op_shl16_cc(dest, src, gen_im32(shift));
+}
+
+static inline void gen_op_shr16_im_cc(int dest, int src, int shift)
+{
+    gen_op_shr16_cc(dest, src, gen_im32(shift));
+}
+
+static inline void gen_op_sar16_im_cc(int dest, int src, int shift)
+{
+    gen_op_sar16_cc(dest, src, gen_im32(shift));
+}
+
 #ifdef USE_DIRECT_JUMP
 #define TBPARAM(x)
 #else
Index: target-m68k/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-m68k/op.c,v
retrieving revision 1.11
diff -u -a -p -r1.11 op.c
--- target-m68k/op.c    9 Jun 2007 20:50:01 -0000       1.11
+++ target-m68k/op.c    2 Jul 2007 11:27:58 -0000
@@ -136,6 +136,76 @@ OP(mul32)
     FORCE_RET();
 }
 
+OP(mulu32_cc)
+{
+    uint32_t op2 = get_op(PARAM2);
+    uint32_t op3 = get_op(PARAM3);
+    uint64_t result = (uint32_t)op2 * op3;
+    uint32_t flags;
+    set_op(PARAM1, result);
+    flags = 0;
+    if (result >> 32)
+       flags |= CCF_V;
+    if ((uint32_t)result == 0)
+       flags |= CCF_Z;
+    if ((int32_t)result < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+    FORCE_RET();
+}
+
+OP(muls32_cc)
+{
+    int32_t op2 = get_op(PARAM2);
+    int32_t op3 = get_op(PARAM3);
+    int64_t result = (int32_t)op2 * op3;
+    uint32_t flags;
+    set_op(PARAM1, result);
+    flags = 0;
+    if (result != (int64_t)(int32_t)result)
+       flags |= CCF_V;
+    if ((uint32_t)result == 0)
+       flags |= CCF_Z;
+    if ((int32_t)result < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+    FORCE_RET();
+}
+
+OP(mulu64)
+{
+    uint32_t op2 = get_op(PARAM2);
+    uint32_t op3 = get_op(PARAM3);
+    uint64_t result = (uint64_t)op2 * op3;
+    uint32_t flags;
+    set_op(PARAM1, result);
+    env->quadh = result >> 32;
+    flags = 0;
+    if (result == 0)
+       flags |= CCF_Z;
+    if ((int64_t)result < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+    FORCE_RET();
+}
+
+OP(muls64)
+{
+    int32_t op2 = get_op(PARAM2);
+    int32_t op3 = get_op(PARAM3);
+    int64_t result = (uint64_t)op2 * op3;
+    uint32_t flags;
+    set_op(PARAM1, result);
+    env->quadh = result >> 32;
+    flags = 0;
+    if (result == 0)
+       flags |= CCF_Z;
+    if (result < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+    FORCE_RET();
+}
+
 OP(not32)
 {
     uint32_t arg = get_op(PARAM2);
@@ -180,6 +250,22 @@ OP(ff1)
     FORCE_RET();
 }
 
+OP(bfffo)
+{
+    uint32_t arg = get_op(PARAM2);
+    int width = get_op(PARAM3);
+    int n;
+    uint32_t mask;
+    mask = 0x80000000;
+    for (n = 0; n < width; n++) {
+       if (arg & mask)
+           break;
+       mask >>= 1;
+    }
+    set_op(PARAM1, n);
+    FORCE_RET();
+}
+
 OP(subx_cc)
 {
     uint32_t op1 = get_op(PARAM1);
@@ -253,14 +339,60 @@ OP(shl32)
     FORCE_RET();
 }
 
+OP(shl8_cc)
+{
+    uint8_t op2 = get_op(PARAM2);
+    uint8_t op3 = get_op(PARAM3);
+    uint8_t result;
+    if (op3 < 8)
+       result = op2 << op3;
+    else
+       result = 0;
+    set_op(PARAM1, result);
+    if (op3 > 0) {
+       if (op3 <= 8)
+           env->cc_x = (op2 << (op3 - 1)) & 0x80;
+       else
+           env->cc_x = 0;
+    }
+    FORCE_RET();
+}
+
+OP(shl16_cc)
+{
+    uint16_t op2 = get_op(PARAM2);
+    uint16_t op3 = get_op(PARAM3);
+    uint16_t result;
+    if (op3 < 16)
+       result = op2 << op3;
+    else
+       result = 0;
+    set_op(PARAM1, result);
+    if (op3 > 0) {
+       if (op3 <= 16)
+           env->cc_x = (op2 << (op3 - 1)) & 0x8000;
+       else
+           env->cc_x = 0;
+    }
+    FORCE_RET();
+}
+
 OP(shl_cc)
 {
     uint32_t op1 = get_op(PARAM1);
     uint32_t op2 = get_op(PARAM2);
     uint32_t result;
-    result = op1 << op2;
+    if (op2 < 32)
+       result = op1 << op2;
+    else
+       result = 0;
     set_op(PARAM1, result);
-    env->cc_x = (op1 << (op2 - 1)) & 1;
+    if (op2 > 0) {
+       if (op2 <= 32)
+           env->cc_x = (op1 << (op2 - 1)) & 0x80000000;
+       else
+           env->cc_x = 0;
+    }
     FORCE_RET();
 }
 
@@ -279,9 +411,55 @@ OP(shr_cc)
     uint32_t op1 = get_op(PARAM1);
     uint32_t op2 = get_op(PARAM2);
     uint32_t result;
-    result = op1 >> op2;
+    if (op2 < 32)
+       result = op1 >> op2;
+    else
+       result = 0;
     set_op(PARAM1, result);
-    env->cc_x = (op1 >> (op2 - 1)) & 1;
+    if (op2 > 0) {
+       if (op2 <= 32)
+           env->cc_x = (op1 >> (op2 - 1)) & 1;
+       else
+           env->cc_x = 0;
+    }
+    FORCE_RET();
+}
+
+OP(shr8_cc)
+{
+    uint8_t op2 = get_op(PARAM2);
+    uint8_t op3 = get_op(PARAM3);
+    uint8_t result;
+    if (op3 < 8)
+       result = op2 >> op3;
+    else
+       result = 0;
+    set_op(PARAM1, result);
+    if (op3 > 0) {
+       if (op3 <= 8)
+           env->cc_x = (op2 >> (op3 - 1)) & 1;
+       else
+           env->cc_x = 0;
+    }
+    FORCE_RET();
+}
+
+OP(shr16_cc)
+{
+    uint16_t op2 = get_op(PARAM2);
+    uint16_t op3 = get_op(PARAM3);
+    uint16_t result;
+    if (op3 < 16)
+       result = op2 >> op3;
+    else
+       result = 0;
+    set_op(PARAM1, result);
+    if (op3 > 0) {
+       if (op3 <= 16)
+           env->cc_x = (op2 >> (op3 - 1)) & 1;
+       else
+           env->cc_x = 0;
+    }
     FORCE_RET();
 }
 
@@ -300,12 +478,199 @@ OP(sar_cc)
     int32_t op1 = get_op(PARAM1);
     uint32_t op2 = get_op(PARAM2);
     uint32_t result;
-    result = op1 >> op2;
+    if (op2 < 32)
+       result = op1 >> op2;
+    else
+       result = 0;
+    set_op(PARAM1, result);
+    if (op2 > 0) {
+       if (op2 <= 32)
+           env->cc_x = (op1 >> (op2 - 1)) & 1;
+       else
+           env->cc_x = 0;
+    }
+    FORCE_RET();
+}
+
+OP(sar8_cc)
+{
+    int8_t op2 = get_op(PARAM2);
+    uint8_t op3 = get_op(PARAM3);
+    uint8_t result;
+    if (op3 < 8)
+       result = op2 >> op3;
+    else
+       result = 0;
+    set_op(PARAM1, result);
+    if (op3 > 0) {
+       if (op3 <= 8)
+           env->cc_x = (op2 >> (op3 - 1)) & 1;
+       else
+           env->cc_x = 0;
+    }
+    FORCE_RET();
+}
+
+OP(sar16_cc)
+{
+    int16_t op2 = get_op(PARAM2);
+    uint16_t op3 = get_op(PARAM3);
+    uint16_t result;
+    if (op3 < 16)
+       result = op2 >> op3;
+    else
+       result = 0;
     set_op(PARAM1, result);
-    env->cc_x = (op1 >> (op2 - 1)) & 1;
+    if (op3 > 0) {
+       if (op3 <= 16)
+           env->cc_x = (op2 >> (op3 - 1)) & 1;
+       else
+           env->cc_x = 0;
+    }
     FORCE_RET();
 }
 
+OP(rol32)
+{
+    uint32_t op2 = get_op(PARAM2);
+    uint32_t op3 = get_op(PARAM3);
+    uint32_t result;
+    result = (op2 << op3) | (op2 >> (32 - op3));
+    set_op(PARAM1, result);
+    FORCE_RET();
+}
+
+OP(ror32)
+{
+    uint32_t op2 = get_op(PARAM2);
+    uint32_t op3 = get_op(PARAM3);
+    uint32_t result;
+    result = (op2 >> op3) | (op2 << (32 - op3));
+    set_op(PARAM1, result);
+    FORCE_RET();
+}
+
+#define OP_ROL(type, bits) \
+OP(glue(glue(rol,bits),_cc)) \
+{ \
+    type op2 = get_op(PARAM2); \
+    uint32_t op3 = get_op(PARAM3); \
+    type result; \
+    uint32_t flags; \
+    int count = op3 & (bits - 1); \
+    if (count) \
+       result = (op2 << count) | (op2 >> (bits - count)); \
+    else \
+       result = op2; \
+    set_op(PARAM1, result); \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (op3 && result & 1) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    FORCE_RET(); \
+}
+OP_ROL(uint8_t, 8)
+OP_ROL(uint16_t, 16)
+OP_ROL(uint32_t, 32)
+
+#define OP_ROR(type, bits) \
+OP(glue(glue(ror,bits),_cc)) \
+{ \
+    type op2 = get_op(PARAM2); \
+    uint32_t op3 = get_op(PARAM3); \
+    type result; \
+    uint32_t flags; \
+    int count = op3 & (bits - 1); \
+    if (count) \
+       result = (op2 >> count) | (op2 << (bits - count)); \
+    else \
+       result = op2; \
+    set_op(PARAM1, result); \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (op3 && result & (1 << (bits - 1))) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    FORCE_RET(); \
+}
+OP_ROR(uint8_t, 8)
+OP_ROR(uint16_t, 16)
+OP_ROR(uint32_t, 32)
+
+#define OP_ROXR(type, bits) \
+OP(glue(glue(roxr,bits),_cc)) \
+{ \
+    type op2 = get_op(PARAM2); \
+    uint32_t op3 = get_op(PARAM3); \
+    type result; \
+    uint32_t flags; \
+    int count = op3; \
+    if (bits == 8) count = rox8_table[count]; \
+    if (bits == 16) count = rox16_table[count]; \
+    if (bits == 32) count = rox32_table[count]; \
+    if (count) { \
+       result = (op2 >> count) | ((type)env->cc_x << (bits - count)); \
+       if (count > 1) \
+           result |= op2 << (bits + 1 - count); \
+       env->cc_x = (op2 >> (count - 1)) & 1; \
+    } else \
+       result = op2; \
+    set_op(PARAM1, result); \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (env->cc_x) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    FORCE_RET(); \
+}
+OP_ROXR(uint8_t, 8)
+OP_ROXR(uint16_t, 16)
+OP_ROXR(uint32_t, 32)
+
+#define OP_ROXL(type, bits) \
+OP(glue(glue(roxl,bits),_cc)) \
+{ \
+    type op2 = get_op(PARAM2); \
+    uint32_t op3 = get_op(PARAM3); \
+    type result; \
+    uint32_t flags; \
+    int count; \
+    count = op3; \
+    if (bits == 8) count = rox8_table[count]; \
+    if (bits == 16) count = rox16_table[count]; \
+    if (bits == 32) count = rox32_table[count]; \
+    if (count) { \
+       result = (op2 << count) | ((type)env->cc_x << (count - 1)); \
+       if (count > 1) \
+           result |= op2 >> (bits + 1 - count); \
+       env->cc_x = (op2 >> (bits - count)) & 1; \
+    } else \
+       result = op2; \
+    set_op(PARAM1, result); \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (env->cc_x) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    FORCE_RET(); \
+}
+OP_ROXL(uint8_t, 8)
+OP_ROXL(uint16_t, 16)
+OP_ROXL(uint32_t, 32)
+
 /* Value extend.  */
 
 OP(ext8u32)
@@ -361,14 +726,17 @@ OP(divu)
     /* Avoid using a PARAM1 of zero.  This breaks dyngen because it uses
        the address of a symbol, and gcc knows symbols can't have address
        zero.  */
-    if (PARAM1 == 2 && quot > 0xffff)
+    if (PARAM1 == 1 && quot > 0xffff)
         flags |= CCF_V;
     if (quot == 0)
         flags |= CCF_Z;
     else if ((int32_t)quot < 0)
         flags |= CCF_N;
-    env->div1 = quot;
-    env->div2 = rem;
+    /* Don't modify destination if overflow occured.  */
+    if ((flags & CCF_V) == 0) {
+       env->div1 = quot;
+       env->div2 = rem;
+    }
     env->cc_dest = flags;
     FORCE_RET();
 }
@@ -379,7 +747,7 @@ OP(divs)
     int32_t den;
     int32_t quot;
     int32_t rem;
-    int32_t flags;
+    uint32_t flags;
     
     num = env->div1;
     den = env->div2;
@@ -388,14 +756,78 @@ OP(divs)
     quot = num / den;
     rem = num % den;
     flags = 0;
-    if (PARAM1 == 2 && quot != (int16_t)quot)
+    if (PARAM1 == 1 && quot != (int16_t)quot)
+        flags |= CCF_V;
+    if (quot == 0)
+        flags |= CCF_Z;
+    else if (quot < 0)
+        flags |= CCF_N;
+    /* Don't modify destination if overflow occured.  */
+    if ((flags & CCF_V) == 0) {
+       env->div1 = quot;
+       env->div2 = rem;
+    }
+    env->cc_dest = flags;
+    FORCE_RET();
+}
+
+OP(divu64)
+{
+    uint32_t num;
+    uint32_t den;
+    uint64_t quot;
+    uint32_t rem;
+    uint32_t flags;
+
+    num = env->div1;
+    den = env->div2;
+    /* ??? This needs to make sure the throwing location is accurate.  */
+    if (den == 0)
+        RAISE_EXCEPTION(EXCP_DIV0);
+    quot = (num | ((uint64_t)env->quadh << 32)) / den;
+    rem = (num | ((uint64_t)env->quadh << 32)) % den;
+    flags = 0;
+    if (quot > 0xffffffff)
+        flags |= CCF_V;
+    if (quot == 0)
+        flags |= CCF_Z;
+    else if ((int64_t)quot < 0)
+        flags |= CCF_N;
+    /* Don't modify destination if overflow occured.  */
+    if ((flags & CCF_V) == 0) {
+       env->div1 = quot;
+       env->div2 = rem;
+    }
+    env->cc_dest = flags;
+    FORCE_RET();
+}
+
+OP(divs64)
+{
+    int32_t num;
+    int32_t den;
+    int64_t quot;
+    int32_t rem;
+    uint32_t flags;
+
+    num = env->div1;
+    den = env->div2;
+    if (den == 0)
+        RAISE_EXCEPTION(EXCP_DIV0);
+    quot = (num | ((int64_t)env->quadh << 32)) / den;
+    rem = (num | ((int64_t)env->quadh << 32)) % den;
+    flags = 0;
+    if (quot != (int32_t)quot)
         flags |= CCF_V;
     if (quot == 0)
         flags |= CCF_Z;
     else if (quot < 0)
         flags |= CCF_N;
-    env->div1 = quot;
-    env->div2 = rem;
+    /* Don't modify destination if overflow occured.  */
+    if ((flags & CCF_V) == 0) {
+       env->div1 = quot;
+       env->div2 = rem;
+    }
     env->cc_dest = flags;
     FORCE_RET();
 }
Index: target-m68k/qregs.def
===================================================================
RCS file: /sources/qemu/qemu/target-m68k/qregs.def,v
retrieving revision 1.3
diff -u -a -p -r1.3 qregs.def
--- target-m68k/qregs.def       29 May 2007 14:57:59 -0000      1.3
+++ target-m68k/qregs.def       2 Jul 2007 11:27:58 -0000
@@ -32,6 +32,7 @@ DEFO32(CC_SRC, cc_src)
 DEFO32(CC_X, cc_x)
 DEFO32(DIV1, div1)
 DEFO32(DIV2, div2)
+DEFO32(QUADH, quadh)
 DEFO32(EXCEPTION, exception_index)
 DEFO32(MACSR, macsr)
 DEFO32(MAC_MASK, mac_mask)
Index: target-m68k/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-m68k/translate.c,v
retrieving revision 1.17
diff -u -a -p -r1.17 translate.c
--- target-m68k/translate.c     9 Jun 2007 21:30:14 -0000       1.17
+++ target-m68k/translate.c     2 Jul 2007 11:27:59 -0000
@@ -250,6 +250,9 @@ static int gen_lea_indexed(DisasContext 
     if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
         return -1;
 
+    if (!m68k_feature(s->env, M68K_FEATURE_SCALED_INDEX))
+       ext &= ~(3 << 9);
+
     if (ext & 0x100) {
         /* full extension word format */
         if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
@@ -258,7 +261,7 @@ static int gen_lea_indexed(DisasContext 
         if ((ext & 0x30) > 0x10) {
             /* base displacement */
             if ((ext & 0x30) == 0x20) {
-                bd = (int16_t)lduw_code(s->pc);
+                bd = ldsw_code(s->pc);
                 s->pc += 2;
             } else {
                 bd = read_im32(s);
@@ -307,7 +310,7 @@ static int gen_lea_indexed(DisasContext 
             if ((ext & 3) > 1) {
                 /* outer displacement */
                 if ((ext & 3) == 2) {
-                    od = (int16_t)lduw_code(s->pc);
+                    od = ldsw_code(s->pc);
                     s->pc += 2;
                 } else {
                     od = read_im32(s);
@@ -366,6 +369,25 @@ static inline int opsize_bytes(int opsiz
     }
 }
 
+static inline int insn_opsize(int insn, int pos)
+{
+    switch ((insn >> pos) & 3) {
+    case 0: return OS_BYTE;
+    case 1: return OS_WORD;
+    case 2: return OS_LONG;
+    default: abort();
+    }
+}
+
+#define SET_CC_OP(opsize, op) do { \
+    switch (opsize) { \
+    case OS_BYTE: s->cc_op = CC_OP_##op##B; break; \
+    case OS_WORD: s->cc_op = CC_OP_##op##W; break; \
+    case OS_LONG: s->cc_op = CC_OP_##op; break; \
+    default: abort(); \
+    } \
+    } while (0)
+
 /* Assign value to a register.  If the width is less than the register width
    only the low part of the register is set.  */
 static void gen_partset_reg(int opsize, int reg, int val)
@@ -881,8 +903,27 @@ DISAS_INSN(divl)
 
     ext = lduw_code(s->pc);
     s->pc += 2;
-    if (ext & 0x87f8) {
-        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+    if (ext & 0x400) {
+       if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
+           gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+           return;
+       }
+       num = DREG(ext, 12);
+       reg = DREG(ext, 0);
+       gen_op_mov32(QREG_DIV1, num);
+       gen_op_mov32(QREG_QUADH, reg);
+       SRC_EA(den, OS_LONG, 0, NULL);
+       gen_op_mov32(QREG_DIV2, den);
+       if (ext & 0x0800) {
+           gen_op_divs64();
+       } else {
+           gen_op_divu64();
+       }
+        gen_op_mov32 (num, QREG_DIV1);
+       if (num != reg)
+           gen_op_mov32 (reg, QREG_DIV2);
+       gen_op_flags_set();
+       s->cc_op = CC_OP_FLAGS;
         return;
     }
     num = DREG(ext, 12);
@@ -895,13 +936,10 @@ DISAS_INSN(divl)
     } else {
         gen_op_divu(2);
     }
-    if (num == reg) {
-        /* div */
-        gen_op_mov32 (reg, QREG_DIV1);
-    } else {
-        /* rem */
-        gen_op_mov32 (reg, QREG_DIV2);
-    }
+    if (num == reg || m68k_feature(s->env, M68K_FEATURE_LONG_MULDIV))
+       gen_op_mov32 (num, QREG_DIV1);
+    if (num != reg)
+       gen_op_mov32 (reg, QREG_DIV2);
     gen_op_flags_set();
     s->cc_op = CC_OP_FLAGS;
 }
@@ -914,31 +952,33 @@ DISAS_INSN(addsub)
     int tmp;
     int addr;
     int add;
+    int opsize;
 
     add = (insn & 0x4000) != 0;
+    opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
     dest = gen_new_qreg(QMODE_I32);
     if (insn & 0x100) {
-        SRC_EA(tmp, OS_LONG, 0, &addr);
+        SRC_EA(tmp, opsize, -1, &addr);
         src = reg;
     } else {
         tmp = reg;
-        SRC_EA(src, OS_LONG, 0, NULL);
+        SRC_EA(src, opsize, -1, NULL);
     }
     if (add) {
         gen_op_add32(dest, tmp, src);
         gen_op_update_xflag_lt(dest, src);
-        s->cc_op = CC_OP_ADD;
+       SET_CC_OP(opsize, ADD);
     } else {
         gen_op_update_xflag_lt(tmp, src);
         gen_op_sub32(dest, tmp, src);
-        s->cc_op = CC_OP_SUB;
+       SET_CC_OP(opsize, SUB);
     }
     gen_op_update_cc_add(dest, src);
     if (insn & 0x100) {
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
     } else {
-        gen_op_mov32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
 }
 
@@ -1065,6 +1105,8 @@ DISAS_INSN(movem)
     int reg;
     int tmp;
     int is_load;
+    int opsize;
+    int incr;
 
     mask = lduw_code(s->pc);
     s->pc += 2;
@@ -1076,21 +1118,40 @@ DISAS_INSN(movem)
     addr = gen_new_qreg(QMODE_I32);
     gen_op_mov32(addr, tmp);
     is_load = ((insn & 0x0400) != 0);
-    for (i = 0; i < 16; i++, mask >>= 1) {
-        if (mask & 1) {
-            if (i < 8)
-                reg = DREG(i, 0);
-            else
-                reg = AREG(i, 0);
-            if (is_load) {
-                tmp = gen_load(s, OS_LONG, addr, 0);
-                gen_op_mov32(reg, tmp);
-            } else {
-                gen_store(s, OS_LONG, addr, reg);
-            }
-            if (mask != 1)
-                gen_op_add32(addr, addr, gen_im32(4));
-        }
+    opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
+    incr = gen_im32(opsize_bytes(opsize));
+    if (!is_load && (insn & 070) == 040) {
+       for (i = 15; i >= 0; i--, mask >>= 1) {
+           if (mask & 1) {
+               if (i < 8)
+                   reg = DREG(i, 0);
+               else
+                   reg = AREG(i, 0);
+               gen_store(s, opsize, addr, reg);
+               if (mask != 1)
+                   gen_op_sub32(addr, addr, incr);
+           }
+       }
+       gen_op_mov32(AREG(insn, 0), addr);
+    } else {
+       for (i = 0; i < 16; i++, mask >>= 1) {
+           if (mask & 1) {
+               if (i < 8)
+                   reg = DREG(i, 0);
+               else
+                   reg = AREG(i, 0);
+               if (is_load) {
+                   tmp = gen_load(s, opsize, addr, 1);
+                   gen_op_mov32(reg, tmp);
+               } else {
+                   gen_store(s, opsize, addr, reg);
+               }
+               if (mask != 1 || (insn & 070) == 030)
+                   gen_op_add32(addr, addr, incr);
+           }
+       }
+       if ((insn & 070) == 030)
+           gen_op_mov32(AREG(insn, 0), addr);
     }
 }
 
@@ -1158,10 +1219,26 @@ DISAS_INSN(arith_im)
     int dest;
     int src2;
     int addr;
+    int opsize;
 
     op = (insn >> 9) & 7;
-    SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
-    src2 = gen_im32(read_im32(s));
+    opsize = insn_opsize(insn, 6);
+    switch (opsize) {
+    case OS_BYTE:
+       src2 = gen_im32(ldsb_code(s->pc + 1));
+       s->pc += 2;
+       break;
+    case OS_WORD:
+       src2 = gen_im32(ldsw_code(s->pc));
+       s->pc += 2;
+       break;
+    case OS_LONG:
+       src2 = gen_im32(read_im32(s));
+       break;
+    default:
+       abort();
+    }
+    SRC_EA(src1, opsize, -1, (op == 6) ? NULL : &addr);
     dest = gen_new_qreg(QMODE_I32);
     switch (op) {
     case 0: /* ori */
@@ -1177,14 +1254,14 @@ DISAS_INSN(arith_im)
         gen_op_update_xflag_lt(dest, src2);
         gen_op_sub32(dest, dest, src2);
         gen_op_update_cc_add(dest, src2);
-        s->cc_op = CC_OP_SUB;
+        SET_CC_OP(opsize, SUB);
         break;
     case 3: /* addi */
         gen_op_mov32(dest, src1);
         gen_op_add32(dest, dest, src2);
         gen_op_update_cc_add(dest, src2);
         gen_op_update_xflag_lt(dest, src2);
-        s->cc_op = CC_OP_ADD;
+        SET_CC_OP(opsize, ADD);
         break;
     case 5: /* eori */
         gen_op_xor32(dest, src1, src2);
@@ -1194,13 +1271,13 @@ DISAS_INSN(arith_im)
         gen_op_mov32(dest, src1);
         gen_op_sub32(dest, dest, src2);
         gen_op_update_cc_add(dest, src2);
-        s->cc_op = CC_OP_SUB;
+        SET_CC_OP(opsize, SUB);
         break;
     default:
         abort();
     }
     if (op != 6) {
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
     }
 }
 
@@ -1290,19 +1367,7 @@ DISAS_INSN(clr)
 {
     int opsize;
 
-    switch ((insn >> 6) & 3) {
-    case 0: /* clr.b */
-        opsize = OS_BYTE;
-        break;
-    case 1: /* clr.w */
-        opsize = OS_WORD;
-        break;
-    case 2: /* clr.l */
-        opsize = OS_LONG;
-        break;
-    default:
-        abort();
-    }
+    opsize = insn_opsize(insn, 6);
     DEST_EA(insn, opsize, gen_im32(0), NULL);
     gen_logic_cc(s, gen_im32(0));
 }
@@ -1331,17 +1396,20 @@ DISAS_INSN(move_from_ccr)
 
 DISAS_INSN(neg)
 {
-    int reg;
     int src1;
+    int dest;
+    int addr;
+    int opsize;
 
-    reg = DREG(insn, 0);
-    src1 = gen_new_qreg(QMODE_I32);
-    gen_op_mov32(src1, reg);
-    gen_op_neg32(reg, src1);
-    s->cc_op = CC_OP_SUB;
-    gen_op_update_cc_add(reg, src1);
-    gen_op_update_xflag_lt(gen_im32(0), src1);
-    s->cc_op = CC_OP_SUB;
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(src1, opsize, -1, &addr);
+    dest = gen_new_qreg(QMODE_I32);
+    gen_op_neg32(dest, src1);
+    DEST_EA(insn, opsize, dest, &addr);
+    SET_CC_OP(opsize, SUB);
+    gen_op_update_cc_add(src1, dest);
+    gen_op_update_xflag_lt(gen_im32(0), dest);
+    SET_CC_OP(opsize, SUB);
 }
 
 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
@@ -1390,11 +1458,17 @@ DISAS_INSN(move_to_ccr)
 
 DISAS_INSN(not)
 {
-    int reg;
+    int src1;
+    int dest;
+    int addr;
+    int opsize;
 
-    reg = DREG(insn, 0);
-    gen_op_not32(reg, reg);
-    gen_logic_cc(s, reg);
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(src1, opsize, -1, &addr);
+    dest = gen_new_qreg(QMODE_I32);
+    gen_op_not32(dest, src1);
+    DEST_EA(insn, opsize, dest, &addr);
+    gen_logic_cc(s, dest);
 }
 
 DISAS_INSN(swap)
@@ -1452,19 +1526,7 @@ DISAS_INSN(tst)
     int opsize;
     int tmp;
 
-    switch ((insn >> 6) & 3) {
-    case 0: /* tst.b */
-        opsize = OS_BYTE;
-        break;
-    case 1: /* tst.w */
-        opsize = OS_WORD;
-        break;
-    case 2: /* tst.l */
-        opsize = OS_LONG;
-        break;
-    default:
-        abort();
-    }
+    opsize = insn_opsize(insn, 6);
     SRC_EA(tmp, opsize, -1, NULL);
     gen_logic_cc(s, tmp);
 }
@@ -1499,22 +1561,47 @@ DISAS_INSN(mull)
     int reg;
     int src1;
     int dest;
+    int regh;
 
     /* The upper 32 bits of the product are discarded, so
        muls.l and mulu.l are functionally equivalent.  */
     ext = lduw_code(s->pc);
     s->pc += 2;
-    if (ext & 0x87ff) {
-        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
-        return;
+    if (ext & 0x400) {
+       if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
+           gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+           return;
+       }
+       reg = DREG(ext, 12);
+       regh = DREG(ext, 0);
+       SRC_EA(src1, OS_LONG, 0, NULL);
+       dest = gen_new_qreg(QMODE_I32);
+       if (ext & 0x800)
+           gen_op_muls64(dest, src1, reg);
+       else
+           gen_op_mulu64(dest, src1, reg);
+       gen_op_mov32(reg, dest);
+       gen_op_mov32(regh, QREG_QUADH);
+       gen_op_flags_set();
+       s->cc_op = CC_OP_FLAGS;
+       return;
     }
     reg = DREG(ext, 12);
     SRC_EA(src1, OS_LONG, 0, NULL);
     dest = gen_new_qreg(QMODE_I32);
-    gen_op_mul32(dest, src1, reg);
+    if (m68k_feature(s->env, M68K_FEATURE_M68000)) {
+       if (ext & 0x800)
+           gen_op_muls32_cc(dest, src1, reg);
+       else
+           gen_op_mulu32_cc(dest, src1, reg);
+       gen_op_flags_set();
+       s->cc_op = CC_OP_FLAGS;
+    } else {
+       gen_op_mul32(dest, src1, reg);
+       /* Unlike m68k, coldfire always clears the overflow bit.  */
+       gen_logic_cc(s, dest);
+    }
     gen_op_mov32(reg, dest);
-    /* Unlike m68k, coldfire always clears the overflow bit.  */
-    gen_logic_cc(s, dest);
 }
 
 DISAS_INSN(link)
@@ -1586,8 +1673,14 @@ DISAS_INSN(addsubq)
     int dest;
     int val;
     int addr;
+    int opsize;
 
-    SRC_EA(src1, OS_LONG, 0, &addr);
+    if ((insn & 070) == 010) {
+       /* Operation on address register is always long.  */
+       opsize = OS_LONG;
+    } else
+       opsize = insn_opsize(insn, 6);
+    SRC_EA(src1, opsize, -1, &addr);
     val = (insn >> 9) & 7;
     if (val == 0)
         val = 8;
@@ -1606,15 +1699,15 @@ DISAS_INSN(addsubq)
         if (insn & 0x0100) {
             gen_op_update_xflag_lt(dest, src2);
             gen_op_sub32(dest, dest, src2);
-            s->cc_op = CC_OP_SUB;
+            SET_CC_OP(opsize, SUB);
         } else {
             gen_op_add32(dest, dest, src2);
             gen_op_update_xflag_lt(dest, src2);
-            s->cc_op = CC_OP_ADD;
+            SET_CC_OP(opsize, ADD);
         }
         gen_op_update_cc_add(dest, src2);
     }
-    DEST_EA(insn, OS_LONG, dest, &addr);
+    DEST_EA(insn, opsize, dest, &addr);
 }
 
 DISAS_INSN(tpf)
@@ -1633,6 +1726,47 @@ DISAS_INSN(tpf)
     }
 }
 
+DISAS_INSN(scc_mem)
+{
+    int l1;
+    int cond;
+    int dest;
+
+    l1 = gen_new_label();
+    cond = (insn >> 8) & 0xf;
+    dest = gen_new_qreg(QMODE_I32);
+    gen_op_mov32(dest, gen_im32(0));
+    gen_jmpcc(s, cond ^ 1, l1);
+    gen_op_mov32(dest, gen_im32(0xff));
+    gen_set_label(l1);
+    DEST_EA(insn, OS_BYTE, dest, NULL);
+}
+
+DISAS_INSN(dbcc)
+{
+    int l1;
+    int reg;
+    int tmp;
+    int16_t offset;
+    uint32_t base;
+
+    reg = DREG(insn, 0);
+    base = s->pc;
+    offset = ldsw_code(s->pc);
+    s->pc += 2;
+    l1 = gen_new_label();
+    gen_jmpcc(s, (insn >> 8) & 0xf, l1);
+    tmp = gen_new_qreg(QMODE_I32);
+    gen_op_ext16s32(tmp, reg);
+    gen_op_set_T0_z32(tmp);
+    gen_op_add32(tmp, tmp, gen_im32(-1));
+    gen_partset_reg(OS_WORD, reg, tmp);
+    gen_op_jmp_T0(l1);
+    gen_jmp_tb(s, 1, base + offset);
+    gen_set_label(l1);
+    gen_jmp_tb(s, 0, s->pc);
+}
+
 DISAS_INSN(branch)
 {
     int32_t offset;
@@ -1698,17 +1832,19 @@ DISAS_INSN(or)
     int dest;
     int src;
     int addr;
+    int opsize;
 
+    opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
     dest = gen_new_qreg(QMODE_I32);
     if (insn & 0x100) {
-        SRC_EA(src, OS_LONG, 0, &addr);
+        SRC_EA(src, opsize, -1, &addr);
         gen_op_or32(dest, src, reg);
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
     } else {
-        SRC_EA(src, OS_LONG, 0, NULL);
+        SRC_EA(src, opsize, 0, NULL);
         gen_op_or32(dest, src, reg);
-        gen_op_mov32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
     gen_logic_cc(s, dest);
 }
@@ -1718,7 +1854,7 @@ DISAS_INSN(suba)
     int src;
     int reg;
 
-    SRC_EA(src, OS_LONG, 0, NULL);
+    SRC_EA(src, (insn & 0x100) ? OS_LONG : OS_WORD, -1, NULL);
     reg = AREG(insn, 9);
     gen_op_sub32(reg, reg, src);
 }
@@ -1763,34 +1899,18 @@ DISAS_INSN(mov3q)
 
 DISAS_INSN(cmp)
 {
-    int op;
     int src;
     int reg;
     int dest;
     int opsize;
 
-    op = (insn >> 6) & 3;
-    switch (op) {
-    case 0: /* cmp.b */
-        opsize = OS_BYTE;
-        s->cc_op = CC_OP_CMPB;
-        break;
-    case 1: /* cmp.w */
-        opsize = OS_WORD;
-        s->cc_op = CC_OP_CMPW;
-        break;
-    case 2: /* cmp.l */
-        opsize = OS_LONG;
-        s->cc_op = CC_OP_SUB;
-        break;
-    default:
-        abort();
-    }
+    opsize = insn_opsize(insn, 6);
     SRC_EA(src, opsize, -1, NULL);
     reg = DREG(insn, 9);
     dest = gen_new_qreg(QMODE_I32);
     gen_op_sub32(dest, reg, src);
     gen_op_update_cc_add(dest, src);
+    SET_CC_OP(opsize, SUB);
 }
 
 DISAS_INSN(cmpa)
@@ -1810,7 +1930,7 @@ DISAS_INSN(cmpa)
     dest = gen_new_qreg(QMODE_I32);
     gen_op_sub32(dest, reg, src);
     gen_op_update_cc_add(dest, src);
-    s->cc_op = CC_OP_SUB;
+    SET_CC_OP(opsize, SUB);
 }
 
 DISAS_INSN(eor)
@@ -1819,13 +1939,15 @@ DISAS_INSN(eor)
     int reg;
     int dest;
     int addr;
+    int opsize;
 
-    SRC_EA(src, OS_LONG, 0, &addr);
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(src, opsize, -1, &addr);
     reg = DREG(insn, 9);
     dest = gen_new_qreg(QMODE_I32);
     gen_op_xor32(dest, src, reg);
     gen_logic_cc(s, dest);
-    DEST_EA(insn, OS_LONG, dest, &addr);
+    DEST_EA(insn, opsize, dest, &addr);
 }
 
 DISAS_INSN(and)
@@ -1834,17 +1956,19 @@ DISAS_INSN(and)
     int reg;
     int dest;
     int addr;
+    int opsize;
 
+    opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
     dest = gen_new_qreg(QMODE_I32);
     if (insn & 0x100) {
-        SRC_EA(src, OS_LONG, 0, &addr);
+        SRC_EA(src, opsize, -1, &addr);
         gen_op_and32(dest, src, reg);
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
     } else {
-        SRC_EA(src, OS_LONG, 0, NULL);
+        SRC_EA(src, opsize, -1, NULL);
         gen_op_and32(dest, src, reg);
-        gen_op_mov32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
     gen_logic_cc(s, dest);
 }
@@ -1854,7 +1978,7 @@ DISAS_INSN(adda)
     int src;
     int reg;
 
-    SRC_EA(src, OS_LONG, 0, NULL);
+    SRC_EA(src, (insn & 0x100) ? OS_LONG : OS_WORD, -1, NULL);
     reg = AREG(insn, 9);
     gen_op_add32(reg, reg, src);
 }
@@ -1907,6 +2031,58 @@ DISAS_INSN(shift_im)
     }
 }
 
+DISAS_INSN(shift8_im)
+{
+    int reg;
+    int dest;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+       tmp = 8;
+    dest = gen_new_qreg(QMODE_I32);
+    if (insn & 0x100) {
+        gen_op_shl8_im_cc(dest, reg, tmp);
+        s->cc_op = CC_OP_SHLB;
+    } else {
+        if (insn & 8) {
+            gen_op_shr8_im_cc(dest, reg, tmp);
+            s->cc_op = CC_OP_SHRB;
+        } else {
+            gen_op_sar8_im_cc(dest, reg, tmp);
+            s->cc_op = CC_OP_SARB;
+        }
+    }
+    gen_partset_reg(OS_BYTE, reg, dest);
+}
+
+DISAS_INSN(shift16_im)
+{
+    int reg;
+    int dest;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+       tmp = 8;
+    dest = gen_new_qreg(QMODE_I32);
+    if (insn & 0x100) {
+        gen_op_shl16_im_cc(dest, reg, tmp);
+        s->cc_op = CC_OP_SHLW;
+    } else {
+        if (insn & 8) {
+            gen_op_shr16_im_cc(dest, reg, tmp);
+            s->cc_op = CC_OP_SHRW;
+        } else {
+            gen_op_sar16_im_cc(dest, reg, tmp);
+            s->cc_op = CC_OP_SARW;
+        }
+    }
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
 DISAS_INSN(shift_reg)
 {
     int reg;
@@ -1931,6 +2107,603 @@ DISAS_INSN(shift_reg)
     }
 }
 
+DISAS_INSN(shift8_reg)
+{
+    int reg;
+    int src;
+    int dest;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = gen_new_qreg(QMODE_I32);
+    gen_op_and32(tmp, src, gen_im32(63));
+    dest = gen_new_qreg(QMODE_I32);
+    if (insn & 0x100) {
+        gen_op_shl8_cc(dest, reg, tmp);
+        s->cc_op = CC_OP_SHLB;
+    } else {
+        if (insn & 8) {
+            gen_op_shr8_cc(dest, reg, tmp);
+            s->cc_op = CC_OP_SHRB;
+        } else {
+            gen_op_sar8_cc(dest, reg, tmp);
+            s->cc_op = CC_OP_SARB;
+        }
+    }
+    gen_partset_reg(OS_BYTE, reg, dest);
+}
+
+DISAS_INSN(shift16_reg)
+{
+    int reg;
+    int src;
+    int dest;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = gen_new_qreg(QMODE_I32);
+    gen_op_and32(tmp, src, gen_im32(63));
+    dest = gen_new_qreg(QMODE_I32);
+    if (insn & 0x100) {
+        gen_op_shl16_cc(dest, reg, tmp);
+        s->cc_op = CC_OP_SHLW;
+    } else {
+        if (insn & 8) {
+            gen_op_shr16_cc(dest, reg, tmp);
+            s->cc_op = CC_OP_SHRW;
+        } else {
+            gen_op_sar16_cc(dest, reg, tmp);
+            s->cc_op = CC_OP_SARW;
+        }
+    }
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
+DISAS_INSN(shift_mem)
+{
+    int src;
+    int dest;
+    int addr;
+
+    SRC_EA(src, OS_WORD, 0, &addr);
+    dest = gen_new_qreg(QMODE_I32);
+    if (insn & 0x100) {
+        gen_op_shl16_im_cc(dest, src, 1);
+        s->cc_op = CC_OP_SHLW;
+    } else {
+        if (insn & 8) {
+            gen_op_shr16_im_cc(dest, src, 1);
+            s->cc_op = CC_OP_SHRW;
+        } else {
+            gen_op_sar16_im_cc(dest, src, 1);
+            s->cc_op = CC_OP_SARW;
+        }
+    }
+    DEST_EA(insn, OS_WORD, dest, &addr);
+}
+
+DISAS_INSN(rotate_im)
+{
+    int reg;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+       tmp = 8;
+    tmp = gen_im32(tmp);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_op_rol32_cc(reg, reg, tmp);
+       } else {
+           gen_op_ror32_cc(reg, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_op_roxl32_cc(reg, reg, tmp);
+        } else {
+            gen_op_roxr32_cc(reg, reg, tmp);
+        }
+    }
+    gen_op_flags_set();
+    s->cc_op = CC_OP_FLAGS;
+}
+
+DISAS_INSN(rotate8_im)
+{
+    int reg;
+    int dest;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+       tmp = 8;
+    tmp = gen_im32(tmp);
+    dest = gen_new_qreg(QMODE_I32);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_op_rol8_cc(dest, reg, tmp);
+       } else {
+           gen_op_ror8_cc(dest, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_op_roxl8_cc(dest, reg, tmp);
+        } else {
+            gen_op_roxr8_cc(dest, reg, tmp);
+        }
+    }
+    gen_op_flags_set();
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_BYTE, reg, dest);
+}
+
+DISAS_INSN(rotate16_im)
+{
+    int reg;
+    int dest;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+       tmp = 8;
+    tmp = gen_im32(tmp);
+    dest = gen_new_qreg(QMODE_I32);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_op_rol16_cc(dest, reg, tmp);
+       } else {
+           gen_op_ror16_cc(dest, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_op_roxl16_cc(dest, reg, tmp);
+        } else {
+            gen_op_roxr16_cc(dest, reg, tmp);
+        }
+    }
+    gen_op_flags_set();
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
+DISAS_INSN(rotate_reg)
+{
+    int reg;
+    int src;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = gen_new_qreg(QMODE_I32);
+    gen_op_and32(tmp, src, gen_im32(63));
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_op_rol32_cc(reg, reg, tmp);
+       } else {
+           gen_op_ror32_cc(reg, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_op_roxl32_cc(reg, reg, tmp);
+        } else {
+            gen_op_roxr32_cc(reg, reg, tmp);
+        }
+    }
+    gen_op_flags_set();
+    s->cc_op = CC_OP_FLAGS;
+}
+
+DISAS_INSN(rotate8_reg)
+{
+    int reg;
+    int src;
+    int dest;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = gen_new_qreg(QMODE_I32);
+    gen_op_and32(tmp, src, gen_im32(63));
+    dest = gen_new_qreg(QMODE_I32);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_op_rol8_cc(dest, reg, tmp);
+       } else {
+           gen_op_ror8_cc(dest, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_op_roxl8_cc(dest, reg, tmp);
+        } else {
+            gen_op_roxr8_cc(dest, reg, tmp);
+        }
+    }
+    gen_op_flags_set();
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_BYTE, reg, dest);
+}
+
+DISAS_INSN(rotate16_reg)
+{
+    int reg;
+    int src;
+    int dest;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = gen_new_qreg(QMODE_I32);
+    gen_op_and32(tmp, src, gen_im32(63));
+    dest = gen_new_qreg(QMODE_I32);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_op_rol16_cc(dest, reg, tmp);
+       } else {
+           gen_op_ror16_cc(dest, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_op_roxl16_cc(dest, reg, tmp);
+        } else {
+            gen_op_roxr16_cc(dest, reg, tmp);
+        }
+    }
+    gen_op_flags_set();
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
+DISAS_INSN(rotate_mem)
+{
+    int src;
+    int dest;
+    int addr;
+
+    SRC_EA(src, OS_WORD, 0, &addr);
+    dest = gen_new_qreg(QMODE_I32);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_op_rol16_cc(dest, src, gen_im32(1));
+       } else {
+           gen_op_ror16_cc(dest, src, gen_im32(1));
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_op_roxl16_cc(dest, src, gen_im32(1));
+        } else {
+            gen_op_roxr16_cc(dest, src, gen_im32(1));
+        }
+    }
+    gen_op_flags_set();
+    s->cc_op = CC_OP_FLAGS;
+    DEST_EA(insn, OS_WORD, dest, &addr);
+}
+
+DISAS_INSN(bitfield_reg)
+{
+    uint16_t ext;
+    int tmp;
+    int tmp1;
+    int reg;
+    int offset;
+    int width;
+    int op;
+    int reg2;
+    uint32_t mask;
+
+    reg = DREG(insn, 0);
+    op = (insn >> 8) & 7;
+    ext = lduw_code(s->pc);
+    s->pc += 2;
+    if ((ext & 0x820) == 0) {
+       /* constant offset and width */
+       offset = (ext >> 6) & 31;
+       width = (ext & 31);
+       if (width == 0)
+           width = 32;
+       reg2 = DREG(ext, 12);
+       mask = 0xffffffff << (32 - width);
+       if (offset > 0)
+           mask = (mask >> offset) | (mask << (32 - offset));
+       tmp = gen_new_qreg(QMODE_I32);
+       gen_op_and32(tmp, reg, gen_im32(mask));
+       if (offset > 0) {
+           tmp1 = gen_new_qreg(QMODE_I32);
+           gen_op_rol32(tmp1, tmp, gen_im32(offset));
+       } else
+           tmp1 = tmp;
+       gen_logic_cc(s, tmp1);
+       switch (op) {
+       case 0: /* bftst */
+           break;
+       case 1: /* bfextu */
+           if (offset + width != 32)
+               gen_op_rol32(reg2, tmp, gen_im32((offset + width) & 31));
+           else
+               gen_op_mov32(reg2, tmp);
+           break;
+       case 2: /* bfchg */
+           gen_op_xor32(reg, reg, gen_im32(mask));
+           break;
+       case 3: /* bfexts */
+           if (offset > 0)
+               gen_op_rol32(reg2, tmp, gen_im32(offset));
+           if (width < 32)
+               gen_op_sar32(reg2, reg2, gen_im32(32 - width));
+           break;
+       case 4: /* bfclr */
+           gen_op_and32(reg, reg, gen_im32(~mask));
+           break;
+       case 5: /* bfffo */
+           if (offset > 0)
+               gen_op_rol32(reg2, tmp, gen_im32(offset));
+           gen_op_bfffo(tmp, tmp, gen_im32(width));
+           gen_op_add32(reg2, tmp, gen_im32(offset));
+           break;
+       case 6: /* bfset */
+           gen_op_or32(reg, reg, gen_im32(mask));
+           break;
+       case 7: /* bfins */
+           if (width == 32) {
+               if (offset > 0)
+                   gen_op_ror32(reg, reg2, gen_im32(offset));
+               else
+                   gen_op_mov32(reg, reg2);
+           } else {
+               gen_op_and32(tmp, reg2, gen_im32((1u << width) - 1));
+               if (offset + width != 32)
+                   gen_op_ror32(tmp, tmp, gen_im32((offset + width) & 31));
+               gen_op_and32(reg, reg, gen_im32(~mask));
+               gen_op_or32(reg, reg, tmp);
+           }
+           break;
+       }
+       return;
+    }
+    /* Not yet implemented */
+    gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+}
+
+/* Generate a load from a bitfield.  */
+static void gen_bitfield_load(DisasContext *s, int addr, int endpos,
+                             int *val1, int *val2)
+{
+    int tmp;
+
+    if (endpos <= 8)
+       *val1 = gen_load(s, OS_BYTE, addr, 0);
+    else if (endpos <= 24) {
+       *val1 = gen_load(s, OS_WORD, addr, 0);
+       if (endpos > 16) {
+           tmp = gen_new_qreg(QMODE_I32);
+           gen_op_add32(tmp, addr, gen_im32(2));
+           *val2 = gen_load(s, OS_BYTE, tmp, 0);
+       }
+    } else {
+       *val1 = gen_load(s, OS_LONG, addr, 0);
+       if (endpos > 32) {
+           tmp = gen_new_qreg(QMODE_I32);
+           gen_op_add32(tmp, addr, gen_im32(4));
+           *val2 = gen_load(s, OS_BYTE, tmp, 0);
+       }
+    }
+}
+
+/* Generate a store to a bitfield.  */
+static void gen_bitfield_store(DisasContext *s, int addr, int endpos,
+                              int val1, int val2)
+{
+    int tmp;
+
+    if (endpos <= 8)
+       gen_store(s, OS_BYTE, addr, val1);
+    else if (endpos <= 24) {
+       gen_store(s, OS_WORD, addr, val1);
+       if (endpos > 16) {
+           tmp = gen_new_qreg(QMODE_I32);
+           gen_op_add32(tmp, addr, gen_im32(2));
+           gen_store(s, OS_BYTE, tmp, val2);
+       }
+    } else {
+       gen_store(s, OS_LONG, addr, val1);
+       if (endpos > 32) {
+           tmp = gen_new_qreg(QMODE_I32);
+           gen_op_add32(tmp, addr, gen_im32(4));
+           gen_store(s, OS_BYTE, tmp, val2);
+       }
+    }
+}
+
+static int gen_bitfield_cc(DisasContext *s, int offset, int width,
+                          int val1, int val2)
+{
+    int dest;
+    int tmp;
+
+    dest = gen_new_qreg(QMODE_I32);
+    if (offset + width <= 8)
+       gen_op_shl32(dest, val1, gen_im32(24 + offset));
+    else if (offset + width <= 24) {
+       gen_op_shl32(dest, val1, gen_im32(16 + offset));
+       if (offset + width > 16) {
+           tmp = gen_new_qreg(QMODE_I32);
+           gen_op_shl32(tmp, val2, gen_im32(8 + offset));
+           gen_op_or32(dest, dest, tmp);
+       }
+    } else {
+       gen_op_shl32(dest, val1, gen_im32(offset));
+       if (offset + width > 32) {
+           tmp = gen_new_qreg(QMODE_I32);
+           gen_op_shr32(tmp, val2, gen_im32(offset));
+           gen_op_or32(dest, dest, tmp);
+       }
+    }
+    gen_op_and32(dest, dest, gen_im32(0xffffffff << (32 - width)));
+    gen_logic_cc(s, dest);
+    return dest;
+}
+
+static void gen_bitfield_op(int offset, int width, int op, int val1, int val2)
+{
+    uint32_t mask1;
+    uint32_t mask2;
+    int endpos = offset + width;
+
+    if (endpos <= 8) {
+       mask1 = (0xff >> offset) & (0xff << (8 - endpos));
+       mask2 = 0;
+    } else if (endpos <= 16) {
+       mask1 = (0xffff >> offset) & (0xffff << (16 - endpos));
+       mask2 = 0;
+    } else if (endpos <= 24) {
+       mask1 = 0xffffff >> offset;
+       mask2 = 0xff & (0xff << (24 - endpos));
+    } else if (endpos <= 32) {
+       mask1 = (0xffffffff >> offset) & (0xffffffff << (32 - endpos));
+       mask2 = 0;
+    } else {
+       mask1 = 0xffffffff >> offset;
+       mask2 = 0xff & (0xff << (40 - endpos));
+    }
+    switch (op) {
+    case 2:                    /* bfchg */
+       gen_op_xor32(val1, val1, gen_im32(mask1));
+       if (mask2)
+           gen_op_xor32(val2, val2, gen_im32(mask2));
+       break;
+    case 4:                    /* bfclr */
+       gen_op_and32(val1, val1, gen_im32(~mask1));
+       if (mask2)
+           gen_op_and32(val2, val2, gen_im32(~mask2));
+       break;
+    case 6:                    /* bfset */
+       gen_op_or32(val1, val1, gen_im32(mask1));
+       if (mask2)
+           gen_op_or32(val2, val2, gen_im32(mask2));
+       break;
+    }
+}
+
+static void gen_bitfield_ins(int offset, int width, int src,
+                            int val1, int val2)
+{
+    int tmp;
+    int endpos = offset + width;
+
+    tmp = gen_new_qreg(QMODE_I32);
+    if (width < 32) {
+       gen_op_and32(tmp, src, gen_im32((1u << width) - 1));
+    } else
+       gen_op_mov32(tmp, src);
+    if (endpos <= 8) {
+       if (endpos < 8)
+           gen_op_shl32(tmp, tmp, gen_im32(8 - endpos));
+       gen_op_or32(val1, val1, tmp);
+    } else if (endpos <= 16) {
+       if (endpos < 16)
+           gen_op_shl32(tmp, tmp, gen_im32(16 - endpos));
+       gen_op_or32(val1, val1, tmp);
+    } else if (endpos <= 24) {
+       gen_op_shr32(tmp, tmp, gen_im32(endpos - 16));
+       gen_op_or32(val1, val1, tmp);
+       gen_op_and32(tmp, src, gen_im32((1u << (endpos - 16)) - 1));
+       if (endpos < 24)
+           gen_op_shl32(tmp, tmp, gen_im32(24 - endpos));
+       gen_op_or32(val2, val2, tmp);
+    } else if (endpos <= 32) {
+       if (endpos < 32)
+           gen_op_shl32(tmp, tmp, gen_im32(32 - endpos));
+       gen_op_or32(val1, val1, tmp);
+    } else {
+       gen_op_shr32(tmp, tmp, gen_im32(endpos - 32));
+       gen_op_or32(val1, val1, tmp);
+       gen_op_and32(tmp, src, gen_im32((1u << (endpos - 32)) - 1));
+       gen_op_shr32(tmp, tmp, gen_im32(32 - endpos));
+       gen_op_or32(val2, val2, tmp);
+    }
+}
+
+DISAS_INSN(bitfield_mem)
+{
+    uint16_t ext;
+    int val;
+    int val1, val2;
+    int src;
+    int offset;
+    int width;
+    int op;
+    int reg;
+    int addr;
+    uint32_t mask;
+
+    op = (insn >> 8) & 7;
+    ext = lduw_code(s->pc);
+    s->pc += 2;
+    src = gen_lea(s, insn, OS_LONG);
+    if (src == -1) {
+       gen_addr_fault(s);
+       return;
+    }
+    if ((ext & 0x820) == 0) {
+       /* constant offset and width */
+       offset = (ext >> 6) & 31;
+       width = (ext & 31);
+       if (width == 0)
+           width = 32;
+       reg = DREG(ext, 12);
+       mask = 0xffffffff << (32 - width);
+       addr = gen_new_qreg(QMODE_I32);
+       if (offset > 7) {
+           gen_op_add32(addr, src, gen_im32(offset >> 3));
+           offset &= 7;
+       } else
+           gen_op_mov32(addr, src);
+       if (offset > 0)
+           mask <<= 32 - offset;
+       gen_bitfield_load(s, addr, offset + width, &val1, &val2);
+       val = gen_bitfield_cc(s, offset, width, val1, val2);
+       switch (op) {
+       case 0: /* bftst */
+           break;
+       case 1: /* bfextu */
+           if (width < 32)
+               gen_op_shr32(reg, val, gen_im32(32 - width));
+           else
+               gen_op_mov32(reg, val);
+           break;
+       case 3: /* bfexts */
+           if (width < 32)
+               gen_op_sar32(reg, val, gen_im32(32 - width));
+           else
+               gen_op_mov32(reg, val);
+           break;
+       case 5: /* bfffo */
+           gen_op_bfffo(val, val, gen_im32(width));
+           gen_op_add32(reg, val, gen_im32(offset));
+           break;
+       case 2: /* bfchg */
+       case 4: /* bfclr */
+       case 6: /* bfset */
+           gen_bitfield_op(offset, width, op, val1, val2);
+           gen_bitfield_store(s, addr, offset + width, val1, val2);
+           break;
+       case 7: /* bfins */
+           gen_bitfield_op(offset, width, 4, val1, val2);
+           gen_bitfield_ins(offset, width, reg, val1, val2);
+           gen_bitfield_store(s, addr, offset + width, val1, val2);
+           break;
+       }
+       return;
+    }
+    /* Not yet implemented */
+    gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+}
+
 DISAS_INSN(ff1)
 {
     int reg;
@@ -2194,17 +2967,42 @@ DISAS_INSN(fpu)
     case 7:
         {
         int addr;
+       int incr;
         uint16_t mask;
-        if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
+        if ((ext & 0xf00) != 0 || (ext & 0xff) == 0)
             goto undef;
-        src = gen_lea(s, insn, OS_LONG);
-        if (src == -1) {
-            gen_addr_fault(s);
-            return;
-        }
+       if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU))
+           goto undef;
+       if ((insn & 070) == 040)
+           src = AREG(insn, 0);
+       else {
+           src = gen_lea(s, insn, OS_LONG);
+           if (src == -1) {
+               gen_addr_fault(s);
+               return;
+           }
+       }
         addr = gen_new_qreg(QMODE_I32);
         gen_op_mov32(addr, src);
         mask = 0x80;
+       if (m68k_feature(s->env, M68K_FEATURE_FPU))
+           incr = gen_im32(12);
+       else
+           incr = gen_im32(8);
+       if ((ext & (1 << 13)) && (insn & 070) == 040) {
+           dest = QREG_F7;
+           while (mask) {
+               if (ext & mask) {
+                   s->is_mem = 1;
+                   gen_op_sub32(addr, addr, incr);
+                   gen_op_mov32(AREG(insn, 0), addr);
+                   gen_st(s, f64, addr, dest);
+               }
+               mask >>= 1;
+               dest++;
+           }
+           return;
+       }
         dest = QREG_F0;
         while (mask) {
             if (ext & mask) {
@@ -2216,8 +3014,11 @@ DISAS_INSN(fpu)
                     /* load */
                     gen_ld(s, f64, dest, addr);
                 }
-                if (ext & (mask - 1))
-                    gen_op_add32(addr, addr, gen_im32(8));
+                if (ext & (mask - 1) || (insn & 070) == 030) {
+                    gen_op_add32(addr, addr, incr);
+                   if ((insn & 070) == 030)
+                       gen_op_mov32(AREG(insn, 0), addr);
+               }
             }
             mask >>= 1;
             dest++;
@@ -2293,6 +3094,12 @@ DISAS_INSN(fpu)
     case 0x23: case 0x63: case 0x67: /* fmul */
         gen_op_mulf64(res, res, src);
         break;
+    case 0x24:                      /* fsgldiv */
+       gen_op_divf64(res, res, src);
+       break;
+    case 0x27:                      /* fsglmul */
+       gen_op_mulf64(res, res, src);
+       break;
     case 0x28: case 0x68: case 0x6c: /* fsub */
         gen_op_subf64(res, res, src);
         break;
@@ -2759,85 +3566,155 @@ void register_m68k_insns (CPUM68KState *
         register_opcode(disas_##name, 0x##opcode, 0x##mask); \
     } while(0)
     INSN(undef,     0000, 0000, CF_ISA_A);
+    INSN(undef,     0000, 0000, M68000);
     INSN(arith_im,  0080, fff8, CF_ISA_A);
+    INSN(arith_im,  0000, ff00, M68000);
+    INSN(undef,     00c0, ffc0, M68000);
     INSN(bitrev,    00c0, fff8, CF_ISA_APLUSC);
     INSN(bitop_reg, 0100, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0100, f1c0, M68000);
     INSN(bitop_reg, 0140, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0140, f1c0, M68000);
     INSN(bitop_reg, 0180, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0180, f1c0, M68000);
     INSN(bitop_reg, 01c0, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 01c0, f1c0, M68000);
     INSN(arith_im,  0280, fff8, CF_ISA_A);
+    INSN(arith_im,  0200, ff00, M68000);
+    INSN(undef,     02c0, ffc0, M68000);
     INSN(byterev,   02c0, fff8, CF_ISA_APLUSC);
     INSN(arith_im,  0480, fff8, CF_ISA_A);
+    INSN(arith_im,  0400, ff00, M68000);
+    INSN(undef,     04c0, ffc0, M68000);
     INSN(ff1,       04c0, fff8, CF_ISA_APLUSC);
     INSN(arith_im,  0680, fff8, CF_ISA_A);
+    INSN(arith_im,  0600, ff00, M68000);
+    INSN(undef,     06c0, ffc0, M68000);
     INSN(bitop_im,  0800, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0800, ffc0, M68000);
     INSN(bitop_im,  0840, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0840, ffc0, M68000);
     INSN(bitop_im,  0880, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0880, ffc0, M68000);
     INSN(bitop_im,  08c0, ffc0, CF_ISA_A);
+    INSN(bitop_im,  08c0, ffc0, M68000);
     INSN(arith_im,  0a80, fff8, CF_ISA_A);
+    INSN(arith_im,  0a00, ff00, M68000);
+    INSN(undef,     0ac0, ffc0, M68000);
     INSN(arith_im,  0c00, ff38, CF_ISA_A);
+    INSN(arith_im,  0c00, ff00, M68000);
+    INSN(undef,     0cc0, ffc0, M68000);
     INSN(move,      1000, f000, CF_ISA_A);
+    INSN(move,      1000, f000, M68000);
     INSN(move,      2000, f000, CF_ISA_A);
+    INSN(move,      2000, f000, M68000);
     INSN(move,      3000, f000, CF_ISA_A);
+    INSN(move,      3000, f000, M68000);
     INSN(strldsr,   40e7, ffff, CF_ISA_APLUSC);
     INSN(negx,      4080, fff8, CF_ISA_A);
+    INSN(negx,      4000, ff00, M68000);
+    INSN(undef,     40c0, ffc0, M68000);
     INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
+    INSN(move_from_sr, 40c0, fff8, M68000);
     INSN(lea,       41c0, f1c0, CF_ISA_A);
+    INSN(lea,       41c0, f1c0, M68000);
     INSN(clr,       4200, ff00, CF_ISA_A);
+    INSN(clr,       4200, ff00, M68000);
     INSN(undef,     42c0, ffc0, CF_ISA_A);
+    INSN(undef,     42c0, ffc0, M68000);
     INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
     INSN(neg,       4480, fff8, CF_ISA_A);
+    INSN(neg,       4400, ff00, M68000);
+    INSN(undef,     44c0, ffc0, M68000);
     INSN(move_to_ccr, 44c0, ffc0, CF_ISA_A);
+    INSN(move_to_ccr, 44c0, ffc0, M68000);
     INSN(not,       4680, fff8, CF_ISA_A);
+    INSN(not,       4600, ff00, M68000);
+    INSN(undef,     46c0, ffc0, M68000);
     INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
     INSN(pea,       4840, ffc0, CF_ISA_A);
+    INSN(pea,       4840, ffc0, M68000);
     INSN(swap,      4840, fff8, CF_ISA_A);
+    INSN(swap,      4840, fff8, M68000);
     INSN(movem,     48c0, fbc0, CF_ISA_A);
+    INSN(movem,     48c0, fbc0, M68000);
     INSN(ext,       4880, fff8, CF_ISA_A);
+    INSN(ext,       4880, fff8, M68000);
     INSN(ext,       48c0, fff8, CF_ISA_A);
+    INSN(ext,       48c0, fff8, M68000);
     INSN(ext,       49c0, fff8, CF_ISA_A);
+    INSN(ext,       49c0, fff8, M68000);
     INSN(tst,       4a00, ff00, CF_ISA_A);
+    INSN(tst,       4a00, ff00, M68000);
     INSN(tas,       4ac0, ffc0, CF_ISA_B);
+    INSN(tas,       4ac0, ffc0, M68000);
     INSN(halt,      4ac8, ffff, CF_ISA_A);
     INSN(pulse,     4acc, ffff, CF_ISA_A);
     INSN(illegal,   4afc, ffff, CF_ISA_A);
+    INSN(illegal,   4afc, ffff, M68000);
     INSN(mull,      4c00, ffc0, CF_ISA_A);
+    INSN(mull,      4c00, ffc0, LONG_MULDIV);
     INSN(divl,      4c40, ffc0, CF_ISA_A);
+    INSN(divl,      4c40, ffc0, LONG_MULDIV);
     INSN(sats,      4c80, fff8, CF_ISA_B);
     INSN(trap,      4e40, fff0, CF_ISA_A);
+    INSN(trap,      4e40, fff0, M68000);
     INSN(link,      4e50, fff8, CF_ISA_A);
+    INSN(link,      4e50, fff8, M68000);
     INSN(unlk,      4e58, fff8, CF_ISA_A);
+    INSN(unlk,      4e58, fff8, M68000);
     INSN(move_to_usp, 4e60, fff8, USP);
     INSN(move_from_usp, 4e68, fff8, USP);
     INSN(nop,       4e71, ffff, CF_ISA_A);
+    INSN(nop,       4e71, ffff, M68000);
     INSN(stop,      4e72, ffff, CF_ISA_A);
+    INSN(stop,      4e72, ffff, M68000);
     INSN(rte,       4e73, ffff, CF_ISA_A);
+    INSN(rte,       4e73, ffff, M68000);
     INSN(rts,       4e75, ffff, CF_ISA_A);
+    INSN(rts,       4e75, ffff, M68000);
     INSN(movec,     4e7b, ffff, CF_ISA_A);
     INSN(jump,      4e80, ffc0, CF_ISA_A);
+    INSN(jump,      4e80, ffc0, M68000);
     INSN(jump,      4ec0, ffc0, CF_ISA_A);
-    INSN(addsubq,   5180, f1c0, CF_ISA_A);
+    INSN(jump,      4ec0, ffc0, M68000);
+    INSN(addsubq,   5080, f0c0, CF_ISA_A);
+    INSN(addsubq,   5000, f080, M68000);
+    INSN(addsubq,   5080, f0c0, M68000);
     INSN(scc,       50c0, f0f8, CF_ISA_A);
-    INSN(addsubq,   5080, f1c0, CF_ISA_A);
+    INSN(scc_mem,   50c0, f0c0, M68000);
+    INSN(scc,       50c0, f0f8, M68000);
+    INSN(dbcc,      50c8, f0f8, M68000);
     INSN(tpf,       51f8, fff8, CF_ISA_A);
 
     /* Branch instructions.  */
     INSN(branch,    6000, f000, CF_ISA_A);
+    INSN(branch,    6000, f000, M68000);
     /* Disable long branch instructions, then add back the ones we want.  */
     INSN(undef,     60ff, f0ff, CF_ISA_A); /* All long branches.  */
+    INSN(undef,     60ff, f0ff, M68000); /* All long branches.  */
     INSN(branch,    60ff, f0ff, CF_ISA_B);
     INSN(undef,     60ff, ffff, CF_ISA_B); /* bra.l */
     INSN(branch,    60ff, ffff, BRAL);
+    INSN(branch,    60ff, f0ff, BCCL);
 
     INSN(moveq,     7000, f100, CF_ISA_A);
+    INSN(moveq,     7000, f100, M68000);
     INSN(mvzs,      7100, f100, CF_ISA_B);
     INSN(or,        8000, f000, CF_ISA_A);
+    INSN(or,        8000, f000, M68000);
     INSN(divw,      80c0, f0c0, CF_ISA_A);
+    INSN(divw,      80c0, f0c0, M68000);
     INSN(addsub,    9000, f000, CF_ISA_A);
+    INSN(addsub,    9000, f000, M68000);
+    INSN(undef,     90c0, f0c0, CF_ISA_A);
     INSN(subx,      9180, f1f8, CF_ISA_A);
+    INSN(subx,      9100, f138, M68000);
     INSN(suba,      91c0, f1c0, CF_ISA_A);
+    INSN(suba,      90c0, f0c0, M68000);
 
     INSN(undef_mac, a000, f000, CF_ISA_A);
+    INSN(undef_mac, a000, f000, M68000);
     INSN(mac,       a000, f100, CF_EMAC);
     INSN(from_mac,  a180, f9b0, CF_EMAC);
     INSN(move_mac,  a110, f9fc, CF_EMAC);
@@ -2856,19 +3733,50 @@ void register_m68k_insns (CPUM68KState *
     INSN(cmpa,      b0c0, f1c0, CF_ISA_B); /* cmpa.w */
     INSN(cmp,       b080, f1c0, CF_ISA_A);
     INSN(cmpa,      b1c0, f1c0, CF_ISA_A);
+    INSN(cmp,       b000, f100, M68000);
+    INSN(cmpa,      b0c0, f0c0, M68000);
     INSN(eor,       b180, f1c0, CF_ISA_A);
+    INSN(eor,       b180, f1c0, M68000);
     INSN(and,       c000, f000, CF_ISA_A);
+    INSN(and,       c000, f000, M68000);
     INSN(mulw,      c0c0, f0c0, CF_ISA_A);
+    INSN(mulw,      c0c0, f0c0, M68000);
     INSN(addsub,    d000, f000, CF_ISA_A);
+    INSN(addsub,    d000, f000, M68000);
+    INSN(undef,     d0c0, f0c0, CF_ISA_A);
     INSN(addx,      d180, f1f8, CF_ISA_A);
+    INSN(addx,      d100, f138, M68000);
     INSN(adda,      d1c0, f1c0, CF_ISA_A);
+    INSN(adda,      d0c0, f0c0, M68000);
     INSN(shift_im,  e080, f0f0, CF_ISA_A);
     INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
+    INSN(shift_im,    e080, f0f0, M68000);
+    INSN(shift8_im,   e000, f0f0, M68000);
+    INSN(shift16_im,  e040, f0f0, M68000);
+    INSN(shift_reg,   e0a0, f0f0, M68000);
+    INSN(shift8_reg,  e020, f0f0, M68000);
+    INSN(shift16_reg, e060, f0f0, M68000);
+    INSN(rotate_im,   e090, f0f0, M68000);
+    INSN(rotate8_im,  e010, f0f0, M68000);
+    INSN(rotate16_im, e050, f0f0, M68000);
+    INSN(rotate_reg,  e0b0, f0f0, M68000);
+    INSN(rotate8_reg, e030, f0f0, M68000);
+    INSN(rotate16_reg,e070, f0f0, M68000);
+    INSN(shift_mem,   e0c0, fcc0, M68000);
+    INSN(rotate_mem,  e4c0, fcc0, M68000);
+    INSN(bitfield_mem,e8c0, f8c0, BITFIELD);
+    INSN(bitfield_reg,e8c0, f8f8, BITFIELD);
+
     INSN(undef_fpu, f000, f000, CF_ISA_A);
+    INSN(undef_fpu, f000, f000, M68000);
     INSN(fpu,       f200, ffc0, CF_FPU);
     INSN(fbcc,      f280, ffc0, CF_FPU);
     INSN(frestore,  f340, ffc0, CF_FPU);
     INSN(fsave,     f340, ffc0, CF_FPU);
+    INSN(fpu,       f200, ffc0, FPU);
+    INSN(fbcc,      f280, ffc0, FPU);
+    INSN(frestore,  f340, ffc0, FPU);
+    INSN(fsave,     f340, ffc0, FPU);
     INSN(intouch,   f340, ffc0, CF_ISA_A);
     INSN(cpushl,    f428, ff38, CF_ISA_A);
     INSN(wddata,    fb00, ff00, CF_ISA_A);
-- 
Andreas Schwab, SuSE Labs, address@hidden
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

reply via email to

[Prev in Thread] Current Thread [Next in Thread]