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
s390_vec_read_element8(const S390Vector * v,uint8_t enr)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
s390_vec_read_element16(const S390Vector * v,uint8_t enr)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
s390_vec_read_element32(const S390Vector * v,uint8_t enr)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
s390_vec_read_element64(const S390Vector * v,uint8_t enr)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
s390_vec_read_element(const S390Vector * v,uint8_t enr,uint8_t es)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
s390_vec_write_element8(S390Vector * v,uint8_t enr,uint8_t data)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
s390_vec_write_element16(S390Vector * v,uint8_t enr,uint16_t data)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
s390_vec_write_element32(S390Vector * v,uint8_t enr,uint32_t data)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
s390_vec_write_element64(S390Vector * v,uint8_t enr,uint64_t data)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
s390_vec_write_element(S390Vector * v,uint8_t enr,uint8_t es,uint64_t data)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