[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some in
From: |
Laurent Vivier |
Subject: |
[Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions. |
Date: |
Sat, 30 May 2009 00:41:48 +0200 |
This patch modifies following instructions to allow them to manage data
size other than "long", by adding "byte" and "word" data size: "addsub",
"arith_im", "addsubq", "or", "eor", "and".
This patch modifies following instructions to use EA to access data:
"neg", "not".
Signed-off-by: Andreas Schwab <address@hidden>
Signed-off-by: Laurent Vivier <address@hidden>
---
target-m68k/cpu.h | 10 ++-
target-m68k/helper.c | 74 ++++++++++++-----
target-m68k/translate.c | 202 +++++++++++++++++++++++++++--------------------
3 files changed, 177 insertions(+), 109 deletions(-)
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index eb18e9e..240d75f 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -131,11 +131,17 @@ 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_SHIFT, /* CC_DEST = result, CC_SRC = carry */
};
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index a22dc97..bcd73d5 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -256,6 +256,33 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
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)
+
flags = 0;
src = env->cc_src;
dest = env->cc_dest;
@@ -266,38 +293,41 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
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_SHIFT:
SET_NZ(dest);
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index dc34a2a..1bf7169 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -264,6 +264,22 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv
addr, TCGv val,
}
}
+/* Read a 8-bit immediat constant */
+static inline uint32_t read_im8(DisasContext *s)
+{
+ uint32_t im;
+ im = ldsb_code(s->pc + 1);
+ s->pc += 2;
+ return im;
+}
+/* Read a 16-bit immediat constant */
+static inline uint32_t read_im16(DisasContext *s)
+{
+ uint32_t im;
+ im = ldsw_code(s->pc);
+ s->pc += 2;
+ return im;
+}
/* Read a 32-bit immediate constant. */
static inline uint32_t read_im32(DisasContext *s)
{
@@ -440,6 +456,25 @@ static inline int opsize_bytes(int opsize)
}
}
+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, TCGv reg, TCGv val)
@@ -977,31 +1012,33 @@ DISAS_INSN(addsub)
TCGv tmp;
TCGv addr;
int add;
+ int opsize;
add = (insn & 0x4000) != 0;
+ opsize = insn_opsize(insn, 6);
reg = DREG(insn, 9);
dest = tcg_temp_new();
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) {
tcg_gen_add_i32(dest, tmp, src);
gen_helper_xflag_lt(QREG_CC_X, dest, src);
- s->cc_op = CC_OP_ADD;
+ SET_CC_OP(opsize, ADD);
} else {
gen_helper_xflag_lt(QREG_CC_X, tmp, src);
tcg_gen_sub_i32(dest, tmp, src);
- s->cc_op = CC_OP_SUB;
+ SET_CC_OP(opsize, SUB);
}
gen_update_cc_add(dest, src);
if (insn & 0x100) {
- DEST_EA(insn, OS_LONG, dest, &addr);
+ DEST_EA(insn, opsize, dest, &addr);
} else {
- tcg_gen_mov_i32(reg, dest);
+ gen_partset_reg(opsize, reg, dest);
}
}
@@ -1192,10 +1229,24 @@ DISAS_INSN(arith_im)
TCGv src1;
TCGv dest;
TCGv addr;
+ int opsize;
op = (insn >> 9) & 7;
- SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
- im = read_im32(s);
+ opsize = insn_opsize(insn, 6);
+ switch (opsize) {
+ case OS_BYTE:
+ im = read_im8(s);
+ break;
+ case OS_WORD:
+ im = read_im16(s);
+ break;
+ case OS_LONG:
+ im = read_im32(s);
+ break;
+ default:
+ abort();
+ }
+ SRC_EA(src1, opsize, -1, (op == 6) ? NULL : &addr);
dest = tcg_temp_new();
switch (op) {
case 0: /* ori */
@@ -1211,14 +1262,14 @@ DISAS_INSN(arith_im)
gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
tcg_gen_subi_i32(dest, dest, im);
gen_update_cc_add(dest, tcg_const_i32(im));
- s->cc_op = CC_OP_SUB;
+ SET_CC_OP(opsize, SUB);
break;
case 3: /* addi */
tcg_gen_mov_i32(dest, src1);
tcg_gen_addi_i32(dest, dest, im);
gen_update_cc_add(dest, tcg_const_i32(im));
gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
- s->cc_op = CC_OP_ADD;
+ SET_CC_OP(opsize, ADD);
break;
case 5: /* eori */
tcg_gen_xori_i32(dest, src1, im);
@@ -1228,13 +1279,13 @@ DISAS_INSN(arith_im)
tcg_gen_mov_i32(dest, src1);
tcg_gen_subi_i32(dest, dest, im);
gen_update_cc_add(dest, tcg_const_i32(im));
- 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);
}
}
@@ -1310,19 +1361,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, tcg_const_i32(0), NULL);
gen_logic_cc(s, tcg_const_i32(0));
}
@@ -1350,17 +1389,20 @@ DISAS_INSN(move_from_ccr)
DISAS_INSN(neg)
{
- TCGv reg;
TCGv src1;
+ TCGv dest;
+ TCGv addr;
+ int opsize;
- reg = DREG(insn, 0);
- src1 = tcg_temp_new();
- tcg_gen_mov_i32(src1, reg);
- tcg_gen_neg_i32(reg, src1);
- s->cc_op = CC_OP_SUB;
- gen_update_cc_add(reg, src1);
- gen_helper_xflag_lt(QREG_CC_X, tcg_const_i32(0), src1);
- s->cc_op = CC_OP_SUB;
+ opsize = insn_opsize(insn, 6);
+ SRC_EA(src1, opsize, -1, &addr);
+ dest = tcg_temp_new();
+ tcg_gen_neg_i32(dest, src1);
+ DEST_EA(insn, opsize, dest, &addr);
+ SET_CC_OP(opsize, SUB);
+ gen_update_cc_add(src1, dest);
+ gen_helper_xflag_lt(QREG_CC_X, tcg_const_i32(0), dest);
+ SET_CC_OP(opsize, SUB);
}
static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
@@ -1407,11 +1449,17 @@ DISAS_INSN(move_to_ccr)
DISAS_INSN(not)
{
- TCGv reg;
+ TCGv src1;
+ TCGv dest;
+ TCGv addr;
+ int opsize;
- reg = DREG(insn, 0);
- tcg_gen_not_i32(reg, reg);
- gen_logic_cc(s, reg);
+ opsize = insn_opsize(insn, 6);
+ SRC_EA(src1, opsize, -1, &addr);
+ dest = tcg_temp_new();
+ tcg_gen_not_i32(dest, src1);
+ DEST_EA(insn, opsize, dest, &addr);
+ gen_logic_cc(s, dest);
}
DISAS_INSN(swap)
@@ -1466,20 +1514,8 @@ DISAS_INSN(tst)
int opsize;
TCGv 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();
- }
- SRC_EA(tmp, opsize, 1, NULL);
+ opsize = insn_opsize(insn, 6);
+ SRC_EA(tmp, opsize, -1, NULL);
gen_logic_cc(s, tmp);
}
@@ -1600,8 +1636,14 @@ DISAS_INSN(addsubq)
TCGv dest;
int val;
TCGv 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;
@@ -1620,11 +1662,11 @@ DISAS_INSN(addsubq)
if (insn & 0x0100) {
gen_helper_xflag_lt(QREG_CC_X, dest, src2);
tcg_gen_subi_i32(dest, dest, val);
- s->cc_op = CC_OP_SUB;
+ SET_CC_OP(opsize, SUB);
} else {
tcg_gen_addi_i32(dest, dest, val);
gen_helper_xflag_lt(QREG_CC_X, dest, src2);
- s->cc_op = CC_OP_ADD;
+ SET_CC_OP(opsize, ADD);
}
gen_update_cc_add(dest, src2);
}
@@ -1712,17 +1754,19 @@ DISAS_INSN(or)
TCGv dest;
TCGv src;
TCGv addr;
+ int opsize;
+ opsize = insn_opsize(insn, 6);
reg = DREG(insn, 9);
dest = tcg_temp_new();
if (insn & 0x100) {
- SRC_EA(src, OS_LONG, 0, &addr);
+ SRC_EA(src, opsize, -1, &addr);
tcg_gen_or_i32(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);
tcg_gen_or_i32(dest, src, reg);
- tcg_gen_mov_i32(reg, dest);
+ gen_partset_reg(opsize, reg, dest);
}
gen_logic_cc(s, dest);
}
@@ -1763,34 +1807,18 @@ DISAS_INSN(mov3q)
DISAS_INSN(cmp)
{
- int op;
TCGv src;
TCGv reg;
TCGv 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();
- }
- SRC_EA(src, opsize, 1, NULL);
+ opsize = insn_opsize(insn, 6);
+ SRC_EA(src, opsize, -1, NULL);
reg = DREG(insn, 9);
dest = tcg_temp_new();
tcg_gen_sub_i32(dest, reg, src);
gen_update_cc_add(dest, src);
+ SET_CC_OP(opsize, SUB);
}
DISAS_INSN(cmpa)
@@ -1810,7 +1838,7 @@ DISAS_INSN(cmpa)
dest = tcg_temp_new();
tcg_gen_sub_i32(dest, reg, src);
gen_update_cc_add(dest, src);
- s->cc_op = CC_OP_SUB;
+ SET_CC_OP(opsize, SUB);
}
DISAS_INSN(eor)
@@ -1819,13 +1847,15 @@ DISAS_INSN(eor)
TCGv reg;
TCGv dest;
TCGv 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 = tcg_temp_new();
tcg_gen_xor_i32(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 +1864,19 @@ DISAS_INSN(and)
TCGv reg;
TCGv dest;
TCGv addr;
+ int opsize;
+ opsize = insn_opsize(insn, 6);
reg = DREG(insn, 9);
dest = tcg_temp_new();
if (insn & 0x100) {
- SRC_EA(src, OS_LONG, 0, &addr);
+ SRC_EA(src, opsize, -1, &addr);
tcg_gen_and_i32(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);
tcg_gen_and_i32(dest, src, reg);
- tcg_gen_mov_i32(reg, dest);
+ gen_partset_reg(opsize, reg, dest);
}
gen_logic_cc(s, dest);
}
--
1.5.6.5
- [Qemu-devel] [PATCH 00/17] m68k: add partial Motorola 680x0 support, Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 01/17] m68k: Replace gen_im32() by tcg_const_i32(), Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 02/17] m68k: add tcg_gen_debug_insn_start(), Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 03/17] m68k: define m680x0 CPUs and features, Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 04/17] m68k: add missing accessing modes for some instructions.,
Laurent Vivier <=
- [Qemu-devel] [PATCH 05/17] m68k: add Motorola 680x0 family common instructions., Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 06/17] m68k: add Scc instruction with memory operand., Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 07/17] m68k: add DBcc instruction., Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 08/17] m68k: modify movem instruction to manage word, Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 09/17] m68k: add 64bit divide., Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 10/17] m68k: add 32bit and 64bit multiply, Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 11/17] m68k: add word data size for suba/adda, Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 12/17] m68k: add fpu, Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 13/17] m68k: add "byte", "word" and memory shift, Laurent Vivier, 2009/05/29
- [Qemu-devel] [PATCH 14/17] m68k: add "byte", "word" and memory rotate., Laurent Vivier, 2009/05/29