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