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 } 94