s390x/tcg: Implement VECTOR STORE WITH LENGTH
[qemu/ar7.git] / target / s390x / vec_helper.c
blobbb4c9304f09b696bcac3f196c41dc9787041e270
1 /*
2 * QEMU TCG support -- s390x vector support instructions
4 * Copyright (C) 2019 Red Hat Inc
6 * Authors:
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"
14 #include "cpu.h"
15 #include "internal.h"
16 #include "vec.h"
17 #include "tcg/tcg.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)) {
26 uint64_t t0, t1;
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);
33 } else {
34 S390Vector tmp = {};
35 int i;
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) \
51 { \
52 int i, saturated = 0; \
53 S390Vector tmp; \
55 for (i = 0; i < (128 / TBITS); i++) { \
56 uint##BITS##_t src; \
58 if (i < (128 / BITS)) { \
59 src = s390_vec_read_element##BITS(v2, i); \
60 } else { \
61 src = s390_vec_read_element##BITS(v3, i - (128 / BITS)); \
62 } \
63 s390_vec_write_element##TBITS(&tmp, i, fn(src, &saturated)); \
64 } \
65 *v1 = tmp; \
66 return saturated; \
68 DEF_VPK_HFN(64, 32)
69 DEF_VPK_HFN(32, 16)
70 DEF_VPK_HFN(16, 8)
72 #define DEF_VPK(BITS, TBITS) \
73 static uint##TBITS##_t vpk##BITS##e(uint##BITS##_t src, int *saturated) \
74 { \
75 return src; \
76 } \
77 void HELPER(gvec_vpk##BITS)(void *v1, const void *v2, const void *v3, \
78 uint32_t desc) \
79 { \
80 vpk##BITS##_hfn(v1, v2, v3, vpk##BITS##e); \
82 DEF_VPK(64, 32)
83 DEF_VPK(32, 16)
84 DEF_VPK(16, 8)
86 #define DEF_VPKS(BITS, TBITS) \
87 static uint##TBITS##_t vpks##BITS##e(uint##BITS##_t src, int *saturated) \
88 { \
89 if ((int##BITS##_t)src > INT##TBITS##_MAX) { \
90 (*saturated)++; \
91 return INT##TBITS##_MAX; \
92 } else if ((int##BITS##_t)src < INT##TBITS##_MIN) { \
93 (*saturated)++; \
94 return INT##TBITS##_MIN; \
95 } \
96 return src; \
97 } \
98 void HELPER(gvec_vpks##BITS)(void *v1, const void *v2, const void *v3, \
99 uint32_t desc) \
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)) { \
109 env->cc_op = 3; \
110 } else if (saturated) { \
111 env->cc_op = 1; \
112 } else { \
113 env->cc_op = 0; \
116 DEF_VPKS(64, 32)
117 DEF_VPKS(32, 16)
118 DEF_VPKS(16, 8)
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) { \
124 (*saturated)++; \
125 return UINT##TBITS##_MAX; \
127 return src; \
129 void HELPER(gvec_vpkls##BITS)(void *v1, const void *v2, const void *v3, \
130 uint32_t desc) \
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)) { \
140 env->cc_op = 3; \
141 } else if (saturated) { \
142 env->cc_op = 1; \
143 } else { \
144 env->cc_op = 0; \
147 DEF_VPKLS(64, 32)
148 DEF_VPKLS(32, 16)
149 DEF_VPKLS(16, 8)
151 void HELPER(gvec_vperm)(void *v1, const void *v2, const void *v3,
152 const void *v4, uint32_t desc)
154 S390Vector tmp;
155 int i;
157 for (i = 0; i < 16; i++) {
158 const uint8_t selector = s390_vec_read_element8(v4, i) & 0x1f;
159 uint8_t byte;
161 if (selector < 16) {
162 byte = s390_vec_read_element8(v2, selector);
163 } else {
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,
172 uint64_t bytes)
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());
181 } else {
182 S390Vector tmp = {};
183 int i;
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;