]> git.proxmox.com Git - qemu.git/blobdiff - target-s390x/translate.c
target-s390: Convert RRBE
[qemu.git] / target-s390x / translate.c
index e0879412c4c89db881d6fc4909a7128eb778d03f..d7d991c58aae4343b019c3b4522ac147da860d97 100644 (file)
@@ -278,17 +278,6 @@ static inline void store_reg32h_i64(int reg, TCGv_i64 v)
     tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
 }
 
-static inline void store_reg16(int reg, TCGv_i32 v)
-{
-    /* 16 bit register writes keep the upper bytes */
-#if HOST_LONG_BITS == 32
-    tcg_gen_deposit_i32(TCGV_LOW(regs[reg]), TCGV_LOW(regs[reg]), v, 0, 16);
-#else
-    tcg_gen_deposit_i64(regs[reg], regs[reg],
-                        MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 16);
-#endif
-}
-
 static inline void store_freg32(int reg, TCGv_i32 v)
 {
     /* 32 bit register writes keep the lower half */
@@ -438,7 +427,7 @@ static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
     return tmp;
 }
 
-static void gen_op_movi_cc(DisasContext *s, uint32_t val)
+static inline void gen_op_movi_cc(DisasContext *s, uint32_t val)
 {
     s->cc_op = CC_OP_CONST0 + val;
 }
@@ -496,6 +485,21 @@ static inline void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
     gen_op_update1_cc_i64(s, CC_OP_NZ, val);
 }
 
+static inline void gen_set_cc_nz_f32(DisasContext *s, TCGv_i64 val)
+{
+    gen_op_update1_cc_i64(s, CC_OP_NZ_F32, val);
+}
+
+static inline void gen_set_cc_nz_f64(DisasContext *s, TCGv_i64 val)
+{
+    gen_op_update1_cc_i64(s, CC_OP_NZ_F64, val);
+}
+
+static inline void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
+{
+    gen_op_update2_cc_i64(s, CC_OP_NZ_F128, vh, vl);
+}
+
 static inline void cmp_32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
                           enum cc_op cond)
 {
@@ -567,19 +571,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
     gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
 }
 
-static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2)
-{
-    tcg_gen_extu_i32_i64(cc_src, v1);
-    tcg_gen_mov_i64(cc_dst, v2);
-    tcg_gen_discard_i64(cc_vr);
-    s->cc_op = CC_OP_LTGT_F32;
-}
-
-static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i32 v1)
-{
-    gen_op_update1_cc_i32(s, CC_OP_NZ_F32, v1);
-}
-
 /* CC value is in env->cc_op */
 static inline void set_cc_static(DisasContext *s)
 {
@@ -629,6 +620,7 @@ static void gen_op_calc_cc(DisasContext *s)
     case CC_OP_COMP_64:
     case CC_OP_NZ_F32:
     case CC_OP_NZ_F64:
+    case CC_OP_FLOGR:
         /* 1 argument */
         gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
         break;
@@ -639,10 +631,9 @@ static void gen_op_calc_cc(DisasContext *s)
     case CC_OP_LTUGTU_64:
     case CC_OP_TM_32:
     case CC_OP_TM_64:
-    case CC_OP_LTGT_F32:
-    case CC_OP_LTGT_F64:
     case CC_OP_SLA_32:
     case CC_OP_SLA_64:
+    case CC_OP_NZ_F128:
         /* 2 arguments */
         gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
         break;
@@ -862,6 +853,20 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
         account_inline_branch(s, old_cc_op);
         break;
 
+    case CC_OP_FLOGR:
+        switch (mask & 0xa) {
+        case 8: /* src == 0 -> no one bit found */
+            cond = TCG_COND_EQ;
+            break;
+        case 2: /* src != 0 -> one bit found */
+            cond = TCG_COND_NE;
+            break;
+        default:
+            goto do_dynamic;
+        }
+        account_inline_branch(s, old_cc_op);
+        break;
+
     default:
     do_dynamic:
         /* Calculate cc value.  */
@@ -898,6 +903,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
 
     case CC_OP_LTGT0_64:
     case CC_OP_NZ:
+    case CC_OP_FLOGR:
         c->u.s64.a = cc_dst;
         c->u.s64.b = tcg_const_i64(0);
         c->g1 = true;
@@ -1012,1167 +1018,171 @@ static void free_compare(DisasCompare *c)
     }
 }
 
-static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
-                     int x2, int b2, int d2)
+static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
+                     uint32_t insn)
 {
-    TCGv_i64 addr, tmp2;
-    TCGv_i32 tmp32_1;
-
-    LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
-              op, r1, x2, b2, d2);
-    addr = get_address(s, x2, b2, d2);
-    switch (op) {
-    case 0xf: /* LRVG     R1,D2(X2,B2)     [RXE] */
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        tcg_gen_bswap64_i64(tmp2, tmp2);
-        store_reg(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 0x17: /* LLGT      R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        tcg_gen_andi_i64(tmp2, tmp2, 0x7fffffffULL);
-        store_reg(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 0x1e: /* LRV R1,D2(X2,B2) [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x1f: /* LRVH R1,D2(X2,B2) [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld16u(tmp2, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        tcg_gen_bswap16_i32(tmp32_1, tmp32_1);
-        store_reg16(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x3e: /* STRV R1,D2(X2,B2) [RXY] */
-        tmp32_1 = load_reg32(r1);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
-        tcg_gen_extu_i32_i64(tmp2, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
-        tcg_temp_free_i64(tmp2);
-        break;
-    default:
-        LOG_DISAS("illegal e3 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-    tcg_temp_free_i64(addr);
-}
-
 #ifndef CONFIG_USER_ONLY
-static void disas_e5(CPUS390XState *env, DisasContext* s, uint64_t insn)
-{
-    TCGv_i64 tmp, tmp2;
-    int op = (insn >> 32) & 0xff;
-
-    tmp = get_address(s, 0, (insn >> 28) & 0xf, (insn >> 16) & 0xfff);
-    tmp2 = get_address(s, 0, (insn >> 12) & 0xf, insn & 0xfff);
-
-    LOG_DISAS("disas_e5: insn %" PRIx64 "\n", insn);
-    switch (op) {
-    case 0x01: /* TPROT    D1(B1),D2(B2)  [SSE] */
-        /* Test Protection */
-        potential_page_fault(s);
-        gen_helper_tprot(cc_op, tmp, tmp2);
-        set_cc_static(s);
-        break;
-    default:
-        LOG_DISAS("illegal e5 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
+    TCGv_i64 tmp, tmp2, tmp3;
+    TCGv_i32 tmp32_1, tmp32_2;
+    int r1, r2;
+    int r3, d2, b2;
 
-    tcg_temp_free_i64(tmp);
-    tcg_temp_free_i64(tmp2);
-}
-#endif
+    r1 = (insn >> 4) & 0xf;
+    r2 = insn & 0xf;
 
-static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
-                     int r3, int b2, int d2)
-{
-    TCGv_i64 tmp;
-    TCGv_i32 tmp32_1, tmp32_2;
+    LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
-    LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
-              op, r1, r3, b2, d2);
     switch (op) {
-    case 0x2c: /* STCMH R1,M3,D2(B2) [RSY] */
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
+    case 0x34: /* STCH ? */
+        /* Store Subchannel */
+        check_privileged(s);
+        gen_op_movi_cc(s, 3);
+        break;
+    case 0x46: /* STURA    R1,R2      [RRE] */
+        /* Store Using Real Address */
+        check_privileged(s);
+        r1 = (insn >> 4) & 0xf;
+        r2 = insn & 0xf;
+        tmp32_1 = load_reg32(r1);
+        tmp = load_reg(r2);
         potential_page_fault(s);
-        gen_helper_stcmh(cpu_env, tmp32_1, tmp, tmp32_2);
+        gen_helper_stura(cpu_env, tmp, tmp32_1);
+        tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
+        break;
+    case 0x50: /* CSP      R1,R2      [RRE] */
+        /* Compare And Swap And Purge */
+        check_privileged(s);
+        r1 = (insn >> 4) & 0xf;
+        r2 = insn & 0xf;
+        tmp32_1 = tcg_const_i32(r1);
+        tmp32_2 = tcg_const_i32(r2);
+        gen_helper_csp(cc_op, cpu_env, tmp32_1, tmp32_2);
+        set_cc_static(s);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-#ifndef CONFIG_USER_ONLY
-    case 0x2f: /* LCTLG     R1,R3,D2(B2)     [RSE] */
-        /* Load Control */
+    case 0x5f: /* CHSC ? */
+        /* Channel Subsystem Call */
         check_privileged(s);
+        gen_op_movi_cc(s, 3);
+        break;
+    case 0x78: /* STCKE    D2(B2)     [S] */
+        /* Store Clock Extended */
+        decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_lctlg(cpu_env, tmp32_1, tmp, tmp32_2);
+        gen_helper_stcke(cc_op, cpu_env, tmp);
+        set_cc_static(s);
         tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x25: /* STCTG     R1,R3,D2(B2)     [RSE] */
-        /* Store Control */
+    case 0x79: /* SACF    D2(B2)     [S] */
+        /* Set Address Space Control Fast */
         check_privileged(s);
+        decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_stctg(cpu_env, tmp32_1, tmp, tmp32_2);
+        gen_helper_sacf(cpu_env, tmp);
         tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
+        /* addressing mode has changed, so end the block */
+        s->pc = s->next_pc;
+        update_psw_addr(s);
+        s->is_jmp = DISAS_JUMP;
         break;
-#endif
-    case 0x30: /* CSG     R1,R3,D2(B2)     [RSY] */
+    case 0x7d: /* STSI     D2,(B2)     [S] */
+        check_privileged(s);
+        decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
+        tmp32_1 = load_reg32(0);
+        tmp32_2 = load_reg32(1);
         potential_page_fault(s);
-        /* XXX rewrite in tcg */
-        gen_helper_csg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
+        gen_helper_stsi(cc_op, cpu_env, tmp, tmp32_1, tmp32_2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x3e: /* CDSG R1,R3,D2(B2) [RSY] */
+    case 0xb1: /* STFL     D2(B2)     [S] */
+        /* Store Facility List (CPU features) at 200 */
+        check_privileged(s);
+        tmp2 = tcg_const_i64(0xc0000000);
+        tmp = tcg_const_i64(200);
+        tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
+        tcg_temp_free_i64(tmp2);
+        tcg_temp_free_i64(tmp);
+        break;
+    case 0xb2: /* LPSWE    D2(B2)     [S] */
+        /* Load PSW Extended */
+        check_privileged(s);
+        decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
+        tmp2 = tcg_temp_new_i64();
+        tmp3 = tcg_temp_new_i64();
+        tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
+        tcg_gen_addi_i64(tmp, tmp, 8);
+        tcg_gen_qemu_ld64(tmp3, tmp, get_mem_index(s));
+        gen_helper_load_psw(cpu_env, tmp2, tmp3);
+        /* we need to keep cc_op intact */
+        s->is_jmp = DISAS_JUMP;
+        tcg_temp_free_i64(tmp);
+        tcg_temp_free_i64(tmp2);
+        tcg_temp_free_i64(tmp3);
+        break;
+    case 0x20: /* SERVC     R1,R2     [RRE] */
+        /* SCLP Service call (PV hypercall) */
+        check_privileged(s);
         potential_page_fault(s);
-        /* XXX rewrite in tcg */
-        gen_helper_cdsg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
+        tmp32_1 = load_reg32(r2);
+        tmp = load_reg(r1);
+        gen_helper_servc(cc_op, cpu_env, tmp32_1, tmp);
         set_cc_static(s);
-        tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
+        tcg_temp_free_i64(tmp);
         break;
     default:
-        LOG_DISAS("illegal eb operation 0x%x\n", op);
+#endif
+        LOG_DISAS("illegal b2 operation 0x%x\n", op);
         gen_illegal_opcode(s);
+#ifndef CONFIG_USER_ONLY
         break;
     }
+#endif
 }
 
-static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
-                     int x2, int b2, int d2, int r1b)
+static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 {
-    TCGv_i32 tmp_r1, tmp32;
-    TCGv_i64 addr, tmp;
-    addr = get_address(s, x2, b2, d2);
-    tmp_r1 = tcg_const_i32(r1);
-    switch (op) {
-    case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */
-        potential_page_fault(s);
-        gen_helper_ldeb(cpu_env, tmp_r1, addr);
-        break;
-    case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */
-        potential_page_fault(s);
-        gen_helper_lxdb(cpu_env, tmp_r1, addr);
-        break;
-    case 0x9: /* CEB    R1,D2(X2,B2)       [RXE] */
-        tmp = tcg_temp_new_i64();
-        tmp32 = load_freg32(r1);
-        tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
-        set_cc_cmp_f32_i64(s, tmp32, tmp);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32);
-        break;
-    case 0xa: /* AEB    R1,D2(X2,B2)       [RXE] */
-        tmp = tcg_temp_new_i64();
-        tmp32 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_aeb(cpu_env, tmp_r1, tmp32);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32);
+    unsigned char opc;
+    uint64_t insn;
+    int op;
 
-        tmp32 = load_freg32(r1);
-        gen_set_cc_nz_f32(s, tmp32);
-        tcg_temp_free_i32(tmp32);
-        break;
-    case 0xb: /* SEB    R1,D2(X2,B2)       [RXE] */
-        tmp = tcg_temp_new_i64();
-        tmp32 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_seb(cpu_env, tmp_r1, tmp32);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32);
+    opc = cpu_ldub_code(env, s->pc);
+    LOG_DISAS("opc 0x%x\n", opc);
 
-        tmp32 = load_freg32(r1);
-        gen_set_cc_nz_f32(s, tmp32);
-        tcg_temp_free_i32(tmp32);
-        break;
-    case 0xd: /* DEB    R1,D2(X2,B2)       [RXE] */
-        tmp = tcg_temp_new_i64();
-        tmp32 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_deb(cpu_env, tmp_r1, tmp32);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32);
-        break;
-    case 0x10: /* TCEB   R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_tceb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    case 0x11: /* TCDB   R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_tcdb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    case 0x12: /* TCXB   R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_tcxb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    case 0x17: /* MEEB   R1,D2(X2,B2)       [RXE] */
-        tmp = tcg_temp_new_i64();
-        tmp32 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_meeb(cpu_env, tmp_r1, tmp32);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32);
-        break;
-    case 0x19: /* CDB    R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_cdb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    case 0x1a: /* ADB    R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_adb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    case 0x1b: /* SDB    R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_sdb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    case 0x1c: /* MDB    R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_mdb(cpu_env, tmp_r1, addr);
-        break;
-    case 0x1d: /* DDB    R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_ddb(cpu_env, tmp_r1, addr);
-        break;
-    case 0x1e: /* MADB  R1,R3,D2(X2,B2) [RXF] */
-        /* for RXF insns, r1 is R3 and r1b is R1 */
-        tmp32 = tcg_const_i32(r1b);
-        potential_page_fault(s);
-        gen_helper_madb(cpu_env, tmp32, addr, tmp_r1);
-        tcg_temp_free_i32(tmp32);
+    switch (opc) {
+    case 0xb2:
+        insn = ld_code4(env, s->pc);
+        op = (insn >> 16) & 0xff;
+        disas_b2(env, s, op, insn);
         break;
     default:
-        LOG_DISAS("illegal ed operation 0x%x\n", op);
+        qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
         gen_illegal_opcode(s);
-        return;
+        break;
     }
-    tcg_temp_free_i32(tmp_r1);
-    tcg_temp_free_i64(addr);
 }
 
-static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
-                     uint32_t insn)
-{
-    TCGv_i64 tmp, tmp2, tmp3;
-    TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
-    int r1, r2;
-#ifndef CONFIG_USER_ONLY
-    int r3, d2, b2;
-#endif
-
-    r1 = (insn >> 4) & 0xf;
-    r2 = insn & 0xf;
+/* ====================================================================== */
+/* Define the insn format enumeration.  */
+#define F0(N)                         FMT_##N,
+#define F1(N, X1)                     F0(N)
+#define F2(N, X1, X2)                 F0(N)
+#define F3(N, X1, X2, X3)             F0(N)
+#define F4(N, X1, X2, X3, X4)         F0(N)
+#define F5(N, X1, X2, X3, X4, X5)     F0(N)
 
-    LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
-
-    switch (op) {
-    case 0x22: /* IPM    R1               [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        gen_op_calc_cc(s);
-        gen_helper_ipm(cpu_env, cc_op, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x41: /* CKSM    R1,R2     [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        potential_page_fault(s);
-        gen_helper_cksm(cpu_env, tmp32_1, tmp32_2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        gen_op_movi_cc(s, 0);
-        break;
-    case 0x4e: /* SAR     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x4f: /* EAR     R1,R2     [RRE] */
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r2]));
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x54: /* MVPG     R1,R2     [RRE] */
-        tmp = load_reg(0);
-        tmp2 = load_reg(r1);
-        tmp3 = load_reg(r2);
-        potential_page_fault(s);
-        gen_helper_mvpg(cpu_env, tmp, tmp2, tmp3);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        /* XXX check CCO bit and set CC accordingly */
-        gen_op_movi_cc(s, 0);
-        break;
-    case 0x55: /* MVST     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(0);
-        tmp32_2 = tcg_const_i32(r1);
-        tmp32_3 = tcg_const_i32(r2);
-        potential_page_fault(s);
-        gen_helper_mvst(cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        gen_op_movi_cc(s, 1);
-        break;
-    case 0x5d: /* CLST     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(0);
-        tmp32_2 = tcg_const_i32(r1);
-        tmp32_3 = tcg_const_i32(r2);
-        potential_page_fault(s);
-        gen_helper_clst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    case 0x5e: /* SRST     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(0);
-        tmp32_2 = tcg_const_i32(r1);
-        tmp32_3 = tcg_const_i32(r2);
-        potential_page_fault(s);
-        gen_helper_srst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-
-#ifndef CONFIG_USER_ONLY
-    case 0x02: /* STIDP     D2(B2)     [S] */
-        /* Store CPU ID */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_stidp(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x04: /* SCK       D2(B2)     [S] */
-        /* Set Clock */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_sck(cc_op, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x05: /* STCK     D2(B2)     [S] */
-        /* Store Clock */
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_stck(cc_op, cpu_env, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x06: /* SCKC     D2(B2)     [S] */
-        /* Set Clock Comparator */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_sckc(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x07: /* STCKC    D2(B2)     [S] */
-        /* Store Clock Comparator */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_stckc(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x08: /* SPT      D2(B2)     [S] */
-        /* Set CPU Timer */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_spt(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x09: /* STPT     D2(B2)     [S] */
-        /* Store CPU Timer */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_stpt(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x0a: /* SPKA     D2(B2)     [S] */
-        /* Set PSW Key from Address */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_andi_i64(tmp2, psw_mask, ~PSW_MASK_KEY);
-        tcg_gen_shli_i64(tmp, tmp, PSW_SHIFT_KEY - 4);
-        tcg_gen_or_i64(psw_mask, tmp2, tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x0d: /* PTLB                [S] */
-        /* Purge TLB */
-        check_privileged(s);
-        gen_helper_ptlb(cpu_env);
-        break;
-    case 0x10: /* SPX      D2(B2)     [S] */
-        /* Set Prefix Register */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_spx(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x11: /* STPX     D2(B2)     [S] */
-        /* Store Prefix */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_ld_i64(tmp2, cpu_env, offsetof(CPUS390XState, psa));
-        tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 0x12: /* STAP     D2(B2)     [S] */
-        /* Store CPU Address */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, cpu_num));
-        tcg_gen_extu_i32_i64(tmp2, tmp32_1);
-        tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x21: /* IPTE     R1,R2      [RRE] */
-        /* Invalidate PTE */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp = load_reg(r1);
-        tmp2 = load_reg(r2);
-        gen_helper_ipte(cpu_env, tmp, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 0x29: /* ISKE     R1,R2      [RRE] */
-        /* Insert Storage Key Extended */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp = load_reg(r2);
-        tmp2 = tcg_temp_new_i64();
-        gen_helper_iske(tmp2, cpu_env, tmp);
-        store_reg(r1, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 0x2a: /* RRBE     R1,R2      [RRE] */
-        /* Set Storage Key Extended */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp32_1 = load_reg32(r1);
-        tmp = load_reg(r2);
-        gen_helper_rrbe(cc_op, cpu_env, tmp32_1, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x2b: /* SSKE     R1,R2      [RRE] */
-        /* Set Storage Key Extended */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp32_1 = load_reg32(r1);
-        tmp = load_reg(r2);
-        gen_helper_sske(cpu_env, tmp32_1, tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x34: /* STCH ? */
-        /* Store Subchannel */
-        check_privileged(s);
-        gen_op_movi_cc(s, 3);
-        break;
-    case 0x46: /* STURA    R1,R2      [RRE] */
-        /* Store Using Real Address */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp32_1 = load_reg32(r1);
-        tmp = load_reg(r2);
-        potential_page_fault(s);
-        gen_helper_stura(cpu_env, tmp, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x50: /* CSP      R1,R2      [RRE] */
-        /* Compare And Swap And Purge */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        gen_helper_csp(cc_op, cpu_env, tmp32_1, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0x5f: /* CHSC ? */
-        /* Channel Subsystem Call */
-        check_privileged(s);
-        gen_op_movi_cc(s, 3);
-        break;
-    case 0x78: /* STCKE    D2(B2)     [S] */
-        /* Store Clock Extended */
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_stcke(cc_op, cpu_env, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x79: /* SACF    D2(B2)     [S] */
-        /* Set Address Space Control Fast */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_sacf(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        /* addressing mode has changed, so end the block */
-        s->pc = s->next_pc;
-        update_psw_addr(s);
-        s->is_jmp = DISAS_JUMP;
-        break;
-    case 0x7d: /* STSI     D2,(B2)     [S] */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = load_reg32(0);
-        tmp32_2 = load_reg32(1);
-        potential_page_fault(s);
-        gen_helper_stsi(cc_op, cpu_env, tmp, tmp32_1, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0x9d: /* LFPC      D2(B2)   [S] */
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0xb1: /* STFL     D2(B2)     [S] */
-        /* Store Facility List (CPU features) at 200 */
-        check_privileged(s);
-        tmp2 = tcg_const_i64(0xc0000000);
-        tmp = tcg_const_i64(200);
-        tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0xb2: /* LPSWE    D2(B2)     [S] */
-        /* Load PSW Extended */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
-        tcg_gen_addi_i64(tmp, tmp, 8);
-        tcg_gen_qemu_ld64(tmp3, tmp, get_mem_index(s));
-        gen_helper_load_psw(cpu_env, tmp2, tmp3);
-        /* we need to keep cc_op intact */
-        s->is_jmp = DISAS_JUMP;
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
-    case 0x20: /* SERVC     R1,R2     [RRE] */
-        /* SCLP Service call (PV hypercall) */
-        check_privileged(s);
-        potential_page_fault(s);
-        tmp32_1 = load_reg32(r2);
-        tmp = load_reg(r1);
-        gen_helper_servc(cc_op, cpu_env, tmp32_1, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
-#endif
-    default:
-        LOG_DISAS("illegal b2 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-}
-
-static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
-                     int r1, int r2)
-{
-    TCGv_i64 tmp;
-    TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
-    LOG_DISAS("disas_b3: op 0x%x m3 0x%x r1 %d r2 %d\n", op, m3, r1, r2);
-#define FP_HELPER(i) \
-    tmp32_1 = tcg_const_i32(r1); \
-    tmp32_2 = tcg_const_i32(r2); \
-    gen_helper_ ## i(cpu_env, tmp32_1, tmp32_2); \
-    tcg_temp_free_i32(tmp32_1); \
-    tcg_temp_free_i32(tmp32_2);
-
-#define FP_HELPER_CC(i) \
-    tmp32_1 = tcg_const_i32(r1); \
-    tmp32_2 = tcg_const_i32(r2); \
-    gen_helper_ ## i(cc_op, cpu_env, tmp32_1, tmp32_2); \
-    set_cc_static(s); \
-    tcg_temp_free_i32(tmp32_1); \
-    tcg_temp_free_i32(tmp32_2);
-
-    switch (op) {
-    case 0x0: /* LPEBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lpebr);
-        break;
-    case 0x2: /* LTEBR       R1,R2             [RRE] */
-        FP_HELPER_CC(ltebr);
-        break;
-    case 0x3: /* LCEBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lcebr);
-        break;
-    case 0x4: /* LDEBR       R1,R2             [RRE] */
-        FP_HELPER(ldebr);
-        break;
-    case 0x5: /* LXDBR       R1,R2             [RRE] */
-        FP_HELPER(lxdbr);
-        break;
-    case 0x9: /* CEBR        R1,R2             [RRE] */
-        FP_HELPER_CC(cebr);
-        break;
-    case 0xa: /* AEBR        R1,R2             [RRE] */
-        FP_HELPER_CC(aebr);
-        break;
-    case 0xb: /* SEBR        R1,R2             [RRE] */
-        FP_HELPER_CC(sebr);
-        break;
-    case 0xd: /* DEBR        R1,R2             [RRE] */
-        FP_HELPER(debr);
-        break;
-    case 0x10: /* LPDBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lpdbr);
-        break;
-    case 0x12: /* LTDBR       R1,R2             [RRE] */
-        FP_HELPER_CC(ltdbr);
-        break;
-    case 0x13: /* LCDBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lcdbr);
-        break;
-    case 0x15: /* SQBDR       R1,R2             [RRE] */
-        FP_HELPER(sqdbr);
-        break;
-    case 0x17: /* MEEBR       R1,R2             [RRE] */
-        FP_HELPER(meebr);
-        break;
-    case 0x19: /* CDBR        R1,R2             [RRE] */
-        FP_HELPER_CC(cdbr);
-        break;
-    case 0x1a: /* ADBR        R1,R2             [RRE] */
-        FP_HELPER_CC(adbr);
-        break;
-    case 0x1b: /* SDBR        R1,R2             [RRE] */
-        FP_HELPER_CC(sdbr);
-        break;
-    case 0x1c: /* MDBR        R1,R2             [RRE] */
-        FP_HELPER(mdbr);
-        break;
-    case 0x1d: /* DDBR        R1,R2             [RRE] */
-        FP_HELPER(ddbr);
-        break;
-    case 0xe: /* MAEBR  R1,R3,R2 [RRF] */
-    case 0x1e: /* MADBR R1,R3,R2 [RRF] */
-    case 0x1f: /* MSDBR R1,R3,R2 [RRF] */
-        /* for RRF insns, m3 is R1, r1 is R3, and r2 is R2 */
-        tmp32_1 = tcg_const_i32(m3);
-        tmp32_2 = tcg_const_i32(r2);
-        tmp32_3 = tcg_const_i32(r1);
-        switch (op) {
-        case 0xe:
-            gen_helper_maebr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
-            break;
-        case 0x1e:
-            gen_helper_madbr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
-            break;
-        case 0x1f:
-            gen_helper_msdbr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    case 0x40: /* LPXBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lpxbr);
-        break;
-    case 0x42: /* LTXBR       R1,R2             [RRE] */
-        FP_HELPER_CC(ltxbr);
-        break;
-    case 0x43: /* LCXBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lcxbr);
-        break;
-    case 0x44: /* LEDBR       R1,R2             [RRE] */
-        FP_HELPER(ledbr);
-        break;
-    case 0x45: /* LDXBR       R1,R2             [RRE] */
-        FP_HELPER(ldxbr);
-        break;
-    case 0x46: /* LEXBR       R1,R2             [RRE] */
-        FP_HELPER(lexbr);
-        break;
-    case 0x49: /* CXBR        R1,R2             [RRE] */
-        FP_HELPER_CC(cxbr);
-        break;
-    case 0x4a: /* AXBR        R1,R2             [RRE] */
-        FP_HELPER_CC(axbr);
-        break;
-    case 0x4b: /* SXBR        R1,R2             [RRE] */
-        FP_HELPER_CC(sxbr);
-        break;
-    case 0x4c: /* MXBR        R1,R2             [RRE] */
-        FP_HELPER(mxbr);
-        break;
-    case 0x4d: /* DXBR        R1,R2             [RRE] */
-        FP_HELPER(dxbr);
-        break;
-    case 0x65: /* LXR         R1,R2             [RRE] */
-        tmp = load_freg(r2);
-        store_freg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        tmp = load_freg(r2 + 2);
-        store_freg(r1 + 2, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x74: /* LZER        R1                [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        gen_helper_lzer(cpu_env, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x75: /* LZDR        R1                [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        gen_helper_lzdr(cpu_env, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x76: /* LZXR        R1                [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        gen_helper_lzxr(cpu_env, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x84: /* SFPC        R1                [RRE] */
-        tmp32_1 = load_reg32(r1);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x8c: /* EFPC        R1                [RRE] */
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x94: /* CEFBR       R1,R2             [RRE] */
-    case 0x95: /* CDFBR       R1,R2             [RRE] */
-    case 0x96: /* CXFBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = load_reg32(r2);
-        switch (op) {
-        case 0x94:
-            gen_helper_cefbr(cpu_env, tmp32_1, tmp32_2);
-            break;
-        case 0x95:
-            gen_helper_cdfbr(cpu_env, tmp32_1, tmp32_2);
-            break;
-        case 0x96:
-            gen_helper_cxfbr(cpu_env, tmp32_1, tmp32_2);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0x98: /* CFEBR       R1,R2             [RRE] */
-    case 0x99: /* CFDBR              R1,R2             [RRE] */
-    case 0x9a: /* CFXBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        tmp32_3 = tcg_const_i32(m3);
-        switch (op) {
-        case 0x98:
-            gen_helper_cfebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        case 0x99:
-            gen_helper_cfdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        case 0x9a:
-            gen_helper_cfxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        default:
-            tcg_abort();
-        }
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    case 0xa4: /* CEGBR       R1,R2             [RRE] */
-    case 0xa5: /* CDGBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp = load_reg(r2);
-        switch (op) {
-        case 0xa4:
-            gen_helper_cegbr(cpu_env, tmp32_1, tmp);
-            break;
-        case 0xa5:
-            gen_helper_cdgbr(cpu_env, tmp32_1, tmp);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0xa6: /* CXGBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp = load_reg(r2);
-        gen_helper_cxgbr(cpu_env, tmp32_1, tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0xa8: /* CGEBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        tmp32_3 = tcg_const_i32(m3);
-        gen_helper_cgebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    case 0xa9: /* CGDBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        tmp32_3 = tcg_const_i32(m3);
-        gen_helper_cgdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    case 0xaa: /* CGXBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        tmp32_3 = tcg_const_i32(m3);
-        gen_helper_cgxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    default:
-        LOG_DISAS("illegal b3 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-
-#undef FP_HELPER_CC
-#undef FP_HELPER
-}
-
-static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
-                     int r2)
-{
-    TCGv_i64 tmp;
-    TCGv_i32 tmp32_1;
-
-    LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
-    switch (op) {
-    case 0x17: /* LLGTR      R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tmp = tcg_temp_new_i64();
-        tcg_gen_andi_i32(tmp32_1, tmp32_1, 0x7fffffffUL);
-        tcg_gen_extu_i32_i64(tmp, tmp32_1);
-        store_reg(r1, tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x0f: /* LRVGR    R1,R2     [RRE] */
-        tcg_gen_bswap64_i64(regs[r1], regs[r2]);
-        break;
-    case 0x1f: /* LRVR     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x83: /* FLOGR R1,R2 [RRE] */
-        tmp = load_reg(r2);
-        tmp32_1 = tcg_const_i32(r1);
-        gen_helper_flogr(cc_op, cpu_env, tmp32_1, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    default:
-        LOG_DISAS("illegal b9 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-}
-
-static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
-{
-    TCGv_i64 tmp, tmp2;
-    TCGv_i32 tmp32_1, tmp32_2;
-    unsigned char opc;
-    uint64_t insn;
-    int op, r1, r2, r3, d2, x2, b2, r1b;
-
-    opc = cpu_ldub_code(env, s->pc);
-    LOG_DISAS("opc 0x%x\n", opc);
-
-    switch (opc) {
-    case 0xb2:
-        insn = ld_code4(env, s->pc);
-        op = (insn >> 16) & 0xff;
-        switch (op) {
-        case 0x9c: /* STFPC    D2(B2) [S] */
-            d2 = insn & 0xfff;
-            b2 = (insn >> 12) & 0xf;
-            tmp32_1 = tcg_temp_new_i32();
-            tmp = tcg_temp_new_i64();
-            tmp2 = get_address(s, 0, b2, d2);
-            tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
-            tcg_gen_extu_i32_i64(tmp, tmp32_1);
-            tcg_gen_qemu_st32(tmp, tmp2, get_mem_index(s));
-            tcg_temp_free_i32(tmp32_1);
-            tcg_temp_free_i64(tmp);
-            tcg_temp_free_i64(tmp2);
-            break;
-        default:
-            disas_b2(env, s, op, insn);
-            break;
-        }
-        break;
-    case 0xb3:
-        insn = ld_code4(env, s->pc);
-        op = (insn >> 16) & 0xff;
-        r3 = (insn >> 12) & 0xf; /* aka m3 */
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        disas_b3(env, s, op, r3, r1, r2);
-        break;
-#ifndef CONFIG_USER_ONLY
-    case 0xb6: /* STCTL     R1,R3,D2(B2)     [RS] */
-        /* Store Control */
-        check_privileged(s);
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_stctl(cpu_env, tmp32_1, tmp, tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0xb7: /* LCTL      R1,R3,D2(B2)     [RS] */
-        /* Load Control */
-        check_privileged(s);
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_lctl(cpu_env, tmp32_1, tmp, tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-#endif
-    case 0xb9:
-        insn = ld_code4(env, s->pc);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        op = (insn >> 16) & 0xff;
-        disas_b9(env, s, op, r1, r2);
-        break;
-    case 0xba: /* CS     R1,R3,D2(B2)     [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_cs(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0xbd: /* CLM    R1,M3,D2(B2)     [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_clm(cc_op, cpu_env, tmp32_1, tmp32_2, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0xbe: /* STCM R1,M3,D2(B2) [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_stcm(cpu_env, tmp32_1, tmp32_2, tmp);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0xe3:
-        insn = ld_code6(env, s->pc);
-        debug_insn(insn);
-        op = insn & 0xff;
-        r1 = (insn >> 36) & 0xf;
-        x2 = (insn >> 32) & 0xf;
-        b2 = (insn >> 28) & 0xf;
-        d2 = ((int)((((insn >> 16) & 0xfff)
-           | ((insn << 4) & 0xff000)) << 12)) >> 12;
-        disas_e3(env, s, op,  r1, x2, b2, d2 );
-        break;
-#ifndef CONFIG_USER_ONLY
-    case 0xe5:
-        /* Test Protection */
-        check_privileged(s);
-        insn = ld_code6(env, s->pc);
-        debug_insn(insn);
-        disas_e5(env, s, insn);
-        break;
-#endif
-    case 0xeb:
-        insn = ld_code6(env, s->pc);
-        debug_insn(insn);
-        op = insn & 0xff;
-        r1 = (insn >> 36) & 0xf;
-        r3 = (insn >> 32) & 0xf;
-        b2 = (insn >> 28) & 0xf;
-        d2 = ((int)((((insn >> 16) & 0xfff)
-           | ((insn << 4) & 0xff000)) << 12)) >> 12;
-        disas_eb(env, s, op, r1, r3, b2, d2);
-        break;
-    case 0xed:
-        insn = ld_code6(env, s->pc);
-        debug_insn(insn);
-        op = insn & 0xff;
-        r1 = (insn >> 36) & 0xf;
-        x2 = (insn >> 32) & 0xf;
-        b2 = (insn >> 28) & 0xf;
-        d2 = (short)((insn >> 16) & 0xfff);
-        r1b = (insn >> 12) & 0xf;
-        disas_ed(env, s, op, r1, x2, b2, d2, r1b);
-        break;
-    default:
-        qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
-        gen_illegal_opcode(s);
-        break;
-    }
-}
-
-/* ====================================================================== */
-/* Define the insn format enumeration.  */
-#define F0(N)                         FMT_##N,
-#define F1(N, X1)                     F0(N)
-#define F2(N, X1, X2)                 F0(N)
-#define F3(N, X1, X2, X3)             F0(N)
-#define F4(N, X1, X2, X3, X4)         F0(N)
-#define F5(N, X1, X2, X3, X4, X5)     F0(N)
-
-typedef enum {
-#include "insn-format.def"
-} DisasFormat;
+typedef enum {
+#include "insn-format.def"
+} DisasFormat;
 
 #undef F0
 #undef F1
@@ -2555,6 +1565,25 @@ static ExitStatus op_abs(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_absf32(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_absf64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_absf128(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_andi_i64(o->out, o->in1, 0x7fffffffffffffffull);
+    tcg_gen_mov_i64(o->out2, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_add(DisasContext *s, DisasOps *o)
 {
     tcg_gen_add_i64(o->out, o->in1, o->in2);
@@ -2578,6 +1607,25 @@ static ExitStatus op_addc(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_aeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_aeb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_adb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_adb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_axb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_axb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_and(DisasContext *s, DisasOps *o)
 {
     tcg_gen_and_i64(o->out, o->in1, o->in2);
@@ -2672,6 +1720,123 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
     return help_branch(s, &c, is_imm, imm, o->in2);
 }
 
+static ExitStatus op_ceb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_cdb(cc_op, cpu_env, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_cxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cfeb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cfeb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f32(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cfdb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cfdb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f64(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cfxb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f128(s, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cgeb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cgeb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f32(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cgdb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cgdb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f64(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cgxb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f128(s, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cegb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cegb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cdgb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cdgb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cxgb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cxgb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cksm(DisasContext *s, DisasOps *o)
+{
+    int r2 = get_field(s->fields, r2);
+    TCGv_i64 len = tcg_temp_new_i64();
+
+    potential_page_fault(s);
+    gen_helper_cksm(len, cpu_env, o->in1, o->in2, regs[r2 + 1]);
+    set_cc_static(s);
+    return_low128(o->out);
+
+    tcg_gen_add_i64(regs[r2], regs[r2], len);
+    tcg_gen_sub_i64(regs[r2 + 1], regs[r2 + 1], len);
+    tcg_temp_free_i64(len);
+
+    return NO_EXIT;
+}
+
 static ExitStatus op_clc(DisasContext *s, DisasOps *o)
 {
     int l = get_field(s->fields, l1);
@@ -2718,6 +1883,69 @@ static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_clm(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    TCGv_i32 t1 = tcg_temp_new_i32();
+    tcg_gen_trunc_i64_i32(t1, o->in1);
+    potential_page_fault(s);
+    gen_helper_clm(cc_op, cpu_env, t1, m3, o->in2);
+    set_cc_static(s);
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(m3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_clst(DisasContext *s, DisasOps *o)
+{
+    potential_page_fault(s);
+    gen_helper_clst(o->in1, cpu_env, regs[0], o->in1, o->in2);
+    set_cc_static(s);
+    return_low128(o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cs(DisasContext *s, DisasOps *o)
+{
+    int r3 = get_field(s->fields, r3);
+    potential_page_fault(s);
+    gen_helper_cs(o->out, cpu_env, o->in1, o->in2, regs[r3]);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_csg(DisasContext *s, DisasOps *o)
+{
+    int r3 = get_field(s->fields, r3);
+    potential_page_fault(s);
+    gen_helper_csg(o->out, cpu_env, o->in1, o->in2, regs[r3]);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cds(DisasContext *s, DisasOps *o)
+{
+    int r3 = get_field(s->fields, r3);
+    TCGv_i64 in3 = tcg_temp_new_i64();
+    tcg_gen_deposit_i64(in3, regs[r3 + 1], regs[r3], 32, 32);
+    potential_page_fault(s);
+    gen_helper_csg(o->out, cpu_env, o->in1, o->in2, in3);
+    tcg_temp_free_i64(in3);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cdsg(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    potential_page_fault(s);
+    /* XXX rewrite in tcg */
+    gen_helper_cdsg(cc_op, cpu_env, r1, o->in2, r3);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
 {
     TCGv_i64 t1 = tcg_temp_new_i64();
@@ -2744,33 +1972,65 @@ static ExitStatus op_diag(DisasContext *s, DisasOps *o)
     tcg_temp_free_i32(tmp);
     return NO_EXIT;
 }
-#endif
+#endif
+
+static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
+{
+    gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
+    return_low128(o->out);
+    return NO_EXIT;
+}
+
+static ExitStatus op_divu32(DisasContext *s, DisasOps *o)
+{
+    gen_helper_divu32(o->out2, cpu_env, o->in1, o->in2);
+    return_low128(o->out);
+    return NO_EXIT;
+}
+
+static ExitStatus op_divs64(DisasContext *s, DisasOps *o)
+{
+    gen_helper_divs64(o->out2, cpu_env, o->in1, o->in2);
+    return_low128(o->out);
+    return NO_EXIT;
+}
+
+static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
+{
+    gen_helper_divu64(o->out2, cpu_env, o->out, o->out2, o->in2);
+    return_low128(o->out);
+    return NO_EXIT;
+}
+
+static ExitStatus op_deb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_deb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
 
-static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
+static ExitStatus op_ddb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
-    return_low128(o->out);
+    gen_helper_ddb(o->out, cpu_env, o->in1, o->in2);
     return NO_EXIT;
 }
 
-static ExitStatus op_divu32(DisasContext *s, DisasOps *o)
+static ExitStatus op_dxb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_divu32(o->out2, cpu_env, o->in1, o->in2);
-    return_low128(o->out);
+    gen_helper_dxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+    return_low128(o->out2);
     return NO_EXIT;
 }
 
-static ExitStatus op_divs64(DisasContext *s, DisasOps *o)
+static ExitStatus op_ear(DisasContext *s, DisasOps *o)
 {
-    gen_helper_divs64(o->out2, cpu_env, o->in1, o->in2);
-    return_low128(o->out);
+    int r2 = get_field(s->fields, r2);
+    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, aregs[r2]));
     return NO_EXIT;
 }
 
-static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
+static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
 {
-    gen_helper_divu64(o->out2, cpu_env, o->out, o->out2, o->in2);
-    return_low128(o->out);
+    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
     return NO_EXIT;
 }
 
@@ -2800,6 +2060,26 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_flogr(DisasContext *s, DisasOps *o)
+{
+    /* We'll use the original input for cc computation, since we get to
+       compare that against 0, which ought to be better than comparing
+       the real output against 64.  It also lets cc_dst be a convenient
+       temporary during our computation.  */
+    gen_op_update1_cc_i64(s, CC_OP_FLOGR, o->in2);
+
+    /* R1 = IN ? CLZ(IN) : 64.  */
+    gen_helper_clz(o->out, o->in2);
+
+    /* R1+1 = IN & ~(found bit).  Note that we may attempt to shift this
+       value by 64, which is undefined.  But since the shift is 64 iff the
+       input is zero, we still get the correct result after and'ing.  */
+    tcg_gen_movi_i64(o->out2, 0x8000000000000000ull);
+    tcg_gen_shr_i64(o->out2, o->out2, o->out);
+    tcg_gen_andc_i64(o->out2, cc_dst, o->out2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_icm(DisasContext *s, DisasOps *o)
 {
     int m3 = get_field(s->fields, m3);
@@ -2868,6 +2148,85 @@ static ExitStatus op_insi(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_ipm(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 t1;
+
+    gen_op_calc_cc(s);
+    tcg_gen_andi_i64(o->out, o->out, ~0xff000000ull);
+
+    t1 = tcg_temp_new_i64();
+    tcg_gen_shli_i64(t1, psw_mask, 20);
+    tcg_gen_shri_i64(t1, t1, 36);
+    tcg_gen_or_i64(o->out, o->out, t1);
+
+    tcg_gen_extu_i32_i64(t1, cc_op);
+    tcg_gen_shli_i64(t1, t1, 28);
+    tcg_gen_or_i64(o->out, o->out, t1);
+    tcg_temp_free_i64(t1);
+    return NO_EXIT;
+}
+
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_ipte(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_ipte(cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_iske(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_iske(o->out, cpu_env, o->in2);
+    return NO_EXIT;
+}
+#endif
+
+static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_ldeb(o->out, cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_ledb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_ledb(o->out, cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_ldxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_lexb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_lxdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_lxdb(o->out, cpu_env, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_lxeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_lxeb(o->out, cpu_env, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_llgt(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
+    return NO_EXIT;
+}
+
 static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
 {
     tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
@@ -2911,6 +2270,29 @@ static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
 }
 
 #ifndef CONFIG_USER_ONLY
+static ExitStatus op_lctl(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_lctl(cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_lctlg(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_lctlg(cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    return NO_EXIT;
+}
 static ExitStatus op_lra(DisasContext *s, DisasOps *o)
 {
     check_privileged(s);
@@ -3090,6 +2472,23 @@ static ExitStatus op_mvcs(DisasContext *s, DisasOps *o)
 }
 #endif
 
+static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
+{
+    potential_page_fault(s);
+    gen_helper_mvpg(cpu_env, regs[0], o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mvst(DisasContext *s, DisasOps *o)
+{
+    potential_page_fault(s);
+    gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2);
+    set_cc_static(s);
+    return_low128(o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_mul(DisasContext *s, DisasOps *o)
 {
     tcg_gen_mul_i64(o->out, o->in1, o->in2);
@@ -3103,78 +2502,260 @@ static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_meeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_meeb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mdeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_mdeb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_mdb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_mxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mxdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_mxdb(o->out, cpu_env, o->out, o->out2, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_maeb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
+    gen_helper_maeb(o->out, cpu_env, o->in1, o->in2, r3);
+    tcg_temp_free_i64(r3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_madb(DisasContext *s, DisasOps *o)
+{
+    int r3 = get_field(s->fields, r3);
+    gen_helper_madb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mseb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
+    gen_helper_mseb(o->out, cpu_env, o->in1, o->in2, r3);
+    tcg_temp_free_i64(r3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_msdb(DisasContext *s, DisasOps *o)
+{
+    int r3 = get_field(s->fields, r3);
+    gen_helper_msdb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
+    return NO_EXIT;
+}
+
 static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
 {
     gen_helper_nabs_i64(o->out, o->in2);
     return NO_EXIT;
 }
 
-static ExitStatus op_nc(DisasContext *s, DisasOps *o)
+static ExitStatus op_nabsf32(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_ori_i64(o->out, o->in2, 0x80000000ull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_nabsf64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_ori_i64(o->out, o->in2, 0x8000000000000000ull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_nabsf128(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_ori_i64(o->out, o->in1, 0x8000000000000000ull);
+    tcg_gen_mov_i64(o->out2, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_nc(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+    potential_page_fault(s);
+    gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2);
+    tcg_temp_free_i32(l);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_neg(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_neg_i64(o->out, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_negf32(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_xori_i64(o->out, o->in2, 0x80000000ull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_negf64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_xori_i64(o->out, o->in2, 0x8000000000000000ull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_negf128(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_xori_i64(o->out, o->in1, 0x8000000000000000ull);
+    tcg_gen_mov_i64(o->out2, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_oc(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+    potential_page_fault(s);
+    gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2);
+    tcg_temp_free_i32(l);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_or(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_or_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_ori(DisasContext *s, DisasOps *o)
+{
+    int shift = s->insn->data & 0xff;
+    int size = s->insn->data >> 8;
+    uint64_t mask = ((1ull << size) - 1) << shift;
+
+    assert(!o->g_in2);
+    tcg_gen_shli_i64(o->in2, o->in2, shift);
+    tcg_gen_or_i64(o->out, o->in1, o->in2);
+
+    /* Produce the CC from only the bits manipulated.  */
+    tcg_gen_andi_i64(cc_dst, o->out, mask);
+    set_cc_nz_u64(s, cc_dst);
+    return NO_EXIT;
+}
+
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_ptlb(cpu_env);
+    return NO_EXIT;
+}
+#endif
+
+static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_bswap16_i64(o->out, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_rev32(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_bswap32_i64(o->out, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_rev64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_bswap64_i64(o->out, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_rll32(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 t1 = tcg_temp_new_i32();
+    TCGv_i32 t2 = tcg_temp_new_i32();
+    TCGv_i32 to = tcg_temp_new_i32();
+    tcg_gen_trunc_i64_i32(t1, o->in1);
+    tcg_gen_trunc_i64_i32(t2, o->in2);
+    tcg_gen_rotl_i32(to, t1, t2);
+    tcg_gen_extu_i32_i64(o->out, to);
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(to);
+    return NO_EXIT;
+}
+
+static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_rotl_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_rrbe(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
-    potential_page_fault(s);
-    gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2);
-    tcg_temp_free_i32(l);
+    check_privileged(s);
+    gen_helper_rrbe(cc_op, cpu_env, o->in2);
     set_cc_static(s);
     return NO_EXIT;
 }
+#endif
 
-static ExitStatus op_neg(DisasContext *s, DisasOps *o)
+static ExitStatus op_sar(DisasContext *s, DisasOps *o)
 {
-    tcg_gen_neg_i64(o->out, o->in2);
+    int r1 = get_field(s->fields, r1);
+    tcg_gen_st32_i64(o->in2, cpu_env, offsetof(CPUS390XState, aregs[r1]));
     return NO_EXIT;
 }
 
-static ExitStatus op_oc(DisasContext *s, DisasOps *o)
+static ExitStatus op_seb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
-    potential_page_fault(s);
-    gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2);
-    tcg_temp_free_i32(l);
-    set_cc_static(s);
+    gen_helper_seb(o->out, cpu_env, o->in1, o->in2);
     return NO_EXIT;
 }
 
-static ExitStatus op_or(DisasContext *s, DisasOps *o)
+static ExitStatus op_sdb(DisasContext *s, DisasOps *o)
 {
-    tcg_gen_or_i64(o->out, o->in1, o->in2);
+    gen_helper_sdb(o->out, cpu_env, o->in1, o->in2);
     return NO_EXIT;
 }
 
-static ExitStatus op_ori(DisasContext *s, DisasOps *o)
+static ExitStatus op_sxb(DisasContext *s, DisasOps *o)
 {
-    int shift = s->insn->data & 0xff;
-    int size = s->insn->data >> 8;
-    uint64_t mask = ((1ull << size) - 1) << shift;
-
-    assert(!o->g_in2);
-    tcg_gen_shli_i64(o->in2, o->in2, shift);
-    tcg_gen_or_i64(o->out, o->in1, o->in2);
+    gen_helper_sxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
 
-    /* Produce the CC from only the bits manipulated.  */
-    tcg_gen_andi_i64(cc_dst, o->out, mask);
-    set_cc_nz_u64(s, cc_dst);
+static ExitStatus op_sqeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_sqeb(o->out, cpu_env, o->in2);
     return NO_EXIT;
 }
 
-static ExitStatus op_rll32(DisasContext *s, DisasOps *o)
+static ExitStatus op_sqdb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 t1 = tcg_temp_new_i32();
-    TCGv_i32 t2 = tcg_temp_new_i32();
-    TCGv_i32 to = tcg_temp_new_i32();
-    tcg_gen_trunc_i64_i32(t1, o->in1);
-    tcg_gen_trunc_i64_i32(t2, o->in2);
-    tcg_gen_rotl_i32(to, t1, t2);
-    tcg_gen_extu_i32_i64(o->out, to);
-    tcg_temp_free_i32(t1);
-    tcg_temp_free_i32(t2);
-    tcg_temp_free_i32(to);
+    gen_helper_sqdb(o->out, cpu_env, o->in2);
     return NO_EXIT;
 }
 
-static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
+static ExitStatus op_sqxb(DisasContext *s, DisasOps *o)
 {
-    tcg_gen_rotl_i64(o->out, o->in1, o->in2);
+    gen_helper_sqxb(o->out, cpu_env, o->in1, o->in2);
+    return_low128(o->out2);
     return NO_EXIT;
 }
 
@@ -3222,7 +2803,28 @@ static ExitStatus op_srl(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
+{
+    gen_helper_sfpc(cpu_env, o->in2);
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
+static ExitStatus op_spka(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    tcg_gen_shri_i64(o->in2, o->in2, 4);
+    tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY - 4, 4);
+    return NO_EXIT;
+}
+
+static ExitStatus op_sske(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_sske(cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
 {
     check_privileged(s);
@@ -3230,6 +2832,98 @@ static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stap(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    /* ??? Surely cpu address != cpu number.  In any case the previous
+       version of this stored more than the required half-word, so it
+       is unlikely this has ever been tested.  */
+    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
+    return NO_EXIT;
+}
+
+static ExitStatus op_stck(DisasContext *s, DisasOps *o)
+{
+    gen_helper_stck(o->out, cpu_env);
+    /* ??? We don't implement clock states.  */
+    gen_op_movi_cc(s, 0);
+    return NO_EXIT;
+}
+
+static ExitStatus op_sckc(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_sckc(cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_stckc(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_stckc(o->out, cpu_env);
+    return NO_EXIT;
+}
+
+static ExitStatus op_stctg(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_stctg(cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_stctl(cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
+    return NO_EXIT;
+}
+
+static ExitStatus op_spt(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_spt(cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_stpt(o->out, cpu_env);
+    return NO_EXIT;
+}
+
+static ExitStatus op_spx(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_spx(cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_stpx(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, psa));
+    tcg_gen_andi_i64(o->out, o->out, 0x7fffe000);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
 {
     uint64_t i2 = get_field(s->fields, i2);
@@ -3290,6 +2984,55 @@ static ExitStatus op_stam(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stcm(DisasContext *s, DisasOps *o)
+{
+    int m3 = get_field(s->fields, m3);
+    int pos, base = s->insn->data;
+    TCGv_i64 tmp = tcg_temp_new_i64();
+
+    pos = base + ctz32(m3) * 8;
+    switch (m3) {
+    case 0xf:
+        /* Effectively a 32-bit store.  */
+        tcg_gen_shri_i64(tmp, o->in1, pos);
+        tcg_gen_qemu_st32(tmp, o->in2, get_mem_index(s));
+        break;
+
+    case 0xc:
+    case 0x6:
+    case 0x3:
+        /* Effectively a 16-bit store.  */
+        tcg_gen_shri_i64(tmp, o->in1, pos);
+        tcg_gen_qemu_st16(tmp, o->in2, get_mem_index(s));
+        break;
+
+    case 0x8:
+    case 0x4:
+    case 0x2:
+    case 0x1:
+        /* Effectively an 8-bit store.  */
+        tcg_gen_shri_i64(tmp, o->in1, pos);
+        tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
+        break;
+
+    default:
+        /* This is going to be a sequence of shifts and stores.  */
+        pos = base + 32 - 8;
+        while (m3) {
+            if (m3 & 0x8) {
+                tcg_gen_shri_i64(tmp, o->in1, pos);
+                tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
+                tcg_gen_addi_i64(o->in2, o->in2, 1);
+            }
+            m3 = (m3 << 1) & 0xf;
+            pos -= 8;
+        }
+        break;
+    }
+    tcg_temp_free_i64(tmp);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stm(DisasContext *s, DisasOps *o)
 {
     int r1 = get_field(s->fields, r1);
@@ -3338,6 +3081,15 @@ static ExitStatus op_stmh(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_srst(DisasContext *s, DisasOps *o)
+{
+    potential_page_fault(s);
+    gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2);
+    set_cc_static(s);
+    return_low128(o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_sub(DisasContext *s, DisasOps *o)
 {
     tcg_gen_sub_i64(o->out, o->in1, o->in2);
@@ -3381,6 +3133,37 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
     return EXIT_NORETURN;
 }
 
+static ExitStatus op_tceb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_tceb(cc_op, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_tcdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_tcdb(cc_op, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_tcxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_tcxb(cc_op, o->out, o->out2, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
+{
+    potential_page_fault(s);
+    gen_helper_tprot(cc_op, o->addr1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+#endif
+
 static ExitStatus op_tr(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
@@ -3432,6 +3215,20 @@ static ExitStatus op_xori(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_zero(DisasContext *s, DisasOps *o)
+{
+    o->out = tcg_const_i64(0);
+    return NO_EXIT;
+}
+
+static ExitStatus op_zero2(DisasContext *s, DisasOps *o)
+{
+    o->out = tcg_const_i64(0);
+    o->out2 = o->out;
+    o->g_out2 = true;
+    return NO_EXIT;
+}
+
 /* ====================================================================== */
 /* The "Cc OUTput" generators.  Given the generated output (and in some cases
    the original inputs), update the various cc data structures in order to
@@ -3497,6 +3294,21 @@ static void cout_cmpu64(DisasContext *s, DisasOps *o)
     gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
 }
 
+static void cout_f32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_NZ_F32, o->out);
+}
+
+static void cout_f64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_NZ_F64, o->out);
+}
+
+static void cout_f128(DisasContext *s, DisasOps *o)
+{
+    gen_op_update2_cc_i64(s, CC_OP_NZ_F128, o->out, o->out2);
+}
+
 static void cout_nabs32(DisasContext *s, DisasOps *o)
 {
     gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
@@ -3610,6 +3422,21 @@ static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_out = o->g_out2 = true;
 }
 
+static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->out = fregs[get_field(f, r1)];
+    o->g_out = true;
+}
+
+static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* ??? Specification exception: r1 must be < 14.  */
+    int r1 = get_field(f, r1);
+    o->out = fregs[r1];
+    o->out2 = fregs[(r1 + 2) & 15];
+    o->g_out = o->g_out2 = true;
+}
+
 /* ====================================================================== */
 /* The "Write OUTput" generators.  These generally perform some non-trivial
    copy of data to TCG globals, or to main memory.  The trivial cases are
@@ -3627,6 +3454,12 @@ static void wout_r1_8(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8);
 }
 
+static void wout_r1_16(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int r1 = get_field(f, r1);
+    tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 16);
+}
+
 static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     store_reg32_i64(get_field(f, r1), o->out);
@@ -3661,6 +3494,7 @@ static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
 
 static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
+    /* ??? Specification exception: r1 must be < 14.  */
     int f1 = get_field(s->fields, r1);
     store_freg(f1, o->out);
     store_freg((f1 + 2) & 15, o->out2);
@@ -3700,6 +3534,11 @@ static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
 }
 
+static void wout_m2_32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s));
+}
+
 /* ====================================================================== */
 /* The "INput 1" generators.  These load the first operand to an insn.  */
 
@@ -3726,6 +3565,12 @@ static void in1_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1)]);
 }
 
+static void in1_r1_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_shri_i64(o->in1, regs[get_field(f, r1)], 32);
+}
+
 static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     /* ??? Specification exception: r1 must be even.  */
@@ -3796,11 +3641,26 @@ static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_in1 = true;
 }
 
+static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* ??? Specification exception: r1 must be < 14.  */
+    int r1 = get_field(f, r1);
+    o->out = fregs[r1];
+    o->out2 = fregs[(r1 + 2) & 15];
+    o->g_out = o->g_out2 = true;
+}
+
 static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
 }
 
+static void in1_la2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
+    o->addr1 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
+}
+
 static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in1_la1(s, f, o);
@@ -3846,6 +3706,24 @@ static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
 /* ====================================================================== */
 /* The "INput 2" generators.  These load the second operand to an insn.  */
 
+static void in2_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = regs[get_field(f, r1)];
+    o->g_in2 = true;
+}
+
+static void in2_r1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r1)]);
+}
+
+static void in2_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r1)]);
+}
+
 static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = load_reg(get_field(f, r2));
@@ -3919,12 +3797,18 @@ static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
 
 static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    int f2 = get_field(f, r2);
-    o->in1 = fregs[f2];
-    o->in2 = fregs[(f2 + 2) & 15];
+    /* ??? Specification exception: r1 must be < 14.  */
+    int r2 = get_field(f, r2);
+    o->in1 = fregs[r2];
+    o->in2 = fregs[(r2 + 2) & 15];
     o->g_in1 = o->g_in2 = true;
 }
 
+static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = get_address(s, 0, get_field(f, r2), 0);
+}
+
 static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
@@ -3958,6 +3842,12 @@ static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
 }
 
+static void in2_m2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_a2(s, f, o);
+    tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
+}
+
 static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);