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