diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def index 995c0f6e75..c3b1f6f5ef 100644 --- a/target-s390x/insn-data.def +++ b/target-s390x/insn-data.def @@ -173,6 +173,13 @@ C(0xb914, LGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, 0) C(0xe304, LG, RXY_a, Z, 0, a2, r1, 0, ld64, 0) C(0xe314, LGF, RXY_a, Z, 0, a2, r1, 0, ld32s, 0) + C(0x2800, LDR, RR_a, Z, 0, f2_o, 0, f1, mov2, 0) + C(0x6800, LD, RX_a, Z, 0, m2_64, 0, f1, mov2, 0) + C(0xed65, LDY, RXY_a, LD, 0, m2_64, 0, f1, mov2, 0) + C(0x3800, LER, RR_a, Z, 0, e2, 0, cond_e1e2, mov2, 0) + C(0x7800, LE, RX_a, Z, 0, m2_32u, 0, e1, mov2, 0) + C(0xed64, LEY, RXY_a, LD, 0, m2_32u, 0, e1, mov2, 0) + C(0xb365, LXR, RRE, Z, 0, x2_o, 0, x1, movx, 0) /* LOAD IMMEDIATE */ C(0xc001, LGFI, RIL_a, EI, 0, i2, 0, r1, mov2, 0) /* LOAD RELATIVE LONG */ diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 0437f9b9a4..d459b25170 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -224,6 +224,13 @@ static inline TCGv_i32 load_freg32(int reg) return r; } +static inline TCGv_i64 load_freg32_i64(int reg) +{ + TCGv_i64 r = tcg_temp_new_i64(); + tcg_gen_shri_i64(r, fregs[reg], 32); + return r; +} + static inline TCGv_i32 load_reg32(int reg) { TCGv_i32 r = tcg_temp_new_i32(); @@ -293,6 +300,11 @@ static inline void store_freg32(int reg, TCGv_i32 v) #endif } +static inline void store_freg32_i64(int reg, TCGv_i64 v) +{ + tcg_gen_deposit_i64(fregs[reg], fregs[reg], v, 32, 32); +} + static inline void return_low128(TCGv_i64 dest) { tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl)); @@ -2371,20 +2383,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s) LOG_DISAS("opc 0x%x\n", opc); switch (opc) { - case 0x28: /* LDR R1,R2 [RR] */ - insn = ld_code2(env, s->pc); - decode_rr(s, insn, &r1, &r2); - tmp = load_freg(r2); - store_freg(r1, tmp); - tcg_temp_free_i64(tmp); - break; - case 0x38: /* LER R1,R2 [RR] */ - insn = ld_code2(env, s->pc); - decode_rr(s, insn, &r1, &r2); - tmp32_1 = load_freg32(r2); - store_freg32(r1, tmp32_1); - tcg_temp_free_i32(tmp32_1); - break; case 0x43: /* IC R1,D2(X2,B2) [RX] */ insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); @@ -2427,15 +2425,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s) tcg_temp_free_i64(tmp); tcg_temp_free_i64(tmp2); break; - case 0x68: /* LD R1,D2(X2,B2) [RX] */ - insn = ld_code4(env, s->pc); - tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); - tmp2 = tcg_temp_new_i64(); - tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s)); - store_freg(r1, tmp2); - tcg_temp_free_i64(tmp); - tcg_temp_free_i64(tmp2); - break; case 0x70: /* STE R1,D2(X2,B2) [RX] */ insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); @@ -2447,18 +2436,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s) tcg_temp_free_i64(tmp2); tcg_temp_free_i32(tmp32_1); break; - case 0x78: /* LE R1,D2(X2,B2) [RX] */ - insn = ld_code4(env, s->pc); - tmp = decode_rx(s, insn, &r1, &x2, &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); - store_freg32(r1, tmp32_1); - tcg_temp_free_i64(tmp); - tcg_temp_free_i64(tmp2); - tcg_temp_free_i32(tmp32_1); - break; #ifndef CONFIG_USER_ONLY case 0x80: /* SSM D2(B2) [S] */ /* Set System Mask */ @@ -3596,6 +3573,18 @@ static ExitStatus op_mov2(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_movx(DisasContext *s, DisasOps *o) +{ + o->out = o->in1; + o->out2 = o->in2; + o->g_out = o->g_in1; + o->g_out2 = o->g_in2; + TCGV_UNUSED_I64(o->in1); + TCGV_UNUSED_I64(o->in2); + o->g_in1 = o->g_in2 = false; + return NO_EXIT; +} + static ExitStatus op_mvcl(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); @@ -3955,6 +3944,23 @@ static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o) store_reg32_i64(r1, o->out); } +static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o) +{ + store_freg32_i64(get_field(f, r1), o->out); +} + +static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o) +{ + store_freg(get_field(f, r1), o->out); +} + +static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o) +{ + int f1 = get_field(s->fields, r1); + store_freg(f1, o->out); + store_freg((f1 + 2) & 15, o->out2); +} + static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o) { if (get_field(f, r1) != get_field(f, r2)) { @@ -3962,6 +3968,13 @@ static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o) } } +static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o) +{ + if (get_field(f, r1) != get_field(f, r2)) { + store_freg32_i64(get_field(f, r1), o->out); + } +} + static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o) { tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s)); @@ -4137,6 +4150,25 @@ static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o) tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]); } +static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o) +{ + o->in2 = load_freg32_i64(get_field(f, r2)); +} + +static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o) +{ + o->in2 = fregs[get_field(f, r2)]; + o->g_in2 = true; +} + +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]; + o->g_in1 = o->g_in2 = true; +} + static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o) { int x2 = have_field(f, x2) ? get_field(f, x2) : 0;