summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2012-08-31 13:54:13 -0700
committerRichard Henderson <rth@twiddle.net>2013-01-05 12:18:44 -0800
commitd6c6372e186e7f17fe9eeec0c50a43b484669d71 (patch)
tree6479fd69a373342f9458e757377fbbb7fd3d0937
parent143cbbc5ebc4a5b5beb82dc31ecc5ac5f6d511d2 (diff)
downloadqemu-d6c6372e186e7f17fe9eeec0c50a43b484669d71.tar.gz
target-s390: Implement R[NOX]SBG
Signed-off-by: Richard Henderson <rth@twiddle.net>
-rw-r--r--target-s390x/insn-data.def4
-rw-r--r--target-s390x/translate.c53
2 files changed, 57 insertions, 0 deletions
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8bcfb2b98a..9582f0c847 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -508,6 +508,10 @@
C(0xec55, RISBG, RIE_f, GIE, 0, r2, r1, 0, risbg, s64)
C(0xec5d, RISBHG, RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
C(0xec51, RISBLG, RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
+/* ROTATE_THEN <OP> SELECTED BITS */
+ C(0xec54, RNSBG, RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
+ C(0xec56, ROSBG, RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
+ C(0xec57, RXSBG, RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
/* SEARCH STRING */
C(0xb25e, SRST, RRE, Z, r1_o, r2_o, 0, 0, srst, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1f8659f4db..dbc43a6754 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2512,6 +2512,59 @@ static ExitStatus op_risbg(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_rosbg(DisasContext *s, DisasOps *o)
+{
+ int i3 = get_field(s->fields, i3);
+ int i4 = get_field(s->fields, i4);
+ int i5 = get_field(s->fields, i5);
+ uint64_t mask;
+
+ /* If this is a test-only form, arrange to discard the result. */
+ if (i3 & 0x80) {
+ o->out = tcg_temp_new_i64();
+ o->g_out = false;
+ }
+
+ i3 &= 63;
+ i4 &= 63;
+ i5 &= 63;
+
+ /* MASK is the set of bits to be operated on from R2.
+ Take care for I3/I4 wraparound. */
+ mask = ~0ull >> i3;
+ if (i3 <= i4) {
+ mask ^= ~0ull >> i4 >> 1;
+ } else {
+ mask |= ~(~0ull >> i4 >> 1);
+ }
+
+ /* Rotate the input as necessary. */
+ tcg_gen_rotli_i64(o->in2, o->in2, i5);
+
+ /* Operate. */
+ switch (s->fields->op2) {
+ case 0x55: /* AND */
+ tcg_gen_ori_i64(o->in2, o->in2, ~mask);
+ tcg_gen_and_i64(o->out, o->out, o->in2);
+ break;
+ case 0x56: /* OR */
+ tcg_gen_andi_i64(o->in2, o->in2, mask);
+ tcg_gen_or_i64(o->out, o->out, o->in2);
+ break;
+ case 0x57: /* XOR */
+ tcg_gen_andi_i64(o->in2, o->in2, mask);
+ tcg_gen_xor_i64(o->out, o->out, o->in2);
+ break;
+ default:
+ abort();
+ }
+
+ /* Set the CC. */
+ tcg_gen_andi_i64(cc_dst, o->out, mask);
+ set_cc_nz_u64(s, cc_dst);
+ return NO_EXIT;
+}
+
static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
{
tcg_gen_bswap16_i64(o->out, o->in2);