]> Git Repo - qemu.git/blobdiff - target-alpha/translate.c
target-alpha: Convert ARITH3 to source/sink
[qemu.git] / target-alpha / translate.c
index 5558b728dd104dd8ad4ffa1b876c332e87b1b39d..cff79ef626e3fb90208d3422d5c288047597fc2f 100644 (file)
@@ -38,7 +38,6 @@
 typedef struct DisasContext DisasContext;
 struct DisasContext {
     struct TranslationBlock *tb;
-    CPUAlphaState *env;
     uint64_t pc;
     int mem_idx;
 
@@ -46,6 +45,17 @@ struct DisasContext {
     int tb_rm;
     /* Current flush-to-zero setting for this TB.  */
     int tb_ftz;
+
+    /* implver value for this CPU.  */
+    int implver;
+
+    /* Temporaries for $31 and $f31 as source and destination.  */
+    TCGv zero;
+    TCGv sink;
+    /* Temporary for immediate constants.  */
+    TCGv lit;
+
+    bool singlestep_enabled;
 };
 
 /* Return values from translate_one, indicating the state of the TB.
@@ -96,8 +106,9 @@ void alpha_translate_init(void)
     char *p;
     static int done_init = 0;
 
-    if (done_init)
+    if (done_init) {
         return;
+    }
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
 
@@ -136,13 +147,74 @@ void alpha_translate_init(void)
                                      offsetof(CPUAlphaState, usp), "usp");
 #endif
 
-    /* register helpers */
-#define GEN_HELPER 2
-#include "helper.h"
-
     done_init = 1;
 }
 
+static TCGv load_zero(DisasContext *ctx)
+{
+    if (TCGV_IS_UNUSED_I64(ctx->zero)) {
+        ctx->zero = tcg_const_local_i64(0);
+    }
+    return ctx->zero;
+}
+
+static TCGv dest_sink(DisasContext *ctx)
+{
+    if (TCGV_IS_UNUSED_I64(ctx->sink)) {
+        ctx->sink = tcg_temp_local_new();
+    }
+    return ctx->sink;
+}
+
+static TCGv load_gpr(DisasContext *ctx, unsigned reg)
+{
+    if (likely(reg < 31)) {
+        return cpu_ir[reg];
+    } else {
+        return load_zero(ctx);
+    }
+}
+
+static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
+                         uint8_t lit, bool islit)
+{
+    if (islit) {
+        ctx->lit = tcg_const_i64(lit);
+        return ctx->lit;
+    } else if (likely(reg < 31)) {
+        return cpu_ir[reg];
+    } else {
+        return load_zero(ctx);
+    }
+}
+
+static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
+{
+    if (likely(reg < 31)) {
+        return cpu_ir[reg];
+    } else {
+        return dest_sink(ctx);
+    }
+}
+
+static TCGv load_fpr(DisasContext *ctx, unsigned reg)
+{
+    if (likely(reg < 31)) {
+        return cpu_fir[reg];
+    } else {
+        return load_zero(ctx);
+    }
+}
+
+static TCGv dest_fpr(DisasContext *ctx, unsigned reg)
+{
+    if (likely(reg < 31)) {
+        return cpu_fir[reg];
+    } else {
+        return dest_sink(ctx);
+    }
+}
+
 static void gen_excp_1(int exception, int error_code)
 {
     TCGv_i32 tmp1, tmp2;
@@ -168,44 +240,38 @@ static inline ExitStatus gen_invalid(DisasContext *ctx)
 
 static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
 {
-    TCGv tmp = tcg_temp_new();
     TCGv_i32 tmp32 = tcg_temp_new_i32();
-    tcg_gen_qemu_ld32u(tmp, t1, flags);
-    tcg_gen_trunc_i64_i32(tmp32, tmp);
+    tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
     gen_helper_memory_to_f(t0, tmp32);
     tcg_temp_free_i32(tmp32);
-    tcg_temp_free(tmp);
 }
 
 static inline void gen_qemu_ldg(TCGv t0, TCGv t1, int flags)
 {
     TCGv tmp = tcg_temp_new();
-    tcg_gen_qemu_ld64(tmp, t1, flags);
+    tcg_gen_qemu_ld_i64(tmp, t1, flags, MO_LEQ);
     gen_helper_memory_to_g(t0, tmp);
     tcg_temp_free(tmp);
 }
 
 static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
 {
-    TCGv tmp = tcg_temp_new();
     TCGv_i32 tmp32 = tcg_temp_new_i32();
-    tcg_gen_qemu_ld32u(tmp, t1, flags);
-    tcg_gen_trunc_i64_i32(tmp32, tmp);
+    tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
     gen_helper_memory_to_s(t0, tmp32);
     tcg_temp_free_i32(tmp32);
-    tcg_temp_free(tmp);
 }
 
 static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
 {
-    tcg_gen_qemu_ld32s(t0, t1, flags);
+    tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LESL);
     tcg_gen_mov_i64(cpu_lock_addr, t1);
     tcg_gen_mov_i64(cpu_lock_value, t0);
 }
 
 static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
 {
-    tcg_gen_qemu_ld64(t0, t1, flags);
+    tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LEQ);
     tcg_gen_mov_i64(cpu_lock_addr, t1);
     tcg_gen_mov_i64(cpu_lock_value, t0);
 }
@@ -213,10 +279,10 @@ static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
 static inline void gen_load_mem(DisasContext *ctx,
                                 void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1,
                                                           int flags),
-                                int ra, int rb, int32_t disp16, int fp,
-                                int clear)
+                                int ra, int rb, int32_t disp16, bool fp,
+                                bool clear)
 {
-    TCGv addr, va;
+    TCGv tmp, addr, va;
 
     /* LDQ_U with ra $31 is UNOP.  Other various loads are forms of
        prefetches, which we can treat as nops.  No worries about
@@ -225,33 +291,29 @@ static inline void gen_load_mem(DisasContext *ctx,
         return;
     }
 
-    addr = tcg_temp_new();
-    if (rb != 31) {
-        tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-        if (clear) {
-            tcg_gen_andi_i64(addr, addr, ~0x7);
-        }
-    } else {
-        if (clear) {
-            disp16 &= ~0x7;
-        }
-        tcg_gen_movi_i64(addr, disp16);
+    tmp = tcg_temp_new();
+    addr = load_gpr(ctx, rb);
+
+    if (disp16) {
+        tcg_gen_addi_i64(tmp, addr, disp16);
+        addr = tmp;
+    }
+    if (clear) {
+        tcg_gen_andi_i64(tmp, addr, ~0x7);
+        addr = tmp;
     }
 
     va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
     tcg_gen_qemu_load(va, addr, ctx->mem_idx);
 
-    tcg_temp_free(addr);
+    tcg_temp_free(tmp);
 }
 
 static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
 {
     TCGv_i32 tmp32 = tcg_temp_new_i32();
-    TCGv tmp = tcg_temp_new();
     gen_helper_f_to_memory(tmp32, t0);
-    tcg_gen_extu_i32_i64(tmp, tmp32);
-    tcg_gen_qemu_st32(tmp, t1, flags);
-    tcg_temp_free(tmp);
+    tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
     tcg_temp_free_i32(tmp32);
 }
 
@@ -259,53 +321,42 @@ static inline void gen_qemu_stg(TCGv t0, TCGv t1, int flags)
 {
     TCGv tmp = tcg_temp_new();
     gen_helper_g_to_memory(tmp, t0);
-    tcg_gen_qemu_st64(tmp, t1, flags);
+    tcg_gen_qemu_st_i64(tmp, t1, flags, MO_LEQ);
     tcg_temp_free(tmp);
 }
 
 static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
 {
     TCGv_i32 tmp32 = tcg_temp_new_i32();
-    TCGv tmp = tcg_temp_new();
     gen_helper_s_to_memory(tmp32, t0);
-    tcg_gen_extu_i32_i64(tmp, tmp32);
-    tcg_gen_qemu_st32(tmp, t1, flags);
-    tcg_temp_free(tmp);
+    tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
     tcg_temp_free_i32(tmp32);
 }
 
 static inline void gen_store_mem(DisasContext *ctx,
                                  void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
                                                             int flags),
-                                 int ra, int rb, int32_t disp16, int fp,
-                                 int clear)
+                                 int ra, int rb, int32_t disp16, bool fp,
+                                 bool clear)
 {
-    TCGv addr, va;
+    TCGv tmp, addr, va;
 
-    addr = tcg_temp_new();
-    if (rb != 31) {
-        tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-        if (clear) {
-            tcg_gen_andi_i64(addr, addr, ~0x7);
-        }
-    } else {
-        if (clear) {
-            disp16 &= ~0x7;
-        }
-        tcg_gen_movi_i64(addr, disp16);
-    }
+    tmp = tcg_temp_new();
+    addr = load_gpr(ctx, rb);
 
-    if (ra == 31) {
-        va = tcg_const_i64(0);
-    } else {
-        va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
+    if (disp16) {
+        tcg_gen_addi_i64(tmp, addr, disp16);
+        addr = tmp;
     }
+    if (clear) {
+        tcg_gen_andi_i64(tmp, addr, ~0x7);
+        addr = tmp;
+    }
+
+    va = (fp ? load_fpr(ctx, ra) : load_gpr(ctx, ra));
     tcg_gen_qemu_store(va, addr, ctx->mem_idx);
 
-    tcg_temp_free(addr);
-    if (ra == 31) {
-        tcg_temp_free(va);
-    }
+    tcg_temp_free(tmp);
 }
 
 static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
@@ -325,11 +376,7 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
     addr = tcg_temp_local_new();
 #endif
 
-    if (rb != 31) {
-        tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-    } else {
-        tcg_gen_movi_i64(addr, disp16);
-    }
+    tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
 
 #if defined(CONFIG_USER_ONLY)
     /* ??? This is handled via a complicated version of compare-and-swap
@@ -348,18 +395,11 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
         tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
 
         val = tcg_temp_new();
-        if (quad) {
-            tcg_gen_qemu_ld64(val, addr, ctx->mem_idx);
-        } else {
-            tcg_gen_qemu_ld32s(val, addr, ctx->mem_idx);
-        }
+        tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, quad ? MO_LEQ : MO_LESL);
         tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
 
-        if (quad) {
-            tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
-        } else {
-            tcg_gen_qemu_st32(cpu_ir[ra], addr, ctx->mem_idx);
-        }
+        tcg_gen_qemu_st_i64(cpu_ir[ra], addr, ctx->mem_idx,
+                            quad ? MO_LEQ : MO_LEUL);
         tcg_gen_movi_i64(cpu_ir[ra], 1);
         tcg_gen_br(lab_done);
 
@@ -375,13 +415,26 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
 #endif
 }
 
-static int use_goto_tb(DisasContext *ctx, uint64_t dest)
+static bool in_superpage(DisasContext *ctx, int64_t addr)
+{
+    return ((ctx->tb->flags & TB_FLAGS_USER_MODE) == 0
+            && addr < 0
+            && ((addr >> 41) & 3) == 2
+            && addr >> TARGET_VIRT_ADDR_SPACE_BITS == addr >> 63);
+}
+
+static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
 {
-    /* Check for the dest on the same page as the start of the TB.  We
-       also want to suppress goto_tb in the case of single-steping and IO.  */
-    return (((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0
-            && !ctx->env->singlestep_enabled
-            && !(ctx->tb->cflags & CF_LAST_IO));
+    /* Suppress goto_tb in the case of single-steping and IO.  */
+    if (ctx->singlestep_enabled || (ctx->tb->cflags & CF_LAST_IO)) {
+        return false;
+    }
+    /* If the destination is in the superpage, the page perms can't change.  */
+    if (in_superpage(ctx, dest)) {
+        return true;
+    }
+    /* Check for the dest on the same page as the start of the TB.  */
+    return ((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0;
 }
 
 static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
@@ -398,7 +451,7 @@ static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
     } else if (use_goto_tb(ctx, dest)) {
         tcg_gen_goto_tb(0);
         tcg_gen_movi_i64(cpu_pc, dest);
-        tcg_gen_exit_tb((tcg_target_long)ctx->tb);
+        tcg_gen_exit_tb((uintptr_t)ctx->tb);
         return EXIT_GOTO_TB;
     } else {
         tcg_gen_movi_i64(cpu_pc, dest);
@@ -417,12 +470,12 @@ static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
 
         tcg_gen_goto_tb(0);
         tcg_gen_movi_i64(cpu_pc, ctx->pc);
-        tcg_gen_exit_tb((tcg_target_long)ctx->tb);
+        tcg_gen_exit_tb((uintptr_t)ctx->tb);
 
         gen_set_label(lab_true);
         tcg_gen_goto_tb(1);
         tcg_gen_movi_i64(cpu_pc, dest);
-        tcg_gen_exit_tb((tcg_target_long)ctx->tb + 1);
+        tcg_gen_exit_tb((uintptr_t)ctx->tb + 1);
 
         return EXIT_GOTO_TB;
     } else {
@@ -506,42 +559,6 @@ static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
     return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
 }
 
-static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
-                     int islit, uint8_t lit, int mask)
-{
-    TCGv_i64 c1, z, v1;
-
-    if (unlikely(rc == 31)) {
-        return;
-    }
-
-    if (ra == 31) {
-        /* Very uncommon case - Do not bother to optimize.  */
-        c1 = tcg_const_i64(0);
-    } else if (mask) {
-        c1 = tcg_const_i64(1);
-        tcg_gen_and_i64(c1, c1, cpu_ir[ra]);
-    } else {
-        c1 = cpu_ir[ra];
-    }
-    if (islit) {
-        v1 = tcg_const_i64(lit);
-    } else {
-        v1 = cpu_ir[rb];
-    }
-    z = tcg_const_i64(0);
-
-    tcg_gen_movcond_i64(cond, cpu_ir[rc], c1, z, v1, cpu_ir[rc]);
-
-    tcg_temp_free_i64(z);
-    if (ra == 31 || mask) {
-        tcg_temp_free_i64(c1);
-    }
-    if (islit) {
-        tcg_temp_free_i64(v1);
-    }
-}
-
 static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
 {
     TCGv_i64 c1, z, v1;
@@ -784,29 +801,6 @@ static void gen_fcvtql_v(DisasContext *ctx, int rb, int rc)
     gen_fcvtql(rb, rc);
 }
 
-#define FARITH2(name)                                                   \
-    static inline void glue(gen_f, name)(int rb, int rc)                \
-    {                                                                   \
-        if (unlikely(rc == 31)) {                                       \
-            return;                                                     \
-        }                                                               \
-        if (rb != 31) {                                                 \
-            gen_helper_ ## name(cpu_fir[rc], cpu_env, cpu_fir[rb]);     \
-        } else {                                                        \
-            TCGv tmp = tcg_const_i64(0);                                \
-            gen_helper_ ## name(cpu_fir[rc], cpu_env, tmp);             \
-            tcg_temp_free(tmp);                                         \
-        }                                                               \
-    }
-
-/* ??? VAX instruction qualifiers ignored.  */
-FARITH2(sqrtf)
-FARITH2(sqrtg)
-FARITH2(cvtgf)
-FARITH2(cvtgq)
-FARITH2(cvtqf)
-FARITH2(cvtqg)
-
 static void gen_ieee_arith2(DisasContext *ctx,
                             void (*helper)(TCGv, TCGv_ptr, TCGv),
                             int rb, int rc, int fn11)
@@ -1001,48 +995,6 @@ static inline void gen_fcpyse(int ra, int rb, int rc)
     gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
 }
 
-#define FARITH3(name)                                                   \
-    static inline void glue(gen_f, name)(int ra, int rb, int rc)        \
-    {                                                                   \
-        TCGv va, vb;                                                    \
-                                                                        \
-        if (unlikely(rc == 31)) {                                       \
-            return;                                                     \
-        }                                                               \
-        if (ra == 31) {                                                 \
-            va = tcg_const_i64(0);                                      \
-        } else {                                                        \
-            va = cpu_fir[ra];                                           \
-        }                                                               \
-        if (rb == 31) {                                                 \
-            vb = tcg_const_i64(0);                                      \
-        } else {                                                        \
-            vb = cpu_fir[rb];                                           \
-        }                                                               \
-                                                                        \
-        gen_helper_ ## name(cpu_fir[rc], cpu_env, va, vb);              \
-                                                                        \
-        if (ra == 31) {                                                 \
-            tcg_temp_free(va);                                          \
-        }                                                               \
-        if (rb == 31) {                                                 \
-            tcg_temp_free(vb);                                          \
-        }                                                               \
-    }
-
-/* ??? VAX instruction qualifiers ignored.  */
-FARITH3(addf)
-FARITH3(subf)
-FARITH3(mulf)
-FARITH3(divf)
-FARITH3(addg)
-FARITH3(subg)
-FARITH3(mulg)
-FARITH3(divg)
-FARITH3(cmpgeq)
-FARITH3(cmpglt)
-FARITH3(cmpgle)
-
 static void gen_ieee_arith3(DisasContext *ctx,
                             void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
                             int ra, int rb, int rc, int fn11)
@@ -1123,8 +1075,9 @@ static inline uint64_t zapnot_mask(uint8_t lit)
     int i;
 
     for (i = 0; i < 8; ++i) {
-        if ((lit >> i) & 1)
+        if ((lit >> i) & 1) {
             mask |= 0xffull << (i * 8);
+        }
     }
     return mask;
 }
@@ -1151,165 +1104,111 @@ static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
         tcg_gen_mov_i64(dest, src);
         break;
     default:
-        tcg_gen_andi_i64 (dest, src, zapnot_mask (lit));
+        tcg_gen_andi_i64(dest, src, zapnot_mask(lit));
         break;
     }
 }
 
-static inline void gen_zapnot(int ra, int rb, int rc, int islit, uint8_t lit)
-{
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else if (islit)
-        gen_zapnoti(cpu_ir[rc], cpu_ir[ra], lit);
-    else
-        gen_helper_zapnot (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-}
-
-static inline void gen_zap(int ra, int rb, int rc, int islit, uint8_t lit)
-{
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else if (islit)
-        gen_zapnoti(cpu_ir[rc], cpu_ir[ra], ~lit);
-    else
-        gen_helper_zap (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-}
-
-
 /* EXTWH, EXTLH, EXTQH */
-static void gen_ext_h(int ra, int rb, int rc, int islit,
+static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else {
-        if (islit) {
-            lit = (64 - (lit & 7) * 8) & 0x3f;
-            tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit);
-        } else {
-            TCGv tmp1 = tcg_temp_new();
-            tcg_gen_andi_i64(tmp1, cpu_ir[rb], 7);
-            tcg_gen_shli_i64(tmp1, tmp1, 3);
-            tcg_gen_neg_i64(tmp1, tmp1);
-            tcg_gen_andi_i64(tmp1, tmp1, 0x3f);
-            tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], tmp1);
-            tcg_temp_free(tmp1);
-        }
-        gen_zapnoti(cpu_ir[rc], cpu_ir[rc], byte_mask);
+    if (islit) {
+        tcg_gen_shli_i64(vc, va, (64 - lit * 8) & 0x3f);
+    } else {
+        TCGv tmp = tcg_temp_new();
+        tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3);
+        tcg_gen_neg_i64(tmp, tmp);
+        tcg_gen_andi_i64(tmp, tmp, 0x3f);
+        tcg_gen_shl_i64(vc, va, tmp);
+        tcg_temp_free(tmp);
     }
+    gen_zapnoti(vc, vc, byte_mask);
 }
 
 /* EXTBL, EXTWL, EXTLL, EXTQL */
-static void gen_ext_l(int ra, int rb, int rc, int islit,
+static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else {
-        if (islit) {
-            tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], (lit & 7) * 8);
-        } else {
-            TCGv tmp = tcg_temp_new();
-            tcg_gen_andi_i64(tmp, cpu_ir[rb], 7);
-            tcg_gen_shli_i64(tmp, tmp, 3);
-            tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], tmp);
-            tcg_temp_free(tmp);
-        }
-        gen_zapnoti(cpu_ir[rc], cpu_ir[rc], byte_mask);
+    if (islit) {
+        tcg_gen_shri_i64(vc, va, (lit & 7) * 8);
+    } else {
+        TCGv tmp = tcg_temp_new();
+        tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7);
+        tcg_gen_shli_i64(tmp, tmp, 3);
+        tcg_gen_shr_i64(vc, va, tmp);
+        tcg_temp_free(tmp);
     }
+    gen_zapnoti(vc, vc, byte_mask);
 }
 
 /* INSWH, INSLH, INSQH */
-static void gen_ins_h(int ra, int rb, int rc, int islit,
+static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31) || (islit && (lit & 7) == 0))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else {
-        TCGv tmp = tcg_temp_new();
+    TCGv tmp = tcg_temp_new();
 
-        /* The instruction description has us left-shift the byte mask
-           and extract bits <15:8> and apply that zap at the end.  This
-           is equivalent to simply performing the zap first and shifting
-           afterward.  */
-        gen_zapnoti (tmp, cpu_ir[ra], byte_mask);
+    /* The instruction description has us left-shift the byte mask and extract
+       bits <15:8> and apply that zap at the end.  This is equivalent to simply
+       performing the zap first and shifting afterward.  */
+    gen_zapnoti(tmp, va, byte_mask);
 
-        if (islit) {
-            /* Note that we have handled the lit==0 case above.  */
-            tcg_gen_shri_i64 (cpu_ir[rc], tmp, 64 - (lit & 7) * 8);
+    if (islit) {
+        lit &= 7;
+        if (unlikely(lit == 0)) {
+            tcg_gen_movi_i64(vc, 0);
         } else {
-            TCGv shift = tcg_temp_new();
-
-            /* If (B & 7) == 0, we need to shift by 64 and leave a zero.
-               Do this portably by splitting the shift into two parts:
-               shift_count-1 and 1.  Arrange for the -1 by using
-               ones-complement instead of twos-complement in the negation:
-               ~((B & 7) * 8) & 63.  */
-
-            tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
-            tcg_gen_shli_i64(shift, shift, 3);
-            tcg_gen_not_i64(shift, shift);
-            tcg_gen_andi_i64(shift, shift, 0x3f);
-
-            tcg_gen_shr_i64(cpu_ir[rc], tmp, shift);
-            tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[rc], 1);
-            tcg_temp_free(shift);
+            tcg_gen_shri_i64(vc, tmp, 64 - lit * 8);
         }
-        tcg_temp_free(tmp);
+    } else {
+        TCGv shift = tcg_temp_new();
+
+        /* If (B & 7) == 0, we need to shift by 64 and leave a zero.  Do this
+           portably by splitting the shift into two parts: shift_count-1 and 1.
+           Arrange for the -1 by using ones-complement instead of
+           twos-complement in the negation: ~(B * 8) & 63.  */
+
+        tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
+        tcg_gen_not_i64(shift, shift);
+        tcg_gen_andi_i64(shift, shift, 0x3f);
+
+        tcg_gen_shr_i64(vc, tmp, shift);
+        tcg_gen_shri_i64(vc, vc, 1);
+        tcg_temp_free(shift);
     }
+    tcg_temp_free(tmp);
 }
 
 /* INSBL, INSWL, INSLL, INSQL */
-static void gen_ins_l(int ra, int rb, int rc, int islit,
+static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else {
-        TCGv tmp = tcg_temp_new();
+    TCGv tmp = tcg_temp_new();
 
-        /* The instruction description has us left-shift the byte mask
-           the same number of byte slots as the data and apply the zap
-           at the end.  This is equivalent to simply performing the zap
-           first and shifting afterward.  */
-        gen_zapnoti (tmp, cpu_ir[ra], byte_mask);
+    /* The instruction description has us left-shift the byte mask
+       the same number of byte slots as the data and apply the zap
+       at the end.  This is equivalent to simply performing the zap
+       first and shifting afterward.  */
+    gen_zapnoti(tmp, va, byte_mask);
 
-        if (islit) {
-            tcg_gen_shli_i64(cpu_ir[rc], tmp, (lit & 7) * 8);
-        } else {
-            TCGv shift = tcg_temp_new();
-            tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
-            tcg_gen_shli_i64(shift, shift, 3);
-            tcg_gen_shl_i64(cpu_ir[rc], tmp, shift);
-            tcg_temp_free(shift);
-        }
-        tcg_temp_free(tmp);
+    if (islit) {
+        tcg_gen_shli_i64(vc, tmp, (lit & 7) * 8);
+    } else {
+        TCGv shift = tcg_temp_new();
+        tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
+        tcg_gen_shli_i64(shift, shift, 3);
+        tcg_gen_shl_i64(vc, tmp, shift);
+        tcg_temp_free(shift);
     }
+    tcg_temp_free(tmp);
 }
 
 /* MSKWH, MSKLH, MSKQH */
-static void gen_msk_h(int ra, int rb, int rc, int islit,
+static void gen_msk_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else if (islit) {
-        gen_zapnoti (cpu_ir[rc], cpu_ir[ra], ~((byte_mask << (lit & 7)) >> 8));
+    if (islit) {
+        gen_zapnoti(vc, va, ~((byte_mask << (lit & 7)) >> 8));
     } else {
         TCGv shift = tcg_temp_new();
         TCGv mask = tcg_temp_new();
@@ -1321,17 +1220,16 @@ static void gen_msk_h(int ra, int rb, int rc, int islit,
            shift of 64 bits in order to generate a zero.  This is done by
            splitting the shift into two parts, the variable shift - 1
            followed by a constant 1 shift.  The code we expand below is
-           equivalent to ~((B & 7) * 8) & 63.  */
+           equivalent to ~(B * 8) & 63.  */
 
-        tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
-        tcg_gen_shli_i64(shift, shift, 3);
+        tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
         tcg_gen_not_i64(shift, shift);
         tcg_gen_andi_i64(shift, shift, 0x3f);
         tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
         tcg_gen_shr_i64(mask, mask, shift);
         tcg_gen_shri_i64(mask, mask, 1);
 
-        tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], mask);
+        tcg_gen_andc_i64(vc, va, mask);
 
         tcg_temp_free(mask);
         tcg_temp_free(shift);
@@ -1339,105 +1237,27 @@ static void gen_msk_h(int ra, int rb, int rc, int islit,
 }
 
 /* MSKBL, MSKWL, MSKLL, MSKQL */
-static void gen_msk_l(int ra, int rb, int rc, int islit,
+static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else if (islit) {
-        gen_zapnoti (cpu_ir[rc], cpu_ir[ra], ~(byte_mask << (lit & 7)));
+    if (islit) {
+        gen_zapnoti(vc, va, ~(byte_mask << (lit & 7)));
     } else {
         TCGv shift = tcg_temp_new();
         TCGv mask = tcg_temp_new();
 
-        tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
+        tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
         tcg_gen_shli_i64(shift, shift, 3);
-        tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
+        tcg_gen_movi_i64(mask, zapnot_mask(byte_mask));
         tcg_gen_shl_i64(mask, mask, shift);
 
-        tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], mask);
+        tcg_gen_andc_i64(vc, va, mask);
 
         tcg_temp_free(mask);
         tcg_temp_free(shift);
     }
 }
 
-/* Code to call arith3 helpers */
-#define ARITH3(name)                                                  \
-static inline void glue(gen_, name)(int ra, int rb, int rc, int islit,\
-                                    uint8_t lit)                      \
-{                                                                     \
-    if (unlikely(rc == 31))                                           \
-        return;                                                       \
-                                                                      \
-    if (ra != 31) {                                                   \
-        if (islit) {                                                  \
-            TCGv tmp = tcg_const_i64(lit);                            \
-            gen_helper_ ## name(cpu_ir[rc], cpu_ir[ra], tmp);         \
-            tcg_temp_free(tmp);                                       \
-        } else                                                        \
-            gen_helper_ ## name (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); \
-    } else {                                                          \
-        TCGv tmp1 = tcg_const_i64(0);                                 \
-        if (islit) {                                                  \
-            TCGv tmp2 = tcg_const_i64(lit);                           \
-            gen_helper_ ## name (cpu_ir[rc], tmp1, tmp2);             \
-            tcg_temp_free(tmp2);                                      \
-        } else                                                        \
-            gen_helper_ ## name (cpu_ir[rc], tmp1, cpu_ir[rb]);       \
-        tcg_temp_free(tmp1);                                          \
-    }                                                                 \
-}
-ARITH3(cmpbge)
-ARITH3(minub8)
-ARITH3(minsb8)
-ARITH3(minuw4)
-ARITH3(minsw4)
-ARITH3(maxub8)
-ARITH3(maxsb8)
-ARITH3(maxuw4)
-ARITH3(maxsw4)
-ARITH3(perr)
-
-/* Code to call arith3 helpers */
-#define ARITH3_EX(name)                                                 \
-    static inline void glue(gen_, name)(int ra, int rb, int rc,         \
-                                        int islit, uint8_t lit)         \
-    {                                                                   \
-        if (unlikely(rc == 31)) {                                       \
-            return;                                                     \
-        }                                                               \
-        if (ra != 31) {                                                 \
-            if (islit) {                                                \
-                TCGv tmp = tcg_const_i64(lit);                          \
-                gen_helper_ ## name(cpu_ir[rc], cpu_env,                \
-                                    cpu_ir[ra], tmp);                   \
-                tcg_temp_free(tmp);                                     \
-            } else {                                                    \
-                gen_helper_ ## name(cpu_ir[rc], cpu_env,                \
-                                    cpu_ir[ra], cpu_ir[rb]);            \
-            }                                                           \
-        } else {                                                        \
-            TCGv tmp1 = tcg_const_i64(0);                               \
-            if (islit) {                                                \
-                TCGv tmp2 = tcg_const_i64(lit);                         \
-                gen_helper_ ## name(cpu_ir[rc], cpu_env, tmp1, tmp2);   \
-                tcg_temp_free(tmp2);                                    \
-            } else {                                                    \
-                gen_helper_ ## name(cpu_ir[rc], cpu_env, tmp1, cpu_ir[rb]); \
-            }                                                           \
-            tcg_temp_free(tmp1);                                        \
-        }                                                               \
-    }
-ARITH3_EX(addlv)
-ARITH3_EX(sublv)
-ARITH3_EX(addqv)
-ARITH3_EX(subqv)
-ARITH3_EX(mullv)
-ARITH3_EX(mulqv)
-
 #define MVIOP2(name)                                    \
 static inline void glue(gen_, name)(int rb, int rc)     \
 {                                                       \
@@ -1453,36 +1273,6 @@ MVIOP2(pkwb)
 MVIOP2(unpkbl)
 MVIOP2(unpkbw)
 
-static void gen_cmp(TCGCond cond, int ra, int rb, int rc,
-                    int islit, uint8_t lit)
-{
-    TCGv va, vb;
-
-    if (unlikely(rc == 31)) {
-        return;
-    }
-
-    if (ra == 31) {
-        va = tcg_const_i64(0);
-    } else {
-        va = cpu_ir[ra];
-    }
-    if (islit) {
-        vb = tcg_const_i64(lit);
-    } else {
-        vb = cpu_ir[rb];
-    }
-
-    tcg_gen_setcond_i64(cond, cpu_ir[rc], va, vb);
-
-    if (ra == 31) {
-        tcg_temp_free(va);
-    }
-    if (islit) {
-        tcg_temp_free(vb);
-    }
-}
-
 static void gen_rx(int ra, int set)
 {
     TCGv_i32 tmp;
@@ -1517,7 +1307,8 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
             tcg_gen_mov_i64(cpu_unique, cpu_ir[IR_A0]);
             break;
         default:
-            return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0xbf);
+            palcode &= 0xbf;
+            goto do_call_pal;
         }
         return NO_EXIT;
     }
@@ -1582,13 +1373,42 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
             break;
 
         default:
-            return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0x3f);
+            palcode &= 0x3f;
+            goto do_call_pal;
         }
         return NO_EXIT;
     }
 #endif
-
     return gen_invalid(ctx);
+
+ do_call_pal:
+#ifdef CONFIG_USER_ONLY
+    return gen_excp(ctx, EXCP_CALL_PAL, palcode);
+#else
+    {
+        TCGv pc = tcg_const_i64(ctx->pc);
+        TCGv entry = tcg_const_i64(palcode & 0x80
+                                   ? 0x2000 + (palcode - 0x80) * 64
+                                   : 0x1000 + palcode * 64);
+
+        gen_helper_call_pal(cpu_env, pc, entry);
+
+        tcg_temp_free(entry);
+        tcg_temp_free(pc);
+
+        /* Since the destination is running in PALmode, we don't really
+           need the page permissions check.  We'll see the existence of
+           the page when we create the TB, and we'll flush all TBs if
+           we change the PAL base register.  */
+        if (!ctx->singlestep_enabled && !(ctx->tb->cflags & CF_LAST_IO)) {
+            tcg_gen_goto_tb(0);
+            tcg_gen_exit_tb((uintptr_t)ctx->tb);
+            return EXIT_GOTO_TB;
+        }
+
+        return EXIT_PC_UPDATED;
+    }
+#endif
 }
 
 #ifndef CONFIG_USER_ONLY
@@ -1704,6 +1524,15 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
         gen_helper_set_alarm(cpu_env, tmp);
         break;
 
+    case 7:
+        /* PALBR */
+        tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUAlphaState, palbr));
+        /* Changing the PAL base register implies un-chaining all of the TBs
+           that ended with a CALL_PAL.  Since the base register usually only
+           changes during boot, flushing everything works well.  */
+        gen_helper_tb_flush(cpu_env);
+        return EXIT_PC_STALE;
+
     default:
         /* The basic registers are data only, and unknown registers
            are read-zero, write-ignore.  */
@@ -1728,6 +1557,20 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
 }
 #endif /* !USER_ONLY*/
 
+#define REQUIRE_TB_FLAG(FLAG)                   \
+    do {                                        \
+        if ((ctx->tb->flags & (FLAG)) == 0) {   \
+            goto invalid_opc;                   \
+        }                                       \
+    } while (0)
+
+#define REQUIRE_REG_31(WHICH)                   \
+    do {                                        \
+        if (WHICH != 31) {                      \
+            goto invalid_opc;                   \
+        }                                       \
+    } while (0)
+
 static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
 {
     uint32_t palcode;
@@ -1736,8 +1579,10 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
     int32_t disp12;
 #endif
     uint16_t fn11;
-    uint8_t opc, ra, rb, rc, fpfn, fn7, islit, real_islit;
-    uint8_t lit;
+    uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
+    bool islit;
+    TCGv va, vb, vc, tmp;
+    TCGv_i32 t32;
     ExitStatus ret;
 
     /* Decode all instruction fields */
@@ -1745,12 +1590,13 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
     ra = (insn >> 21) & 0x1F;
     rb = (insn >> 16) & 0x1F;
     rc = insn & 0x1F;
-    real_islit = islit = (insn >> 12) & 1;
+    islit = (insn >> 12) & 1;
     if (rb == 31 && !islit) {
         islit = 1;
         lit = 0;
-    } else
+    } else {
         lit = (insn >> 13) & 0xFF;
+    }
     palcode = insn & 0x03FFFFFF;
     disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
     disp16 = (int16_t)(insn & 0x0000FFFF);
@@ -1790,837 +1636,627 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
     case 0x07:
         /* OPC07 */
         goto invalid_opc;
-    case 0x08:
-        /* LDA */
-        if (likely(ra != 31)) {
-            if (rb != 31)
-                tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16);
-            else
-                tcg_gen_movi_i64(cpu_ir[ra], disp16);
-        }
-        break;
+
     case 0x09:
         /* LDAH */
-        if (likely(ra != 31)) {
-            if (rb != 31)
-                tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16 << 16);
-            else
-                tcg_gen_movi_i64(cpu_ir[ra], disp16 << 16);
+        disp16 = (uint32_t)disp16 << 16;
+        /* fall through */
+    case 0x08:
+        /* LDA */
+        va = dest_gpr(ctx, ra);
+        /* It's worth special-casing immediate loads.  */
+        if (rb == 31) {
+            tcg_gen_movi_i64(va, disp16);
+        } else {
+            tcg_gen_addi_i64(va, load_gpr(ctx, rb), disp16);
         }
         break;
+
     case 0x0A:
         /* LDBU */
-        if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
-            gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
-            break;
-        }
-        goto invalid_opc;
+        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+        gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
+        break;
     case 0x0B:
         /* LDQ_U */
         gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
         break;
     case 0x0C:
         /* LDWU */
-        if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
-            gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
-            break;
-        }
-        goto invalid_opc;
+        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+        gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
+        break;
     case 0x0D:
         /* STW */
+        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
         gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
         break;
     case 0x0E:
         /* STB */
+        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
         gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
         break;
     case 0x0F:
         /* STQ_U */
         gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
         break;
+
     case 0x10:
+        vc = dest_gpr(ctx, rc);
+        vb = load_gpr_lit(ctx, rb, lit, islit);
+
+        if (ra == 31) {
+            if (fn7 == 0x00) {
+                /* Special case ADDL as SEXTL.  */
+                tcg_gen_ext32s_i64(vc, vb);
+                break;
+            }
+            if (fn7 == 0x29) {
+                /* Special case SUBQ as NEGQ.  */
+                tcg_gen_neg_i64(vc, vb);
+                break;
+            }
+        }
+
+        va = load_gpr(ctx, ra);
         switch (fn7) {
         case 0x00:
             /* ADDL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit) {
-                        tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                    } else {
-                        tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                    }
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_add_i64(vc, va, vb);
+            tcg_gen_ext32s_i64(vc, vc);
             break;
         case 0x02:
             /* S4ADDL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
-                    if (islit)
-                        tcg_gen_addi_i64(tmp, tmp, lit);
-                    else
-                        tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 2);
+            tcg_gen_add_i64(tmp, tmp, vb);
+            tcg_gen_ext32s_i64(vc, tmp);
+            tcg_temp_free(tmp);
             break;
         case 0x09:
             /* SUBL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else {
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                }
-            }
+            tcg_gen_sub_i64(vc, va, vb);
+            tcg_gen_ext32s_i64(vc, vc);
             break;
         case 0x0B:
             /* S4SUBL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
-                    if (islit)
-                        tcg_gen_subi_i64(tmp, tmp, lit);
-                    else
-                        tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else {
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                    }
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 2);
+            tcg_gen_sub_i64(tmp, tmp, vb);
+            tcg_gen_ext32s_i64(vc, tmp);
+            tcg_temp_free(tmp);
             break;
         case 0x0F:
             /* CMPBGE */
-            gen_cmpbge(ra, rb, rc, islit, lit);
+            gen_helper_cmpbge(vc, va, vb);
             break;
         case 0x12:
             /* S8ADDL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
-                    if (islit)
-                        tcg_gen_addi_i64(tmp, tmp, lit);
-                    else
-                        tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 3);
+            tcg_gen_add_i64(tmp, tmp, vb);
+            tcg_gen_ext32s_i64(vc, tmp);
+            tcg_temp_free(tmp);
             break;
         case 0x1B:
             /* S8SUBL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
-                    if (islit)
-                        tcg_gen_subi_i64(tmp, tmp, lit);
-                    else
-                       tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                    }
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 3);
+            tcg_gen_sub_i64(tmp, tmp, vb);
+            tcg_gen_ext32s_i64(vc, tmp);
+            tcg_temp_free(tmp);
             break;
         case 0x1D:
             /* CMPULT */
-            gen_cmp(TCG_COND_LTU, ra, rb, rc, islit, lit);
+            tcg_gen_setcond_i64(TCG_COND_LTU, vc, va, vb);
             break;
         case 0x20:
             /* ADDQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_add_i64(vc, va, vb);
             break;
         case 0x22:
             /* S4ADDQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
-                    if (islit)
-                        tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
-                    else
-                        tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 2);
+            tcg_gen_add_i64(vc, tmp, vb);
+            tcg_temp_free(tmp);
             break;
         case 0x29:
             /* SUBQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_sub_i64(vc, va, vb);
             break;
         case 0x2B:
             /* S4SUBQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
-                    if (islit)
-                        tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
-                    else
-                        tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 2);
+            tcg_gen_sub_i64(vc, tmp, vb);
+            tcg_temp_free(tmp);
             break;
         case 0x2D:
             /* CMPEQ */
-            gen_cmp(TCG_COND_EQ, ra, rb, rc, islit, lit);
+            tcg_gen_setcond_i64(TCG_COND_EQ, vc, va, vb);
             break;
         case 0x32:
             /* S8ADDQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
-                    if (islit)
-                        tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
-                    else
-                        tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 3);
+            tcg_gen_add_i64(vc, tmp, vb);
+            tcg_temp_free(tmp);
             break;
         case 0x3B:
             /* S8SUBQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
-                    if (islit)
-                        tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
-                    else
-                        tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 3);
+            tcg_gen_sub_i64(vc, tmp, vb);
+            tcg_temp_free(tmp);
             break;
         case 0x3D:
             /* CMPULE */
-            gen_cmp(TCG_COND_LEU, ra, rb, rc, islit, lit);
+            tcg_gen_setcond_i64(TCG_COND_LEU, vc, va, vb);
             break;
         case 0x40:
             /* ADDL/V */
-            gen_addlv(ra, rb, rc, islit, lit);
+            gen_helper_addlv(vc, cpu_env, va, vb);
             break;
         case 0x49:
             /* SUBL/V */
-            gen_sublv(ra, rb, rc, islit, lit);
+            gen_helper_sublv(vc, cpu_env, va, vb);
             break;
         case 0x4D:
             /* CMPLT */
-            gen_cmp(TCG_COND_LT, ra, rb, rc, islit, lit);
+            tcg_gen_setcond_i64(TCG_COND_LT, vc, va, vb);
             break;
         case 0x60:
             /* ADDQ/V */
-            gen_addqv(ra, rb, rc, islit, lit);
+            gen_helper_addqv(vc, cpu_env, va, vb);
             break;
         case 0x69:
             /* SUBQ/V */
-            gen_subqv(ra, rb, rc, islit, lit);
+            gen_helper_subqv(vc, cpu_env, va, vb);
             break;
         case 0x6D:
             /* CMPLE */
-            gen_cmp(TCG_COND_LE, ra, rb, rc, islit, lit);
+            tcg_gen_setcond_i64(TCG_COND_LE, vc, va, vb);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x11:
+        if (fn7 == 0x20) {
+            if (rc == 31) {
+                /* Special case BIS as NOP.  */
+                break;
+            }
+            if (ra == 31) {
+                /* Special case BIS as MOV.  */
+                vc = dest_gpr(ctx, rc);
+                if (islit) {
+                    tcg_gen_movi_i64(vc, lit);
+                } else {
+                    tcg_gen_mov_i64(vc, load_gpr(ctx, rb));
+                }
+                break;
+            }
+        }
+
+        vc = dest_gpr(ctx, rc);
+        vb = load_gpr_lit(ctx, rb, lit, islit);
+
+        if (fn7 == 0x28 && ra == 31) {
+            /* Special case ORNOT as NOT.  */
+            tcg_gen_not_i64(vc, vb);
+            break;
+        }
+
+        va = load_gpr(ctx, ra);
         switch (fn7) {
         case 0x00:
             /* AND */
-            if (likely(rc != 31)) {
-                if (ra == 31)
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-                else if (islit)
-                    tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                else
-                    tcg_gen_and_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-            }
+            tcg_gen_and_i64(vc, va, vb);
             break;
         case 0x08:
             /* BIC */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
-                    else
-                        tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-            }
+            tcg_gen_andc_i64(vc, va, vb);
             break;
         case 0x14:
             /* CMOVLBS */
-            gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 1);
+            tmp = tcg_temp_new();
+            tcg_gen_andi_i64(tmp, va, 1);
+            tcg_gen_movcond_i64(TCG_COND_NE, vc, tmp, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
+            tcg_temp_free(tmp);
             break;
         case 0x16:
             /* CMOVLBC */
-            gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
+            tmp = tcg_temp_new();
+            tcg_gen_andi_i64(tmp, va, 1);
+            tcg_gen_movcond_i64(TCG_COND_EQ, vc, tmp, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
+            tcg_temp_free(tmp);
             break;
         case 0x20:
             /* BIS */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_or_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_or_i64(vc, va, vb);
             break;
         case 0x24:
             /* CMOVEQ */
-            gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_EQ, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x26:
             /* CMOVNE */
-            gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_NE, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x28:
             /* ORNOT */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
-                    else
-                        tcg_gen_orc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], ~lit);
-                    else
-                        tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_orc_i64(vc, va, vb);
             break;
         case 0x40:
             /* XOR */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_xor_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_xor_i64(vc, va, vb);
             break;
         case 0x44:
             /* CMOVLT */
-            gen_cmov(TCG_COND_LT, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_LT, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x46:
             /* CMOVGE */
-            gen_cmov(TCG_COND_GE, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_GE, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x48:
             /* EQV */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
-                    else
-                        tcg_gen_eqv_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], ~lit);
-                    else
-                        tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_eqv_i64(vc, va, vb);
             break;
         case 0x61:
             /* AMASK */
-            if (likely(rc != 31)) {
+            REQUIRE_REG_31(ra);
+            {
                 uint64_t amask = ctx->tb->flags >> TB_FLAGS_AMASK_SHIFT;
-
-                if (islit) {
-                    tcg_gen_movi_i64(cpu_ir[rc], lit & ~amask);
-                } else {
-                    tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[rb], ~amask);
-                }
+                tcg_gen_andi_i64(vc, vb, ~amask);
             }
             break;
         case 0x64:
             /* CMOVLE */
-            gen_cmov(TCG_COND_LE, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_LE, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x66:
             /* CMOVGT */
-            gen_cmov(TCG_COND_GT, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_GT, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x6C:
             /* IMPLVER */
-            if (rc != 31)
-                tcg_gen_movi_i64(cpu_ir[rc], ctx->env->implver);
+            REQUIRE_REG_31(ra);
+            tcg_gen_movi_i64(vc, ctx->implver);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x12:
+        vc = dest_gpr(ctx, rc);
+        va = load_gpr(ctx, ra);
         switch (fn7) {
         case 0x02:
             /* MSKBL */
-            gen_msk_l(ra, rb, rc, islit, lit, 0x01);
+            gen_msk_l(ctx, vc, va, rb, islit, lit, 0x01);
             break;
         case 0x06:
             /* EXTBL */
-            gen_ext_l(ra, rb, rc, islit, lit, 0x01);
+            gen_ext_l(ctx, vc, va, rb, islit, lit, 0x01);
             break;
         case 0x0B:
             /* INSBL */
-            gen_ins_l(ra, rb, rc, islit, lit, 0x01);
+            gen_ins_l(ctx, vc, va, rb, islit, lit, 0x01);
             break;
         case 0x12:
             /* MSKWL */
-            gen_msk_l(ra, rb, rc, islit, lit, 0x03);
+            gen_msk_l(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x16:
             /* EXTWL */
-            gen_ext_l(ra, rb, rc, islit, lit, 0x03);
+            gen_ext_l(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x1B:
             /* INSWL */
-            gen_ins_l(ra, rb, rc, islit, lit, 0x03);
+            gen_ins_l(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x22:
             /* MSKLL */
-            gen_msk_l(ra, rb, rc, islit, lit, 0x0f);
+            gen_msk_l(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x26:
             /* EXTLL */
-            gen_ext_l(ra, rb, rc, islit, lit, 0x0f);
+            gen_ext_l(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x2B:
             /* INSLL */
-            gen_ins_l(ra, rb, rc, islit, lit, 0x0f);
+            gen_ins_l(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x30:
             /* ZAP */
-            gen_zap(ra, rb, rc, islit, lit);
+            if (islit) {
+                gen_zapnoti(vc, va, ~lit);
+            } else {
+                gen_helper_zap(vc, va, load_gpr(ctx, rb));
+            }
             break;
         case 0x31:
             /* ZAPNOT */
-            gen_zapnot(ra, rb, rc, islit, lit);
+            if (islit) {
+                gen_zapnoti(vc, va, lit);
+            } else {
+                gen_helper_zapnot(vc, va, load_gpr(ctx, rb));
+            }
             break;
         case 0x32:
             /* MSKQL */
-            gen_msk_l(ra, rb, rc, islit, lit, 0xff);
+            gen_msk_l(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         case 0x34:
             /* SRL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
-                    else {
-                        TCGv shift = tcg_temp_new();
-                        tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
-                        tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], shift);
-                        tcg_temp_free(shift);
-                    }
-                } else
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
+            if (islit) {
+                tcg_gen_shri_i64(vc, va, lit & 0x3f);
+            } else {
+                tmp = tcg_temp_new();
+                vb = load_gpr(ctx, rb);
+                tcg_gen_andi_i64(tmp, vb, 0x3f);
+                tcg_gen_shr_i64(vc, va, tmp);
+                tcg_temp_free(tmp);
             }
             break;
         case 0x36:
             /* EXTQL */
-            gen_ext_l(ra, rb, rc, islit, lit, 0xff);
+            gen_ext_l(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         case 0x39:
             /* SLL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
-                    else {
-                        TCGv shift = tcg_temp_new();
-                        tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
-                        tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], shift);
-                        tcg_temp_free(shift);
-                    }
-                } else
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
+            if (islit) {
+                tcg_gen_shli_i64(vc, va, lit & 0x3f);
+            } else {
+                tmp = tcg_temp_new();
+                vb = load_gpr(ctx, rb);
+                tcg_gen_andi_i64(tmp, vb, 0x3f);
+                tcg_gen_shl_i64(vc, va, tmp);
+                tcg_temp_free(tmp);
             }
             break;
         case 0x3B:
             /* INSQL */
-            gen_ins_l(ra, rb, rc, islit, lit, 0xff);
+            gen_ins_l(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         case 0x3C:
             /* SRA */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_sari_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
-                    else {
-                        TCGv shift = tcg_temp_new();
-                        tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
-                        tcg_gen_sar_i64(cpu_ir[rc], cpu_ir[ra], shift);
-                        tcg_temp_free(shift);
-                    }
-                } else
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
+            if (islit) {
+                tcg_gen_sari_i64(vc, va, lit & 0x3f);
+            } else {
+                tmp = tcg_temp_new();
+                vb = load_gpr(ctx, rb);
+                tcg_gen_andi_i64(tmp, vb, 0x3f);
+                tcg_gen_sar_i64(vc, va, tmp);
+                tcg_temp_free(tmp);
             }
             break;
         case 0x52:
             /* MSKWH */
-            gen_msk_h(ra, rb, rc, islit, lit, 0x03);
+            gen_msk_h(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x57:
             /* INSWH */
-            gen_ins_h(ra, rb, rc, islit, lit, 0x03);
+            gen_ins_h(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x5A:
             /* EXTWH */
-            gen_ext_h(ra, rb, rc, islit, lit, 0x03);
+            gen_ext_h(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x62:
             /* MSKLH */
-            gen_msk_h(ra, rb, rc, islit, lit, 0x0f);
+            gen_msk_h(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x67:
             /* INSLH */
-            gen_ins_h(ra, rb, rc, islit, lit, 0x0f);
+            gen_ins_h(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x6A:
             /* EXTLH */
-            gen_ext_h(ra, rb, rc, islit, lit, 0x0f);
+            gen_ext_h(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x72:
             /* MSKQH */
-            gen_msk_h(ra, rb, rc, islit, lit, 0xff);
+            gen_msk_h(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         case 0x77:
             /* INSQH */
-            gen_ins_h(ra, rb, rc, islit, lit, 0xff);
+            gen_ins_h(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         case 0x7A:
             /* EXTQH */
-            gen_ext_h(ra, rb, rc, islit, lit, 0xff);
+            gen_ext_h(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x13:
+        vc = dest_gpr(ctx, rc);
+        vb = load_gpr_lit(ctx, rb, lit, islit);
+        va = load_gpr(ctx, ra);
         switch (fn7) {
         case 0x00:
             /* MULL */
-            if (likely(rc != 31)) {
-                if (ra == 31)
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-                else {
-                    if (islit)
-                        tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                }
-            }
+            tcg_gen_mul_i64(vc, va, vb);
+            tcg_gen_ext32s_i64(vc, vc);
             break;
         case 0x20:
             /* MULQ */
-            if (likely(rc != 31)) {
-                if (ra == 31)
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-                else if (islit)
-                    tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                else
-                    tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-            }
+            tcg_gen_mul_i64(vc, va, vb);
             break;
         case 0x30:
             /* UMULH */
-            {
-                TCGv low;
-                if (unlikely(rc == 31)){
-                    break;
-                }
-                if (ra == 31) {
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-                    break;
-                }
-                low = tcg_temp_new();
-                if (islit) {
-                    tcg_gen_movi_tl(low, lit);
-                    tcg_gen_mulu2_i64(low, cpu_ir[rc], cpu_ir[ra], low);
-                } else {
-                    tcg_gen_mulu2_i64(low, cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                }
-                tcg_temp_free(low);
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_mulu2_i64(tmp, vc, va, vb);
+            tcg_temp_free(tmp);
             break;
         case 0x40:
             /* MULL/V */
-            gen_mullv(ra, rb, rc, islit, lit);
+            gen_helper_mullv(vc, cpu_env, va, vb);
             break;
         case 0x60:
             /* MULQ/V */
-            gen_mulqv(ra, rb, rc, islit, lit);
+            gen_helper_mulqv(vc, cpu_env, va, vb);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x14:
+        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
+        vc = dest_fpr(ctx, rc);
         switch (fpfn) { /* fn11 & 0x3F */
         case 0x04:
             /* ITOFS */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
-                goto invalid_opc;
-            }
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv_i32 tmp = tcg_temp_new_i32();
-                    tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
-                    gen_helper_memory_to_s(cpu_fir[rc], tmp);
-                    tcg_temp_free_i32(tmp);
-                } else
-                    tcg_gen_movi_i64(cpu_fir[rc], 0);
-            }
+            REQUIRE_REG_31(rb);
+            t32 = tcg_temp_new_i32();
+            va = load_gpr(ctx, ra);
+            tcg_gen_trunc_i64_i32(t32, va);
+            gen_helper_memory_to_s(vc, t32);
+            tcg_temp_free_i32(t32);
             break;
         case 0x0A:
             /* SQRTF */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
-                gen_fsqrtf(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_REG_31(ra);
+            vb = load_fpr(ctx, rb);
+            gen_helper_sqrtf(vc, cpu_env, vb);
+            break;
         case 0x0B:
             /* SQRTS */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
-                gen_fsqrts(ctx, rb, rc, fn11);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_REG_31(ra);
+            gen_fsqrts(ctx, rb, rc, fn11);
+            break;
         case 0x14:
             /* ITOFF */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
-                goto invalid_opc;
-            }
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv_i32 tmp = tcg_temp_new_i32();
-                    tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
-                    gen_helper_memory_to_f(cpu_fir[rc], tmp);
-                    tcg_temp_free_i32(tmp);
-                } else
-                    tcg_gen_movi_i64(cpu_fir[rc], 0);
-            }
+            REQUIRE_REG_31(rb);
+            t32 = tcg_temp_new_i32();
+            va = load_gpr(ctx, ra);
+            tcg_gen_trunc_i64_i32(t32, va);
+            gen_helper_memory_to_f(vc, t32);
+            tcg_temp_free_i32(t32);
             break;
         case 0x24:
             /* ITOFT */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
-                goto invalid_opc;
-            }
-            if (likely(rc != 31)) {
-                if (ra != 31)
-                    tcg_gen_mov_i64(cpu_fir[rc], cpu_ir[ra]);
-                else
-                    tcg_gen_movi_i64(cpu_fir[rc], 0);
-            }
+            REQUIRE_REG_31(rb);
+            va = load_gpr(ctx, ra);
+            tcg_gen_mov_i64(vc, va);
             break;
         case 0x2A:
             /* SQRTG */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
-                gen_fsqrtg(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_REG_31(ra);
+            vb = load_fpr(ctx, rb);
+            gen_helper_sqrtg(vc, cpu_env, vb);
+            break;
         case 0x02B:
             /* SQRTT */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
-                gen_fsqrtt(ctx, rb, rc, fn11);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_REG_31(ra);
+            gen_fsqrtt(ctx, rb, rc, fn11);
+            break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x15:
         /* VAX floating point */
         /* XXX: rounding mode and trap are ignored (!) */
+        vc = dest_fpr(ctx, rc);
+        vb = load_fpr(ctx, rb);
+        va = load_fpr(ctx, ra);
         switch (fpfn) { /* fn11 & 0x3F */
         case 0x00:
             /* ADDF */
-            gen_faddf(ra, rb, rc);
+            gen_helper_addf(vc, cpu_env, va, vb);
             break;
         case 0x01:
             /* SUBF */
-            gen_fsubf(ra, rb, rc);
+            gen_helper_subf(vc, cpu_env, va, vb);
             break;
         case 0x02:
             /* MULF */
-            gen_fmulf(ra, rb, rc);
+            gen_helper_mulf(vc, cpu_env, va, vb);
             break;
         case 0x03:
             /* DIVF */
-            gen_fdivf(ra, rb, rc);
+            gen_helper_divf(vc, cpu_env, va, vb);
             break;
         case 0x1E:
-            /* CVTDG */
-#if 0 // TODO
-            gen_fcvtdg(rb, rc);
-#else
+            /* CVTDG -- TODO */
+            REQUIRE_REG_31(ra);
             goto invalid_opc;
-#endif
-            break;
         case 0x20:
             /* ADDG */
-            gen_faddg(ra, rb, rc);
+            gen_helper_addg(vc, cpu_env, va, vb);
             break;
         case 0x21:
             /* SUBG */
-            gen_fsubg(ra, rb, rc);
+            gen_helper_subg(vc, cpu_env, va, vb);
             break;
         case 0x22:
             /* MULG */
-            gen_fmulg(ra, rb, rc);
+            gen_helper_mulg(vc, cpu_env, va, vb);
             break;
         case 0x23:
             /* DIVG */
-            gen_fdivg(ra, rb, rc);
+            gen_helper_divg(vc, cpu_env, va, vb);
             break;
         case 0x25:
             /* CMPGEQ */
-            gen_fcmpgeq(ra, rb, rc);
+            gen_helper_cmpgeq(vc, cpu_env, va, vb);
             break;
         case 0x26:
             /* CMPGLT */
-            gen_fcmpglt(ra, rb, rc);
+            gen_helper_cmpglt(vc, cpu_env, va, vb);
             break;
         case 0x27:
             /* CMPGLE */
-            gen_fcmpgle(ra, rb, rc);
+            gen_helper_cmpgle(vc, cpu_env, va, vb);
             break;
         case 0x2C:
             /* CVTGF */
-            gen_fcvtgf(rb, rc);
+            REQUIRE_REG_31(ra);
+            gen_helper_cvtgf(vc, cpu_env, vb);
             break;
         case 0x2D:
-            /* CVTGD */
-#if 0 // TODO
-            gen_fcvtgd(rb, rc);
-#else
+            /* CVTGD -- TODO */
+            REQUIRE_REG_31(ra);
             goto invalid_opc;
-#endif
-            break;
         case 0x2F:
             /* CVTGQ */
-            gen_fcvtgq(rb, rc);
+            REQUIRE_REG_31(ra);
+            gen_helper_cvtgq(vc, cpu_env, vb);
             break;
         case 0x3C:
             /* CVTQF */
-            gen_fcvtqf(rb, rc);
+            REQUIRE_REG_31(ra);
+            gen_helper_cvtqf(vc, cpu_env, vb);
             break;
         case 0x3E:
             /* CVTQG */
-            gen_fcvtqg(rb, rc);
+            REQUIRE_REG_31(ra);
+            gen_helper_cvtqg(vc, cpu_env, vb);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x16:
         /* IEEE floating-point */
         switch (fpfn) { /* fn11 & 0x3F */
@@ -2673,6 +2309,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             gen_fcmptle(ctx, ra, rb, rc, fn11);
             break;
         case 0x2C:
+            REQUIRE_REG_31(ra);
             if (fn11 == 0x2AC || fn11 == 0x6AC) {
                 /* CVTST */
                 gen_fcvtst(ctx, rb, rc, fn11);
@@ -2683,38 +2320,46 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             break;
         case 0x2F:
             /* CVTTQ */
+            REQUIRE_REG_31(ra);
             gen_fcvttq(ctx, rb, rc, fn11);
             break;
         case 0x3C:
             /* CVTQS */
+            REQUIRE_REG_31(ra);
             gen_fcvtqs(ctx, rb, rc, fn11);
             break;
         case 0x3E:
             /* CVTQT */
+            REQUIRE_REG_31(ra);
             gen_fcvtqt(ctx, rb, rc, fn11);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x17:
         switch (fn11) {
         case 0x010:
             /* CVTLQ */
+            REQUIRE_REG_31(ra);
             gen_fcvtlq(rb, rc);
             break;
         case 0x020:
-            if (likely(rc != 31)) {
-                if (ra == rb) {
-                    /* FMOV */
-                    if (ra == 31)
-                        tcg_gen_movi_i64(cpu_fir[rc], 0);
-                    else
-                        tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[ra]);
+            /* CPYS */
+            if (rc == 31) {
+                /* Special case CPYS as FNOP.  */
+            } else if (ra == rb) {
+                vc = dest_fpr(ctx, rc);
+                /* Special case CPYS as FMOV.  */
+                if (ra == 31) {
+                    tcg_gen_movi_i64(vc, 0);
                 } else {
-                    /* CPYS */
-                    gen_fcpys(ra, rb, rc);
+                    va = load_fpr(ctx, ra);
+                    tcg_gen_mov_i64(vc, va);
                 }
+            } else {
+                gen_fcpys(ra, rb, rc);
             }
             break;
         case 0x021:
@@ -2727,18 +2372,13 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             break;
         case 0x024:
             /* MT_FPCR */
-            if (likely(ra != 31))
-                gen_helper_store_fpcr(cpu_env, cpu_fir[ra]);
-            else {
-                TCGv tmp = tcg_const_i64(0);
-                gen_helper_store_fpcr(cpu_env, tmp);
-                tcg_temp_free(tmp);
-            }
+            va = load_fpr(ctx, ra);
+            gen_helper_store_fpcr(cpu_env, va);
             break;
         case 0x025:
             /* MF_FPCR */
-            if (likely(ra != 31))
-                gen_helper_load_fpcr(cpu_fir[ra], cpu_env);
+            va = dest_fpr(ctx, ra);
+            gen_helper_load_fpcr(va, cpu_env);
             break;
         case 0x02A:
             /* FCMOVEQ */
@@ -2766,12 +2406,14 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             break;
         case 0x030:
             /* CVTQL */
+            REQUIRE_REG_31(ra);
             gen_fcvtql(rb, rc);
             break;
         case 0x130:
             /* CVTQL/V */
         case 0x530:
             /* CVTQL/SV */
+            REQUIRE_REG_31(ra);
             /* ??? I'm pretty sure there's nothing that /sv needs to do that
                /v doesn't do.  The only thing I can think is that /sv is a
                valid instruction merely for completeness in the ISA.  */
@@ -2781,6 +2423,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             goto invalid_opc;
         }
         break;
+
     case 0x18:
         switch ((uint16_t)disp16) {
         case 0x0000:
@@ -2809,15 +2452,14 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             break;
         case 0xC000:
             /* RPCC */
-            if (ra != 31) {
-                if (use_icount) {
-                    gen_io_start();
-                    gen_helper_load_pcc(cpu_ir[ra], cpu_env);
-                    gen_io_end();
-                    ret = EXIT_PC_STALE;
-                } else {
-                    gen_helper_load_pcc(cpu_ir[ra], cpu_env);
-                }
+            va = dest_gpr(ctx, ra);
+            if (use_icount) {
+                gen_io_start();
+                gen_helper_load_pcc(va, cpu_env);
+                gen_io_end();
+                ret = EXIT_PC_STALE;
+            } else {
+                gen_helper_load_pcc(va, cpu_env);
             }
             break;
         case 0xE000:
@@ -2839,58 +2481,53 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             goto invalid_opc;
         }
         break;
+
     case 0x19:
         /* HW_MFPR (PALcode) */
 #ifndef CONFIG_USER_ONLY
-        if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            return gen_mfpr(ra, insn & 0xffff);
-        }
-#endif
+        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+        return gen_mfpr(ra, insn & 0xffff);
+#else
         goto invalid_opc;
+#endif
+
     case 0x1A:
         /* JMP, JSR, RET, JSR_COROUTINE.  These only differ by the branch
            prediction stack action, which of course we don't implement.  */
-        if (rb != 31) {
-            tcg_gen_andi_i64(cpu_pc, cpu_ir[rb], ~3);
-        } else {
-            tcg_gen_movi_i64(cpu_pc, 0);
-        }
+        vb = load_gpr(ctx, rb);
+        tcg_gen_andi_i64(cpu_pc, vb, ~3);
         if (ra != 31) {
             tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
         }
         ret = EXIT_PC_UPDATED;
         break;
+
     case 0x1B:
         /* HW_LD (PALcode) */
 #ifndef CONFIG_USER_ONLY
-        if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            TCGv addr;
-
-            if (ra == 31) {
-                break;
-            }
+        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+        {
+            TCGv addr = tcg_temp_new();
+            vb = load_gpr(ctx, rb);
+            va = dest_gpr(ctx, ra);
 
-            addr = tcg_temp_new();
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
-            else
-                tcg_gen_movi_i64(addr, disp12);
+            tcg_gen_addi_i64(addr, vb, disp12);
             switch ((insn >> 12) & 0xF) {
             case 0x0:
                 /* Longword physical access (hw_ldl/p) */
-                gen_helper_ldl_phys(cpu_ir[ra], addr);
+                gen_helper_ldl_phys(va, cpu_env, addr);
                 break;
             case 0x1:
                 /* Quadword physical access (hw_ldq/p) */
-                gen_helper_ldq_phys(cpu_ir[ra], addr);
+                gen_helper_ldq_phys(va, cpu_env, addr);
                 break;
             case 0x2:
                 /* Longword physical access with lock (hw_ldl_l/p) */
-                gen_helper_ldl_l_phys(cpu_ir[ra], cpu_env, addr);
+                gen_helper_ldl_l_phys(va, cpu_env, addr);
                 break;
             case 0x3:
                 /* Quadword physical access with lock (hw_ldq_l/p) */
-                gen_helper_ldq_l_phys(cpu_ir[ra], cpu_env, addr);
+                gen_helper_ldq_l_phys(va, cpu_env, addr);
                 break;
             case 0x4:
                 /* Longword virtual PTE fetch (hw_ldl/v) */
@@ -2913,11 +2550,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
                 goto invalid_opc;
             case 0xA:
                 /* Longword virtual access with protection check (hw_ldl/w) */
-                tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_KERNEL_IDX);
+                tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LESL);
                 break;
             case 0xB:
                 /* Quadword virtual access with protection check (hw_ldq/w) */
-                tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_KERNEL_IDX);
+                tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEQ);
                 break;
             case 0xC:
                 /* Longword virtual access with alt access mode (hw_ldl/a)*/
@@ -2928,282 +2565,213 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             case 0xE:
                 /* Longword virtual access with alternate access mode and
                    protection checks (hw_ldl/wa) */
-                tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_USER_IDX);
+                tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LESL);
                 break;
             case 0xF:
                 /* Quadword virtual access with alternate access mode and
                    protection checks (hw_ldq/wa) */
-                tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_USER_IDX);
+                tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEQ);
                 break;
             }
             tcg_temp_free(addr);
             break;
         }
-#endif
+#else
         goto invalid_opc;
+#endif
+
     case 0x1C:
+        vc = dest_gpr(ctx, rc);
+        if (fn7 == 0x70) {
+            /* FTOIT */
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
+            REQUIRE_REG_31(rb);
+            va = load_fpr(ctx, ra);
+            tcg_gen_mov_i64(vc, va);
+            break;
+        } else if (fn7 == 0x78) {
+            /* FTOIS */
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
+            REQUIRE_REG_31(rb);
+            t32 = tcg_temp_new_i32();
+            va = load_fpr(ctx, ra);
+            gen_helper_s_to_memory(t32, va);
+            tcg_gen_ext_i32_i64(vc, t32);
+            tcg_temp_free_i32(t32);
+            break;
+        }
+
+        vb = load_gpr_lit(ctx, rb, lit, islit);
         switch (fn7) {
         case 0x00:
             /* SEXTB */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_BWX) == 0) {
-                goto invalid_opc;
-            }
-            if (likely(rc != 31)) {
-                if (islit)
-                    tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int8_t)lit));
-                else
-                    tcg_gen_ext8s_i64(cpu_ir[rc], cpu_ir[rb]);
-            }
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+            REQUIRE_REG_31(ra);
+            tcg_gen_ext8s_i64(vc, vb);
             break;
         case 0x01:
             /* SEXTW */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
-                if (likely(rc != 31)) {
-                    if (islit) {
-                        tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int16_t)lit));
-                    } else {
-                        tcg_gen_ext16s_i64(cpu_ir[rc], cpu_ir[rb]);
-                    }
-                }
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+            REQUIRE_REG_31(ra);
+            tcg_gen_ext16s_i64(vc, vb);
+            break;
         case 0x30:
             /* CTPOP */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
-                if (likely(rc != 31)) {
-                    if (islit) {
-                        tcg_gen_movi_i64(cpu_ir[rc], ctpop64(lit));
-                    } else {
-                        gen_helper_ctpop(cpu_ir[rc], cpu_ir[rb]);
-                    }
-                }
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
+            REQUIRE_REG_31(ra);
+            gen_helper_ctpop(vc, vb);
+            break;
         case 0x31:
             /* PERR */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_perr(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_perr(vc, va, vb);
+            break;
         case 0x32:
             /* CTLZ */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
-                if (likely(rc != 31)) {
-                    if (islit) {
-                        tcg_gen_movi_i64(cpu_ir[rc], clz64(lit));
-                    } else {
-                        gen_helper_ctlz(cpu_ir[rc], cpu_ir[rb]);
-                    }
-                }
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
+            REQUIRE_REG_31(ra);
+            gen_helper_ctlz(vc, vb);
+            break;
         case 0x33:
             /* CTTZ */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
-                if (likely(rc != 31)) {
-                    if (islit) {
-                        tcg_gen_movi_i64(cpu_ir[rc], ctz64(lit));
-                    } else {
-                        gen_helper_cttz(cpu_ir[rc], cpu_ir[rb]);
-                    }
-                }
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
+            REQUIRE_REG_31(ra);
+            gen_helper_cttz(vc, vb);
+            break;
         case 0x34:
             /* UNPKBW */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                if (real_islit || ra != 31) {
-                    goto invalid_opc;
-                }
-                gen_unpkbw(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            REQUIRE_REG_31(ra);
+            gen_unpkbw(rb, rc);
+            break;
         case 0x35:
             /* UNPKBL */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                if (real_islit || ra != 31) {
-                    goto invalid_opc;
-                }
-                gen_unpkbl(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            REQUIRE_REG_31(ra);
+            gen_unpkbl(rb, rc);
+            break;
         case 0x36:
             /* PKWB */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                if (real_islit || ra != 31) {
-                    goto invalid_opc;
-                }
-                gen_pkwb(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            REQUIRE_REG_31(ra);
+            gen_pkwb(rb, rc);
+            break;
         case 0x37:
             /* PKLB */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                if (real_islit || ra != 31) {
-                    goto invalid_opc;
-                }
-                gen_pklb(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            REQUIRE_REG_31(ra);
+            gen_pklb(rb, rc);
+            break;
         case 0x38:
             /* MINSB8 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_minsb8(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_minsb8(vc, va, vb);
+            break;
         case 0x39:
             /* MINSW4 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_minsw4(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_minsw4(vc, va, vb);
+            break;
         case 0x3A:
             /* MINUB8 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_minub8(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_minub8(vc, va, vb);
+            break;
         case 0x3B:
             /* MINUW4 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_minuw4(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_minuw4(vc, va, vb);
+            break;
         case 0x3C:
             /* MAXUB8 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_maxub8(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_maxub8(vc, va, vb);
+            break;
         case 0x3D:
             /* MAXUW4 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_maxuw4(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_maxuw4(vc, va, vb);
+            break;
         case 0x3E:
             /* MAXSB8 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_maxsb8(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_maxsb8(vc, va, vb);
+            break;
         case 0x3F:
             /* MAXSW4 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_maxsw4(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
-        case 0x70:
-            /* FTOIT */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
-                goto invalid_opc;
-            }
-            if (likely(rc != 31)) {
-                if (ra != 31)
-                    tcg_gen_mov_i64(cpu_ir[rc], cpu_fir[ra]);
-                else
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-            }
-            break;
-        case 0x78:
-            /* FTOIS */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
-                goto invalid_opc;
-            }
-            if (rc != 31) {
-                TCGv_i32 tmp1 = tcg_temp_new_i32();
-                if (ra != 31)
-                    gen_helper_s_to_memory(tmp1, cpu_fir[ra]);
-                else {
-                    TCGv tmp2 = tcg_const_i64(0);
-                    gen_helper_s_to_memory(tmp1, tmp2);
-                    tcg_temp_free(tmp2);
-                }
-                tcg_gen_ext_i32_i64(cpu_ir[rc], tmp1);
-                tcg_temp_free_i32(tmp1);
-            }
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_maxsw4(vc, va, vb);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x1D:
         /* HW_MTPR (PALcode) */
 #ifndef CONFIG_USER_ONLY
-        if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            return gen_mtpr(ctx, rb, insn & 0xffff);
-        }
-#endif
+        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+        return gen_mtpr(ctx, rb, insn & 0xffff);
+#else
         goto invalid_opc;
+#endif
+
     case 0x1E:
         /* HW_RET (PALcode) */
 #ifndef CONFIG_USER_ONLY
-        if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            if (rb == 31) {
-                /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
-                   address from EXC_ADDR.  This turns out to be useful for our
-                   emulation PALcode, so continue to accept it.  */
-                TCGv tmp = tcg_temp_new();
-                tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
-                gen_helper_hw_ret(cpu_env, tmp);
-                tcg_temp_free(tmp);
-            } else {
-                gen_helper_hw_ret(cpu_env, cpu_ir[rb]);
-            }
-            ret = EXIT_PC_UPDATED;
-            break;
+        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+        if (rb == 31) {
+            /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
+               address from EXC_ADDR.  This turns out to be useful for our
+               emulation PALcode, so continue to accept it.  */
+            tmp = tcg_temp_new();
+            tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
+            gen_helper_hw_ret(cpu_env, tmp);
+            tcg_temp_free(tmp);
+        } else {
+            gen_helper_hw_ret(cpu_env, load_gpr(ctx, rb));
         }
-#endif
+        ret = EXIT_PC_UPDATED;
+        break;
+#else
         goto invalid_opc;
+#endif
+
     case 0x1F:
         /* HW_ST (PALcode) */
 #ifndef CONFIG_USER_ONLY
-        if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            TCGv addr, val;
-            addr = tcg_temp_new();
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
-            else
-                tcg_gen_movi_i64(addr, disp12);
-            if (ra != 31)
-                val = cpu_ir[ra];
-            else {
-                val = tcg_temp_new();
-                tcg_gen_movi_i64(val, 0);
-            }
+        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+        {
+            TCGv addr = tcg_temp_new();
+            va = load_gpr(ctx, ra);
+            vb = load_gpr(ctx, rb);
+
+            tcg_gen_addi_i64(addr, vb, disp12);
             switch ((insn >> 12) & 0xF) {
             case 0x0:
                 /* Longword physical access */
-                gen_helper_stl_phys(addr, val);
+                gen_helper_stl_phys(cpu_env, addr, va);
                 break;
             case 0x1:
                 /* Quadword physical access */
-                gen_helper_stq_phys(addr, val);
+                gen_helper_stq_phys(cpu_env, addr, va);
                 break;
             case 0x2:
                 /* Longword physical access with lock */
-                gen_helper_stl_c_phys(val, cpu_env, addr, val);
+                gen_helper_stl_c_phys(dest_gpr(ctx, ra), cpu_env, addr, va);
                 break;
             case 0x3:
                 /* Quadword physical access with lock */
-                gen_helper_stq_c_phys(val, cpu_env, addr, val);
+                gen_helper_stq_c_phys(dest_gpr(ctx, ra), cpu_env, addr, va);
                 break;
             case 0x4:
                 /* Longword virtual access */
@@ -3242,13 +2810,12 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
                 /* Invalid */
                 goto invalid_opc;
             }
-            if (ra == 31)
-                tcg_temp_free(val);
             tcg_temp_free(addr);
             break;
         }
-#endif
+#else
         goto invalid_opc;
+#endif
     case 0x20:
         /* LDF */
         gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
@@ -3383,9 +2950,11 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
                                                   TranslationBlock *tb,
                                                   bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUAlphaState *env = &cpu->env;
     DisasContext ctx, *ctxp = &ctx;
     target_ulong pc_start;
+    target_ulong pc_mask;
     uint32_t insn;
     uint16_t *gen_opc_end;
     CPUBreakpoint *bp;
@@ -3398,9 +2967,10 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
     gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     ctx.tb = tb;
-    ctx.env = env;
     ctx.pc = pc_start;
     ctx.mem_idx = cpu_mmu_index(env);
+    ctx.implver = env->implver;
+    ctx.singlestep_enabled = cs->singlestep_enabled;
 
     /* ??? Every TB begins with unset rounding mode, to be initialized on
        the first fp insn of the TB.  Alternately we could define a proper
@@ -3414,13 +2984,20 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
 
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;
-    if (max_insns == 0)
+    if (max_insns == 0) {
         max_insns = CF_COUNT_MASK;
+    }
+
+    if (in_superpage(&ctx, pc_start)) {
+        pc_mask = (1ULL << 41) - 1;
+    } else {
+        pc_mask = ~TARGET_PAGE_MASK;
+    }
 
     gen_tb_start();
     do {
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == ctx.pc) {
                     gen_excp(&ctx, EXCP_DEBUG, 0);
                     break;
@@ -3438,8 +3015,9 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
             tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
-        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
+        }
         insn = cpu_ldl_code(env, ctx.pc);
         num_insns++;
 
@@ -3447,17 +3025,32 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
             tcg_gen_debug_insn_start(ctx.pc);
         }
 
+        TCGV_UNUSED_I64(ctx.zero);
+        TCGV_UNUSED_I64(ctx.sink);
+        TCGV_UNUSED_I64(ctx.lit);
+
         ctx.pc += 4;
         ret = translate_one(ctxp, insn);
 
+        if (!TCGV_IS_UNUSED_I64(ctx.sink)) {
+            tcg_gen_discard_i64(ctx.sink);
+            tcg_temp_free(ctx.sink);
+        }
+        if (!TCGV_IS_UNUSED_I64(ctx.zero)) {
+            tcg_temp_free(ctx.zero);
+        }
+        if (!TCGV_IS_UNUSED_I64(ctx.lit)) {
+            tcg_temp_free(ctx.lit);
+        }
+
         /* If we reach a page boundary, are single stepping,
            or exhaust instruction count, stop generation.  */
         if (ret == NO_EXIT
-            && ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
+            && ((ctx.pc & pc_mask) == 0
                 || tcg_ctx.gen_opc_ptr >= gen_opc_end
                 || num_insns >= max_insns
                 || singlestep
-                || env->singlestep_enabled)) {
+                || ctx.singlestep_enabled)) {
             ret = EXIT_PC_STALE;
         }
     } while (ret == NO_EXIT);
@@ -3474,7 +3067,7 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
         tcg_gen_movi_i64(cpu_pc, ctx.pc);
         /* FALLTHRU */
     case EXIT_PC_UPDATED:
-        if (env->singlestep_enabled) {
+        if (ctx.singlestep_enabled) {
             gen_excp_1(EXCP_DEBUG, 0);
         } else {
             tcg_gen_exit_tb(0);
This page took 0.116987 seconds and 4 git commands to generate.