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"
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"
22 void HELPER(vll
)(CPUS390XState
*env
, void *v1
, uint64_t addr
, uint64_t bytes
)
24 if (likely(bytes
>= 16)) {
27 t0
= cpu_ldq_data_ra(env
, addr
, GETPC());
28 addr
= wrap_address(env
, addr
+ 8);
29 t1
= cpu_ldq_data_ra(env
, addr
, GETPC());
30 s390_vec_write_element64(v1
, 0, t0
);
31 s390_vec_write_element64(v1
, 1, t1
);
36 for (i
= 0; i
< bytes
; i
++) {
37 uint8_t byte
= cpu_ldub_data_ra(env
, addr
, GETPC());
39 s390_vec_write_element8(&tmp
, i
, byte
);
40 addr
= wrap_address(env
, addr
+ 1);
42 *(S390Vector
*)v1
= tmp
;
46 #define DEF_VPK_HFN(BITS, TBITS) \
47 typedef uint##TBITS##_t (*vpk##BITS##_fn)(uint##BITS##_t, int *); \
48 static int vpk##BITS##_hfn(S390Vector *v1, const S390Vector *v2, \
49 const S390Vector *v3, vpk##BITS##_fn fn) \
51 int i, saturated = 0; \
54 for (i = 0; i < (128 / TBITS); i++) { \
57 if (i < (128 / BITS)) { \
58 src = s390_vec_read_element##BITS(v2, i); \
60 src = s390_vec_read_element##BITS(v3, i - (128 / BITS)); \
62 s390_vec_write_element##TBITS(&tmp, i, fn(src, &saturated)); \
71 #define DEF_VPK(BITS, TBITS) \
72 static uint##TBITS##_t vpk##BITS##e(uint##BITS##_t src, int *saturated) \
76 void HELPER(gvec_vpk##BITS)(void *v1, const void *v2, const void *v3, \
79 vpk##BITS##_hfn(v1, v2, v3, vpk##BITS##e); \
85 #define DEF_VPKS(BITS, TBITS) \
86 static uint##TBITS##_t vpks##BITS##e(uint##BITS##_t src, int *saturated) \
88 if ((int##BITS##_t)src > INT##TBITS##_MAX) { \
90 return INT##TBITS##_MAX; \
91 } else if ((int##BITS##_t)src < INT##TBITS##_MIN) { \
93 return INT##TBITS##_MIN; \
97 void HELPER(gvec_vpks##BITS)(void *v1, const void *v2, const void *v3, \
100 vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \
102 void HELPER(gvec_vpks_cc##BITS)(void *v1, const void *v2, const void *v3, \
103 CPUS390XState *env, uint32_t desc) \
105 int saturated = vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \
107 if (saturated == (128 / TBITS)) { \
109 } else if (saturated) { \
119 #define DEF_VPKLS(BITS, TBITS) \
120 static uint##TBITS##_t vpkls##BITS##e(uint##BITS##_t src, int *saturated) \
122 if (src > UINT##TBITS##_MAX) { \
124 return UINT##TBITS##_MAX; \
128 void HELPER(gvec_vpkls##BITS)(void *v1, const void *v2, const void *v3, \
131 vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \
133 void HELPER(gvec_vpkls_cc##BITS)(void *v1, const void *v2, const void *v3, \
134 CPUS390XState *env, uint32_t desc) \
136 int saturated = vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \
138 if (saturated == (128 / TBITS)) { \
140 } else if (saturated) { \
150 void HELPER(gvec_vperm
)(void *v1
, const void *v2
, const void *v3
,
151 const void *v4
, uint32_t desc
)
156 for (i
= 0; i
< 16; i
++) {
157 const uint8_t selector
= s390_vec_read_element8(v4
, i
) & 0x1f;
161 byte
= s390_vec_read_element8(v2
, selector
);
163 byte
= s390_vec_read_element8(v3
, selector
- 16);
165 s390_vec_write_element8(&tmp
, i
, byte
);
167 *(S390Vector
*)v1
= tmp
;
170 void HELPER(vstl
)(CPUS390XState
*env
, const void *v1
, uint64_t addr
,
173 /* Probe write access before actually modifying memory */
174 probe_write_access(env
, addr
, bytes
, GETPC());
176 if (likely(bytes
>= 16)) {
177 cpu_stq_data_ra(env
, addr
, s390_vec_read_element64(v1
, 0), GETPC());
178 addr
= wrap_address(env
, addr
+ 8);
179 cpu_stq_data_ra(env
, addr
, s390_vec_read_element64(v1
, 1), GETPC());
184 for (i
= 0; i
< bytes
; i
++) {
185 uint8_t byte
= s390_vec_read_element8(v1
, i
);
187 cpu_stb_data_ra(env
, addr
, byte
, GETPC());
188 addr
= wrap_address(env
, addr
+ 1);
190 *(S390Vector
*)v1
= tmp
;