提交 f1c2e27c 编写于 作者: D David Hildenbrand

s390x/tcg: MVCL: Process max 4k bytes at a time

Process max 4k bytes at a time, writing back registers between the
accesses. The instruction is interruptible.
    "For operands longer than 2K bytes, access exceptions are not
    recognized for locations more than 2K bytes beyond the current location
    being processed."
Note that on z/Architecture, 2k vs. 4k access cannot get differentiated as
long as pages are not crossed. This seems to be a leftover from ESA/390.
Simply stay within single pages.

MVCL handling is quite different than MVCLE/MVCLU handling, so split up
the handlers.

Defer interrupt handling, as that will require more thought, add a TODO
for that.
Reviewed-by: NRichard Henderson <richard.henderson@linaro.org>
Signed-off-by: NDavid Hildenbrand <david@redhat.com>
上级 fbc17598
......@@ -798,19 +798,51 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2)
uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
uint64_t src = get_address(env, r2);
uint8_t pad = env->regs[r2 + 1] >> 24;
uint32_t cc;
uint32_t cc, cur_len;
if (is_destructive_overlap(env, dest, src, MIN(srclen, destlen))) {
cc = 3;
} else if (srclen == destlen) {
cc = 0;
} else if (destlen < srclen) {
cc = 1;
} else {
cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, 1, ra);
cc = 2;
}
env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen);
env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen);
/* We might have to zero-out some bits even if there was no action. */
if (unlikely(!destlen || cc == 3)) {
set_address_zero(env, r2, src);
set_address_zero(env, r1, dest);
return cc;
} else if (!srclen) {
set_address_zero(env, r2, src);
}
/*
* Only perform one type of type of operation (move/pad) in one step.
* Stay within single pages.
*/
while (destlen) {
cur_len = MIN(destlen, -(dest | TARGET_PAGE_MASK));
if (!srclen) {
fast_memset(env, dest, pad, cur_len, ra);
} else {
cur_len = MIN(MIN(srclen, -(src | TARGET_PAGE_MASK)), cur_len);
fast_memmove(env, dest, src, cur_len, ra);
src = wrap_address(env, src + cur_len);
srclen -= cur_len;
env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen);
set_address_zero(env, r2, src);
}
dest = wrap_address(env, dest + cur_len);
destlen -= cur_len;
env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen);
set_address_zero(env, r1, dest);
/* TODO: Deliver interrupts. */
}
return cc;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册