]> git.proxmox.com Git - mirror_qemu.git/blob - target/loongarch/lsx_helper.c
target/loongarch: Implement vexth
[mirror_qemu.git] / target / loongarch / lsx_helper.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * QEMU LoongArch LSX helper functions.
4 *
5 * Copyright (c) 2022-2023 Loongson Technology Corporation Limited
6 */
7
8 #include "qemu/osdep.h"
9 #include "cpu.h"
10 #include "exec/exec-all.h"
11 #include "exec/helper-proto.h"
12
13 #define DO_ADD(a, b) (a + b)
14 #define DO_SUB(a, b) (a - b)
15
16 #define DO_ODD_EVEN(NAME, BIT, E1, E2, DO_OP) \
17 void HELPER(NAME)(CPULoongArchState *env, \
18 uint32_t vd, uint32_t vj, uint32_t vk) \
19 { \
20 int i; \
21 VReg *Vd = &(env->fpr[vd].vreg); \
22 VReg *Vj = &(env->fpr[vj].vreg); \
23 VReg *Vk = &(env->fpr[vk].vreg); \
24 typedef __typeof(Vd->E1(0)) TD; \
25 \
26 for (i = 0; i < LSX_LEN/BIT; i++) { \
27 Vd->E1(i) = DO_OP((TD)Vj->E2(2 * i + 1), (TD)Vk->E2(2 * i)); \
28 } \
29 }
30
31 DO_ODD_EVEN(vhaddw_h_b, 16, H, B, DO_ADD)
32 DO_ODD_EVEN(vhaddw_w_h, 32, W, H, DO_ADD)
33 DO_ODD_EVEN(vhaddw_d_w, 64, D, W, DO_ADD)
34
35 void HELPER(vhaddw_q_d)(CPULoongArchState *env,
36 uint32_t vd, uint32_t vj, uint32_t vk)
37 {
38 VReg *Vd = &(env->fpr[vd].vreg);
39 VReg *Vj = &(env->fpr[vj].vreg);
40 VReg *Vk = &(env->fpr[vk].vreg);
41
42 Vd->Q(0) = int128_add(int128_makes64(Vj->D(1)), int128_makes64(Vk->D(0)));
43 }
44
45 DO_ODD_EVEN(vhsubw_h_b, 16, H, B, DO_SUB)
46 DO_ODD_EVEN(vhsubw_w_h, 32, W, H, DO_SUB)
47 DO_ODD_EVEN(vhsubw_d_w, 64, D, W, DO_SUB)
48
49 void HELPER(vhsubw_q_d)(CPULoongArchState *env,
50 uint32_t vd, uint32_t vj, uint32_t vk)
51 {
52 VReg *Vd = &(env->fpr[vd].vreg);
53 VReg *Vj = &(env->fpr[vj].vreg);
54 VReg *Vk = &(env->fpr[vk].vreg);
55
56 Vd->Q(0) = int128_sub(int128_makes64(Vj->D(1)), int128_makes64(Vk->D(0)));
57 }
58
59 DO_ODD_EVEN(vhaddw_hu_bu, 16, UH, UB, DO_ADD)
60 DO_ODD_EVEN(vhaddw_wu_hu, 32, UW, UH, DO_ADD)
61 DO_ODD_EVEN(vhaddw_du_wu, 64, UD, UW, DO_ADD)
62
63 void HELPER(vhaddw_qu_du)(CPULoongArchState *env,
64 uint32_t vd, uint32_t vj, uint32_t vk)
65 {
66 VReg *Vd = &(env->fpr[vd].vreg);
67 VReg *Vj = &(env->fpr[vj].vreg);
68 VReg *Vk = &(env->fpr[vk].vreg);
69
70 Vd->Q(0) = int128_add(int128_make64((uint64_t)Vj->D(1)),
71 int128_make64((uint64_t)Vk->D(0)));
72 }
73
74 DO_ODD_EVEN(vhsubw_hu_bu, 16, UH, UB, DO_SUB)
75 DO_ODD_EVEN(vhsubw_wu_hu, 32, UW, UH, DO_SUB)
76 DO_ODD_EVEN(vhsubw_du_wu, 64, UD, UW, DO_SUB)
77
78 void HELPER(vhsubw_qu_du)(CPULoongArchState *env,
79 uint32_t vd, uint32_t vj, uint32_t vk)
80 {
81 VReg *Vd = &(env->fpr[vd].vreg);
82 VReg *Vj = &(env->fpr[vj].vreg);
83 VReg *Vk = &(env->fpr[vk].vreg);
84
85 Vd->Q(0) = int128_sub(int128_make64((uint64_t)Vj->D(1)),
86 int128_make64((uint64_t)Vk->D(0)));
87 }
88
89 #define DO_EVEN(NAME, BIT, E1, E2, DO_OP) \
90 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
91 { \
92 int i; \
93 VReg *Vd = (VReg *)vd; \
94 VReg *Vj = (VReg *)vj; \
95 VReg *Vk = (VReg *)vk; \
96 typedef __typeof(Vd->E1(0)) TD; \
97 for (i = 0; i < LSX_LEN/BIT; i++) { \
98 Vd->E1(i) = DO_OP((TD)Vj->E2(2 * i) ,(TD)Vk->E2(2 * i)); \
99 } \
100 }
101
102 #define DO_ODD(NAME, BIT, E1, E2, DO_OP) \
103 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
104 { \
105 int i; \
106 VReg *Vd = (VReg *)vd; \
107 VReg *Vj = (VReg *)vj; \
108 VReg *Vk = (VReg *)vk; \
109 typedef __typeof(Vd->E1(0)) TD; \
110 for (i = 0; i < LSX_LEN/BIT; i++) { \
111 Vd->E1(i) = DO_OP((TD)Vj->E2(2 * i + 1), (TD)Vk->E2(2 * i + 1)); \
112 } \
113 }
114
115 void HELPER(vaddwev_q_d)(void *vd, void *vj, void *vk, uint32_t v)
116 {
117 VReg *Vd = (VReg *)vd;
118 VReg *Vj = (VReg *)vj;
119 VReg *Vk = (VReg *)vk;
120
121 Vd->Q(0) = int128_add(int128_makes64(Vj->D(0)), int128_makes64(Vk->D(0)));
122 }
123
124 DO_EVEN(vaddwev_h_b, 16, H, B, DO_ADD)
125 DO_EVEN(vaddwev_w_h, 32, W, H, DO_ADD)
126 DO_EVEN(vaddwev_d_w, 64, D, W, DO_ADD)
127
128 void HELPER(vaddwod_q_d)(void *vd, void *vj, void *vk, uint32_t v)
129 {
130 VReg *Vd = (VReg *)vd;
131 VReg *Vj = (VReg *)vj;
132 VReg *Vk = (VReg *)vk;
133
134 Vd->Q(0) = int128_add(int128_makes64(Vj->D(1)), int128_makes64(Vk->D(1)));
135 }
136
137 DO_ODD(vaddwod_h_b, 16, H, B, DO_ADD)
138 DO_ODD(vaddwod_w_h, 32, W, H, DO_ADD)
139 DO_ODD(vaddwod_d_w, 64, D, W, DO_ADD)
140
141 void HELPER(vsubwev_q_d)(void *vd, void *vj, void *vk, uint32_t v)
142 {
143 VReg *Vd = (VReg *)vd;
144 VReg *Vj = (VReg *)vj;
145 VReg *Vk = (VReg *)vk;
146
147 Vd->Q(0) = int128_sub(int128_makes64(Vj->D(0)), int128_makes64(Vk->D(0)));
148 }
149
150 DO_EVEN(vsubwev_h_b, 16, H, B, DO_SUB)
151 DO_EVEN(vsubwev_w_h, 32, W, H, DO_SUB)
152 DO_EVEN(vsubwev_d_w, 64, D, W, DO_SUB)
153
154 void HELPER(vsubwod_q_d)(void *vd, void *vj, void *vk, uint32_t v)
155 {
156 VReg *Vd = (VReg *)vd;
157 VReg *Vj = (VReg *)vj;
158 VReg *Vk = (VReg *)vk;
159
160 Vd->Q(0) = int128_sub(int128_makes64(Vj->D(1)), int128_makes64(Vk->D(1)));
161 }
162
163 DO_ODD(vsubwod_h_b, 16, H, B, DO_SUB)
164 DO_ODD(vsubwod_w_h, 32, W, H, DO_SUB)
165 DO_ODD(vsubwod_d_w, 64, D, W, DO_SUB)
166
167 void HELPER(vaddwev_q_du)(void *vd, void *vj, void *vk, uint32_t v)
168 {
169 VReg *Vd = (VReg *)vd;
170 VReg *Vj = (VReg *)vj;
171 VReg *Vk = (VReg *)vk;
172
173 Vd->Q(0) = int128_add(int128_make64((uint64_t)Vj->D(0)),
174 int128_make64((uint64_t)Vk->D(0)));
175 }
176
177 DO_EVEN(vaddwev_h_bu, 16, UH, UB, DO_ADD)
178 DO_EVEN(vaddwev_w_hu, 32, UW, UH, DO_ADD)
179 DO_EVEN(vaddwev_d_wu, 64, UD, UW, DO_ADD)
180
181 void HELPER(vaddwod_q_du)(void *vd, void *vj, void *vk, uint32_t v)
182 {
183 VReg *Vd = (VReg *)vd;
184 VReg *Vj = (VReg *)vj;
185 VReg *Vk = (VReg *)vk;
186
187 Vd->Q(0) = int128_add(int128_make64((uint64_t)Vj->D(1)),
188 int128_make64((uint64_t)Vk->D(1)));
189 }
190
191 DO_ODD(vaddwod_h_bu, 16, UH, UB, DO_ADD)
192 DO_ODD(vaddwod_w_hu, 32, UW, UH, DO_ADD)
193 DO_ODD(vaddwod_d_wu, 64, UD, UW, DO_ADD)
194
195 void HELPER(vsubwev_q_du)(void *vd, void *vj, void *vk, uint32_t v)
196 {
197 VReg *Vd = (VReg *)vd;
198 VReg *Vj = (VReg *)vj;
199 VReg *Vk = (VReg *)vk;
200
201 Vd->Q(0) = int128_sub(int128_make64((uint64_t)Vj->D(0)),
202 int128_make64((uint64_t)Vk->D(0)));
203 }
204
205 DO_EVEN(vsubwev_h_bu, 16, UH, UB, DO_SUB)
206 DO_EVEN(vsubwev_w_hu, 32, UW, UH, DO_SUB)
207 DO_EVEN(vsubwev_d_wu, 64, UD, UW, DO_SUB)
208
209 void HELPER(vsubwod_q_du)(void *vd, void *vj, void *vk, uint32_t v)
210 {
211 VReg *Vd = (VReg *)vd;
212 VReg *Vj = (VReg *)vj;
213 VReg *Vk = (VReg *)vk;
214
215 Vd->Q(0) = int128_sub(int128_make64((uint64_t)Vj->D(1)),
216 int128_make64((uint64_t)Vk->D(1)));
217 }
218
219 DO_ODD(vsubwod_h_bu, 16, UH, UB, DO_SUB)
220 DO_ODD(vsubwod_w_hu, 32, UW, UH, DO_SUB)
221 DO_ODD(vsubwod_d_wu, 64, UD, UW, DO_SUB)
222
223 #define DO_EVEN_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
224 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
225 { \
226 int i; \
227 VReg *Vd = (VReg *)vd; \
228 VReg *Vj = (VReg *)vj; \
229 VReg *Vk = (VReg *)vk; \
230 typedef __typeof(Vd->ES1(0)) TDS; \
231 typedef __typeof(Vd->EU1(0)) TDU; \
232 for (i = 0; i < LSX_LEN/BIT; i++) { \
233 Vd->ES1(i) = DO_OP((TDU)Vj->EU2(2 * i) ,(TDS)Vk->ES2(2 * i)); \
234 } \
235 }
236
237 #define DO_ODD_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
238 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
239 { \
240 int i; \
241 VReg *Vd = (VReg *)vd; \
242 VReg *Vj = (VReg *)vj; \
243 VReg *Vk = (VReg *)vk; \
244 typedef __typeof(Vd->ES1(0)) TDS; \
245 typedef __typeof(Vd->EU1(0)) TDU; \
246 for (i = 0; i < LSX_LEN/BIT; i++) { \
247 Vd->ES1(i) = DO_OP((TDU)Vj->EU2(2 * i + 1), (TDS)Vk->ES2(2 * i + 1)); \
248 } \
249 }
250
251 void HELPER(vaddwev_q_du_d)(void *vd, void *vj, void *vk, uint32_t v)
252 {
253 VReg *Vd = (VReg *)vd;
254 VReg *Vj = (VReg *)vj;
255 VReg *Vk = (VReg *)vk;
256
257 Vd->Q(0) = int128_add(int128_make64((uint64_t)Vj->D(0)),
258 int128_makes64(Vk->D(0)));
259 }
260
261 DO_EVEN_U_S(vaddwev_h_bu_b, 16, H, UH, B, UB, DO_ADD)
262 DO_EVEN_U_S(vaddwev_w_hu_h, 32, W, UW, H, UH, DO_ADD)
263 DO_EVEN_U_S(vaddwev_d_wu_w, 64, D, UD, W, UW, DO_ADD)
264
265 void HELPER(vaddwod_q_du_d)(void *vd, void *vj, void *vk, uint32_t v)
266 {
267 VReg *Vd = (VReg *)vd;
268 VReg *Vj = (VReg *)vj;
269 VReg *Vk = (VReg *)vk;
270
271 Vd->Q(0) = int128_add(int128_make64((uint64_t)Vj->D(1)),
272 int128_makes64(Vk->D(1)));
273 }
274
275 DO_ODD_U_S(vaddwod_h_bu_b, 16, H, UH, B, UB, DO_ADD)
276 DO_ODD_U_S(vaddwod_w_hu_h, 32, W, UW, H, UH, DO_ADD)
277 DO_ODD_U_S(vaddwod_d_wu_w, 64, D, UD, W, UW, DO_ADD)
278
279 #define DO_VAVG(a, b) ((a >> 1) + (b >> 1) + (a & b & 1))
280 #define DO_VAVGR(a, b) ((a >> 1) + (b >> 1) + ((a | b) & 1))
281
282 #define DO_3OP(NAME, BIT, E, DO_OP) \
283 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
284 { \
285 int i; \
286 VReg *Vd = (VReg *)vd; \
287 VReg *Vj = (VReg *)vj; \
288 VReg *Vk = (VReg *)vk; \
289 for (i = 0; i < LSX_LEN/BIT; i++) { \
290 Vd->E(i) = DO_OP(Vj->E(i), Vk->E(i)); \
291 } \
292 }
293
294 DO_3OP(vavg_b, 8, B, DO_VAVG)
295 DO_3OP(vavg_h, 16, H, DO_VAVG)
296 DO_3OP(vavg_w, 32, W, DO_VAVG)
297 DO_3OP(vavg_d, 64, D, DO_VAVG)
298 DO_3OP(vavgr_b, 8, B, DO_VAVGR)
299 DO_3OP(vavgr_h, 16, H, DO_VAVGR)
300 DO_3OP(vavgr_w, 32, W, DO_VAVGR)
301 DO_3OP(vavgr_d, 64, D, DO_VAVGR)
302 DO_3OP(vavg_bu, 8, UB, DO_VAVG)
303 DO_3OP(vavg_hu, 16, UH, DO_VAVG)
304 DO_3OP(vavg_wu, 32, UW, DO_VAVG)
305 DO_3OP(vavg_du, 64, UD, DO_VAVG)
306 DO_3OP(vavgr_bu, 8, UB, DO_VAVGR)
307 DO_3OP(vavgr_hu, 16, UH, DO_VAVGR)
308 DO_3OP(vavgr_wu, 32, UW, DO_VAVGR)
309 DO_3OP(vavgr_du, 64, UD, DO_VAVGR)
310
311 #define DO_VABSD(a, b) ((a > b) ? (a -b) : (b-a))
312
313 DO_3OP(vabsd_b, 8, B, DO_VABSD)
314 DO_3OP(vabsd_h, 16, H, DO_VABSD)
315 DO_3OP(vabsd_w, 32, W, DO_VABSD)
316 DO_3OP(vabsd_d, 64, D, DO_VABSD)
317 DO_3OP(vabsd_bu, 8, UB, DO_VABSD)
318 DO_3OP(vabsd_hu, 16, UH, DO_VABSD)
319 DO_3OP(vabsd_wu, 32, UW, DO_VABSD)
320 DO_3OP(vabsd_du, 64, UD, DO_VABSD)
321
322 #define DO_VABS(a) ((a < 0) ? (-a) : (a))
323
324 #define DO_VADDA(NAME, BIT, E, DO_OP) \
325 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
326 { \
327 int i; \
328 VReg *Vd = (VReg *)vd; \
329 VReg *Vj = (VReg *)vj; \
330 VReg *Vk = (VReg *)vk; \
331 for (i = 0; i < LSX_LEN/BIT; i++) { \
332 Vd->E(i) = DO_OP(Vj->E(i)) + DO_OP(Vk->E(i)); \
333 } \
334 }
335
336 DO_VADDA(vadda_b, 8, B, DO_VABS)
337 DO_VADDA(vadda_h, 16, H, DO_VABS)
338 DO_VADDA(vadda_w, 32, W, DO_VABS)
339 DO_VADDA(vadda_d, 64, D, DO_VABS)
340
341 #define DO_MIN(a, b) (a < b ? a : b)
342 #define DO_MAX(a, b) (a > b ? a : b)
343
344 #define VMINMAXI(NAME, BIT, E, DO_OP) \
345 void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t v) \
346 { \
347 int i; \
348 VReg *Vd = (VReg *)vd; \
349 VReg *Vj = (VReg *)vj; \
350 typedef __typeof(Vd->E(0)) TD; \
351 \
352 for (i = 0; i < LSX_LEN/BIT; i++) { \
353 Vd->E(i) = DO_OP(Vj->E(i), (TD)imm); \
354 } \
355 }
356
357 VMINMAXI(vmini_b, 8, B, DO_MIN)
358 VMINMAXI(vmini_h, 16, H, DO_MIN)
359 VMINMAXI(vmini_w, 32, W, DO_MIN)
360 VMINMAXI(vmini_d, 64, D, DO_MIN)
361 VMINMAXI(vmaxi_b, 8, B, DO_MAX)
362 VMINMAXI(vmaxi_h, 16, H, DO_MAX)
363 VMINMAXI(vmaxi_w, 32, W, DO_MAX)
364 VMINMAXI(vmaxi_d, 64, D, DO_MAX)
365 VMINMAXI(vmini_bu, 8, UB, DO_MIN)
366 VMINMAXI(vmini_hu, 16, UH, DO_MIN)
367 VMINMAXI(vmini_wu, 32, UW, DO_MIN)
368 VMINMAXI(vmini_du, 64, UD, DO_MIN)
369 VMINMAXI(vmaxi_bu, 8, UB, DO_MAX)
370 VMINMAXI(vmaxi_hu, 16, UH, DO_MAX)
371 VMINMAXI(vmaxi_wu, 32, UW, DO_MAX)
372 VMINMAXI(vmaxi_du, 64, UD, DO_MAX)
373
374 #define DO_VMUH(NAME, BIT, E1, E2, DO_OP) \
375 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
376 { \
377 int i; \
378 VReg *Vd = (VReg *)vd; \
379 VReg *Vj = (VReg *)vj; \
380 VReg *Vk = (VReg *)vk; \
381 typedef __typeof(Vd->E1(0)) T; \
382 \
383 for (i = 0; i < LSX_LEN/BIT; i++) { \
384 Vd->E2(i) = ((T)Vj->E2(i)) * ((T)Vk->E2(i)) >> BIT; \
385 } \
386 }
387
388 void HELPER(vmuh_d)(void *vd, void *vj, void *vk, uint32_t v)
389 {
390 uint64_t l, h1, h2;
391 VReg *Vd = (VReg *)vd;
392 VReg *Vj = (VReg *)vj;
393 VReg *Vk = (VReg *)vk;
394
395 muls64(&l, &h1, Vj->D(0), Vk->D(0));
396 muls64(&l, &h2, Vj->D(1), Vk->D(1));
397
398 Vd->D(0) = h1;
399 Vd->D(1) = h2;
400 }
401
402 DO_VMUH(vmuh_b, 8, H, B, DO_MUH)
403 DO_VMUH(vmuh_h, 16, W, H, DO_MUH)
404 DO_VMUH(vmuh_w, 32, D, W, DO_MUH)
405
406 void HELPER(vmuh_du)(void *vd, void *vj, void *vk, uint32_t v)
407 {
408 uint64_t l, h1, h2;
409 VReg *Vd = (VReg *)vd;
410 VReg *Vj = (VReg *)vj;
411 VReg *Vk = (VReg *)vk;
412
413 mulu64(&l, &h1, Vj->D(0), Vk->D(0));
414 mulu64(&l, &h2, Vj->D(1), Vk->D(1));
415
416 Vd->D(0) = h1;
417 Vd->D(1) = h2;
418 }
419
420 DO_VMUH(vmuh_bu, 8, UH, UB, DO_MUH)
421 DO_VMUH(vmuh_hu, 16, UW, UH, DO_MUH)
422 DO_VMUH(vmuh_wu, 32, UD, UW, DO_MUH)
423
424 #define DO_MUL(a, b) (a * b)
425
426 DO_EVEN(vmulwev_h_b, 16, H, B, DO_MUL)
427 DO_EVEN(vmulwev_w_h, 32, W, H, DO_MUL)
428 DO_EVEN(vmulwev_d_w, 64, D, W, DO_MUL)
429
430 DO_ODD(vmulwod_h_b, 16, H, B, DO_MUL)
431 DO_ODD(vmulwod_w_h, 32, W, H, DO_MUL)
432 DO_ODD(vmulwod_d_w, 64, D, W, DO_MUL)
433
434 DO_EVEN(vmulwev_h_bu, 16, UH, UB, DO_MUL)
435 DO_EVEN(vmulwev_w_hu, 32, UW, UH, DO_MUL)
436 DO_EVEN(vmulwev_d_wu, 64, UD, UW, DO_MUL)
437
438 DO_ODD(vmulwod_h_bu, 16, UH, UB, DO_MUL)
439 DO_ODD(vmulwod_w_hu, 32, UW, UH, DO_MUL)
440 DO_ODD(vmulwod_d_wu, 64, UD, UW, DO_MUL)
441
442 DO_EVEN_U_S(vmulwev_h_bu_b, 16, H, UH, B, UB, DO_MUL)
443 DO_EVEN_U_S(vmulwev_w_hu_h, 32, W, UW, H, UH, DO_MUL)
444 DO_EVEN_U_S(vmulwev_d_wu_w, 64, D, UD, W, UW, DO_MUL)
445
446 DO_ODD_U_S(vmulwod_h_bu_b, 16, H, UH, B, UB, DO_MUL)
447 DO_ODD_U_S(vmulwod_w_hu_h, 32, W, UW, H, UH, DO_MUL)
448 DO_ODD_U_S(vmulwod_d_wu_w, 64, D, UD, W, UW, DO_MUL)
449
450 #define DO_MADD(a, b, c) (a + b * c)
451 #define DO_MSUB(a, b, c) (a - b * c)
452
453 #define VMADDSUB(NAME, BIT, E, DO_OP) \
454 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
455 { \
456 int i; \
457 VReg *Vd = (VReg *)vd; \
458 VReg *Vj = (VReg *)vj; \
459 VReg *Vk = (VReg *)vk; \
460 for (i = 0; i < LSX_LEN/BIT; i++) { \
461 Vd->E(i) = DO_OP(Vd->E(i), Vj->E(i) ,Vk->E(i)); \
462 } \
463 }
464
465 VMADDSUB(vmadd_b, 8, B, DO_MADD)
466 VMADDSUB(vmadd_h, 16, H, DO_MADD)
467 VMADDSUB(vmadd_w, 32, W, DO_MADD)
468 VMADDSUB(vmadd_d, 64, D, DO_MADD)
469 VMADDSUB(vmsub_b, 8, B, DO_MSUB)
470 VMADDSUB(vmsub_h, 16, H, DO_MSUB)
471 VMADDSUB(vmsub_w, 32, W, DO_MSUB)
472 VMADDSUB(vmsub_d, 64, D, DO_MSUB)
473
474 #define VMADDWEV(NAME, BIT, E1, E2, DO_OP) \
475 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
476 { \
477 int i; \
478 VReg *Vd = (VReg *)vd; \
479 VReg *Vj = (VReg *)vj; \
480 VReg *Vk = (VReg *)vk; \
481 typedef __typeof(Vd->E1(0)) TD; \
482 \
483 for (i = 0; i < LSX_LEN/BIT; i++) { \
484 Vd->E1(i) += DO_OP((TD)Vj->E2(2 * i), (TD)Vk->E2(2 * i)); \
485 } \
486 }
487
488 VMADDWEV(vmaddwev_h_b, 16, H, B, DO_MUL)
489 VMADDWEV(vmaddwev_w_h, 32, W, H, DO_MUL)
490 VMADDWEV(vmaddwev_d_w, 64, D, W, DO_MUL)
491 VMADDWEV(vmaddwev_h_bu, 16, UH, UB, DO_MUL)
492 VMADDWEV(vmaddwev_w_hu, 32, UW, UH, DO_MUL)
493 VMADDWEV(vmaddwev_d_wu, 64, UD, UW, DO_MUL)
494
495 #define VMADDWOD(NAME, BIT, E1, E2, DO_OP) \
496 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
497 { \
498 int i; \
499 VReg *Vd = (VReg *)vd; \
500 VReg *Vj = (VReg *)vj; \
501 VReg *Vk = (VReg *)vk; \
502 typedef __typeof(Vd->E1(0)) TD; \
503 \
504 for (i = 0; i < LSX_LEN/BIT; i++) { \
505 Vd->E1(i) += DO_OP((TD)Vj->E2(2 * i + 1), \
506 (TD)Vk->E2(2 * i + 1)); \
507 } \
508 }
509
510 VMADDWOD(vmaddwod_h_b, 16, H, B, DO_MUL)
511 VMADDWOD(vmaddwod_w_h, 32, W, H, DO_MUL)
512 VMADDWOD(vmaddwod_d_w, 64, D, W, DO_MUL)
513 VMADDWOD(vmaddwod_h_bu, 16, UH, UB, DO_MUL)
514 VMADDWOD(vmaddwod_w_hu, 32, UW, UH, DO_MUL)
515 VMADDWOD(vmaddwod_d_wu, 64, UD, UW, DO_MUL)
516
517 #define VMADDWEV_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
518 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
519 { \
520 int i; \
521 VReg *Vd = (VReg *)vd; \
522 VReg *Vj = (VReg *)vj; \
523 VReg *Vk = (VReg *)vk; \
524 typedef __typeof(Vd->ES1(0)) TS1; \
525 typedef __typeof(Vd->EU1(0)) TU1; \
526 \
527 for (i = 0; i < LSX_LEN/BIT; i++) { \
528 Vd->ES1(i) += DO_OP((TU1)Vj->EU2(2 * i), \
529 (TS1)Vk->ES2(2 * i)); \
530 } \
531 }
532
533 VMADDWEV_U_S(vmaddwev_h_bu_b, 16, H, UH, B, UB, DO_MUL)
534 VMADDWEV_U_S(vmaddwev_w_hu_h, 32, W, UW, H, UH, DO_MUL)
535 VMADDWEV_U_S(vmaddwev_d_wu_w, 64, D, UD, W, UW, DO_MUL)
536
537 #define VMADDWOD_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
538 void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
539 { \
540 int i; \
541 VReg *Vd = (VReg *)vd; \
542 VReg *Vj = (VReg *)vj; \
543 VReg *Vk = (VReg *)vk; \
544 typedef __typeof(Vd->ES1(0)) TS1; \
545 typedef __typeof(Vd->EU1(0)) TU1; \
546 \
547 for (i = 0; i < LSX_LEN/BIT; i++) { \
548 Vd->ES1(i) += DO_OP((TU1)Vj->EU2(2 * i + 1), \
549 (TS1)Vk->ES2(2 * i + 1)); \
550 } \
551 }
552
553 VMADDWOD_U_S(vmaddwod_h_bu_b, 16, H, UH, B, UB, DO_MUL)
554 VMADDWOD_U_S(vmaddwod_w_hu_h, 32, W, UW, H, UH, DO_MUL)
555 VMADDWOD_U_S(vmaddwod_d_wu_w, 64, D, UD, W, UW, DO_MUL)
556
557 #define DO_DIVU(N, M) (unlikely(M == 0) ? 0 : N / M)
558 #define DO_REMU(N, M) (unlikely(M == 0) ? 0 : N % M)
559 #define DO_DIV(N, M) (unlikely(M == 0) ? 0 :\
560 unlikely((N == -N) && (M == (__typeof(N))(-1))) ? N : N / M)
561 #define DO_REM(N, M) (unlikely(M == 0) ? 0 :\
562 unlikely((N == -N) && (M == (__typeof(N))(-1))) ? 0 : N % M)
563
564 #define VDIV(NAME, BIT, E, DO_OP) \
565 void HELPER(NAME)(CPULoongArchState *env, \
566 uint32_t vd, uint32_t vj, uint32_t vk) \
567 { \
568 int i; \
569 VReg *Vd = &(env->fpr[vd].vreg); \
570 VReg *Vj = &(env->fpr[vj].vreg); \
571 VReg *Vk = &(env->fpr[vk].vreg); \
572 for (i = 0; i < LSX_LEN/BIT; i++) { \
573 Vd->E(i) = DO_OP(Vj->E(i), Vk->E(i)); \
574 } \
575 }
576
577 VDIV(vdiv_b, 8, B, DO_DIV)
578 VDIV(vdiv_h, 16, H, DO_DIV)
579 VDIV(vdiv_w, 32, W, DO_DIV)
580 VDIV(vdiv_d, 64, D, DO_DIV)
581 VDIV(vdiv_bu, 8, UB, DO_DIVU)
582 VDIV(vdiv_hu, 16, UH, DO_DIVU)
583 VDIV(vdiv_wu, 32, UW, DO_DIVU)
584 VDIV(vdiv_du, 64, UD, DO_DIVU)
585 VDIV(vmod_b, 8, B, DO_REM)
586 VDIV(vmod_h, 16, H, DO_REM)
587 VDIV(vmod_w, 32, W, DO_REM)
588 VDIV(vmod_d, 64, D, DO_REM)
589 VDIV(vmod_bu, 8, UB, DO_REMU)
590 VDIV(vmod_hu, 16, UH, DO_REMU)
591 VDIV(vmod_wu, 32, UW, DO_REMU)
592 VDIV(vmod_du, 64, UD, DO_REMU)
593
594 #define VSAT_S(NAME, BIT, E) \
595 void HELPER(NAME)(void *vd, void *vj, uint64_t max, uint32_t v) \
596 { \
597 int i; \
598 VReg *Vd = (VReg *)vd; \
599 VReg *Vj = (VReg *)vj; \
600 typedef __typeof(Vd->E(0)) TD; \
601 \
602 for (i = 0; i < LSX_LEN/BIT; i++) { \
603 Vd->E(i) = Vj->E(i) > (TD)max ? (TD)max : \
604 Vj->E(i) < (TD)~max ? (TD)~max: Vj->E(i); \
605 } \
606 }
607
608 VSAT_S(vsat_b, 8, B)
609 VSAT_S(vsat_h, 16, H)
610 VSAT_S(vsat_w, 32, W)
611 VSAT_S(vsat_d, 64, D)
612
613 #define VSAT_U(NAME, BIT, E) \
614 void HELPER(NAME)(void *vd, void *vj, uint64_t max, uint32_t v) \
615 { \
616 int i; \
617 VReg *Vd = (VReg *)vd; \
618 VReg *Vj = (VReg *)vj; \
619 typedef __typeof(Vd->E(0)) TD; \
620 \
621 for (i = 0; i < LSX_LEN/BIT; i++) { \
622 Vd->E(i) = Vj->E(i) > (TD)max ? (TD)max : Vj->E(i); \
623 } \
624 }
625
626 VSAT_U(vsat_bu, 8, UB)
627 VSAT_U(vsat_hu, 16, UH)
628 VSAT_U(vsat_wu, 32, UW)
629 VSAT_U(vsat_du, 64, UD)
630
631 #define VEXTH(NAME, BIT, E1, E2) \
632 void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
633 { \
634 int i; \
635 VReg *Vd = &(env->fpr[vd].vreg); \
636 VReg *Vj = &(env->fpr[vj].vreg); \
637 \
638 for (i = 0; i < LSX_LEN/BIT; i++) { \
639 Vd->E1(i) = Vj->E2(i + LSX_LEN/BIT); \
640 } \
641 }
642
643 void HELPER(vexth_q_d)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
644 {
645 VReg *Vd = &(env->fpr[vd].vreg);
646 VReg *Vj = &(env->fpr[vj].vreg);
647
648 Vd->Q(0) = int128_makes64(Vj->D(1));
649 }
650
651 void HELPER(vexth_qu_du)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
652 {
653 VReg *Vd = &(env->fpr[vd].vreg);
654 VReg *Vj = &(env->fpr[vj].vreg);
655
656 Vd->Q(0) = int128_make64((uint64_t)Vj->D(1));
657 }
658
659 VEXTH(vexth_h_b, 16, H, B)
660 VEXTH(vexth_w_h, 32, W, H)
661 VEXTH(vexth_d_w, 64, D, W)
662 VEXTH(vexth_hu_bu, 16, UH, UB)
663 VEXTH(vexth_wu_hu, 32, UW, UH)
664 VEXTH(vexth_du_wu, 64, UD, UW)