2 * MIPS SIMD Architecture Module Instruction emulation helpers for QEMU.
4 * Copyright (c) 2014 Imagination Technologies
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.
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.
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/>.
20 #include "qemu/osdep.h"
23 #include "exec/exec-all.h"
24 #include "exec/helper-proto.h"
26 /* Data format min and max values */
27 #define DF_BITS(df) (1 << ((df) + 3))
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)
32 #define DF_MIN_INT(df) (int64_t)(-(1LL << (DF_BITS(df) - 1)))
33 #define M_MIN_INT(m) (int64_t)(-(1LL << ((m) - 1)))
35 #define DF_MAX_UINT(df) (uint64_t)(-1ULL >> (64 - DF_BITS(df)))
36 #define M_MAX_UINT(m) (uint64_t)(-1ULL >> (64 - (m)))
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)))
42 /* Element-by-element access macros */
43 #define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df))
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 * +---------------+----------------------------------------------------------+
67 /* TODO: insert Bit Count group helpers here */
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 * +---------------+----------------------------------------------------------+
89 /* TODO: insert Bit Move group helpers here */
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 * +---------------+----------------------------------------------------------+
112 /* TODO: insert Bit Set group helpers here */
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 * +---------------+----------------------------------------------------------+
135 /* TODO: insert Fixed Multiply group helpers here */
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 * +---------------+----------------------------------------------------------+
154 /* TODO: insert Float Max Min group helpers here */
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 * +---------------+----------------------------------------------------------+
191 /* TODO: insert Int Add group helpers here */
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 * +---------------+----------------------------------------------------------+
218 /* TODO: insert Int Average group helpers here */
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 * +---------------+----------------------------------------------------------+
249 /* TODO: insert Int Compare group helpers here */
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 * +---------------+----------------------------------------------------------+
268 /* TODO: insert Int Divide group helpers here */
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 * +---------------+----------------------------------------------------------+
285 /* TODO: insert Int Dot Product group helpers here */
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 * +---------------+----------------------------------------------------------+
320 /* TODO: insert Int Max Min group helpers here */
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 * +---------------+----------------------------------------------------------+
339 /* TODO: insert Int Modulo group helpers here */
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 * +---------------+----------------------------------------------------------+
362 /* TODO: insert Int Multiply group helpers here */
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 * +---------------+----------------------------------------------------------+
407 /* TODO: insert Int Subtract group helpers here */
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 * +---------------+----------------------------------------------------------+
434 /* TODO: insert Interleave group helpers here */
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 * +---------------+----------------------------------------------------------+
449 /* TODO: insert Logic group helpers here */
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 * +---------------+----------------------------------------------------------+
472 /* TODO: insert Pack group helpers here */
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 * +---------------+----------------------------------------------------------+
503 /* TODO: insert Shift group helpers here */
506 static inline void msa_move_v(wr_t
*pwd
, wr_t
*pws
)
510 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
511 pwd
->d
[i
] = pws
->d
[i
];
515 #define MSA_FN_IMM8(FUNC, DEST, OPERATION) \
516 void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \
519 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
520 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
522 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \
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
)
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
))
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
))
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
))
549 #define SHF_POS(i, imm) (((i) & 0xfc) + (((imm) >> (2 * ((i) & 0x03))) & 0x03))
551 void helper_msa_shf_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
552 uint32_t ws
, uint32_t imm
)
554 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
555 wr_t
*pws
= &(env
->active_fpu
.fpr
[ws
].wr
);
561 for (i
= 0; i
< DF_ELEMENTS(DF_BYTE
); i
++) {
562 pwx
->b
[i
] = pws
->b
[SHF_POS(i
, imm
)];
566 for (i
= 0; i
< DF_ELEMENTS(DF_HALF
); i
++) {
567 pwx
->h
[i
] = pws
->h
[SHF_POS(i
, imm
)];
571 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
572 pwx
->w
[i
] = pws
->w
[SHF_POS(i
, imm
)];
578 msa_move_v(pwd
, pwx
);
581 #define MSA_FN_VECTOR(FUNC, DEST, OPERATION) \
582 void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \
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); \
589 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
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
605 void helper_msa_and_v(CPUMIPSState
*env
, uint32_t wd
, uint32_t ws
, uint32_t wt
)
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
);
611 pwd
->d
[0] = pws
->d
[0] & pwt
->d
[0];
612 pwd
->d
[1] = pws
->d
[1] & pwt
->d
[1];
615 void helper_msa_or_v(CPUMIPSState
*env
, uint32_t wd
, uint32_t ws
, uint32_t wt
)
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
);
621 pwd
->d
[0] = pws
->d
[0] | pwt
->d
[0];
622 pwd
->d
[1] = pws
->d
[1] | pwt
->d
[1];
625 void helper_msa_nor_v(CPUMIPSState
*env
, uint32_t wd
, uint32_t ws
, uint32_t wt
)
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
);
631 pwd
->d
[0] = ~(pws
->d
[0] | pwt
->d
[0]);
632 pwd
->d
[1] = ~(pws
->d
[1] | pwt
->d
[1]);
635 void helper_msa_xor_v(CPUMIPSState
*env
, uint32_t wd
, uint32_t ws
, uint32_t wt
)
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
);
641 pwd
->d
[0] = pws
->d
[0] ^ pwt
->d
[0];
642 pwd
->d
[1] = pws
->d
[1] ^ pwt
->d
[1];
645 static inline int64_t msa_addv_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
650 static inline int64_t msa_subv_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
655 static inline int64_t msa_ceq_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
657 return arg1
== arg2
? -1 : 0;
660 static inline int64_t msa_cle_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
662 return arg1
<= arg2
? -1 : 0;
665 static inline int64_t msa_cle_u_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
667 uint64_t u_arg1
= UNSIGNED(arg1
, df
);
668 uint64_t u_arg2
= UNSIGNED(arg2
, df
);
669 return u_arg1
<= u_arg2
? -1 : 0;
672 static inline int64_t msa_clt_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
674 return arg1
< arg2
? -1 : 0;
677 static inline int64_t msa_clt_u_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
679 uint64_t u_arg1
= UNSIGNED(arg1
, df
);
680 uint64_t u_arg2
= UNSIGNED(arg2
, df
);
681 return u_arg1
< u_arg2
? -1 : 0;
684 static inline int64_t msa_max_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
686 return arg1
> arg2
? arg1
: arg2
;
689 static inline int64_t msa_max_u_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
691 uint64_t u_arg1
= UNSIGNED(arg1
, df
);
692 uint64_t u_arg2
= UNSIGNED(arg2
, df
);
693 return u_arg1
> u_arg2
? arg1
: arg2
;
696 static inline int64_t msa_min_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
698 return arg1
< arg2
? arg1
: arg2
;
701 static inline int64_t msa_min_u_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
703 uint64_t u_arg1
= UNSIGNED(arg1
, df
);
704 uint64_t u_arg2
= UNSIGNED(arg2
, df
);
705 return u_arg1
< u_arg2
? arg1
: arg2
;
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) \
712 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
713 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
718 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \
719 pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], u5); \
723 for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \
724 pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], u5); \
728 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \
729 pwd->w[i] = msa_ ## func ## _df(df, pws->w[i], u5); \
733 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
734 pwd->d[i] = msa_ ## func ## _df(df, pws->d[i], u5); \
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
755 void helper_msa_ldi_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
758 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
763 for (i
= 0; i
< DF_ELEMENTS(DF_BYTE
); i
++) {
764 pwd
->b
[i
] = (int8_t)s10
;
768 for (i
= 0; i
< DF_ELEMENTS(DF_HALF
); i
++) {
769 pwd
->h
[i
] = (int16_t)s10
;
773 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
774 pwd
->w
[i
] = (int32_t)s10
;
778 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
779 pwd
->d
[i
] = (int64_t)s10
;
787 /* Data format bit position and unsigned values */
788 #define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df))
790 static inline int64_t msa_sll_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
792 int32_t b_arg2
= BIT_POSITION(arg2
, df
);
793 return arg1
<< b_arg2
;
796 static inline int64_t msa_sra_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
798 int32_t b_arg2
= BIT_POSITION(arg2
, df
);
799 return arg1
>> b_arg2
;
802 static inline int64_t msa_srl_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
804 uint64_t u_arg1
= UNSIGNED(arg1
, df
);
805 int32_t b_arg2
= BIT_POSITION(arg2
, df
);
806 return u_arg1
>> b_arg2
;
809 static inline int64_t msa_bclr_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
811 int32_t b_arg2
= BIT_POSITION(arg2
, df
);
812 return UNSIGNED(arg1
& (~(1LL << b_arg2
)), df
);
815 static inline int64_t msa_bset_df(uint32_t df
, int64_t arg1
,
818 int32_t b_arg2
= BIT_POSITION(arg2
, df
);
819 return UNSIGNED(arg1
| (1LL << b_arg2
), df
);
822 static inline int64_t msa_bneg_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
824 int32_t b_arg2
= BIT_POSITION(arg2
, df
);
825 return UNSIGNED(arg1
^ (1LL << b_arg2
), df
);
828 static inline int64_t msa_binsl_df(uint32_t df
, int64_t dest
, int64_t arg1
,
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
)) {
838 return UNSIGNED(UNSIGNED(u_dest
<< sh_d
, df
) >> sh_d
, df
) |
839 UNSIGNED(UNSIGNED(u_arg1
>> sh_a
, df
) << sh_a
, df
);
843 static inline int64_t msa_binsr_df(uint32_t df
, int64_t dest
, int64_t arg1
,
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
)) {
853 return UNSIGNED(UNSIGNED(u_dest
>> sh_d
, df
) << sh_d
, df
) |
854 UNSIGNED(UNSIGNED(u_arg1
<< sh_a
, df
) >> sh_a
, df
);
858 static inline int64_t msa_sat_s_df(uint32_t df
, int64_t arg
, uint32_t m
)
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) :
865 static inline int64_t msa_sat_u_df(uint32_t df
, int64_t arg
, uint32_t m
)
867 uint64_t u_arg
= UNSIGNED(arg
, df
);
868 return u_arg
< M_MAX_UINT(m
+ 1) ? u_arg
:
872 static inline int64_t msa_srar_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
874 int32_t b_arg2
= BIT_POSITION(arg2
, df
);
878 int64_t r_bit
= (arg1
>> (b_arg2
- 1)) & 1;
879 return (arg1
>> b_arg2
) + r_bit
;
883 static inline int64_t msa_srlr_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
885 uint64_t u_arg1
= UNSIGNED(arg1
, df
);
886 int32_t b_arg2
= BIT_POSITION(arg2
, df
);
890 uint64_t r_bit
= (u_arg1
>> (b_arg2
- 1)) & 1;
891 return (u_arg1
>> b_arg2
) + r_bit
;
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) \
899 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
900 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
905 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \
906 pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], u5); \
910 for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \
911 pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], u5); \
915 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \
916 pwd->w[i] = msa_ ## func ## _df(df, pws->w[i], u5); \
920 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
921 pwd->d[i] = msa_ ## func ## _df(df, pws->d[i], u5); \
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
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) \
945 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
946 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
951 for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \
952 pwd->b[i] = msa_ ## func ## _df(df, pwd->b[i], pws->b[i], \
957 for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \
958 pwd->h[i] = msa_ ## func ## _df(df, pwd->h[i], pws->h[i], \
963 for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \
964 pwd->w[i] = msa_ ## func ## _df(df, pwd->w[i], pws->w[i], \
969 for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
970 pwd->d[i] = msa_ ## func ## _df(df, pwd->d[i], pws->d[i], \
979 MSA_TEROP_IMMU_DF(binsli
, binsl
)
980 MSA_TEROP_IMMU_DF(binsri
, binsr
)
981 #undef MSA_TEROP_IMMU_DF
983 static inline int64_t msa_max_a_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
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
;
990 static inline int64_t msa_min_a_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
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
;
997 static inline int64_t msa_add_a_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
999 uint64_t abs_arg1
= arg1
>= 0 ? arg1
: -arg1
;
1000 uint64_t abs_arg2
= arg2
>= 0 ? arg2
: -arg2
;
1001 return abs_arg1
+ abs_arg2
;
1004 static inline int64_t msa_adds_a_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
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
;
1012 return (abs_arg1
< max_int
- abs_arg2
) ? abs_arg1
+ abs_arg2
: max_int
;
1016 static inline int64_t msa_adds_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1018 int64_t max_int
= DF_MAX_INT(df
);
1019 int64_t min_int
= DF_MIN_INT(df
);
1021 return (min_int
- arg1
< arg2
) ? arg1
+ arg2
: min_int
;
1023 return (arg2
< max_int
- arg1
) ? arg1
+ arg2
: max_int
;
1027 static inline uint64_t msa_adds_u_df(uint32_t df
, uint64_t arg1
, uint64_t arg2
)
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
;
1035 static inline int64_t msa_ave_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1038 return (arg1
>> 1) + (arg2
>> 1) + (arg1
& arg2
& 1);
1041 static inline uint64_t msa_ave_u_df(uint32_t df
, uint64_t arg1
, uint64_t arg2
)
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);
1049 static inline int64_t msa_aver_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1052 return (arg1
>> 1) + (arg2
>> 1) + ((arg1
| arg2
) & 1);
1055 static inline uint64_t msa_aver_u_df(uint32_t df
, uint64_t arg1
, uint64_t arg2
)
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);
1063 static inline int64_t msa_subs_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1065 int64_t max_int
= DF_MAX_INT(df
);
1066 int64_t min_int
= DF_MIN_INT(df
);
1068 return (min_int
+ arg2
< arg1
) ? arg1
- arg2
: min_int
;
1070 return (arg1
< max_int
+ arg2
) ? arg1
- arg2
: max_int
;
1074 static inline int64_t msa_subs_u_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
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;
1081 static inline int64_t msa_subsus_u_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1083 uint64_t u_arg1
= UNSIGNED(arg1
, df
);
1084 uint64_t max_uint
= DF_MAX_UINT(df
);
1086 uint64_t u_arg2
= (uint64_t)arg2
;
1087 return (u_arg1
> u_arg2
) ?
1088 (int64_t)(u_arg1
- u_arg2
) :
1091 uint64_t u_arg2
= (uint64_t)(-arg2
);
1092 return (u_arg1
< max_uint
- u_arg2
) ?
1093 (int64_t)(u_arg1
+ u_arg2
) :
1098 static inline int64_t msa_subsuu_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
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
) :
1109 return u_arg2
- u_arg1
< (uint64_t)(-min_int
) ?
1110 (int64_t)(u_arg1
- u_arg2
) :
1115 static inline int64_t msa_asub_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1117 /* signed compare */
1118 return (arg1
< arg2
) ?
1119 (uint64_t)(arg2
- arg1
) : (uint64_t)(arg1
- arg2
);
1122 static inline uint64_t msa_asub_u_df(uint32_t df
, uint64_t arg1
, uint64_t arg2
)
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
);
1131 static inline int64_t msa_mulv_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1136 static inline int64_t msa_div_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1138 if (arg1
== DF_MIN_INT(df
) && arg2
== -1) {
1139 return DF_MIN_INT(df
);
1141 return arg2
? arg1
/ arg2
1142 : arg1
>= 0 ? -1 : 1;
1145 static inline int64_t msa_div_u_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1147 uint64_t u_arg1
= UNSIGNED(arg1
, df
);
1148 uint64_t u_arg2
= UNSIGNED(arg2
, df
);
1149 return arg2
? u_arg1
/ u_arg2
: -1;
1152 static inline int64_t msa_mod_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1154 if (arg1
== DF_MIN_INT(df
) && arg2
== -1) {
1157 return arg2
? arg1
% arg2
: arg1
;
1160 static inline int64_t msa_mod_u_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
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
;
1167 #define SIGNED_EVEN(a, df) \
1168 ((((int64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2))
1170 #define UNSIGNED_EVEN(a, df) \
1171 ((((uint64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2))
1173 #define SIGNED_ODD(a, df) \
1174 ((((int64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2))
1176 #define UNSIGNED_ODD(a, df) \
1177 ((((uint64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2))
1179 #define SIGNED_EXTRACT(e, o, a, df) \
1181 e = SIGNED_EVEN(a, df); \
1182 o = SIGNED_ODD(a, df); \
1185 #define UNSIGNED_EXTRACT(e, o, a, df) \
1187 e = UNSIGNED_EVEN(a, df); \
1188 o = UNSIGNED_ODD(a, df); \
1191 static inline int64_t msa_dotp_s_df(uint32_t df
, int64_t arg1
, int64_t 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
);
1202 static inline int64_t msa_dotp_u_df(uint32_t df
, int64_t arg1
, int64_t 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
);
1213 #define CONCATENATE_AND_SLIDE(s, k) \
1215 for (i = 0; i < s; i++) { \
1216 v[i] = pws->b[s * k + i]; \
1217 v[i + s] = pwd->b[s * k + i]; \
1219 for (i = 0; i < s; i++) { \
1220 pwd->b[s * k + i] = v[i + n]; \
1224 static inline void msa_sld_df(uint32_t df
, wr_t
*pwd
,
1225 wr_t
*pws
, target_ulong rt
)
1227 uint32_t n
= rt
% DF_ELEMENTS(df
);
1233 CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_BYTE
), 0);
1236 for (k
= 0; k
< 2; k
++) {
1237 CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_HALF
), k
);
1241 for (k
= 0; k
< 4; k
++) {
1242 CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_WORD
), k
);
1246 for (k
= 0; k
< 8; k
++) {
1247 CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_DOUBLE
), k
);
1255 static inline int64_t msa_hadd_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1257 return SIGNED_ODD(arg1
, df
) + SIGNED_EVEN(arg2
, df
);
1260 static inline int64_t msa_hadd_u_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1262 return UNSIGNED_ODD(arg1
, df
) + UNSIGNED_EVEN(arg2
, df
);
1265 static inline int64_t msa_hsub_s_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1267 return SIGNED_ODD(arg1
, df
) - SIGNED_EVEN(arg2
, df
);
1270 static inline int64_t msa_hsub_u_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1272 return UNSIGNED_ODD(arg1
, df
) - UNSIGNED_EVEN(arg2
, df
);
1275 static inline int64_t msa_mul_q_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
1277 int64_t q_min
= DF_MIN_INT(df
);
1278 int64_t q_max
= DF_MAX_INT(df
);
1280 if (arg1
== q_min
&& arg2
== q_min
) {
1283 return (arg1
* arg2
) >> (DF_BITS(df
) - 1);
1286 static inline int64_t msa_mulr_q_df(uint32_t df
, int64_t arg1
, int64_t arg2
)
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);
1292 if (arg1
== q_min
&& arg2
== q_min
) {
1295 return (arg1
* arg2
+ r_bit
) >> (DF_BITS(df
) - 1);
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) \
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); \
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]); \
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]); \
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]); \
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]); \
1370 MSA_BINOP_DF(adds_a
)
1371 MSA_BINOP_DF(adds_s
)
1372 MSA_BINOP_DF(adds_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
)
1388 MSA_BINOP_DF(dotp_s
)
1389 MSA_BINOP_DF(dotp_u
)
1392 MSA_BINOP_DF(hadd_s
)
1393 MSA_BINOP_DF(hadd_u
)
1394 MSA_BINOP_DF(hsub_s
)
1395 MSA_BINOP_DF(hsub_u
)
1398 MSA_BINOP_DF(mulr_q
)
1401 void helper_msa_sld_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
1402 uint32_t ws
, uint32_t rt
)
1404 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
1405 wr_t
*pws
= &(env
->active_fpu
.fpr
[ws
].wr
);
1407 msa_sld_df(df
, pwd
, pws
, env
->active_tc
.gpr
[rt
]);
1410 static inline int64_t msa_maddv_df(uint32_t df
, int64_t dest
, int64_t arg1
,
1413 return dest
+ arg1
* arg2
;
1416 static inline int64_t msa_msubv_df(uint32_t df
, int64_t dest
, int64_t arg1
,
1419 return dest
- arg1
* arg2
;
1422 static inline int64_t msa_dpadd_s_df(uint32_t df
, int64_t dest
, int64_t arg1
,
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
);
1434 static inline int64_t msa_dpadd_u_df(uint32_t df
, int64_t dest
, int64_t arg1
,
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
);
1446 static inline int64_t msa_dpsub_s_df(uint32_t df
, int64_t dest
, int64_t arg1
,
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
));
1458 static inline int64_t msa_dpsub_u_df(uint32_t df
, int64_t dest
, int64_t arg1
,
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
));
1470 static inline int64_t msa_madd_q_df(uint32_t df
, int64_t dest
, int64_t arg1
,
1473 int64_t q_prod
, q_ret
;
1475 int64_t q_max
= DF_MAX_INT(df
);
1476 int64_t q_min
= DF_MIN_INT(df
);
1478 q_prod
= arg1
* arg2
;
1479 q_ret
= ((dest
<< (DF_BITS(df
) - 1)) + q_prod
) >> (DF_BITS(df
) - 1);
1481 return (q_ret
< q_min
) ? q_min
: (q_max
< q_ret
) ? q_max
: q_ret
;
1484 static inline int64_t msa_msub_q_df(uint32_t df
, int64_t dest
, int64_t arg1
,
1487 int64_t q_prod
, q_ret
;
1489 int64_t q_max
= DF_MAX_INT(df
);
1490 int64_t q_min
= DF_MIN_INT(df
);
1492 q_prod
= arg1
* arg2
;
1493 q_ret
= ((dest
<< (DF_BITS(df
) - 1)) - q_prod
) >> (DF_BITS(df
) - 1);
1495 return (q_ret
< q_min
) ? q_min
: (q_max
< q_ret
) ? q_max
: q_ret
;
1498 static inline int64_t msa_maddr_q_df(uint32_t df
, int64_t dest
, int64_t arg1
,
1501 int64_t q_prod
, q_ret
;
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);
1507 q_prod
= arg1
* arg2
;
1508 q_ret
= ((dest
<< (DF_BITS(df
) - 1)) + q_prod
+ r_bit
) >> (DF_BITS(df
) - 1);
1510 return (q_ret
< q_min
) ? q_min
: (q_max
< q_ret
) ? q_max
: q_ret
;
1513 static inline int64_t msa_msubr_q_df(uint32_t df
, int64_t dest
, int64_t arg1
,
1516 int64_t q_prod
, q_ret
;
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);
1522 q_prod
= arg1
* arg2
;
1523 q_ret
= ((dest
<< (DF_BITS(df
) - 1)) - q_prod
+ r_bit
) >> (DF_BITS(df
) - 1);
1525 return (q_ret
< q_min
) ? q_min
: (q_max
< q_ret
) ? q_max
: q_ret
;
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) \
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); \
1538 pwd->b[0] = msa_ ## func ## _df(df, pwd->b[0], pws->b[0], \
1540 pwd->b[1] = msa_ ## func ## _df(df, pwd->b[1], pws->b[1], \
1542 pwd->b[2] = msa_ ## func ## _df(df, pwd->b[2], pws->b[2], \
1544 pwd->b[3] = msa_ ## func ## _df(df, pwd->b[3], pws->b[3], \
1546 pwd->b[4] = msa_ ## func ## _df(df, pwd->b[4], pws->b[4], \
1548 pwd->b[5] = msa_ ## func ## _df(df, pwd->b[5], pws->b[5], \
1550 pwd->b[6] = msa_ ## func ## _df(df, pwd->b[6], pws->b[6], \
1552 pwd->b[7] = msa_ ## func ## _df(df, pwd->b[7], pws->b[7], \
1554 pwd->b[8] = msa_ ## func ## _df(df, pwd->b[8], pws->b[8], \
1556 pwd->b[9] = msa_ ## func ## _df(df, pwd->b[9], pws->b[9], \
1558 pwd->b[10] = msa_ ## func ## _df(df, pwd->b[10], pws->b[10], \
1560 pwd->b[11] = msa_ ## func ## _df(df, pwd->b[11], pws->b[11], \
1562 pwd->b[12] = msa_ ## func ## _df(df, pwd->b[12], pws->b[12], \
1564 pwd->b[13] = msa_ ## func ## _df(df, pwd->b[13], pws->b[13], \
1566 pwd->b[14] = msa_ ## func ## _df(df, pwd->b[14], pws->b[14], \
1568 pwd->b[15] = msa_ ## func ## _df(df, pwd->b[15], pws->b[15], \
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]); \
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]); \
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]); \
1598 MSA_TEROP_DF(dpadd_s
)
1599 MSA_TEROP_DF(dpadd_u
)
1600 MSA_TEROP_DF(dpsub_s
)
1601 MSA_TEROP_DF(dpsub_u
)
1604 MSA_TEROP_DF(madd_q
)
1605 MSA_TEROP_DF(msub_q
)
1606 MSA_TEROP_DF(maddr_q
)
1607 MSA_TEROP_DF(msubr_q
)
1610 static inline void msa_splat_df(uint32_t df
, wr_t
*pwd
,
1611 wr_t
*pws
, target_ulong rt
)
1613 uint32_t n
= rt
% DF_ELEMENTS(df
);
1618 for (i
= 0; i
< DF_ELEMENTS(DF_BYTE
); i
++) {
1619 pwd
->b
[i
] = pws
->b
[n
];
1623 for (i
= 0; i
< DF_ELEMENTS(DF_HALF
); i
++) {
1624 pwd
->h
[i
] = pws
->h
[n
];
1628 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
1629 pwd
->w
[i
] = pws
->w
[n
];
1633 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
1634 pwd
->d
[i
] = pws
->d
[n
];
1642 void helper_msa_splat_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
1643 uint32_t ws
, uint32_t rt
)
1645 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
1646 wr_t
*pws
= &(env
->active_fpu
.fpr
[ws
].wr
);
1648 msa_splat_df(df
, pwd
, pws
, env
->active_tc
.gpr
[rt
]);
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)
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)
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)
1666 #define MSA_LOOP(DF) \
1668 for (i = 0; i < (MSA_LOOP_COND_ ## DF) ; i++) { \
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) \
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; \
1698 msa_move_v(pwd, pwx); \
1701 #define MSA_LOOP_COND(DF) \
1702 (DF_ELEMENTS(DF) / 2)
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])
1713 #undef MSA_LOOP_COND
1715 #define MSA_LOOP_COND(DF) \
1718 #define MSA_DO(DF) \
1720 uint32_t n = DF_ELEMENTS(df); \
1721 uint32_t k = (pwd->DF[i] & 0x3f) % (2 * n); \
1723 (pwd->DF[i] & 0xc0) ? 0 : k < n ? pwt->DF[k] : pws->DF[k - n]; \
1727 #undef MSA_LOOP_COND
1731 void helper_msa_ilvev_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
1732 uint32_t ws
, uint32_t wt
)
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
);
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];
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];
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];
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];
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];
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];
1811 pwd
->d
[1] = pws
->d
[0];
1812 pwd
->d
[0] = pwt
->d
[0];
1819 void helper_msa_ilvod_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
1820 uint32_t ws
, uint32_t wt
)
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
);
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];
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];
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];
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];
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];
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];
1899 pwd
->d
[0] = pwt
->d
[1];
1900 pwd
->d
[1] = pws
->d
[1];
1907 void helper_msa_ilvl_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
1908 uint32_t ws
, uint32_t wt
)
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
);
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];
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];
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];
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];
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];
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];
1987 pwd
->d
[0] = pwt
->d
[1];
1988 pwd
->d
[1] = pws
->d
[1];
1995 void helper_msa_ilvr_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
1996 uint32_t ws
, uint32_t wt
)
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
);
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];
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];
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];
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];
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];
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];
2075 pwd
->d
[1] = pws
->d
[0];
2076 pwd
->d
[0] = pwt
->d
[0];
2083 void helper_msa_pckev_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
2084 uint32_t ws
, uint32_t wt
)
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
);
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];
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];
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];
2126 pwd
->d
[1] = pws
->d
[0];
2127 pwd
->d
[0] = pwt
->d
[0];
2134 void helper_msa_pckod_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
2135 uint32_t ws
, uint32_t wt
)
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
);
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];
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];
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];
2177 pwd
->d
[0] = pwt
->d
[1];
2178 pwd
->d
[1] = pws
->d
[1];
2186 void helper_msa_sldi_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
2187 uint32_t ws
, uint32_t n
)
2189 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
2190 wr_t
*pws
= &(env
->active_fpu
.fpr
[ws
].wr
);
2192 msa_sld_df(df
, pwd
, pws
, n
);
2195 void helper_msa_splati_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
2196 uint32_t ws
, uint32_t n
)
2198 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
2199 wr_t
*pws
= &(env
->active_fpu
.fpr
[ws
].wr
);
2201 msa_splat_df(df
, pwd
, pws
, n
);
2204 void helper_msa_copy_s_b(CPUMIPSState
*env
, uint32_t rd
,
2205 uint32_t ws
, uint32_t n
)
2208 #if defined(HOST_WORDS_BIGENDIAN)
2215 env
->active_tc
.gpr
[rd
] = (int8_t)env
->active_fpu
.fpr
[ws
].wr
.b
[n
];
2218 void helper_msa_copy_s_h(CPUMIPSState
*env
, uint32_t rd
,
2219 uint32_t ws
, uint32_t n
)
2222 #if defined(HOST_WORDS_BIGENDIAN)
2229 env
->active_tc
.gpr
[rd
] = (int16_t)env
->active_fpu
.fpr
[ws
].wr
.h
[n
];
2232 void helper_msa_copy_s_w(CPUMIPSState
*env
, uint32_t rd
,
2233 uint32_t ws
, uint32_t n
)
2236 #if defined(HOST_WORDS_BIGENDIAN)
2243 env
->active_tc
.gpr
[rd
] = (int32_t)env
->active_fpu
.fpr
[ws
].wr
.w
[n
];
2246 void helper_msa_copy_s_d(CPUMIPSState
*env
, uint32_t rd
,
2247 uint32_t ws
, uint32_t n
)
2250 env
->active_tc
.gpr
[rd
] = (int64_t)env
->active_fpu
.fpr
[ws
].wr
.d
[n
];
2253 void helper_msa_copy_u_b(CPUMIPSState
*env
, uint32_t rd
,
2254 uint32_t ws
, uint32_t n
)
2257 #if defined(HOST_WORDS_BIGENDIAN)
2264 env
->active_tc
.gpr
[rd
] = (uint8_t)env
->active_fpu
.fpr
[ws
].wr
.b
[n
];
2267 void helper_msa_copy_u_h(CPUMIPSState
*env
, uint32_t rd
,
2268 uint32_t ws
, uint32_t n
)
2271 #if defined(HOST_WORDS_BIGENDIAN)
2278 env
->active_tc
.gpr
[rd
] = (uint16_t)env
->active_fpu
.fpr
[ws
].wr
.h
[n
];
2281 void helper_msa_copy_u_w(CPUMIPSState
*env
, uint32_t rd
,
2282 uint32_t ws
, uint32_t n
)
2285 #if defined(HOST_WORDS_BIGENDIAN)
2292 env
->active_tc
.gpr
[rd
] = (uint32_t)env
->active_fpu
.fpr
[ws
].wr
.w
[n
];
2295 void helper_msa_insert_b(CPUMIPSState
*env
, uint32_t wd
,
2296 uint32_t rs_num
, uint32_t n
)
2298 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
2299 target_ulong rs
= env
->active_tc
.gpr
[rs_num
];
2301 #if defined(HOST_WORDS_BIGENDIAN)
2308 pwd
->b
[n
] = (int8_t)rs
;
2311 void helper_msa_insert_h(CPUMIPSState
*env
, uint32_t wd
,
2312 uint32_t rs_num
, uint32_t n
)
2314 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
2315 target_ulong rs
= env
->active_tc
.gpr
[rs_num
];
2317 #if defined(HOST_WORDS_BIGENDIAN)
2324 pwd
->h
[n
] = (int16_t)rs
;
2327 void helper_msa_insert_w(CPUMIPSState
*env
, uint32_t wd
,
2328 uint32_t rs_num
, uint32_t n
)
2330 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
2331 target_ulong rs
= env
->active_tc
.gpr
[rs_num
];
2333 #if defined(HOST_WORDS_BIGENDIAN)
2340 pwd
->w
[n
] = (int32_t)rs
;
2343 void helper_msa_insert_d(CPUMIPSState
*env
, uint32_t wd
,
2344 uint32_t rs_num
, uint32_t n
)
2346 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
2347 target_ulong rs
= env
->active_tc
.gpr
[rs_num
];
2349 pwd
->d
[n
] = (int64_t)rs
;
2352 void helper_msa_insve_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
2353 uint32_t ws
, uint32_t n
)
2355 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
2356 wr_t
*pws
= &(env
->active_fpu
.fpr
[ws
].wr
);
2360 pwd
->b
[n
] = (int8_t)pws
->b
[0];
2363 pwd
->h
[n
] = (int16_t)pws
->h
[0];
2366 pwd
->w
[n
] = (int32_t)pws
->w
[0];
2369 pwd
->d
[n
] = (int64_t)pws
->d
[0];
2376 void helper_msa_ctcmsa(CPUMIPSState
*env
, target_ulong elm
, uint32_t cd
)
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());
2393 target_ulong
helper_msa_cfcmsa(CPUMIPSState
*env
, uint32_t cs
)
2399 return env
->active_tc
.msacsr
& MSACSR_MASK
;
2404 void helper_msa_move_v(CPUMIPSState
*env
, uint32_t wd
, uint32_t ws
)
2406 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
2407 wr_t
*pws
= &(env
->active_fpu
.fpr
[ws
].wr
);
2409 msa_move_v(pwd
, pws
);
2412 static inline int64_t msa_pcnt_df(uint32_t df
, int64_t arg
)
2416 x
= UNSIGNED(arg
, df
);
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));
2428 static inline int64_t msa_nlzc_df(uint32_t df
, int64_t arg
)
2433 x
= UNSIGNED(arg
, df
);
2435 c
= DF_BITS(df
) / 2;
2449 static inline int64_t msa_nloc_df(uint32_t df
, int64_t arg
)
2451 return msa_nlzc_df(df
, UNSIGNED((~arg
), df
));
2454 void helper_msa_fill_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
2457 wr_t
*pwd
= &(env
->active_fpu
.fpr
[wd
].wr
);
2462 for (i
= 0; i
< DF_ELEMENTS(DF_BYTE
); i
++) {
2463 pwd
->b
[i
] = (int8_t)env
->active_tc
.gpr
[rs
];
2467 for (i
= 0; i
< DF_ELEMENTS(DF_HALF
); i
++) {
2468 pwd
->h
[i
] = (int16_t)env
->active_tc
.gpr
[rs
];
2472 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
2473 pwd
->w
[i
] = (int32_t)env
->active_tc
.gpr
[rs
];
2477 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
2478 pwd
->d
[i
] = (int64_t)env
->active_tc
.gpr
[rs
];
2486 #define MSA_UNOP_DF(func) \
2487 void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \
2488 uint32_t wd, uint32_t ws) \
2490 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
2491 wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
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]); \
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]); \
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]); \
2529 pwd->d[0] = msa_ ## func ## _df(df, pws->d[0]); \
2530 pwd->d[1] = msa_ ## func ## _df(df, pws->d[1]); \
2542 #define FLOAT_ONE32 make_float32(0x3f8 << 20)
2543 #define FLOAT_ONE64 make_float64(0x3ffULL << 52)
2545 #define FLOAT_SNAN16(s) (float16_default_nan(s) ^ 0x0220)
2547 #define FLOAT_SNAN32(s) (float32_default_nan(s) ^ 0x00400020)
2549 #define FLOAT_SNAN64(s) (float64_default_nan(s) ^ 0x0008000000000020ULL)
2550 /* 0x7ff0000000000020 */
2552 static inline void clear_msacsr_cause(CPUMIPSState
*env
)
2554 SET_FP_CAUSE(env
->active_tc
.msacsr
, 0);
2557 static inline void check_msacsr_cause(CPUMIPSState
*env
, uintptr_t retaddr
)
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
));
2564 do_raise_exception(env
, EXCP_MSAFPE
, retaddr
);
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
2573 static inline int update_msacsr(CPUMIPSState
*env
, int action
, int denormal
)
2581 ieee_ex
= get_float_exception_flags(&env
->active_tc
.msa_fp_status
);
2583 /* QEMU softfloat does not signal all underflow cases */
2585 ieee_ex
|= float_flag_underflow
;
2588 c
= ieee_ex_to_mips(ieee_ex
);
2589 enable
= GET_FP_ENABLE(env
->active_tc
.msacsr
) | FP_UNIMPLEMENTED
;
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
) {
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) {
2605 if (action
& CLEAR_FS_UNDERFLOW
) {
2612 /* Set Inexact (I) when Overflow (O) is not enabled */
2613 if ((c
& FP_OVERFLOW
) != 0 && (enable
& FP_OVERFLOW
) == 0) {
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) {
2624 * Reciprocal operations set only Inexact when valid and not
2627 if ((action
& RECIPROCAL_INEXACT
) &&
2628 (c
& (FP_INVALID
| FP_DIV0
)) == 0) {
2632 cause
= c
& enable
; /* all current enabled exceptions */
2636 * No enabled exception, update the MSACSR Cause
2637 * with all current exceptions
2639 SET_FP_CAUSE(env
->active_tc
.msacsr
,
2640 (GET_FP_CAUSE(env
->active_tc
.msacsr
) | c
));
2642 /* Current exceptions are enabled */
2643 if ((env
->active_tc
.msacsr
& MSACSR_NX_MASK
) == 0) {
2645 * Exception(s) will trap, update MSACSR Cause
2646 * with all enabled exceptions
2648 SET_FP_CAUSE(env
->active_tc
.msacsr
,
2649 (GET_FP_CAUSE(env
->active_tc
.msacsr
) | c
));
2656 static inline int get_enabled_exceptions(const CPUMIPSState
*env
, int c
)
2658 int enable
= GET_FP_ENABLE(env
->active_tc
.msacsr
) | FP_UNIMPLEMENTED
;
2662 static inline float16
float16_from_float32(int32_t a
, flag ieee
,
2663 float_status
*status
)
2667 f_val
= float32_to_float16((float32
)a
, ieee
, status
);
2669 return a
< 0 ? (f_val
| (1 << 15)) : f_val
;
2672 static inline float32
float32_from_float64(int64_t a
, float_status
*status
)
2676 f_val
= float64_to_float32((float64
)a
, status
);
2678 return a
< 0 ? (f_val
| (1 << 31)) : f_val
;
2681 static inline float32
float32_from_float16(int16_t a
, flag ieee
,
2682 float_status
*status
)
2686 f_val
= float16_to_float32((float16
)a
, ieee
, status
);
2688 return a
< 0 ? (f_val
| (1 << 31)) : f_val
;
2691 static inline float64
float64_from_float32(int32_t a
, float_status
*status
)
2695 f_val
= float32_to_float64((float64
)a
, status
);
2697 return a
< 0 ? (f_val
| (1ULL << 63)) : f_val
;
2700 static inline float32
float32_from_q16(int16_t a
, float_status
*status
)
2704 /* conversion as integer and scaling */
2705 f_val
= int32_to_float32(a
, status
);
2706 f_val
= float32_scalbn(f_val
, -15, status
);
2711 static inline float64
float64_from_q32(int32_t a
, float_status
*status
)
2715 /* conversion as integer and scaling */
2716 f_val
= int32_to_float64(a
, status
);
2717 f_val
= float64_scalbn(f_val
, -31, status
);
2722 static inline int16_t float32_to_q16(float32 a
, float_status
*status
)
2725 int32_t q_min
= 0xffff8000;
2726 int32_t q_max
= 0x00007fff;
2730 if (float32_is_any_nan(a
)) {
2731 float_raise(float_flag_invalid
, status
);
2736 a
= float32_scalbn(a
, 15, status
);
2738 ieee_ex
= get_float_exception_flags(status
);
2739 set_float_exception_flags(ieee_ex
& (~float_flag_underflow
)
2742 if (ieee_ex
& float_flag_overflow
) {
2743 float_raise(float_flag_inexact
, status
);
2744 return (int32_t)a
< 0 ? q_min
: q_max
;
2747 /* conversion to int */
2748 q_val
= float32_to_int32(a
, status
);
2750 ieee_ex
= get_float_exception_flags(status
);
2751 set_float_exception_flags(ieee_ex
& (~float_flag_underflow
)
2754 if (ieee_ex
& float_flag_invalid
) {
2755 set_float_exception_flags(ieee_ex
& (~float_flag_invalid
)
2757 float_raise(float_flag_overflow
| float_flag_inexact
, status
);
2758 return (int32_t)a
< 0 ? q_min
: q_max
;
2761 if (q_val
< q_min
) {
2762 float_raise(float_flag_overflow
| float_flag_inexact
, status
);
2763 return (int16_t)q_min
;
2766 if (q_max
< q_val
) {
2767 float_raise(float_flag_overflow
| float_flag_inexact
, status
);
2768 return (int16_t)q_max
;
2771 return (int16_t)q_val
;
2774 static inline int32_t float64_to_q32(float64 a
, float_status
*status
)
2777 int64_t q_min
= 0xffffffff80000000LL
;
2778 int64_t q_max
= 0x000000007fffffffLL
;
2782 if (float64_is_any_nan(a
)) {
2783 float_raise(float_flag_invalid
, status
);
2788 a
= float64_scalbn(a
, 31, status
);
2790 ieee_ex
= get_float_exception_flags(status
);
2791 set_float_exception_flags(ieee_ex
& (~float_flag_underflow
)
2794 if (ieee_ex
& float_flag_overflow
) {
2795 float_raise(float_flag_inexact
, status
);
2796 return (int64_t)a
< 0 ? q_min
: q_max
;
2799 /* conversion to integer */
2800 q_val
= float64_to_int64(a
, status
);
2802 ieee_ex
= get_float_exception_flags(status
);
2803 set_float_exception_flags(ieee_ex
& (~float_flag_underflow
)
2806 if (ieee_ex
& float_flag_invalid
) {
2807 set_float_exception_flags(ieee_ex
& (~float_flag_invalid
)
2809 float_raise(float_flag_overflow
| float_flag_inexact
, status
);
2810 return (int64_t)a
< 0 ? q_min
: q_max
;
2813 if (q_val
< q_min
) {
2814 float_raise(float_flag_overflow
| float_flag_inexact
, status
);
2815 return (int32_t)q_min
;
2818 if (q_max
< q_val
) {
2819 float_raise(float_flag_overflow
| float_flag_inexact
, status
);
2820 return (int32_t)q_max
;
2823 return (int32_t)q_val
;
2826 #define MSA_FLOAT_COND(DEST, OP, ARG1, ARG2, BITS, QUIET) \
2828 float_status *status = &env->active_tc.msa_fp_status; \
2831 set_float_exception_flags(0, status); \
2833 cond = float ## BITS ## _ ## OP(ARG1, ARG2, status); \
2835 cond = float ## BITS ## _ ## OP ## _quiet(ARG1, ARG2, status); \
2837 DEST = cond ? M_MAX_UINT(BITS) : 0; \
2838 c = update_msacsr(env, CLEAR_IS_INEXACT, 0); \
2840 if (get_enabled_exceptions(env, c)) { \
2841 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
2845 #define MSA_FLOAT_AF(DEST, ARG1, ARG2, BITS, QUIET) \
2847 MSA_FLOAT_COND(DEST, eq, ARG1, ARG2, BITS, QUIET); \
2848 if ((DEST & M_MAX_UINT(BITS)) == M_MAX_UINT(BITS)) { \
2853 #define MSA_FLOAT_UEQ(DEST, ARG1, ARG2, BITS, QUIET) \
2855 MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET); \
2857 MSA_FLOAT_COND(DEST, eq, ARG1, ARG2, BITS, QUIET); \
2861 #define MSA_FLOAT_NE(DEST, ARG1, ARG2, BITS, QUIET) \
2863 MSA_FLOAT_COND(DEST, lt, ARG1, ARG2, BITS, QUIET); \
2865 MSA_FLOAT_COND(DEST, lt, ARG2, ARG1, BITS, QUIET); \
2869 #define MSA_FLOAT_UNE(DEST, ARG1, ARG2, BITS, QUIET) \
2871 MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET); \
2873 MSA_FLOAT_COND(DEST, lt, ARG1, ARG2, BITS, QUIET); \
2875 MSA_FLOAT_COND(DEST, lt, ARG2, ARG1, BITS, QUIET); \
2880 #define MSA_FLOAT_ULE(DEST, ARG1, ARG2, BITS, QUIET) \
2882 MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET); \
2884 MSA_FLOAT_COND(DEST, le, ARG1, ARG2, BITS, QUIET); \
2888 #define MSA_FLOAT_ULT(DEST, ARG1, ARG2, BITS, QUIET) \
2890 MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET); \
2892 MSA_FLOAT_COND(DEST, lt, ARG1, ARG2, BITS, QUIET); \
2896 #define MSA_FLOAT_OR(DEST, ARG1, ARG2, BITS, QUIET) \
2898 MSA_FLOAT_COND(DEST, le, ARG1, ARG2, BITS, QUIET); \
2900 MSA_FLOAT_COND(DEST, le, ARG2, ARG1, BITS, QUIET); \
2904 static inline void compare_af(CPUMIPSState
*env
, wr_t
*pwd
, wr_t
*pws
,
2905 wr_t
*pwt
, uint32_t df
, int quiet
,
2908 wr_t wx
, *pwx
= &wx
;
2911 clear_msacsr_cause(env
);
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
);
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
);
2928 check_msacsr_cause(env
, retaddr
);
2930 msa_move_v(pwd
, pwx
);
2933 static inline void compare_un(CPUMIPSState
*env
, wr_t
*pwd
, wr_t
*pws
,
2934 wr_t
*pwt
, uint32_t df
, int quiet
,
2937 wr_t wx
, *pwx
= &wx
;
2940 clear_msacsr_cause(env
);
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,
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,
2959 check_msacsr_cause(env
, retaddr
);
2961 msa_move_v(pwd
, pwx
);
2964 static inline void compare_eq(CPUMIPSState
*env
, wr_t
*pwd
, wr_t
*pws
,
2965 wr_t
*pwt
, uint32_t df
, int quiet
,
2968 wr_t wx
, *pwx
= &wx
;
2971 clear_msacsr_cause(env
);
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
);
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
);
2988 check_msacsr_cause(env
, retaddr
);
2990 msa_move_v(pwd
, pwx
);
2993 static inline void compare_ueq(CPUMIPSState
*env
, wr_t
*pwd
, wr_t
*pws
,
2994 wr_t
*pwt
, uint32_t df
, int quiet
,
2997 wr_t wx
, *pwx
= &wx
;
3000 clear_msacsr_cause(env
);
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
);
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
);
3017 check_msacsr_cause(env
, retaddr
);
3019 msa_move_v(pwd
, pwx
);
3022 static inline void compare_lt(CPUMIPSState
*env
, wr_t
*pwd
, wr_t
*pws
,
3023 wr_t
*pwt
, uint32_t df
, int quiet
,
3026 wr_t wx
, *pwx
= &wx
;
3029 clear_msacsr_cause(env
);
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
);
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
);
3046 check_msacsr_cause(env
, retaddr
);
3048 msa_move_v(pwd
, pwx
);
3051 static inline void compare_ult(CPUMIPSState
*env
, wr_t
*pwd
, wr_t
*pws
,
3052 wr_t
*pwt
, uint32_t df
, int quiet
,
3055 wr_t wx
, *pwx
= &wx
;
3058 clear_msacsr_cause(env
);
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
);
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
);
3075 check_msacsr_cause(env
, retaddr
);
3077 msa_move_v(pwd
, pwx
);
3080 static inline void compare_le(CPUMIPSState
*env
, wr_t
*pwd
, wr_t
*pws
,
3081 wr_t
*pwt
, uint32_t df
, int quiet
,
3084 wr_t wx
, *pwx
= &wx
;
3087 clear_msacsr_cause(env
);
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
);
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
);
3104 check_msacsr_cause(env
, retaddr
);
3106 msa_move_v(pwd
, pwx
);
3109 static inline void compare_ule(CPUMIPSState
*env
, wr_t
*pwd
, wr_t
*pws
,
3110 wr_t
*pwt
, uint32_t df
, int quiet
,
3113 wr_t wx
, *pwx
= &wx
;
3116 clear_msacsr_cause(env
);
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
);
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
);
3133 check_msacsr_cause(env
, retaddr
);
3135 msa_move_v(pwd
, pwx
);
3138 static inline void compare_or(CPUMIPSState
*env
, wr_t
*pwd
, wr_t
*pws
,
3139 wr_t
*pwt
, uint32_t df
, int quiet
,
3142 wr_t wx
, *pwx
= &wx
;
3145 clear_msacsr_cause(env
);
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
);
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
);
3162 check_msacsr_cause(env
, retaddr
);
3164 msa_move_v(pwd
, pwx
);
3167 static inline void compare_une(CPUMIPSState
*env
, wr_t
*pwd
, wr_t
*pws
,
3168 wr_t
*pwt
, uint32_t df
, int quiet
,
3171 wr_t wx
, *pwx
= &wx
;
3174 clear_msacsr_cause(env
);
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
);
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
);
3191 check_msacsr_cause(env
, retaddr
);
3193 msa_move_v(pwd
, pwx
);
3196 static inline void compare_ne(CPUMIPSState
*env
, wr_t
*pwd
, wr_t
*pws
,
3197 wr_t
*pwt
, uint32_t df
, int quiet
,
3200 wr_t wx
, *pwx
= &wx
;
3203 clear_msacsr_cause(env
);
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
);
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
);
3220 check_msacsr_cause(env
, retaddr
);
3222 msa_move_v(pwd
, pwx
);
3225 void helper_msa_fcaf_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3226 uint32_t ws
, uint32_t wt
)
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());
3234 void helper_msa_fcun_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3235 uint32_t ws
, uint32_t wt
)
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());
3243 void helper_msa_fceq_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3244 uint32_t ws
, uint32_t wt
)
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());
3252 void helper_msa_fcueq_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3253 uint32_t ws
, uint32_t wt
)
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());
3261 void helper_msa_fclt_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3262 uint32_t ws
, uint32_t wt
)
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());
3270 void helper_msa_fcult_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3271 uint32_t ws
, uint32_t wt
)
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());
3279 void helper_msa_fcle_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3280 uint32_t ws
, uint32_t wt
)
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());
3288 void helper_msa_fcule_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3289 uint32_t ws
, uint32_t wt
)
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());
3297 void helper_msa_fsaf_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3298 uint32_t ws
, uint32_t wt
)
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());
3306 void helper_msa_fsun_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3307 uint32_t ws
, uint32_t wt
)
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());
3315 void helper_msa_fseq_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3316 uint32_t ws
, uint32_t wt
)
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());
3324 void helper_msa_fsueq_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3325 uint32_t ws
, uint32_t wt
)
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());
3333 void helper_msa_fslt_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3334 uint32_t ws
, uint32_t wt
)
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());
3342 void helper_msa_fsult_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3343 uint32_t ws
, uint32_t wt
)
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());
3351 void helper_msa_fsle_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3352 uint32_t ws
, uint32_t wt
)
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());
3360 void helper_msa_fsule_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3361 uint32_t ws
, uint32_t wt
)
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());
3369 void helper_msa_fcor_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3370 uint32_t ws
, uint32_t wt
)
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());
3378 void helper_msa_fcune_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3379 uint32_t ws
, uint32_t wt
)
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());
3387 void helper_msa_fcne_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3388 uint32_t ws
, uint32_t wt
)
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());
3396 void helper_msa_fsor_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3397 uint32_t ws
, uint32_t wt
)
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());
3405 void helper_msa_fsune_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3406 uint32_t ws
, uint32_t wt
)
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());
3414 void helper_msa_fsne_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3415 uint32_t ws
, uint32_t wt
)
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());
3423 #define float16_is_zero(ARG) 0
3424 #define float16_is_zero_or_denormal(ARG) 0
3426 #define IS_DENORMAL(ARG, BITS) \
3427 (!float ## BITS ## _is_zero(ARG) \
3428 && float ## BITS ## _is_zero_or_denormal(ARG))
3430 #define MSA_FLOAT_BINOP(DEST, OP, ARG1, ARG2, BITS) \
3432 float_status *status = &env->active_tc.msa_fp_status; \
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)); \
3439 if (get_enabled_exceptions(env, c)) { \
3440 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
3444 void helper_msa_fadd_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3445 uint32_t ws
, uint32_t wt
)
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
);
3453 clear_msacsr_cause(env
);
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);
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);
3470 check_msacsr_cause(env
, GETPC());
3471 msa_move_v(pwd
, pwx
);
3474 void helper_msa_fsub_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3475 uint32_t ws
, uint32_t wt
)
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
);
3483 clear_msacsr_cause(env
);
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);
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);
3500 check_msacsr_cause(env
, GETPC());
3501 msa_move_v(pwd
, pwx
);
3504 void helper_msa_fmul_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3505 uint32_t ws
, uint32_t wt
)
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
);
3513 clear_msacsr_cause(env
);
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);
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);
3530 check_msacsr_cause(env
, GETPC());
3532 msa_move_v(pwd
, pwx
);
3535 void helper_msa_fdiv_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3536 uint32_t ws
, uint32_t wt
)
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
);
3544 clear_msacsr_cause(env
);
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);
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);
3561 check_msacsr_cause(env
, GETPC());
3563 msa_move_v(pwd
, pwx
);
3566 #define MSA_FLOAT_MULADD(DEST, ARG1, ARG2, ARG3, NEGATE, BITS) \
3568 float_status *status = &env->active_tc.msa_fp_status; \
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)); \
3575 if (get_enabled_exceptions(env, c)) { \
3576 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
3580 void helper_msa_fmadd_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3581 uint32_t ws
, uint32_t wt
)
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
);
3589 clear_msacsr_cause(env
);
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);
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);
3608 check_msacsr_cause(env
, GETPC());
3610 msa_move_v(pwd
, pwx
);
3613 void helper_msa_fmsub_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3614 uint32_t ws
, uint32_t wt
)
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
);
3622 clear_msacsr_cause(env
);
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);
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);
3643 check_msacsr_cause(env
, GETPC());
3645 msa_move_v(pwd
, pwx
);
3648 void helper_msa_fexp2_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3649 uint32_t ws
, uint32_t wt
)
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
);
3657 clear_msacsr_cause(env
);
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
],
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
],
3680 check_msacsr_cause(env
, GETPC());
3682 msa_move_v(pwd
, pwx
);
3685 #define MSA_FLOAT_UNOP(DEST, OP, ARG, BITS) \
3687 float_status *status = &env->active_tc.msa_fp_status; \
3690 set_float_exception_flags(0, status); \
3691 DEST = float ## BITS ## _ ## OP(ARG, status); \
3692 c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
3694 if (get_enabled_exceptions(env, c)) { \
3695 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
3699 void helper_msa_fexdo_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3700 uint32_t ws
, uint32_t wt
)
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
);
3708 clear_msacsr_cause(env
);
3712 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
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.
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);
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);
3734 check_msacsr_cause(env
, GETPC());
3735 msa_move_v(pwd
, pwx
);
3738 #define MSA_FLOAT_UNOP_XD(DEST, OP, ARG, BITS, XBITS) \
3740 float_status *status = &env->active_tc.msa_fp_status; \
3743 set_float_exception_flags(0, status); \
3744 DEST = float ## BITS ## _ ## OP(ARG, status); \
3745 c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \
3747 if (get_enabled_exceptions(env, c)) { \
3748 DEST = ((FLOAT_SNAN ## XBITS(status) >> 6) << 6) | c; \
3752 void helper_msa_ftq_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3753 uint32_t ws
, uint32_t wt
)
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
);
3761 clear_msacsr_cause(env
);
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);
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);
3780 check_msacsr_cause(env
, GETPC());
3782 msa_move_v(pwd
, pwx
);
3785 #define NUMBER_QNAN_PAIR(ARG1, ARG2, BITS, STATUS) \
3786 !float ## BITS ## _is_any_nan(ARG1) \
3787 && float ## BITS ## _is_quiet_nan(ARG2, STATUS)
3789 #define MSA_FLOAT_MAXOP(DEST, OP, ARG1, ARG2, BITS) \
3791 float_status *status = &env->active_tc.msa_fp_status; \
3794 set_float_exception_flags(0, status); \
3795 DEST = float ## BITS ## _ ## OP(ARG1, ARG2, status); \
3796 c = update_msacsr(env, 0, 0); \
3798 if (get_enabled_exceptions(env, c)) { \
3799 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
3803 #define FMAXMIN_A(F, G, X, _S, _T, BITS, STATUS) \
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)) { \
3810 else if (NUMBER_QNAN_PAIR(T, S, BITS, STATUS)) { \
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; \
3821 void helper_msa_fmin_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3822 uint32_t ws
, uint32_t wt
)
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
);
3831 clear_msacsr_cause(env
);
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);
3841 MSA_FLOAT_MAXOP(pwx
->w
[i
], min
, pws
->w
[i
], pwt
->w
[i
], 32);
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);
3852 MSA_FLOAT_MAXOP(pwx
->d
[i
], min
, pws
->d
[i
], pwt
->d
[i
], 64);
3860 check_msacsr_cause(env
, GETPC());
3862 msa_move_v(pwd
, pwx
);
3865 void helper_msa_fmin_a_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3866 uint32_t ws
, uint32_t wt
)
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
);
3875 clear_msacsr_cause(env
);
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
);
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
);
3892 check_msacsr_cause(env
, GETPC());
3894 msa_move_v(pwd
, pwx
);
3897 void helper_msa_fmax_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3898 uint32_t ws
, uint32_t wt
)
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
);
3907 clear_msacsr_cause(env
);
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);
3917 MSA_FLOAT_MAXOP(pwx
->w
[i
], max
, pws
->w
[i
], pwt
->w
[i
], 32);
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);
3928 MSA_FLOAT_MAXOP(pwx
->d
[i
], max
, pws
->d
[i
], pwt
->d
[i
], 64);
3936 check_msacsr_cause(env
, GETPC());
3938 msa_move_v(pwd
, pwx
);
3941 void helper_msa_fmax_a_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
3942 uint32_t ws
, uint32_t wt
)
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
);
3951 clear_msacsr_cause(env
);
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
);
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
);
3968 check_msacsr_cause(env
, GETPC());
3970 msa_move_v(pwd
, pwx
);
3973 void helper_msa_fclass_df(CPUMIPSState
*env
, uint32_t df
,
3974 uint32_t wd
, uint32_t ws
)
3976 float_status
*status
= &env
->active_tc
.msa_fp_status
;
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
);
3986 pwd
->d
[0] = float_class_d(pws
->d
[0], status
);
3987 pwd
->d
[1] = float_class_d(pws
->d
[1], status
);
3991 #define MSA_FLOAT_UNOP0(DEST, OP, ARG, BITS) \
3993 float_status *status = &env->active_tc.msa_fp_status; \
3996 set_float_exception_flags(0, status); \
3997 DEST = float ## BITS ## _ ## OP(ARG, status); \
3998 c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \
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)) { \
4007 void helper_msa_ftrunc_s_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4015 clear_msacsr_cause(env
);
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);
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);
4032 check_msacsr_cause(env
, GETPC());
4034 msa_move_v(pwd
, pwx
);
4037 void helper_msa_ftrunc_u_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4045 clear_msacsr_cause(env
);
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);
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);
4062 check_msacsr_cause(env
, GETPC());
4064 msa_move_v(pwd
, pwx
);
4067 void helper_msa_fsqrt_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4075 clear_msacsr_cause(env
);
4079 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
4080 MSA_FLOAT_UNOP(pwx
->w
[i
], sqrt
, pws
->w
[i
], 32);
4084 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4085 MSA_FLOAT_UNOP(pwx
->d
[i
], sqrt
, pws
->d
[i
], 64);
4092 check_msacsr_cause(env
, GETPC());
4094 msa_move_v(pwd
, pwx
);
4097 #define MSA_FLOAT_RECIPROCAL(DEST, ARG, BITS) \
4099 float_status *status = &env->active_tc.msa_fp_status; \
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)); \
4109 if (get_enabled_exceptions(env, c)) { \
4110 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
4114 void helper_msa_frsqrt_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4122 clear_msacsr_cause(env
);
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);
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);
4141 check_msacsr_cause(env
, GETPC());
4143 msa_move_v(pwd
, pwx
);
4146 void helper_msa_frcp_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4154 clear_msacsr_cause(env
);
4158 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
4159 MSA_FLOAT_RECIPROCAL(pwx
->w
[i
], pws
->w
[i
], 32);
4163 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4164 MSA_FLOAT_RECIPROCAL(pwx
->d
[i
], pws
->d
[i
], 64);
4171 check_msacsr_cause(env
, GETPC());
4173 msa_move_v(pwd
, pwx
);
4176 void helper_msa_frint_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4184 clear_msacsr_cause(env
);
4188 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
4189 MSA_FLOAT_UNOP(pwx
->w
[i
], round_to_int
, pws
->w
[i
], 32);
4193 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4194 MSA_FLOAT_UNOP(pwx
->d
[i
], round_to_int
, pws
->d
[i
], 64);
4201 check_msacsr_cause(env
, GETPC());
4203 msa_move_v(pwd
, pwx
);
4206 #define MSA_FLOAT_LOGB(DEST, ARG, BITS) \
4208 float_status *status = &env->active_tc.msa_fp_status; \
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], \
4219 set_float_exception_flags(get_float_exception_flags(status) & \
4220 (~float_flag_inexact), \
4223 c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
4225 if (get_enabled_exceptions(env, c)) { \
4226 DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
4230 void helper_msa_flog2_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4238 clear_msacsr_cause(env
);
4242 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
4243 MSA_FLOAT_LOGB(pwx
->w
[i
], pws
->w
[i
], 32);
4247 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4248 MSA_FLOAT_LOGB(pwx
->d
[i
], pws
->d
[i
], 64);
4255 check_msacsr_cause(env
, GETPC());
4257 msa_move_v(pwd
, pwx
);
4260 void helper_msa_fexupl_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4268 clear_msacsr_cause(env
);
4272 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
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.
4280 MSA_FLOAT_BINOP(pwx
->w
[i
], from_float16
, Lh(pws
, i
), ieee
, 32);
4284 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4285 MSA_FLOAT_UNOP(pwx
->d
[i
], from_float32
, Lw(pws
, i
), 64);
4292 check_msacsr_cause(env
, GETPC());
4293 msa_move_v(pwd
, pwx
);
4296 void helper_msa_fexupr_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4304 clear_msacsr_cause(env
);
4308 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
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.
4316 MSA_FLOAT_BINOP(pwx
->w
[i
], from_float16
, Rh(pws
, i
), ieee
, 32);
4320 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4321 MSA_FLOAT_UNOP(pwx
->d
[i
], from_float32
, Rw(pws
, i
), 64);
4328 check_msacsr_cause(env
, GETPC());
4329 msa_move_v(pwd
, pwx
);
4332 void helper_msa_ffql_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4342 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
4343 MSA_FLOAT_UNOP(pwx
->w
[i
], from_q16
, Lh(pws
, i
), 32);
4347 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4348 MSA_FLOAT_UNOP(pwx
->d
[i
], from_q32
, Lw(pws
, i
), 64);
4355 msa_move_v(pwd
, pwx
);
4358 void helper_msa_ffqr_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4368 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
4369 MSA_FLOAT_UNOP(pwx
->w
[i
], from_q16
, Rh(pws
, i
), 32);
4373 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4374 MSA_FLOAT_UNOP(pwx
->d
[i
], from_q32
, Rw(pws
, i
), 64);
4381 msa_move_v(pwd
, pwx
);
4384 void helper_msa_ftint_s_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4392 clear_msacsr_cause(env
);
4396 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
4397 MSA_FLOAT_UNOP0(pwx
->w
[i
], to_int32
, pws
->w
[i
], 32);
4401 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4402 MSA_FLOAT_UNOP0(pwx
->d
[i
], to_int64
, pws
->d
[i
], 64);
4409 check_msacsr_cause(env
, GETPC());
4411 msa_move_v(pwd
, pwx
);
4414 void helper_msa_ftint_u_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4422 clear_msacsr_cause(env
);
4426 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
4427 MSA_FLOAT_UNOP0(pwx
->w
[i
], to_uint32
, pws
->w
[i
], 32);
4431 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4432 MSA_FLOAT_UNOP0(pwx
->d
[i
], to_uint64
, pws
->d
[i
], 64);
4439 check_msacsr_cause(env
, GETPC());
4441 msa_move_v(pwd
, pwx
);
4444 #define float32_from_int32 int32_to_float32
4445 #define float32_from_uint32 uint32_to_float32
4447 #define float64_from_int64 int64_to_float64
4448 #define float64_from_uint64 uint64_to_float64
4450 void helper_msa_ffint_s_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4458 clear_msacsr_cause(env
);
4462 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
4463 MSA_FLOAT_UNOP(pwx
->w
[i
], from_int32
, pws
->w
[i
], 32);
4467 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4468 MSA_FLOAT_UNOP(pwx
->d
[i
], from_int64
, pws
->d
[i
], 64);
4475 check_msacsr_cause(env
, GETPC());
4477 msa_move_v(pwd
, pwx
);
4480 void helper_msa_ffint_u_df(CPUMIPSState
*env
, uint32_t df
, uint32_t wd
,
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
);
4488 clear_msacsr_cause(env
);
4492 for (i
= 0; i
< DF_ELEMENTS(DF_WORD
); i
++) {
4493 MSA_FLOAT_UNOP(pwx
->w
[i
], from_uint32
, pws
->w
[i
], 32);
4497 for (i
= 0; i
< DF_ELEMENTS(DF_DOUBLE
); i
++) {
4498 MSA_FLOAT_UNOP(pwx
->d
[i
], from_uint64
, pws
->d
[i
], 64);
4505 check_msacsr_cause(env
, GETPC());
4507 msa_move_v(pwd
, pwx
);