2 * QEMU TCG support -- s390x vector support instructions
4 * Copyright (C) 2019 Red Hat Inc
7 * David Hildenbrand <david@redhat.com>
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.
12 #include "qemu/osdep.h"
13 #include "qemu-common.h"
18 #include "tcg/tcg-gvec-desc.h"
19 #include "exec/helper-proto.h"
20 #include "exec/cpu_ldst.h"
21 #include "exec/exec-all.h"
23 void HELPER(vll
)(CPUS390XState
*env
, void *v1
, uint64_t addr
, uint64_t bytes
)
25 if (likely(bytes
>= 16)) {
28 t0
= cpu_ldq_data_ra(env
, addr
, GETPC());
29 addr
= wrap_address(env
, addr
+ 8);
30 t1
= cpu_ldq_data_ra(env
, addr
, GETPC());
31 s390_vec_write_element64(v1
, 0, t0
);
32 s390_vec_write_element64(v1
, 1, t1
);
37 for (i
= 0; i
< bytes
; i
++) {
38 uint8_t byte
= cpu_ldub_data_ra(env
, addr
, GETPC());
40 s390_vec_write_element8(&tmp
, i
, byte
);
41 addr
= wrap_address(env
, addr
+ 1);
43 *(S390Vector
*)v1
= tmp
;
47 #define DEF_VPK_HFN(BITS, TBITS) \
48 typedef uint##TBITS##_t (*vpk##BITS##_fn)(uint##BITS##_t, int *); \
49 static int vpk##BITS##_hfn(S390Vector *v1, const S390Vector *v2, \
50 const S390Vector *v3, vpk##BITS##_fn fn) \
52 int i, saturated = 0; \
55 for (i = 0; i < (128 / TBITS); i++) { \
58 if (i < (128 / BITS)) { \
59 src = s390_vec_read_element##BITS(v2, i); \
61 src = s390_vec_read_element##BITS(v3, i - (128 / BITS)); \
63 s390_vec_write_element##TBITS(&tmp, i, fn(src, &saturated)); \
72 #define DEF_VPK(BITS, TBITS) \
73 static uint##TBITS##_t vpk##BITS##e(uint##BITS##_t src, int *saturated) \
77 void HELPER(gvec_vpk##BITS)(void *v1, const void *v2, const void *v3, \
80 vpk##BITS##_hfn(v1, v2, v3, vpk##BITS##e); \
86 #define DEF_VPKS(BITS, TBITS) \
87 static uint##TBITS##_t vpks##BITS##e(uint##BITS##_t src, int *saturated) \
89 if ((int##BITS##_t)src > INT##TBITS##_MAX) { \
91 return INT##TBITS##_MAX; \
92 } else if ((int##BITS##_t)src < INT##TBITS##_MIN) { \
94 return INT##TBITS##_MIN; \
98 void HELPER(gvec_vpks##BITS)(void *v1, const void *v2, const void *v3, \
101 vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \
103 void HELPER(gvec_vpks_cc##BITS)(void *v1, const void *v2, const void *v3, \
104 CPUS390XState *env, uint32_t desc) \
106 int saturated = vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \
108 if (saturated == (128 / TBITS)) { \
110 } else if (saturated) { \
120 #define DEF_VPKLS(BITS, TBITS) \
121 static uint##TBITS##_t vpkls##BITS##e(uint##BITS##_t src, int *saturated) \
123 if (src > UINT##TBITS##_MAX) { \
125 return UINT##TBITS##_MAX; \
129 void HELPER(gvec_vpkls##BITS)(void *v1, const void *v2, const void *v3, \
132 vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \
134 void HELPER(gvec_vpkls_cc##BITS)(void *v1, const void *v2, const void *v3, \
135 CPUS390XState *env, uint32_t desc) \
137 int saturated = vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \
139 if (saturated == (128 / TBITS)) { \
141 } else if (saturated) { \
151 void HELPER(gvec_vperm
)(void *v1
, const void *v2
, const void *v3
,
152 const void *v4
, uint32_t desc
)
157 for (i
= 0; i
< 16; i
++) {
158 const uint8_t selector
= s390_vec_read_element8(v4
, i
) & 0x1f;
162 byte
= s390_vec_read_element8(v2
, selector
);
164 byte
= s390_vec_read_element8(v3
, selector
- 16);
166 s390_vec_write_element8(&tmp
, i
, byte
);
168 *(S390Vector
*)v1
= tmp
;
171 void HELPER(vstl
)(CPUS390XState
*env
, const void *v1
, uint64_t addr
,
174 /* Probe write access before actually modifying memory */
175 probe_write_access(env
, addr
, bytes
, GETPC());
177 if (likely(bytes
>= 16)) {
178 cpu_stq_data_ra(env
, addr
, s390_vec_read_element64(v1
, 0), GETPC());
179 addr
= wrap_address(env
, addr
+ 8);
180 cpu_stq_data_ra(env
, addr
, s390_vec_read_element64(v1
, 1), GETPC());
185 for (i
= 0; i
< bytes
; i
++) {
186 uint8_t byte
= s390_vec_read_element8(v1
, i
);
188 cpu_stb_data_ra(env
, addr
, byte
, GETPC());
189 addr
= wrap_address(env
, addr
+ 1);
191 *(S390Vector
*)v1
= tmp
;