xref: /openbmc/qemu/tests/tcg/s390x/cdsg.c (revision 8c6631e6)
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