| 1 | /* |
| 2 | * Test CDSG instruction. |
| 3 | * |
| 4 | * Increment the first half of aligned_quadword by 1, and the second half by 2 |
| 5 | * from 2 threads. Verify that the result is consistent. |
| 6 | * |
| 7 | * SPDX-License-Identifier: GPL-2.0-or-later |
| 8 | */ |
| 9 | #include <assert.h> |
| 10 | #include <pthread.h> |
| 11 | #include <stdbool.h> |
| 12 | #include <stdlib.h> |
| 13 | |
| 14 | static volatile bool start; |
| 15 | typedef unsigned long aligned_quadword[2] __attribute__((__aligned__(16))); |
| 16 | static aligned_quadword val; |
| 17 | static const int n_iterations = 1000000; |
| 18 | |
| 19 | static inline int cdsg(unsigned long *orig0, unsigned long *orig1, |
| 20 | unsigned long new0, unsigned long new1, |
| 21 | aligned_quadword *mem) |
| 22 | { |
| 23 | register unsigned long r0 asm("r0"); |
| 24 | register unsigned long r1 asm("r1"); |
| 25 | register unsigned long r2 asm("r2"); |
| 26 | register unsigned long r3 asm("r3"); |
| 27 | int cc; |
| 28 | |
| 29 | r0 = *orig0; |
| 30 | r1 = *orig1; |
| 31 | r2 = new0; |
| 32 | r3 = new1; |
| 33 | asm("cdsg %[r0],%[r2],%[db2]\n" |
| 34 | "ipm %[cc]" |
| 35 | : [r0] "+r" (r0) |
| 36 | , [r1] "+r" (r1) |
| 37 | , [db2] "+m" (*mem) |
| 38 | , [cc] "=r" (cc) |
| 39 | : [r2] "r" (r2) |
| 40 | , [r3] "r" (r3) |
| 41 | : "cc"); |
| 42 | *orig0 = r0; |
| 43 | *orig1 = r1; |
| 44 | |
| 45 | return (cc >> 28) & 3; |
| 46 | } |
| 47 | |
| 48 | void *cdsg_loop(void *arg) |
| 49 | { |
| 50 | unsigned long orig0, orig1, new0, new1; |
| 51 | int cc; |
| 52 | int i; |
| 53 | |
| 54 | while (!start) { |
| 55 | } |
| 56 | |
| 57 | orig0 = val[0]; |
| 58 | orig1 = val[1]; |
| 59 | for (i = 0; i < n_iterations;) { |
| 60 | new0 = orig0 + 1; |
| 61 | new1 = orig1 + 2; |
| 62 | |
| 63 | cc = cdsg(&orig0, &orig1, new0, new1, &val); |
| 64 | |
| 65 | if (cc == 0) { |
| 66 | orig0 = new0; |
| 67 | orig1 = new1; |
| 68 | i++; |
| 69 | } else { |
| 70 | assert(cc == 1); |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | return NULL; |
| 75 | } |
| 76 | |
| 77 | int main(void) |
| 78 | { |
| 79 | pthread_t thread; |
| 80 | int ret; |
| 81 | |
| 82 | ret = pthread_create(&thread, NULL, cdsg_loop, NULL); |
| 83 | assert(ret == 0); |
| 84 | start = true; |
| 85 | cdsg_loop(NULL); |
| 86 | ret = pthread_join(thread, NULL); |
| 87 | assert(ret == 0); |
| 88 | |
| 89 | assert(val[0] == n_iterations * 2); |
| 90 | assert(val[1] == n_iterations * 4); |
| 91 | |
| 92 | return EXIT_SUCCESS; |
| 93 | } |