diff options
-rw-r--r-- | target-s390x/insn-data.def | 10 | ||||
-rw-r--r-- | target-s390x/translate.c | 80 |
2 files changed, 81 insertions, 9 deletions
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def index ddc6337584..7bf686b354 100644 --- a/target-s390x/insn-data.def +++ b/target-s390x/insn-data.def @@ -389,6 +389,9 @@ C(0xb302, LTEBR, RRE, Z, 0, e2, 0, cond_e1e2, mov2, f32) C(0xb312, LTDBR, RRE, Z, 0, f2_o, 0, f1, mov2, f64) C(0xb342, LTXBR, RRE, Z, 0, x2_o, 0, x1, movx, f128) +/* LOAD AND TRAP */ + C(0xe39f, LAT, RXY_a, LAT, 0, m2_32u, r1, 0, lat, 0) + C(0xe385, LGAT, RXY_a, LAT, 0, a2, r1, 0, lgat, 0) /* LOAD BYTE */ C(0xb926, LBR, RRE, EI, 0, r2_8s, 0, r1_32, mov2, 0) C(0xb906, LGBR, RRE, EI, 0, r2_8s, 0, r1, mov2, 0) @@ -414,9 +417,13 @@ /* LOAD HALFWORD RELATIVE LONG */ C(0xc405, LHRL, RIL_b, GIE, 0, ri2, new, r1_32, ld16s, 0) C(0xc404, LGHRL, RIL_b, GIE, 0, ri2, r1, 0, ld16s, 0) +/* LOAG HIGH AND TRAP */ + C(0xe3c8, LFHAT, RXY_a, LAT, 0, m2_32u, r1, 0, lfhat, 0) /* LOAD LOGICAL */ C(0xb916, LLGFR, RRE, Z, 0, r2_32u, 0, r1, mov2, 0) C(0xe316, LLGF, RXY_a, Z, 0, a2, r1, 0, ld32u, 0) +/* LOAD LOGICAL AND TRAP */ + C(0xe39d, LLGFAT, RXY_a, LAT, 0, a2, r1, 0, llgfat, 0) /* LOAD LOGICAL RELATIVE LONG */ C(0xc40e, LLGFRL, RIL_b, GIE, 0, ri2, r1, 0, ld32u, 0) /* LOAD LOGICAL CHARACTER */ @@ -442,6 +449,9 @@ /* LOAD LOGICAL THIRTY ONE BITS */ C(0xb917, LLGTR, RRE, Z, 0, r2_o, r1, 0, llgt, 0) C(0xe317, LLGT, RXY_a, Z, 0, m2_32u, r1, 0, llgt, 0) +/* LOAD LOGICAL THIRTY ONE BITS AND TRAP */ + C(0xe39c, LLGTAT, RXY_a, LAT, 0, m2_32u, r1, 0, llgtat, 0) + /* LOAD FPR FROM GR */ C(0xb3c1, LDGR, RRE, FPRGR, 0, r2_o, 0, f1, mov2, 0) /* LOAD GR FROM FPR */ diff --git a/target-s390x/translate.c b/target-s390x/translate.c index fbf7f91ec0..9e53c9812e 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -323,6 +323,20 @@ static inline void gen_illegal_opcode(DisasContext *s) gen_program_exception(s, PGM_OPERATION); } +static inline void gen_trap(DisasContext *s) +{ + TCGv_i32 t; + + /* Set DXC to 0xff. */ + t = tcg_temp_new_i32(); + tcg_gen_ld_i32(t, cpu_env, offsetof(CPUS390XState, fpc)); + tcg_gen_ori_i32(t, t, 0xff00); + tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, fpc)); + tcg_temp_free_i32(t); + + gen_program_exception(s, PGM_DATA); +} + #ifndef CONFIG_USER_ONLY static void check_privileged(DisasContext *s) { @@ -1120,6 +1134,7 @@ typedef enum DisasFacility { FAC_HW, /* high-word */ FAC_IEEEE_SIM, /* IEEE exception sumilation */ FAC_MIE, /* miscellaneous-instruction-extensions */ + FAC_LAT, /* load-and-trap */ FAC_LOC, /* load/store on condition */ FAC_LD, /* long displacement */ FAC_PC, /* population count */ @@ -1968,7 +1983,6 @@ static ExitStatus op_ct(DisasContext *s, DisasOps *o) { int m3 = get_field(s->fields, m3); TCGLabel *lab = gen_new_label(); - TCGv_i32 t; TCGCond c; c = tcg_invert_cond(ltgt_cond[m3]); @@ -1977,15 +1991,8 @@ static ExitStatus op_ct(DisasContext *s, DisasOps *o) } tcg_gen_brcond_i64(c, o->in1, o->in2, lab); - /* Set DXC to 0xff. */ - t = tcg_temp_new_i32(); - tcg_gen_ld_i32(t, cpu_env, offsetof(CPUS390XState, fpc)); - tcg_gen_ori_i32(t, t, 0xff00); - tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, fpc)); - tcg_temp_free_i32(t); - /* Trap. */ - gen_program_exception(s, PGM_DATA); + gen_trap(s); gen_set_label(lab); return NO_EXIT; @@ -2351,6 +2358,61 @@ static ExitStatus op_ld64(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_lat(DisasContext *s, DisasOps *o) +{ + TCGLabel *lab = gen_new_label(); + store_reg32_i64(get_field(s->fields, r1), o->in2); + /* The value is stored even in case of trap. */ + tcg_gen_brcondi_i64(TCG_COND_NE, o->in2, 0, lab); + gen_trap(s); + gen_set_label(lab); + return NO_EXIT; +} + +static ExitStatus op_lgat(DisasContext *s, DisasOps *o) +{ + TCGLabel *lab = gen_new_label(); + tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s)); + /* The value is stored even in case of trap. */ + tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab); + gen_trap(s); + gen_set_label(lab); + return NO_EXIT; +} + +static ExitStatus op_lfhat(DisasContext *s, DisasOps *o) +{ + TCGLabel *lab = gen_new_label(); + store_reg32h_i64(get_field(s->fields, r1), o->in2); + /* The value is stored even in case of trap. */ + tcg_gen_brcondi_i64(TCG_COND_NE, o->in2, 0, lab); + gen_trap(s); + gen_set_label(lab); + return NO_EXIT; +} + +static ExitStatus op_llgfat(DisasContext *s, DisasOps *o) +{ + TCGLabel *lab = gen_new_label(); + tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s)); + /* The value is stored even in case of trap. */ + tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab); + gen_trap(s); + gen_set_label(lab); + return NO_EXIT; +} + +static ExitStatus op_llgtat(DisasContext *s, DisasOps *o) +{ + TCGLabel *lab = gen_new_label(); + tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff); + /* The value is stored even in case of trap. */ + tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab); + gen_trap(s); + gen_set_label(lab); + return NO_EXIT; +} + static ExitStatus op_loc(DisasContext *s, DisasOps *o) { DisasCompare c; |