1 /*
2 * S/390 memory access helper routines
3 *
4 * Copyright (c) 2009 Ulrich Hecht
5 * Copyright (c) 2009 Alexander Graf
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "qemu/osdep.h"
22 #include "qemu/log.h"
23 #include "cpu.h"
24 #include "s390x-internal.h"
25 #include "tcg_s390x.h"
26 #include "exec/helper-proto.h"
27 #include "exec/exec-all.h"
28 #include "exec/page-protection.h"
29 #include "exec/cpu_ldst.h"
30 #include "hw/core/tcg-cpu-ops.h"
31 #include "qemu/int128.h"
32 #include "qemu/atomic128.h"
33 #include "trace.h"
34
35 #if !defined(CONFIG_USER_ONLY)
36 #include "hw/s390x/storage-keys.h"
37 #include "hw/boards.h"
38 #endif
39
40 #ifdef CONFIG_USER_ONLY
41 # define user_or_likely(X) true
42 #else
43 # define user_or_likely(X) likely(X)
44 #endif
45
46 /*****************************************************************************/
47 /* Softmmu support */
48
49 /* #define DEBUG_HELPER */
50 #ifdef DEBUG_HELPER
51 #define HELPER_LOG(x...) qemu_log(x)
52 #else
53 #define HELPER_LOG(x...)
54 #endif
55
psw_key_valid(CPUS390XState * env,uint8_t psw_key)56 static inline bool psw_key_valid(CPUS390XState *env, uint8_t psw_key)
57 {
58 uint16_t pkm = env->cregs[3] >> 16;
59
60 if (env->psw.mask & PSW_MASK_PSTATE) {
61 /* PSW key has range 0..15, it is valid if the bit is 1 in the PKM */
62 return pkm & (0x8000 >> psw_key);
63 }
64 return true;
65 }
66
is_destructive_overlap(CPUS390XState * env,uint64_t dest,uint64_t src,uint32_t len)67 static bool is_destructive_overlap(CPUS390XState *env, uint64_t dest,
68 uint64_t src, uint32_t len)
69 {
70 if (!len || src == dest) {
71 return false;
72 }
73 /* Take care of wrapping at the end of address space. */
74 if (unlikely(wrap_address(env, src + len - 1) < src)) {
75 return dest > src || dest <= wrap_address(env, src + len - 1);
76 }
77 return dest > src && dest <= src + len - 1;
78 }
79
80 /* Trigger a SPECIFICATION exception if an address or a length is not
81 naturally aligned. */
check_alignment(CPUS390XState * env,uint64_t v,int wordsize,uintptr_t ra)82 static inline void check_alignment(CPUS390XState *env, uint64_t v,
83 int wordsize, uintptr_t ra)
84 {
85 if (v % wordsize) {
86 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
87 }
88 }
89
90 /* Load a value from memory according to its size. */
cpu_ldusize_data_ra(CPUS390XState * env,uint64_t addr,int wordsize,uintptr_t ra)91 static inline uint64_t cpu_ldusize_data_ra(CPUS390XState *env, uint64_t addr,
92 int wordsize, uintptr_t ra)
93 {
94 switch (wordsize) {
95 case 1:
96 return cpu_ldub_data_ra(env, addr, ra);
97 case 2:
98 return cpu_lduw_data_ra(env, addr, ra);
99 default:
100 abort();
101 }
102 }
103
104 /* Store a to memory according to its size. */
cpu_stsize_data_ra(CPUS390XState * env,uint64_t addr,uint64_t value,int wordsize,uintptr_t ra)105 static inline void cpu_stsize_data_ra(CPUS390XState *env, uint64_t addr,
106 uint64_t value, int wordsize,
107 uintptr_t ra)
108 {
109 switch (wordsize) {
110 case 1:
111 cpu_stb_data_ra(env, addr, value, ra);
112 break;
113 case 2:
114 cpu_stw_data_ra(env, addr, value, ra);
115 break;
116 default:
117 abort();
118 }
119 }
120
121 /* An access covers at most 4096 bytes and therefore at most two pages. */
122 typedef struct S390Access {
123 target_ulong vaddr1;
124 target_ulong vaddr2;
125 void *haddr1;
126 void *haddr2;
127 uint16_t size1;
128 uint16_t size2;
129 /*
130 * If we can't access the host page directly, we'll have to do I/O access
131 * via ld/st helpers. These are internal details, so we store the
132 * mmu idx to do the access here instead of passing it around in the
133 * helpers.
134 */
135 int mmu_idx;
136 } S390Access;
137
138 /*
139 * With nonfault=1, return the PGM_ exception that would have been injected
140 * into the guest; return 0 if no exception was detected.
141 *
142 * For !CONFIG_USER_ONLY, the TEC is stored stored to env->tlb_fill_tec.
143 * For CONFIG_USER_ONLY, the faulting address is stored to env->__excp_addr.
144 */
s390_probe_access(CPUArchState * env,target_ulong addr,int size,MMUAccessType access_type,int mmu_idx,bool nonfault,void ** phost,uintptr_t ra)145 static inline int s390_probe_access(CPUArchState *env, target_ulong addr,
146 int size, MMUAccessType access_type,
147 int mmu_idx, bool nonfault,
148 void **phost, uintptr_t ra)
149 {
150 int flags = probe_access_flags(env, addr, 0, access_type, mmu_idx,
151 nonfault, phost, ra);
152
153 if (unlikely(flags & TLB_INVALID_MASK)) {
154 #ifdef CONFIG_USER_ONLY
155 /* Address is in TEC in system mode; see s390_cpu_record_sigsegv. */
156 env->__excp_addr = addr & TARGET_PAGE_MASK;
157 return (page_get_flags(addr) & PAGE_VALID
158 ? PGM_PROTECTION : PGM_ADDRESSING);
159 #else
160 return env->tlb_fill_exc;
161 #endif
162 }
163
164 #ifndef CONFIG_USER_ONLY
165 if (unlikely(flags & TLB_WATCHPOINT)) {
166 /* S390 does not presently use transaction attributes. */
167 cpu_check_watchpoint(env_cpu(env), addr, size,
168 MEMTXATTRS_UNSPECIFIED,
169 (access_type == MMU_DATA_STORE
170 ? BP_MEM_WRITE : BP_MEM_READ), ra);
171 }
172 #endif
173
174 return 0;
175 }
176
access_prepare_nf(S390Access * access,CPUS390XState * env,bool nonfault,vaddr vaddr1,int size,MMUAccessType access_type,int mmu_idx,uintptr_t ra)177 static int access_prepare_nf(S390Access *access, CPUS390XState *env,
178 bool nonfault, vaddr vaddr1, int size,
179 MMUAccessType access_type,
180 int mmu_idx, uintptr_t ra)
181 {
182 int size1, size2, exc;
183
184 assert(size > 0 && size <= 4096);
185
186 size1 = MIN(size, -(vaddr1 | TARGET_PAGE_MASK)),
187 size2 = size - size1;
188
189 memset(access, 0, sizeof(*access));
190 access->vaddr1 = vaddr1;
191 access->size1 = size1;
192 access->size2 = size2;
193 access->mmu_idx = mmu_idx;
194
195 exc = s390_probe_access(env, vaddr1, size1, access_type, mmu_idx, nonfault,
196 &access->haddr1, ra);
197 if (unlikely(exc)) {
198 return exc;
199 }
200 if (unlikely(size2)) {
201 /* The access crosses page boundaries. */
202 vaddr vaddr2 = wrap_address(env, vaddr1 + size1);
203
204 access->vaddr2 = vaddr2;
205 exc = s390_probe_access(env, vaddr2, size2, access_type, mmu_idx,
206 nonfault, &access->haddr2, ra);
207 if (unlikely(exc)) {
208 return exc;
209 }
210 }
211 return 0;
212 }
213
access_prepare(S390Access * ret,CPUS390XState * env,vaddr vaddr,int size,MMUAccessType access_type,int mmu_idx,uintptr_t ra)214 static inline void access_prepare(S390Access *ret, CPUS390XState *env,
215 vaddr vaddr, int size,
216 MMUAccessType access_type, int mmu_idx,
217 uintptr_t ra)
218 {
219 int exc = access_prepare_nf(ret, env, false, vaddr, size,
220 access_type, mmu_idx, ra);
221 assert(!exc);
222 }
223
224 /* Helper to handle memset on a single page. */
do_access_memset(CPUS390XState * env,vaddr vaddr,char * haddr,uint8_t byte,uint16_t size,int mmu_idx,uintptr_t ra)225 static void do_access_memset(CPUS390XState *env, vaddr vaddr, char *haddr,
226 uint8_t byte, uint16_t size, int mmu_idx,
227 uintptr_t ra)
228 {
229 #ifdef CONFIG_USER_ONLY
230 memset(haddr, byte, size);
231 #else
232 if (likely(haddr)) {
233 memset(haddr, byte, size);
234 } else {
235 MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
236 for (int i = 0; i < size; i++) {
237 cpu_stb_mmu(env, vaddr + i, byte, oi, ra);
238 }
239 }
240 #endif
241 }
242
access_memset(CPUS390XState * env,S390Access * desta,uint8_t byte,uintptr_t ra)243 static void access_memset(CPUS390XState *env, S390Access *desta,
244 uint8_t byte, uintptr_t ra)
245 {
246
247 do_access_memset(env, desta->vaddr1, desta->haddr1, byte, desta->size1,
248 desta->mmu_idx, ra);
249 if (likely(!desta->size2)) {
250 return;
251 }
252 do_access_memset(env, desta->vaddr2, desta->haddr2, byte, desta->size2,
253 desta->mmu_idx, ra);
254 }
255
access_get_byte(CPUS390XState * env,S390Access * access,int offset,uintptr_t ra)256 static uint8_t access_get_byte(CPUS390XState *env, S390Access *access,
257 int offset, uintptr_t ra)
258 {
259 target_ulong vaddr = access->vaddr1;
260 void *haddr = access->haddr1;
261
262 if (unlikely(offset >= access->size1)) {
263 offset -= access->size1;
264 vaddr = access->vaddr2;
265 haddr = access->haddr2;
266 }
267
268 if (user_or_likely(haddr)) {
269 return ldub_p(haddr + offset);
270 } else {
271 MemOpIdx oi = make_memop_idx(MO_UB, access->mmu_idx);
272 return cpu_ldb_mmu(env, vaddr + offset, oi, ra);
273 }
274 }
275
access_set_byte(CPUS390XState * env,S390Access * access,int offset,uint8_t byte,uintptr_t ra)276 static void access_set_byte(CPUS390XState *env, S390Access *access,
277 int offset, uint8_t byte, uintptr_t ra)
278 {
279 target_ulong vaddr = access->vaddr1;
280 void *haddr = access->haddr1;
281
282 if (unlikely(offset >= access->size1)) {
283 offset -= access->size1;
284 vaddr = access->vaddr2;
285 haddr = access->haddr2;
286 }
287
288 if (user_or_likely(haddr)) {
289 stb_p(haddr + offset, byte);
290 } else {
291 MemOpIdx oi = make_memop_idx(MO_UB, access->mmu_idx);
292 cpu_stb_mmu(env, vaddr + offset, byte, oi, ra);
293 }
294 }
295
296 /*
297 * Move data with the same semantics as memmove() in case ranges don't overlap
298 * or src > dest. Undefined behavior on destructive overlaps.
299 */
access_memmove(CPUS390XState * env,S390Access * desta,S390Access * srca,uintptr_t ra)300 static void access_memmove(CPUS390XState *env, S390Access *desta,
301 S390Access *srca, uintptr_t ra)
302 {
303 int len = desta->size1 + desta->size2;
304 int diff;
305
306 assert(len == srca->size1 + srca->size2);
307
308 /* Fallback to slow access in case we don't have access to all host pages */
309 if (unlikely(!desta->haddr1 || (desta->size2 && !desta->haddr2) ||
310 !srca->haddr1 || (srca->size2 && !srca->haddr2))) {
311 int i;
312
313 for (i = 0; i < len; i++) {
314 uint8_t byte = access_get_byte(env, srca, i, ra);
315
316 access_set_byte(env, desta, i, byte, ra);
317 }
318 return;
319 }
320
321 diff = desta->size1 - srca->size1;
322 if (likely(diff == 0)) {
323 memmove(desta->haddr1, srca->haddr1, srca->size1);
324 if (unlikely(srca->size2)) {
325 memmove(desta->haddr2, srca->haddr2, srca->size2);
326 }
327 } else if (diff > 0) {
328 memmove(desta->haddr1, srca->haddr1, srca->size1);
329 memmove(desta->haddr1 + srca->size1, srca->haddr2, diff);
330 if (likely(desta->size2)) {
331 memmove(desta->haddr2, srca->haddr2 + diff, desta->size2);
332 }
333 } else {
334 diff = -diff;
335 memmove(desta->haddr1, srca->haddr1, desta->size1);
336 memmove(desta->haddr2, srca->haddr1 + desta->size1, diff);
337 if (likely(srca->size2)) {
338 memmove(desta->haddr2 + diff, srca->haddr2, srca->size2);
339 }
340 }
341 }
342
mmu_idx_from_as(uint8_t as)343 static int mmu_idx_from_as(uint8_t as)
344 {
345 switch (as) {
346 case AS_PRIMARY:
347 return MMU_PRIMARY_IDX;
348 case AS_SECONDARY:
349 return MMU_SECONDARY_IDX;
350 case AS_HOME:
351 return MMU_HOME_IDX;
352 default:
353 /* FIXME AS_ACCREG */
354 g_assert_not_reached();
355 }
356 }
357
358 /* and on array */
do_helper_nc(CPUS390XState * env,uint32_t l,uint64_t dest,uint64_t src,uintptr_t ra)359 static uint32_t do_helper_nc(CPUS390XState *env, uint32_t l, uint64_t dest,
360 uint64_t src, uintptr_t ra)
361 {
362 const int mmu_idx = s390x_env_mmu_index(env, false);
363 S390Access srca1, srca2, desta;
364 uint32_t i;
365 uint8_t c = 0;
366
367 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
368 __func__, l, dest, src);
369
370 /* NC always processes one more byte than specified - maximum is 256 */
371 l++;
372
373 access_prepare(&srca1, env, src, l, MMU_DATA_LOAD, mmu_idx, ra);
374 access_prepare(&srca2, env, dest, l, MMU_DATA_LOAD, mmu_idx, ra);
375 access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra);
376 for (i = 0; i < l; i++) {
377 const uint8_t x = access_get_byte(env, &srca1, i, ra) &
378 access_get_byte(env, &srca2, i, ra);
379
380 c |= x;
381 access_set_byte(env, &desta, i, x, ra);
382 }
383 return c != 0;
384 }
385
HELPER(nc)386 uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, uint64_t dest,
387 uint64_t src)
388 {
389 return do_helper_nc(env, l, dest, src, GETPC());
390 }
391
392 /* xor on array */
do_helper_xc(CPUS390XState * env,uint32_t l,uint64_t dest,uint64_t src,uintptr_t ra)393 static uint32_t do_helper_xc(CPUS390XState *env, uint32_t l, uint64_t dest,
394 uint64_t src, uintptr_t ra)
395 {
396 const int mmu_idx = s390x_env_mmu_index(env, false);
397 S390Access srca1, srca2, desta;
398 uint32_t i;
399 uint8_t c = 0;
400
401 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
402 __func__, l, dest, src);
403
404 /* XC always processes one more byte than specified - maximum is 256 */
405 l++;
406
407 access_prepare(&srca1, env, src, l, MMU_DATA_LOAD, mmu_idx, ra);
408 access_prepare(&srca2, env, dest, l, MMU_DATA_LOAD, mmu_idx, ra);
409 access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra);
410
411 /* xor with itself is the same as memset(0) */
412 if (src == dest) {
413 access_memset(env, &desta, 0, ra);
414 return 0;
415 }
416
417 for (i = 0; i < l; i++) {
418 const uint8_t x = access_get_byte(env, &srca1, i, ra) ^
419 access_get_byte(env, &srca2, i, ra);
420
421 c |= x;
422 access_set_byte(env, &desta, i, x, ra);
423 }
424 return c != 0;
425 }
426
HELPER(xc)427 uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest,
428 uint64_t src)
429 {
430 return do_helper_xc(env, l, dest, src, GETPC());
431 }
432
433 /* or on array */
do_helper_oc(CPUS390XState * env,uint32_t l,uint64_t dest,uint64_t src,uintptr_t ra)434 static uint32_t do_helper_oc(CPUS390XState *env, uint32_t l, uint64_t dest,
435 uint64_t src, uintptr_t ra)
436 {
437 const int mmu_idx = s390x_env_mmu_index(env, false);
438 S390Access srca1, srca2, desta;
439 uint32_t i;
440 uint8_t c = 0;
441
442 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
443 __func__, l, dest, src);
444
445 /* OC always processes one more byte than specified - maximum is 256 */
446 l++;
447
448 access_prepare(&srca1, env, src, l, MMU_DATA_LOAD, mmu_idx, ra);
449 access_prepare(&srca2, env, dest, l, MMU_DATA_LOAD, mmu_idx, ra);
450 access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra);
451 for (i = 0; i < l; i++) {
452 const uint8_t x = access_get_byte(env, &srca1, i, ra) |
453 access_get_byte(env, &srca2, i, ra);
454
455 c |= x;
456 access_set_byte(env, &desta, i, x, ra);
457 }
458 return c != 0;
459 }
460
HELPER(oc)461 uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest,
462 uint64_t src)
463 {
464 return do_helper_oc(env, l, dest, src, GETPC());
465 }
466
467 /* memmove */
do_helper_mvc(CPUS390XState * env,uint32_t l,uint64_t dest,uint64_t src,uintptr_t ra)468 static uint32_t do_helper_mvc(CPUS390XState *env, uint32_t l, uint64_t dest,
469 uint64_t src, uintptr_t ra)
470 {
471 const int mmu_idx = s390x_env_mmu_index(env, false);
472 S390Access srca, desta;
473 uint32_t i;
474
475 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
476 __func__, l, dest, src);
477
478 /* MVC always copies one more byte than specified - maximum is 256 */
479 l++;
480
481 access_prepare(&srca, env, src, l, MMU_DATA_LOAD, mmu_idx, ra);
482 access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra);
483
484 /*
485 * "When the operands overlap, the result is obtained as if the operands
486 * were processed one byte at a time". Only non-destructive overlaps
487 * behave like memmove().
488 */
489 if (dest == src + 1) {
490 access_memset(env, &desta, access_get_byte(env, &srca, 0, ra), ra);
491 } else if (!is_destructive_overlap(env, dest, src, l)) {
492 access_memmove(env, &desta, &srca, ra);
493 } else {
494 for (i = 0; i < l; i++) {
495 uint8_t byte = access_get_byte(env, &srca, i, ra);
496
497 access_set_byte(env, &desta, i, byte, ra);
498 }
499 }
500
501 return env->cc_op;
502 }
503
HELPER(mvc)504 void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
505 {
506 do_helper_mvc(env, l, dest, src, GETPC());
507 }
508
509 /* move right to left */
HELPER(mvcrl)510 void HELPER(mvcrl)(CPUS390XState *env, uint64_t l, uint64_t dest, uint64_t src)
511 {
512 const int mmu_idx = s390x_env_mmu_index(env, false);
513 const uint64_t ra = GETPC();
514 S390Access srca, desta;
515 int32_t i;
516
517 /* MVCRL always copies one more byte than specified - maximum is 256 */
518 l &= 0xff;
519 l++;
520
521 access_prepare(&srca, env, src, l, MMU_DATA_LOAD, mmu_idx, ra);
522 access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra);
523
524 for (i = l - 1; i >= 0; i--) {
525 uint8_t byte = access_get_byte(env, &srca, i, ra);
526 access_set_byte(env, &desta, i, byte, ra);
527 }
528 }
529
530 /* move inverse */
HELPER(mvcin)531 void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
532 {
533 const int mmu_idx = s390x_env_mmu_index(env, false);
534 S390Access srca, desta;
535 uintptr_t ra = GETPC();
536 int i;
537
538 /* MVCIN always copies one more byte than specified - maximum is 256 */
539 l++;
540
541 src = wrap_address(env, src - l + 1);
542 access_prepare(&srca, env, src, l, MMU_DATA_LOAD, mmu_idx, ra);
543 access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra);
544 for (i = 0; i < l; i++) {
545 const uint8_t x = access_get_byte(env, &srca, l - i - 1, ra);
546
547 access_set_byte(env, &desta, i, x, ra);
548 }
549 }
550
551 /* move numerics */
HELPER(mvn)552 void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
553 {
554 const int mmu_idx = s390x_env_mmu_index(env, false);
555 S390Access srca1, srca2, desta;
556 uintptr_t ra = GETPC();
557 int i;
558
559 /* MVN always copies one more byte than specified - maximum is 256 */
560 l++;
561
562 access_prepare(&srca1, env, src, l, MMU_DATA_LOAD, mmu_idx, ra);
563 access_prepare(&srca2, env, dest, l, MMU_DATA_LOAD, mmu_idx, ra);
564 access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra);
565 for (i = 0; i < l; i++) {
566 const uint8_t x = (access_get_byte(env, &srca1, i, ra) & 0x0f) |
567 (access_get_byte(env, &srca2, i, ra) & 0xf0);
568
569 access_set_byte(env, &desta, i, x, ra);
570 }
571 }
572
573 /* move with offset */
HELPER(mvo)574 void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
575 {
576 const int mmu_idx = s390x_env_mmu_index(env, false);
577 /* MVO always processes one more byte than specified - maximum is 16 */
578 const int len_dest = (l >> 4) + 1;
579 const int len_src = (l & 0xf) + 1;
580 uintptr_t ra = GETPC();
581 uint8_t byte_dest, byte_src;
582 S390Access srca, desta;
583 int i, j;
584
585 access_prepare(&srca, env, src, len_src, MMU_DATA_LOAD, mmu_idx, ra);
586 access_prepare(&desta, env, dest, len_dest, MMU_DATA_STORE, mmu_idx, ra);
587
588 /* Handle rightmost byte */
589 byte_dest = cpu_ldub_data_ra(env, dest + len_dest - 1, ra);
590 byte_src = access_get_byte(env, &srca, len_src - 1, ra);
591 byte_dest = (byte_dest & 0x0f) | (byte_src << 4);
592 access_set_byte(env, &desta, len_dest - 1, byte_dest, ra);
593
594 /* Process remaining bytes from right to left */
595 for (i = len_dest - 2, j = len_src - 2; i >= 0; i--, j--) {
596 byte_dest = byte_src >> 4;
597 if (j >= 0) {
598 byte_src = access_get_byte(env, &srca, j, ra);
599 } else {
600 byte_src = 0;
601 }
602 byte_dest |= byte_src << 4;
603 access_set_byte(env, &desta, i, byte_dest, ra);
604 }
605 }
606
607 /* move zones */
HELPER(mvz)608 void HELPER(mvz)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
609 {
610 const int mmu_idx = s390x_env_mmu_index(env, false);
611 S390Access srca1, srca2, desta;
612 uintptr_t ra = GETPC();
613 int i;
614
615 /* MVZ always copies one more byte than specified - maximum is 256 */
616 l++;
617
618 access_prepare(&srca1, env, src, l, MMU_DATA_LOAD, mmu_idx, ra);
619 access_prepare(&srca2, env, dest, l, MMU_DATA_LOAD, mmu_idx, ra);
620 access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra);
621 for (i = 0; i < l; i++) {
622 const uint8_t x = (access_get_byte(env, &srca1, i, ra) & 0xf0) |
623 (access_get_byte(env, &srca2, i, ra) & 0x0f);
624
625 access_set_byte(env, &desta, i, x, ra);
626 }
627 }
628
629 /* compare unsigned byte arrays */
do_helper_clc(CPUS390XState * env,uint32_t l,uint64_t s1,uint64_t s2,uintptr_t ra)630 static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1,
631 uint64_t s2, uintptr_t ra)
632 {
633 uint32_t i;
634 uint32_t cc = 0;
635
636 HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n",
637 __func__, l, s1, s2);
638
639 for (i = 0; i <= l; i++) {
640 uint8_t x = cpu_ldub_data_ra(env, s1 + i, ra);
641 uint8_t y = cpu_ldub_data_ra(env, s2 + i, ra);
642 HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y);
643 if (x < y) {
644 cc = 1;
645 break;
646 } else if (x > y) {
647 cc = 2;
648 break;
649 }
650 }
651
652 HELPER_LOG("\n");
653 return cc;
654 }
655
HELPER(clc)656 uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2)
657 {
658 return do_helper_clc(env, l, s1, s2, GETPC());
659 }
660
661 /* compare logical under mask */
HELPER(clm)662 uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
663 uint64_t addr)
664 {
665 uintptr_t ra = GETPC();
666 uint32_t cc = 0;
667
668 HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1,
669 mask, addr);
670
671 if (!mask) {
672 /* Recognize access exceptions for the first byte */
673 probe_read(env, addr, 1, s390x_env_mmu_index(env, false), ra);
674 }
675
676 while (mask) {
677 if (mask & 8) {
678 uint8_t d = cpu_ldub_data_ra(env, addr, ra);
679 uint8_t r = extract32(r1, 24, 8);
680 HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d,
681 addr);
682 if (r < d) {
683 cc = 1;
684 break;
685 } else if (r > d) {
686 cc = 2;
687 break;
688 }
689 addr++;
690 }
691 mask = (mask << 1) & 0xf;
692 r1 <<= 8;
693 }
694
695 HELPER_LOG("\n");
696 return cc;
697 }
698
get_address(CPUS390XState * env,int reg)699 static inline uint64_t get_address(CPUS390XState *env, int reg)
700 {
701 return wrap_address(env, env->regs[reg]);
702 }
703
704 /*
705 * Store the address to the given register, zeroing out unused leftmost
706 * bits in bit positions 32-63 (24-bit and 31-bit mode only).
707 */
set_address_zero(CPUS390XState * env,int reg,uint64_t address)708 static inline void set_address_zero(CPUS390XState *env, int reg,
709 uint64_t address)
710 {
711 if (env->psw.mask & PSW_MASK_64) {
712 env->regs[reg] = address;
713 } else {
714 if (!(env->psw.mask & PSW_MASK_32)) {
715 address &= 0x00ffffff;
716 } else {
717 address &= 0x7fffffff;
718 }
719 env->regs[reg] = deposit64(env->regs[reg], 0, 32, address);
720 }
721 }
722
set_address(CPUS390XState * env,int reg,uint64_t address)723 static inline void set_address(CPUS390XState *env, int reg, uint64_t address)
724 {
725 if (env->psw.mask & PSW_MASK_64) {
726 /* 64-Bit mode */
727 env->regs[reg] = address;
728 } else {
729 if (!(env->psw.mask & PSW_MASK_32)) {
730 /* 24-Bit mode. According to the PoO it is implementation
731 dependent if bits 32-39 remain unchanged or are set to
732 zeros. Choose the former so that the function can also be
733 used for TRT. */
734 env->regs[reg] = deposit64(env->regs[reg], 0, 24, address);
735 } else {
736 /* 31-Bit mode. According to the PoO it is implementation
737 dependent if bit 32 remains unchanged or is set to zero.
738 Choose the latter so that the function can also be used for
739 TRT. */
740 address &= 0x7fffffff;
741 env->regs[reg] = deposit64(env->regs[reg], 0, 32, address);
742 }
743 }
744 }
745
wrap_length32(CPUS390XState * env,uint64_t length)746 static inline uint64_t wrap_length32(CPUS390XState *env, uint64_t length)
747 {
748 if (!(env->psw.mask & PSW_MASK_64)) {
749 return (uint32_t)length;
750 }
751 return length;
752 }
753
wrap_length31(CPUS390XState * env,uint64_t length)754 static inline uint64_t wrap_length31(CPUS390XState *env, uint64_t length)
755 {
756 if (!(env->psw.mask & PSW_MASK_64)) {
757 /* 24-Bit and 31-Bit mode */
758 length &= 0x7fffffff;
759 }
760 return length;
761 }
762
get_length(CPUS390XState * env,int reg)763 static inline uint64_t get_length(CPUS390XState *env, int reg)
764 {
765 return wrap_length31(env, env->regs[reg]);
766 }
767
set_length(CPUS390XState * env,int reg,uint64_t length)768 static inline void set_length(CPUS390XState *env, int reg, uint64_t length)
769 {
770 if (env->psw.mask & PSW_MASK_64) {
771 /* 64-Bit mode */
772 env->regs[reg] = length;
773 } else {
774 /* 24-Bit and 31-Bit mode */
775 env->regs[reg] = deposit64(env->regs[reg], 0, 32, length);
776 }
777 }
778
779 /* search string (c is byte to search, r2 is string, r1 end of string) */
HELPER(srst)780 void HELPER(srst)(CPUS390XState *env, uint32_t r1, uint32_t r2)
781 {
782 uintptr_t ra = GETPC();
783 uint64_t end, str;
784 uint32_t len;
785 uint8_t v, c = env->regs[0];
786
787 /* Bits 32-55 must contain all 0. */
788 if (env->regs[0] & 0xffffff00u) {
789 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
790 }
791
792 str = get_address(env, r2);
793 end = get_address(env, r1);
794
795 /* Lest we fail to service interrupts in a timely manner, limit the
796 amount of work we're willing to do. For now, let's cap at 8k. */
797 for (len = 0; len < 0x2000; ++len) {
798 if (str + len == end) {
799 /* Character not found. R1 & R2 are unmodified. */
800 env->cc_op = 2;
801 return;
802 }
803 v = cpu_ldub_data_ra(env, str + len, ra);
804 if (v == c) {
805 /* Character found. Set R1 to the location; R2 is unmodified. */
806 env->cc_op = 1;
807 set_address(env, r1, str + len);
808 return;
809 }
810 }
811
812 /* CPU-determined bytes processed. Advance R2 to next byte to process. */
813 env->cc_op = 3;
814 set_address(env, r2, str + len);
815 }
816
HELPER(srstu)817 void HELPER(srstu)(CPUS390XState *env, uint32_t r1, uint32_t r2)
818 {
819 uintptr_t ra = GETPC();
820 uint32_t len;
821 uint16_t v, c = env->regs[0];
822 uint64_t end, str, adj_end;
823
824 /* Bits 32-47 of R0 must be zero. */
825 if (env->regs[0] & 0xffff0000u) {
826 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
827 }
828
829 str = get_address(env, r2);
830 end = get_address(env, r1);
831
832 /* If the LSB of the two addresses differ, use one extra byte. */
833 adj_end = end + ((str ^ end) & 1);
834
835 /* Lest we fail to service interrupts in a timely manner, limit the
836 amount of work we're willing to do. For now, let's cap at 8k. */
837 for (len = 0; len < 0x2000; len += 2) {
838 if (str + len == adj_end) {
839 /* End of input found. */
840 env->cc_op = 2;
841 return;
842 }
843 v = cpu_lduw_data_ra(env, str + len, ra);
844 if (v == c) {
845 /* Character found. Set R1 to the location; R2 is unmodified. */
846 env->cc_op = 1;
847 set_address(env, r1, str + len);
848 return;
849 }
850 }
851
852 /* CPU-determined bytes processed. Advance R2 to next byte to process. */
853 env->cc_op = 3;
854 set_address(env, r2, str + len);
855 }
856
857 /* unsigned string compare (c is string terminator) */
HELPER(clst)858 Int128 HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2)
859 {
860 uintptr_t ra = GETPC();
861 uint32_t len;
862
863 c = c & 0xff;
864 s1 = wrap_address(env, s1);
865 s2 = wrap_address(env, s2);
866
867 /* Lest we fail to service interrupts in a timely manner, limit the
868 amount of work we're willing to do. For now, let's cap at 8k. */
869 for (len = 0; len < 0x2000; ++len) {
870 uint8_t v1 = cpu_ldub_data_ra(env, s1 + len, ra);
871 uint8_t v2 = cpu_ldub_data_ra(env, s2 + len, ra);
872 if (v1 == v2) {
873 if (v1 == c) {
874 /* Equal. CC=0, and don't advance the registers. */
875 env->cc_op = 0;
876 return int128_make128(s2, s1);
877 }
878 } else {
879 /* Unequal. CC={1,2}, and advance the registers. Note that
880 the terminator need not be zero, but the string that contains
881 the terminator is by definition "low". */
882 env->cc_op = (v1 == c ? 1 : v2 == c ? 2 : v1 < v2 ? 1 : 2);
883 return int128_make128(s2 + len, s1 + len);
884 }
885 }
886
887 /* CPU-determined bytes equal; advance the registers. */
888 env->cc_op = 3;
889 return int128_make128(s2 + len, s1 + len);
890 }
891
892 /* move page */
HELPER(mvpg)893 uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint32_t r1, uint32_t r2)
894 {
895 const uint64_t src = get_address(env, r2) & TARGET_PAGE_MASK;
896 const uint64_t dst = get_address(env, r1) & TARGET_PAGE_MASK;
897 const int mmu_idx = s390x_env_mmu_index(env, false);
898 const bool f = extract64(r0, 11, 1);
899 const bool s = extract64(r0, 10, 1);
900 const bool cco = extract64(r0, 8, 1);
901 uintptr_t ra = GETPC();
902 S390Access srca, desta;
903 int exc;
904
905 if ((f && s) || extract64(r0, 12, 4)) {
906 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
907 }
908
909 /*
910 * We always manually handle exceptions such that we can properly store
911 * r1/r2 to the lowcore on page-translation exceptions.
912 *
913 * TODO: Access key handling
914 */
915 exc = access_prepare_nf(&srca, env, true, src, TARGET_PAGE_SIZE,
916 MMU_DATA_LOAD, mmu_idx, ra);
917 if (exc) {
918 if (cco) {
919 return 2;
920 }
921 goto inject_exc;
922 }
923 exc = access_prepare_nf(&desta, env, true, dst, TARGET_PAGE_SIZE,
924 MMU_DATA_STORE, mmu_idx, ra);
925 if (exc) {
926 if (cco && exc != PGM_PROTECTION) {
927 return 1;
928 }
929 goto inject_exc;
930 }
931 access_memmove(env, &desta, &srca, ra);
932 return 0; /* data moved */
933 inject_exc:
934 #if !defined(CONFIG_USER_ONLY)
935 if (exc != PGM_ADDRESSING) {
936 stq_phys(env_cpu(env)->as, env->psa + offsetof(LowCore, trans_exc_code),
937 env->tlb_fill_tec);
938 }
939 if (exc == PGM_PAGE_TRANS) {
940 stb_phys(env_cpu(env)->as, env->psa + offsetof(LowCore, op_access_id),
941 r1 << 4 | r2);
942 }
943 #endif
944 tcg_s390_program_interrupt(env, exc, ra);
945 }
946
947 /* string copy */
HELPER(mvst)948 uint32_t HELPER(mvst)(CPUS390XState *env, uint32_t r1, uint32_t r2)
949 {
950 const int mmu_idx = s390x_env_mmu_index(env, false);
951 const uint64_t d = get_address(env, r1);
952 const uint64_t s = get_address(env, r2);
953 const uint8_t c = env->regs[0];
954 const int len = MIN(-(d | TARGET_PAGE_MASK), -(s | TARGET_PAGE_MASK));
955 S390Access srca, desta;
956 uintptr_t ra = GETPC();
957 int i;
958
959 if (env->regs[0] & 0xffffff00ull) {
960 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
961 }
962
963 /*
964 * Our access should not exceed single pages, as we must not report access
965 * exceptions exceeding the actually copied range (which we don't know at
966 * this point). We might over-indicate watchpoints within the pages
967 * (if we ever care, we have to limit processing to a single byte).
968 */
969 access_prepare(&srca, env, s, len, MMU_DATA_LOAD, mmu_idx, ra);
970 access_prepare(&desta, env, d, len, MMU_DATA_STORE, mmu_idx, ra);
971 for (i = 0; i < len; i++) {
972 const uint8_t v = access_get_byte(env, &srca, i, ra);
973
974 access_set_byte(env, &desta, i, v, ra);
975 if (v == c) {
976 set_address_zero(env, r1, d + i);
977 return 1;
978 }
979 }
980 set_address_zero(env, r1, d + len);
981 set_address_zero(env, r2, s + len);
982 return 3;
983 }
984
985 /* load access registers r1 to r3 from memory at a2 */
HELPER(lam)986 void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
987 {
988 uintptr_t ra = GETPC();
989 int i;
990
991 if (a2 & 0x3) {
992 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
993 }
994
995 for (i = r1;; i = (i + 1) % 16) {
996 env->aregs[i] = cpu_ldl_data_ra(env, a2, ra);
997 a2 += 4;
998
999 if (i == r3) {
1000 break;
1001 }
1002 }
1003 }
1004
1005 /* store access registers r1 to r3 in memory at a2 */
HELPER(stam)1006 void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
1007 {
1008 uintptr_t ra = GETPC();
1009 int i;
1010
1011 if (a2 & 0x3) {
1012 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
1013 }
1014
1015 for (i = r1;; i = (i + 1) % 16) {
1016 cpu_stl_data_ra(env, a2, env->aregs[i], ra);
1017 a2 += 4;
1018
1019 if (i == r3) {
1020 break;
1021 }
1022 }
1023 }
1024
1025 /* move long helper */
do_mvcl(CPUS390XState * env,uint64_t * dest,uint64_t * destlen,uint64_t * src,uint64_t * srclen,uint16_t pad,int wordsize,uintptr_t ra)1026 static inline uint32_t do_mvcl(CPUS390XState *env,
1027 uint64_t *dest, uint64_t *destlen,
1028 uint64_t *src, uint64_t *srclen,
1029 uint16_t pad, int wordsize, uintptr_t ra)
1030 {
1031 const int mmu_idx = s390x_env_mmu_index(env, false);
1032 int len = MIN(*destlen, -(*dest | TARGET_PAGE_MASK));
1033 S390Access srca, desta;
1034 int i, cc;
1035
1036 if (*destlen == *srclen) {
1037 cc = 0;
1038 } else if (*destlen < *srclen) {
1039 cc = 1;
1040 } else {
1041 cc = 2;
1042 }
1043
1044 if (!*destlen) {
1045 return cc;
1046 }
1047
1048 /*
1049 * Only perform one type of type of operation (move/pad) at a time.
1050 * Stay within single pages.
1051 */
1052 if (*srclen) {
1053 /* Copy the src array */
1054 len = MIN(MIN(*srclen, -(*src | TARGET_PAGE_MASK)), len);
1055 *destlen -= len;
1056 *srclen -= len;
1057 access_prepare(&srca, env, *src, len, MMU_DATA_LOAD, mmu_idx, ra);
1058 access_prepare(&desta, env, *dest, len, MMU_DATA_STORE, mmu_idx, ra);
1059 access_memmove(env, &desta, &srca, ra);
1060 *src = wrap_address(env, *src + len);
1061 *dest = wrap_address(env, *dest + len);
1062 } else if (wordsize == 1) {
1063 /* Pad the remaining area */
1064 *destlen -= len;
1065 access_prepare(&desta, env, *dest, len, MMU_DATA_STORE, mmu_idx, ra);
1066 access_memset(env, &desta, pad, ra);
1067 *dest = wrap_address(env, *dest + len);
1068 } else {
1069 access_prepare(&desta, env, *dest, len, MMU_DATA_STORE, mmu_idx, ra);
1070
1071 /* The remaining length selects the padding byte. */
1072 for (i = 0; i < len; (*destlen)--, i++) {
1073 if (*destlen & 1) {
1074 access_set_byte(env, &desta, i, pad, ra);
1075 } else {
1076 access_set_byte(env, &desta, i, pad >> 8, ra);
1077 }
1078 }
1079 *dest = wrap_address(env, *dest + len);
1080 }
1081
1082 return *destlen ? 3 : cc;
1083 }
1084
1085 /* move long */
HELPER(mvcl)1086 uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2)
1087 {
1088 const int mmu_idx = s390x_env_mmu_index(env, false);
1089 uintptr_t ra = GETPC();
1090 uint64_t destlen = env->regs[r1 + 1] & 0xffffff;
1091 uint64_t dest = get_address(env, r1);
1092 uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
1093 uint64_t src = get_address(env, r2);
1094 uint8_t pad = env->regs[r2 + 1] >> 24;
1095 CPUState *cs = env_cpu(env);
1096 S390Access srca, desta;
1097 uint32_t cc, cur_len;
1098
1099 if (is_destructive_overlap(env, dest, src, MIN(srclen, destlen))) {
1100 cc = 3;
1101 } else if (srclen == destlen) {
1102 cc = 0;
1103 } else if (destlen < srclen) {
1104 cc = 1;
1105 } else {
1106 cc = 2;
1107 }
1108
1109 /* We might have to zero-out some bits even if there was no action. */
1110 if (unlikely(!destlen || cc == 3)) {
1111 set_address_zero(env, r2, src);
1112 set_address_zero(env, r1, dest);
1113 return cc;
1114 } else if (!srclen) {
1115 set_address_zero(env, r2, src);
1116 }
1117
1118 /*
1119 * Only perform one type of type of operation (move/pad) in one step.
1120 * Stay within single pages.
1121 */
1122 while (destlen) {
1123 cur_len = MIN(destlen, -(dest | TARGET_PAGE_MASK));
1124 if (!srclen) {
1125 access_prepare(&desta, env, dest, cur_len,
1126 MMU_DATA_STORE, mmu_idx, ra);
1127 access_memset(env, &desta, pad, ra);
1128 } else {
1129 cur_len = MIN(MIN(srclen, -(src | TARGET_PAGE_MASK)), cur_len);
1130
1131 access_prepare(&srca, env, src, cur_len,
1132 MMU_DATA_LOAD, mmu_idx, ra);
1133 access_prepare(&desta, env, dest, cur_len,
1134 MMU_DATA_STORE, mmu_idx, ra);
1135 access_memmove(env, &desta, &srca, ra);
1136 src = wrap_address(env, src + cur_len);
1137 srclen -= cur_len;
1138 env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen);
1139 set_address_zero(env, r2, src);
1140 }
1141 dest = wrap_address(env, dest + cur_len);
1142 destlen -= cur_len;
1143 env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen);
1144 set_address_zero(env, r1, dest);
1145
1146 /*
1147 * MVCL is interruptible. Return to the main loop if requested after
1148 * writing back all state to registers. If no interrupt will get
1149 * injected, we'll end up back in this handler and continue processing
1150 * the remaining parts.
1151 */
1152 if (destlen && unlikely(cpu_loop_exit_requested(cs))) {
1153 cpu_loop_exit_restore(cs, ra);
1154 }
1155 }
1156 return cc;
1157 }
1158
1159 /* move long extended */
HELPER(mvcle)1160 uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2,
1161 uint32_t r3)
1162 {
1163 uintptr_t ra = GETPC();
1164 uint64_t destlen = get_length(env, r1 + 1);
1165 uint64_t dest = get_address(env, r1);
1166 uint64_t srclen = get_length(env, r3 + 1);
1167 uint64_t src = get_address(env, r3);
1168 uint8_t pad = a2;
1169 uint32_t cc;
1170
1171 cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, 1, ra);
1172
1173 set_length(env, r1 + 1, destlen);
1174 set_length(env, r3 + 1, srclen);
1175 set_address(env, r1, dest);
1176 set_address(env, r3, src);
1177
1178 return cc;
1179 }
1180
1181 /* move long unicode */
HELPER(mvclu)1182 uint32_t HELPER(mvclu)(CPUS390XState *env, uint32_t r1, uint64_t a2,
1183 uint32_t r3)
1184 {
1185 uintptr_t ra = GETPC();
1186 uint64_t destlen = get_length(env, r1 + 1);
1187 uint64_t dest = get_address(env, r1);
1188 uint64_t srclen = get_length(env, r3 + 1);
1189 uint64_t src = get_address(env, r3);
1190 uint16_t pad = a2;
1191 uint32_t cc;
1192
1193 cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, 2, ra);
1194
1195 set_length(env, r1 + 1, destlen);
1196 set_length(env, r3 + 1, srclen);
1197 set_address(env, r1, dest);
1198 set_address(env, r3, src);
1199
1200 return cc;
1201 }
1202
1203 /* compare logical long helper */
do_clcl(CPUS390XState * env,uint64_t * src1,uint64_t * src1len,uint64_t * src3,uint64_t * src3len,uint16_t pad,uint64_t limit,int wordsize,uintptr_t ra)1204 static inline uint32_t do_clcl(CPUS390XState *env,
1205 uint64_t *src1, uint64_t *src1len,
1206 uint64_t *src3, uint64_t *src3len,
1207 uint16_t pad, uint64_t limit,
1208 int wordsize, uintptr_t ra)
1209 {
1210 uint64_t len = MAX(*src1len, *src3len);
1211 uint32_t cc = 0;
1212
1213 check_alignment(env, *src1len | *src3len, wordsize, ra);
1214
1215 if (!len) {
1216 return cc;
1217 }
1218
1219 /* Lest we fail to service interrupts in a timely manner, limit the
1220 amount of work we're willing to do. */
1221 if (len > limit) {
1222 len = limit;
1223 cc = 3;
1224 }
1225
1226 for (; len; len -= wordsize) {
1227 uint16_t v1 = pad;
1228 uint16_t v3 = pad;
1229
1230 if (*src1len) {
1231 v1 = cpu_ldusize_data_ra(env, *src1, wordsize, ra);
1232 }
1233 if (*src3len) {
1234 v3 = cpu_ldusize_data_ra(env, *src3, wordsize, ra);
1235 }
1236
1237 if (v1 != v3) {
1238 cc = (v1 < v3) ? 1 : 2;
1239 break;
1240 }
1241
1242 if (*src1len) {
1243 *src1 += wordsize;
1244 *src1len -= wordsize;
1245 }
1246 if (*src3len) {
1247 *src3 += wordsize;
1248 *src3len -= wordsize;
1249 }
1250 }
1251
1252 return cc;
1253 }
1254
1255
1256 /* compare logical long */
HELPER(clcl)1257 uint32_t HELPER(clcl)(CPUS390XState *env, uint32_t r1, uint32_t r2)
1258 {
1259 uintptr_t ra = GETPC();
1260 uint64_t src1len = extract64(env->regs[r1 + 1], 0, 24);
1261 uint64_t src1 = get_address(env, r1);
1262 uint64_t src3len = extract64(env->regs[r2 + 1], 0, 24);
1263 uint64_t src3 = get_address(env, r2);
1264 uint8_t pad = env->regs[r2 + 1] >> 24;
1265 uint32_t cc;
1266
1267 cc = do_clcl(env, &src1, &src1len, &src3, &src3len, pad, -1, 1, ra);
1268
1269 env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, src1len);
1270 env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, src3len);
1271 set_address(env, r1, src1);
1272 set_address(env, r2, src3);
1273
1274 return cc;
1275 }
1276
1277 /* compare logical long extended memcompare insn with padding */
HELPER(clcle)1278 uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2,
1279 uint32_t r3)
1280 {
1281 uintptr_t ra = GETPC();
1282 uint64_t src1len = get_length(env, r1 + 1);
1283 uint64_t src1 = get_address(env, r1);
1284 uint64_t src3len = get_length(env, r3 + 1);
1285 uint64_t src3 = get_address(env, r3);
1286 uint8_t pad = a2;
1287 uint32_t cc;
1288
1289 cc = do_clcl(env, &src1, &src1len, &src3, &src3len, pad, 0x2000, 1, ra);
1290
1291 set_length(env, r1 + 1, src1len);
1292 set_length(env, r3 + 1, src3len);
1293 set_address(env, r1, src1);
1294 set_address(env, r3, src3);
1295
1296 return cc;
1297 }
1298
1299 /* compare logical long unicode memcompare insn with padding */
HELPER(clclu)1300 uint32_t HELPER(clclu)(CPUS390XState *env, uint32_t r1, uint64_t a2,
1301 uint32_t r3)
1302 {
1303 uintptr_t ra = GETPC();
1304 uint64_t src1len = get_length(env, r1 + 1);
1305 uint64_t src1 = get_address(env, r1);
1306 uint64_t src3len = get_length(env, r3 + 1);
1307 uint64_t src3 = get_address(env, r3);
1308 uint16_t pad = a2;
1309 uint32_t cc = 0;
1310
1311 cc = do_clcl(env, &src1, &src1len, &src3, &src3len, pad, 0x1000, 2, ra);
1312
1313 set_length(env, r1 + 1, src1len);
1314 set_length(env, r3 + 1, src3len);
1315 set_address(env, r1, src1);
1316 set_address(env, r3, src3);
1317
1318 return cc;
1319 }
1320
1321 /* checksum */
HELPER(cksm)1322 Int128 HELPER(cksm)(CPUS390XState *env, uint64_t r1,
1323 uint64_t src, uint64_t src_len)
1324 {
1325 uintptr_t ra = GETPC();
1326 uint64_t max_len, len;
1327 uint64_t cksm = (uint32_t)r1;
1328
1329 /* Lest we fail to service interrupts in a timely manner, limit the
1330 amount of work we're willing to do. For now, let's cap at 8k. */
1331 max_len = (src_len > 0x2000 ? 0x2000 : src_len);
1332
1333 /* Process full words as available. */
1334 for (len = 0; len + 4 <= max_len; len += 4, src += 4) {
1335 cksm += (uint32_t)cpu_ldl_data_ra(env, src, ra);
1336 }
1337
1338 switch (max_len - len) {
1339 case 1:
1340 cksm += cpu_ldub_data_ra(env, src, ra) << 24;
1341 len += 1;
1342 break;
1343 case 2:
1344 cksm += cpu_lduw_data_ra(env, src, ra) << 16;
1345 len += 2;
1346 break;
1347 case 3:
1348 cksm += cpu_lduw_data_ra(env, src, ra) << 16;
1349 cksm += cpu_ldub_data_ra(env, src + 2, ra) << 8;
1350 len += 3;
1351 break;
1352 }
1353
1354 /* Fold the carry from the checksum. Note that we can see carry-out
1355 during folding more than once (but probably not more than twice). */
1356 while (cksm > 0xffffffffull) {
1357 cksm = (uint32_t)cksm + (cksm >> 32);
1358 }
1359
1360 /* Indicate whether or not we've processed everything. */
1361 env->cc_op = (len == src_len ? 0 : 3);
1362
1363 /* Return both cksm and processed length. */
1364 return int128_make128(cksm, len);
1365 }
1366
HELPER(pack)1367 void HELPER(pack)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src)
1368 {
1369 uintptr_t ra = GETPC();
1370 int len_dest = len >> 4;
1371 int len_src = len & 0xf;
1372 uint8_t b;
1373
1374 dest += len_dest;
1375 src += len_src;
1376
1377 /* last byte is special, it only flips the nibbles */
1378 b = cpu_ldub_data_ra(env, src, ra);
1379 cpu_stb_data_ra(env, dest, (b << 4) | (b >> 4), ra);
1380 src--;
1381 len_src--;
1382
1383 /* now pack every value */
1384 while (len_dest > 0) {
1385 b = 0;
1386
1387 if (len_src >= 0) {
1388 b = cpu_ldub_data_ra(env, src, ra) & 0x0f;
1389 src--;
1390 len_src--;
1391 }
1392 if (len_src >= 0) {
1393 b |= cpu_ldub_data_ra(env, src, ra) << 4;
1394 src--;
1395 len_src--;
1396 }
1397
1398 len_dest--;
1399 dest--;
1400 cpu_stb_data_ra(env, dest, b, ra);
1401 }
1402 }
1403
do_pkau(CPUS390XState * env,uint64_t dest,uint64_t src,uint32_t srclen,int ssize,uintptr_t ra)1404 static inline void do_pkau(CPUS390XState *env, uint64_t dest, uint64_t src,
1405 uint32_t srclen, int ssize, uintptr_t ra)
1406 {
1407 int i;
1408 /* The destination operand is always 16 bytes long. */
1409 const int destlen = 16;
1410
1411 /* The operands are processed from right to left. */
1412 src += srclen - 1;
1413 dest += destlen - 1;
1414
1415 for (i = 0; i < destlen; i++) {
1416 uint8_t b = 0;
1417
1418 /* Start with a positive sign */
1419 if (i == 0) {
1420 b = 0xc;
1421 } else if (srclen > ssize) {
1422 b = cpu_ldub_data_ra(env, src, ra) & 0x0f;
1423 src -= ssize;
1424 srclen -= ssize;
1425 }
1426
1427 if (srclen > ssize) {
1428 b |= cpu_ldub_data_ra(env, src, ra) << 4;
1429 src -= ssize;
1430 srclen -= ssize;
1431 }
1432
1433 cpu_stb_data_ra(env, dest, b, ra);
1434 dest--;
1435 }
1436 }
1437
1438
HELPER(pka)1439 void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src,
1440 uint32_t srclen)
1441 {
1442 do_pkau(env, dest, src, srclen, 1, GETPC());
1443 }
1444
HELPER(pku)1445 void HELPER(pku)(CPUS390XState *env, uint64_t dest, uint64_t src,
1446 uint32_t srclen)
1447 {
1448 do_pkau(env, dest, src, srclen, 2, GETPC());
1449 }
1450
HELPER(unpk)1451 void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest,
1452 uint64_t src)
1453 {
1454 uintptr_t ra = GETPC();
1455 int len_dest = len >> 4;
1456 int len_src = len & 0xf;
1457 uint8_t b;
1458 int second_nibble = 0;
1459
1460 dest += len_dest;
1461 src += len_src;
1462
1463 /* last byte is special, it only flips the nibbles */
1464 b = cpu_ldub_data_ra(env, src, ra);
1465 cpu_stb_data_ra(env, dest, (b << 4) | (b >> 4), ra);
1466 src--;
1467 len_src--;
1468
1469 /* now pad every nibble with 0xf0 */
1470
1471 while (len_dest > 0) {
1472 uint8_t cur_byte = 0;
1473
1474 if (len_src > 0) {
1475 cur_byte = cpu_ldub_data_ra(env, src, ra);
1476 }
1477
1478 len_dest--;
1479 dest--;
1480
1481 /* only advance one nibble at a time */
1482 if (second_nibble) {
1483 cur_byte >>= 4;
1484 len_src--;
1485 src--;
1486 }
1487 second_nibble = !second_nibble;
1488
1489 /* digit */
1490 cur_byte = (cur_byte & 0xf);
1491 /* zone bits */
1492 cur_byte |= 0xf0;
1493
1494 cpu_stb_data_ra(env, dest, cur_byte, ra);
1495 }
1496 }
1497
do_unpkau(CPUS390XState * env,uint64_t dest,uint32_t destlen,int dsize,uint64_t src,uintptr_t ra)1498 static inline uint32_t do_unpkau(CPUS390XState *env, uint64_t dest,
1499 uint32_t destlen, int dsize, uint64_t src,
1500 uintptr_t ra)
1501 {
1502 int i;
1503 uint32_t cc;
1504 uint8_t b;
1505 /* The source operand is always 16 bytes long. */
1506 const int srclen = 16;
1507
1508 /* The operands are processed from right to left. */
1509 src += srclen - 1;
1510 dest += destlen - dsize;
1511
1512 /* Check for the sign. */
1513 b = cpu_ldub_data_ra(env, src, ra);
1514 src--;
1515 switch (b & 0xf) {
1516 case 0xa:
1517 case 0xc:
1518 case 0xe ... 0xf:
1519 cc = 0; /* plus */
1520 break;
1521 case 0xb:
1522 case 0xd:
1523 cc = 1; /* minus */
1524 break;
1525 default:
1526 case 0x0 ... 0x9:
1527 cc = 3; /* invalid */
1528 break;
1529 }
1530
1531 /* Now pad every nibble with 0x30, advancing one nibble at a time. */
1532 for (i = 0; i < destlen; i += dsize) {
1533 if (i == (31 * dsize)) {
1534 /* If length is 32/64 bytes, the leftmost byte is 0. */
1535 b = 0;
1536 } else if (i % (2 * dsize)) {
1537 b = cpu_ldub_data_ra(env, src, ra);
1538 src--;
1539 } else {
1540 b >>= 4;
1541 }
1542 cpu_stsize_data_ra(env, dest, 0x30 + (b & 0xf), dsize, ra);
1543 dest -= dsize;
1544 }
1545
1546 return cc;
1547 }
1548
HELPER(unpka)1549 uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen,
1550 uint64_t src)
1551 {
1552 return do_unpkau(env, dest, destlen, 1, src, GETPC());
1553 }
1554
HELPER(unpku)1555 uint32_t HELPER(unpku)(CPUS390XState *env, uint64_t dest, uint32_t destlen,
1556 uint64_t src)
1557 {
1558 return do_unpkau(env, dest, destlen, 2, src, GETPC());
1559 }
1560
HELPER(tp)1561 uint32_t HELPER(tp)(CPUS390XState *env, uint64_t dest, uint32_t destlen)
1562 {
1563 uintptr_t ra = GETPC();
1564 uint32_t cc = 0;
1565 int i;
1566
1567 for (i = 0; i < destlen; i++) {
1568 uint8_t b = cpu_ldub_data_ra(env, dest + i, ra);
1569 /* digit */
1570 cc |= (b & 0xf0) > 0x90 ? 2 : 0;
1571
1572 if (i == (destlen - 1)) {
1573 /* sign */
1574 cc |= (b & 0xf) < 0xa ? 1 : 0;
1575 } else {
1576 /* digit */
1577 cc |= (b & 0xf) > 0x9 ? 2 : 0;
1578 }
1579 }
1580
1581 return cc;
1582 }
1583
do_helper_tr(CPUS390XState * env,uint32_t len,uint64_t array,uint64_t trans,uintptr_t ra)1584 static uint32_t do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array,
1585 uint64_t trans, uintptr_t ra)
1586 {
1587 uint32_t i;
1588
1589 for (i = 0; i <= len; i++) {
1590 uint8_t byte = cpu_ldub_data_ra(env, array + i, ra);
1591 uint8_t new_byte = cpu_ldub_data_ra(env, trans + byte, ra);
1592 cpu_stb_data_ra(env, array + i, new_byte, ra);
1593 }
1594
1595 return env->cc_op;
1596 }
1597
HELPER(tr)1598 void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array,
1599 uint64_t trans)
1600 {
1601 do_helper_tr(env, len, array, trans, GETPC());
1602 }
1603
HELPER(tre)1604 Int128 HELPER(tre)(CPUS390XState *env, uint64_t array,
1605 uint64_t len, uint64_t trans)
1606 {
1607 uintptr_t ra = GETPC();
1608 uint8_t end = env->regs[0] & 0xff;
1609 uint64_t l = len;
1610 uint64_t i;
1611 uint32_t cc = 0;
1612
1613 if (!(env->psw.mask & PSW_MASK_64)) {
1614 array &= 0x7fffffff;
1615 l = (uint32_t)l;
1616 }
1617
1618 /* Lest we fail to service interrupts in a timely manner, limit the
1619 amount of work we're willing to do. For now, let's cap at 8k. */
1620 if (l > 0x2000) {
1621 l = 0x2000;
1622 cc = 3;
1623 }
1624
1625 for (i = 0; i < l; i++) {
1626 uint8_t byte, new_byte;
1627
1628 byte = cpu_ldub_data_ra(env, array + i, ra);
1629
1630 if (byte == end) {
1631 cc = 1;
1632 break;
1633 }
1634
1635 new_byte = cpu_ldub_data_ra(env, trans + byte, ra);
1636 cpu_stb_data_ra(env, array + i, new_byte, ra);
1637 }
1638
1639 env->cc_op = cc;
1640 return int128_make128(len - i, array + i);
1641 }
1642
do_helper_trt(CPUS390XState * env,int len,uint64_t array,uint64_t trans,int inc,uintptr_t ra)1643 static inline uint32_t do_helper_trt(CPUS390XState *env, int len,
1644 uint64_t array, uint64_t trans,
1645 int inc, uintptr_t ra)
1646 {
1647 int i;
1648
1649 for (i = 0; i <= len; i++) {
1650 uint8_t byte = cpu_ldub_data_ra(env, array + i * inc, ra);
1651 uint8_t sbyte = cpu_ldub_data_ra(env, trans + byte, ra);
1652
1653 if (sbyte != 0) {
1654 set_address(env, 1, array + i * inc);
1655 env->regs[2] = deposit64(env->regs[2], 0, 8, sbyte);
1656 return (i == len) ? 2 : 1;
1657 }
1658 }
1659
1660 return 0;
1661 }
1662
do_helper_trt_fwd(CPUS390XState * env,uint32_t len,uint64_t array,uint64_t trans,uintptr_t ra)1663 static uint32_t do_helper_trt_fwd(CPUS390XState *env, uint32_t len,
1664 uint64_t array, uint64_t trans,
1665 uintptr_t ra)
1666 {
1667 return do_helper_trt(env, len, array, trans, 1, ra);
1668 }
1669
HELPER(trt)1670 uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array,
1671 uint64_t trans)
1672 {
1673 return do_helper_trt(env, len, array, trans, 1, GETPC());
1674 }
1675
do_helper_trt_bkwd(CPUS390XState * env,uint32_t len,uint64_t array,uint64_t trans,uintptr_t ra)1676 static uint32_t do_helper_trt_bkwd(CPUS390XState *env, uint32_t len,
1677 uint64_t array, uint64_t trans,
1678 uintptr_t ra)
1679 {
1680 return do_helper_trt(env, len, array, trans, -1, ra);
1681 }
1682
HELPER(trtr)1683 uint32_t HELPER(trtr)(CPUS390XState *env, uint32_t len, uint64_t array,
1684 uint64_t trans)
1685 {
1686 return do_helper_trt(env, len, array, trans, -1, GETPC());
1687 }
1688
1689 /* Translate one/two to one/two */
HELPER(trXX)1690 uint32_t HELPER(trXX)(CPUS390XState *env, uint32_t r1, uint32_t r2,
1691 uint32_t tst, uint32_t sizes)
1692 {
1693 uintptr_t ra = GETPC();
1694 int dsize = (sizes & 1) ? 1 : 2;
1695 int ssize = (sizes & 2) ? 1 : 2;
1696 uint64_t tbl = get_address(env, 1);
1697 uint64_t dst = get_address(env, r1);
1698 uint64_t len = get_length(env, r1 + 1);
1699 uint64_t src = get_address(env, r2);
1700 uint32_t cc = 3;
1701 int i;
1702
1703 /* The lower address bits of TBL are ignored. For TROO, TROT, it's
1704 the low 3 bits (double-word aligned). For TRTO, TRTT, it's either
1705 the low 12 bits (4K, without ETF2-ENH) or 3 bits (with ETF2-ENH). */
1706 if (ssize == 2 && !s390_has_feat(S390_FEAT_ETF2_ENH)) {
1707 tbl &= -4096;
1708 } else {
1709 tbl &= -8;
1710 }
1711
1712 check_alignment(env, len, ssize, ra);
1713
1714 /* Lest we fail to service interrupts in a timely manner, */
1715 /* limit the amount of work we're willing to do. */
1716 for (i = 0; i < 0x2000; i++) {
1717 uint16_t sval = cpu_ldusize_data_ra(env, src, ssize, ra);
1718 uint64_t tble = tbl + (sval * dsize);
1719 uint16_t dval = cpu_ldusize_data_ra(env, tble, dsize, ra);
1720 if (dval == tst) {
1721 cc = 1;
1722 break;
1723 }
1724 cpu_stsize_data_ra(env, dst, dval, dsize, ra);
1725
1726 len -= ssize;
1727 src += ssize;
1728 dst += dsize;
1729
1730 if (len == 0) {
1731 cc = 0;
1732 break;
1733 }
1734 }
1735
1736 set_address(env, r1, dst);
1737 set_length(env, r1 + 1, len);
1738 set_address(env, r2, src);
1739
1740 return cc;
1741 }
1742
do_csst(CPUS390XState * env,uint32_t r3,uint64_t a1,uint64_t a2,bool parallel)1743 static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
1744 uint64_t a2, bool parallel)
1745 {
1746 uint32_t mem_idx = s390x_env_mmu_index(env, false);
1747 MemOpIdx oi16 = make_memop_idx(MO_TE | MO_128, mem_idx);
1748 MemOpIdx oi8 = make_memop_idx(MO_TE | MO_64, mem_idx);
1749 MemOpIdx oi4 = make_memop_idx(MO_TE | MO_32, mem_idx);
1750 MemOpIdx oi2 = make_memop_idx(MO_TE | MO_16, mem_idx);
1751 MemOpIdx oi1 = make_memop_idx(MO_8, mem_idx);
1752 uintptr_t ra = GETPC();
1753 uint32_t fc = extract32(env->regs[0], 0, 8);
1754 uint32_t sc = extract32(env->regs[0], 8, 8);
1755 uint64_t pl = get_address(env, 1) & -16;
1756 uint64_t svh, svl;
1757 uint32_t cc;
1758
1759 /* Sanity check the function code and storage characteristic. */
1760 if (fc > 1 || sc > 3) {
1761 if (!s390_has_feat(S390_FEAT_COMPARE_AND_SWAP_AND_STORE_2)) {
1762 goto spec_exception;
1763 }
1764 if (fc > 2 || sc > 4 || (fc == 2 && (r3 & 1))) {
1765 goto spec_exception;
1766 }
1767 }
1768
1769 /* Sanity check the alignments. */
1770 if (extract32(a1, 0, fc + 2) || extract32(a2, 0, sc)) {
1771 goto spec_exception;
1772 }
1773
1774 /* Sanity check writability of the store address. */
1775 probe_write(env, a2, 1 << sc, mem_idx, ra);
1776
1777 /*
1778 * Note that the compare-and-swap is atomic, and the store is atomic,
1779 * but the complete operation is not. Therefore we do not need to
1780 * assert serial context in order to implement this. That said,
1781 * restart early if we can't support either operation that is supposed
1782 * to be atomic.
1783 */
1784 if (parallel) {
1785 uint32_t max = 2;
1786 #ifdef CONFIG_ATOMIC64
1787 max = 3;
1788 #endif
1789 if ((HAVE_CMPXCHG128 ? 0 : fc + 2 > max) ||
1790 (HAVE_ATOMIC128_RW ? 0 : sc > max)) {
1791 cpu_loop_exit_atomic(env_cpu(env), ra);
1792 }
1793 }
1794
1795 /*
1796 * All loads happen before all stores. For simplicity, load the entire
1797 * store value area from the parameter list.
1798 */
1799 svh = cpu_ldq_mmu(env, pl + 16, oi8, ra);
1800 svl = cpu_ldq_mmu(env, pl + 24, oi8, ra);
1801
1802 switch (fc) {
1803 case 0:
1804 {
1805 uint32_t nv = cpu_ldl_mmu(env, pl, oi4, ra);
1806 uint32_t cv = env->regs[r3];
1807 uint32_t ov;
1808
1809 if (parallel) {
1810 ov = cpu_atomic_cmpxchgl_be_mmu(env, a1, cv, nv, oi4, ra);
1811 } else {
1812 ov = cpu_ldl_mmu(env, a1, oi4, ra);
1813 cpu_stl_mmu(env, a1, (ov == cv ? nv : ov), oi4, ra);
1814 }
1815 cc = (ov != cv);
1816 env->regs[r3] = deposit64(env->regs[r3], 32, 32, ov);
1817 }
1818 break;
1819
1820 case 1:
1821 {
1822 uint64_t nv = cpu_ldq_mmu(env, pl, oi8, ra);
1823 uint64_t cv = env->regs[r3];
1824 uint64_t ov;
1825
1826 if (parallel) {
1827 #ifdef CONFIG_ATOMIC64
1828 ov = cpu_atomic_cmpxchgq_be_mmu(env, a1, cv, nv, oi8, ra);
1829 #else
1830 /* Note that we asserted !parallel above. */
1831 g_assert_not_reached();
1832 #endif
1833 } else {
1834 ov = cpu_ldq_mmu(env, a1, oi8, ra);
1835 cpu_stq_mmu(env, a1, (ov == cv ? nv : ov), oi8, ra);
1836 }
1837 cc = (ov != cv);
1838 env->regs[r3] = ov;
1839 }
1840 break;
1841
1842 case 2:
1843 {
1844 Int128 nv = cpu_ld16_mmu(env, pl, oi16, ra);
1845 Int128 cv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
1846 Int128 ov;
1847
1848 if (!parallel) {
1849 ov = cpu_ld16_mmu(env, a1, oi16, ra);
1850 cc = !int128_eq(ov, cv);
1851 if (cc) {
1852 nv = ov;
1853 }
1854 cpu_st16_mmu(env, a1, nv, oi16, ra);
1855 } else if (HAVE_CMPXCHG128) {
1856 ov = cpu_atomic_cmpxchgo_be_mmu(env, a1, cv, nv, oi16, ra);
1857 cc = !int128_eq(ov, cv);
1858 } else {
1859 /* Note that we asserted !parallel above. */
1860 g_assert_not_reached();
1861 }
1862
1863 env->regs[r3 + 0] = int128_gethi(ov);
1864 env->regs[r3 + 1] = int128_getlo(ov);
1865 }
1866 break;
1867
1868 default:
1869 g_assert_not_reached();
1870 }
1871
1872 /* Store only if the comparison succeeded. Note that above we use a pair
1873 of 64-bit big-endian loads, so for sc < 3 we must extract the value
1874 from the most-significant bits of svh. */
1875 if (cc == 0) {
1876 switch (sc) {
1877 case 0:
1878 cpu_stb_mmu(env, a2, svh >> 56, oi1, ra);
1879 break;
1880 case 1:
1881 cpu_stw_mmu(env, a2, svh >> 48, oi2, ra);
1882 break;
1883 case 2:
1884 cpu_stl_mmu(env, a2, svh >> 32, oi4, ra);
1885 break;
1886 case 3:
1887 cpu_stq_mmu(env, a2, svh, oi8, ra);
1888 break;
1889 case 4:
1890 cpu_st16_mmu(env, a2, int128_make128(svl, svh), oi16, ra);
1891 break;
1892 default:
1893 g_assert_not_reached();
1894 }
1895 }
1896
1897 return cc;
1898
1899 spec_exception:
1900 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
1901 }
1902
HELPER(csst)1903 uint32_t HELPER(csst)(CPUS390XState *env, uint32_t r3, uint64_t a1, uint64_t a2)
1904 {
1905 return do_csst(env, r3, a1, a2, false);
1906 }
1907
HELPER(csst_parallel)1908 uint32_t HELPER(csst_parallel)(CPUS390XState *env, uint32_t r3, uint64_t a1,
1909 uint64_t a2)
1910 {
1911 return do_csst(env, r3, a1, a2, true);
1912 }
1913
1914 #if !defined(CONFIG_USER_ONLY)
HELPER(lctlg)1915 void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
1916 {
1917 uintptr_t ra = GETPC();
1918 bool PERchanged = false;
1919 uint64_t src = a2;
1920 uint32_t i;
1921
1922 if (src & 0x7) {
1923 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
1924 }
1925
1926 for (i = r1;; i = (i + 1) % 16) {
1927 uint64_t val = cpu_ldq_data_ra(env, src, ra);
1928 if (env->cregs[i] != val && i >= 9 && i <= 11) {
1929 PERchanged = true;
1930 }
1931 env->cregs[i] = val;
1932 HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
1933 i, src, val);
1934 src += sizeof(uint64_t);
1935
1936 if (i == r3) {
1937 break;
1938 }
1939 }
1940
1941 if (PERchanged && env->psw.mask & PSW_MASK_PER) {
1942 s390_cpu_recompute_watchpoints(env_cpu(env));
1943 }
1944
1945 tlb_flush(env_cpu(env));
1946 }
1947
HELPER(lctl)1948 void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
1949 {
1950 uintptr_t ra = GETPC();
1951 bool PERchanged = false;
1952 uint64_t src = a2;
1953 uint32_t i;
1954
1955 if (src & 0x3) {
1956 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
1957 }
1958
1959 for (i = r1;; i = (i + 1) % 16) {
1960 uint32_t val = cpu_ldl_data_ra(env, src, ra);
1961 if ((uint32_t)env->cregs[i] != val && i >= 9 && i <= 11) {
1962 PERchanged = true;
1963 }
1964 env->cregs[i] = deposit64(env->cregs[i], 0, 32, val);
1965 HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%x\n", i, src, val);
1966 src += sizeof(uint32_t);
1967
1968 if (i == r3) {
1969 break;
1970 }
1971 }
1972
1973 if (PERchanged && env->psw.mask & PSW_MASK_PER) {
1974 s390_cpu_recompute_watchpoints(env_cpu(env));
1975 }
1976
1977 tlb_flush(env_cpu(env));
1978 }
1979
HELPER(stctg)1980 void HELPER(stctg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
1981 {
1982 uintptr_t ra = GETPC();
1983 uint64_t dest = a2;
1984 uint32_t i;
1985
1986 if (dest & 0x7) {
1987 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
1988 }
1989
1990 for (i = r1;; i = (i + 1) % 16) {
1991 cpu_stq_data_ra(env, dest, env->cregs[i], ra);
1992 dest += sizeof(uint64_t);
1993
1994 if (i == r3) {
1995 break;
1996 }
1997 }
1998 }
1999
HELPER(stctl)2000 void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
2001 {
2002 uintptr_t ra = GETPC();
2003 uint64_t dest = a2;
2004 uint32_t i;
2005
2006 if (dest & 0x3) {
2007 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
2008 }
2009
2010 for (i = r1;; i = (i + 1) % 16) {
2011 cpu_stl_data_ra(env, dest, env->cregs[i], ra);
2012 dest += sizeof(uint32_t);
2013
2014 if (i == r3) {
2015 break;
2016 }
2017 }
2018 }
2019
HELPER(testblock)2020 uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr)
2021 {
2022 uintptr_t ra = GETPC();
2023 int i;
2024
2025 real_addr = wrap_address(env, real_addr) & TARGET_PAGE_MASK;
2026
2027 for (i = 0; i < TARGET_PAGE_SIZE; i += 8) {
2028 cpu_stq_mmuidx_ra(env, real_addr + i, 0, MMU_REAL_IDX, ra);
2029 }
2030
2031 return 0;
2032 }
2033
HELPER(tprot)2034 uint32_t HELPER(tprot)(CPUS390XState *env, uint64_t a1, uint64_t a2)
2035 {
2036 S390CPU *cpu = env_archcpu(env);
2037 CPUState *cs = env_cpu(env);
2038
2039 /*
2040 * TODO: we currently don't handle all access protection types
2041 * (including access-list and key-controlled) as well as AR mode.
2042 */
2043 if (!s390_cpu_virt_mem_check_write(cpu, a1, 0, 1)) {
2044 /* Fetching permitted; storing permitted */
2045 return 0;
2046 }
2047
2048 if (env->int_pgm_code == PGM_PROTECTION) {
2049 /* retry if reading is possible */
2050 cs->exception_index = -1;
2051 if (!s390_cpu_virt_mem_check_read(cpu, a1, 0, 1)) {
2052 /* Fetching permitted; storing not permitted */
2053 return 1;
2054 }
2055 }
2056
2057 switch (env->int_pgm_code) {
2058 case PGM_PROTECTION:
2059 /* Fetching not permitted; storing not permitted */
2060 cs->exception_index = -1;
2061 return 2;
2062 case PGM_ADDRESSING:
2063 case PGM_TRANS_SPEC:
2064 /* exceptions forwarded to the guest */
2065 s390_cpu_virt_mem_handle_exc(cpu, GETPC());
2066 return 0;
2067 }
2068
2069 /* Translation not available */
2070 cs->exception_index = -1;
2071 return 3;
2072 }
2073
2074 /* insert storage key extended */
HELPER(iske)2075 uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
2076 {
2077 static S390SKeysState *ss;
2078 static S390SKeysClass *skeyclass;
2079 uint64_t addr = wrap_address(env, r2);
2080 uint8_t key;
2081 int rc;
2082
2083 addr = mmu_real2abs(env, addr);
2084 if (!mmu_absolute_addr_valid(addr, false)) {
2085 tcg_s390_program_interrupt(env, PGM_ADDRESSING, GETPC());
2086 }
2087
2088 if (unlikely(!ss)) {
2089 ss = s390_get_skeys_device();
2090 skeyclass = S390_SKEYS_GET_CLASS(ss);
2091 if (skeyclass->enable_skeys && !skeyclass->enable_skeys(ss)) {
2092 tlb_flush_all_cpus_synced(env_cpu(env));
2093 }
2094 }
2095
2096 rc = skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
2097 if (rc) {
2098 trace_get_skeys_nonzero(rc);
2099 return 0;
2100 }
2101 return key;
2102 }
2103
2104 /* set storage key extended */
HELPER(sske)2105 void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
2106 {
2107 static S390SKeysState *ss;
2108 static S390SKeysClass *skeyclass;
2109 uint64_t addr = wrap_address(env, r2);
2110 uint8_t key;
2111 int rc;
2112
2113 addr = mmu_real2abs(env, addr);
2114 if (!mmu_absolute_addr_valid(addr, false)) {
2115 tcg_s390_program_interrupt(env, PGM_ADDRESSING, GETPC());
2116 }
2117
2118 if (unlikely(!ss)) {
2119 ss = s390_get_skeys_device();
2120 skeyclass = S390_SKEYS_GET_CLASS(ss);
2121 if (skeyclass->enable_skeys && !skeyclass->enable_skeys(ss)) {
2122 tlb_flush_all_cpus_synced(env_cpu(env));
2123 }
2124 }
2125
2126 key = r1 & 0xfe;
2127 rc = skeyclass->set_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
2128 if (rc) {
2129 trace_set_skeys_nonzero(rc);
2130 }
2131 /*
2132 * As we can only flush by virtual address and not all the entries
2133 * that point to a physical address we have to flush the whole TLB.
2134 */
2135 tlb_flush_all_cpus_synced(env_cpu(env));
2136 }
2137
2138 /* reset reference bit extended */
HELPER(rrbe)2139 uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
2140 {
2141 uint64_t addr = wrap_address(env, r2);
2142 static S390SKeysState *ss;
2143 static S390SKeysClass *skeyclass;
2144 uint8_t re, key;
2145 int rc;
2146
2147 addr = mmu_real2abs(env, addr);
2148 if (!mmu_absolute_addr_valid(addr, false)) {
2149 tcg_s390_program_interrupt(env, PGM_ADDRESSING, GETPC());
2150 }
2151
2152 if (unlikely(!ss)) {
2153 ss = s390_get_skeys_device();
2154 skeyclass = S390_SKEYS_GET_CLASS(ss);
2155 if (skeyclass->enable_skeys && !skeyclass->enable_skeys(ss)) {
2156 tlb_flush_all_cpus_synced(env_cpu(env));
2157 }
2158 }
2159
2160 rc = skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
2161 if (rc) {
2162 trace_get_skeys_nonzero(rc);
2163 return 0;
2164 }
2165
2166 re = key & (SK_R | SK_C);
2167 key &= ~SK_R;
2168
2169 rc = skeyclass->set_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
2170 if (rc) {
2171 trace_set_skeys_nonzero(rc);
2172 return 0;
2173 }
2174 /*
2175 * As we can only flush by virtual address and not all the entries
2176 * that point to a physical address we have to flush the whole TLB.
2177 */
2178 tlb_flush_all_cpus_synced(env_cpu(env));
2179
2180 /*
2181 * cc
2182 *
2183 * 0 Reference bit zero; change bit zero
2184 * 1 Reference bit zero; change bit one
2185 * 2 Reference bit one; change bit zero
2186 * 3 Reference bit one; change bit one
2187 */
2188
2189 return re >> 1;
2190 }
2191
HELPER(mvcs)2192 uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2,
2193 uint64_t key)
2194 {
2195 const uint8_t psw_as = (env->psw.mask & PSW_MASK_ASC) >> PSW_SHIFT_ASC;
2196 S390Access srca, desta;
2197 uintptr_t ra = GETPC();
2198 int cc = 0;
2199
2200 HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
2201 __func__, l, a1, a2);
2202
2203 if (!(env->psw.mask & PSW_MASK_DAT) || !(env->cregs[0] & CR0_SECONDARY) ||
2204 psw_as == AS_HOME || psw_as == AS_ACCREG) {
2205 s390_program_interrupt(env, PGM_SPECIAL_OP, ra);
2206 }
2207
2208 if (!psw_key_valid(env, (key >> 4) & 0xf)) {
2209 s390_program_interrupt(env, PGM_PRIVILEGED, ra);
2210 }
2211
2212 l = wrap_length32(env, l);
2213 if (l > 256) {
2214 /* max 256 */
2215 l = 256;
2216 cc = 3;
2217 } else if (!l) {
2218 return cc;
2219 }
2220
2221 access_prepare(&srca, env, a2, l, MMU_DATA_LOAD, MMU_PRIMARY_IDX, ra);
2222 access_prepare(&desta, env, a1, l, MMU_DATA_STORE, MMU_SECONDARY_IDX, ra);
2223 access_memmove(env, &desta, &srca, ra);
2224 return cc;
2225 }
2226
HELPER(mvcp)2227 uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2,
2228 uint64_t key)
2229 {
2230 const uint8_t psw_as = (env->psw.mask & PSW_MASK_ASC) >> PSW_SHIFT_ASC;
2231 S390Access srca, desta;
2232 uintptr_t ra = GETPC();
2233 int cc = 0;
2234
2235 HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
2236 __func__, l, a1, a2);
2237
2238 if (!(env->psw.mask & PSW_MASK_DAT) || !(env->cregs[0] & CR0_SECONDARY) ||
2239 psw_as == AS_HOME || psw_as == AS_ACCREG) {
2240 s390_program_interrupt(env, PGM_SPECIAL_OP, ra);
2241 }
2242
2243 if (!psw_key_valid(env, (key >> 4) & 0xf)) {
2244 s390_program_interrupt(env, PGM_PRIVILEGED, ra);
2245 }
2246
2247 l = wrap_length32(env, l);
2248 if (l > 256) {
2249 /* max 256 */
2250 l = 256;
2251 cc = 3;
2252 } else if (!l) {
2253 return cc;
2254 }
2255 access_prepare(&srca, env, a2, l, MMU_DATA_LOAD, MMU_SECONDARY_IDX, ra);
2256 access_prepare(&desta, env, a1, l, MMU_DATA_STORE, MMU_PRIMARY_IDX, ra);
2257 access_memmove(env, &desta, &srca, ra);
2258 return cc;
2259 }
2260
HELPER(idte)2261 void HELPER(idte)(CPUS390XState *env, uint64_t r1, uint64_t r2, uint32_t m4)
2262 {
2263 CPUState *cs = env_cpu(env);
2264 const uintptr_t ra = GETPC();
2265 uint64_t table, entry, raddr;
2266 uint16_t entries, i, index = 0;
2267
2268 if (r2 & 0xff000) {
2269 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
2270 }
2271
2272 if (!(r2 & 0x800)) {
2273 /* invalidation-and-clearing operation */
2274 table = r1 & ASCE_ORIGIN;
2275 entries = (r2 & 0x7ff) + 1;
2276
2277 switch (r1 & ASCE_TYPE_MASK) {
2278 case ASCE_TYPE_REGION1:
2279 index = (r2 >> 53) & 0x7ff;
2280 break;
2281 case ASCE_TYPE_REGION2:
2282 index = (r2 >> 42) & 0x7ff;
2283 break;
2284 case ASCE_TYPE_REGION3:
2285 index = (r2 >> 31) & 0x7ff;
2286 break;
2287 case ASCE_TYPE_SEGMENT:
2288 index = (r2 >> 20) & 0x7ff;
2289 break;
2290 }
2291 for (i = 0; i < entries; i++) {
2292 /* addresses are not wrapped in 24/31bit mode but table index is */
2293 raddr = table + ((index + i) & 0x7ff) * sizeof(entry);
2294 entry = cpu_ldq_mmuidx_ra(env, raddr, MMU_REAL_IDX, ra);
2295 if (!(entry & REGION_ENTRY_I)) {
2296 /* we are allowed to not store if already invalid */
2297 entry |= REGION_ENTRY_I;
2298 cpu_stq_mmuidx_ra(env, raddr, entry, MMU_REAL_IDX, ra);
2299 }
2300 }
2301 }
2302
2303 /* We simply flush the complete tlb, therefore we can ignore r3. */
2304 if (m4 & 1) {
2305 tlb_flush(cs);
2306 } else {
2307 tlb_flush_all_cpus_synced(cs);
2308 }
2309 }
2310
2311 /* invalidate pte */
HELPER(ipte)2312 void HELPER(ipte)(CPUS390XState *env, uint64_t pto, uint64_t vaddr,
2313 uint32_t m4)
2314 {
2315 CPUState *cs = env_cpu(env);
2316 const uintptr_t ra = GETPC();
2317 uint64_t page = vaddr & TARGET_PAGE_MASK;
2318 uint64_t pte_addr, pte;
2319
2320 /* Compute the page table entry address */
2321 pte_addr = (pto & SEGMENT_ENTRY_ORIGIN);
2322 pte_addr += VADDR_PAGE_TX(vaddr) * 8;
2323
2324 /* Mark the page table entry as invalid */
2325 pte = cpu_ldq_mmuidx_ra(env, pte_addr, MMU_REAL_IDX, ra);
2326 pte |= PAGE_ENTRY_I;
2327 cpu_stq_mmuidx_ra(env, pte_addr, pte, MMU_REAL_IDX, ra);
2328
2329 /* XXX we exploit the fact that Linux passes the exact virtual
2330 address here - it's not obliged to! */
2331 if (m4 & 1) {
2332 if (vaddr & ~VADDR_PAGE_TX_MASK) {
2333 tlb_flush_page(cs, page);
2334 /* XXX 31-bit hack */
2335 tlb_flush_page(cs, page ^ 0x80000000);
2336 } else {
2337 /* looks like we don't have a valid virtual address */
2338 tlb_flush(cs);
2339 }
2340 } else {
2341 if (vaddr & ~VADDR_PAGE_TX_MASK) {
2342 tlb_flush_page_all_cpus_synced(cs, page);
2343 /* XXX 31-bit hack */
2344 tlb_flush_page_all_cpus_synced(cs, page ^ 0x80000000);
2345 } else {
2346 /* looks like we don't have a valid virtual address */
2347 tlb_flush_all_cpus_synced(cs);
2348 }
2349 }
2350 }
2351
2352 /* flush local tlb */
HELPER(ptlb)2353 void HELPER(ptlb)(CPUS390XState *env)
2354 {
2355 tlb_flush(env_cpu(env));
2356 }
2357
2358 /* flush global tlb */
HELPER(purge)2359 void HELPER(purge)(CPUS390XState *env)
2360 {
2361 tlb_flush_all_cpus_synced(env_cpu(env));
2362 }
2363
2364 /* load real address */
HELPER(lra)2365 uint64_t HELPER(lra)(CPUS390XState *env, uint64_t r1, uint64_t addr)
2366 {
2367 uint64_t asc = env->psw.mask & PSW_MASK_ASC;
2368 uint64_t ret, tec;
2369 int flags, exc, cc;
2370
2371 /* XXX incomplete - has more corner cases */
2372 if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) {
2373 tcg_s390_program_interrupt(env, PGM_SPECIAL_OP, GETPC());
2374 }
2375
2376 exc = mmu_translate(env, addr, MMU_S390_LRA, asc, &ret, &flags, &tec);
2377 if (exc) {
2378 cc = 3;
2379 ret = (r1 & 0xFFFFFFFF00000000ULL) | exc | 0x80000000;
2380 } else {
2381 cc = 0;
2382 ret |= addr & ~TARGET_PAGE_MASK;
2383 }
2384
2385 env->cc_op = cc;
2386 return ret;
2387 }
2388 #endif
2389
2390 /* Execute instruction. This instruction executes an insn modified with
2391 the contents of r1. It does not change the executed instruction in memory;
2392 it does not change the program counter.
2393
2394 Perform this by recording the modified instruction in env->ex_value.
2395 This will be noticed by cpu_get_tb_cpu_state and thus tb translation.
2396 */
HELPER(ex)2397 void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr)
2398 {
2399 uint64_t insn;
2400 uint8_t opc;
2401
2402 /* EXECUTE targets must be at even addresses. */
2403 if (addr & 1) {
2404 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
2405 }
2406
2407 insn = cpu_lduw_code(env, addr);
2408 opc = insn >> 8;
2409
2410 /* Or in the contents of R1[56:63]. */
2411 insn |= r1 & 0xff;
2412
2413 /* Load the rest of the instruction. */
2414 insn <<= 48;
2415 switch (get_ilen(opc)) {
2416 case 2:
2417 break;
2418 case 4:
2419 insn |= (uint64_t)cpu_lduw_code(env, addr + 2) << 32;
2420 break;
2421 case 6:
2422 insn |= (uint64_t)(uint32_t)cpu_ldl_code(env, addr + 2) << 16;
2423 break;
2424 default:
2425 g_assert_not_reached();
2426 }
2427
2428 /* The very most common cases can be sped up by avoiding a new TB. */
2429 if ((opc & 0xf0) == 0xd0) {
2430 typedef uint32_t (*dx_helper)(CPUS390XState *, uint32_t, uint64_t,
2431 uint64_t, uintptr_t);
2432 static const dx_helper dx[16] = {
2433 [0x0] = do_helper_trt_bkwd,
2434 [0x2] = do_helper_mvc,
2435 [0x4] = do_helper_nc,
2436 [0x5] = do_helper_clc,
2437 [0x6] = do_helper_oc,
2438 [0x7] = do_helper_xc,
2439 [0xc] = do_helper_tr,
2440 [0xd] = do_helper_trt_fwd,
2441 };
2442 dx_helper helper = dx[opc & 0xf];
2443
2444 if (helper) {
2445 uint32_t l = extract64(insn, 48, 8);
2446 uint32_t b1 = extract64(insn, 44, 4);
2447 uint32_t d1 = extract64(insn, 32, 12);
2448 uint32_t b2 = extract64(insn, 28, 4);
2449 uint32_t d2 = extract64(insn, 16, 12);
2450 uint64_t a1 = wrap_address(env, (b1 ? env->regs[b1] : 0) + d1);
2451 uint64_t a2 = wrap_address(env, (b2 ? env->regs[b2] : 0) + d2);
2452
2453 env->cc_op = helper(env, l, a1, a2, 0);
2454 env->psw.addr += ilen;
2455 return;
2456 }
2457 } else if (opc == 0x0a) {
2458 env->int_svc_code = extract64(insn, 48, 8);
2459 env->int_svc_ilen = ilen;
2460 helper_exception(env, EXCP_SVC);
2461 g_assert_not_reached();
2462 }
2463
2464 /* Record the insn we want to execute as well as the ilen to use
2465 during the execution of the target insn. This will also ensure
2466 that ex_value is non-zero, which flags that we are in a state
2467 that requires such execution. */
2468 env->ex_value = insn | ilen;
2469 env->ex_target = addr;
2470 }
2471
HELPER(mvcos)2472 uint32_t HELPER(mvcos)(CPUS390XState *env, uint64_t dest, uint64_t src,
2473 uint64_t len)
2474 {
2475 const uint8_t psw_key = (env->psw.mask & PSW_MASK_KEY) >> PSW_SHIFT_KEY;
2476 const uint8_t psw_as = (env->psw.mask & PSW_MASK_ASC) >> PSW_SHIFT_ASC;
2477 const uint64_t r0 = env->regs[0];
2478 const uintptr_t ra = GETPC();
2479 uint8_t dest_key, dest_as, dest_k, dest_a;
2480 uint8_t src_key, src_as, src_k, src_a;
2481 uint64_t val;
2482 int cc = 0;
2483
2484 HELPER_LOG("%s dest %" PRIx64 ", src %" PRIx64 ", len %" PRIx64 "\n",
2485 __func__, dest, src, len);
2486
2487 if (!(env->psw.mask & PSW_MASK_DAT)) {
2488 tcg_s390_program_interrupt(env, PGM_SPECIAL_OP, ra);
2489 }
2490
2491 /* OAC (operand access control) for the first operand -> dest */
2492 val = (r0 & 0xffff0000ULL) >> 16;
2493 dest_key = (val >> 12) & 0xf;
2494 dest_as = (val >> 6) & 0x3;
2495 dest_k = (val >> 1) & 0x1;
2496 dest_a = val & 0x1;
2497
2498 /* OAC (operand access control) for the second operand -> src */
2499 val = (r0 & 0x0000ffffULL);
2500 src_key = (val >> 12) & 0xf;
2501 src_as = (val >> 6) & 0x3;
2502 src_k = (val >> 1) & 0x1;
2503 src_a = val & 0x1;
2504
2505 if (!dest_k) {
2506 dest_key = psw_key;
2507 }
2508 if (!src_k) {
2509 src_key = psw_key;
2510 }
2511 if (!dest_a) {
2512 dest_as = psw_as;
2513 }
2514 if (!src_a) {
2515 src_as = psw_as;
2516 }
2517
2518 if (dest_a && dest_as == AS_HOME && (env->psw.mask & PSW_MASK_PSTATE)) {
2519 tcg_s390_program_interrupt(env, PGM_SPECIAL_OP, ra);
2520 }
2521 if (!(env->cregs[0] & CR0_SECONDARY) &&
2522 (dest_as == AS_SECONDARY || src_as == AS_SECONDARY)) {
2523 tcg_s390_program_interrupt(env, PGM_SPECIAL_OP, ra);
2524 }
2525 if (!psw_key_valid(env, dest_key) || !psw_key_valid(env, src_key)) {
2526 tcg_s390_program_interrupt(env, PGM_PRIVILEGED, ra);
2527 }
2528
2529 len = wrap_length32(env, len);
2530 if (len > 4096) {
2531 cc = 3;
2532 len = 4096;
2533 }
2534
2535 /* FIXME: AR-mode and proper problem state mode (using PSW keys) missing */
2536 if (src_as == AS_ACCREG || dest_as == AS_ACCREG ||
2537 (env->psw.mask & PSW_MASK_PSTATE)) {
2538 qemu_log_mask(LOG_UNIMP, "%s: AR-mode and PSTATE support missing\n",
2539 __func__);
2540 tcg_s390_program_interrupt(env, PGM_ADDRESSING, ra);
2541 }
2542
2543 /* FIXME: Access using correct keys and AR-mode */
2544 if (len) {
2545 S390Access srca, desta;
2546
2547 access_prepare(&srca, env, src, len, MMU_DATA_LOAD,
2548 mmu_idx_from_as(src_as), ra);
2549 access_prepare(&desta, env, dest, len, MMU_DATA_STORE,
2550 mmu_idx_from_as(dest_as), ra);
2551
2552 access_memmove(env, &desta, &srca, ra);
2553 }
2554
2555 return cc;
2556 }
2557
2558 /* Decode a Unicode character. A return value < 0 indicates success, storing
2559 the UTF-32 result into OCHAR and the input length into OLEN. A return
2560 value >= 0 indicates failure, and the CC value to be returned. */
2561 typedef int (*decode_unicode_fn)(CPUS390XState *env, uint64_t addr,
2562 uint64_t ilen, bool enh_check, uintptr_t ra,
2563 uint32_t *ochar, uint32_t *olen);
2564
2565 /* Encode a Unicode character. A return value < 0 indicates success, storing
2566 the bytes into ADDR and the output length into OLEN. A return value >= 0
2567 indicates failure, and the CC value to be returned. */
2568 typedef int (*encode_unicode_fn)(CPUS390XState *env, uint64_t addr,
2569 uint64_t ilen, uintptr_t ra, uint32_t c,
2570 uint32_t *olen);
2571
decode_utf8(CPUS390XState * env,uint64_t addr,uint64_t ilen,bool enh_check,uintptr_t ra,uint32_t * ochar,uint32_t * olen)2572 static int decode_utf8(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2573 bool enh_check, uintptr_t ra,
2574 uint32_t *ochar, uint32_t *olen)
2575 {
2576 uint8_t s0, s1, s2, s3;
2577 uint32_t c, l;
2578
2579 if (ilen < 1) {
2580 return 0;
2581 }
2582 s0 = cpu_ldub_data_ra(env, addr, ra);
2583 if (s0 <= 0x7f) {
2584 /* one byte character */
2585 l = 1;
2586 c = s0;
2587 } else if (s0 <= (enh_check ? 0xc1 : 0xbf)) {
2588 /* invalid character */
2589 return 2;
2590 } else if (s0 <= 0xdf) {
2591 /* two byte character */
2592 l = 2;
2593 if (ilen < 2) {
2594 return 0;
2595 }
2596 s1 = cpu_ldub_data_ra(env, addr + 1, ra);
2597 c = s0 & 0x1f;
2598 c = (c << 6) | (s1 & 0x3f);
2599 if (enh_check && (s1 & 0xc0) != 0x80) {
2600 return 2;
2601 }
2602 } else if (s0 <= 0xef) {
2603 /* three byte character */
2604 l = 3;
2605 if (ilen < 3) {
2606 return 0;
2607 }
2608 s1 = cpu_ldub_data_ra(env, addr + 1, ra);
2609 s2 = cpu_ldub_data_ra(env, addr + 2, ra);
2610 c = s0 & 0x0f;
2611 c = (c << 6) | (s1 & 0x3f);
2612 c = (c << 6) | (s2 & 0x3f);
2613 /* Fold the byte-by-byte range descriptions in the PoO into
2614 tests against the complete value. It disallows encodings
2615 that could be smaller, and the UTF-16 surrogates. */
2616 if (enh_check
2617 && ((s1 & 0xc0) != 0x80
2618 || (s2 & 0xc0) != 0x80
2619 || c < 0x1000
2620 || (c >= 0xd800 && c <= 0xdfff))) {
2621 return 2;
2622 }
2623 } else if (s0 <= (enh_check ? 0xf4 : 0xf7)) {
2624 /* four byte character */
2625 l = 4;
2626 if (ilen < 4) {
2627 return 0;
2628 }
2629 s1 = cpu_ldub_data_ra(env, addr + 1, ra);
2630 s2 = cpu_ldub_data_ra(env, addr + 2, ra);
2631 s3 = cpu_ldub_data_ra(env, addr + 3, ra);
2632 c = s0 & 0x07;
2633 c = (c << 6) | (s1 & 0x3f);
2634 c = (c << 6) | (s2 & 0x3f);
2635 c = (c << 6) | (s3 & 0x3f);
2636 /* See above. */
2637 if (enh_check
2638 && ((s1 & 0xc0) != 0x80
2639 || (s2 & 0xc0) != 0x80
2640 || (s3 & 0xc0) != 0x80
2641 || c < 0x010000
2642 || c > 0x10ffff)) {
2643 return 2;
2644 }
2645 } else {
2646 /* invalid character */
2647 return 2;
2648 }
2649
2650 *ochar = c;
2651 *olen = l;
2652 return -1;
2653 }
2654
decode_utf16(CPUS390XState * env,uint64_t addr,uint64_t ilen,bool enh_check,uintptr_t ra,uint32_t * ochar,uint32_t * olen)2655 static int decode_utf16(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2656 bool enh_check, uintptr_t ra,
2657 uint32_t *ochar, uint32_t *olen)
2658 {
2659 uint16_t s0, s1;
2660 uint32_t c, l;
2661
2662 if (ilen < 2) {
2663 return 0;
2664 }
2665 s0 = cpu_lduw_data_ra(env, addr, ra);
2666 if ((s0 & 0xfc00) != 0xd800) {
2667 /* one word character */
2668 l = 2;
2669 c = s0;
2670 } else {
2671 /* two word character */
2672 l = 4;
2673 if (ilen < 4) {
2674 return 0;
2675 }
2676 s1 = cpu_lduw_data_ra(env, addr + 2, ra);
2677 c = extract32(s0, 6, 4) + 1;
2678 c = (c << 6) | (s0 & 0x3f);
2679 c = (c << 10) | (s1 & 0x3ff);
2680 if (enh_check && (s1 & 0xfc00) != 0xdc00) {
2681 /* invalid surrogate character */
2682 return 2;
2683 }
2684 }
2685
2686 *ochar = c;
2687 *olen = l;
2688 return -1;
2689 }
2690
decode_utf32(CPUS390XState * env,uint64_t addr,uint64_t ilen,bool enh_check,uintptr_t ra,uint32_t * ochar,uint32_t * olen)2691 static int decode_utf32(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2692 bool enh_check, uintptr_t ra,
2693 uint32_t *ochar, uint32_t *olen)
2694 {
2695 uint32_t c;
2696
2697 if (ilen < 4) {
2698 return 0;
2699 }
2700 c = cpu_ldl_data_ra(env, addr, ra);
2701 if ((c >= 0xd800 && c <= 0xdbff) || c > 0x10ffff) {
2702 /* invalid unicode character */
2703 return 2;
2704 }
2705
2706 *ochar = c;
2707 *olen = 4;
2708 return -1;
2709 }
2710
encode_utf8(CPUS390XState * env,uint64_t addr,uint64_t ilen,uintptr_t ra,uint32_t c,uint32_t * olen)2711 static int encode_utf8(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2712 uintptr_t ra, uint32_t c, uint32_t *olen)
2713 {
2714 uint8_t d[4];
2715 uint32_t l, i;
2716
2717 if (c <= 0x7f) {
2718 /* one byte character */
2719 l = 1;
2720 d[0] = c;
2721 } else if (c <= 0x7ff) {
2722 /* two byte character */
2723 l = 2;
2724 d[1] = 0x80 | extract32(c, 0, 6);
2725 d[0] = 0xc0 | extract32(c, 6, 5);
2726 } else if (c <= 0xffff) {
2727 /* three byte character */
2728 l = 3;
2729 d[2] = 0x80 | extract32(c, 0, 6);
2730 d[1] = 0x80 | extract32(c, 6, 6);
2731 d[0] = 0xe0 | extract32(c, 12, 4);
2732 } else {
2733 /* four byte character */
2734 l = 4;
2735 d[3] = 0x80 | extract32(c, 0, 6);
2736 d[2] = 0x80 | extract32(c, 6, 6);
2737 d[1] = 0x80 | extract32(c, 12, 6);
2738 d[0] = 0xf0 | extract32(c, 18, 3);
2739 }
2740
2741 if (ilen < l) {
2742 return 1;
2743 }
2744 for (i = 0; i < l; ++i) {
2745 cpu_stb_data_ra(env, addr + i, d[i], ra);
2746 }
2747
2748 *olen = l;
2749 return -1;
2750 }
2751
encode_utf16(CPUS390XState * env,uint64_t addr,uint64_t ilen,uintptr_t ra,uint32_t c,uint32_t * olen)2752 static int encode_utf16(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2753 uintptr_t ra, uint32_t c, uint32_t *olen)
2754 {
2755 uint16_t d0, d1;
2756
2757 if (c <= 0xffff) {
2758 /* one word character */
2759 if (ilen < 2) {
2760 return 1;
2761 }
2762 cpu_stw_data_ra(env, addr, c, ra);
2763 *olen = 2;
2764 } else {
2765 /* two word character */
2766 if (ilen < 4) {
2767 return 1;
2768 }
2769 d1 = 0xdc00 | extract32(c, 0, 10);
2770 d0 = 0xd800 | extract32(c, 10, 6);
2771 d0 = deposit32(d0, 6, 4, extract32(c, 16, 5) - 1);
2772 cpu_stw_data_ra(env, addr + 0, d0, ra);
2773 cpu_stw_data_ra(env, addr + 2, d1, ra);
2774 *olen = 4;
2775 }
2776
2777 return -1;
2778 }
2779
encode_utf32(CPUS390XState * env,uint64_t addr,uint64_t ilen,uintptr_t ra,uint32_t c,uint32_t * olen)2780 static int encode_utf32(CPUS390XState *env, uint64_t addr, uint64_t ilen,
2781 uintptr_t ra, uint32_t c, uint32_t *olen)
2782 {
2783 if (ilen < 4) {
2784 return 1;
2785 }
2786 cpu_stl_data_ra(env, addr, c, ra);
2787 *olen = 4;
2788 return -1;
2789 }
2790
convert_unicode(CPUS390XState * env,uint32_t r1,uint32_t r2,uint32_t m3,uintptr_t ra,decode_unicode_fn decode,encode_unicode_fn encode)2791 static inline uint32_t convert_unicode(CPUS390XState *env, uint32_t r1,
2792 uint32_t r2, uint32_t m3, uintptr_t ra,
2793 decode_unicode_fn decode,
2794 encode_unicode_fn encode)
2795 {
2796 uint64_t dst = get_address(env, r1);
2797 uint64_t dlen = get_length(env, r1 + 1);
2798 uint64_t src = get_address(env, r2);
2799 uint64_t slen = get_length(env, r2 + 1);
2800 bool enh_check = m3 & 1;
2801 int cc, i;
2802
2803 /* Lest we fail to service interrupts in a timely manner, limit the
2804 amount of work we're willing to do. For now, let's cap at 256. */
2805 for (i = 0; i < 256; ++i) {
2806 uint32_t c, ilen, olen;
2807
2808 cc = decode(env, src, slen, enh_check, ra, &c, &ilen);
2809 if (unlikely(cc >= 0)) {
2810 break;
2811 }
2812 cc = encode(env, dst, dlen, ra, c, &olen);
2813 if (unlikely(cc >= 0)) {
2814 break;
2815 }
2816
2817 src += ilen;
2818 slen -= ilen;
2819 dst += olen;
2820 dlen -= olen;
2821 cc = 3;
2822 }
2823
2824 set_address(env, r1, dst);
2825 set_length(env, r1 + 1, dlen);
2826 set_address(env, r2, src);
2827 set_length(env, r2 + 1, slen);
2828
2829 return cc;
2830 }
2831
HELPER(cu12)2832 uint32_t HELPER(cu12)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2833 {
2834 return convert_unicode(env, r1, r2, m3, GETPC(),
2835 decode_utf8, encode_utf16);
2836 }
2837
HELPER(cu14)2838 uint32_t HELPER(cu14)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2839 {
2840 return convert_unicode(env, r1, r2, m3, GETPC(),
2841 decode_utf8, encode_utf32);
2842 }
2843
HELPER(cu21)2844 uint32_t HELPER(cu21)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2845 {
2846 return convert_unicode(env, r1, r2, m3, GETPC(),
2847 decode_utf16, encode_utf8);
2848 }
2849
HELPER(cu24)2850 uint32_t HELPER(cu24)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2851 {
2852 return convert_unicode(env, r1, r2, m3, GETPC(),
2853 decode_utf16, encode_utf32);
2854 }
2855
HELPER(cu41)2856 uint32_t HELPER(cu41)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2857 {
2858 return convert_unicode(env, r1, r2, m3, GETPC(),
2859 decode_utf32, encode_utf8);
2860 }
2861
HELPER(cu42)2862 uint32_t HELPER(cu42)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3)
2863 {
2864 return convert_unicode(env, r1, r2, m3, GETPC(),
2865 decode_utf32, encode_utf16);
2866 }
2867
probe_write_access(CPUS390XState * env,uint64_t addr,uint64_t len,uintptr_t ra)2868 void probe_write_access(CPUS390XState *env, uint64_t addr, uint64_t len,
2869 uintptr_t ra)
2870 {
2871 const int mmu_idx = s390x_env_mmu_index(env, false);
2872
2873 /* test the actual access, not just any access to the page due to LAP */
2874 while (len) {
2875 const uint64_t pagelen = -(addr | TARGET_PAGE_MASK);
2876 const uint64_t curlen = MIN(pagelen, len);
2877
2878 probe_write(env, addr, curlen, mmu_idx, ra);
2879 addr = wrap_address(env, addr + curlen);
2880 len -= curlen;
2881 }
2882 }
2883
HELPER(probe_write_access)2884 void HELPER(probe_write_access)(CPUS390XState *env, uint64_t addr, uint64_t len)
2885 {
2886 probe_write_access(env, addr, len, GETPC());
2887 }
2888