aboutsummaryrefslogtreecommitdiff
path: root/target-s390x/mem_helper.c
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2015-06-03 23:09:48 +0200
committerAlexander Graf <agraf@suse.de>2015-06-05 01:37:59 +0200
commit3f4de6756cd87b508b37c7ffa93f7b827832c4eb (patch)
treed7f693d208a23f7b1c71bf6fd74425df53265750 /target-s390x/mem_helper.c
parent54f007750978ffbb98ce933077e0d1741e0202b0 (diff)
target-s390x: implement TRANSLATE EXTENDED instruction
It is part of the basic zArchitecture instructions. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-s390x/mem_helper.c')
-rw-r--r--target-s390x/mem_helper.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index e19e1aa961..30a2a6dfd5 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -804,6 +804,45 @@ void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array,
}
}
+uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array,
+ uint64_t len, uint64_t trans)
+{
+ uint8_t end = env->regs[0] & 0xff;
+ uint64_t l = len;
+ uint64_t i;
+
+ if (!(env->psw.mask & PSW_MASK_64)) {
+ array &= 0x7fffffff;
+ l = (uint32_t)l;
+ }
+
+ /* 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. */
+ if (l > 0x2000) {
+ l = 0x2000;
+ env->cc_op = 3;
+ } else {
+ env->cc_op = 0;
+ }
+
+ for (i = 0; i < l; i++) {
+ uint8_t byte, new_byte;
+
+ byte = cpu_ldub_data(env, array + i);
+
+ if (byte == end) {
+ env->cc_op = 1;
+ break;
+ }
+
+ new_byte = cpu_ldub_data(env, trans + byte);
+ cpu_stb_data(env, array + i, new_byte);
+ }
+
+ env->retxl = len - i;
+ return array + i;
+}
+
uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array,
uint64_t trans)
{