xref: /openbmc/qemu/target/s390x/tcg/vec.h (revision d0bf492f)
1 /*
2  * QEMU TCG support -- s390x vector utilitites
3  *
4  * Copyright (C) 2019 Red Hat Inc
5  *
6  * Authors:
7  *   David Hildenbrand <david@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  */
12 #ifndef S390X_VEC_H
13 #define S390X_VEC_H
14 
15 #include "tcg/tcg.h"
16 
17 typedef union S390Vector {
18     uint64_t doubleword[2];
19     uint32_t word[4];
20     uint16_t halfword[8];
21     uint8_t byte[16];
22 } S390Vector;
23 
24 /*
25  * Each vector is stored as two 64bit host values. So when talking about
26  * byte/halfword/word numbers, we have to take care of proper translation
27  * between element numbers.
28  *
29  * Big Endian (target/possible host)
30  * B:  [ 0][ 1][ 2][ 3][ 4][ 5][ 6][ 7] - [ 8][ 9][10][11][12][13][14][15]
31  * HW: [     0][     1][     2][     3] - [     4][     5][     6][     7]
32  * W:  [             0][             1] - [             2][             3]
33  * DW: [                             0] - [                             1]
34  *
35  * Little Endian (possible host)
36  * B:  [ 7][ 6][ 5][ 4][ 3][ 2][ 1][ 0] - [15][14][13][12][11][10][ 9][ 8]
37  * HW: [     3][     2][     1][     0] - [     7][     6][     5][     4]
38  * W:  [             1][             0] - [             3][             2]
39  * DW: [                             0] - [                             1]
40  */
41 #if !HOST_BIG_ENDIAN
42 #define H1(x)  ((x) ^ 7)
43 #define H2(x)  ((x) ^ 3)
44 #define H4(x)  ((x) ^ 1)
45 #else
46 #define H1(x)  (x)
47 #define H2(x)  (x)
48 #define H4(x)  (x)
49 #endif
50 
51 static inline uint8_t s390_vec_read_element8(const S390Vector *v, uint8_t enr)
52 {
53     g_assert(enr < 16);
54     return v->byte[H1(enr)];
55 }
56 
57 static inline uint16_t s390_vec_read_element16(const S390Vector *v, uint8_t enr)
58 {
59     g_assert(enr < 8);
60     return v->halfword[H2(enr)];
61 }
62 
63 static inline uint32_t s390_vec_read_element32(const S390Vector *v, uint8_t enr)
64 {
65     g_assert(enr < 4);
66     return v->word[H4(enr)];
67 }
68 
69 static inline uint64_t s390_vec_read_element64(const S390Vector *v, uint8_t enr)
70 {
71     g_assert(enr < 2);
72     return v->doubleword[enr];
73 }
74 
75 static inline uint64_t s390_vec_read_element(const S390Vector *v, uint8_t enr,
76                                              uint8_t es)
77 {
78     switch (es) {
79     case MO_8:
80         return s390_vec_read_element8(v, enr);
81     case MO_16:
82         return s390_vec_read_element16(v, enr);
83     case MO_32:
84         return s390_vec_read_element32(v, enr);
85     case MO_64:
86         return s390_vec_read_element64(v, enr);
87     default:
88         g_assert_not_reached();
89     }
90 }
91 
92 static inline void s390_vec_write_element8(S390Vector *v, uint8_t enr,
93                                            uint8_t data)
94 {
95     g_assert(enr < 16);
96     v->byte[H1(enr)] = data;
97 }
98 
99 static inline void s390_vec_write_element16(S390Vector *v, uint8_t enr,
100                                             uint16_t data)
101 {
102     g_assert(enr < 8);
103     v->halfword[H2(enr)] = data;
104 }
105 
106 static inline void s390_vec_write_element32(S390Vector *v, uint8_t enr,
107                                             uint32_t data)
108 {
109     g_assert(enr < 4);
110     v->word[H4(enr)] = data;
111 }
112 
113 static inline void s390_vec_write_element64(S390Vector *v, uint8_t enr,
114                                             uint64_t data)
115 {
116     g_assert(enr < 2);
117     v->doubleword[enr] = data;
118 }
119 
120 static inline void s390_vec_write_element(S390Vector *v, uint8_t enr,
121                                           uint8_t es, uint64_t data)
122 {
123     switch (es) {
124     case MO_8:
125         s390_vec_write_element8(v, enr, data);
126         break;
127     case MO_16:
128         s390_vec_write_element16(v, enr, data);
129         break;
130     case MO_32:
131         s390_vec_write_element32(v, enr, data);
132         break;
133     case MO_64:
134         s390_vec_write_element64(v, enr, data);
135         break;
136     default:
137         g_assert_not_reached();
138     }
139 }
140 
141 #endif /* S390X_VEC_H */
142