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