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

Let's stay within single pages.

... and indicate cc=3 in case there is work remaining. Keep unicode
padding simple.

While reworking, properly wrap the addresses.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
master
David Hildenbrand 2019-09-02 16:43:21 +02:00
parent a3910396ba
commit 86678418b2
1 changed files with 31 additions and 23 deletions

View File

@ -768,8 +768,8 @@ static inline uint32_t do_mvcl(CPUS390XState *env,
uint64_t *src, uint64_t *srclen, uint64_t *src, uint64_t *srclen,
uint16_t pad, int wordsize, uintptr_t ra) uint16_t pad, int wordsize, uintptr_t ra)
{ {
uint64_t len = MIN(*srclen, *destlen); int len = MIN(*destlen, -(*dest | TARGET_PAGE_MASK));
uint32_t cc; int i, cc;
if (*destlen == *srclen) { if (*destlen == *srclen) {
cc = 0; cc = 0;
@ -779,32 +779,40 @@ static inline uint32_t do_mvcl(CPUS390XState *env,
cc = 2; cc = 2;
} }
/* Copy the src array */ if (!*destlen) {
fast_memmove(env, *dest, *src, len, ra); return cc;
*src += len; }
*srclen -= len;
*dest += len;
*destlen -= len;
/* Pad the remaining area */ /*
if (wordsize == 1) { * Only perform one type of type of operation (move/pad) at a time.
fast_memset(env, *dest, pad, *destlen, ra); * Stay within single pages.
*dest += *destlen; */
*destlen = 0; if (*srclen) {
/* Copy the src array */
len = MIN(MIN(*srclen, -(*src | TARGET_PAGE_MASK)), len);
*destlen -= len;
*srclen -= len;
fast_memmove(env, *dest, *src, len, ra);
*src = wrap_address(env, *src + len);
*dest = wrap_address(env, *dest + len);
} else if (wordsize == 1) {
/* Pad the remaining area */
*destlen -= len;
fast_memset(env, *dest, pad, len, ra);
*dest = wrap_address(env, *dest + len);
} else { } else {
/* If remaining length is odd, pad with odd byte first. */ /* The remaining length selects the padding byte. */
if (*destlen & 1) { for (i = 0; i < len; (*destlen)--, i++) {
cpu_stb_data_ra(env, *dest, pad & 0xff, ra); if (*destlen & 1) {
*dest += 1; cpu_stb_data_ra(env, *dest, pad, ra);
*destlen -= 1; } else {
} cpu_stb_data_ra(env, *dest, pad >> 8, ra);
/* The remaining length is even, pad using words. */ }
for (; *destlen; *dest += 2, *destlen -= 2) { *dest = wrap_address(env, *dest + 1);
cpu_stw_data_ra(env, *dest, pad, ra);
} }
} }
return cc; return *destlen ? 3 : cc;
} }
/* move long */ /* move long */