1
2
3
4
5
6
7
8
9
10
11
12#include "qemu/osdep.h"
13#include "cpu.h"
14#include "s390x-internal.h"
15#include "vec.h"
16#include "tcg/tcg.h"
17#include "tcg/tcg-gvec-desc.h"
18#include "exec/helper-proto.h"
19#include "exec/cpu_ldst.h"
20#include "exec/exec-all.h"
21
22void HELPER(gvec_vbperm)(void *v1, const void *v2, const void *v3,
23 uint32_t desc)
24{
25 S390Vector tmp = {};
26 uint16_t result = 0;
27 int i;
28
29 for (i = 0; i < 16; i++) {
30 const uint8_t bit_nr = s390_vec_read_element8(v3, i);
31 uint16_t bit;
32
33 if (bit_nr >= 128) {
34 continue;
35 }
36 bit = (s390_vec_read_element8(v2, bit_nr / 8)
37 >> (7 - (bit_nr % 8))) & 1;
38 result |= (bit << (15 - i));
39 }
40 s390_vec_write_element16(&tmp, 3, result);
41 *(S390Vector *)v1 = tmp;
42}
43
44void HELPER(vll)(CPUS390XState *env, void *v1, uint64_t addr, uint64_t bytes)
45{
46 if (likely(bytes >= 16)) {
47 uint64_t t0, t1;
48
49 t0 = cpu_ldq_data_ra(env, addr, GETPC());
50 addr = wrap_address(env, addr + 8);
51 t1 = cpu_ldq_data_ra(env, addr, GETPC());
52 s390_vec_write_element64(v1, 0, t0);
53 s390_vec_write_element64(v1, 1, t1);
54 } else {
55 S390Vector tmp = {};
56 int i;
57
58 for (i = 0; i < bytes; i++) {
59 uint8_t byte = cpu_ldub_data_ra(env, addr, GETPC());
60
61 s390_vec_write_element8(&tmp, i, byte);
62 addr = wrap_address(env, addr + 1);
63 }
64 *(S390Vector *)v1 = tmp;
65 }
66}
67
68#define DEF_VPK_HFN(BITS, TBITS) \
69typedef uint##TBITS##_t (*vpk##BITS##_fn)(uint##BITS##_t, int *); \
70static int vpk##BITS##_hfn(S390Vector *v1, const S390Vector *v2, \
71 const S390Vector *v3, vpk##BITS##_fn fn) \
72{ \
73 int i, saturated = 0; \
74 S390Vector tmp; \
75 \
76 for (i = 0; i < (128 / TBITS); i++) { \
77 uint##BITS##_t src; \
78 \
79 if (i < (128 / BITS)) { \
80 src = s390_vec_read_element##BITS(v2, i); \
81 } else { \
82 src = s390_vec_read_element##BITS(v3, i - (128 / BITS)); \
83 } \
84 s390_vec_write_element##TBITS(&tmp, i, fn(src, &saturated)); \
85 } \
86 *v1 = tmp; \
87 return saturated; \
88}
89DEF_VPK_HFN(64, 32)
90DEF_VPK_HFN(32, 16)
91DEF_VPK_HFN(16, 8)
92
93#define DEF_VPK(BITS, TBITS) \
94static uint##TBITS##_t vpk##BITS##e(uint##BITS##_t src, int *saturated) \
95{ \
96 return src; \
97} \
98void HELPER(gvec_vpk##BITS)(void *v1, const void *v2, const void *v3, \
99 uint32_t desc) \
100{ \
101 vpk##BITS##_hfn(v1, v2, v3, vpk##BITS##e); \
102}
103DEF_VPK(64, 32)
104DEF_VPK(32, 16)
105DEF_VPK(16, 8)
106
107#define DEF_VPKS(BITS, TBITS) \
108static uint##TBITS##_t vpks##BITS##e(uint##BITS##_t src, int *saturated) \
109{ \
110 if ((int##BITS##_t)src > INT##TBITS##_MAX) { \
111 (*saturated)++; \
112 return INT##TBITS##_MAX; \
113 } else if ((int##BITS##_t)src < INT##TBITS##_MIN) { \
114 (*saturated)++; \
115 return INT##TBITS##_MIN; \
116 } \
117 return src; \
118} \
119void HELPER(gvec_vpks##BITS)(void *v1, const void *v2, const void *v3, \
120 uint32_t desc) \
121{ \
122 vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \
123} \
124void HELPER(gvec_vpks_cc##BITS)(void *v1, const void *v2, const void *v3, \
125 CPUS390XState *env, uint32_t desc) \
126{ \
127 int saturated = vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \
128 \
129 if (saturated == (128 / TBITS)) { \
130 env->cc_op = 3; \
131 } else if (saturated) { \
132 env->cc_op = 1; \
133 } else { \
134 env->cc_op = 0; \
135 } \
136}
137DEF_VPKS(64, 32)
138DEF_VPKS(32, 16)
139DEF_VPKS(16, 8)
140
141#define DEF_VPKLS(BITS, TBITS) \
142static uint##TBITS##_t vpkls##BITS##e(uint##BITS##_t src, int *saturated) \
143{ \
144 if (src > UINT##TBITS##_MAX) { \
145 (*saturated)++; \
146 return UINT##TBITS##_MAX; \
147 } \
148 return src; \
149} \
150void HELPER(gvec_vpkls##BITS)(void *v1, const void *v2, const void *v3, \
151 uint32_t desc) \
152{ \
153 vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \
154} \
155void HELPER(gvec_vpkls_cc##BITS)(void *v1, const void *v2, const void *v3, \
156 CPUS390XState *env, uint32_t desc) \
157{ \
158 int saturated = vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \
159 \
160 if (saturated == (128 / TBITS)) { \
161 env->cc_op = 3; \
162 } else if (saturated) { \
163 env->cc_op = 1; \
164 } else { \
165 env->cc_op = 0; \
166 } \
167}
168DEF_VPKLS(64, 32)
169DEF_VPKLS(32, 16)
170DEF_VPKLS(16, 8)
171
172void HELPER(gvec_vperm)(void *v1, const void *v2, const void *v3,
173 const void *v4, uint32_t desc)
174{
175 S390Vector tmp;
176 int i;
177
178 for (i = 0; i < 16; i++) {
179 const uint8_t selector = s390_vec_read_element8(v4, i) & 0x1f;
180 uint8_t byte;
181
182 if (selector < 16) {
183 byte = s390_vec_read_element8(v2, selector);
184 } else {
185 byte = s390_vec_read_element8(v3, selector - 16);
186 }
187 s390_vec_write_element8(&tmp, i, byte);
188 }
189 *(S390Vector *)v1 = tmp;
190}
191
192void HELPER(vstl)(CPUS390XState *env, const void *v1, uint64_t addr,
193 uint64_t bytes)
194{
195
196 probe_write_access(env, addr, bytes, GETPC());
197
198 if (likely(bytes >= 16)) {
199 cpu_stq_data_ra(env, addr, s390_vec_read_element64(v1, 0), GETPC());
200 addr = wrap_address(env, addr + 8);
201 cpu_stq_data_ra(env, addr, s390_vec_read_element64(v1, 1), GETPC());
202 } else {
203 int i;
204
205 for (i = 0; i < bytes; i++) {
206 uint8_t byte = s390_vec_read_element8(v1, i);
207
208 cpu_stb_data_ra(env, addr, byte, GETPC());
209 addr = wrap_address(env, addr + 1);
210 }
211 }
212}
213