]>
Commit | Line | Data |
---|---|---|
60e9e3f1 DH |
1 | /* |
2 | * QEMU TCG support -- s390x vector support instructions | |
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 | #include "qemu/osdep.h" | |
60e9e3f1 DH |
13 | #include "cpu.h" |
14 | #include "internal.h" | |
15 | #include "vec.h" | |
16 | #include "tcg/tcg.h" | |
73946f0d | 17 | #include "tcg/tcg-gvec-desc.h" |
60e9e3f1 DH |
18 | #include "exec/helper-proto.h" |
19 | #include "exec/cpu_ldst.h" | |
20 | #include "exec/exec-all.h" | |
21 | ||
22 | void HELPER(vll)(CPUS390XState *env, void *v1, uint64_t addr, uint64_t bytes) | |
23 | { | |
24 | if (likely(bytes >= 16)) { | |
25 | uint64_t t0, t1; | |
26 | ||
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); | |
32 | } else { | |
33 | S390Vector tmp = {}; | |
34 | int i; | |
35 | ||
36 | for (i = 0; i < bytes; i++) { | |
37 | uint8_t byte = cpu_ldub_data_ra(env, addr, GETPC()); | |
38 | ||
39 | s390_vec_write_element8(&tmp, i, byte); | |
40 | addr = wrap_address(env, addr + 1); | |
41 | } | |
42 | *(S390Vector *)v1 = tmp; | |
43 | } | |
44 | } | |
73946f0d DH |
45 | |
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) \ | |
50 | { \ | |
51 | int i, saturated = 0; \ | |
52 | S390Vector tmp; \ | |
53 | \ | |
54 | for (i = 0; i < (128 / TBITS); i++) { \ | |
55 | uint##BITS##_t src; \ | |
56 | \ | |
57 | if (i < (128 / BITS)) { \ | |
58 | src = s390_vec_read_element##BITS(v2, i); \ | |
59 | } else { \ | |
60 | src = s390_vec_read_element##BITS(v3, i - (128 / BITS)); \ | |
61 | } \ | |
62 | s390_vec_write_element##TBITS(&tmp, i, fn(src, &saturated)); \ | |
63 | } \ | |
64 | *v1 = tmp; \ | |
65 | return saturated; \ | |
66 | } | |
67 | DEF_VPK_HFN(64, 32) | |
68 | DEF_VPK_HFN(32, 16) | |
69 | DEF_VPK_HFN(16, 8) | |
70 | ||
71 | #define DEF_VPK(BITS, TBITS) \ | |
72 | static uint##TBITS##_t vpk##BITS##e(uint##BITS##_t src, int *saturated) \ | |
73 | { \ | |
74 | return src; \ | |
75 | } \ | |
76 | void HELPER(gvec_vpk##BITS)(void *v1, const void *v2, const void *v3, \ | |
77 | uint32_t desc) \ | |
78 | { \ | |
79 | vpk##BITS##_hfn(v1, v2, v3, vpk##BITS##e); \ | |
80 | } | |
81 | DEF_VPK(64, 32) | |
82 | DEF_VPK(32, 16) | |
83 | DEF_VPK(16, 8) | |
84 | ||
85 | #define DEF_VPKS(BITS, TBITS) \ | |
86 | static uint##TBITS##_t vpks##BITS##e(uint##BITS##_t src, int *saturated) \ | |
87 | { \ | |
88 | if ((int##BITS##_t)src > INT##TBITS##_MAX) { \ | |
89 | (*saturated)++; \ | |
90 | return INT##TBITS##_MAX; \ | |
91 | } else if ((int##BITS##_t)src < INT##TBITS##_MIN) { \ | |
92 | (*saturated)++; \ | |
93 | return INT##TBITS##_MIN; \ | |
94 | } \ | |
95 | return src; \ | |
96 | } \ | |
97 | void HELPER(gvec_vpks##BITS)(void *v1, const void *v2, const void *v3, \ | |
98 | uint32_t desc) \ | |
99 | { \ | |
100 | vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \ | |
101 | } \ | |
102 | void HELPER(gvec_vpks_cc##BITS)(void *v1, const void *v2, const void *v3, \ | |
103 | CPUS390XState *env, uint32_t desc) \ | |
104 | { \ | |
105 | int saturated = vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \ | |
106 | \ | |
107 | if (saturated == (128 / TBITS)) { \ | |
108 | env->cc_op = 3; \ | |
109 | } else if (saturated) { \ | |
110 | env->cc_op = 1; \ | |
111 | } else { \ | |
112 | env->cc_op = 0; \ | |
113 | } \ | |
114 | } | |
115 | DEF_VPKS(64, 32) | |
116 | DEF_VPKS(32, 16) | |
117 | DEF_VPKS(16, 8) | |
118 | ||
119 | #define DEF_VPKLS(BITS, TBITS) \ | |
120 | static uint##TBITS##_t vpkls##BITS##e(uint##BITS##_t src, int *saturated) \ | |
121 | { \ | |
122 | if (src > UINT##TBITS##_MAX) { \ | |
123 | (*saturated)++; \ | |
124 | return UINT##TBITS##_MAX; \ | |
125 | } \ | |
126 | return src; \ | |
127 | } \ | |
128 | void HELPER(gvec_vpkls##BITS)(void *v1, const void *v2, const void *v3, \ | |
129 | uint32_t desc) \ | |
130 | { \ | |
131 | vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \ | |
132 | } \ | |
133 | void HELPER(gvec_vpkls_cc##BITS)(void *v1, const void *v2, const void *v3, \ | |
134 | CPUS390XState *env, uint32_t desc) \ | |
135 | { \ | |
136 | int saturated = vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \ | |
137 | \ | |
138 | if (saturated == (128 / TBITS)) { \ | |
139 | env->cc_op = 3; \ | |
140 | } else if (saturated) { \ | |
141 | env->cc_op = 1; \ | |
142 | } else { \ | |
143 | env->cc_op = 0; \ | |
144 | } \ | |
145 | } | |
146 | DEF_VPKLS(64, 32) | |
147 | DEF_VPKLS(32, 16) | |
148 | DEF_VPKLS(16, 8) | |
7aaf844d DH |
149 | |
150 | void HELPER(gvec_vperm)(void *v1, const void *v2, const void *v3, | |
151 | const void *v4, uint32_t desc) | |
152 | { | |
153 | S390Vector tmp; | |
154 | int i; | |
155 | ||
156 | for (i = 0; i < 16; i++) { | |
157 | const uint8_t selector = s390_vec_read_element8(v4, i) & 0x1f; | |
158 | uint8_t byte; | |
159 | ||
160 | if (selector < 16) { | |
161 | byte = s390_vec_read_element8(v2, selector); | |
162 | } else { | |
163 | byte = s390_vec_read_element8(v3, selector - 16); | |
164 | } | |
165 | s390_vec_write_element8(&tmp, i, byte); | |
166 | } | |
167 | *(S390Vector *)v1 = tmp; | |
168 | } | |
0e0a5b49 DH |
169 | |
170 | void HELPER(vstl)(CPUS390XState *env, const void *v1, uint64_t addr, | |
171 | uint64_t bytes) | |
172 | { | |
173 | /* Probe write access before actually modifying memory */ | |
174 | probe_write_access(env, addr, bytes, GETPC()); | |
175 | ||
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()); | |
180 | } else { | |
181 | S390Vector tmp = {}; | |
182 | int i; | |
183 | ||
184 | for (i = 0; i < bytes; i++) { | |
185 | uint8_t byte = s390_vec_read_element8(v1, i); | |
186 | ||
187 | cpu_stb_data_ra(env, addr, byte, GETPC()); | |
188 | addr = wrap_address(env, addr + 1); | |
189 | } | |
190 | *(S390Vector *)v1 = tmp; | |
191 | } | |
192 | } |