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