diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2015-06-03 23:09:48 +0200 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2015-06-05 01:37:59 +0200 |
commit | 3f4de6756cd87b508b37c7ffa93f7b827832c4eb (patch) | |
tree | d7f693d208a23f7b1c71bf6fd74425df53265750 /target-s390x/mem_helper.c | |
parent | 54f007750978ffbb98ce933077e0d1741e0202b0 (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.c | 39 |
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) { |