This patch aims to add CMP2 instruction for m68k family.

Description: Compares the value in Rn to each bound. The effective address 
contains the
bounds pair: upper bound following the lower bound. For signed comparisons, the
arithmetically smaller value should be used as the lower bound. For unsigned
comparisons, the logically smaller value should be the lower bound.
The size of the data and the bounds can be specified as byte, word, or long. If 
Rn is a
data register and the operation size is byte or word, only the appropriate 
low-order part
of Rn is checked. If Rn is an address register and the operation size is byte 
or word,
the bounds operands are sign-extended to 32 bits, and the resultant operands are
compared to the full 32 bits of An.
If the upper bound equals the lower bound, the valid range is a single value.


signed-off-by: Guolei <guol-f...@cn.fujitsu.com 
<mailto:guol-f...@cn.fujitsu.com%20> >

---
target-m68k/translate.c |   74 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 74 insertions(+)

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index efd4cfc..8c09248 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1931,6 +1931,79 @@ DISAS_INSN(ff1)
     gen_helper_ff1(reg, reg);
}
+DISAS_INSN(cmp2)
+{
+    TCGv src;
+    TCGv reg;
+    int opsize;
+    int l1, l2, l3, l4;
+    TCGv lower, upper;
+    uint16_t ext;
+
+    switch ((insn >> 9) & 3) {
+           case 0:
+                    opsize = OS_BYTE;
+                    break;
+           case 1:
+                    opsize = OS_WORD;
+                    break;
+           case 2:
+                    opsize = OS_LONG;
+                    break;
+           default:
+                    gen_exception(s, s->pc, EXCP_ILLEGAL);
+                    return;
+    }
+
+    SRC_EA(env, src, opsize, -1, NULL);
+    lower = tcg_temp_new();
+    upper = tcg_temp_new();
+    tcg_gen_shri_i32(lower, lower, 16);
+    tcg_gen_andi_i32(lower, lower, 0xffff);
+    tcg_gen_andi_i32(upper, upper, 0xffff);
+
+    ext = cpu_ldsw_code(env, s->pc);
+       s->pc += 2;
+    if (ext & 0x8000) {
+           reg = AREG(ext, 12);
+    } else {
+           reg = DREG(ext, 12);
+           if (opsize == OS_BYTE){
+                    tcg_gen_andi_i32(reg, reg, 0xf);
+           } else if (opsize == OS_WORD) {
+                          tcg_gen_andi_i32(reg, reg, 0xff);
+           }
+    }
+
+    l1 = gen_new_label();
+    l2 = gen_new_label();
+    l3 = gen_new_label();
+    l4 = gen_new_label();
+
+    tcg_gen_brcond_i32(TCG_COND_NE, reg, lower, l1);
+    s->cc_op = CC_OP_FLAGS;
+    tcg_gen_ori_i32(QREG_CC_DEST, QREG_CC_DEST, CCF_Z);
+    tcg_gen_br(l4);
+
+    gen_set_label(l1);
+    tcg_gen_brcond_i32(TCG_COND_NE, reg, upper, l2);
+    s->cc_op = CC_OP_FLAGS;
+    tcg_gen_ori_i32(QREG_CC_DEST, QREG_CC_DEST, CCF_Z);
+    tcg_gen_br(l4);
+
+    gen_set_label(l2);
+    tcg_gen_brcond_i32(TCG_COND_GT, reg, lower, l3);
+    s->cc_op = CC_OP_FLAGS;
+    tcg_gen_ori_i32(QREG_CC_DEST, QREG_CC_DEST, CCF_C);
+    tcg_gen_br(l4);
+
+    gen_set_label(l3);
+    tcg_gen_brcond_i32(TCG_COND_LT, reg, upper, l4);
+    s->cc_op = CC_OP_FLAGS;
+    tcg_gen_ori_i32(QREG_CC_DEST, QREG_CC_DEST, CCF_C);
+    gen_set_label(l4);
+}
+
static TCGv gen_get_sr(DisasContext *s)
{
     TCGv ccr;
@@ -2847,6 +2920,7 @@ void register_m68k_insns (CPUM68KState *env)
     INSN(bitop_reg, 01c0, f1c0, CF_ISA_A);
     INSN(arith_im,  0280, fff8, CF_ISA_A);
     INSN(byterev,   02c0, fff8, CF_ISA_APLUSC);
+    INSN(cmp2,      02c0, ffff, CF_ISA_A);
     INSN(arith_im,  0480, fff8, CF_ISA_A);
     INSN(ff1,       04c0, fff8, CF_ISA_APLUSC);
     INSN(arith_im,  0680, fff8, CF_ISA_A);
--
1.7.9.5

Reply via email to