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