target/s390x: Tidy SRST
authorRichard Henderson <rth@twiddle.net>
Sun, 18 Jun 2017 18:26:38 +0000 (11:26 -0700)
committerRichard Henderson <rth@twiddle.net>
Mon, 17 Jul 2017 21:13:17 +0000 (14:13 -0700)
Since we require all registers saved on input, read R0 from ENV instead
of passing it manually.  Recognize the specification exception when R0
contains incorrect data.  Keep high bits of result registers unmodified
when in 31 or 24-bit mode.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
target/s390x/helper.h
target/s390x/insn-data.def
target/s390x/mem_helper.c
target/s390x/translate.c

index 2793cf353acf2cc0c0766f6bf2a417c833e77621..a2e5b9b2f3719b47cdc53ddaade26ccfc7536876 100644 (file)
@@ -12,7 +12,7 @@ DEF_HELPER_FLAGS_3(divs32, TCG_CALL_NO_WG, s64, env, s64, s64)
 DEF_HELPER_FLAGS_3(divu32, TCG_CALL_NO_WG, i64, env, i64, i64)
 DEF_HELPER_FLAGS_3(divs64, TCG_CALL_NO_WG, s64, env, s64, s64)
 DEF_HELPER_FLAGS_4(divu64, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
-DEF_HELPER_4(srst, i64, env, i64, i64, i64)
+DEF_HELPER_3(srst, void, env, i32, i32)
 DEF_HELPER_4(clst, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_4(mvn, TCG_CALL_NO_WG, void, env, i32, i64, i64)
 DEF_HELPER_FLAGS_4(mvo, TCG_CALL_NO_WG, void, env, i32, i64, i64)
index 323a301d80be7e7253be4425f7456afbaf6a999d..bc6ff01ad25c69f6760386cd6355e977fbfdf64d 100644 (file)
     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)
+    C(0xb25e, SRST,    RRE,   Z,   0, 0, 0, 0, srst, 0)
 
 /* SET ACCESS */
     C(0xb24e, SAR,     RRE,   Z,   0, r2_o, 0, 0, sar, 0)
index 33e2694c0306d04f1a24dcf491e97369fc25657e..2e3941f0c67148da4cc07c303a98a13f600676a1 100644 (file)
@@ -538,18 +538,21 @@ static inline void set_length(CPUS390XState *env, int reg, uint64_t length)
 }
 
 /* search string (c is byte to search, r2 is string, r1 end of string) */
-uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end,
-                      uint64_t str)
+void HELPER(srst)(CPUS390XState *env, uint32_t r1, uint32_t r2)
 {
     uintptr_t ra = GETPC();
+    uint64_t end, str;
     uint32_t len;
-    uint8_t v, c = r0;
+    uint8_t v, c = env->regs[0];
 
-    str = wrap_address(env, str);
-    end = wrap_address(env, end);
+    /* Bits 32-55 must contain all 0.  */
+    if (env->regs[0] & 0xffffff00u) {
+        cpu_restore_state(ENV_GET_CPU(env), ra);
+        program_interrupt(env, PGM_SPECIFICATION, 6);
+    }
 
-    /* Assume for now that R2 is unmodified.  */
-    env->retxl = str;
+    str = get_address(env, r2);
+    end = get_address(env, r1);
 
     /* Lest we fail to service interrupts in a timely manner, limit the
        amount of work we're willing to do.  For now, let's cap at 8k.  */
@@ -557,20 +560,20 @@ uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end,
         if (str + len == end) {
             /* Character not found.  R1 & R2 are unmodified.  */
             env->cc_op = 2;
-            return end;
+            return;
         }
         v = cpu_ldub_data_ra(env, str + len, ra);
         if (v == c) {
             /* Character found.  Set R1 to the location; R2 is unmodified.  */
             env->cc_op = 1;
-            return str + len;
+            set_address(env, r1, str + len);
+            return;
         }
     }
 
     /* CPU-determined bytes processed.  Advance R2 to next byte to process.  */
-    env->retxl = str + len;
     env->cc_op = 3;
-    return end;
+    set_address(env, r2, str + len);
 }
 
 /* unsigned string compare (c is string terminator) */
index edfdaf40f33a1b356152986f4d36991f7f3b973e..e37a56fc8597a9c66543b6ea6cf7b69a8d67556c 100644 (file)
@@ -4287,9 +4287,14 @@ static ExitStatus op_stpq(DisasContext *s, DisasOps *o)
 
 static ExitStatus op_srst(DisasContext *s, DisasOps *o)
 {
-    gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2);
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
+
+    gen_helper_srst(cpu_env, r1, r2);
+
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r2);
     set_cc_static(s);
-    return_low128(o->in2);
     return NO_EXIT;
 }