/* * Test CDSG instruction. * * Increment the first half of aligned_quadword by 1, and the second half by 2 * from 2 threads. Verify that the result is consistent. * * SPDX-License-Identifier: GPL-2.0-or-later */ #include #include #include #include static volatile bool start; typedef unsigned long aligned_quadword[2] __attribute__((__aligned__(16))); static aligned_quadword val; static const int n_iterations = 1000000; static inline int cdsg(unsigned long *orig0, unsigned long *orig1, unsigned long new0, unsigned long new1, aligned_quadword *mem) { register unsigned long r0 asm("r0"); register unsigned long r1 asm("r1"); register unsigned long r2 asm("r2"); register unsigned long r3 asm("r3"); int cc; r0 = *orig0; r1 = *orig1; r2 = new0; r3 = new1; asm("cdsg %[r0],%[r2],%[db2]\n" "ipm %[cc]" : [r0] "+r" (r0) , [r1] "+r" (r1) , [db2] "+m" (*mem) , [cc] "=r" (cc) : [r2] "r" (r2) , [r3] "r" (r3) : "cc"); *orig0 = r0; *orig1 = r1; return (cc >> 28) & 3; } void *cdsg_loop(void *arg) { unsigned long orig0, orig1, new0, new1; int cc; int i; while (!start) { } orig0 = val[0]; orig1 = val[1]; for (i = 0; i < n_iterations;) { new0 = orig0 + 1; new1 = orig1 + 2; cc = cdsg(&orig0, &orig1, new0, new1, &val); if (cc == 0) { orig0 = new0; orig1 = new1; i++; } else { assert(cc == 1); } } return NULL; } int main(void) { pthread_t thread; int ret; ret = pthread_create(&thread, NULL, cdsg_loop, NULL); assert(ret == 0); start = true; cdsg_loop(NULL); ret = pthread_join(thread, NULL); assert(ret == 0); assert(val[0] == n_iterations * 2); assert(val[1] == n_iterations * 4); return EXIT_SUCCESS; }