qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 1/3] target-m68k: add cmpm


From: Richard Henderson
Subject: Re: [Qemu-devel] [PATCH v2 1/3] target-m68k: add cmpm
Date: Tue, 1 Nov 2016 11:48:36 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0

On 10/27/2016 03:43 PM, Laurent Vivier wrote:
+DISAS_INSN(cmpm)
+{
+    int opsize = insn_opsize(insn);
+    TCGv tmp = tcg_temp_new();
+    TCGv src, dst, addr;
+
+    src = gen_load(s, opsize, AREG(insn, 0), 1);
+    /* delay the update after the second gen_load() */
+    tcg_gen_addi_i32(tmp, AREG(insn, 0), opsize_bytes(opsize));
+
+    /* but if the we use the same address register to
+     * read the second value, we must use the updated address
+     */
+    if (REG(insn, 0) == REG(insn, 9)) {
+        addr = tmp;
+    } else {
+        addr = AREG(insn, 9);
+    }
+
+    dst = gen_load(s, opsize, addr, 1);
+    tcg_gen_mov_i32(AREG(insn, 0), tmp);
+    tcg_gen_addi_i32(AREG(insn, 9), addr, opsize_bytes(opsize));

I wonder if we should make this more generic.
I'm thinking of transparently fixing

    case 3: /* Indirect postincrement.  */
        reg = AREG(insn, 0);
        result = gen_ldst(s, opsize, reg, val, what);
        /* ??? This is not exception safe.  The instruction may still
           fault after this point.  */
        if (what == EA_STORE || !addrp)
            tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
        return result;

If we add to DisasContext

        unsigned writeback_mask;
        TCGv writeback[8];

Then

static TCGv get_areg(DisasContext *s, unsigned regno)
{
    if (s->writeback_mask & (1 << regno)) {
        return s->writeback[regno];
    } else {
        return cpu_aregs[regno];
    }
}

static void delay_set_areg(DisasContext *s, unsigned regno,
                           TCGv val, bool give_temp)
{
    if (s->writeback_mask & (1 << regno)) {
        tcg_gen_mov_i32(s->writeback[regno], val);
        if (give_temp) {
            tcg_temp_free(val);
        }
    } else {
        s->writeback_mask |= 1 << regno;
        if (give_temp) {
            s->writeback[regno] = val;
        } else {
            TCGv tmp = tcg_temp_new();
            tcg_gen_mov_i32(tmp, val);
            s->writeback[regno] = tmp;
        }
    }
}

static void do_writebacks(DisasContext *s)
{
    unsigned mask = s->writeback_mask;
    if (mask) {
        s->writeback_mask = 0;
        do {
            unsigned regno = ctz32(mask);
            tcg_gen_mov_i32(cpu_aregs[regno], s->writeback[regno]);
            tcg_temp_free(s->writeback[regno]);
            mask &= mask - 1;
        } while (mask);
    }
}

where get_areg is used within the AREG macro, delay_set_areg is used in those cases where pre- and post-increment are needed, and do_writebacks is invoked at the end of disas_m68k_insn.

This all pre-supposes that cmpm is not a special-case within the ISA, that any time one reuses a register after modification one sees the new value. Given the existing code within gen_ea, this would seem to be the case.

Thoughts?


r~



reply via email to

[Prev in Thread] Current Thread [Next in Thread]