diff mbox

[for-2.5,22/30] m68k: add cas instruction

Message ID 1439151229-27747-23-git-send-email-laurent@vivier.eu
State New
Headers show

Commit Message

Laurent Vivier Aug. 9, 2015, 8:13 p.m. UTC
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

Comments

Richard Henderson Aug. 12, 2015, 5:14 p.m. UTC | #1
On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> +    gen_logic_cc(s, res, opsize);
> +
> +    l1 = gen_new_label();
> +    l2 = gen_new_label();
> +
> +    gen_jmpcc(s, 6 /* !Z */, l1);
> +    gen_store(s, opsize, addr, update);
> +    tcg_gen_br(l2);
> +    gen_set_label(l1);
> +    tcg_gen_mov_i32(cmp, dest);
> +    gen_set_label(l2);
> +    tcg_temp_free(dest);
> +    tcg_temp_free(addr);

I would suggest writing this with movcond.  It avoids the branch, which is
requiring the use of the local temps.



r~
diff mbox

Patch

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index add3b69..9a7558a 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1464,6 +1464,70 @@  DISAS_INSN(arith_im)
     }
 }
 
+DISAS_INSN(cas)
+{
+    int opsize;
+    TCGv dest;
+    TCGv tmp;
+    TCGv cmp;
+    TCGv update;
+    TCGv taddr;
+    TCGv addr;
+    TCGv res;
+    uint16_t ext;
+    TCGLabel *l1, *l2;
+
+    if ((insn & 0x3f) == 0x3c) {
+        /* CAS2: Not yet implemented */
+        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+    }
+
+    switch ((insn >> 9) & 3) {
+    case 1:
+        opsize = OS_BYTE;
+        break;
+    case 2:
+        opsize = OS_WORD;
+        break;
+    case 3:
+        opsize = OS_LONG;
+        break;
+    default:
+        abort();
+    }
+
+    ext = read_im16(env, s);
+    taddr = gen_lea(env, s, insn, opsize);
+    if (IS_NULL_QREG(taddr)) {
+        gen_addr_fault(s);
+        return;
+    }
+
+    cmp = DREG(ext, 0);
+    update = DREG(ext, 6);
+    tmp = gen_load(s, opsize, taddr, 0);
+    dest = tcg_temp_local_new();
+    tcg_gen_mov_i32(dest, tmp);
+    addr = tcg_temp_local_new();
+    tcg_gen_mov_i32(addr, taddr);
+
+    res = tcg_temp_new();
+    tcg_gen_sub_i32(res, dest, cmp);
+    gen_logic_cc(s, res, opsize);
+
+    l1 = gen_new_label();
+    l2 = gen_new_label();
+
+    gen_jmpcc(s, 6 /* !Z */, l1);
+    gen_store(s, opsize, addr, update);
+    tcg_gen_br(l2);
+    gen_set_label(l1);
+    tcg_gen_mov_i32(cmp, dest);
+    gen_set_label(l2);
+    tcg_temp_free(dest);
+    tcg_temp_free(addr);
+}
+
 DISAS_INSN(byterev)
 {
     TCGv reg;
@@ -3080,6 +3144,7 @@  void register_m68k_insns (CPUM68KState *env)
     INSN(bitop_im,  0840, ffc0, M68000);
     INSN(bitop_im,  0880, ffc0, CF_ISA_A);
     INSN(bitop_im,  0880, ffc0, M68000);
+    INSN(cas,       08c0, f9c0, CAS);
     INSN(bitop_im,  08c0, ffc0, CF_ISA_A);
     INSN(bitop_im,  08c0, ffc0, M68000);
     INSN(arith_im,  0a80, fff8, CF_ISA_A);