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