diff options
Diffstat (limited to 'tests/tcg/s390x/vrep.c')
-rw-r--r-- | tests/tcg/s390x/vrep.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/tests/tcg/s390x/vrep.c b/tests/tcg/s390x/vrep.c new file mode 100644 index 0000000000..d5a3bd8eb2 --- /dev/null +++ b/tests/tcg/s390x/vrep.c @@ -0,0 +1,81 @@ +/* + * Test the VREP instruction. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include <assert.h> +#include <signal.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "vx.h" + +static void handle_sigill(int sig, siginfo_t *info, void *ucontext) +{ + mcontext_t *mcontext = &((ucontext_t *)ucontext)->uc_mcontext; + char *insn = (char *)info->si_addr; + + if (insn[0] != 0xe7 || insn[5] != 0x4d) { + _exit(EXIT_FAILURE); + } + + mcontext->gregs[2] = SIGILL; +} + +static inline __attribute__((__always_inline__)) unsigned long +vrep(S390Vector *v1, const S390Vector *v3, const uint16_t i2, const uint8_t m4) +{ + register unsigned long sig asm("r2") = -1; + + asm("vrep %[v1],%[v3],%[i2],%[m4]\n" + : [v1] "=v" (v1->v) + , [sig] "+r" (sig) + : [v3] "v" (v3->v) + , [i2] "i" (i2) + , [m4] "i" (m4)); + + return sig; +} + +int main(int argc, char *argv[]) +{ + S390Vector v3 = {.d[0] = 1, .d[1] = 2}; + struct sigaction act; + S390Vector v1; + int err; + + memset(&act, 0, sizeof(act)); + act.sa_sigaction = handle_sigill; + act.sa_flags = SA_SIGINFO; + err = sigaction(SIGILL, &act, NULL); + assert(err == 0); + + assert(vrep(&v1, &v3, 7, 0) == -1); + assert(v1.d[0] == 0x0101010101010101ULL); + assert(v1.d[1] == 0x0101010101010101ULL); + + assert(vrep(&v1, &v3, 7, 1) == -1); + assert(v1.d[0] == 0x0002000200020002ULL); + assert(v1.d[1] == 0x0002000200020002ULL); + + assert(vrep(&v1, &v3, 1, 2) == -1); + assert(v1.d[0] == 0x0000000100000001ULL); + assert(v1.d[1] == 0x0000000100000001ULL); + + assert(vrep(&v1, &v3, 1, 3) == -1); + assert(v1.d[0] == 2); + assert(v1.d[1] == 2); + + assert(vrep(&v1, &v3, 0x10, 0) == SIGILL); + assert(vrep(&v1, &v3, 0x101, 0) == SIGILL); + assert(vrep(&v1, &v3, 0x8, 1) == SIGILL); + assert(vrep(&v1, &v3, 0x108, 1) == SIGILL); + assert(vrep(&v1, &v3, 0x4, 2) == SIGILL); + assert(vrep(&v1, &v3, 0x104, 2) == SIGILL); + assert(vrep(&v1, &v3, 0x2, 3) == SIGILL); + assert(vrep(&v1, &v3, 0x102, 3) == SIGILL); + + return EXIT_SUCCESS; +} |