aboutsummaryrefslogtreecommitdiff
path: root/target/s390x
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2018-08-20 19:56:24 -0700
committerRichard Henderson <richard.henderson@linaro.org>2018-10-18 19:46:53 -0700
commit72d8ad67ba6d2fb71b84c884bd9f7e7817e2817d (patch)
tree7adfc4da526910d2be559e536363bd865be5b456 /target/s390x
parent0c9fa16805b450f53f602b9a8043e1d5fbe997ff (diff)
downloadqemu-72d8ad67ba6d2fb71b84c884bd9f7e7817e2817d.zip
qemu-72d8ad67ba6d2fb71b84c884bd9f7e7817e2817d.tar.gz
qemu-72d8ad67ba6d2fb71b84c884bd9f7e7817e2817d.tar.bz2
target/s390x: Skip wout, cout helpers if op helper does not return
When op raises an exception, it may not have initialized the output temps that would be written back by wout or cout. Reviewed-by: David Hildenbrand <david@redhat.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/s390x')
-rw-r--r--target/s390x/translate.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 18861cd..a7bd689 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -1128,11 +1128,19 @@ struct DisasInsn {
const char *name;
+ /* Pre-process arguments before HELP_OP. */
void (*help_in1)(DisasContext *, DisasFields *, DisasOps *);
void (*help_in2)(DisasContext *, DisasFields *, DisasOps *);
void (*help_prep)(DisasContext *, DisasFields *, DisasOps *);
+
+ /*
+ * Post-process output after HELP_OP.
+ * Note that these are not called if HELP_OP returns DISAS_NORETURN.
+ */
void (*help_wout)(DisasContext *, DisasFields *, DisasOps *);
void (*help_cout)(DisasContext *, DisasOps *);
+
+ /* Implement the operation itself. */
DisasJumpType (*help_op)(DisasContext *, DisasOps *);
uint64_t data;
@@ -6125,11 +6133,13 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
if (insn->help_op) {
ret = insn->help_op(s, &o);
}
- if (insn->help_wout) {
- insn->help_wout(s, &f, &o);
- }
- if (insn->help_cout) {
- insn->help_cout(s, &o);
+ if (ret != DISAS_NORETURN) {
+ if (insn->help_wout) {
+ insn->help_wout(s, &f, &o);
+ }
+ if (insn->help_cout) {
+ insn->help_cout(s, &o);
+ }
}
/* Free any temporaries created by the helpers. */