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