2727 lines
71 KiB
Diff
2727 lines
71 KiB
Diff
Index: gdbstub.c
|
|
================================================================================
|
|
--- gdbstub.c
|
|
+++ gdbstub.c
|
|
@@ -558,7 +558,9 @@
|
|
for (i = 0; i < 8; i++) {
|
|
u.d = env->fregs[i];
|
|
*(uint32_t *)ptr = tswap32(u.l.upper);
|
|
+ ptr += 4;
|
|
*(uint32_t *)ptr = tswap32(u.l.lower);
|
|
+ ptr += 8;
|
|
}
|
|
/* FP control regs (not implemented). */
|
|
memset (ptr, 0, 3 * 4);
|
|
@@ -592,7 +594,9 @@
|
|
ColdFire has 8-bit double precision registers. */
|
|
for (i = 0; i < 8; i++) {
|
|
u.l.upper = tswap32(*(uint32_t *)ptr);
|
|
+ ptr += 4;
|
|
u.l.lower = tswap32(*(uint32_t *)ptr);
|
|
+ ptr += 8;
|
|
env->fregs[i] = u.d;
|
|
}
|
|
/* FP control regs (not implemented). */
|
|
--- target-m68k/cpu.h
|
|
+++ target-m68k/cpu.h
|
|
@@ -89,6 +89,9 @@
|
|
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;
|
|
@@ -135,14 +138,26 @@
|
|
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 */
|
|
};
|
|
|
|
@@ -191,6 +206,12 @@
|
|
ISA revisions mentioned. */
|
|
|
|
enum m68k_features {
|
|
+ M68K_FEATURE_M68000,
|
|
+ M68K_FEATURE_M68020,
|
|
+ M68K_FEATURE_M68020_40, /* Features common to 68020 - 68040 */
|
|
+ M68K_FEATURE_M68040,
|
|
+ M68K_FEATURE_M68020_60, /* Feature common to 68020 - 68060 */
|
|
+ M68K_FEATURE_M68060,
|
|
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). */
|
|
@@ -201,7 +222,9 @@
|
|
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_FPU
|
|
};
|
|
|
|
static inline int m68k_feature(CPUM68KState *env, int feature)
|
|
@@ -212,8 +235,8 @@
|
|
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
|
|
--- target-m68k/exec.h
|
|
+++ target-m68k/exec.h
|
|
@@ -48,6 +48,10 @@
|
|
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) {
|
|
--- target-m68k/helper.c
|
|
+++ target-m68k/helper.c
|
|
@@ -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 @@
|
|
};
|
|
|
|
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,41 @@
|
|
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_M68020_40);
|
|
+ m68k_set_feature(env, M68K_FEATURE_M68020_60);
|
|
+ m68k_set_feature(env, M68K_FEATURE_USP);
|
|
+ m68k_set_feature(env, M68K_FEATURE_BRAL);
|
|
+ m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
|
|
+ m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
|
|
+ m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
|
|
+ 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_M68020_60);
|
|
+ m68k_set_feature(env, M68K_FEATURE_USP);
|
|
+ m68k_set_feature(env, M68K_FEATURE_BRAL);
|
|
+ m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
|
|
+ m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
|
|
+ m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
|
|
+ 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,12 +113,19 @@
|
|
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_M68020);
|
|
+ m68k_set_feature(env, M68K_FEATURE_M68020_40);
|
|
+ m68k_set_feature(env, M68K_FEATURE_M68040);
|
|
+ m68k_set_feature(env, M68K_FEATURE_M68020_60);
|
|
+ m68k_set_feature(env, M68K_FEATURE_M68060);
|
|
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);
|
|
@@ -93,6 +137,7 @@
|
|
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);
|
|
break;
|
|
}
|
|
@@ -102,6 +147,42 @@
|
|
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 +208,66 @@
|
|
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 +278,68 @@
|
|
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);
|
|
--- target-m68k/op-hacks.h
|
|
+++ target-m68k/op-hacks.h
|
|
@@ -89,6 +89,36 @@
|
|
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
|
|
--- target-m68k/op.c
|
|
+++ target-m68k/op.c
|
|
@@ -136,6 +136,76 @@
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
/* 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 @@
|
|
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 @@
|
|
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();
|
|
}
|
|
--- target-m68k/qregs.def
|
|
+++ target-m68k/qregs.def
|
|
@@ -32,6 +32,7 @@
|
|
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)
|
|
--- target-m68k/translate.c
|
|
+++ target-m68k/translate.c
|
|
@@ -250,6 +250,9 @@
|
|
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 @@
|
|
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 @@
|
|
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 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 @@
|
|
|
|
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_M68020_40)) {
|
|
+ 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 @@
|
|
} 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_M68020_60))
|
|
+ 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 @@
|
|
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 @@
|
|
int reg;
|
|
int tmp;
|
|
int is_load;
|
|
+ int opsize;
|
|
+ int incr;
|
|
|
|
mask = lduw_code(s->pc);
|
|
s->pc += 2;
|
|
@@ -1076,21 +1118,40 @@
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
{
|
|
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(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(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 @@
|
|
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);
|
|
}
|
|
@@ -1493,28 +1555,149 @@
|
|
DEST_EA(insn, OS_BYTE, dest, &addr);
|
|
}
|
|
|
|
+DISAS_INSN(cas)
|
|
+{
|
|
+ int opsize;
|
|
+ int src;
|
|
+ int tmp;
|
|
+ int ext;
|
|
+ int regc;
|
|
+ int regu;
|
|
+ int l1, l2;
|
|
+ int addr;
|
|
+
|
|
+ ext = lduw_code(s->pc);
|
|
+ s->pc += 2;
|
|
+ regc = DREG(ext, 0);
|
|
+ regu = DREG(ext, 6);
|
|
+ tmp = gen_new_qreg(QMODE_I32);
|
|
+ switch ((insn >> 9) & 3) {
|
|
+ case 1:
|
|
+ opsize = OS_BYTE;
|
|
+ break;
|
|
+ case 2:
|
|
+ opsize = OS_WORD;
|
|
+ break;
|
|
+ case 3:
|
|
+ opsize = OS_LONG;
|
|
+ break;
|
|
+ default:
|
|
+ abort();
|
|
+ }
|
|
+ SRC_EA(src, opsize, -1, &addr);
|
|
+ gen_op_sub32(tmp, src, regc);
|
|
+ gen_op_update_cc_add(tmp, regc);
|
|
+ SET_CC_OP(opsize, SUB);
|
|
+ l1 = gen_new_label();
|
|
+ l2 = gen_new_label();
|
|
+ gen_jmpcc(s, 6, l1);
|
|
+ DEST_EA(insn, opsize, regu, &addr);
|
|
+ gen_op_jmp(l2);
|
|
+ gen_set_label(l1);
|
|
+ gen_partset_reg(opsize, regc, src);
|
|
+ gen_set_label(l2);
|
|
+}
|
|
+
|
|
+DISAS_INSN(cas2)
|
|
+{
|
|
+ int opsize;
|
|
+ int src1, src2;
|
|
+ int cmp1, cmp2;
|
|
+ int ext1, ext2;
|
|
+ int regc1, regc2;
|
|
+ int regu1, regu2;
|
|
+ int tmp;
|
|
+ int l1, l2;
|
|
+
|
|
+ ext1 = lduw_code(s->pc);
|
|
+ s->pc += 2;
|
|
+ regc1 = DREG(ext1, 0);
|
|
+ regu1 = DREG(ext1, 6);
|
|
+ if (ext1 & 0x8000)
|
|
+ src1 = AREG(ext1, 12);
|
|
+ else
|
|
+ src1 = DREG(ext1, 12);
|
|
+ ext2 = lduw_code(s->pc);
|
|
+ s->pc += 2;
|
|
+ regc2 = DREG(ext2, 0);
|
|
+ regu2 = DREG(ext2, 6);
|
|
+ if (ext2 & 0x8000)
|
|
+ src2 = AREG(ext2, 12);
|
|
+ else
|
|
+ src2 = DREG(ext2, 12);
|
|
+ if (insn & 0x200)
|
|
+ opsize = OS_LONG;
|
|
+ else
|
|
+ opsize = OS_WORD;
|
|
+ l1 = gen_new_label();
|
|
+ l2 = gen_new_label();
|
|
+ tmp = gen_new_qreg(QMODE_I32);
|
|
+ cmp1 = gen_load(s, opsize, src1, 1);
|
|
+ cmp2 = gen_load(s, opsize, src2, 1);
|
|
+ gen_op_sub32(tmp, cmp1, regc1);
|
|
+ gen_op_update_cc_add(tmp, regc1);
|
|
+ SET_CC_OP(opsize, SUB);
|
|
+ gen_jmpcc(s, 6, l1);
|
|
+ gen_op_sub32(tmp, cmp2, regc2);
|
|
+ gen_op_update_cc_add(tmp, regc2);
|
|
+ SET_CC_OP(opsize, SUB);
|
|
+ gen_jmpcc(s, 6, l1);
|
|
+ gen_store(s, opsize, src1, regu1);
|
|
+ gen_store(s, opsize, src2, regu2);
|
|
+ gen_op_jmp(l2);
|
|
+ gen_set_label(l1);
|
|
+ gen_partset_reg(opsize, regc1, cmp1);
|
|
+ gen_partset_reg(opsize, regc2, cmp2);
|
|
+ gen_set_label(l2);
|
|
+}
|
|
+
|
|
DISAS_INSN(mull)
|
|
{
|
|
uint16_t ext;
|
|
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_M68020_40)) {
|
|
+ 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)
|
|
@@ -1534,6 +1717,22 @@
|
|
gen_op_add32(QREG_SP, tmp, gen_im32(offset));
|
|
}
|
|
|
|
+DISAS_INSN(linkl)
|
|
+{
|
|
+ int32_t offset;
|
|
+ int reg;
|
|
+ int tmp;
|
|
+
|
|
+ offset = read_im32(s);
|
|
+ reg = AREG(insn, 0);
|
|
+ tmp = gen_new_qreg(QMODE_I32);
|
|
+ gen_op_sub32(tmp, QREG_SP, gen_im32(4));
|
|
+ gen_store(s, OS_LONG, tmp, reg);
|
|
+ if (reg != QREG_SP)
|
|
+ gen_op_mov32(reg, tmp);
|
|
+ gen_op_add32(QREG_SP, tmp, gen_im32(offset));
|
|
+}
|
|
+
|
|
DISAS_INSN(unlk)
|
|
{
|
|
int src;
|
|
@@ -1586,8 +1785,14 @@
|
|
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 +1811,15 @@
|
|
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 +1838,47 @@
|
|
}
|
|
}
|
|
|
|
+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 +1944,19 @@
|
|
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 +1966,7 @@
|
|
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 +2011,18 @@
|
|
|
|
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 +2042,7 @@
|
|
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 +2051,15 @@
|
|
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 +2068,19 @@
|
|
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 +2090,7 @@
|
|
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 +2143,58 @@
|
|
}
|
|
}
|
|
|
|
+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 +2219,603 @@
|
|
}
|
|
}
|
|
|
|
+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 +3079,42 @@
|
|
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 +3126,11 @@
|
|
/* 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 +3206,12 @@
|
|
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 +3678,158 @@
|
|
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(cas, 08c0, f8c0, M68020_60);
|
|
+ INSN(cas2, 0cfc, fdff, M68020_40);
|
|
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(linkl, 4808, fff8, M68020_60);
|
|
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, M68020_60);
|
|
INSN(divl, 4c40, ffc0, CF_ISA_A);
|
|
+ INSN(divl, 4c40, ffc0, M68020_60);
|
|
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, M68020_60);
|
|
|
|
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 +3848,50 @@
|
|
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, M68020_60);
|
|
+ INSN(bitfield_reg,e8c0, f8f8, M68020_60);
|
|
+
|
|
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);
|