xref: /qemu/tests/tcg/s390x/vrep.c (revision 024d7caf)
1024d7cafSIlya Leoshkevich /*
2024d7cafSIlya Leoshkevich  * Test the VREP instruction.
3024d7cafSIlya Leoshkevich  *
4024d7cafSIlya Leoshkevich  * SPDX-License-Identifier: GPL-2.0-or-later
5024d7cafSIlya Leoshkevich  */
6024d7cafSIlya Leoshkevich #include <assert.h>
7024d7cafSIlya Leoshkevich #include <signal.h>
8024d7cafSIlya Leoshkevich #include <stdbool.h>
9024d7cafSIlya Leoshkevich #include <stdint.h>
10024d7cafSIlya Leoshkevich #include <stdlib.h>
11024d7cafSIlya Leoshkevich #include <string.h>
12024d7cafSIlya Leoshkevich #include <unistd.h>
13024d7cafSIlya Leoshkevich #include "vx.h"
14024d7cafSIlya Leoshkevich 
handle_sigill(int sig,siginfo_t * info,void * ucontext)15024d7cafSIlya Leoshkevich static void handle_sigill(int sig, siginfo_t *info, void *ucontext)
16024d7cafSIlya Leoshkevich {
17024d7cafSIlya Leoshkevich     mcontext_t *mcontext = &((ucontext_t *)ucontext)->uc_mcontext;
18024d7cafSIlya Leoshkevich     char *insn = (char *)info->si_addr;
19024d7cafSIlya Leoshkevich 
20024d7cafSIlya Leoshkevich     if (insn[0] != 0xe7 || insn[5] != 0x4d) {
21024d7cafSIlya Leoshkevich         _exit(EXIT_FAILURE);
22024d7cafSIlya Leoshkevich     }
23024d7cafSIlya Leoshkevich 
24024d7cafSIlya Leoshkevich     mcontext->gregs[2] = SIGILL;
25024d7cafSIlya Leoshkevich }
26024d7cafSIlya Leoshkevich 
27024d7cafSIlya Leoshkevich static inline __attribute__((__always_inline__)) unsigned long
vrep(S390Vector * v1,const S390Vector * v3,const uint16_t i2,const uint8_t m4)28024d7cafSIlya Leoshkevich vrep(S390Vector *v1, const S390Vector *v3, const uint16_t i2, const uint8_t m4)
29024d7cafSIlya Leoshkevich {
30024d7cafSIlya Leoshkevich     register unsigned long sig asm("r2") = -1;
31024d7cafSIlya Leoshkevich 
32024d7cafSIlya Leoshkevich     asm("vrep %[v1],%[v3],%[i2],%[m4]\n"
33024d7cafSIlya Leoshkevich         : [v1] "=v" (v1->v)
34024d7cafSIlya Leoshkevich         , [sig] "+r" (sig)
35024d7cafSIlya Leoshkevich         : [v3] "v" (v3->v)
36024d7cafSIlya Leoshkevich         , [i2] "i" (i2)
37024d7cafSIlya Leoshkevich         , [m4] "i" (m4));
38024d7cafSIlya Leoshkevich 
39024d7cafSIlya Leoshkevich     return sig;
40024d7cafSIlya Leoshkevich }
41024d7cafSIlya Leoshkevich 
main(int argc,char * argv[])42024d7cafSIlya Leoshkevich int main(int argc, char *argv[])
43024d7cafSIlya Leoshkevich {
44024d7cafSIlya Leoshkevich     S390Vector v3 = {.d[0] = 1, .d[1] = 2};
45024d7cafSIlya Leoshkevich     struct sigaction act;
46024d7cafSIlya Leoshkevich     S390Vector v1;
47024d7cafSIlya Leoshkevich     int err;
48024d7cafSIlya Leoshkevich 
49024d7cafSIlya Leoshkevich     memset(&act, 0, sizeof(act));
50024d7cafSIlya Leoshkevich     act.sa_sigaction = handle_sigill;
51024d7cafSIlya Leoshkevich     act.sa_flags = SA_SIGINFO;
52024d7cafSIlya Leoshkevich     err = sigaction(SIGILL, &act, NULL);
53024d7cafSIlya Leoshkevich     assert(err == 0);
54024d7cafSIlya Leoshkevich 
55024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 7, 0) == -1);
56024d7cafSIlya Leoshkevich     assert(v1.d[0] == 0x0101010101010101ULL);
57024d7cafSIlya Leoshkevich     assert(v1.d[1] == 0x0101010101010101ULL);
58024d7cafSIlya Leoshkevich 
59024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 7, 1) == -1);
60024d7cafSIlya Leoshkevich     assert(v1.d[0] == 0x0002000200020002ULL);
61024d7cafSIlya Leoshkevich     assert(v1.d[1] == 0x0002000200020002ULL);
62024d7cafSIlya Leoshkevich 
63024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 1, 2) == -1);
64024d7cafSIlya Leoshkevich     assert(v1.d[0] == 0x0000000100000001ULL);
65024d7cafSIlya Leoshkevich     assert(v1.d[1] == 0x0000000100000001ULL);
66024d7cafSIlya Leoshkevich 
67024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 1, 3) == -1);
68024d7cafSIlya Leoshkevich     assert(v1.d[0] == 2);
69024d7cafSIlya Leoshkevich     assert(v1.d[1] == 2);
70024d7cafSIlya Leoshkevich 
71024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 0x10, 0) == SIGILL);
72024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 0x101, 0) == SIGILL);
73024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 0x8, 1) == SIGILL);
74024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 0x108, 1) == SIGILL);
75024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 0x4, 2) == SIGILL);
76024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 0x104, 2) == SIGILL);
77024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 0x2, 3) == SIGILL);
78024d7cafSIlya Leoshkevich     assert(vrep(&v1, &v3, 0x102, 3) == SIGILL);
79024d7cafSIlya Leoshkevich 
80024d7cafSIlya Leoshkevich     return EXIT_SUCCESS;
81024d7cafSIlya Leoshkevich }
82