]> git.proxmox.com Git - mirror_qemu.git/blob - target/mips/msa_helper.c
docs/devel/testing: Fix typo in dockerfile path
[mirror_qemu.git] / target / mips / msa_helper.c
1 /*
2 * MIPS SIMD Architecture Module Instruction emulation helpers for QEMU.
3 *
4 * Copyright (c) 2014 Imagination Technologies
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "qemu/osdep.h"
21 #include "cpu.h"
22 #include "internal.h"
23 #include "exec/exec-all.h"
24 #include "exec/helper-proto.h"
25
26 /* Data format min and max values */
27 #define DF_BITS(df) (1 << ((df) + 3))
28
29 #define DF_MAX_INT(df) (int64_t)((1LL << (DF_BITS(df) - 1)) - 1)
30 #define M_MAX_INT(m) (int64_t)((1LL << ((m) - 1)) - 1)
31
32 #define DF_MIN_INT(df) (int64_t)(-(1LL << (DF_BITS(df) - 1)))
33 #define M_MIN_INT(m) (int64_t)(-(1LL << ((m) - 1)))
34
35 #define DF_MAX_UINT(df) (uint64_t)(-1ULL >> (64 - DF_BITS(df)))
36 #define M_MAX_UINT(m) (uint64_t)(-1ULL >> (64 - (m)))
37
38 #define UNSIGNED(x, df) ((x) & DF_MAX_UINT(df))
39 #define SIGNED(x, df) \
40 ((((int64_t)x) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df)))
41
42 /* Element-by-element access macros */
43 #define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df))
44
45
46
47 /*
48 * Bit Count
49 * ---------
50 *
51 * +---------------+----------------------------------------------------------+
52 * | NLOC.B | Vector Leading Ones Count (byte) |
53 * | NLOC.H | Vector Leading Ones Count (halfword) |
54 * | NLOC.W | Vector Leading Ones Count (word) |
55 * | NLOC.D | Vector Leading Ones Count (doubleword) |
56 * | NLZC.B | Vector Leading Zeros Count (byte) |
57 * | NLZC.H | Vector Leading Zeros Count (halfword) |
58 * | NLZC.W | Vector Leading Zeros Count (word) |
59 * | NLZC.D | Vector Leading Zeros Count (doubleword) |
60 * | PCNT.B | Vector Population Count (byte) |
61 * | PCNT.H | Vector Population Count (halfword) |
62 * | PCNT.W | Vector Population Count (word) |
63 * | PCNT.D | Vector Population Count (doubleword) |
64 * +---------------+----------------------------------------------------------+
65 */
66
67 /* TODO: insert Bit Count group helpers here */
68
69
70 /*
71 * Bit Move
72 * --------
73 *
74 * +---------------+----------------------------------------------------------+
75 * | BMNZ.V | Vector Bit Move If Not Zero |
76 * | BMZ.V | Vector Bit Move If Zero |
77 * | BSEL.V | Vector Bit Select |
78 * | BINSL.B | Vector Bit Insert Left (byte) |
79 * | BINSL.H | Vector Bit Insert Left (halfword) |
80 * | BINSL.W | Vector Bit Insert Left (word) |
81 * | BINSL.D | Vector Bit Insert Left (doubleword) |
82 * | BINSR.B | Vector Bit Insert Right (byte) |
83 * | BINSR.H | Vector Bit Insert Right (halfword) |
84 * | BINSR.W | Vector Bit Insert Right (word) |
85 * | BINSR.D | Vector Bit Insert Right (doubleword) |
86 * +---------------+----------------------------------------------------------+
87 */
88
89 /* TODO: insert Bit Move group helpers here */
90
91
92 /*
93 * Bit Set
94 * -------
95 *
96 * +---------------+----------------------------------------------------------+
97 * | BCLR.B | Vector Bit Clear (byte) |
98 * | BCLR.H | Vector Bit Clear (halfword) |
99 * | BCLR.W | Vector Bit Clear (word) |
100 * | BCLR.D | Vector Bit Clear (doubleword) |
101 * | BNEG.B | Vector Bit Negate (byte) |
102 * | BNEG.H | Vector Bit Negate (halfword) |
103 * | BNEG.W | Vector Bit Negate (word) |
104 * | BNEG.D | Vector Bit Negate (doubleword) |
105 * | BSET.B | Vector Bit Set (byte) |
106 * | BSET.H | Vector Bit Set (halfword) |
107 * | BSET.W | Vector Bit Set (word) |
108 * | BSET.D | Vector Bit Set (doubleword) |
109 * +---------------+----------------------------------------------------------+
110 */
111
112 /* TODO: insert Bit Set group helpers here */
113
114
115 /*
116 * Fixed Multiply
117 * --------------
118 *
119 * +---------------+----------------------------------------------------------+
120 * | MADD_Q.H | Vector Fixed-Point Multiply and Add (halfword) |
121 * | MADD_Q.W | Vector Fixed-Point Multiply and Add (word) |
122 * | MADDR_Q.H | Vector Fixed-Point Multiply and Add Rounded (halfword) |
123 * | MADDR_Q.W | Vector Fixed-Point Multiply and Add Rounded (word) |
124 * | MSUB_Q.H | Vector Fixed-Point Multiply and Subtr. (halfword) |
125 * | MSUB_Q.W | Vector Fixed-Point Multiply and Subtr. (word) |
126 * | MSUBR_Q.H | Vector Fixed-Point Multiply and Subtr. Rounded (halfword)|
127 * | MSUBR_Q.W | Vector Fixed-Point Multiply and Subtr. Rounded (word) |
128 * | MUL_Q.H | Vector Fixed-Point Multiply (halfword) |
129 * | MUL_Q.W | Vector Fixed-Point Multiply (word) |
130 * | MULR_Q.H | Vector Fixed-Point Multiply Rounded (halfword) |
131 * | MULR_Q.W | Vector Fixed-Point Multiply Rounded (word) |
132 * +---------------+----------------------------------------------------------+
133 */
134
135 /* TODO: insert Fixed Multiply group helpers here */
136
137
138 /*
139 * Float Max Min
140 * -------------
141 *
142 * +---------------+----------------------------------------------------------+
143 * | FMAX_A.W | Vector Floating-Point Maximum (Absolute) (word) |
144 * | FMAX_A.D | Vector Floating-Point Maximum (Absolute) (doubleword) |
145 * | FMAX.W | Vector Floating-Point Maximum (word) |
146 * | FMAX.D | Vector Floating-Point Maximum (doubleword) |
147 * | FMIN_A.W | Vector Floating-Point Minimum (Absolute) (word) |
148 * | FMIN_A.D | Vector Floating-Point Minimum (Absolute) (doubleword) |
149 * | FMIN.W | Vector Floating-Point Minimum (word) |
150 * | FMIN.D | Vector Floating-Point Minimum (doubleword) |
151 * +---------------+----------------------------------------------------------+
152 */
153
154 /* TODO: insert Float Max Min group helpers here */
155
156
157 /*
158 * Int Add
159 * -------
160 *
161 * +---------------+----------------------------------------------------------+
162 * | ADD_A.B | Vector Add Absolute Values (byte) |
163 * | ADD_A.H | Vector Add Absolute Values (halfword) |
164 * | ADD_A.W | Vector Add Absolute Values (word) |
165 * | ADD_A.D | Vector Add Absolute Values (doubleword) |
166 * | ADDS_A.B | Vector Signed Saturated Add (of Absolute) (byte) |
167 * | ADDS_A.H | Vector Signed Saturated Add (of Absolute) (halfword) |
168 * | ADDS_A.W | Vector Signed Saturated Add (of Absolute) (word) |
169 * | ADDS_A.D | Vector Signed Saturated Add (of Absolute) (doubleword) |
170 * | ADDS_S.B | Vector Signed Saturated Add (of Signed) (byte) |
171 * | ADDS_S.H | Vector Signed Saturated Add (of Signed) (halfword) |
172 * | ADDS_S.W | Vector Signed Saturated Add (of Signed) (word) |
173 * | ADDS_S.D | Vector Signed Saturated Add (of Signed) (doubleword) |
174 * | ADDS_U.B | Vector Unsigned Saturated Add (of Unsigned) (byte) |
175 * | ADDS_U.H | Vector Unsigned Saturated Add (of Unsigned) (halfword) |
176 * | ADDS_U.W | Vector Unsigned Saturated Add (of Unsigned) (word) |
177 * | ADDS_U.D | Vector Unsigned Saturated Add (of Unsigned) (doubleword) |
178 * | ADDV.B | Vector Add (byte) |
179 * | ADDV.H | Vector Add (halfword) |
180 * | ADDV.W | Vector Add (word) |
181 * | ADDV.D | Vector Add (doubleword) |
182 * | HSUB_S.H | Vector Signed Horizontal Add (halfword) |
183 * | HSUB_S.W | Vector Signed Horizontal Add (word) |
184 * | HSUB_S.D | Vector Signed Horizontal Add (doubleword) |
185 * | HSUB_U.H | Vector Unigned Horizontal Add (halfword) |
186 * | HSUB_U.W | Vector Unigned Horizontal Add (word) |
187 * | HSUB_U.D | Vector Unigned Horizontal Add (doubleword) |
188 * +---------------+----------------------------------------------------------+
189 */
190
191 /* TODO: insert Int Add group helpers here */
192
193
194 /*
195 * Int Average
196 * -----------
197 *
198 * +---------------+----------------------------------------------------------+
199 * | AVE_S.B | Vector Signed Average (byte) |
200 * | AVE_S.H | Vector Signed Average (halfword) |
201 * | AVE_S.W | Vector Signed Average (word) |
202 * | AVE_S.D | Vector Signed Average (doubleword) |
203 * | AVE_U.B | Vector Unsigned Average (byte) |
204 * | AVE_U.H | Vector Unsigned Average (halfword) |
205 * | AVE_U.W | Vector Unsigned Average (word) |
206 * | AVE_U.D | Vector Unsigned Average (doubleword) |
207 * | AVER_S.B | Vector Signed Average Rounded (byte) |
208 * | AVER_S.H | Vector Signed Average Rounded (halfword) |
209 * | AVER_S.W | Vector Signed Average Rounded (word) |
210 * | AVER_S.D | Vector Signed Average Rounded (doubleword) |
211 * | AVER_U.B | Vector Unsigned Average Rounded (byte) |
212 * | AVER_U.H | Vector Unsigned Average Rounded (halfword) |
213 * | AVER_U.W | Vector Unsigned Average Rounded (word) |
214 * | AVER_U.D | Vector Unsigned Average Rounded (doubleword) |
215 * +---------------+----------------------------------------------------------+
216 */
217
218 /* TODO: insert Int Average group helpers here */
219
220
221 /*
222 * Int Compare
223 * -----------
224 *
225 * +---------------+----------------------------------------------------------+
226 * | CEQ.B | Vector Compare Equal (byte) |
227 * | CEQ.H | Vector Compare Equal (halfword) |
228 * | CEQ.W | Vector Compare Equal (word) |
229 * | CEQ.D | Vector Compare Equal (doubleword) |
230 * | CLE_S.B | Vector Compare Signed Less Than or Equal (byte) |
231 * | CLE_S.H | Vector Compare Signed Less Than or Equal (halfword) |
232 * | CLE_S.W | Vector Compare Signed Less Than or Equal (word) |
233 * | CLE_S.D | Vector Compare Signed Less Than or Equal (doubleword) |
234 * | CLE_U.B | Vector Compare Unsigned Less Than or Equal (byte) |
235 * | CLE_U.H | Vector Compare Unsigned Less Than or Equal (halfword) |
236 * | CLE_U.W | Vector Compare Unsigned Less Than or Equal (word) |
237 * | CLE_U.D | Vector Compare Unsigned Less Than or Equal (doubleword) |
238 * | CLT_S.B | Vector Compare Signed Less Than (byte) |
239 * | CLT_S.H | Vector Compare Signed Less Than (halfword) |
240 * | CLT_S.W | Vector Compare Signed Less Than (word) |
241 * | CLT_S.D | Vector Compare Signed Less Than (doubleword) |
242 * | CLT_U.B | Vector Compare Unsigned Less Than (byte) |
243 * | CLT_U.H | Vector Compare Unsigned Less Than (halfword) |
244 * | CLT_U.W | Vector Compare Unsigned Less Than (word) |
245 * | CLT_U.D | Vector Compare Unsigned Less Than (doubleword) |
246 * +---------------+----------------------------------------------------------+
247 */
248
249 /* TODO: insert Int Compare group helpers here */
250
251
252 /*
253 * Int Divide
254 * ----------
255 *
256 * +---------------+----------------------------------------------------------+
257 * | DIV_S.B | Vector Signed Divide (byte) |
258 * | DIV_S.H | Vector Signed Divide (halfword) |
259 * | DIV_S.W | Vector Signed Divide (word) |
260 * | DIV_S.D | Vector Signed Divide (doubleword) |
261 * | DIV_U.B | Vector Unsigned Divide (byte) |
262 * | DIV_U.H | Vector Unsigned Divide (halfword) |
263 * | DIV_U.W | Vector Unsigned Divide (word) |
264 * | DIV_U.D | Vector Unsigned Divide (doubleword) |
265 * +---------------+----------------------------------------------------------+
266 */
267
268 /* TODO: insert Int Divide group helpers here */
269
270
271 /*
272 * Int Dot Product
273 * ---------------
274 *
275 * +---------------+----------------------------------------------------------+
276 * | DOTP_S.H | Vector Signed Dot Product (halfword) |
277 * | DOTP_S.W | Vector Signed Dot Product (word) |
278 * | DOTP_S.D | Vector Signed Dot Product (doubleword) |
279 * | DOTP_U.H | Vector Unsigned Dot Product (halfword) |
280 * | DOTP_U.W | Vector Unsigned Dot Product (word) |
281 * | DOTP_U.D | Vector Unsigned Dot Product (doubleword) |
282 * +---------------+----------------------------------------------------------+
283 */
284
285 /* TODO: insert Int Dot Product group helpers here */
286
287
288 /*
289 * Int Max Min
290 * -----------
291 *
292 * +---------------+----------------------------------------------------------+
293 * | MAX_A.B | Vector Maximum Based on Absolute Value (byte) |
294 * | MAX_A.H | Vector Maximum Based on Absolute Value (halfword) |
295 * | MAX_A.W | Vector Maximum Based on Absolute Value (word) |
296 * | MAX_A.D | Vector Maximum Based on Absolute Value (doubleword) |
297 * | MAX_S.B | Vector Signed Maximum (byte) |
298 * | MAX_S.H | Vector Signed Maximum (halfword) |
299 * | MAX_S.W | Vector Signed Maximum (word) |
300 * | MAX_S.D | Vector Signed Maximum (doubleword) |
301 * | MAX_U.B | Vector Unsigned Maximum (byte) |
302 * | MAX_U.H | Vector Unsigned Maximum (halfword) |
303 * | MAX_U.W | Vector Unsigned Maximum (word) |
304 * | MAX_U.D | Vector Unsigned Maximum (doubleword) |
305 * | MIN_A.B | Vector Minimum Based on Absolute Value (byte) |
306 * | MIN_A.H | Vector Minimum Based on Absolute Value (halfword) |
307 * | MIN_A.W | Vector Minimum Based on Absolute Value (word) |
308 * | MIN_A.D | Vector Minimum Based on Absolute Value (doubleword) |
309 * | MIN_S.B | Vector Signed Minimum (byte) |
310 * | MIN_S.H | Vector Signed Minimum (halfword) |
311 * | MIN_S.W | Vector Signed Minimum (word) |
312 * | MIN_S.D | Vector Signed Minimum (doubleword) |
313 * | MIN_U.B | Vector Unsigned Minimum (byte) |
314 * | MIN_U.H | Vector Unsigned Minimum (halfword) |
315 * | MIN_U.W | Vector Unsigned Minimum (word) |
316 * | MIN_U.D | Vector Unsigned Minimum (doubleword) |
317 * +---------------+----------------------------------------------------------+
318 */
319
320 /* TODO: insert Int Max Min group helpers here */
321
322
323 /*
324 * Int Modulo
325 * ----------
326 *
327 * +---------------+----------------------------------------------------------+
328 * | MOD_S.B | Vector Signed Modulo (byte) |
329 * | MOD_S.H | Vector Signed Modulo (halfword) |
330 * | MOD_S.W | Vector Signed Modulo (word) |
331 * | MOD_S.D | Vector Signed Modulo (doubleword) |
332 * | MOD_U.B | Vector Unsigned Modulo (byte) |
333 * | MOD_U.H | Vector Unsigned Modulo (halfword) |
334 * | MOD_U.W | Vector Unsigned Modulo (word) |
335 * | MOD_U.D | Vector Unsigned Modulo (doubleword) |
336 * +---------------+----------------------------------------------------------+
337 */
338
339 /* TODO: insert Int Modulo group helpers here */
340
341
342 /*
343 * Int Multiply
344 * ------------
345 *
346 * +---------------+----------------------------------------------------------+
347 * | MADDV.B | Vector Multiply and Add (byte) |
348 * | MADDV.H | Vector Multiply and Add (halfword) |
349 * | MADDV.W | Vector Multiply and Add (word) |
350 * | MADDV.D | Vector Multiply and Add (doubleword) |
351 * | MSUBV.B | Vector Multiply and Subtract (byte) |
352 * | MSUBV.H | Vector Multiply and Subtract (halfword) |
353 * | MSUBV.W | Vector Multiply and Subtract (word) |
354 * | MSUBV.D | Vector Multiply and Subtract (doubleword) |
355 * | MULV.B | Vector Multiply (byte) |
356 * | MULV.H | Vector Multiply (halfword) |
357 * | MULV.W | Vector Multiply (word) |
358 * | MULV.D | Vector Multiply (doubleword) |
359 * +---------------+----------------------------------------------------------+
360 */
361
362 /* TODO: insert Int Multiply group helpers here */
363
364
365 /*
366 * Int Subtract
367 * ------------
368 *
369 * +---------------+----------------------------------------------------------+
370 * | ASUB_S.B | Vector Absolute Values of Signed Subtract (byte) |
371 * | ASUB_S.H | Vector Absolute Values of Signed Subtract (halfword) |
372 * | ASUB_S.W | Vector Absolute Values of Signed Subtract (word) |
373 * | ASUB_S.D | Vector Absolute Values of Signed Subtract (doubleword) |
374 * | ASUB_U.B | Vector Absolute Values of Unsigned Subtract (byte) |
375 * | ASUB_U.H | Vector Absolute Values of Unsigned Subtract (halfword) |
376 * | ASUB_U.W | Vector Absolute Values of Unsigned Subtract (word) |
377 * | ASUB_U.D | Vector Absolute Values of Unsigned Subtract (doubleword) |
378 * | HSUB_S.H | Vector Signed Horizontal Subtract (halfword) |
379 * | HSUB_S.W | Vector Signed Horizontal Subtract (word) |
380 * | HSUB_S.D | Vector Signed Horizontal Subtract (doubleword) |
381 * | HSUB_U.H | Vector Unigned Horizontal Subtract (halfword) |
382 * | HSUB_U.W | Vector Unigned Horizontal Subtract (word) |
383 * | HSUB_U.D | Vector Unigned Horizontal Subtract (doubleword) |
384 * | SUBS_S.B | Vector Signed Saturated Subtract (of Signed) (byte) |
385 * | SUBS_S.H | Vector Signed Saturated Subtract (of Signed) (halfword) |
386 * | SUBS_S.W | Vector Signed Saturated Subtract (of Signed) (word) |
387 * | SUBS_S.D | Vector Signed Saturated Subtract (of Signed) (doubleword)|
388 * | SUBS_U.B | Vector Unsigned Saturated Subtract (of Uns.) (byte) |
389 * | SUBS_U.H | Vector Unsigned Saturated Subtract (of Uns.) (halfword) |
390 * | SUBS_U.W | Vector Unsigned Saturated Subtract (of Uns.) (word) |
391 * | SUBS_U.D | Vector Unsigned Saturated Subtract (of Uns.) (doubleword)|
392 * | SUBSUS_S.B | Vector Uns. Sat. Subtract (of S. from Uns.) (byte) |
393 * | SUBSUS_S.H | Vector Uns. Sat. Subtract (of S. from Uns.) (halfword) |
394 * | SUBSUS_S.W | Vector Uns. Sat. Subtract (of S. from Uns.) (word) |
395 * | SUBSUS_S.D | Vector Uns. Sat. Subtract (of S. from Uns.) (doubleword) |
396 * | SUBSUU_U.B | Vector Signed Saturated Subtract (of Uns.) (byte) |
397 * | SUBSUU_U.H | Vector Signed Saturated Subtract (of Uns.) (halfword) |
398 * | SUBSUU_U.W | Vector Signed Saturated Subtract (of Uns.) (word) |
399 * | SUBSUU_U.D | Vector Signed Saturated Subtract (of Uns.) (doubleword) |
400 * | SUBV.B | Vector Subtract (byte) |
401 * | SUBV.H | Vector Subtract (halfword) |
402 * | SUBV.W | Vector Subtract (word) |
403 * | SUBV.D | Vector Subtract (doubleword) |
404 * +---------------+----------------------------------------------------------+
405 */
406
407 /* TODO: insert Int Subtract group helpers here */
408
409
410 /*
411 * Interleave
412 * ----------
413 *
414 * +---------------+----------------------------------------------------------+
415 * | ILVEV.B | Vector Interleave Even (byte) |
416 * | ILVEV.H | Vector Interleave Even (halfword) |
417 * | ILVEV.W | Vector Interleave Even (word) |
418 * | ILVEV.D | Vector Interleave Even (doubleword) |
419 * | ILVOD.B | Vector Interleave Odd (byte) |
420 * | ILVOD.H | Vector Interleave Odd (halfword) |
421 * | ILVOD.W | Vector Interleave Odd (word) |
422 * | ILVOD.D | Vector Interleave Odd (doubleword) |
423 * | ILVL.B | Vector Interleave Left (byte) |
424 * | ILVL.H | Vector Interleave Left (halfword) |
425 * | ILVL.W | Vector Interleave Left (word) |
426 * | ILVL.D | Vector Interleave Left (doubleword) |
427 * | ILVR.B | Vector Interleave Right (byte) |
428 * | ILVR.H | Vector Interleave Right (halfword) |
429 * | ILVR.W | Vector Interleave Right (word) |
430 * | ILVR.D | Vector Interleave Right (doubleword) |
431 * +---------------+----------------------------------------------------------+
432 */
433
434 /* TODO: insert Interleave group helpers here */
435
436
437 /*
438 * Logic
439 * -----
440 *
441 * +---------------+----------------------------------------------------------+
442 * | AND.V | Vector Logical And |
443 * | NOR.V | Vector Logical Negated Or |
444 * | OR.V | Vector Logical Or |
445 * | XOR.V | Vector Logical Exclusive Or |
446 * +---------------+----------------------------------------------------------+
447 */
448
449 /* TODO: insert Logic group helpers here */
450
451
452 /*
453 * Pack
454 * ----
455 *
456 * +---------------+----------------------------------------------------------+
457 * | PCKEV.B | Vector Pack Even (byte) |
458 * | PCKEV.H | Vector Pack Even (halfword) |
459 * | PCKEV.W | Vector Pack Even (word) |
460 * | PCKEV.D | Vector Pack Even (doubleword) |
461 * | PCKOD.B | Vector Pack Odd (byte) |
462 * | PCKOD.H | Vector Pack Odd (halfword) |
463 * | PCKOD.W | Vector Pack Odd (word) |
464 * | PCKOD.D | Vector Pack Odd (doubleword) |
465 * | VSHF.B | Vector Data Preserving Shuffle (byte) |
466 * | VSHF.H | Vector Data Preserving Shuffle (halfword) |
467 * | VSHF.W | Vector Data Preserving Shuffle (word) |
468 * | VSHF.D | Vector Data Preserving Shuffle (doubleword) |
469 * +---------------+----------------------------------------------------------+
470 */
471
472 /* TODO: insert Pack group helpers here */
473
474
475 /*
476 * Shift
477 * -----
478 *
479 * +---------------+----------------------------------------------------------+
480 * | SLL.B | Vector Shift Left (byte) |
481 * | SLL.H | Vector Shift Left (halfword) |
482 * | SLL.W | Vector Shift Left (word) |
483 * | SLL.D | Vector Shift Left (doubleword) |
484 * | SRA.B | Vector Shift Right Arithmetic (byte) |
485 * | SRA.H | Vector Shift Right Arithmetic (halfword) |
486 * | SRA.W | Vector Shift Right Arithmetic (word) |
487 * | SRA.D | Vector Shift Right Arithmetic (doubleword) |
488 * | SRAR.B | Vector Shift Right Arithmetic Rounded (byte) |
489 * | SRAR.H | Vector Shift Right Arithmetic Rounded (halfword) |
490 * | SRAR.W | Vector Shift Right Arithmetic Rounded (word) |
491 * | SRAR.D | Vector Shift Right Arithmetic Rounded (doubleword) |
492 * | SRL.B | Vector Shift Right Logical (byte) |
493 * | SRL.H | Vector Shift Right Logical (halfword) |
494 * | SRL.W | Vector Shift Right Logical (word) |
495 * | SRL.D | Vector Shift Right Logical (doubleword) |
496 * | SRLR.B | Vector Shift Right Logical Rounded (byte) |
497 * | SRLR.H | Vector Shift Right Logical Rounded (halfword) |
498 * | SRLR.W | Vector Shift Right Logical Rounded (word) |
499 * | SRLR.D | Vector Shift Right Logical Rounded (doubleword) |
500 * +---------------+----------------------------------------------------------+
501 */
502
503 /* TODO: insert Shift group helpers here */
504
505
506 static inline void msa_move_v(wr_t *pwd, wr_t *pws)
507 {
508 uint32_t i;
509
510 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
511 pwd->d[i] = pws->d[i];
512 }
513 }
514
515 #define MSA_FN_IMM8(FUNC, DEST, OPERATION) \
516 void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \
517 uint32_t i8) \
518 { \
519 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
520 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
521 uint32_t i; \
522 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \
523 DEST = OPERATION; \
524 } \
525 }
526
527 MSA_FN_IMM8(andi_b, pwd->b[i], pws->b[i] & i8)
528 MSA_FN_IMM8(ori_b, pwd->b[i], pws->b[i] | i8)
529 MSA_FN_IMM8(nori_b, pwd->b[i], ~(pws->b[i] | i8))
530 MSA_FN_IMM8(xori_b, pwd->b[i], pws->b[i] ^ i8)
531
532 #define BIT_MOVE_IF_NOT_ZERO(dest, arg1, arg2, df) \
533 UNSIGNED(((dest & (~arg2)) | (arg1 & arg2)), df)
534 MSA_FN_IMM8(bmnzi_b, pwd->b[i],
535 BIT_MOVE_IF_NOT_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE))
536
537 #define BIT_MOVE_IF_ZERO(dest, arg1, arg2, df) \
538 UNSIGNED((dest & arg2) | (arg1 & (~arg2)), df)
539 MSA_FN_IMM8(bmzi_b, pwd->b[i],
540 BIT_MOVE_IF_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE))
541
542 #define BIT_SELECT(dest, arg1, arg2, df) \
543 UNSIGNED((arg1 & (~dest)) | (arg2 & dest), df)
544 MSA_FN_IMM8(bseli_b, pwd->b[i],
545 BIT_SELECT(pwd->b[i], pws->b[i], i8, DF_BYTE))
546
547 #undef MSA_FN_IMM8
548
549 #define SHF_POS(i, imm) (((i) & 0xfc) + (((imm) >> (2 * ((i) & 0x03))) & 0x03))
550
551 void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
552 uint32_t ws, uint32_t imm)
553 {
554 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
555 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
556 wr_t wx, *pwx = &wx;
557 uint32_t i;
558
559 switch (df) {
560 case DF_BYTE:
561 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
562 pwx->b[i] = pws->b[SHF_POS(i, imm)];
563 }
564 break;
565 case DF_HALF:
566 for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {
567 pwx->h[i] = pws->h[SHF_POS(i, imm)];
568 }
569 break;
570 case DF_WORD:
571 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
572 pwx->w[i] = pws->w[SHF_POS(i, imm)];
573 }
574 break;
575 default:
576 assert(0);
577 }
578 msa_move_v(pwd, pwx);
579 }
580
581 #define MSA_FN_VECTOR(FUNC, DEST, OPERATION) \
582 void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \
583 uint32_t wt) \
584 { \
585 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
586 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
587 wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \
588 uint32_t i; \
589 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
590 DEST = OPERATION; \
591 } \
592 }
593
594 MSA_FN_VECTOR(bmnz_v, pwd->d[i],
595 BIT_MOVE_IF_NOT_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE))
596 MSA_FN_VECTOR(bmz_v, pwd->d[i],
597 BIT_MOVE_IF_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE))
598 MSA_FN_VECTOR(bsel_v, pwd->d[i],
599 BIT_SELECT(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE))
600 #undef BIT_MOVE_IF_NOT_ZERO
601 #undef BIT_MOVE_IF_ZERO
602 #undef BIT_SELECT
603 #undef MSA_FN_VECTOR
604
605 void helper_msa_and_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
606 {
607 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
608 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
609 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
610
611 pwd->d[0] = pws->d[0] & pwt->d[0];
612 pwd->d[1] = pws->d[1] & pwt->d[1];
613 }
614
615 void helper_msa_or_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
616 {
617 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
618 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
619 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
620
621 pwd->d[0] = pws->d[0] | pwt->d[0];
622 pwd->d[1] = pws->d[1] | pwt->d[1];
623 }
624
625 void helper_msa_nor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
626 {
627 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
628 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
629 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
630
631 pwd->d[0] = ~(pws->d[0] | pwt->d[0]);
632 pwd->d[1] = ~(pws->d[1] | pwt->d[1]);
633 }
634
635 void helper_msa_xor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
636 {
637 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
638 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
639 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
640
641 pwd->d[0] = pws->d[0] ^ pwt->d[0];
642 pwd->d[1] = pws->d[1] ^ pwt->d[1];
643 }
644
645 static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2)
646 {
647 return arg1 + arg2;
648 }
649
650 static inline int64_t msa_subv_df(uint32_t df, int64_t arg1, int64_t arg2)
651 {
652 return arg1 - arg2;
653 }
654
655 static inline int64_t msa_ceq_df(uint32_t df, int64_t arg1, int64_t arg2)
656 {
657 return arg1 == arg2 ? -1 : 0;
658 }
659
660 static inline int64_t msa_cle_s_df(uint32_t df, int64_t arg1, int64_t arg2)
661 {
662 return arg1 <= arg2 ? -1 : 0;
663 }
664
665 static inline int64_t msa_cle_u_df(uint32_t df, int64_t arg1, int64_t arg2)
666 {
667 uint64_t u_arg1 = UNSIGNED(arg1, df);
668 uint64_t u_arg2 = UNSIGNED(arg2, df);
669 return u_arg1 <= u_arg2 ? -1 : 0;
670 }
671
672 static inline int64_t msa_clt_s_df(uint32_t df, int64_t arg1, int64_t arg2)
673 {
674 return arg1 < arg2 ? -1 : 0;
675 }
676
677 static inline int64_t msa_clt_u_df(uint32_t df, int64_t arg1, int64_t arg2)
678 {
679 uint64_t u_arg1 = UNSIGNED(arg1, df);
680 uint64_t u_arg2 = UNSIGNED(arg2, df);
681 return u_arg1 < u_arg2 ? -1 : 0;
682 }
683
684 static inline int64_t msa_max_s_df(uint32_t df, int64_t arg1, int64_t arg2)
685 {
686 return arg1 > arg2 ? arg1 : arg2;
687 }
688
689 static inline int64_t msa_max_u_df(uint32_t df, int64_t arg1, int64_t arg2)
690 {
691 uint64_t u_arg1 = UNSIGNED(arg1, df);
692 uint64_t u_arg2 = UNSIGNED(arg2, df);
693 return u_arg1 > u_arg2 ? arg1 : arg2;
694 }
695
696 static inline int64_t msa_min_s_df(uint32_t df, int64_t arg1, int64_t arg2)
697 {
698 return arg1 < arg2 ? arg1 : arg2;
699 }
700
701 static inline int64_t msa_min_u_df(uint32_t df, int64_t arg1, int64_t arg2)
702 {
703 uint64_t u_arg1 = UNSIGNED(arg1, df);
704 uint64_t u_arg2 = UNSIGNED(arg2, df);
705 return u_arg1 < u_arg2 ? arg1 : arg2;
706 }
707
708 #define MSA_BINOP_IMM_DF(helper, func) \
709 void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, \
710 uint32_t wd, uint32_t ws, int32_t u5) \
711 { \
712 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
713 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
714 uint32_t i; \
715 \
716 switch (df) { \
717 case DF_BYTE: \
718 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \
719 pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], u5); \
720 } \
721 break; \
722 case DF_HALF: \
723 for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \
724 pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], u5); \
725 } \
726 break; \
727 case DF_WORD: \
728 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \
729 pwd->w[i] = msa_ ## func ## _df(df, pws->w[i], u5); \
730 } \
731 break; \
732 case DF_DOUBLE: \
733 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
734 pwd->d[i] = msa_ ## func ## _df(df, pws->d[i], u5); \
735 } \
736 break; \
737 default: \
738 assert(0); \
739 } \
740 }
741
742 MSA_BINOP_IMM_DF(addvi, addv)
743 MSA_BINOP_IMM_DF(subvi, subv)
744 MSA_BINOP_IMM_DF(ceqi, ceq)
745 MSA_BINOP_IMM_DF(clei_s, cle_s)
746 MSA_BINOP_IMM_DF(clei_u, cle_u)
747 MSA_BINOP_IMM_DF(clti_s, clt_s)
748 MSA_BINOP_IMM_DF(clti_u, clt_u)
749 MSA_BINOP_IMM_DF(maxi_s, max_s)
750 MSA_BINOP_IMM_DF(maxi_u, max_u)
751 MSA_BINOP_IMM_DF(mini_s, min_s)
752 MSA_BINOP_IMM_DF(mini_u, min_u)
753 #undef MSA_BINOP_IMM_DF
754
755 void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
756 int32_t s10)
757 {
758 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
759 uint32_t i;
760
761 switch (df) {
762 case DF_BYTE:
763 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
764 pwd->b[i] = (int8_t)s10;
765 }
766 break;
767 case DF_HALF:
768 for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {
769 pwd->h[i] = (int16_t)s10;
770 }
771 break;
772 case DF_WORD:
773 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
774 pwd->w[i] = (int32_t)s10;
775 }
776 break;
777 case DF_DOUBLE:
778 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
779 pwd->d[i] = (int64_t)s10;
780 }
781 break;
782 default:
783 assert(0);
784 }
785 }
786
787 /* Data format bit position and unsigned values */
788 #define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df))
789
790 static inline int64_t msa_sll_df(uint32_t df, int64_t arg1, int64_t arg2)
791 {
792 int32_t b_arg2 = BIT_POSITION(arg2, df);
793 return arg1 << b_arg2;
794 }
795
796 static inline int64_t msa_sra_df(uint32_t df, int64_t arg1, int64_t arg2)
797 {
798 int32_t b_arg2 = BIT_POSITION(arg2, df);
799 return arg1 >> b_arg2;
800 }
801
802 static inline int64_t msa_srl_df(uint32_t df, int64_t arg1, int64_t arg2)
803 {
804 uint64_t u_arg1 = UNSIGNED(arg1, df);
805 int32_t b_arg2 = BIT_POSITION(arg2, df);
806 return u_arg1 >> b_arg2;
807 }
808
809 static inline int64_t msa_bclr_df(uint32_t df, int64_t arg1, int64_t arg2)
810 {
811 int32_t b_arg2 = BIT_POSITION(arg2, df);
812 return UNSIGNED(arg1 & (~(1LL << b_arg2)), df);
813 }
814
815 static inline int64_t msa_bset_df(uint32_t df, int64_t arg1,
816 int64_t arg2)
817 {
818 int32_t b_arg2 = BIT_POSITION(arg2, df);
819 return UNSIGNED(arg1 | (1LL << b_arg2), df);
820 }
821
822 static inline int64_t msa_bneg_df(uint32_t df, int64_t arg1, int64_t arg2)
823 {
824 int32_t b_arg2 = BIT_POSITION(arg2, df);
825 return UNSIGNED(arg1 ^ (1LL << b_arg2), df);
826 }
827
828 static inline int64_t msa_binsl_df(uint32_t df, int64_t dest, int64_t arg1,
829 int64_t arg2)
830 {
831 uint64_t u_arg1 = UNSIGNED(arg1, df);
832 uint64_t u_dest = UNSIGNED(dest, df);
833 int32_t sh_d = BIT_POSITION(arg2, df) + 1;
834 int32_t sh_a = DF_BITS(df) - sh_d;
835 if (sh_d == DF_BITS(df)) {
836 return u_arg1;
837 } else {
838 return UNSIGNED(UNSIGNED(u_dest << sh_d, df) >> sh_d, df) |
839 UNSIGNED(UNSIGNED(u_arg1 >> sh_a, df) << sh_a, df);
840 }
841 }
842
843 static inline int64_t msa_binsr_df(uint32_t df, int64_t dest, int64_t arg1,
844 int64_t arg2)
845 {
846 uint64_t u_arg1 = UNSIGNED(arg1, df);
847 uint64_t u_dest = UNSIGNED(dest, df);
848 int32_t sh_d = BIT_POSITION(arg2, df) + 1;
849 int32_t sh_a = DF_BITS(df) - sh_d;
850 if (sh_d == DF_BITS(df)) {
851 return u_arg1;
852 } else {
853 return UNSIGNED(UNSIGNED(u_dest >> sh_d, df) << sh_d, df) |
854 UNSIGNED(UNSIGNED(u_arg1 << sh_a, df) >> sh_a, df);
855 }
856 }
857
858 static inline int64_t msa_sat_s_df(uint32_t df, int64_t arg, uint32_t m)
859 {
860 return arg < M_MIN_INT(m + 1) ? M_MIN_INT(m + 1) :
861 arg > M_MAX_INT(m + 1) ? M_MAX_INT(m + 1) :
862 arg;
863 }
864
865 static inline int64_t msa_sat_u_df(uint32_t df, int64_t arg, uint32_t m)
866 {
867 uint64_t u_arg = UNSIGNED(arg, df);
868 return u_arg < M_MAX_UINT(m + 1) ? u_arg :
869 M_MAX_UINT(m + 1);
870 }
871
872 static inline int64_t msa_srar_df(uint32_t df, int64_t arg1, int64_t arg2)
873 {
874 int32_t b_arg2 = BIT_POSITION(arg2, df);
875 if (b_arg2 == 0) {
876 return arg1;
877 } else {
878 int64_t r_bit = (arg1 >> (b_arg2 - 1)) & 1;
879 return (arg1 >> b_arg2) + r_bit;
880 }
881 }
882
883 static inline int64_t msa_srlr_df(uint32_t df, int64_t arg1, int64_t arg2)
884 {
885 uint64_t u_arg1 = UNSIGNED(arg1, df);
886 int32_t b_arg2 = BIT_POSITION(arg2, df);
887 if (b_arg2 == 0) {
888 return u_arg1;
889 } else {
890 uint64_t r_bit = (u_arg1 >> (b_arg2 - 1)) & 1;
891 return (u_arg1 >> b_arg2) + r_bit;
892 }
893 }
894
895 #define MSA_BINOP_IMMU_DF(helper, func) \
896 void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd, \
897 uint32_t ws, uint32_t u5) \
898 { \
899 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
900 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
901 uint32_t i; \
902 \
903 switch (df) { \
904 case DF_BYTE: \
905 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \
906 pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], u5); \
907 } \
908 break; \
909 case DF_HALF: \
910 for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \
911 pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], u5); \
912 } \
913 break; \
914 case DF_WORD: \
915 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \
916 pwd->w[i] = msa_ ## func ## _df(df, pws->w[i], u5); \
917 } \
918 break; \
919 case DF_DOUBLE: \
920 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
921 pwd->d[i] = msa_ ## func ## _df(df, pws->d[i], u5); \
922 } \
923 break; \
924 default: \
925 assert(0); \
926 } \
927 }
928
929 MSA_BINOP_IMMU_DF(slli, sll)
930 MSA_BINOP_IMMU_DF(srai, sra)
931 MSA_BINOP_IMMU_DF(srli, srl)
932 MSA_BINOP_IMMU_DF(bclri, bclr)
933 MSA_BINOP_IMMU_DF(bseti, bset)
934 MSA_BINOP_IMMU_DF(bnegi, bneg)
935 MSA_BINOP_IMMU_DF(sat_s, sat_s)
936 MSA_BINOP_IMMU_DF(sat_u, sat_u)
937 MSA_BINOP_IMMU_DF(srari, srar)
938 MSA_BINOP_IMMU_DF(srlri, srlr)
939 #undef MSA_BINOP_IMMU_DF
940
941 #define MSA_TEROP_IMMU_DF(helper, func) \
942 void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, \
943 uint32_t wd, uint32_t ws, uint32_t u5) \
944 { \
945 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
946 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
947 uint32_t i; \
948 \
949 switch (df) { \
950 case DF_BYTE: \
951 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \
952 pwd->b[i] = msa_ ## func ## _df(df, pwd->b[i], pws->b[i], \
953 u5); \
954 } \
955 break; \
956 case DF_HALF: \
957 for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \
958 pwd->h[i] = msa_ ## func ## _df(df, pwd->h[i], pws->h[i], \
959 u5); \
960 } \
961 break; \
962 case DF_WORD: \
963 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \
964 pwd->w[i] = msa_ ## func ## _df(df, pwd->w[i], pws->w[i], \
965 u5); \
966 } \
967 break; \
968 case DF_DOUBLE: \
969 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
970 pwd->d[i] = msa_ ## func ## _df(df, pwd->d[i], pws->d[i], \
971 u5); \
972 } \
973 break; \
974 default: \
975 assert(0); \
976 } \
977 }
978
979 MSA_TEROP_IMMU_DF(binsli, binsl)
980 MSA_TEROP_IMMU_DF(binsri, binsr)
981 #undef MSA_TEROP_IMMU_DF
982
983 static inline int64_t msa_max_a_df(uint32_t df, int64_t arg1, int64_t arg2)
984 {
985 uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
986 uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
987 return abs_arg1 > abs_arg2 ? arg1 : arg2;
988 }
989
990 static inline int64_t msa_min_a_df(uint32_t df, int64_t arg1, int64_t arg2)
991 {
992 uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
993 uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
994 return abs_arg1 < abs_arg2 ? arg1 : arg2;
995 }
996
997 static inline int64_t msa_add_a_df(uint32_t df, int64_t arg1, int64_t arg2)
998 {
999 uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
1000 uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
1001 return abs_arg1 + abs_arg2;
1002 }
1003
1004 static inline int64_t msa_adds_a_df(uint32_t df, int64_t arg1, int64_t arg2)
1005 {
1006 uint64_t max_int = (uint64_t)DF_MAX_INT(df);
1007 uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
1008 uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
1009 if (abs_arg1 > max_int || abs_arg2 > max_int) {
1010 return (int64_t)max_int;
1011 } else {
1012 return (abs_arg1 < max_int - abs_arg2) ? abs_arg1 + abs_arg2 : max_int;
1013 }
1014 }
1015
1016 static inline int64_t msa_adds_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1017 {
1018 int64_t max_int = DF_MAX_INT(df);
1019 int64_t min_int = DF_MIN_INT(df);
1020 if (arg1 < 0) {
1021 return (min_int - arg1 < arg2) ? arg1 + arg2 : min_int;
1022 } else {
1023 return (arg2 < max_int - arg1) ? arg1 + arg2 : max_int;
1024 }
1025 }
1026
1027 static inline uint64_t msa_adds_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
1028 {
1029 uint64_t max_uint = DF_MAX_UINT(df);
1030 uint64_t u_arg1 = UNSIGNED(arg1, df);
1031 uint64_t u_arg2 = UNSIGNED(arg2, df);
1032 return (u_arg1 < max_uint - u_arg2) ? u_arg1 + u_arg2 : max_uint;
1033 }
1034
1035 static inline int64_t msa_ave_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1036 {
1037 /* signed shift */
1038 return (arg1 >> 1) + (arg2 >> 1) + (arg1 & arg2 & 1);
1039 }
1040
1041 static inline uint64_t msa_ave_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
1042 {
1043 uint64_t u_arg1 = UNSIGNED(arg1, df);
1044 uint64_t u_arg2 = UNSIGNED(arg2, df);
1045 /* unsigned shift */
1046 return (u_arg1 >> 1) + (u_arg2 >> 1) + (u_arg1 & u_arg2 & 1);
1047 }
1048
1049 static inline int64_t msa_aver_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1050 {
1051 /* signed shift */
1052 return (arg1 >> 1) + (arg2 >> 1) + ((arg1 | arg2) & 1);
1053 }
1054
1055 static inline uint64_t msa_aver_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
1056 {
1057 uint64_t u_arg1 = UNSIGNED(arg1, df);
1058 uint64_t u_arg2 = UNSIGNED(arg2, df);
1059 /* unsigned shift */
1060 return (u_arg1 >> 1) + (u_arg2 >> 1) + ((u_arg1 | u_arg2) & 1);
1061 }
1062
1063 static inline int64_t msa_subs_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1064 {
1065 int64_t max_int = DF_MAX_INT(df);
1066 int64_t min_int = DF_MIN_INT(df);
1067 if (arg2 > 0) {
1068 return (min_int + arg2 < arg1) ? arg1 - arg2 : min_int;
1069 } else {
1070 return (arg1 < max_int + arg2) ? arg1 - arg2 : max_int;
1071 }
1072 }
1073
1074 static inline int64_t msa_subs_u_df(uint32_t df, int64_t arg1, int64_t arg2)
1075 {
1076 uint64_t u_arg1 = UNSIGNED(arg1, df);
1077 uint64_t u_arg2 = UNSIGNED(arg2, df);
1078 return (u_arg1 > u_arg2) ? u_arg1 - u_arg2 : 0;
1079 }
1080
1081 static inline int64_t msa_subsus_u_df(uint32_t df, int64_t arg1, int64_t arg2)
1082 {
1083 uint64_t u_arg1 = UNSIGNED(arg1, df);
1084 uint64_t max_uint = DF_MAX_UINT(df);
1085 if (arg2 >= 0) {
1086 uint64_t u_arg2 = (uint64_t)arg2;
1087 return (u_arg1 > u_arg2) ?
1088 (int64_t)(u_arg1 - u_arg2) :
1089 0;
1090 } else {
1091 uint64_t u_arg2 = (uint64_t)(-arg2);
1092 return (u_arg1 < max_uint - u_arg2) ?
1093 (int64_t)(u_arg1 + u_arg2) :
1094 (int64_t)max_uint;
1095 }
1096 }
1097
1098 static inline int64_t msa_subsuu_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1099 {
1100 uint64_t u_arg1 = UNSIGNED(arg1, df);
1101 uint64_t u_arg2 = UNSIGNED(arg2, df);
1102 int64_t max_int = DF_MAX_INT(df);
1103 int64_t min_int = DF_MIN_INT(df);
1104 if (u_arg1 > u_arg2) {
1105 return u_arg1 - u_arg2 < (uint64_t)max_int ?
1106 (int64_t)(u_arg1 - u_arg2) :
1107 max_int;
1108 } else {
1109 return u_arg2 - u_arg1 < (uint64_t)(-min_int) ?
1110 (int64_t)(u_arg1 - u_arg2) :
1111 min_int;
1112 }
1113 }
1114
1115 static inline int64_t msa_asub_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1116 {
1117 /* signed compare */
1118 return (arg1 < arg2) ?
1119 (uint64_t)(arg2 - arg1) : (uint64_t)(arg1 - arg2);
1120 }
1121
1122 static inline uint64_t msa_asub_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
1123 {
1124 uint64_t u_arg1 = UNSIGNED(arg1, df);
1125 uint64_t u_arg2 = UNSIGNED(arg2, df);
1126 /* unsigned compare */
1127 return (u_arg1 < u_arg2) ?
1128 (uint64_t)(u_arg2 - u_arg1) : (uint64_t)(u_arg1 - u_arg2);
1129 }
1130
1131 static inline int64_t msa_mulv_df(uint32_t df, int64_t arg1, int64_t arg2)
1132 {
1133 return arg1 * arg2;
1134 }
1135
1136 static inline int64_t msa_div_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1137 {
1138 if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
1139 return DF_MIN_INT(df);
1140 }
1141 return arg2 ? arg1 / arg2
1142 : arg1 >= 0 ? -1 : 1;
1143 }
1144
1145 static inline int64_t msa_div_u_df(uint32_t df, int64_t arg1, int64_t arg2)
1146 {
1147 uint64_t u_arg1 = UNSIGNED(arg1, df);
1148 uint64_t u_arg2 = UNSIGNED(arg2, df);
1149 return arg2 ? u_arg1 / u_arg2 : -1;
1150 }
1151
1152 static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1153 {
1154 if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
1155 return 0;
1156 }
1157 return arg2 ? arg1 % arg2 : arg1;
1158 }
1159
1160 static inline int64_t msa_mod_u_df(uint32_t df, int64_t arg1, int64_t arg2)
1161 {
1162 uint64_t u_arg1 = UNSIGNED(arg1, df);
1163 uint64_t u_arg2 = UNSIGNED(arg2, df);
1164 return u_arg2 ? u_arg1 % u_arg2 : u_arg1;
1165 }
1166
1167 #define SIGNED_EVEN(a, df) \
1168 ((((int64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2))
1169
1170 #define UNSIGNED_EVEN(a, df) \
1171 ((((uint64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2))
1172
1173 #define SIGNED_ODD(a, df) \
1174 ((((int64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2))
1175
1176 #define UNSIGNED_ODD(a, df) \
1177 ((((uint64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2))
1178
1179 #define SIGNED_EXTRACT(e, o, a, df) \
1180 do { \
1181 e = SIGNED_EVEN(a, df); \
1182 o = SIGNED_ODD(a, df); \
1183 } while (0)
1184
1185 #define UNSIGNED_EXTRACT(e, o, a, df) \
1186 do { \
1187 e = UNSIGNED_EVEN(a, df); \
1188 o = UNSIGNED_ODD(a, df); \
1189 } while (0)
1190
1191 static inline int64_t msa_dotp_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1192 {
1193 int64_t even_arg1;
1194 int64_t even_arg2;
1195 int64_t odd_arg1;
1196 int64_t odd_arg2;
1197 SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
1198 SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
1199 return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
1200 }
1201
1202 static inline int64_t msa_dotp_u_df(uint32_t df, int64_t arg1, int64_t arg2)
1203 {
1204 int64_t even_arg1;
1205 int64_t even_arg2;
1206 int64_t odd_arg1;
1207 int64_t odd_arg2;
1208 UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
1209 UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
1210 return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
1211 }
1212
1213 #define CONCATENATE_AND_SLIDE(s, k) \
1214 do { \
1215 for (i = 0; i < s; i++) { \
1216 v[i] = pws->b[s * k + i]; \
1217 v[i + s] = pwd->b[s * k + i]; \
1218 } \
1219 for (i = 0; i < s; i++) { \
1220 pwd->b[s * k + i] = v[i + n]; \
1221 } \
1222 } while (0)
1223
1224 static inline void msa_sld_df(uint32_t df, wr_t *pwd,
1225 wr_t *pws, target_ulong rt)
1226 {
1227 uint32_t n = rt % DF_ELEMENTS(df);
1228 uint8_t v[64];
1229 uint32_t i, k;
1230
1231 switch (df) {
1232 case DF_BYTE:
1233 CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_BYTE), 0);
1234 break;
1235 case DF_HALF:
1236 for (k = 0; k < 2; k++) {
1237 CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_HALF), k);
1238 }
1239 break;
1240 case DF_WORD:
1241 for (k = 0; k < 4; k++) {
1242 CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_WORD), k);
1243 }
1244 break;
1245 case DF_DOUBLE:
1246 for (k = 0; k < 8; k++) {
1247 CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_DOUBLE), k);
1248 }
1249 break;
1250 default:
1251 assert(0);
1252 }
1253 }
1254
1255 static inline int64_t msa_hadd_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1256 {
1257 return SIGNED_ODD(arg1, df) + SIGNED_EVEN(arg2, df);
1258 }
1259
1260 static inline int64_t msa_hadd_u_df(uint32_t df, int64_t arg1, int64_t arg2)
1261 {
1262 return UNSIGNED_ODD(arg1, df) + UNSIGNED_EVEN(arg2, df);
1263 }
1264
1265 static inline int64_t msa_hsub_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1266 {
1267 return SIGNED_ODD(arg1, df) - SIGNED_EVEN(arg2, df);
1268 }
1269
1270 static inline int64_t msa_hsub_u_df(uint32_t df, int64_t arg1, int64_t arg2)
1271 {
1272 return UNSIGNED_ODD(arg1, df) - UNSIGNED_EVEN(arg2, df);
1273 }
1274
1275 static inline int64_t msa_mul_q_df(uint32_t df, int64_t arg1, int64_t arg2)
1276 {
1277 int64_t q_min = DF_MIN_INT(df);
1278 int64_t q_max = DF_MAX_INT(df);
1279
1280 if (arg1 == q_min && arg2 == q_min) {
1281 return q_max;
1282 }
1283 return (arg1 * arg2) >> (DF_BITS(df) - 1);
1284 }
1285
1286 static inline int64_t msa_mulr_q_df(uint32_t df, int64_t arg1, int64_t arg2)
1287 {
1288 int64_t q_min = DF_MIN_INT(df);
1289 int64_t q_max = DF_MAX_INT(df);
1290 int64_t r_bit = 1 << (DF_BITS(df) - 2);
1291
1292 if (arg1 == q_min && arg2 == q_min) {
1293 return q_max;
1294 }
1295 return (arg1 * arg2 + r_bit) >> (DF_BITS(df) - 1);
1296 }
1297
1298 #define MSA_BINOP_DF(func) \
1299 void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \
1300 uint32_t wd, uint32_t ws, uint32_t wt) \
1301 { \
1302 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
1303 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
1304 wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \
1305 \
1306 switch (df) { \
1307 case DF_BYTE: \
1308 pwd->b[0] = msa_ ## func ## _df(df, pws->b[0], pwt->b[0]); \
1309 pwd->b[1] = msa_ ## func ## _df(df, pws->b[1], pwt->b[1]); \
1310 pwd->b[2] = msa_ ## func ## _df(df, pws->b[2], pwt->b[2]); \
1311 pwd->b[3] = msa_ ## func ## _df(df, pws->b[3], pwt->b[3]); \
1312 pwd->b[4] = msa_ ## func ## _df(df, pws->b[4], pwt->b[4]); \
1313 pwd->b[5] = msa_ ## func ## _df(df, pws->b[5], pwt->b[5]); \
1314 pwd->b[6] = msa_ ## func ## _df(df, pws->b[6], pwt->b[6]); \
1315 pwd->b[7] = msa_ ## func ## _df(df, pws->b[7], pwt->b[7]); \
1316 pwd->b[8] = msa_ ## func ## _df(df, pws->b[8], pwt->b[8]); \
1317 pwd->b[9] = msa_ ## func ## _df(df, pws->b[9], pwt->b[9]); \
1318 pwd->b[10] = msa_ ## func ## _df(df, pws->b[10], pwt->b[10]); \
1319 pwd->b[11] = msa_ ## func ## _df(df, pws->b[11], pwt->b[11]); \
1320 pwd->b[12] = msa_ ## func ## _df(df, pws->b[12], pwt->b[12]); \
1321 pwd->b[13] = msa_ ## func ## _df(df, pws->b[13], pwt->b[13]); \
1322 pwd->b[14] = msa_ ## func ## _df(df, pws->b[14], pwt->b[14]); \
1323 pwd->b[15] = msa_ ## func ## _df(df, pws->b[15], pwt->b[15]); \
1324 break; \
1325 case DF_HALF: \
1326 pwd->h[0] = msa_ ## func ## _df(df, pws->h[0], pwt->h[0]); \
1327 pwd->h[1] = msa_ ## func ## _df(df, pws->h[1], pwt->h[1]); \
1328 pwd->h[2] = msa_ ## func ## _df(df, pws->h[2], pwt->h[2]); \
1329 pwd->h[3] = msa_ ## func ## _df(df, pws->h[3], pwt->h[3]); \
1330 pwd->h[4] = msa_ ## func ## _df(df, pws->h[4], pwt->h[4]); \
1331 pwd->h[5] = msa_ ## func ## _df(df, pws->h[5], pwt->h[5]); \
1332 pwd->h[6] = msa_ ## func ## _df(df, pws->h[6], pwt->h[6]); \
1333 pwd->h[7] = msa_ ## func ## _df(df, pws->h[7], pwt->h[7]); \
1334 break; \
1335 case DF_WORD: \
1336 pwd->w[0] = msa_ ## func ## _df(df, pws->w[0], pwt->w[0]); \
1337 pwd->w[1] = msa_ ## func ## _df(df, pws->w[1], pwt->w[1]); \
1338 pwd->w[2] = msa_ ## func ## _df(df, pws->w[2], pwt->w[2]); \
1339 pwd->w[3] = msa_ ## func ## _df(df, pws->w[3], pwt->w[3]); \
1340 break; \
1341 case DF_DOUBLE: \
1342 pwd->d[0] = msa_ ## func ## _df(df, pws->d[0], pwt->d[0]); \
1343 pwd->d[1] = msa_ ## func ## _df(df, pws->d[1], pwt->d[1]); \
1344 break; \
1345 default: \
1346 assert(0); \
1347 } \
1348 }
1349
1350 MSA_BINOP_DF(sll)
1351 MSA_BINOP_DF(sra)
1352 MSA_BINOP_DF(srl)
1353 MSA_BINOP_DF(bclr)
1354 MSA_BINOP_DF(bset)
1355 MSA_BINOP_DF(bneg)
1356 MSA_BINOP_DF(addv)
1357 MSA_BINOP_DF(subv)
1358 MSA_BINOP_DF(max_s)
1359 MSA_BINOP_DF(max_u)
1360 MSA_BINOP_DF(min_s)
1361 MSA_BINOP_DF(min_u)
1362 MSA_BINOP_DF(max_a)
1363 MSA_BINOP_DF(min_a)
1364 MSA_BINOP_DF(ceq)
1365 MSA_BINOP_DF(clt_s)
1366 MSA_BINOP_DF(clt_u)
1367 MSA_BINOP_DF(cle_s)
1368 MSA_BINOP_DF(cle_u)
1369 MSA_BINOP_DF(add_a)
1370 MSA_BINOP_DF(adds_a)
1371 MSA_BINOP_DF(adds_s)
1372 MSA_BINOP_DF(adds_u)
1373 MSA_BINOP_DF(ave_s)
1374 MSA_BINOP_DF(ave_u)
1375 MSA_BINOP_DF(aver_s)
1376 MSA_BINOP_DF(aver_u)
1377 MSA_BINOP_DF(subs_s)
1378 MSA_BINOP_DF(subs_u)
1379 MSA_BINOP_DF(subsus_u)
1380 MSA_BINOP_DF(subsuu_s)
1381 MSA_BINOP_DF(asub_s)
1382 MSA_BINOP_DF(asub_u)
1383 MSA_BINOP_DF(mulv)
1384 MSA_BINOP_DF(div_s)
1385 MSA_BINOP_DF(div_u)
1386 MSA_BINOP_DF(mod_s)
1387 MSA_BINOP_DF(mod_u)
1388 MSA_BINOP_DF(dotp_s)
1389 MSA_BINOP_DF(dotp_u)
1390 MSA_BINOP_DF(srar)
1391 MSA_BINOP_DF(srlr)
1392 MSA_BINOP_DF(hadd_s)
1393 MSA_BINOP_DF(hadd_u)
1394 MSA_BINOP_DF(hsub_s)
1395 MSA_BINOP_DF(hsub_u)
1396
1397 MSA_BINOP_DF(mul_q)
1398 MSA_BINOP_DF(mulr_q)
1399 #undef MSA_BINOP_DF
1400
1401 void helper_msa_sld_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
1402 uint32_t ws, uint32_t rt)
1403 {
1404 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1405 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1406
1407 msa_sld_df(df, pwd, pws, env->active_tc.gpr[rt]);
1408 }
1409
1410 static inline int64_t msa_maddv_df(uint32_t df, int64_t dest, int64_t arg1,
1411 int64_t arg2)
1412 {
1413 return dest + arg1 * arg2;
1414 }
1415
1416 static inline int64_t msa_msubv_df(uint32_t df, int64_t dest, int64_t arg1,
1417 int64_t arg2)
1418 {
1419 return dest - arg1 * arg2;
1420 }
1421
1422 static inline int64_t msa_dpadd_s_df(uint32_t df, int64_t dest, int64_t arg1,
1423 int64_t arg2)
1424 {
1425 int64_t even_arg1;
1426 int64_t even_arg2;
1427 int64_t odd_arg1;
1428 int64_t odd_arg2;
1429 SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
1430 SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
1431 return dest + (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
1432 }
1433
1434 static inline int64_t msa_dpadd_u_df(uint32_t df, int64_t dest, int64_t arg1,
1435 int64_t arg2)
1436 {
1437 int64_t even_arg1;
1438 int64_t even_arg2;
1439 int64_t odd_arg1;
1440 int64_t odd_arg2;
1441 UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
1442 UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
1443 return dest + (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
1444 }
1445
1446 static inline int64_t msa_dpsub_s_df(uint32_t df, int64_t dest, int64_t arg1,
1447 int64_t arg2)
1448 {
1449 int64_t even_arg1;
1450 int64_t even_arg2;
1451 int64_t odd_arg1;
1452 int64_t odd_arg2;
1453 SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
1454 SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
1455 return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2));
1456 }
1457
1458 static inline int64_t msa_dpsub_u_df(uint32_t df, int64_t dest, int64_t arg1,
1459 int64_t arg2)
1460 {
1461 int64_t even_arg1;
1462 int64_t even_arg2;
1463 int64_t odd_arg1;
1464 int64_t odd_arg2;
1465 UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
1466 UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
1467 return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2));
1468 }
1469
1470 static inline int64_t msa_madd_q_df(uint32_t df, int64_t dest, int64_t arg1,
1471 int64_t arg2)
1472 {
1473 int64_t q_prod, q_ret;
1474
1475 int64_t q_max = DF_MAX_INT(df);
1476 int64_t q_min = DF_MIN_INT(df);
1477
1478 q_prod = arg1 * arg2;
1479 q_ret = ((dest << (DF_BITS(df) - 1)) + q_prod) >> (DF_BITS(df) - 1);
1480
1481 return (q_ret < q_min) ? q_min : (q_max < q_ret) ? q_max : q_ret;
1482 }
1483
1484 static inline int64_t msa_msub_q_df(uint32_t df, int64_t dest, int64_t arg1,
1485 int64_t arg2)
1486 {
1487 int64_t q_prod, q_ret;
1488
1489 int64_t q_max = DF_MAX_INT(df);
1490 int64_t q_min = DF_MIN_INT(df);
1491
1492 q_prod = arg1 * arg2;
1493 q_ret = ((dest << (DF_BITS(df) - 1)) - q_prod) >> (DF_BITS(df) - 1);
1494
1495 return (q_ret < q_min) ? q_min : (q_max < q_ret) ? q_max : q_ret;
1496 }
1497
1498 static inline int64_t msa_maddr_q_df(uint32_t df, int64_t dest, int64_t arg1,
1499 int64_t arg2)
1500 {
1501 int64_t q_prod, q_ret;
1502
1503 int64_t q_max = DF_MAX_INT(df);
1504 int64_t q_min = DF_MIN_INT(df);
1505 int64_t r_bit = 1 << (DF_BITS(df) - 2);
1506
1507 q_prod = arg1 * arg2;
1508 q_ret = ((dest << (DF_BITS(df) - 1)) + q_prod + r_bit) >> (DF_BITS(df) - 1);
1509
1510 return (q_ret < q_min) ? q_min : (q_max < q_ret) ? q_max : q_ret;
1511 }
1512
1513 static inline int64_t msa_msubr_q_df(uint32_t df, int64_t dest, int64_t arg1,
1514 int64_t arg2)
1515 {
1516 int64_t q_prod, q_ret;
1517
1518 int64_t q_max = DF_MAX_INT(df);
1519 int64_t q_min = DF_MIN_INT(df);
1520 int64_t r_bit = 1 << (DF_BITS(df) - 2);
1521
1522 q_prod = arg1 * arg2;
1523 q_ret = ((dest << (DF_BITS(df) - 1)) - q_prod + r_bit) >> (DF_BITS(df) - 1);
1524
1525 return (q_ret < q_min) ? q_min : (q_max < q_ret) ? q_max : q_ret;
1526 }
1527
1528 #define MSA_TEROP_DF(func) \
1529 void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd, \
1530 uint32_t ws, uint32_t wt) \
1531 { \
1532 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
1533 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
1534 wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \
1535 \
1536 switch (df) { \
1537 case DF_BYTE: \
1538 pwd->b[0] = msa_ ## func ## _df(df, pwd->b[0], pws->b[0], \
1539 pwt->b[0]); \
1540 pwd->b[1] = msa_ ## func ## _df(df, pwd->b[1], pws->b[1], \
1541 pwt->b[1]); \
1542 pwd->b[2] = msa_ ## func ## _df(df, pwd->b[2], pws->b[2], \
1543 pwt->b[2]); \
1544 pwd->b[3] = msa_ ## func ## _df(df, pwd->b[3], pws->b[3], \
1545 pwt->b[3]); \
1546 pwd->b[4] = msa_ ## func ## _df(df, pwd->b[4], pws->b[4], \
1547 pwt->b[4]); \
1548 pwd->b[5] = msa_ ## func ## _df(df, pwd->b[5], pws->b[5], \
1549 pwt->b[5]); \
1550 pwd->b[6] = msa_ ## func ## _df(df, pwd->b[6], pws->b[6], \
1551 pwt->b[6]); \
1552 pwd->b[7] = msa_ ## func ## _df(df, pwd->b[7], pws->b[7], \
1553 pwt->b[7]); \
1554 pwd->b[8] = msa_ ## func ## _df(df, pwd->b[8], pws->b[8], \
1555 pwt->b[8]); \
1556 pwd->b[9] = msa_ ## func ## _df(df, pwd->b[9], pws->b[9], \
1557 pwt->b[9]); \
1558 pwd->b[10] = msa_ ## func ## _df(df, pwd->b[10], pws->b[10], \
1559 pwt->b[10]); \
1560 pwd->b[11] = msa_ ## func ## _df(df, pwd->b[11], pws->b[11], \
1561 pwt->b[11]); \
1562 pwd->b[12] = msa_ ## func ## _df(df, pwd->b[12], pws->b[12], \
1563 pwt->b[12]); \
1564 pwd->b[13] = msa_ ## func ## _df(df, pwd->b[13], pws->b[13], \
1565 pwt->b[13]); \
1566 pwd->b[14] = msa_ ## func ## _df(df, pwd->b[14], pws->b[14], \
1567 pwt->b[14]); \
1568 pwd->b[15] = msa_ ## func ## _df(df, pwd->b[15], pws->b[15], \
1569 pwt->b[15]); \
1570 break; \
1571 case DF_HALF: \
1572 pwd->h[0] = msa_ ## func ## _df(df, pwd->h[0], pws->h[0], pwt->h[0]); \
1573 pwd->h[1] = msa_ ## func ## _df(df, pwd->h[1], pws->h[1], pwt->h[1]); \
1574 pwd->h[2] = msa_ ## func ## _df(df, pwd->h[2], pws->h[2], pwt->h[2]); \
1575 pwd->h[3] = msa_ ## func ## _df(df, pwd->h[3], pws->h[3], pwt->h[3]); \
1576 pwd->h[4] = msa_ ## func ## _df(df, pwd->h[4], pws->h[4], pwt->h[4]); \
1577 pwd->h[5] = msa_ ## func ## _df(df, pwd->h[5], pws->h[5], pwt->h[5]); \
1578 pwd->h[6] = msa_ ## func ## _df(df, pwd->h[6], pws->h[6], pwt->h[6]); \
1579 pwd->h[7] = msa_ ## func ## _df(df, pwd->h[7], pws->h[7], pwt->h[7]); \
1580 break; \
1581 case DF_WORD: \
1582 pwd->w[0] = msa_ ## func ## _df(df, pwd->w[0], pws->w[0], pwt->w[0]); \
1583 pwd->w[1] = msa_ ## func ## _df(df, pwd->w[1], pws->w[1], pwt->w[1]); \
1584 pwd->w[2] = msa_ ## func ## _df(df, pwd->w[2], pws->w[2], pwt->w[2]); \
1585 pwd->w[3] = msa_ ## func ## _df(df, pwd->w[3], pws->w[3], pwt->w[3]); \
1586 break; \
1587 case DF_DOUBLE: \
1588 pwd->d[0] = msa_ ## func ## _df(df, pwd->d[0], pws->d[0], pwt->d[0]); \
1589 pwd->d[1] = msa_ ## func ## _df(df, pwd->d[1], pws->d[1], pwt->d[1]); \
1590 break; \
1591 default: \
1592 assert(0); \
1593 } \
1594 }
1595
1596 MSA_TEROP_DF(maddv)
1597 MSA_TEROP_DF(msubv)
1598 MSA_TEROP_DF(dpadd_s)
1599 MSA_TEROP_DF(dpadd_u)
1600 MSA_TEROP_DF(dpsub_s)
1601 MSA_TEROP_DF(dpsub_u)
1602 MSA_TEROP_DF(binsl)
1603 MSA_TEROP_DF(binsr)
1604 MSA_TEROP_DF(madd_q)
1605 MSA_TEROP_DF(msub_q)
1606 MSA_TEROP_DF(maddr_q)
1607 MSA_TEROP_DF(msubr_q)
1608 #undef MSA_TEROP_DF
1609
1610 static inline void msa_splat_df(uint32_t df, wr_t *pwd,
1611 wr_t *pws, target_ulong rt)
1612 {
1613 uint32_t n = rt % DF_ELEMENTS(df);
1614 uint32_t i;
1615
1616 switch (df) {
1617 case DF_BYTE:
1618 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
1619 pwd->b[i] = pws->b[n];
1620 }
1621 break;
1622 case DF_HALF:
1623 for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {
1624 pwd->h[i] = pws->h[n];
1625 }
1626 break;
1627 case DF_WORD:
1628 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
1629 pwd->w[i] = pws->w[n];
1630 }
1631 break;
1632 case DF_DOUBLE:
1633 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
1634 pwd->d[i] = pws->d[n];
1635 }
1636 break;
1637 default:
1638 assert(0);
1639 }
1640 }
1641
1642 void helper_msa_splat_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
1643 uint32_t ws, uint32_t rt)
1644 {
1645 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1646 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1647
1648 msa_splat_df(df, pwd, pws, env->active_tc.gpr[rt]);
1649 }
1650
1651 #define MSA_DO_B MSA_DO(b)
1652 #define MSA_DO_H MSA_DO(h)
1653 #define MSA_DO_W MSA_DO(w)
1654 #define MSA_DO_D MSA_DO(d)
1655
1656 #define MSA_LOOP_B MSA_LOOP(B)
1657 #define MSA_LOOP_H MSA_LOOP(H)
1658 #define MSA_LOOP_W MSA_LOOP(W)
1659 #define MSA_LOOP_D MSA_LOOP(D)
1660
1661 #define MSA_LOOP_COND_B MSA_LOOP_COND(DF_BYTE)
1662 #define MSA_LOOP_COND_H MSA_LOOP_COND(DF_HALF)
1663 #define MSA_LOOP_COND_W MSA_LOOP_COND(DF_WORD)
1664 #define MSA_LOOP_COND_D MSA_LOOP_COND(DF_DOUBLE)
1665
1666 #define MSA_LOOP(DF) \
1667 do { \
1668 for (i = 0; i < (MSA_LOOP_COND_ ## DF) ; i++) { \
1669 MSA_DO_ ## DF; \
1670 } \
1671 } while (0)
1672
1673 #define MSA_FN_DF(FUNC) \
1674 void helper_msa_##FUNC(CPUMIPSState *env, uint32_t df, uint32_t wd, \
1675 uint32_t ws, uint32_t wt) \
1676 { \
1677 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
1678 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
1679 wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \
1680 wr_t wx, *pwx = &wx; \
1681 uint32_t i; \
1682 switch (df) { \
1683 case DF_BYTE: \
1684 MSA_LOOP_B; \
1685 break; \
1686 case DF_HALF: \
1687 MSA_LOOP_H; \
1688 break; \
1689 case DF_WORD: \
1690 MSA_LOOP_W; \
1691 break; \
1692 case DF_DOUBLE: \
1693 MSA_LOOP_D; \
1694 break; \
1695 default: \
1696 assert(0); \
1697 } \
1698 msa_move_v(pwd, pwx); \
1699 }
1700
1701 #define MSA_LOOP_COND(DF) \
1702 (DF_ELEMENTS(DF) / 2)
1703
1704 #define Rb(pwr, i) (pwr->b[i])
1705 #define Lb(pwr, i) (pwr->b[i + DF_ELEMENTS(DF_BYTE) / 2])
1706 #define Rh(pwr, i) (pwr->h[i])
1707 #define Lh(pwr, i) (pwr->h[i + DF_ELEMENTS(DF_HALF) / 2])
1708 #define Rw(pwr, i) (pwr->w[i])
1709 #define Lw(pwr, i) (pwr->w[i + DF_ELEMENTS(DF_WORD) / 2])
1710 #define Rd(pwr, i) (pwr->d[i])
1711 #define Ld(pwr, i) (pwr->d[i + DF_ELEMENTS(DF_DOUBLE) / 2])
1712
1713 #undef MSA_LOOP_COND
1714
1715 #define MSA_LOOP_COND(DF) \
1716 (DF_ELEMENTS(DF))
1717
1718 #define MSA_DO(DF) \
1719 do { \
1720 uint32_t n = DF_ELEMENTS(df); \
1721 uint32_t k = (pwd->DF[i] & 0x3f) % (2 * n); \
1722 pwx->DF[i] = \
1723 (pwd->DF[i] & 0xc0) ? 0 : k < n ? pwt->DF[k] : pws->DF[k - n]; \
1724 } while (0)
1725 MSA_FN_DF(vshf_df)
1726 #undef MSA_DO
1727 #undef MSA_LOOP_COND
1728 #undef MSA_FN_DF
1729
1730
1731 void helper_msa_ilvev_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
1732 uint32_t ws, uint32_t wt)
1733 {
1734 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1735 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1736 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1737
1738 switch (df) {
1739 case DF_BYTE:
1740 #if defined(HOST_WORDS_BIGENDIAN)
1741 pwd->b[8] = pws->b[9];
1742 pwd->b[9] = pwt->b[9];
1743 pwd->b[10] = pws->b[11];
1744 pwd->b[11] = pwt->b[11];
1745 pwd->b[12] = pws->b[13];
1746 pwd->b[13] = pwt->b[13];
1747 pwd->b[14] = pws->b[15];
1748 pwd->b[15] = pwt->b[15];
1749 pwd->b[0] = pws->b[1];
1750 pwd->b[1] = pwt->b[1];
1751 pwd->b[2] = pws->b[3];
1752 pwd->b[3] = pwt->b[3];
1753 pwd->b[4] = pws->b[5];
1754 pwd->b[5] = pwt->b[5];
1755 pwd->b[6] = pws->b[7];
1756 pwd->b[7] = pwt->b[7];
1757 #else
1758 pwd->b[15] = pws->b[14];
1759 pwd->b[14] = pwt->b[14];
1760 pwd->b[13] = pws->b[12];
1761 pwd->b[12] = pwt->b[12];
1762 pwd->b[11] = pws->b[10];
1763 pwd->b[10] = pwt->b[10];
1764 pwd->b[9] = pws->b[8];
1765 pwd->b[8] = pwt->b[8];
1766 pwd->b[7] = pws->b[6];
1767 pwd->b[6] = pwt->b[6];
1768 pwd->b[5] = pws->b[4];
1769 pwd->b[4] = pwt->b[4];
1770 pwd->b[3] = pws->b[2];
1771 pwd->b[2] = pwt->b[2];
1772 pwd->b[1] = pws->b[0];
1773 pwd->b[0] = pwt->b[0];
1774 #endif
1775 break;
1776 case DF_HALF:
1777 #if defined(HOST_WORDS_BIGENDIAN)
1778 pwd->h[4] = pws->h[5];
1779 pwd->h[5] = pwt->h[5];
1780 pwd->h[6] = pws->h[7];
1781 pwd->h[7] = pwt->h[7];
1782 pwd->h[0] = pws->h[1];
1783 pwd->h[1] = pwt->h[1];
1784 pwd->h[2] = pws->h[3];
1785 pwd->h[3] = pwt->h[3];
1786 #else
1787 pwd->h[7] = pws->h[6];
1788 pwd->h[6] = pwt->h[6];
1789 pwd->h[5] = pws->h[4];
1790 pwd->h[4] = pwt->h[4];
1791 pwd->h[3] = pws->h[2];
1792 pwd->h[2] = pwt->h[2];
1793 pwd->h[1] = pws->h[0];
1794 pwd->h[0] = pwt->h[0];
1795 #endif
1796 break;
1797 case DF_WORD:
1798 #if defined(HOST_WORDS_BIGENDIAN)
1799 pwd->w[2] = pws->w[3];
1800 pwd->w[3] = pwt->w[3];
1801 pwd->w[0] = pws->w[1];
1802 pwd->w[1] = pwt->w[1];
1803 #else
1804 pwd->w[3] = pws->w[2];
1805 pwd->w[2] = pwt->w[2];
1806 pwd->w[1] = pws->w[0];
1807 pwd->w[0] = pwt->w[0];
1808 #endif
1809 break;
1810 case DF_DOUBLE:
1811 pwd->d[1] = pws->d[0];
1812 pwd->d[0] = pwt->d[0];
1813 break;
1814 default:
1815 assert(0);
1816 }
1817 }
1818
1819 void helper_msa_ilvod_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
1820 uint32_t ws, uint32_t wt)
1821 {
1822 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1823 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1824 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1825
1826 switch (df) {
1827 case DF_BYTE:
1828 #if defined(HOST_WORDS_BIGENDIAN)
1829 pwd->b[7] = pwt->b[6];
1830 pwd->b[6] = pws->b[6];
1831 pwd->b[5] = pwt->b[4];
1832 pwd->b[4] = pws->b[4];
1833 pwd->b[3] = pwt->b[2];
1834 pwd->b[2] = pws->b[2];
1835 pwd->b[1] = pwt->b[0];
1836 pwd->b[0] = pws->b[0];
1837 pwd->b[15] = pwt->b[14];
1838 pwd->b[14] = pws->b[14];
1839 pwd->b[13] = pwt->b[12];
1840 pwd->b[12] = pws->b[12];
1841 pwd->b[11] = pwt->b[10];
1842 pwd->b[10] = pws->b[10];
1843 pwd->b[9] = pwt->b[8];
1844 pwd->b[8] = pws->b[8];
1845 #else
1846 pwd->b[0] = pwt->b[1];
1847 pwd->b[1] = pws->b[1];
1848 pwd->b[2] = pwt->b[3];
1849 pwd->b[3] = pws->b[3];
1850 pwd->b[4] = pwt->b[5];
1851 pwd->b[5] = pws->b[5];
1852 pwd->b[6] = pwt->b[7];
1853 pwd->b[7] = pws->b[7];
1854 pwd->b[8] = pwt->b[9];
1855 pwd->b[9] = pws->b[9];
1856 pwd->b[10] = pwt->b[11];
1857 pwd->b[11] = pws->b[11];
1858 pwd->b[12] = pwt->b[13];
1859 pwd->b[13] = pws->b[13];
1860 pwd->b[14] = pwt->b[15];
1861 pwd->b[15] = pws->b[15];
1862 #endif
1863 break;
1864 case DF_HALF:
1865 #if defined(HOST_WORDS_BIGENDIAN)
1866 pwd->h[3] = pwt->h[2];
1867 pwd->h[2] = pws->h[2];
1868 pwd->h[1] = pwt->h[0];
1869 pwd->h[0] = pws->h[0];
1870 pwd->h[7] = pwt->h[6];
1871 pwd->h[6] = pws->h[6];
1872 pwd->h[5] = pwt->h[4];
1873 pwd->h[4] = pws->h[4];
1874 #else
1875 pwd->h[0] = pwt->h[1];
1876 pwd->h[1] = pws->h[1];
1877 pwd->h[2] = pwt->h[3];
1878 pwd->h[3] = pws->h[3];
1879 pwd->h[4] = pwt->h[5];
1880 pwd->h[5] = pws->h[5];
1881 pwd->h[6] = pwt->h[7];
1882 pwd->h[7] = pws->h[7];
1883 #endif
1884 break;
1885 case DF_WORD:
1886 #if defined(HOST_WORDS_BIGENDIAN)
1887 pwd->w[1] = pwt->w[0];
1888 pwd->w[0] = pws->w[0];
1889 pwd->w[3] = pwt->w[2];
1890 pwd->w[2] = pws->w[2];
1891 #else
1892 pwd->w[0] = pwt->w[1];
1893 pwd->w[1] = pws->w[1];
1894 pwd->w[2] = pwt->w[3];
1895 pwd->w[3] = pws->w[3];
1896 #endif
1897 break;
1898 case DF_DOUBLE:
1899 pwd->d[0] = pwt->d[1];
1900 pwd->d[1] = pws->d[1];
1901 break;
1902 default:
1903 assert(0);
1904 }
1905 }
1906
1907 void helper_msa_ilvl_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
1908 uint32_t ws, uint32_t wt)
1909 {
1910 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1911 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1912 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1913
1914 switch (df) {
1915 case DF_BYTE:
1916 #if defined(HOST_WORDS_BIGENDIAN)
1917 pwd->b[7] = pwt->b[15];
1918 pwd->b[6] = pws->b[15];
1919 pwd->b[5] = pwt->b[14];
1920 pwd->b[4] = pws->b[14];
1921 pwd->b[3] = pwt->b[13];
1922 pwd->b[2] = pws->b[13];
1923 pwd->b[1] = pwt->b[12];
1924 pwd->b[0] = pws->b[12];
1925 pwd->b[15] = pwt->b[11];
1926 pwd->b[14] = pws->b[11];
1927 pwd->b[13] = pwt->b[10];
1928 pwd->b[12] = pws->b[10];
1929 pwd->b[11] = pwt->b[9];
1930 pwd->b[10] = pws->b[9];
1931 pwd->b[9] = pwt->b[8];
1932 pwd->b[8] = pws->b[8];
1933 #else
1934 pwd->b[0] = pwt->b[8];
1935 pwd->b[1] = pws->b[8];
1936 pwd->b[2] = pwt->b[9];
1937 pwd->b[3] = pws->b[9];
1938 pwd->b[4] = pwt->b[10];
1939 pwd->b[5] = pws->b[10];
1940 pwd->b[6] = pwt->b[11];
1941 pwd->b[7] = pws->b[11];
1942 pwd->b[8] = pwt->b[12];
1943 pwd->b[9] = pws->b[12];
1944 pwd->b[10] = pwt->b[13];
1945 pwd->b[11] = pws->b[13];
1946 pwd->b[12] = pwt->b[14];
1947 pwd->b[13] = pws->b[14];
1948 pwd->b[14] = pwt->b[15];
1949 pwd->b[15] = pws->b[15];
1950 #endif
1951 break;
1952 case DF_HALF:
1953 #if defined(HOST_WORDS_BIGENDIAN)
1954 pwd->h[3] = pwt->h[7];
1955 pwd->h[2] = pws->h[7];
1956 pwd->h[1] = pwt->h[6];
1957 pwd->h[0] = pws->h[6];
1958 pwd->h[7] = pwt->h[5];
1959 pwd->h[6] = pws->h[5];
1960 pwd->h[5] = pwt->h[4];
1961 pwd->h[4] = pws->h[4];
1962 #else
1963 pwd->h[0] = pwt->h[4];
1964 pwd->h[1] = pws->h[4];
1965 pwd->h[2] = pwt->h[5];
1966 pwd->h[3] = pws->h[5];
1967 pwd->h[4] = pwt->h[6];
1968 pwd->h[5] = pws->h[6];
1969 pwd->h[6] = pwt->h[7];
1970 pwd->h[7] = pws->h[7];
1971 #endif
1972 break;
1973 case DF_WORD:
1974 #if defined(HOST_WORDS_BIGENDIAN)
1975 pwd->w[1] = pwt->w[3];
1976 pwd->w[0] = pws->w[3];
1977 pwd->w[3] = pwt->w[2];
1978 pwd->w[2] = pws->w[2];
1979 #else
1980 pwd->w[0] = pwt->w[2];
1981 pwd->w[1] = pws->w[2];
1982 pwd->w[2] = pwt->w[3];
1983 pwd->w[3] = pws->w[3];
1984 #endif
1985 break;
1986 case DF_DOUBLE:
1987 pwd->d[0] = pwt->d[1];
1988 pwd->d[1] = pws->d[1];
1989 break;
1990 default:
1991 assert(0);
1992 }
1993 }
1994
1995 void helper_msa_ilvr_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
1996 uint32_t ws, uint32_t wt)
1997 {
1998 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1999 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2000 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2001
2002 switch (df) {
2003 case DF_BYTE:
2004 #if defined(HOST_WORDS_BIGENDIAN)
2005 pwd->b[8] = pws->b[0];
2006 pwd->b[9] = pwt->b[0];
2007 pwd->b[10] = pws->b[1];
2008 pwd->b[11] = pwt->b[1];
2009 pwd->b[12] = pws->b[2];
2010 pwd->b[13] = pwt->b[2];
2011 pwd->b[14] = pws->b[3];
2012 pwd->b[15] = pwt->b[3];
2013 pwd->b[0] = pws->b[4];
2014 pwd->b[1] = pwt->b[4];
2015 pwd->b[2] = pws->b[5];
2016 pwd->b[3] = pwt->b[5];
2017 pwd->b[4] = pws->b[6];
2018 pwd->b[5] = pwt->b[6];
2019 pwd->b[6] = pws->b[7];
2020 pwd->b[7] = pwt->b[7];
2021 #else
2022 pwd->b[15] = pws->b[7];
2023 pwd->b[14] = pwt->b[7];
2024 pwd->b[13] = pws->b[6];
2025 pwd->b[12] = pwt->b[6];
2026 pwd->b[11] = pws->b[5];
2027 pwd->b[10] = pwt->b[5];
2028 pwd->b[9] = pws->b[4];
2029 pwd->b[8] = pwt->b[4];
2030 pwd->b[7] = pws->b[3];
2031 pwd->b[6] = pwt->b[3];
2032 pwd->b[5] = pws->b[2];
2033 pwd->b[4] = pwt->b[2];
2034 pwd->b[3] = pws->b[1];
2035 pwd->b[2] = pwt->b[1];
2036 pwd->b[1] = pws->b[0];
2037 pwd->b[0] = pwt->b[0];
2038 #endif
2039 break;
2040 case DF_HALF:
2041 #if defined(HOST_WORDS_BIGENDIAN)
2042 pwd->h[4] = pws->h[0];
2043 pwd->h[5] = pwt->h[0];
2044 pwd->h[6] = pws->h[1];
2045 pwd->h[7] = pwt->h[1];
2046 pwd->h[0] = pws->h[2];
2047 pwd->h[1] = pwt->h[2];
2048 pwd->h[2] = pws->h[3];
2049 pwd->h[3] = pwt->h[3];
2050 #else
2051 pwd->h[7] = pws->h[3];
2052 pwd->h[6] = pwt->h[3];
2053 pwd->h[5] = pws->h[2];
2054 pwd->h[4] = pwt->h[2];
2055 pwd->h[3] = pws->h[1];
2056 pwd->h[2] = pwt->h[1];
2057 pwd->h[1] = pws->h[0];
2058 pwd->h[0] = pwt->h[0];
2059 #endif
2060 break;
2061 case DF_WORD:
2062 #if defined(HOST_WORDS_BIGENDIAN)
2063 pwd->w[2] = pws->w[0];
2064 pwd->w[3] = pwt->w[0];
2065 pwd->w[0] = pws->w[1];
2066 pwd->w[1] = pwt->w[1];
2067 #else
2068 pwd->w[3] = pws->w[1];
2069 pwd->w[2] = pwt->w[1];
2070 pwd->w[1] = pws->w[0];
2071 pwd->w[0] = pwt->w[0];
2072 #endif
2073 break;
2074 case DF_DOUBLE:
2075 pwd->d[1] = pws->d[0];
2076 pwd->d[0] = pwt->d[0];
2077 break;
2078 default:
2079 assert(0);
2080 }
2081 }
2082
2083 void helper_msa_pckev_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
2084 uint32_t ws, uint32_t wt)
2085 {
2086 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2087 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2088 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2089
2090 switch (df) {
2091 case DF_BYTE:
2092 pwd->b[15] = pws->b[14];
2093 pwd->b[13] = pws->b[10];
2094 pwd->b[11] = pws->b[6];
2095 pwd->b[9] = pws->b[2];
2096 pwd->b[7] = pwt->b[14];
2097 pwd->b[5] = pwt->b[10];
2098 pwd->b[3] = pwt->b[6];
2099 pwd->b[1] = pwt->b[2];
2100 pwd->b[14] = pws->b[12];
2101 pwd->b[10] = pws->b[4];
2102 pwd->b[6] = pwt->b[12];
2103 pwd->b[2] = pwt->b[4];
2104 pwd->b[12] = pws->b[8];
2105 pwd->b[4] = pwt->b[8];
2106 pwd->b[8] = pws->b[0];
2107 pwd->b[0] = pwt->b[0];
2108 break;
2109 case DF_HALF:
2110 pwd->h[7] = pws->h[6];
2111 pwd->h[5] = pws->h[2];
2112 pwd->h[3] = pwt->h[6];
2113 pwd->h[1] = pwt->h[2];
2114 pwd->h[6] = pws->h[4];
2115 pwd->h[2] = pwt->h[4];
2116 pwd->h[4] = pws->h[0];
2117 pwd->h[0] = pwt->h[0];
2118 break;
2119 case DF_WORD:
2120 pwd->w[3] = pws->w[2];
2121 pwd->w[1] = pwt->w[2];
2122 pwd->w[2] = pws->w[0];
2123 pwd->w[0] = pwt->w[0];
2124 break;
2125 case DF_DOUBLE:
2126 pwd->d[1] = pws->d[0];
2127 pwd->d[0] = pwt->d[0];
2128 break;
2129 default:
2130 assert(0);
2131 }
2132 }
2133
2134 void helper_msa_pckod_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
2135 uint32_t ws, uint32_t wt)
2136 {
2137 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2138 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2139 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2140
2141 switch (df) {
2142 case DF_BYTE:
2143 pwd->b[0] = pwt->b[1];
2144 pwd->b[2] = pwt->b[5];
2145 pwd->b[4] = pwt->b[9];
2146 pwd->b[6] = pwt->b[13];
2147 pwd->b[8] = pws->b[1];
2148 pwd->b[10] = pws->b[5];
2149 pwd->b[12] = pws->b[9];
2150 pwd->b[14] = pws->b[13];
2151 pwd->b[1] = pwt->b[3];
2152 pwd->b[5] = pwt->b[11];
2153 pwd->b[9] = pws->b[3];
2154 pwd->b[13] = pws->b[11];
2155 pwd->b[3] = pwt->b[7];
2156 pwd->b[11] = pws->b[7];
2157 pwd->b[7] = pwt->b[15];
2158 pwd->b[15] = pws->b[15];
2159 break;
2160 case DF_HALF:
2161 pwd->h[0] = pwt->h[1];
2162 pwd->h[2] = pwt->h[5];
2163 pwd->h[4] = pws->h[1];
2164 pwd->h[6] = pws->h[5];
2165 pwd->h[1] = pwt->h[3];
2166 pwd->h[5] = pws->h[3];
2167 pwd->h[3] = pwt->h[7];
2168 pwd->h[7] = pws->h[7];
2169 break;
2170 case DF_WORD:
2171 pwd->w[0] = pwt->w[1];
2172 pwd->w[2] = pws->w[1];
2173 pwd->w[1] = pwt->w[3];
2174 pwd->w[3] = pws->w[3];
2175 break;
2176 case DF_DOUBLE:
2177 pwd->d[0] = pwt->d[1];
2178 pwd->d[1] = pws->d[1];
2179 break;
2180 default:
2181 assert(0);
2182 }
2183 }
2184
2185
2186 void helper_msa_sldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
2187 uint32_t ws, uint32_t n)
2188 {
2189 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2190 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2191
2192 msa_sld_df(df, pwd, pws, n);
2193 }
2194
2195 void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
2196 uint32_t ws, uint32_t n)
2197 {
2198 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2199 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2200
2201 msa_splat_df(df, pwd, pws, n);
2202 }
2203
2204 void helper_msa_copy_s_b(CPUMIPSState *env, uint32_t rd,
2205 uint32_t ws, uint32_t n)
2206 {
2207 n %= 16;
2208 #if defined(HOST_WORDS_BIGENDIAN)
2209 if (n < 8) {
2210 n = 8 - n - 1;
2211 } else {
2212 n = 24 - n - 1;
2213 }
2214 #endif
2215 env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n];
2216 }
2217
2218 void helper_msa_copy_s_h(CPUMIPSState *env, uint32_t rd,
2219 uint32_t ws, uint32_t n)
2220 {
2221 n %= 8;
2222 #if defined(HOST_WORDS_BIGENDIAN)
2223 if (n < 4) {
2224 n = 4 - n - 1;
2225 } else {
2226 n = 12 - n - 1;
2227 }
2228 #endif
2229 env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n];
2230 }
2231
2232 void helper_msa_copy_s_w(CPUMIPSState *env, uint32_t rd,
2233 uint32_t ws, uint32_t n)
2234 {
2235 n %= 4;
2236 #if defined(HOST_WORDS_BIGENDIAN)
2237 if (n < 2) {
2238 n = 2 - n - 1;
2239 } else {
2240 n = 6 - n - 1;
2241 }
2242 #endif
2243 env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n];
2244 }
2245
2246 void helper_msa_copy_s_d(CPUMIPSState *env, uint32_t rd,
2247 uint32_t ws, uint32_t n)
2248 {
2249 n %= 2;
2250 env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n];
2251 }
2252
2253 void helper_msa_copy_u_b(CPUMIPSState *env, uint32_t rd,
2254 uint32_t ws, uint32_t n)
2255 {
2256 n %= 16;
2257 #if defined(HOST_WORDS_BIGENDIAN)
2258 if (n < 8) {
2259 n = 8 - n - 1;
2260 } else {
2261 n = 24 - n - 1;
2262 }
2263 #endif
2264 env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n];
2265 }
2266
2267 void helper_msa_copy_u_h(CPUMIPSState *env, uint32_t rd,
2268 uint32_t ws, uint32_t n)
2269 {
2270 n %= 8;
2271 #if defined(HOST_WORDS_BIGENDIAN)
2272 if (n < 4) {
2273 n = 4 - n - 1;
2274 } else {
2275 n = 12 - n - 1;
2276 }
2277 #endif
2278 env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n];
2279 }
2280
2281 void helper_msa_copy_u_w(CPUMIPSState *env, uint32_t rd,
2282 uint32_t ws, uint32_t n)
2283 {
2284 n %= 4;
2285 #if defined(HOST_WORDS_BIGENDIAN)
2286 if (n < 2) {
2287 n = 2 - n - 1;
2288 } else {
2289 n = 6 - n - 1;
2290 }
2291 #endif
2292 env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n];
2293 }
2294
2295 void helper_msa_insert_b(CPUMIPSState *env, uint32_t wd,
2296 uint32_t rs_num, uint32_t n)
2297 {
2298 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2299 target_ulong rs = env->active_tc.gpr[rs_num];
2300 n %= 16;
2301 #if defined(HOST_WORDS_BIGENDIAN)
2302 if (n < 8) {
2303 n = 8 - n - 1;
2304 } else {
2305 n = 24 - n - 1;
2306 }
2307 #endif
2308 pwd->b[n] = (int8_t)rs;
2309 }
2310
2311 void helper_msa_insert_h(CPUMIPSState *env, uint32_t wd,
2312 uint32_t rs_num, uint32_t n)
2313 {
2314 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2315 target_ulong rs = env->active_tc.gpr[rs_num];
2316 n %= 8;
2317 #if defined(HOST_WORDS_BIGENDIAN)
2318 if (n < 4) {
2319 n = 4 - n - 1;
2320 } else {
2321 n = 12 - n - 1;
2322 }
2323 #endif
2324 pwd->h[n] = (int16_t)rs;
2325 }
2326
2327 void helper_msa_insert_w(CPUMIPSState *env, uint32_t wd,
2328 uint32_t rs_num, uint32_t n)
2329 {
2330 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2331 target_ulong rs = env->active_tc.gpr[rs_num];
2332 n %= 4;
2333 #if defined(HOST_WORDS_BIGENDIAN)
2334 if (n < 2) {
2335 n = 2 - n - 1;
2336 } else {
2337 n = 6 - n - 1;
2338 }
2339 #endif
2340 pwd->w[n] = (int32_t)rs;
2341 }
2342
2343 void helper_msa_insert_d(CPUMIPSState *env, uint32_t wd,
2344 uint32_t rs_num, uint32_t n)
2345 {
2346 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2347 target_ulong rs = env->active_tc.gpr[rs_num];
2348 n %= 2;
2349 pwd->d[n] = (int64_t)rs;
2350 }
2351
2352 void helper_msa_insve_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
2353 uint32_t ws, uint32_t n)
2354 {
2355 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2356 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2357
2358 switch (df) {
2359 case DF_BYTE:
2360 pwd->b[n] = (int8_t)pws->b[0];
2361 break;
2362 case DF_HALF:
2363 pwd->h[n] = (int16_t)pws->h[0];
2364 break;
2365 case DF_WORD:
2366 pwd->w[n] = (int32_t)pws->w[0];
2367 break;
2368 case DF_DOUBLE:
2369 pwd->d[n] = (int64_t)pws->d[0];
2370 break;
2371 default:
2372 assert(0);
2373 }
2374 }
2375
2376 void helper_msa_ctcmsa(CPUMIPSState *env, target_ulong elm, uint32_t cd)
2377 {
2378 switch (cd) {
2379 case 0:
2380 break;
2381 case 1:
2382 env->active_tc.msacsr = (int32_t)elm & MSACSR_MASK;
2383 restore_msa_fp_status(env);
2384 /* check exception */
2385 if ((GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED)
2386 & GET_FP_CAUSE(env->active_tc.msacsr)) {
2387 do_raise_exception(env, EXCP_MSAFPE, GETPC());
2388 }
2389 break;
2390 }
2391 }
2392
2393 target_ulong helper_msa_cfcmsa(CPUMIPSState *env, uint32_t cs)
2394 {
2395 switch (cs) {
2396 case 0:
2397 return env->msair;
2398 case 1:
2399 return env->active_tc.msacsr & MSACSR_MASK;
2400 }
2401 return 0;
2402 }
2403
2404 void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws)
2405 {
2406 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2407 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2408
2409 msa_move_v(pwd, pws);
2410 }
2411
2412 static inline int64_t msa_pcnt_df(uint32_t df, int64_t arg)
2413 {
2414 uint64_t x;
2415
2416 x = UNSIGNED(arg, df);
2417
2418 x = (x & 0x5555555555555555ULL) + ((x >> 1) & 0x5555555555555555ULL);
2419 x = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL);
2420 x = (x & 0x0F0F0F0F0F0F0F0FULL) + ((x >> 4) & 0x0F0F0F0F0F0F0F0FULL);
2421 x = (x & 0x00FF00FF00FF00FFULL) + ((x >> 8) & 0x00FF00FF00FF00FFULL);
2422 x = (x & 0x0000FFFF0000FFFFULL) + ((x >> 16) & 0x0000FFFF0000FFFFULL);
2423 x = (x & 0x00000000FFFFFFFFULL) + ((x >> 32));
2424
2425 return x;
2426 }
2427
2428 static inline int64_t msa_nlzc_df(uint32_t df, int64_t arg)
2429 {
2430 uint64_t x, y;
2431 int n, c;
2432
2433 x = UNSIGNED(arg, df);
2434 n = DF_BITS(df);
2435 c = DF_BITS(df) / 2;
2436
2437 do {
2438 y = x >> c;
2439 if (y != 0) {
2440 n = n - c;
2441 x = y;
2442 }
2443 c = c >> 1;
2444 } while (c != 0);
2445
2446 return n - x;
2447 }
2448
2449 static inline int64_t msa_nloc_df(uint32_t df, int64_t arg)
2450 {
2451 return msa_nlzc_df(df, UNSIGNED((~arg), df));
2452 }
2453
2454 void helper_msa_fill_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
2455 uint32_t rs)
2456 {
2457 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2458 uint32_t i;
2459
2460 switch (df) {
2461 case DF_BYTE:
2462 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
2463 pwd->b[i] = (int8_t)env->active_tc.gpr[rs];
2464 }
2465 break;
2466 case DF_HALF:
2467 for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {
2468 pwd->h[i] = (int16_t)env->active_tc.gpr[rs];
2469 }
2470 break;
2471 case DF_WORD:
2472 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
2473 pwd->w[i] = (int32_t)env->active_tc.gpr[rs];
2474 }
2475 break;
2476 case DF_DOUBLE:
2477 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
2478 pwd->d[i] = (int64_t)env->active_tc.gpr[rs];
2479 }
2480 break;
2481 default:
2482 assert(0);
2483 }
2484 }
2485
2486 #define MSA_UNOP_DF(func) \
2487 void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \
2488 uint32_t wd, uint32_t ws) \
2489 { \
2490 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
2491 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
2492 \
2493 switch (df) { \
2494 case DF_BYTE: \
2495 pwd->b[0] = msa_ ## func ## _df(df, pws->b[0]); \
2496 pwd->b[1] = msa_ ## func ## _df(df, pws->b[1]); \
2497 pwd->b[2] = msa_ ## func ## _df(df, pws->b[2]); \
2498 pwd->b[3] = msa_ ## func ## _df(df, pws->b[3]); \
2499 pwd->b[4] = msa_ ## func ## _df(df, pws->b[4]); \
2500 pwd->b[5] = msa_ ## func ## _df(df, pws->b[5]); \
2501 pwd->b[6] = msa_ ## func ## _df(df, pws->b[6]); \
2502 pwd->b[7] = msa_ ## func ## _df(df, pws->b[7]); \
2503 pwd->b[8] = msa_ ## func ## _df(df, pws->b[8]); \
2504 pwd->b[9] = msa_ ## func ## _df(df, pws->b[9]); \
2505 pwd->b[10] = msa_ ## func ## _df(df, pws->b[10]); \
2506 pwd->b[11] = msa_ ## func ## _df(df, pws->b[11]); \
2507 pwd->b[12] = msa_ ## func ## _df(df, pws->b[12]); \
2508 pwd->b[13] = msa_ ## func ## _df(df, pws->b[13]); \
2509 pwd->b[14] = msa_ ## func ## _df(df, pws->b[14]); \
2510 pwd->b[15] = msa_ ## func ## _df(df, pws->b[15]); \
2511 break; \
2512 case DF_HALF: \
2513 pwd->h[0] = msa_ ## func ## _df(df, pws->h[0]); \
2514 pwd->h[1] = msa_ ## func ## _df(df, pws->h[1]); \
2515 pwd->h[2] = msa_ ## func ## _df(df, pws->h[2]); \
2516 pwd->h[3] = msa_ ## func ## _df(df, pws->h[3]); \
2517 pwd->h[4] = msa_ ## func ## _df(df, pws->h[4]); \
2518 pwd->h[5] = msa_ ## func ## _df(df, pws->h[5]); \
2519 pwd->h[6] = msa_ ## func ## _df(df, pws->h[6]); \
2520 pwd->h[7] = msa_ ## func ## _df(df, pws->h[7]); \
2521 break; \
2522 case DF_WORD: \
2523 pwd->w[0] = msa_ ## func ## _df(df, pws->w[0]); \
2524 pwd->w[1] = msa_ ## func ## _df(df, pws->w[1]); \
2525 pwd->w[2] = msa_ ## func ## _df(df, pws->w[2]); \
2526 pwd->w[3] = msa_ ## func ## _df(df, pws->w[3]); \
2527 break; \
2528 case DF_DOUBLE: \
2529 pwd->d[0] = msa_ ## func ## _df(df, pws->d[0]); \
2530 pwd->d[1] = msa_ ## func ## _df(df, pws->d[1]); \
2531 break; \
2532 default: \
2533 assert(0); \
2534 } \
2535 }
2536
2537 MSA_UNOP_DF(nlzc)
2538 MSA_UNOP_DF(nloc)
2539 MSA_UNOP_DF(pcnt)
2540 #undef MSA_UNOP_DF
2541
2542 #define FLOAT_ONE32 make_float32(0x3f8 << 20)
2543 #define FLOAT_ONE64 make_float64(0x3ffULL << 52)
2544
2545 #define FLOAT_SNAN16(s) (float16_default_nan(s) ^ 0x0220)
2546 /* 0x7c20 */
2547 #define FLOAT_SNAN32(s) (float32_default_nan(s) ^ 0x00400020)
2548 /* 0x7f800020 */
2549 #define FLOAT_SNAN64(s) (float64_default_nan(s) ^ 0x0008000000000020ULL)
2550 /* 0x7ff0000000000020 */
2551
2552 static inline void clear_msacsr_cause(CPUMIPSState *env)
2553 {
2554 SET_FP_CAUSE(env->active_tc.msacsr, 0);
2555 }
2556
2557 static inline void check_msacsr_cause(CPUMIPSState *env, uintptr_t retaddr)
2558 {
2559 if ((GET_FP_CAUSE(env->active_tc.msacsr) &
2560 (GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED)) == 0) {
2561 UPDATE_FP_FLAGS(env->active_tc.msacsr,
2562 GET_FP_CAUSE(env->active_tc.msacsr));
2563 } else {
2564 do_raise_exception(env, EXCP_MSAFPE, retaddr);
2565 }
2566 }
2567
2568 /* Flush-to-zero use cases for update_msacsr() */
2569 #define CLEAR_FS_UNDERFLOW 1
2570 #define CLEAR_IS_INEXACT 2
2571 #define RECIPROCAL_INEXACT 4
2572
2573 static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
2574 {
2575 int ieee_ex;
2576
2577 int c;
2578 int cause;
2579 int enable;
2580
2581 ieee_ex = get_float_exception_flags(&env->active_tc.msa_fp_status);
2582
2583 /* QEMU softfloat does not signal all underflow cases */
2584 if (denormal) {
2585 ieee_ex |= float_flag_underflow;
2586 }
2587
2588 c = ieee_ex_to_mips(ieee_ex);
2589 enable = GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED;
2590
2591 /* Set Inexact (I) when flushing inputs to zero */
2592 if ((ieee_ex & float_flag_input_denormal) &&
2593 (env->active_tc.msacsr & MSACSR_FS_MASK) != 0) {
2594 if (action & CLEAR_IS_INEXACT) {
2595 c &= ~FP_INEXACT;
2596 } else {
2597 c |= FP_INEXACT;
2598 }
2599 }
2600
2601 /* Set Inexact (I) and Underflow (U) when flushing outputs to zero */
2602 if ((ieee_ex & float_flag_output_denormal) &&
2603 (env->active_tc.msacsr & MSACSR_FS_MASK) != 0) {
2604 c |= FP_INEXACT;
2605 if (action & CLEAR_FS_UNDERFLOW) {
2606 c &= ~FP_UNDERFLOW;
2607 } else {
2608 c |= FP_UNDERFLOW;
2609 }
2610 }
2611
2612 /* Set Inexact (I) when Overflow (O) is not enabled */
2613 if ((c & FP_OVERFLOW) != 0 && (enable & FP_OVERFLOW) == 0) {
2614 c |= FP_INEXACT;
2615 }
2616
2617 /* Clear Exact Underflow when Underflow (U) is not enabled */
2618 if ((c & FP_UNDERFLOW) != 0 && (enable & FP_UNDERFLOW) == 0 &&
2619 (c & FP_INEXACT) == 0) {
2620 c &= ~FP_UNDERFLOW;
2621 }
2622
2623 /*
2624 * Reciprocal operations set only Inexact when valid and not
2625 * divide by zero
2626 */
2627 if ((action & RECIPROCAL_INEXACT) &&
2628 (c & (FP_INVALID | FP_DIV0)) == 0) {
2629 c = FP_INEXACT;
2630 }
2631
2632 cause = c & enable; /* all current enabled exceptions */
2633
2634 if (cause == 0) {
2635 /*
2636 * No enabled exception, update the MSACSR Cause
2637 * with all current exceptions
2638 */
2639 SET_FP_CAUSE(env->active_tc.msacsr,
2640 (GET_FP_CAUSE(env->active_tc.msacsr) | c));
2641 } else {
2642 /* Current exceptions are enabled */
2643 if ((env->active_tc.msacsr & MSACSR_NX_MASK) == 0) {
2644 /*
2645 * Exception(s) will trap, update MSACSR Cause
2646 * with all enabled exceptions
2647 */
2648 SET_FP_CAUSE(env->active_tc.msacsr,
2649 (GET_FP_CAUSE(env->active_tc.msacsr) | c));
2650 }
2651 }
2652
2653 return c;
2654 }
2655
2656 static inline int get_enabled_exceptions(const CPUMIPSState *env, int c)
2657 {
2658 int enable = GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED;
2659 return c & enable;
2660 }
2661
2662 static inline float16 float16_from_float32(int32_t a, flag ieee,
2663 float_status *status)
2664 {
2665 float16 f_val;
2666
2667 f_val = float32_to_float16((float32)a, ieee, status);
2668
2669 return a < 0 ? (f_val | (1 << 15)) : f_val;
2670 }
2671
2672 static inline float32 float32_from_float64(int64_t a, float_status *status)
2673 {
2674 float32 f_val;
2675
2676 f_val = float64_to_float32((float64)a, status);
2677
2678 return a < 0 ? (f_val | (1 << 31)) : f_val;
2679 }
2680
2681 static inline float32 float32_from_float16(int16_t a, flag ieee,
2682 float_status *status)
2683 {
2684 float32 f_val;
2685
2686 f_val = float16_to_float32((float16)a, ieee, status);
2687
2688 return a < 0 ? (f_val | (1 << 31)) : f_val;
2689 }
2690
2691 static inline float64 float64_from_float32(int32_t a, float_status *status)
2692 {
2693 float64 f_val;
2694
2695 f_val = float32_to_float64((float64)a, status);
2696
2697 return a < 0 ? (f_val | (1ULL << 63)) : f_val;
2698 }
2699
2700 static inline float32 float32_from_q16(int16_t a, float_status *status)
2701 {
2702 float32 f_val;
2703
2704 /* conversion as integer and scaling */
2705 f_val = int32_to_float32(a, status);
2706 f_val = float32_scalbn(f_val, -15, status);
2707
2708 return f_val;
2709 }
2710
2711 static inline float64 float64_from_q32(int32_t a, float_status *status)
2712 {
2713 float64 f_val;
2714
2715 /* conversion as integer and scaling */
2716 f_val = int32_to_float64(a, status);
2717 f_val = float64_scalbn(f_val, -31, status);
2718
2719 return f_val;
2720 }
2721
2722 static inline int16_t float32_to_q16(float32 a, float_status *status)
2723 {
2724 int32_t q_val;
2725 int32_t q_min = 0xffff8000;
2726 int32_t q_max = 0x00007fff;
2727
2728 int ieee_ex;
2729
2730 if (float32_is_any_nan(a)) {
2731 float_raise(float_flag_invalid, status);
2732 return 0;
2733 }
2734
2735 /* scaling */
2736 a = float32_scalbn(a, 15, status);
2737
2738 ieee_ex = get_float_exception_flags(status);
2739 set_float_exception_flags(ieee_ex & (~float_flag_underflow)
2740 , status);
2741
2742 if (ieee_ex & float_flag_overflow) {
2743 float_raise(float_flag_inexact, status);
2744 return (int32_t)a < 0 ? q_min : q_max;
2745 }
2746
2747 /* conversion to int */
2748 q_val = float32_to_int32(a, status);
2749
2750 ieee_ex = get_float_exception_flags(status);
2751 set_float_exception_flags(ieee_ex & (~float_flag_underflow)
2752 , status);
2753
2754 if (ieee_ex & float_flag_invalid) {
2755 set_float_exception_flags(ieee_ex & (~float_flag_invalid)
2756 , status);
2757 float_raise(float_flag_overflow | float_flag_inexact, status);
2758 return (int32_t)a < 0 ? q_min : q_max;
2759 }
2760
2761 if (q_val < q_min) {
2762 float_raise(float_flag_overflow | float_flag_inexact, status);
2763 return (int16_t)q_min;
2764 }
2765
2766 if (q_max < q_val) {
2767 float_raise(float_flag_overflow | float_flag_inexact, status);
2768 return (int16_t)q_max;
2769 }
2770
2771 return (int16_t)q_val;
2772 }
2773
2774 static inline int32_t float64_to_q32(float64 a, float_status *status)
2775 {
2776 int64_t q_val;
2777 int64_t q_min = 0xffffffff80000000LL;
2778 int64_t q_max = 0x000000007fffffffLL;
2779
2780 int ieee_ex;
2781
2782 if (float64_is_any_nan(a)) {
2783 float_raise(float_flag_invalid, status);
2784 return 0;
2785 }
2786
2787 /* scaling */
2788 a = float64_scalbn(a, 31, status);
2789
2790 ieee_ex = get_float_exception_flags(status);
2791 set_float_exception_flags(ieee_ex & (~float_flag_underflow)
2792 , status);
2793
2794 if (ieee_ex & float_flag_overflow) {
2795 float_raise(float_flag_inexact, status);
2796 return (int64_t)a < 0 ? q_min : q_max;
2797 }
2798
2799 /* conversion to integer */
2800 q_val = float64_to_int64(a, status);
2801
2802 ieee_ex = get_float_exception_flags(status);
2803 set_float_exception_flags(ieee_ex & (~float_flag_underflow)
2804 , status);
2805
2806 if (ieee_ex & float_flag_invalid) {
2807 set_float_exception_flags(ieee_ex & (~float_flag_invalid)
2808 , status);
2809 float_raise(float_flag_overflow | float_flag_inexact, status);
2810 return (int64_t)a < 0 ? q_min : q_max;
2811 }
2812
2813 if (q_val < q_min) {
2814 float_raise(float_flag_overflow | float_flag_inexact, status);
2815 return (int32_t)q_min;
2816 }
2817
2818 if (q_max < q_val) {
2819 float_raise(float_flag_overflow | float_flag_inexact, status);
2820 return (int32_t)q_max;
2821 }
2822
2823 return (int32_t)q_val;
2824 }
2825
2826 #define MSA_FLOAT_COND(DEST, OP, ARG1, ARG2, BITS, QUIET) \
2827 do { \
2828 float_status *status = &env->active_tc.msa_fp_status; \
2829 int c; \
2830 int64_t cond; \
2831 set_float_exception_flags(0, status); \
2832 if (!QUIET) { \
2833 cond = float ## BITS ## _ ## OP(ARG1, ARG2, status); \
2834 } else { \
2835 cond = float ## BITS ## _ ## OP ## _quiet(ARG1, ARG2, status); \
2836 } \
2837 DEST = cond ? M_MAX_UINT(BITS) : 0; \
2838 c = update_msacsr(env, CLEAR_IS_INEXACT, 0); \
2839 \
2840 if (get_enabled_exceptions(env, c)) { \
2841 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
2842 } \
2843 } while (0)
2844
2845 #define MSA_FLOAT_AF(DEST, ARG1, ARG2, BITS, QUIET) \
2846 do { \
2847 MSA_FLOAT_COND(DEST, eq, ARG1, ARG2, BITS, QUIET); \
2848 if ((DEST & M_MAX_UINT(BITS)) == M_MAX_UINT(BITS)) { \
2849 DEST = 0; \
2850 } \
2851 } while (0)
2852
2853 #define MSA_FLOAT_UEQ(DEST, ARG1, ARG2, BITS, QUIET) \
2854 do { \
2855 MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET); \
2856 if (DEST == 0) { \
2857 MSA_FLOAT_COND(DEST, eq, ARG1, ARG2, BITS, QUIET); \
2858 } \
2859 } while (0)
2860
2861 #define MSA_FLOAT_NE(DEST, ARG1, ARG2, BITS, QUIET) \
2862 do { \
2863 MSA_FLOAT_COND(DEST, lt, ARG1, ARG2, BITS, QUIET); \
2864 if (DEST == 0) { \
2865 MSA_FLOAT_COND(DEST, lt, ARG2, ARG1, BITS, QUIET); \
2866 } \
2867 } while (0)
2868
2869 #define MSA_FLOAT_UNE(DEST, ARG1, ARG2, BITS, QUIET) \
2870 do { \
2871 MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET); \
2872 if (DEST == 0) { \
2873 MSA_FLOAT_COND(DEST, lt, ARG1, ARG2, BITS, QUIET); \
2874 if (DEST == 0) { \
2875 MSA_FLOAT_COND(DEST, lt, ARG2, ARG1, BITS, QUIET); \
2876 } \
2877 } \
2878 } while (0)
2879
2880 #define MSA_FLOAT_ULE(DEST, ARG1, ARG2, BITS, QUIET) \
2881 do { \
2882 MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET); \
2883 if (DEST == 0) { \
2884 MSA_FLOAT_COND(DEST, le, ARG1, ARG2, BITS, QUIET); \
2885 } \
2886 } while (0)
2887
2888 #define MSA_FLOAT_ULT(DEST, ARG1, ARG2, BITS, QUIET) \
2889 do { \
2890 MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET); \
2891 if (DEST == 0) { \
2892 MSA_FLOAT_COND(DEST, lt, ARG1, ARG2, BITS, QUIET); \
2893 } \
2894 } while (0)
2895
2896 #define MSA_FLOAT_OR(DEST, ARG1, ARG2, BITS, QUIET) \
2897 do { \
2898 MSA_FLOAT_COND(DEST, le, ARG1, ARG2, BITS, QUIET); \
2899 if (DEST == 0) { \
2900 MSA_FLOAT_COND(DEST, le, ARG2, ARG1, BITS, QUIET); \
2901 } \
2902 } while (0)
2903
2904 static inline void compare_af(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
2905 wr_t *pwt, uint32_t df, int quiet,
2906 uintptr_t retaddr)
2907 {
2908 wr_t wx, *pwx = &wx;
2909 uint32_t i;
2910
2911 clear_msacsr_cause(env);
2912
2913 switch (df) {
2914 case DF_WORD:
2915 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
2916 MSA_FLOAT_AF(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
2917 }
2918 break;
2919 case DF_DOUBLE:
2920 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
2921 MSA_FLOAT_AF(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
2922 }
2923 break;
2924 default:
2925 assert(0);
2926 }
2927
2928 check_msacsr_cause(env, retaddr);
2929
2930 msa_move_v(pwd, pwx);
2931 }
2932
2933 static inline void compare_un(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
2934 wr_t *pwt, uint32_t df, int quiet,
2935 uintptr_t retaddr)
2936 {
2937 wr_t wx, *pwx = &wx;
2938 uint32_t i;
2939
2940 clear_msacsr_cause(env);
2941
2942 switch (df) {
2943 case DF_WORD:
2944 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
2945 MSA_FLOAT_COND(pwx->w[i], unordered, pws->w[i], pwt->w[i], 32,
2946 quiet);
2947 }
2948 break;
2949 case DF_DOUBLE:
2950 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
2951 MSA_FLOAT_COND(pwx->d[i], unordered, pws->d[i], pwt->d[i], 64,
2952 quiet);
2953 }
2954 break;
2955 default:
2956 assert(0);
2957 }
2958
2959 check_msacsr_cause(env, retaddr);
2960
2961 msa_move_v(pwd, pwx);
2962 }
2963
2964 static inline void compare_eq(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
2965 wr_t *pwt, uint32_t df, int quiet,
2966 uintptr_t retaddr)
2967 {
2968 wr_t wx, *pwx = &wx;
2969 uint32_t i;
2970
2971 clear_msacsr_cause(env);
2972
2973 switch (df) {
2974 case DF_WORD:
2975 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
2976 MSA_FLOAT_COND(pwx->w[i], eq, pws->w[i], pwt->w[i], 32, quiet);
2977 }
2978 break;
2979 case DF_DOUBLE:
2980 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
2981 MSA_FLOAT_COND(pwx->d[i], eq, pws->d[i], pwt->d[i], 64, quiet);
2982 }
2983 break;
2984 default:
2985 assert(0);
2986 }
2987
2988 check_msacsr_cause(env, retaddr);
2989
2990 msa_move_v(pwd, pwx);
2991 }
2992
2993 static inline void compare_ueq(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
2994 wr_t *pwt, uint32_t df, int quiet,
2995 uintptr_t retaddr)
2996 {
2997 wr_t wx, *pwx = &wx;
2998 uint32_t i;
2999
3000 clear_msacsr_cause(env);
3001
3002 switch (df) {
3003 case DF_WORD:
3004 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3005 MSA_FLOAT_UEQ(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
3006 }
3007 break;
3008 case DF_DOUBLE:
3009 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3010 MSA_FLOAT_UEQ(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
3011 }
3012 break;
3013 default:
3014 assert(0);
3015 }
3016
3017 check_msacsr_cause(env, retaddr);
3018
3019 msa_move_v(pwd, pwx);
3020 }
3021
3022 static inline void compare_lt(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
3023 wr_t *pwt, uint32_t df, int quiet,
3024 uintptr_t retaddr)
3025 {
3026 wr_t wx, *pwx = &wx;
3027 uint32_t i;
3028
3029 clear_msacsr_cause(env);
3030
3031 switch (df) {
3032 case DF_WORD:
3033 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3034 MSA_FLOAT_COND(pwx->w[i], lt, pws->w[i], pwt->w[i], 32, quiet);
3035 }
3036 break;
3037 case DF_DOUBLE:
3038 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3039 MSA_FLOAT_COND(pwx->d[i], lt, pws->d[i], pwt->d[i], 64, quiet);
3040 }
3041 break;
3042 default:
3043 assert(0);
3044 }
3045
3046 check_msacsr_cause(env, retaddr);
3047
3048 msa_move_v(pwd, pwx);
3049 }
3050
3051 static inline void compare_ult(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
3052 wr_t *pwt, uint32_t df, int quiet,
3053 uintptr_t retaddr)
3054 {
3055 wr_t wx, *pwx = &wx;
3056 uint32_t i;
3057
3058 clear_msacsr_cause(env);
3059
3060 switch (df) {
3061 case DF_WORD:
3062 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3063 MSA_FLOAT_ULT(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
3064 }
3065 break;
3066 case DF_DOUBLE:
3067 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3068 MSA_FLOAT_ULT(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
3069 }
3070 break;
3071 default:
3072 assert(0);
3073 }
3074
3075 check_msacsr_cause(env, retaddr);
3076
3077 msa_move_v(pwd, pwx);
3078 }
3079
3080 static inline void compare_le(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
3081 wr_t *pwt, uint32_t df, int quiet,
3082 uintptr_t retaddr)
3083 {
3084 wr_t wx, *pwx = &wx;
3085 uint32_t i;
3086
3087 clear_msacsr_cause(env);
3088
3089 switch (df) {
3090 case DF_WORD:
3091 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3092 MSA_FLOAT_COND(pwx->w[i], le, pws->w[i], pwt->w[i], 32, quiet);
3093 }
3094 break;
3095 case DF_DOUBLE:
3096 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3097 MSA_FLOAT_COND(pwx->d[i], le, pws->d[i], pwt->d[i], 64, quiet);
3098 }
3099 break;
3100 default:
3101 assert(0);
3102 }
3103
3104 check_msacsr_cause(env, retaddr);
3105
3106 msa_move_v(pwd, pwx);
3107 }
3108
3109 static inline void compare_ule(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
3110 wr_t *pwt, uint32_t df, int quiet,
3111 uintptr_t retaddr)
3112 {
3113 wr_t wx, *pwx = &wx;
3114 uint32_t i;
3115
3116 clear_msacsr_cause(env);
3117
3118 switch (df) {
3119 case DF_WORD:
3120 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3121 MSA_FLOAT_ULE(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
3122 }
3123 break;
3124 case DF_DOUBLE:
3125 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3126 MSA_FLOAT_ULE(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
3127 }
3128 break;
3129 default:
3130 assert(0);
3131 }
3132
3133 check_msacsr_cause(env, retaddr);
3134
3135 msa_move_v(pwd, pwx);
3136 }
3137
3138 static inline void compare_or(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
3139 wr_t *pwt, uint32_t df, int quiet,
3140 uintptr_t retaddr)
3141 {
3142 wr_t wx, *pwx = &wx;
3143 uint32_t i;
3144
3145 clear_msacsr_cause(env);
3146
3147 switch (df) {
3148 case DF_WORD:
3149 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3150 MSA_FLOAT_OR(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
3151 }
3152 break;
3153 case DF_DOUBLE:
3154 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3155 MSA_FLOAT_OR(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
3156 }
3157 break;
3158 default:
3159 assert(0);
3160 }
3161
3162 check_msacsr_cause(env, retaddr);
3163
3164 msa_move_v(pwd, pwx);
3165 }
3166
3167 static inline void compare_une(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
3168 wr_t *pwt, uint32_t df, int quiet,
3169 uintptr_t retaddr)
3170 {
3171 wr_t wx, *pwx = &wx;
3172 uint32_t i;
3173
3174 clear_msacsr_cause(env);
3175
3176 switch (df) {
3177 case DF_WORD:
3178 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3179 MSA_FLOAT_UNE(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
3180 }
3181 break;
3182 case DF_DOUBLE:
3183 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3184 MSA_FLOAT_UNE(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
3185 }
3186 break;
3187 default:
3188 assert(0);
3189 }
3190
3191 check_msacsr_cause(env, retaddr);
3192
3193 msa_move_v(pwd, pwx);
3194 }
3195
3196 static inline void compare_ne(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
3197 wr_t *pwt, uint32_t df, int quiet,
3198 uintptr_t retaddr)
3199 {
3200 wr_t wx, *pwx = &wx;
3201 uint32_t i;
3202
3203 clear_msacsr_cause(env);
3204
3205 switch (df) {
3206 case DF_WORD:
3207 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3208 MSA_FLOAT_NE(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
3209 }
3210 break;
3211 case DF_DOUBLE:
3212 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3213 MSA_FLOAT_NE(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
3214 }
3215 break;
3216 default:
3217 assert(0);
3218 }
3219
3220 check_msacsr_cause(env, retaddr);
3221
3222 msa_move_v(pwd, pwx);
3223 }
3224
3225 void helper_msa_fcaf_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3226 uint32_t ws, uint32_t wt)
3227 {
3228 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3229 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3230 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3231 compare_af(env, pwd, pws, pwt, df, 1, GETPC());
3232 }
3233
3234 void helper_msa_fcun_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3235 uint32_t ws, uint32_t wt)
3236 {
3237 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3238 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3239 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3240 compare_un(env, pwd, pws, pwt, df, 1, GETPC());
3241 }
3242
3243 void helper_msa_fceq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3244 uint32_t ws, uint32_t wt)
3245 {
3246 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3247 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3248 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3249 compare_eq(env, pwd, pws, pwt, df, 1, GETPC());
3250 }
3251
3252 void helper_msa_fcueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3253 uint32_t ws, uint32_t wt)
3254 {
3255 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3256 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3257 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3258 compare_ueq(env, pwd, pws, pwt, df, 1, GETPC());
3259 }
3260
3261 void helper_msa_fclt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3262 uint32_t ws, uint32_t wt)
3263 {
3264 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3265 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3266 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3267 compare_lt(env, pwd, pws, pwt, df, 1, GETPC());
3268 }
3269
3270 void helper_msa_fcult_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3271 uint32_t ws, uint32_t wt)
3272 {
3273 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3274 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3275 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3276 compare_ult(env, pwd, pws, pwt, df, 1, GETPC());
3277 }
3278
3279 void helper_msa_fcle_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3280 uint32_t ws, uint32_t wt)
3281 {
3282 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3283 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3284 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3285 compare_le(env, pwd, pws, pwt, df, 1, GETPC());
3286 }
3287
3288 void helper_msa_fcule_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3289 uint32_t ws, uint32_t wt)
3290 {
3291 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3292 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3293 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3294 compare_ule(env, pwd, pws, pwt, df, 1, GETPC());
3295 }
3296
3297 void helper_msa_fsaf_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3298 uint32_t ws, uint32_t wt)
3299 {
3300 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3301 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3302 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3303 compare_af(env, pwd, pws, pwt, df, 0, GETPC());
3304 }
3305
3306 void helper_msa_fsun_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3307 uint32_t ws, uint32_t wt)
3308 {
3309 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3310 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3311 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3312 compare_un(env, pwd, pws, pwt, df, 0, GETPC());
3313 }
3314
3315 void helper_msa_fseq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3316 uint32_t ws, uint32_t wt)
3317 {
3318 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3319 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3320 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3321 compare_eq(env, pwd, pws, pwt, df, 0, GETPC());
3322 }
3323
3324 void helper_msa_fsueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3325 uint32_t ws, uint32_t wt)
3326 {
3327 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3328 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3329 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3330 compare_ueq(env, pwd, pws, pwt, df, 0, GETPC());
3331 }
3332
3333 void helper_msa_fslt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3334 uint32_t ws, uint32_t wt)
3335 {
3336 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3337 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3338 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3339 compare_lt(env, pwd, pws, pwt, df, 0, GETPC());
3340 }
3341
3342 void helper_msa_fsult_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3343 uint32_t ws, uint32_t wt)
3344 {
3345 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3346 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3347 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3348 compare_ult(env, pwd, pws, pwt, df, 0, GETPC());
3349 }
3350
3351 void helper_msa_fsle_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3352 uint32_t ws, uint32_t wt)
3353 {
3354 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3355 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3356 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3357 compare_le(env, pwd, pws, pwt, df, 0, GETPC());
3358 }
3359
3360 void helper_msa_fsule_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3361 uint32_t ws, uint32_t wt)
3362 {
3363 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3364 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3365 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3366 compare_ule(env, pwd, pws, pwt, df, 0, GETPC());
3367 }
3368
3369 void helper_msa_fcor_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3370 uint32_t ws, uint32_t wt)
3371 {
3372 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3373 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3374 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3375 compare_or(env, pwd, pws, pwt, df, 1, GETPC());
3376 }
3377
3378 void helper_msa_fcune_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3379 uint32_t ws, uint32_t wt)
3380 {
3381 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3382 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3383 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3384 compare_une(env, pwd, pws, pwt, df, 1, GETPC());
3385 }
3386
3387 void helper_msa_fcne_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3388 uint32_t ws, uint32_t wt)
3389 {
3390 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3391 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3392 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3393 compare_ne(env, pwd, pws, pwt, df, 1, GETPC());
3394 }
3395
3396 void helper_msa_fsor_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3397 uint32_t ws, uint32_t wt)
3398 {
3399 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3400 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3401 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3402 compare_or(env, pwd, pws, pwt, df, 0, GETPC());
3403 }
3404
3405 void helper_msa_fsune_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3406 uint32_t ws, uint32_t wt)
3407 {
3408 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3409 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3410 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3411 compare_une(env, pwd, pws, pwt, df, 0, GETPC());
3412 }
3413
3414 void helper_msa_fsne_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3415 uint32_t ws, uint32_t wt)
3416 {
3417 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3418 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3419 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3420 compare_ne(env, pwd, pws, pwt, df, 0, GETPC());
3421 }
3422
3423 #define float16_is_zero(ARG) 0
3424 #define float16_is_zero_or_denormal(ARG) 0
3425
3426 #define IS_DENORMAL(ARG, BITS) \
3427 (!float ## BITS ## _is_zero(ARG) \
3428 && float ## BITS ## _is_zero_or_denormal(ARG))
3429
3430 #define MSA_FLOAT_BINOP(DEST, OP, ARG1, ARG2, BITS) \
3431 do { \
3432 float_status *status = &env->active_tc.msa_fp_status; \
3433 int c; \
3434 \
3435 set_float_exception_flags(0, status); \
3436 DEST = float ## BITS ## _ ## OP(ARG1, ARG2, status); \
3437 c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
3438 \
3439 if (get_enabled_exceptions(env, c)) { \
3440 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
3441 } \
3442 } while (0)
3443
3444 void helper_msa_fadd_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3445 uint32_t ws, uint32_t wt)
3446 {
3447 wr_t wx, *pwx = &wx;
3448 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3449 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3450 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3451 uint32_t i;
3452
3453 clear_msacsr_cause(env);
3454
3455 switch (df) {
3456 case DF_WORD:
3457 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3458 MSA_FLOAT_BINOP(pwx->w[i], add, pws->w[i], pwt->w[i], 32);
3459 }
3460 break;
3461 case DF_DOUBLE:
3462 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3463 MSA_FLOAT_BINOP(pwx->d[i], add, pws->d[i], pwt->d[i], 64);
3464 }
3465 break;
3466 default:
3467 assert(0);
3468 }
3469
3470 check_msacsr_cause(env, GETPC());
3471 msa_move_v(pwd, pwx);
3472 }
3473
3474 void helper_msa_fsub_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3475 uint32_t ws, uint32_t wt)
3476 {
3477 wr_t wx, *pwx = &wx;
3478 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3479 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3480 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3481 uint32_t i;
3482
3483 clear_msacsr_cause(env);
3484
3485 switch (df) {
3486 case DF_WORD:
3487 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3488 MSA_FLOAT_BINOP(pwx->w[i], sub, pws->w[i], pwt->w[i], 32);
3489 }
3490 break;
3491 case DF_DOUBLE:
3492 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3493 MSA_FLOAT_BINOP(pwx->d[i], sub, pws->d[i], pwt->d[i], 64);
3494 }
3495 break;
3496 default:
3497 assert(0);
3498 }
3499
3500 check_msacsr_cause(env, GETPC());
3501 msa_move_v(pwd, pwx);
3502 }
3503
3504 void helper_msa_fmul_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3505 uint32_t ws, uint32_t wt)
3506 {
3507 wr_t wx, *pwx = &wx;
3508 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3509 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3510 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3511 uint32_t i;
3512
3513 clear_msacsr_cause(env);
3514
3515 switch (df) {
3516 case DF_WORD:
3517 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3518 MSA_FLOAT_BINOP(pwx->w[i], mul, pws->w[i], pwt->w[i], 32);
3519 }
3520 break;
3521 case DF_DOUBLE:
3522 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3523 MSA_FLOAT_BINOP(pwx->d[i], mul, pws->d[i], pwt->d[i], 64);
3524 }
3525 break;
3526 default:
3527 assert(0);
3528 }
3529
3530 check_msacsr_cause(env, GETPC());
3531
3532 msa_move_v(pwd, pwx);
3533 }
3534
3535 void helper_msa_fdiv_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3536 uint32_t ws, uint32_t wt)
3537 {
3538 wr_t wx, *pwx = &wx;
3539 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3540 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3541 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3542 uint32_t i;
3543
3544 clear_msacsr_cause(env);
3545
3546 switch (df) {
3547 case DF_WORD:
3548 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3549 MSA_FLOAT_BINOP(pwx->w[i], div, pws->w[i], pwt->w[i], 32);
3550 }
3551 break;
3552 case DF_DOUBLE:
3553 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3554 MSA_FLOAT_BINOP(pwx->d[i], div, pws->d[i], pwt->d[i], 64);
3555 }
3556 break;
3557 default:
3558 assert(0);
3559 }
3560
3561 check_msacsr_cause(env, GETPC());
3562
3563 msa_move_v(pwd, pwx);
3564 }
3565
3566 #define MSA_FLOAT_MULADD(DEST, ARG1, ARG2, ARG3, NEGATE, BITS) \
3567 do { \
3568 float_status *status = &env->active_tc.msa_fp_status; \
3569 int c; \
3570 \
3571 set_float_exception_flags(0, status); \
3572 DEST = float ## BITS ## _muladd(ARG2, ARG3, ARG1, NEGATE, status); \
3573 c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
3574 \
3575 if (get_enabled_exceptions(env, c)) { \
3576 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
3577 } \
3578 } while (0)
3579
3580 void helper_msa_fmadd_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3581 uint32_t ws, uint32_t wt)
3582 {
3583 wr_t wx, *pwx = &wx;
3584 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3585 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3586 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3587 uint32_t i;
3588
3589 clear_msacsr_cause(env);
3590
3591 switch (df) {
3592 case DF_WORD:
3593 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3594 MSA_FLOAT_MULADD(pwx->w[i], pwd->w[i],
3595 pws->w[i], pwt->w[i], 0, 32);
3596 }
3597 break;
3598 case DF_DOUBLE:
3599 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3600 MSA_FLOAT_MULADD(pwx->d[i], pwd->d[i],
3601 pws->d[i], pwt->d[i], 0, 64);
3602 }
3603 break;
3604 default:
3605 assert(0);
3606 }
3607
3608 check_msacsr_cause(env, GETPC());
3609
3610 msa_move_v(pwd, pwx);
3611 }
3612
3613 void helper_msa_fmsub_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3614 uint32_t ws, uint32_t wt)
3615 {
3616 wr_t wx, *pwx = &wx;
3617 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3618 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3619 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3620 uint32_t i;
3621
3622 clear_msacsr_cause(env);
3623
3624 switch (df) {
3625 case DF_WORD:
3626 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3627 MSA_FLOAT_MULADD(pwx->w[i], pwd->w[i],
3628 pws->w[i], pwt->w[i],
3629 float_muladd_negate_product, 32);
3630 }
3631 break;
3632 case DF_DOUBLE:
3633 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3634 MSA_FLOAT_MULADD(pwx->d[i], pwd->d[i],
3635 pws->d[i], pwt->d[i],
3636 float_muladd_negate_product, 64);
3637 }
3638 break;
3639 default:
3640 assert(0);
3641 }
3642
3643 check_msacsr_cause(env, GETPC());
3644
3645 msa_move_v(pwd, pwx);
3646 }
3647
3648 void helper_msa_fexp2_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3649 uint32_t ws, uint32_t wt)
3650 {
3651 wr_t wx, *pwx = &wx;
3652 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3653 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3654 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3655 uint32_t i;
3656
3657 clear_msacsr_cause(env);
3658
3659 switch (df) {
3660 case DF_WORD:
3661 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3662 MSA_FLOAT_BINOP(pwx->w[i], scalbn, pws->w[i],
3663 pwt->w[i] > 0x200 ? 0x200 :
3664 pwt->w[i] < -0x200 ? -0x200 : pwt->w[i],
3665 32);
3666 }
3667 break;
3668 case DF_DOUBLE:
3669 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3670 MSA_FLOAT_BINOP(pwx->d[i], scalbn, pws->d[i],
3671 pwt->d[i] > 0x1000 ? 0x1000 :
3672 pwt->d[i] < -0x1000 ? -0x1000 : pwt->d[i],
3673 64);
3674 }
3675 break;
3676 default:
3677 assert(0);
3678 }
3679
3680 check_msacsr_cause(env, GETPC());
3681
3682 msa_move_v(pwd, pwx);
3683 }
3684
3685 #define MSA_FLOAT_UNOP(DEST, OP, ARG, BITS) \
3686 do { \
3687 float_status *status = &env->active_tc.msa_fp_status; \
3688 int c; \
3689 \
3690 set_float_exception_flags(0, status); \
3691 DEST = float ## BITS ## _ ## OP(ARG, status); \
3692 c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
3693 \
3694 if (get_enabled_exceptions(env, c)) { \
3695 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
3696 } \
3697 } while (0)
3698
3699 void helper_msa_fexdo_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3700 uint32_t ws, uint32_t wt)
3701 {
3702 wr_t wx, *pwx = &wx;
3703 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3704 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3705 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3706 uint32_t i;
3707
3708 clear_msacsr_cause(env);
3709
3710 switch (df) {
3711 case DF_WORD:
3712 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3713 /*
3714 * Half precision floats come in two formats: standard
3715 * IEEE and "ARM" format. The latter gains extra exponent
3716 * range by omitting the NaN/Inf encodings.
3717 */
3718 flag ieee = 1;
3719
3720 MSA_FLOAT_BINOP(Lh(pwx, i), from_float32, pws->w[i], ieee, 16);
3721 MSA_FLOAT_BINOP(Rh(pwx, i), from_float32, pwt->w[i], ieee, 16);
3722 }
3723 break;
3724 case DF_DOUBLE:
3725 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3726 MSA_FLOAT_UNOP(Lw(pwx, i), from_float64, pws->d[i], 32);
3727 MSA_FLOAT_UNOP(Rw(pwx, i), from_float64, pwt->d[i], 32);
3728 }
3729 break;
3730 default:
3731 assert(0);
3732 }
3733
3734 check_msacsr_cause(env, GETPC());
3735 msa_move_v(pwd, pwx);
3736 }
3737
3738 #define MSA_FLOAT_UNOP_XD(DEST, OP, ARG, BITS, XBITS) \
3739 do { \
3740 float_status *status = &env->active_tc.msa_fp_status; \
3741 int c; \
3742 \
3743 set_float_exception_flags(0, status); \
3744 DEST = float ## BITS ## _ ## OP(ARG, status); \
3745 c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \
3746 \
3747 if (get_enabled_exceptions(env, c)) { \
3748 DEST = ((FLOAT_SNAN ## XBITS(status) >> 6) << 6) | c; \
3749 } \
3750 } while (0)
3751
3752 void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3753 uint32_t ws, uint32_t wt)
3754 {
3755 wr_t wx, *pwx = &wx;
3756 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3757 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3758 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3759 uint32_t i;
3760
3761 clear_msacsr_cause(env);
3762
3763 switch (df) {
3764 case DF_WORD:
3765 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3766 MSA_FLOAT_UNOP_XD(Lh(pwx, i), to_q16, pws->w[i], 32, 16);
3767 MSA_FLOAT_UNOP_XD(Rh(pwx, i), to_q16, pwt->w[i], 32, 16);
3768 }
3769 break;
3770 case DF_DOUBLE:
3771 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3772 MSA_FLOAT_UNOP_XD(Lw(pwx, i), to_q32, pws->d[i], 64, 32);
3773 MSA_FLOAT_UNOP_XD(Rw(pwx, i), to_q32, pwt->d[i], 64, 32);
3774 }
3775 break;
3776 default:
3777 assert(0);
3778 }
3779
3780 check_msacsr_cause(env, GETPC());
3781
3782 msa_move_v(pwd, pwx);
3783 }
3784
3785 #define NUMBER_QNAN_PAIR(ARG1, ARG2, BITS, STATUS) \
3786 !float ## BITS ## _is_any_nan(ARG1) \
3787 && float ## BITS ## _is_quiet_nan(ARG2, STATUS)
3788
3789 #define MSA_FLOAT_MAXOP(DEST, OP, ARG1, ARG2, BITS) \
3790 do { \
3791 float_status *status = &env->active_tc.msa_fp_status; \
3792 int c; \
3793 \
3794 set_float_exception_flags(0, status); \
3795 DEST = float ## BITS ## _ ## OP(ARG1, ARG2, status); \
3796 c = update_msacsr(env, 0, 0); \
3797 \
3798 if (get_enabled_exceptions(env, c)) { \
3799 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
3800 } \
3801 } while (0)
3802
3803 #define FMAXMIN_A(F, G, X, _S, _T, BITS, STATUS) \
3804 do { \
3805 uint## BITS ##_t S = _S, T = _T; \
3806 uint## BITS ##_t as, at, xs, xt, xd; \
3807 if (NUMBER_QNAN_PAIR(S, T, BITS, STATUS)) { \
3808 T = S; \
3809 } \
3810 else if (NUMBER_QNAN_PAIR(T, S, BITS, STATUS)) { \
3811 S = T; \
3812 } \
3813 as = float## BITS ##_abs(S); \
3814 at = float## BITS ##_abs(T); \
3815 MSA_FLOAT_MAXOP(xs, F, S, T, BITS); \
3816 MSA_FLOAT_MAXOP(xt, G, S, T, BITS); \
3817 MSA_FLOAT_MAXOP(xd, F, as, at, BITS); \
3818 X = (as == at || xd == float## BITS ##_abs(xs)) ? xs : xt; \
3819 } while (0)
3820
3821 void helper_msa_fmin_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3822 uint32_t ws, uint32_t wt)
3823 {
3824 float_status *status = &env->active_tc.msa_fp_status;
3825 wr_t wx, *pwx = &wx;
3826 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3827 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3828 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3829 uint32_t i;
3830
3831 clear_msacsr_cause(env);
3832
3833 switch (df) {
3834 case DF_WORD:
3835 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3836 if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32, status)) {
3837 MSA_FLOAT_MAXOP(pwx->w[i], min, pws->w[i], pws->w[i], 32);
3838 } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32, status)) {
3839 MSA_FLOAT_MAXOP(pwx->w[i], min, pwt->w[i], pwt->w[i], 32);
3840 } else {
3841 MSA_FLOAT_MAXOP(pwx->w[i], min, pws->w[i], pwt->w[i], 32);
3842 }
3843 }
3844 break;
3845 case DF_DOUBLE:
3846 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3847 if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64, status)) {
3848 MSA_FLOAT_MAXOP(pwx->d[i], min, pws->d[i], pws->d[i], 64);
3849 } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64, status)) {
3850 MSA_FLOAT_MAXOP(pwx->d[i], min, pwt->d[i], pwt->d[i], 64);
3851 } else {
3852 MSA_FLOAT_MAXOP(pwx->d[i], min, pws->d[i], pwt->d[i], 64);
3853 }
3854 }
3855 break;
3856 default:
3857 assert(0);
3858 }
3859
3860 check_msacsr_cause(env, GETPC());
3861
3862 msa_move_v(pwd, pwx);
3863 }
3864
3865 void helper_msa_fmin_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3866 uint32_t ws, uint32_t wt)
3867 {
3868 float_status *status = &env->active_tc.msa_fp_status;
3869 wr_t wx, *pwx = &wx;
3870 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3871 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3872 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3873 uint32_t i;
3874
3875 clear_msacsr_cause(env);
3876
3877 switch (df) {
3878 case DF_WORD:
3879 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3880 FMAXMIN_A(min, max, pwx->w[i], pws->w[i], pwt->w[i], 32, status);
3881 }
3882 break;
3883 case DF_DOUBLE:
3884 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3885 FMAXMIN_A(min, max, pwx->d[i], pws->d[i], pwt->d[i], 64, status);
3886 }
3887 break;
3888 default:
3889 assert(0);
3890 }
3891
3892 check_msacsr_cause(env, GETPC());
3893
3894 msa_move_v(pwd, pwx);
3895 }
3896
3897 void helper_msa_fmax_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3898 uint32_t ws, uint32_t wt)
3899 {
3900 float_status *status = &env->active_tc.msa_fp_status;
3901 wr_t wx, *pwx = &wx;
3902 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3903 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3904 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3905 uint32_t i;
3906
3907 clear_msacsr_cause(env);
3908
3909 switch (df) {
3910 case DF_WORD:
3911 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3912 if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32, status)) {
3913 MSA_FLOAT_MAXOP(pwx->w[i], max, pws->w[i], pws->w[i], 32);
3914 } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32, status)) {
3915 MSA_FLOAT_MAXOP(pwx->w[i], max, pwt->w[i], pwt->w[i], 32);
3916 } else {
3917 MSA_FLOAT_MAXOP(pwx->w[i], max, pws->w[i], pwt->w[i], 32);
3918 }
3919 }
3920 break;
3921 case DF_DOUBLE:
3922 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3923 if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64, status)) {
3924 MSA_FLOAT_MAXOP(pwx->d[i], max, pws->d[i], pws->d[i], 64);
3925 } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64, status)) {
3926 MSA_FLOAT_MAXOP(pwx->d[i], max, pwt->d[i], pwt->d[i], 64);
3927 } else {
3928 MSA_FLOAT_MAXOP(pwx->d[i], max, pws->d[i], pwt->d[i], 64);
3929 }
3930 }
3931 break;
3932 default:
3933 assert(0);
3934 }
3935
3936 check_msacsr_cause(env, GETPC());
3937
3938 msa_move_v(pwd, pwx);
3939 }
3940
3941 void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
3942 uint32_t ws, uint32_t wt)
3943 {
3944 float_status *status = &env->active_tc.msa_fp_status;
3945 wr_t wx, *pwx = &wx;
3946 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3947 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3948 wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3949 uint32_t i;
3950
3951 clear_msacsr_cause(env);
3952
3953 switch (df) {
3954 case DF_WORD:
3955 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
3956 FMAXMIN_A(max, min, pwx->w[i], pws->w[i], pwt->w[i], 32, status);
3957 }
3958 break;
3959 case DF_DOUBLE:
3960 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
3961 FMAXMIN_A(max, min, pwx->d[i], pws->d[i], pwt->d[i], 64, status);
3962 }
3963 break;
3964 default:
3965 assert(0);
3966 }
3967
3968 check_msacsr_cause(env, GETPC());
3969
3970 msa_move_v(pwd, pwx);
3971 }
3972
3973 void helper_msa_fclass_df(CPUMIPSState *env, uint32_t df,
3974 uint32_t wd, uint32_t ws)
3975 {
3976 float_status *status = &env->active_tc.msa_fp_status;
3977
3978 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3979 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3980 if (df == DF_WORD) {
3981 pwd->w[0] = float_class_s(pws->w[0], status);
3982 pwd->w[1] = float_class_s(pws->w[1], status);
3983 pwd->w[2] = float_class_s(pws->w[2], status);
3984 pwd->w[3] = float_class_s(pws->w[3], status);
3985 } else {
3986 pwd->d[0] = float_class_d(pws->d[0], status);
3987 pwd->d[1] = float_class_d(pws->d[1], status);
3988 }
3989 }
3990
3991 #define MSA_FLOAT_UNOP0(DEST, OP, ARG, BITS) \
3992 do { \
3993 float_status *status = &env->active_tc.msa_fp_status; \
3994 int c; \
3995 \
3996 set_float_exception_flags(0, status); \
3997 DEST = float ## BITS ## _ ## OP(ARG, status); \
3998 c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \
3999 \
4000 if (get_enabled_exceptions(env, c)) { \
4001 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
4002 } else if (float ## BITS ## _is_any_nan(ARG)) { \
4003 DEST = 0; \
4004 } \
4005 } while (0)
4006
4007 void helper_msa_ftrunc_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4008 uint32_t ws)
4009 {
4010 wr_t wx, *pwx = &wx;
4011 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4012 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4013 uint32_t i;
4014
4015 clear_msacsr_cause(env);
4016
4017 switch (df) {
4018 case DF_WORD:
4019 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4020 MSA_FLOAT_UNOP0(pwx->w[i], to_int32_round_to_zero, pws->w[i], 32);
4021 }
4022 break;
4023 case DF_DOUBLE:
4024 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4025 MSA_FLOAT_UNOP0(pwx->d[i], to_int64_round_to_zero, pws->d[i], 64);
4026 }
4027 break;
4028 default:
4029 assert(0);
4030 }
4031
4032 check_msacsr_cause(env, GETPC());
4033
4034 msa_move_v(pwd, pwx);
4035 }
4036
4037 void helper_msa_ftrunc_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4038 uint32_t ws)
4039 {
4040 wr_t wx, *pwx = &wx;
4041 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4042 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4043 uint32_t i;
4044
4045 clear_msacsr_cause(env);
4046
4047 switch (df) {
4048 case DF_WORD:
4049 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4050 MSA_FLOAT_UNOP0(pwx->w[i], to_uint32_round_to_zero, pws->w[i], 32);
4051 }
4052 break;
4053 case DF_DOUBLE:
4054 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4055 MSA_FLOAT_UNOP0(pwx->d[i], to_uint64_round_to_zero, pws->d[i], 64);
4056 }
4057 break;
4058 default:
4059 assert(0);
4060 }
4061
4062 check_msacsr_cause(env, GETPC());
4063
4064 msa_move_v(pwd, pwx);
4065 }
4066
4067 void helper_msa_fsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4068 uint32_t ws)
4069 {
4070 wr_t wx, *pwx = &wx;
4071 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4072 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4073 uint32_t i;
4074
4075 clear_msacsr_cause(env);
4076
4077 switch (df) {
4078 case DF_WORD:
4079 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4080 MSA_FLOAT_UNOP(pwx->w[i], sqrt, pws->w[i], 32);
4081 }
4082 break;
4083 case DF_DOUBLE:
4084 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4085 MSA_FLOAT_UNOP(pwx->d[i], sqrt, pws->d[i], 64);
4086 }
4087 break;
4088 default:
4089 assert(0);
4090 }
4091
4092 check_msacsr_cause(env, GETPC());
4093
4094 msa_move_v(pwd, pwx);
4095 }
4096
4097 #define MSA_FLOAT_RECIPROCAL(DEST, ARG, BITS) \
4098 do { \
4099 float_status *status = &env->active_tc.msa_fp_status; \
4100 int c; \
4101 \
4102 set_float_exception_flags(0, status); \
4103 DEST = float ## BITS ## _ ## div(FLOAT_ONE ## BITS, ARG, status); \
4104 c = update_msacsr(env, float ## BITS ## _is_infinity(ARG) || \
4105 float ## BITS ## _is_quiet_nan(DEST, status) ? \
4106 0 : RECIPROCAL_INEXACT, \
4107 IS_DENORMAL(DEST, BITS)); \
4108 \
4109 if (get_enabled_exceptions(env, c)) { \
4110 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
4111 } \
4112 } while (0)
4113
4114 void helper_msa_frsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4115 uint32_t ws)
4116 {
4117 wr_t wx, *pwx = &wx;
4118 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4119 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4120 uint32_t i;
4121
4122 clear_msacsr_cause(env);
4123
4124 switch (df) {
4125 case DF_WORD:
4126 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4127 MSA_FLOAT_RECIPROCAL(pwx->w[i], float32_sqrt(pws->w[i],
4128 &env->active_tc.msa_fp_status), 32);
4129 }
4130 break;
4131 case DF_DOUBLE:
4132 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4133 MSA_FLOAT_RECIPROCAL(pwx->d[i], float64_sqrt(pws->d[i],
4134 &env->active_tc.msa_fp_status), 64);
4135 }
4136 break;
4137 default:
4138 assert(0);
4139 }
4140
4141 check_msacsr_cause(env, GETPC());
4142
4143 msa_move_v(pwd, pwx);
4144 }
4145
4146 void helper_msa_frcp_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4147 uint32_t ws)
4148 {
4149 wr_t wx, *pwx = &wx;
4150 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4151 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4152 uint32_t i;
4153
4154 clear_msacsr_cause(env);
4155
4156 switch (df) {
4157 case DF_WORD:
4158 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4159 MSA_FLOAT_RECIPROCAL(pwx->w[i], pws->w[i], 32);
4160 }
4161 break;
4162 case DF_DOUBLE:
4163 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4164 MSA_FLOAT_RECIPROCAL(pwx->d[i], pws->d[i], 64);
4165 }
4166 break;
4167 default:
4168 assert(0);
4169 }
4170
4171 check_msacsr_cause(env, GETPC());
4172
4173 msa_move_v(pwd, pwx);
4174 }
4175
4176 void helper_msa_frint_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4177 uint32_t ws)
4178 {
4179 wr_t wx, *pwx = &wx;
4180 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4181 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4182 uint32_t i;
4183
4184 clear_msacsr_cause(env);
4185
4186 switch (df) {
4187 case DF_WORD:
4188 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4189 MSA_FLOAT_UNOP(pwx->w[i], round_to_int, pws->w[i], 32);
4190 }
4191 break;
4192 case DF_DOUBLE:
4193 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4194 MSA_FLOAT_UNOP(pwx->d[i], round_to_int, pws->d[i], 64);
4195 }
4196 break;
4197 default:
4198 assert(0);
4199 }
4200
4201 check_msacsr_cause(env, GETPC());
4202
4203 msa_move_v(pwd, pwx);
4204 }
4205
4206 #define MSA_FLOAT_LOGB(DEST, ARG, BITS) \
4207 do { \
4208 float_status *status = &env->active_tc.msa_fp_status; \
4209 int c; \
4210 \
4211 set_float_exception_flags(0, status); \
4212 set_float_rounding_mode(float_round_down, status); \
4213 DEST = float ## BITS ## _ ## log2(ARG, status); \
4214 DEST = float ## BITS ## _ ## round_to_int(DEST, status); \
4215 set_float_rounding_mode(ieee_rm[(env->active_tc.msacsr & \
4216 MSACSR_RM_MASK) >> MSACSR_RM], \
4217 status); \
4218 \
4219 set_float_exception_flags(get_float_exception_flags(status) & \
4220 (~float_flag_inexact), \
4221 status); \
4222 \
4223 c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
4224 \
4225 if (get_enabled_exceptions(env, c)) { \
4226 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
4227 } \
4228 } while (0)
4229
4230 void helper_msa_flog2_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4231 uint32_t ws)
4232 {
4233 wr_t wx, *pwx = &wx;
4234 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4235 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4236 uint32_t i;
4237
4238 clear_msacsr_cause(env);
4239
4240 switch (df) {
4241 case DF_WORD:
4242 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4243 MSA_FLOAT_LOGB(pwx->w[i], pws->w[i], 32);
4244 }
4245 break;
4246 case DF_DOUBLE:
4247 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4248 MSA_FLOAT_LOGB(pwx->d[i], pws->d[i], 64);
4249 }
4250 break;
4251 default:
4252 assert(0);
4253 }
4254
4255 check_msacsr_cause(env, GETPC());
4256
4257 msa_move_v(pwd, pwx);
4258 }
4259
4260 void helper_msa_fexupl_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4261 uint32_t ws)
4262 {
4263 wr_t wx, *pwx = &wx;
4264 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4265 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4266 uint32_t i;
4267
4268 clear_msacsr_cause(env);
4269
4270 switch (df) {
4271 case DF_WORD:
4272 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4273 /*
4274 * Half precision floats come in two formats: standard
4275 * IEEE and "ARM" format. The latter gains extra exponent
4276 * range by omitting the NaN/Inf encodings.
4277 */
4278 flag ieee = 1;
4279
4280 MSA_FLOAT_BINOP(pwx->w[i], from_float16, Lh(pws, i), ieee, 32);
4281 }
4282 break;
4283 case DF_DOUBLE:
4284 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4285 MSA_FLOAT_UNOP(pwx->d[i], from_float32, Lw(pws, i), 64);
4286 }
4287 break;
4288 default:
4289 assert(0);
4290 }
4291
4292 check_msacsr_cause(env, GETPC());
4293 msa_move_v(pwd, pwx);
4294 }
4295
4296 void helper_msa_fexupr_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4297 uint32_t ws)
4298 {
4299 wr_t wx, *pwx = &wx;
4300 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4301 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4302 uint32_t i;
4303
4304 clear_msacsr_cause(env);
4305
4306 switch (df) {
4307 case DF_WORD:
4308 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4309 /*
4310 * Half precision floats come in two formats: standard
4311 * IEEE and "ARM" format. The latter gains extra exponent
4312 * range by omitting the NaN/Inf encodings.
4313 */
4314 flag ieee = 1;
4315
4316 MSA_FLOAT_BINOP(pwx->w[i], from_float16, Rh(pws, i), ieee, 32);
4317 }
4318 break;
4319 case DF_DOUBLE:
4320 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4321 MSA_FLOAT_UNOP(pwx->d[i], from_float32, Rw(pws, i), 64);
4322 }
4323 break;
4324 default:
4325 assert(0);
4326 }
4327
4328 check_msacsr_cause(env, GETPC());
4329 msa_move_v(pwd, pwx);
4330 }
4331
4332 void helper_msa_ffql_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4333 uint32_t ws)
4334 {
4335 wr_t wx, *pwx = &wx;
4336 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4337 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4338 uint32_t i;
4339
4340 switch (df) {
4341 case DF_WORD:
4342 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4343 MSA_FLOAT_UNOP(pwx->w[i], from_q16, Lh(pws, i), 32);
4344 }
4345 break;
4346 case DF_DOUBLE:
4347 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4348 MSA_FLOAT_UNOP(pwx->d[i], from_q32, Lw(pws, i), 64);
4349 }
4350 break;
4351 default:
4352 assert(0);
4353 }
4354
4355 msa_move_v(pwd, pwx);
4356 }
4357
4358 void helper_msa_ffqr_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4359 uint32_t ws)
4360 {
4361 wr_t wx, *pwx = &wx;
4362 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4363 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4364 uint32_t i;
4365
4366 switch (df) {
4367 case DF_WORD:
4368 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4369 MSA_FLOAT_UNOP(pwx->w[i], from_q16, Rh(pws, i), 32);
4370 }
4371 break;
4372 case DF_DOUBLE:
4373 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4374 MSA_FLOAT_UNOP(pwx->d[i], from_q32, Rw(pws, i), 64);
4375 }
4376 break;
4377 default:
4378 assert(0);
4379 }
4380
4381 msa_move_v(pwd, pwx);
4382 }
4383
4384 void helper_msa_ftint_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4385 uint32_t ws)
4386 {
4387 wr_t wx, *pwx = &wx;
4388 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4389 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4390 uint32_t i;
4391
4392 clear_msacsr_cause(env);
4393
4394 switch (df) {
4395 case DF_WORD:
4396 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4397 MSA_FLOAT_UNOP0(pwx->w[i], to_int32, pws->w[i], 32);
4398 }
4399 break;
4400 case DF_DOUBLE:
4401 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4402 MSA_FLOAT_UNOP0(pwx->d[i], to_int64, pws->d[i], 64);
4403 }
4404 break;
4405 default:
4406 assert(0);
4407 }
4408
4409 check_msacsr_cause(env, GETPC());
4410
4411 msa_move_v(pwd, pwx);
4412 }
4413
4414 void helper_msa_ftint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4415 uint32_t ws)
4416 {
4417 wr_t wx, *pwx = &wx;
4418 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4419 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4420 uint32_t i;
4421
4422 clear_msacsr_cause(env);
4423
4424 switch (df) {
4425 case DF_WORD:
4426 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4427 MSA_FLOAT_UNOP0(pwx->w[i], to_uint32, pws->w[i], 32);
4428 }
4429 break;
4430 case DF_DOUBLE:
4431 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4432 MSA_FLOAT_UNOP0(pwx->d[i], to_uint64, pws->d[i], 64);
4433 }
4434 break;
4435 default:
4436 assert(0);
4437 }
4438
4439 check_msacsr_cause(env, GETPC());
4440
4441 msa_move_v(pwd, pwx);
4442 }
4443
4444 #define float32_from_int32 int32_to_float32
4445 #define float32_from_uint32 uint32_to_float32
4446
4447 #define float64_from_int64 int64_to_float64
4448 #define float64_from_uint64 uint64_to_float64
4449
4450 void helper_msa_ffint_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4451 uint32_t ws)
4452 {
4453 wr_t wx, *pwx = &wx;
4454 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4455 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4456 uint32_t i;
4457
4458 clear_msacsr_cause(env);
4459
4460 switch (df) {
4461 case DF_WORD:
4462 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4463 MSA_FLOAT_UNOP(pwx->w[i], from_int32, pws->w[i], 32);
4464 }
4465 break;
4466 case DF_DOUBLE:
4467 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4468 MSA_FLOAT_UNOP(pwx->d[i], from_int64, pws->d[i], 64);
4469 }
4470 break;
4471 default:
4472 assert(0);
4473 }
4474
4475 check_msacsr_cause(env, GETPC());
4476
4477 msa_move_v(pwd, pwx);
4478 }
4479
4480 void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4481 uint32_t ws)
4482 {
4483 wr_t wx, *pwx = &wx;
4484 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4485 wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4486 uint32_t i;
4487
4488 clear_msacsr_cause(env);
4489
4490 switch (df) {
4491 case DF_WORD:
4492 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4493 MSA_FLOAT_UNOP(pwx->w[i], from_uint32, pws->w[i], 32);
4494 }
4495 break;
4496 case DF_DOUBLE:
4497 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4498 MSA_FLOAT_UNOP(pwx->d[i], from_uint64, pws->d[i], 64);
4499 }
4500 break;
4501 default:
4502 assert(0);
4503 }
4504
4505 check_msacsr_cause(env, GETPC());
4506
4507 msa_move_v(pwd, pwx);
4508 }