master
inc 1,013 lines 24.7 KB
Raw
1 /*
2 * Routines common to user and system emulation of load/store.
3 *
4 * Copyright (c) 2022 Linaro, Ltd.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 *
8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
9 * See the COPYING file in the top-level directory.
10 */
11
12 #include "host/load-extract-al16-al8.h.inc"
13 #include "host/store-insert-al16.h.inc"
14
15 /**
16 * required_atomicity:
17 *
18 * Return the lg2 bytes of atomicity required by @memop for @p.
19 * If the operation must be split into two operations to be
20 * examined separately for atomicity, return -lg2.
21 */
22 static int required_atomicity(CPUState *cpu, uintptr_t p, MemOp memop)
23 {
24 MemOp atom = memop & MO_ATOM_MASK;
25 MemOp size = memop & MO_SIZE;
26 MemOp half = size ? size - 1 : 0;
27 unsigned tmp;
28 int atmax;
29
30 switch (atom) {
31 case MO_ATOM_NONE:
32 atmax = MO_8;
33 break;
34
35 case MO_ATOM_IFALIGN_PAIR:
36 size = half;
37 /* fall through */
38
39 case MO_ATOM_IFALIGN:
40 tmp = (1 << size) - 1;
41 atmax = p & tmp ? MO_8 : size;
42 break;
43
44 case MO_ATOM_WITHIN16:
45 tmp = p & 15;
46 atmax = (tmp + (1 << size) <= 16 ? size : MO_8);
47 break;
48
49 case MO_ATOM_WITHIN16_PAIR:
50 tmp = p & 15;
51 if (tmp + (1 << size) <= 16) {
52 atmax = size;
53 } else if (tmp + (1 << half) == 16) {
54 /*
55 * The pair exactly straddles the boundary.
56 * Both halves are naturally aligned and atomic.
57 */
58 atmax = half;
59 } else {
60 /*
61 * One of the pair crosses the boundary, and is non-atomic.
62 * The other of the pair does not cross, and is atomic.
63 */
64 atmax = -half;
65 }
66 break;
67
68 case MO_ATOM_SUBALIGN:
69 /*
70 * Examine the alignment of p to determine if there are subobjects
71 * that must be aligned. Note that we only really need ctz4() --
72 * any more significant bits are discarded by the immediately
73 * following comparison.
74 */
75 tmp = ctz32(p);
76 atmax = MIN(size, tmp);
77 break;
78
79 default:
80 g_assert_not_reached();
81 }
82
83 /*
84 * Here we have the architectural atomicity of the operation.
85 * However, when executing in a serial context, we need no extra
86 * host atomicity in order to avoid racing. This reduction
87 * avoids looping with cpu_loop_exit_atomic.
88 */
89 if (cpu_in_serial_context(cpu)) {
90 return MO_8;
91 }
92 return atmax;
93 }
94
95 /**
96 * load_atomic2:
97 * @pv: host address
98 *
99 * Atomically load 2 aligned bytes from @pv.
100 */
101 static inline uint16_t load_atomic2(void *pv)
102 {
103 uint16_t *p = __builtin_assume_aligned(pv, 2);
104 return qatomic_read(p);
105 }
106
107 /**
108 * load_atomic4:
109 * @pv: host address
110 *
111 * Atomically load 4 aligned bytes from @pv.
112 */
113 static inline uint32_t load_atomic4(void *pv)
114 {
115 uint32_t *p = __builtin_assume_aligned(pv, 4);
116 return qatomic_read(p);
117 }
118
119 /**
120 * load_atomic8:
121 * @pv: host address
122 *
123 * Atomically load 8 aligned bytes from @pv.
124 */
125 static inline uint64_t load_atomic8(void *pv)
126 {
127 uint64_t *p = __builtin_assume_aligned(pv, 8);
128 return qatomic_read(p);
129 }
130
131 /**
132 * load_atomic16_or_exit:
133 * @cpu: generic cpu state
134 * @ra: host unwind address
135 * @pv: host address
136 *
137 * Atomically load 16 aligned bytes from @pv.
138 * If this is not possible, longjmp out to restart serially.
139 */
140 static Int128 load_atomic16_or_exit(CPUState *cpu, uintptr_t ra, void *pv)
141 {
142 Int128 *p = __builtin_assume_aligned(pv, 16);
143
144 if (HAVE_ATOMIC128_RO) {
145 return atomic16_read_ro(p);
146 }
147
148 /*
149 * We can only use cmpxchg to emulate a load if the page is writable.
150 * If the page is not writable, then assume the value is immutable
151 * and requires no locking. This ignores the case of MAP_SHARED with
152 * another process, because the fallback start_exclusive solution
153 * provides no protection across processes.
154 *
155 * In system mode all guest pages are writable. For user mode,
156 * we must take mmap_lock so that the query remains valid until
157 * the write is complete -- tests/tcg/multiarch/munmap-pthread.c
158 * is an example that can race.
159 */
160 WITH_MMAP_LOCK_GUARD() {
161 #ifdef CONFIG_USER_ONLY
162 if (!page_check_range(h2g(p), 16, PAGE_WRITE_ORG)) {
163 return *p;
164 }
165 #endif
166 if (HAVE_ATOMIC128_RW) {
167 return atomic16_read_rw(p);
168 }
169 }
170
171 /* Ultimate fallback: re-execute in serial context. */
172 trace_load_atom16_or_exit_fallback(ra);
173 cpu_loop_exit_atomic(cpu, ra);
174 }
175
176 /**
177 * load_atom_extract_al4x2:
178 * @pv: host address
179 *
180 * Load 4 bytes from @p, from two sequential atomic 4-byte loads.
181 */
182 static uint32_t load_atom_extract_al4x2(void *pv)
183 {
184 uintptr_t pi = (uintptr_t)pv;
185 int sh = (pi & 3) * 8;
186 uint32_t a, b;
187
188 pv = (void *)(pi & ~3);
189 a = load_atomic4(pv);
190 b = load_atomic4(pv + 4);
191
192 if (HOST_BIG_ENDIAN) {
193 return (a << sh) | (b >> (-sh & 31));
194 } else {
195 return (a >> sh) | (b << (-sh & 31));
196 }
197 }
198
199 /**
200 * load_atom_extract_al8x2:
201 * @pv: host address
202 *
203 * Load 8 bytes from @p, from two sequential atomic 8-byte loads.
204 */
205 static uint64_t load_atom_extract_al8x2(void *pv)
206 {
207 uintptr_t pi = (uintptr_t)pv;
208 int sh = (pi & 7) * 8;
209 uint64_t a, b;
210
211 pv = (void *)(pi & ~7);
212 a = load_atomic8(pv);
213 b = load_atomic8(pv + 8);
214
215 if (HOST_BIG_ENDIAN) {
216 return (a << sh) | (b >> (-sh & 63));
217 } else {
218 return (a >> sh) | (b << (-sh & 63));
219 }
220 }
221
222 /**
223 * load_atom_extract_al8
224 * @pv: host address
225 * @s: object size in bytes, @s <= 4.
226 *
227 * Atomically load @s bytes from @p, when p % s != 0, and [p, p+s-1] does
228 * not cross an 8-byte boundary. This means that we can perform an atomic
229 * 8-byte load and extract.
230 * The value is returned in the low bits of a uint32_t.
231 */
232 static uint32_t load_atom_extract_al8(void *pv, int s)
233 {
234 uintptr_t pi = (uintptr_t)pv;
235 int o = pi & 7;
236 int shr = (HOST_BIG_ENDIAN ? 8 - s - o : o) * 8;
237
238 pv = (void *)(pi & ~7);
239 return load_atomic8(pv) >> shr;
240 }
241
242 /**
243 * load_atom_extract_al16_or_exit:
244 * @cpu: generic cpu state
245 * @ra: host unwind address
246 * @p: host address
247 * @s: object size in bytes, @s <= 8.
248 *
249 * Atomically load @s bytes from @p, when p % 16 < 8
250 * and p % 16 + s > 8. I.e. does not cross a 16-byte
251 * boundary, but *does* cross an 8-byte boundary.
252 * This is the slow version, so we must have eliminated
253 * any faster load_atom_extract_al8 case.
254 *
255 * If this is not possible, longjmp out to restart serially.
256 */
257 static uint64_t load_atom_extract_al16_or_exit(CPUState *cpu, uintptr_t ra,
258 void *pv, int s)
259 {
260 uintptr_t pi = (uintptr_t)pv;
261 int o = pi & 7;
262 int shr = (HOST_BIG_ENDIAN ? 16 - s - o : o) * 8;
263 Int128 r;
264
265 /*
266 * Note constraints above: p & 8 must be clear.
267 * Provoke SIGBUS if possible otherwise.
268 */
269 pv = (void *)(pi & ~7);
270 r = load_atomic16_or_exit(cpu, ra, pv);
271
272 r = int128_urshift(r, shr);
273 return int128_getlo(r);
274 }
275
276 /**
277 * load_atom_4_by_2:
278 * @pv: host address
279 *
280 * Load 4 bytes from @pv, with two 2-byte atomic loads.
281 */
282 static inline uint32_t load_atom_4_by_2(void *pv)
283 {
284 uint32_t a = load_atomic2(pv);
285 uint32_t b = load_atomic2(pv + 2);
286
287 if (HOST_BIG_ENDIAN) {
288 return (a << 16) | b;
289 } else {
290 return (b << 16) | a;
291 }
292 }
293
294 /**
295 * load_atom_8_by_2:
296 * @pv: host address
297 *
298 * Load 8 bytes from @pv, with four 2-byte atomic loads.
299 */
300 static inline uint64_t load_atom_8_by_2(void *pv)
301 {
302 uint32_t a = load_atom_4_by_2(pv);
303 uint32_t b = load_atom_4_by_2(pv + 4);
304
305 if (HOST_BIG_ENDIAN) {
306 return ((uint64_t)a << 32) | b;
307 } else {
308 return ((uint64_t)b << 32) | a;
309 }
310 }
311
312 /**
313 * load_atom_8_by_4:
314 * @pv: host address
315 *
316 * Load 8 bytes from @pv, with two 4-byte atomic loads.
317 */
318 static inline uint64_t load_atom_8_by_4(void *pv)
319 {
320 uint32_t a = load_atomic4(pv);
321 uint32_t b = load_atomic4(pv + 4);
322
323 if (HOST_BIG_ENDIAN) {
324 return ((uint64_t)a << 32) | b;
325 } else {
326 return ((uint64_t)b << 32) | a;
327 }
328 }
329
330 /**
331 * load_atom_2:
332 * @p: host address
333 * @memop: the full memory op
334 *
335 * Load 2 bytes from @p, honoring the atomicity of @memop.
336 */
337 static uint16_t load_atom_2(CPUState *cpu, uintptr_t ra,
338 void *pv, MemOp memop)
339 {
340 uintptr_t pi = (uintptr_t)pv;
341 int atmax;
342
343 if (likely((pi & 1) == 0)) {
344 return load_atomic2(pv);
345 }
346 if (HAVE_ATOMIC128_RO) {
347 intptr_t left_in_page = -(pi | TARGET_PAGE_MASK);
348 if (likely(left_in_page > 8)) {
349 return load_atom_extract_al16_or_al8(pv, 2);
350 }
351 }
352
353 atmax = required_atomicity(cpu, pi, memop);
354 switch (atmax) {
355 case MO_8:
356 return lduw_he_p(pv);
357 case MO_16:
358 /* The only case remaining is MO_ATOM_WITHIN16. */
359 if ((pi & 15) != 7) {
360 return load_atom_extract_al8(pv, 2);
361 }
362 return load_atom_extract_al16_or_exit(cpu, ra, pv, 2);
363 default:
364 g_assert_not_reached();
365 }
366 }
367
368 /**
369 * load_atom_4:
370 * @p: host address
371 * @memop: the full memory op
372 *
373 * Load 4 bytes from @p, honoring the atomicity of @memop.
374 */
375 static uint32_t load_atom_4(CPUState *cpu, uintptr_t ra,
376 void *pv, MemOp memop)
377 {
378 uintptr_t pi = (uintptr_t)pv;
379 int atmax;
380
381 if (likely((pi & 3) == 0)) {
382 return load_atomic4(pv);
383 }
384 if (HAVE_ATOMIC128_RO) {
385 intptr_t left_in_page = -(pi | TARGET_PAGE_MASK);
386 if (likely(left_in_page > 8)) {
387 return load_atom_extract_al16_or_al8(pv, 4);
388 }
389 }
390
391 atmax = required_atomicity(cpu, pi, memop);
392 switch (atmax) {
393 case MO_8:
394 case MO_16:
395 case -MO_16:
396 /*
397 * For MO_ATOM_IFALIGN, this is more atomicity than required,
398 * but it's trivially supported on all hosts, better than 4
399 * individual byte loads (when the host requires alignment),
400 * and overlaps with the MO_ATOM_SUBALIGN case of p % 2 == 0.
401 */
402 return load_atom_extract_al4x2(pv);
403 case MO_32:
404 if (!(pi & 4)) {
405 return load_atom_extract_al8(pv, 4);
406 }
407 return load_atom_extract_al16_or_exit(cpu, ra, pv, 4);
408 default:
409 g_assert_not_reached();
410 }
411 }
412
413 /**
414 * load_atom_8:
415 * @p: host address
416 * @memop: the full memory op
417 *
418 * Load 8 bytes from @p, honoring the atomicity of @memop.
419 */
420 static uint64_t load_atom_8(CPUState *cpu, uintptr_t ra,
421 void *pv, MemOp memop)
422 {
423 uintptr_t pi = (uintptr_t)pv;
424 int atmax;
425
426 /*
427 * If the host does not support 8-byte atomics, wait until we have
428 * examined the atomicity parameters below.
429 */
430 if (likely((pi & 7) == 0)) {
431 return load_atomic8(pv);
432 }
433 if (HAVE_ATOMIC128_RO) {
434 return load_atom_extract_al16_or_al8(pv, 8);
435 }
436
437 atmax = required_atomicity(cpu, pi, memop);
438 if (atmax == MO_64) {
439 return load_atom_extract_al16_or_exit(cpu, ra, pv, 8);
440 }
441 return load_atom_extract_al8x2(pv);
442 }
443
444 /**
445 * load_atom_16:
446 * @p: host address
447 * @memop: the full memory op
448 *
449 * Load 16 bytes from @p, honoring the atomicity of @memop.
450 */
451 static Int128 load_atom_16(CPUState *cpu, uintptr_t ra,
452 void *pv, MemOp memop)
453 {
454 uintptr_t pi = (uintptr_t)pv;
455 int atmax;
456 Int128 r;
457 uint64_t a, b;
458
459 /*
460 * If the host does not support 16-byte atomics, wait until we have
461 * examined the atomicity parameters below.
462 */
463 if (HAVE_ATOMIC128_RO && likely((pi & 15) == 0)) {
464 return atomic16_read_ro(pv);
465 }
466
467 atmax = required_atomicity(cpu, pi, memop);
468 switch (atmax) {
469 case MO_8:
470 memcpy(&r, pv, 16);
471 return r;
472 case MO_16:
473 a = load_atom_8_by_2(pv);
474 b = load_atom_8_by_2(pv + 8);
475 break;
476 case MO_32:
477 a = load_atom_8_by_4(pv);
478 b = load_atom_8_by_4(pv + 8);
479 break;
480 case MO_64:
481 a = load_atomic8(pv);
482 b = load_atomic8(pv + 8);
483 break;
484 case -MO_64:
485 a = load_atom_extract_al8x2(pv);
486 b = load_atom_extract_al8x2(pv + 8);
487 break;
488 case MO_128:
489 return load_atomic16_or_exit(cpu, ra, pv);
490 default:
491 g_assert_not_reached();
492 }
493 return int128_make128(HOST_BIG_ENDIAN ? b : a, HOST_BIG_ENDIAN ? a : b);
494 }
495
496 /**
497 * store_atomic2:
498 * @pv: host address
499 * @val: value to store
500 *
501 * Atomically store 2 aligned bytes to @pv.
502 */
503 static inline void store_atomic2(void *pv, uint16_t val)
504 {
505 uint16_t *p = __builtin_assume_aligned(pv, 2);
506 qatomic_set(p, val);
507 }
508
509 /**
510 * store_atomic4:
511 * @pv: host address
512 * @val: value to store
513 *
514 * Atomically store 4 aligned bytes to @pv.
515 */
516 static inline void store_atomic4(void *pv, uint32_t val)
517 {
518 uint32_t *p = __builtin_assume_aligned(pv, 4);
519 qatomic_set(p, val);
520 }
521
522 /**
523 * store_atomic8:
524 * @pv: host address
525 * @val: value to store
526 *
527 * Atomically store 8 aligned bytes to @pv.
528 */
529 static inline void store_atomic8(void *pv, uint64_t val)
530 {
531 uint64_t *p = __builtin_assume_aligned(pv, 8);
532 qatomic_set(p, val);
533 }
534
535 /**
536 * store_atom_4x2
537 */
538 static inline void store_atom_4_by_2(void *pv, uint32_t val)
539 {
540 store_atomic2(pv, val >> (HOST_BIG_ENDIAN ? 16 : 0));
541 store_atomic2(pv + 2, val >> (HOST_BIG_ENDIAN ? 0 : 16));
542 }
543
544 /**
545 * store_atom_8_by_2
546 */
547 static inline void store_atom_8_by_2(void *pv, uint64_t val)
548 {
549 store_atom_4_by_2(pv, val >> (HOST_BIG_ENDIAN ? 32 : 0));
550 store_atom_4_by_2(pv + 4, val >> (HOST_BIG_ENDIAN ? 0 : 32));
551 }
552
553 /**
554 * store_atom_8_by_4
555 */
556 static inline void store_atom_8_by_4(void *pv, uint64_t val)
557 {
558 store_atomic4(pv, val >> (HOST_BIG_ENDIAN ? 32 : 0));
559 store_atomic4(pv + 4, val >> (HOST_BIG_ENDIAN ? 0 : 32));
560 }
561
562 /**
563 * store_atom_insert_al4:
564 * @p: host address
565 * @val: shifted value to store
566 * @msk: mask for value to store
567 *
568 * Atomically store @val to @p, masked by @msk.
569 */
570 static void store_atom_insert_al4(uint32_t *p, uint32_t val, uint32_t msk)
571 {
572 uint32_t old, new;
573
574 p = __builtin_assume_aligned(p, 4);
575 old = qatomic_read(p);
576 do {
577 new = (old & ~msk) | val;
578 } while (!__atomic_compare_exchange_n(p, &old, new, true,
579 __ATOMIC_RELAXED, __ATOMIC_RELAXED));
580 }
581
582 /**
583 * store_atom_insert_al8:
584 * @p: host address
585 * @val: shifted value to store
586 * @msk: mask for value to store
587 *
588 * Atomically store @val to @p masked by @msk.
589 */
590 static void store_atom_insert_al8(uint64_t *p, uint64_t val, uint64_t msk)
591 {
592 uint64_t old, new;
593
594 p = __builtin_assume_aligned(p, 8);
595 old = qatomic_read(p);
596 do {
597 new = (old & ~msk) | val;
598 } while (!__atomic_compare_exchange_n(p, &old, new, true,
599 __ATOMIC_RELAXED, __ATOMIC_RELAXED));
600 }
601
602 /**
603 * store_bytes_leN:
604 * @pv: host address
605 * @size: number of bytes to store
606 * @val_le: data to store
607 *
608 * Store @size bytes at @p. The bytes to store are extracted in little-endian order
609 * from @val_le; return the bytes of @val_le beyond @size that have not been stored.
610 */
611 static uint64_t store_bytes_leN(void *pv, int size, uint64_t val_le)
612 {
613 uint8_t *p = pv;
614 for (int i = 0; i < size; i++, val_le >>= 8) {
615 p[i] = val_le;
616 }
617 return val_le;
618 }
619
620 /**
621 * store_parts_leN
622 * @pv: host address
623 * @size: number of bytes to store
624 * @val_le: data to store
625 *
626 * As store_bytes_leN, but atomically on each aligned part.
627 */
628 G_GNUC_UNUSED
629 static uint64_t store_parts_leN(void *pv, int size, uint64_t val_le)
630 {
631 do {
632 int n;
633
634 /* Find minimum of alignment and size */
635 switch (((uintptr_t)pv | size) & 7) {
636 case 4:
637 store_atomic4(pv, le32_to_cpu(val_le));
638 val_le >>= 32;
639 n = 4;
640 break;
641 case 2:
642 case 6:
643 store_atomic2(pv, le16_to_cpu(val_le));
644 val_le >>= 16;
645 n = 2;
646 break;
647 default:
648 *(uint8_t *)pv = val_le;
649 val_le >>= 8;
650 n = 1;
651 break;
652 case 0:
653 g_assert_not_reached();
654 }
655 pv += n;
656 size -= n;
657 } while (size != 0);
658
659 return val_le;
660 }
661
662 /**
663 * store_whole_le4
664 * @pv: host address
665 * @size: number of bytes to store
666 * @val_le: data to store
667 *
668 * As store_bytes_leN, but atomically as a whole.
669 * Four aligned bytes are guaranteed to cover the store.
670 */
671 static uint64_t store_whole_le4(void *pv, int size, uint64_t val_le)
672 {
673 int sz = size * 8;
674 int o = (uintptr_t)pv & 3;
675 int sh = o * 8;
676 uint32_t m = MAKE_64BIT_MASK(0, sz);
677 uint32_t v;
678
679 if (HOST_BIG_ENDIAN) {
680 v = bswap32(val_le) >> sh;
681 m = bswap32(m) >> sh;
682 } else {
683 v = val_le << sh;
684 m <<= sh;
685 }
686 store_atom_insert_al4(pv - o, v, m);
687 return val_le >> sz;
688 }
689
690 /**
691 * store_whole_le8
692 * @pv: host address
693 * @size: number of bytes to store
694 * @val_le: data to store
695 *
696 * As store_bytes_leN, but atomically as a whole.
697 * Eight aligned bytes are guaranteed to cover the store.
698 */
699 static uint64_t store_whole_le8(void *pv, int size, uint64_t val_le)
700 {
701 int sz = size * 8;
702 int o = (uintptr_t)pv & 7;
703 int sh = o * 8;
704 uint64_t m = MAKE_64BIT_MASK(0, sz);
705 uint64_t v;
706
707 if (HOST_BIG_ENDIAN) {
708 v = bswap64(val_le) >> sh;
709 m = bswap64(m) >> sh;
710 } else {
711 v = val_le << sh;
712 m <<= sh;
713 }
714 store_atom_insert_al8(pv - o, v, m);
715 return val_le >> sz;
716 }
717
718 /**
719 * store_whole_le16
720 * @pv: host address
721 * @size: number of bytes to store
722 * @val_le: data to store
723 *
724 * As store_bytes_leN, but atomically as a whole.
725 * 16 aligned bytes are guaranteed to cover the store.
726 */
727 static uint64_t store_whole_le16(void *pv, int size, Int128 val_le)
728 {
729 int sz = size * 8;
730 int o = (uintptr_t)pv & 15;
731 int sh = o * 8;
732 Int128 m, v;
733
734 qemu_build_assert(HAVE_CMPXCHG128);
735
736 /* Like MAKE_64BIT_MASK(0, sz), but larger. */
737 if (sz <= 64) {
738 m = int128_make64(MAKE_64BIT_MASK(0, sz));
739 } else {
740 m = int128_make128(-1, MAKE_64BIT_MASK(0, sz - 64));
741 }
742
743 if (HOST_BIG_ENDIAN) {
744 v = int128_urshift(bswap128(val_le), sh);
745 m = int128_urshift(bswap128(m), sh);
746 } else {
747 v = int128_lshift(val_le, sh);
748 m = int128_lshift(m, sh);
749 }
750 store_atom_insert_al16(pv - o, v, m);
751
752 if (sz <= 64) {
753 return 0;
754 }
755 return int128_gethi(val_le) >> (sz - 64);
756 }
757
758 /**
759 * store_atom_2:
760 * @p: host address
761 * @val: the value to store
762 * @memop: the full memory op
763 *
764 * Store 2 bytes to @p, honoring the atomicity of @memop.
765 */
766 static void store_atom_2(CPUState *cpu, uintptr_t ra,
767 void *pv, MemOp memop, uint16_t val)
768 {
769 uintptr_t pi = (uintptr_t)pv;
770 int atmax;
771
772 if (likely((pi & 1) == 0)) {
773 store_atomic2(pv, val);
774 return;
775 }
776
777 atmax = required_atomicity(cpu, pi, memop);
778 if (atmax == MO_8) {
779 stw_he_p(pv, val);
780 return;
781 }
782
783 /*
784 * The only case remaining is MO_ATOM_WITHIN16.
785 * Big or little endian, we want the middle two bytes in each test.
786 */
787 if ((pi & 3) == 1) {
788 store_atom_insert_al4(pv - 1, (uint32_t)val << 8, MAKE_64BIT_MASK(8, 16));
789 return;
790 } else if ((pi & 7) == 3) {
791 store_atom_insert_al8(pv - 3, (uint64_t)val << 24, MAKE_64BIT_MASK(24, 16));
792 return;
793 } else if ((pi & 15) == 7) {
794 if (HAVE_CMPXCHG128) {
795 Int128 v = int128_lshift(int128_make64(val), 56);
796 Int128 m = int128_lshift(int128_make64(0xffff), 56);
797 store_atom_insert_al16(pv - 7, v, m);
798 return;
799 }
800 } else {
801 g_assert_not_reached();
802 }
803
804 trace_store_atom2_fallback(memop, ra);
805 cpu_loop_exit_atomic(cpu, ra);
806 }
807
808 /**
809 * store_atom_4:
810 * @p: host address
811 * @val: the value to store
812 * @memop: the full memory op
813 *
814 * Store 4 bytes to @p, honoring the atomicity of @memop.
815 */
816 static void store_atom_4(CPUState *cpu, uintptr_t ra,
817 void *pv, MemOp memop, uint32_t val)
818 {
819 uintptr_t pi = (uintptr_t)pv;
820 int atmax;
821
822 if (likely((pi & 3) == 0)) {
823 store_atomic4(pv, val);
824 return;
825 }
826
827 atmax = required_atomicity(cpu, pi, memop);
828 switch (atmax) {
829 case MO_8:
830 stl_he_p(pv, val);
831 return;
832 case MO_16:
833 store_atom_4_by_2(pv, val);
834 return;
835 case -MO_16:
836 {
837 uint32_t val_le = cpu_to_le32(val);
838 int s2 = pi & 3;
839 int s1 = 4 - s2;
840
841 switch (s2) {
842 case 1:
843 val_le = store_whole_le4(pv, s1, val_le);
844 *(uint8_t *)(pv + 3) = val_le;
845 break;
846 case 3:
847 *(uint8_t *)pv = val_le;
848 store_whole_le4(pv + 1, s2, val_le >> 8);
849 break;
850 case 0: /* aligned */
851 case 2: /* atmax MO_16 */
852 default:
853 g_assert_not_reached();
854 }
855 }
856 return;
857 case MO_32:
858 if ((pi & 7) < 4) {
859 store_whole_le8(pv, 4, cpu_to_le32(val));
860 return;
861 } else {
862 if (HAVE_CMPXCHG128) {
863 store_whole_le16(pv, 4, int128_make64(cpu_to_le32(val)));
864 return;
865 }
866 }
867 trace_store_atom4_fallback(memop, ra);
868 cpu_loop_exit_atomic(cpu, ra);
869 default:
870 g_assert_not_reached();
871 }
872 }
873
874 /**
875 * store_atom_8:
876 * @p: host address
877 * @val: the value to store
878 * @memop: the full memory op
879 *
880 * Store 8 bytes to @p, honoring the atomicity of @memop.
881 */
882 static void store_atom_8(CPUState *cpu, uintptr_t ra,
883 void *pv, MemOp memop, uint64_t val)
884 {
885 uintptr_t pi = (uintptr_t)pv;
886 int atmax;
887
888 if (likely((pi & 7) == 0)) {
889 store_atomic8(pv, val);
890 return;
891 }
892
893 atmax = required_atomicity(cpu, pi, memop);
894 switch (atmax) {
895 case MO_8:
896 stq_he_p(pv, val);
897 return;
898 case MO_16:
899 store_atom_8_by_2(pv, val);
900 return;
901 case MO_32:
902 store_atom_8_by_4(pv, val);
903 return;
904 case -MO_32:
905 {
906 uint64_t val_le = cpu_to_le64(val);
907 int s2 = pi & 7;
908 int s1 = 8 - s2;
909
910 switch (s2) {
911 case 1 ... 3:
912 val_le = store_whole_le8(pv, s1, val_le);
913 store_bytes_leN(pv + s1, s2, val_le);
914 break;
915 case 5 ... 7:
916 val_le = store_bytes_leN(pv, s1, val_le);
917 store_whole_le8(pv + s1, s2, val_le);
918 break;
919 case 0: /* aligned */
920 case 4: /* atmax MO_32 */
921 default:
922 g_assert_not_reached();
923 }
924 }
925 return;
926 case MO_64:
927 if (HAVE_CMPXCHG128) {
928 store_whole_le16(pv, 8, int128_make64(cpu_to_le64(val)));
929 return;
930 }
931 break;
932 default:
933 g_assert_not_reached();
934 }
935 trace_store_atom8_fallback(memop, ra);
936 cpu_loop_exit_atomic(cpu, ra);
937 }
938
939 /**
940 * store_atom_16:
941 * @p: host address
942 * @val: the value to store
943 * @memop: the full memory op
944 *
945 * Store 16 bytes to @p, honoring the atomicity of @memop.
946 */
947 static void store_atom_16(CPUState *cpu, uintptr_t ra,
948 void *pv, MemOp memop, Int128 val)
949 {
950 uintptr_t pi = (uintptr_t)pv;
951 uint64_t a, b;
952 int atmax;
953
954 if (HAVE_ATOMIC128_RW && likely((pi & 15) == 0)) {
955 atomic16_set(pv, val);
956 return;
957 }
958
959 atmax = required_atomicity(cpu, pi, memop);
960
961 a = HOST_BIG_ENDIAN ? int128_gethi(val) : int128_getlo(val);
962 b = HOST_BIG_ENDIAN ? int128_getlo(val) : int128_gethi(val);
963 switch (atmax) {
964 case MO_8:
965 memcpy(pv, &val, 16);
966 return;
967 case MO_16:
968 store_atom_8_by_2(pv, a);
969 store_atom_8_by_2(pv + 8, b);
970 return;
971 case MO_32:
972 store_atom_8_by_4(pv, a);
973 store_atom_8_by_4(pv + 8, b);
974 return;
975 case MO_64:
976 store_atomic8(pv, a);
977 store_atomic8(pv + 8, b);
978 return;
979 case -MO_64:
980 if (HAVE_CMPXCHG128) {
981 uint64_t val_le;
982 int s2 = pi & 15;
983 int s1 = 16 - s2;
984
985 if (HOST_BIG_ENDIAN) {
986 val = bswap128(val);
987 }
988 switch (s2) {
989 case 1 ... 7:
990 val_le = store_whole_le16(pv, s1, val);
991 store_bytes_leN(pv + s1, s2, val_le);
992 break;
993 case 9 ... 15:
994 store_bytes_leN(pv, s1, int128_getlo(val));
995 val = int128_urshift(val, s1 * 8);
996 store_whole_le16(pv + s1, s2, val);
997 break;
998 case 0: /* aligned */
999 case 8: /* atmax MO_64 */
1000 default:
1001 g_assert_not_reached();
1002 }
1003 return;
1004 }
1005 break;
1006 case MO_128:
1007 break;
1008 default:
1009 g_assert_not_reached();
1010 }
1011 trace_store_atom16_fallback(memop, ra);
1012 cpu_loop_exit_atomic(cpu, ra);
1013 }