qemu/tests/tcg/s390x/cdsg.c

94 lines
2.0 KiB
C
Raw Normal View History

/*
* 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 <assert.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>
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;
}