Signed-off-by: Laurent Vivier
---
target-m68k/cpu.h | 14 -
target-m68k/helper.c| 139 ++--
target-m68k/translate.c | 82 ++--
3 files changed, 151 insertions(+), 84 deletions(-)
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index de902fd..c769711 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -133,13 +133,23 @@ void cpu_m68k_flush_flags(CPUM68KState *, int);
enum {
CC_OP_DYNAMIC, /* Use env->cc_op */
CC_OP_FLAGS, /* CC_DEST = CVZN, CC_SRC = unused */
+CC_OP_LOGICB, /* CC_DEST = result, CC_SRC = unused */
+CC_OP_LOGICW, /* CC_DEST = result, 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_SHIFTB, /* CC_DEST = result, CC_SRC = carry */
+CC_OP_SHIFTW, /* CC_DEST = result, CC_SRC = carry */
CC_OP_SHIFT, /* CC_DEST = result, CC_SRC = carry */
};
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index a8f6d9d..c97b989 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -139,22 +139,63 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
uint32_t dest;
uint32_t tmp;
-#define HIGHBIT 0x8000u
-
-#define SET_NZ(x) do { \
-if ((x) == 0) \
-flags |= CCF_Z; \
-else if ((int32_t)(x) < 0) \
-flags |= CCF_N; \
+#define HIGHBIT(type) (1u << (sizeof(type) * 8 - 1))
+
+#define SET_NZ(x, type) do { \
+if ((type)(x) == 0) { \
+flags |= CCF_Z; \
+} else if ((type)(x) < 0) { \
+flags |= CCF_N; \
+} \
} while (0)
#define SET_FLAGS_SUB(type, utype) do { \
-SET_NZ((type)dest); \
-tmp = dest + src; \
-if ((utype) tmp < (utype) src) \
-flags |= CCF_C; \
-if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
-flags |= CCF_V; \
+SET_NZ(dest, type); \
+tmp = dest + src; \
+if ((utype) tmp < (utype) src) { \
+flags |= CCF_C; \
+} \
+if (HIGHBIT(type) & (tmp ^ dest) & (tmp ^ src)) { \
+flags |= CCF_V; \
+} \
+} while (0)
+
+#define SET_FLAGS_ADD(type, utype) do { \
+SET_NZ(dest, type); \
+if ((utype) dest < (utype) src) { \
+flags |= CCF_C; \
+} \
+tmp = dest - src; \
+if (HIGHBIT(type) & (src ^ dest) & ~(tmp ^ src)) { \
+flags |= CCF_V; \
+} \
+} while (0)
+
+#define SET_FLAGS_ADDX(type, utype) do { \
+SET_NZ(dest, type); \
+if ((utype) dest <= (utype) src) { \
+flags |= CCF_C; \
+} \
+tmp = dest - src - 1; \
+if (HIGHBIT(type) & (src ^ dest) & ~(tmp ^ src)) { \
+flags |= CCF_V; \
+} \
+} while (0)
+
+#define SET_FLAGS_SUBX(type, utype) do { \
+SET_NZ(dest, type); \
+tmp = dest + src + 1; \
+if ((utype) tmp <= (utype) src) { \
+flags |= CCF_C; \
+} \
+if (HIGHBIT(type) & (tmp ^ dest) & (tmp ^ src)) { \
+flags |= CCF_V; \
+} \
+} while (0)
+
+#define SET_FLAGS_SHIFT(type) do { \
+SET_NZ(dest, type); \
+flags |= src; \
} while (0)
flags = 0;
@@ -164,46 +205,66 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
case CC_OP_FLAGS:
flags = dest;
break;
+case CC_OP_LOGICB:
+SET_NZ(dest, int8_t);
+goto set_x;
+break;
+case CC_OP_LOGICW:
+SET_NZ(dest, int16_t);
+goto set_x;
+break;
case CC_OP_LOGIC:
-SET_NZ(dest);
+SET_NZ(dest, int32_t);
+set_x:
+if (!m68k_feature(env, M68K_FEATURE_M68000)) {
+/* Unlike m68k, coldfire always clears the overflow bit. */
+env->cc_x = 0;
+}
+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))
-