]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/arm/iwmmxt.c
ld: pru: Increase the default memory region sizes
[thirdparty/binutils-gdb.git] / sim / arm / iwmmxt.c
CommitLineData
0f026fd0 1/* iwmmxt.c -- Intel(r) Wireless MMX(tm) technology co-processor interface.
1d506c26 2 Copyright (C) 2002-2024 Free Software Foundation, Inc.
0f026fd0 3 Contributed by matthew green (mrg@redhat.com).
454de2ee 4
0f026fd0
NC
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
4744ac1b 7 the Free Software Foundation; either version 3 of the License, or
0f026fd0 8 (at your option) any later version.
4744ac1b 9
0f026fd0
NC
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
4744ac1b 14
0f026fd0 15 You should have received a copy of the GNU General Public License
4744ac1b 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
0f026fd0 17
6df01ab8
MF
18/* This must come before any other includes. */
19#include "defs.h"
20
9416af6e 21#include <stdlib.h>
a85c0b49
JS
22#include <string.h>
23
0f026fd0
NC
24#include "armdefs.h"
25#include "armos.h"
26#include "armemu.h"
27#include "ansidecl.h"
28#include "iwmmxt.h"
29
30/* #define DEBUG 1 */
31
454de2ee 32/* Intel(r) Wireless MMX(tm) technology co-processor.
0f026fd0
NC
33 It uses co-processor numbers (0 and 1). There are 16 vector registers wRx
34 and 16 control registers wCx. Co-processors 0 and 1 are used in MCR/MRC
35 to access wRx and wCx respectively. */
36
37static ARMdword wR[16];
38static ARMword wC[16] = { 0x69051010 };
39
40#define SUBSTR(w,t,m,n) ((t)(w << ((sizeof (t) * 8 - 1) - (n))) \
41 >> (((sizeof (t) * 8 - 1) - (n)) + (m)))
42#define wCBITS(w,x,y) SUBSTR (wC[w], ARMword, x, y)
43#define wRBITS(w,x,y) SUBSTR (wR[w], ARMdword, x, y)
44#define wCID 0
45#define wCon 1
46#define wCSSF 2
47#define wCASF 3
48#define wCGR0 8
49#define wCGR1 9
50#define wCGR2 10
51#define wCGR3 11
52
53/* Bits in the wCon register. */
54#define WCON_CUP (1 << 0)
55#define WCON_MUP (1 << 1)
56
57/* Set the SIMD wCASF flags for 8, 16, 32 or 64-bit operations. */
58#define SIMD8_SET(x, v, n, b) (x) |= ((v != 0) << ((((b) + 1) * 4) + (n)))
59#define SIMD16_SET(x, v, n, h) (x) |= ((v != 0) << ((((h) + 1) * 8) + (n)))
60#define SIMD32_SET(x, v, n, w) (x) |= ((v != 0) << ((((w) + 1) * 16) + (n)))
61#define SIMD64_SET(x, v, n) (x) |= ((v != 0) << (32 + (n)))
62
63/* Flags to pass as "n" above. */
64#define SIMD_NBIT -1
65#define SIMD_ZBIT -2
66#define SIMD_CBIT -3
67#define SIMD_VBIT -4
68
69/* Various status bit macros. */
70#define NBIT8(x) ((x) & 0x80)
71#define NBIT16(x) ((x) & 0x8000)
72#define NBIT32(x) ((x) & 0x80000000)
73#define NBIT64(x) ((x) & 0x8000000000000000ULL)
74#define ZBIT8(x) (((x) & 0xff) == 0)
75#define ZBIT16(x) (((x) & 0xffff) == 0)
76#define ZBIT32(x) (((x) & 0xffffffff) == 0)
77#define ZBIT64(x) (x == 0)
78
79/* Access byte/half/word "n" of register "x". */
80#define wRBYTE(x,n) wRBITS ((x), (n) * 8, (n) * 8 + 7)
81#define wRHALF(x,n) wRBITS ((x), (n) * 16, (n) * 16 + 15)
82#define wRWORD(x,n) wRBITS ((x), (n) * 32, (n) * 32 + 31)
83
84/* Macro to handle how the G bit selects wCGR registers. */
85#define DECODE_G_BIT(state, instr, shift) \
86{ \
87 unsigned int reg; \
88 \
89 reg = BITS (0, 3); \
90 \
91 if (BIT (8)) /* G */ \
92 { \
93 if (reg < wCGR0 || reg > wCGR3) \
94 { \
95 ARMul_UndefInstr (state, instr); \
96 return ARMul_DONE; \
97 } \
98 shift = wC [reg]; \
99 } \
100 else \
101 shift = wR [reg]; \
102 \
103 shift &= 0xff; \
104}
105
106/* Index calculations for the satrv[] array. */
107#define BITIDX8(x) (x)
108#define BITIDX16(x) (((x) + 1) * 2 - 1)
109#define BITIDX32(x) (((x) + 1) * 4 - 1)
110
111/* Sign extension macros. */
112#define EXTEND8(a) ((a) & 0x80 ? ((a) | 0xffffff00) : (a))
113#define EXTEND16(a) ((a) & 0x8000 ? ((a) | 0xffff0000) : (a))
114#define EXTEND32(a) ((a) & 0x80000000ULL ? ((a) | 0xffffffff00000000ULL) : (a))
115
116/* Set the wCSSF from 8 values. */
117#define SET_wCSSF(a,b,c,d,e,f,g,h) \
118 wC[wCSSF] = (((h) != 0) << 7) | (((g) != 0) << 6) \
119 | (((f) != 0) << 5) | (((e) != 0) << 4) \
120 | (((d) != 0) << 3) | (((c) != 0) << 2) \
121 | (((b) != 0) << 1) | (((a) != 0) << 0);
122
123/* Set the wCSSR from an array with 8 values. */
124#define SET_wCSSFvec(v) \
125 SET_wCSSF((v)[0],(v)[1],(v)[2],(v)[3],(v)[4],(v)[5],(v)[6],(v)[7])
126
127/* Size qualifiers for vector operations. */
128#define Bqual 0
129#define Hqual 1
130#define Wqual 2
131#define Dqual 3
132
133/* Saturation qualifiers for vector operations. */
134#define NoSaturation 0
135#define UnsignedSaturation 1
136#define SignedSaturation 3
137
138\f
139/* Prototypes. */
140static ARMword Add32 (ARMword, ARMword, int *, int *, ARMword);
141static ARMdword AddS32 (ARMdword, ARMdword, int *, int *);
142static ARMdword AddU32 (ARMdword, ARMdword, int *, int *);
143static ARMword AddS16 (ARMword, ARMword, int *, int *);
144static ARMword AddU16 (ARMword, ARMword, int *, int *);
145static ARMword AddS8 (ARMword, ARMword, int *, int *);
146static ARMword AddU8 (ARMword, ARMword, int *, int *);
147static ARMword Sub32 (ARMword, ARMword, int *, int *, ARMword);
148static ARMdword SubS32 (ARMdword, ARMdword, int *, int *);
149static ARMdword SubU32 (ARMdword, ARMdword, int *, int *);
150static ARMword SubS16 (ARMword, ARMword, int *, int *);
151static ARMword SubS8 (ARMword, ARMword, int *, int *);
152static ARMword SubU16 (ARMword, ARMword, int *, int *);
153static ARMword SubU8 (ARMword, ARMword, int *, int *);
154static unsigned char IwmmxtSaturateU8 (signed short, int *);
155static signed char IwmmxtSaturateS8 (signed short, int *);
156static unsigned short IwmmxtSaturateU16 (signed int, int *);
157static signed short IwmmxtSaturateS16 (signed int, int *);
158static unsigned long IwmmxtSaturateU32 (signed long long, int *);
159static signed long IwmmxtSaturateS32 (signed long long, int *);
160static ARMword Compute_Iwmmxt_Address (ARMul_State *, ARMword, int *);
161static ARMdword Iwmmxt_Load_Double_Word (ARMul_State *, ARMword);
162static ARMword Iwmmxt_Load_Word (ARMul_State *, ARMword);
163static ARMword Iwmmxt_Load_Half_Word (ARMul_State *, ARMword);
164static ARMword Iwmmxt_Load_Byte (ARMul_State *, ARMword);
165static void Iwmmxt_Store_Double_Word (ARMul_State *, ARMword, ARMdword);
166static void Iwmmxt_Store_Word (ARMul_State *, ARMword, ARMword);
167static void Iwmmxt_Store_Half_Word (ARMul_State *, ARMword, ARMword);
168static void Iwmmxt_Store_Byte (ARMul_State *, ARMword, ARMword);
169static int Process_Instruction (ARMul_State *, ARMword);
170
171static int TANDC (ARMul_State *, ARMword);
172static int TBCST (ARMul_State *, ARMword);
173static int TEXTRC (ARMul_State *, ARMword);
174static int TEXTRM (ARMul_State *, ARMword);
175static int TINSR (ARMul_State *, ARMword);
176static int TMCR (ARMul_State *, ARMword);
177static int TMCRR (ARMul_State *, ARMword);
178static int TMIA (ARMul_State *, ARMword);
179static int TMIAPH (ARMul_State *, ARMword);
180static int TMIAxy (ARMul_State *, ARMword);
181static int TMOVMSK (ARMul_State *, ARMword);
182static int TMRC (ARMul_State *, ARMword);
183static int TMRRC (ARMul_State *, ARMword);
184static int TORC (ARMul_State *, ARMword);
185static int WACC (ARMul_State *, ARMword);
186static int WADD (ARMul_State *, ARMword);
187static int WALIGNI (ARMword);
188static int WALIGNR (ARMul_State *, ARMword);
189static int WAND (ARMword);
190static int WANDN (ARMword);
191static int WAVG2 (ARMword);
192static int WCMPEQ (ARMul_State *, ARMword);
193static int WCMPGT (ARMul_State *, ARMword);
194static int WLDR (ARMul_State *, ARMword);
195static int WMAC (ARMword);
196static int WMADD (ARMword);
197static int WMAX (ARMul_State *, ARMword);
198static int WMIN (ARMul_State *, ARMword);
199static int WMUL (ARMword);
200static int WOR (ARMword);
201static int WPACK (ARMul_State *, ARMword);
202static int WROR (ARMul_State *, ARMword);
203static int WSAD (ARMword);
204static int WSHUFH (ARMword);
205static int WSLL (ARMul_State *, ARMword);
206static int WSRA (ARMul_State *, ARMword);
207static int WSRL (ARMul_State *, ARMword);
208static int WSTR (ARMul_State *, ARMword);
209static int WSUB (ARMul_State *, ARMword);
210static int WUNPCKEH (ARMul_State *, ARMword);
211static int WUNPCKEL (ARMul_State *, ARMword);
212static int WUNPCKIH (ARMul_State *, ARMword);
213static int WUNPCKIL (ARMul_State *, ARMword);
214static int WXOR (ARMword);
215\f
216/* This function does the work of adding two 32bit values
217 together, and calculating if a carry has occurred. */
218
219static ARMword
220Add32 (ARMword a1,
221 ARMword a2,
222 int * carry_ptr,
223 int * overflow_ptr,
224 ARMword sign_mask)
225{
226 ARMword result = (a1 + a2);
227 unsigned int uresult = (unsigned int) result;
228 unsigned int ua1 = (unsigned int) a1;
229
230 /* If (result == a1) and (a2 == 0),
231 or (result > a2) then we have no carry. */
232 * carry_ptr = ((uresult == ua1) ? (a2 != 0) : (uresult < ua1));
233
234 /* Overflow occurs when both arguments are the
235 same sign, but the result is a different sign. */
236 * overflow_ptr = ( ( (result & sign_mask) && !(a1 & sign_mask) && !(a2 & sign_mask))
237 || (!(result & sign_mask) && (a1 & sign_mask) && (a2 & sign_mask)));
454de2ee 238
0f026fd0
NC
239 return result;
240}
241
242static ARMdword
243AddS32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr)
244{
245 ARMdword result;
246 unsigned int uresult;
247 unsigned int ua1;
248
249 a1 = EXTEND32 (a1);
250 a2 = EXTEND32 (a2);
251
252 result = a1 + a2;
253 uresult = (unsigned int) result;
254 ua1 = (unsigned int) a1;
255
256 * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1));
257
258 * overflow_ptr = ( ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL))
259 || (!(result & 0x80000000ULL) && (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL)));
260
261 return result;
262}
263
264static ARMdword
265AddU32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr)
266{
267 ARMdword result;
268 unsigned int uresult;
269 unsigned int ua1;
270
271 a1 &= 0xffffffff;
272 a2 &= 0xffffffff;
273
274 result = a1 + a2;
275 uresult = (unsigned int) result;
276 ua1 = (unsigned int) a1;
277
278 * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1));
279
280 * overflow_ptr = ( ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL))
281 || (!(result & 0x80000000ULL) && (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL)));
282
283 return result;
284}
285
286static ARMword
287AddS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
288{
289 a1 = EXTEND16 (a1);
290 a2 = EXTEND16 (a2);
291
292 return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
293}
294
295static ARMword
296AddU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
297{
298 a1 &= 0xffff;
299 a2 &= 0xffff;
300
301 return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
302}
303
304static ARMword
305AddS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
306{
307 a1 = EXTEND8 (a1);
308 a2 = EXTEND8 (a2);
309
310 return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
311}
312
313static ARMword
314AddU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
315{
316 a1 &= 0xff;
317 a2 &= 0xff;
318
319 return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
320}
321
322static ARMword
323Sub32 (ARMword a1,
324 ARMword a2,
325 int * borrow_ptr,
326 int * overflow_ptr,
327 ARMword sign_mask)
328{
329 ARMword result = (a1 - a2);
330 unsigned int ua1 = (unsigned int) a1;
331 unsigned int ua2 = (unsigned int) a2;
332
333 /* A borrow occurs if a2 is (unsigned) larger than a1.
334 However the carry flag is *cleared* if a borrow occurs. */
335 * borrow_ptr = ! (ua2 > ua1);
336
337 /* Overflow occurs when a negative number is subtracted from a
338 positive number and the result is negative or a positive
339 number is subtracted from a negative number and the result is
340 positive. */
341 * overflow_ptr = ( (! (a1 & sign_mask) && (a2 & sign_mask) && (result & sign_mask))
342 || ((a1 & sign_mask) && ! (a2 & sign_mask) && ! (result & sign_mask)));
343
344 return result;
345}
346
347static ARMdword
348SubS32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr)
349{
350 ARMdword result;
351 unsigned int ua1;
352 unsigned int ua2;
353
354 a1 = EXTEND32 (a1);
355 a2 = EXTEND32 (a2);
356
357 result = a1 - a2;
358 ua1 = (unsigned int) a1;
359 ua2 = (unsigned int) a2;
360
361 * borrow_ptr = ! (ua2 > ua1);
362
363 * overflow_ptr = ( (! (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL) && (result & 0x80000000ULL))
364 || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL)));
365
366 return result;
367}
368
369static ARMword
370SubS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
371{
372 a1 = EXTEND16 (a1);
373 a2 = EXTEND16 (a2);
374
375 return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
376}
377
378static ARMword
379SubS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
380{
381 a1 = EXTEND8 (a1);
382 a2 = EXTEND8 (a2);
383
384 return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
385}
386
387static ARMword
388SubU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
389{
390 a1 &= 0xffff;
391 a2 &= 0xffff;
392
393 return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
394}
395
396static ARMword
397SubU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
398{
399 a1 &= 0xff;
400 a2 &= 0xff;
401
402 return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
403}
404
405static ARMdword
406SubU32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr)
407{
408 ARMdword result;
409 unsigned int ua1;
410 unsigned int ua2;
411
412 a1 &= 0xffffffff;
413 a2 &= 0xffffffff;
414
415 result = a1 - a2;
416 ua1 = (unsigned int) a1;
417 ua2 = (unsigned int) a2;
418
419 * borrow_ptr = ! (ua2 > ua1);
420
421 * overflow_ptr = ( (! (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL) && (result & 0x80000000ULL))
422 || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL)));
423
424 return result;
425}
426
427/* For the saturation. */
428
429static unsigned char
430IwmmxtSaturateU8 (signed short val, int * sat)
431{
432 unsigned char rv;
433
434 if (val < 0)
435 {
436 rv = 0;
437 *sat = 1;
438 }
439 else if (val > 0xff)
440 {
441 rv = 0xff;
442 *sat = 1;
443 }
444 else
445 {
446 rv = val & 0xff;
447 *sat = 0;
448 }
449 return rv;
450}
451
452static signed char
453IwmmxtSaturateS8 (signed short val, int * sat)
454{
455 signed char rv;
456
457 if (val < -0x80)
458 {
459 rv = -0x80;
460 *sat = 1;
461 }
462 else if (val > 0x7f)
463 {
464 rv = 0x7f;
465 *sat = 1;
466 }
467 else
468 {
469 rv = val & 0xff;
470 *sat = 0;
471 }
472 return rv;
473}
474
475static unsigned short
476IwmmxtSaturateU16 (signed int val, int * sat)
477{
478 unsigned short rv;
479
480 if (val < 0)
481 {
482 rv = 0;
483 *sat = 1;
484 }
485 else if (val > 0xffff)
486 {
487 rv = 0xffff;
488 *sat = 1;
489 }
490 else
491 {
492 rv = val & 0xffff;
493 *sat = 0;
494 }
495 return rv;
496}
497
498static signed short
499IwmmxtSaturateS16 (signed int val, int * sat)
500{
501 signed short rv;
454de2ee 502
0f026fd0
NC
503 if (val < -0x8000)
504 {
505 rv = - 0x8000;
506 *sat = 1;
507 }
508 else if (val > 0x7fff)
509 {
510 rv = 0x7fff;
511 *sat = 1;
512 }
513 else
514 {
515 rv = val & 0xffff;
516 *sat = 0;
517 }
518 return rv;
519}
520
521static unsigned long
522IwmmxtSaturateU32 (signed long long val, int * sat)
523{
524 unsigned long rv;
525
526 if (val < 0)
527 {
528 rv = 0;
529 *sat = 1;
530 }
531 else if (val > 0xffffffff)
532 {
533 rv = 0xffffffff;
534 *sat = 1;
535 }
536 else
537 {
538 rv = val & 0xffffffff;
539 *sat = 0;
540 }
541 return rv;
542}
543
544static signed long
545IwmmxtSaturateS32 (signed long long val, int * sat)
546{
547 signed long rv;
454de2ee 548
0f026fd0
NC
549 if (val < -0x80000000LL)
550 {
551 rv = -0x80000000;
552 *sat = 1;
553 }
554 else if (val > 0x7fffffff)
555 {
556 rv = 0x7fffffff;
557 *sat = 1;
558 }
559 else
560 {
561 rv = val & 0xffffffff;
562 *sat = 0;
563 }
564 return rv;
565}
566
567/* Intel(r) Wireless MMX(tm) technology Acessor functions. */
568
569unsigned
570IwmmxtLDC (ARMul_State * state ATTRIBUTE_UNUSED,
571 unsigned type ATTRIBUTE_UNUSED,
572 ARMword instr,
573 ARMword data)
574{
575 return ARMul_CANT;
576}
577
578unsigned
579IwmmxtSTC (ARMul_State * state ATTRIBUTE_UNUSED,
580 unsigned type ATTRIBUTE_UNUSED,
581 ARMword instr,
582 ARMword * data)
583{
584 return ARMul_CANT;
585}
586
587unsigned
588IwmmxtMRC (ARMul_State * state ATTRIBUTE_UNUSED,
589 unsigned type ATTRIBUTE_UNUSED,
590 ARMword instr,
591 ARMword * value)
592{
593 return ARMul_CANT;
594}
595
596unsigned
597IwmmxtMCR (ARMul_State * state ATTRIBUTE_UNUSED,
598 unsigned type ATTRIBUTE_UNUSED,
599 ARMword instr,
600 ARMword value)
601{
602 return ARMul_CANT;
603}
604
605unsigned
606IwmmxtCDP (ARMul_State * state, unsigned type, ARMword instr)
607{
608 return ARMul_CANT;
609}
610
611/* Intel(r) Wireless MMX(tm) technology instruction implementations. */
612
613static int
614TANDC (ARMul_State * state, ARMword instr)
615{
616 ARMword cpsr;
617
618 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
619 return ARMul_CANT;
620
621#ifdef DEBUG
622 fprintf (stderr, "tandc\n");
454de2ee 623#endif
0f026fd0
NC
624
625 /* The Rd field must be r15. */
626 if (BITS (12, 15) != 15)
627 return ARMul_CANT;
628
629 /* The CRn field must be r3. */
630 if (BITS (16, 19) != 3)
631 return ARMul_CANT;
632
633 /* The CRm field must be r0. */
634 if (BITS (0, 3) != 0)
635 return ARMul_CANT;
636
637 cpsr = ARMul_GetCPSR (state) & 0x0fffffff;
638
639 switch (BITS (22, 23))
640 {
641 case Bqual:
642 cpsr |= ( (wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 24, 27)
643 & wCBITS (wCASF, 20, 23) & wCBITS (wCASF, 16, 19)
644 & wCBITS (wCASF, 12, 15) & wCBITS (wCASF, 8, 11)
645 & wCBITS (wCASF, 4, 7) & wCBITS (wCASF, 0, 3)) << 28);
646 break;
647
648 case Hqual:
649 cpsr |= ( (wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 20, 23)
650 & wCBITS (wCASF, 12, 15) & wCBITS (wCASF, 4, 7)) << 28);
651 break;
652
653 case Wqual:
654 cpsr |= ((wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 12, 15)) << 28);
655 break;
656
657 default:
658 ARMul_UndefInstr (state, instr);
659 return ARMul_DONE;
660 }
454de2ee 661
0f026fd0
NC
662 ARMul_SetCPSR (state, cpsr);
663
664 return ARMul_DONE;
665}
666
667static int
668TBCST (ARMul_State * state, ARMword instr)
669{
670 ARMdword Rn;
671 int wRd;
672
673 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
674 return ARMul_CANT;
675
676#ifdef DEBUG
677 fprintf (stderr, "tbcst\n");
454de2ee 678#endif
0f026fd0
NC
679
680 Rn = state->Reg [BITS (12, 15)];
681 if (BITS (12, 15) == 15)
682 Rn &= 0xfffffffc;
683
684 wRd = BITS (16, 19);
685
686 switch (BITS (6, 7))
687 {
688 case Bqual:
689 Rn &= 0xff;
690 wR [wRd] = (Rn << 56) | (Rn << 48) | (Rn << 40) | (Rn << 32)
691 | (Rn << 24) | (Rn << 16) | (Rn << 8) | Rn;
692 break;
693
694 case Hqual:
695 Rn &= 0xffff;
696 wR [wRd] = (Rn << 48) | (Rn << 32) | (Rn << 16) | Rn;
697 break;
698
699 case Wqual:
700 Rn &= 0xffffffff;
701 wR [wRd] = (Rn << 32) | Rn;
702 break;
703
704 default:
705 ARMul_UndefInstr (state, instr);
706 break;
707 }
708
709 wC [wCon] |= WCON_MUP;
710 return ARMul_DONE;
711}
712
713static int
714TEXTRC (ARMul_State * state, ARMword instr)
715{
716 ARMword cpsr;
717 ARMword selector;
718
719 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
720 return ARMul_CANT;
721
722#ifdef DEBUG
723 fprintf (stderr, "textrc\n");
454de2ee 724#endif
0f026fd0
NC
725
726 /* The Rd field must be r15. */
727 if (BITS (12, 15) != 15)
728 return ARMul_CANT;
729
730 /* The CRn field must be r3. */
731 if (BITS (16, 19) != 3)
732 return ARMul_CANT;
733
734 /* The CRm field must be 0xxx. */
735 if (BIT (3) != 0)
736 return ARMul_CANT;
737
738 selector = BITS (0, 2);
739 cpsr = ARMul_GetCPSR (state) & 0x0fffffff;
740
741 switch (BITS (22, 23))
742 {
743 case Bqual: selector *= 4; break;
744 case Hqual: selector = ((selector & 3) * 8) + 4; break;
745 case Wqual: selector = ((selector & 1) * 16) + 12; break;
746
747 default:
748 ARMul_UndefInstr (state, instr);
749 return ARMul_DONE;
750 }
454de2ee 751
0f026fd0
NC
752 cpsr |= wCBITS (wCASF, selector, selector + 3) << 28;
753 ARMul_SetCPSR (state, cpsr);
754
755 return ARMul_DONE;
756}
757
758static int
759TEXTRM (ARMul_State * state, ARMword instr)
760{
761 ARMword Rd;
762 int offset;
763 int wRn;
764 int sign;
765
766 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
767 return ARMul_CANT;
768
769#ifdef DEBUG
770 fprintf (stderr, "textrm\n");
454de2ee 771#endif
0f026fd0
NC
772
773 wRn = BITS (16, 19);
774 sign = BIT (3);
775 offset = BITS (0, 2);
454de2ee 776
0f026fd0
NC
777 switch (BITS (22, 23))
778 {
779 case Bqual:
780 offset *= 8;
781 Rd = wRBITS (wRn, offset, offset + 7);
782 if (sign)
783 Rd = EXTEND8 (Rd);
784 break;
785
786 case Hqual:
787 offset = (offset & 3) * 16;
788 Rd = wRBITS (wRn, offset, offset + 15);
789 if (sign)
790 Rd = EXTEND16 (Rd);
791 break;
792
793 case Wqual:
794 offset = (offset & 1) * 32;
795 Rd = wRBITS (wRn, offset, offset + 31);
796 break;
797
798 default:
799 ARMul_UndefInstr (state, instr);
800 return ARMul_DONE;
801 }
802
803 if (BITS (12, 15) == 15)
804 ARMul_UndefInstr (state, instr);
805 else
806 state->Reg [BITS (12, 15)] = Rd;
807
808 return ARMul_DONE;
809}
810
811static int
812TINSR (ARMul_State * state, ARMword instr)
813{
814 ARMdword data;
815 ARMword offset;
816 int wRd;
817
818 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
819 return ARMul_CANT;
820
821#ifdef DEBUG
822 fprintf (stderr, "tinsr\n");
823#endif
824
825 wRd = BITS (16, 19);
826 data = state->Reg [BITS (12, 15)];
827 offset = BITS (0, 2);
828
829 switch (BITS (6, 7))
830 {
831 case Bqual:
832 data &= 0xff;
833 switch (offset)
834 {
835 case 0: wR [wRd] = data | (wRBITS (wRd, 8, 63) << 8); break;
836 case 1: wR [wRd] = wRBITS (wRd, 0, 7) | (data << 8) | (wRBITS (wRd, 16, 63) << 16); break;
837 case 2: wR [wRd] = wRBITS (wRd, 0, 15) | (data << 16) | (wRBITS (wRd, 24, 63) << 24); break;
838 case 3: wR [wRd] = wRBITS (wRd, 0, 23) | (data << 24) | (wRBITS (wRd, 32, 63) << 32); break;
839 case 4: wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32) | (wRBITS (wRd, 40, 63) << 40); break;
840 case 5: wR [wRd] = wRBITS (wRd, 0, 39) | (data << 40) | (wRBITS (wRd, 48, 63) << 48); break;
841 case 6: wR [wRd] = wRBITS (wRd, 0, 47) | (data << 48) | (wRBITS (wRd, 56, 63) << 56); break;
842 case 7: wR [wRd] = wRBITS (wRd, 0, 55) | (data << 56); break;
843 }
844 break;
845
846 case Hqual:
847 data &= 0xffff;
848
849 switch (offset & 3)
850 {
454de2ee 851 case 0: wR [wRd] = data | (wRBITS (wRd, 16, 63) << 16); break;
0f026fd0
NC
852 case 1: wR [wRd] = wRBITS (wRd, 0, 15) | (data << 16) | (wRBITS (wRd, 32, 63) << 32); break;
853 case 2: wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32) | (wRBITS (wRd, 48, 63) << 48); break;
854 case 3: wR [wRd] = wRBITS (wRd, 0, 47) | (data << 48); break;
855 }
856 break;
857
858 case Wqual:
859 if (offset & 1)
860 wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32);
861 else
862 wR [wRd] = (wRBITS (wRd, 32, 63) << 32) | data;
863 break;
864
865 default:
866 ARMul_UndefInstr (state, instr);
867 break;
868 }
869
870 wC [wCon] |= WCON_MUP;
871 return ARMul_DONE;
872}
873
874static int
875TMCR (ARMul_State * state, ARMword instr)
876{
877 ARMword val;
878 int wCreg;
879
880 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
881 return ARMul_CANT;
882
883#ifdef DEBUG
884 fprintf (stderr, "tmcr\n");
454de2ee 885#endif
0f026fd0
NC
886
887 if (BITS (0, 3) != 0)
888 return ARMul_CANT;
889
890 val = state->Reg [BITS (12, 15)];
891 if (BITS (12, 15) == 15)
892 val &= 0xfffffffc;
893
894 wCreg = BITS (16, 19);
895
896 switch (wCreg)
897 {
898 case wCID:
899 /* The wCID register is read only. */
900 break;
901
902 case wCon:
903 /* Writing to the MUP or CUP bits clears them. */
904 wC [wCon] &= ~ (val & 0x3);
905 break;
454de2ee 906
0f026fd0
NC
907 case wCSSF:
908 /* Only the bottom 8 bits can be written to.
909 The higher bits write as zero. */
910 wC [wCSSF] = (val & 0xff);
911 wC [wCon] |= WCON_CUP;
912 break;
454de2ee 913
0f026fd0
NC
914 default:
915 wC [wCreg] = val;
916 wC [wCon] |= WCON_CUP;
917 break;
918 }
919
920 return ARMul_DONE;
921}
922
923static int
924TMCRR (ARMul_State * state, ARMword instr)
925{
926 ARMdword RdHi = state->Reg [BITS (16, 19)];
927 ARMword RdLo = state->Reg [BITS (12, 15)];
928
929 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
930 return ARMul_CANT;
931
932#ifdef DEBUG
933 fprintf (stderr, "tmcrr\n");
454de2ee 934#endif
0f026fd0
NC
935
936 if ((BITS (16, 19) == 15) || (BITS (12, 15) == 15))
937 return ARMul_CANT;
938
939 wR [BITS (0, 3)] = (RdHi << 32) | RdLo;
940
941 wC [wCon] |= WCON_MUP;
942
943 return ARMul_DONE;
944}
945
946static int
947TMIA (ARMul_State * state, ARMword instr)
948{
949 signed long long a, b;
950
951 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
952 return ARMul_CANT;
953
954#ifdef DEBUG
955 fprintf (stderr, "tmia\n");
454de2ee 956#endif
0f026fd0
NC
957
958 if ((BITS (0, 3) == 15) || (BITS (12, 15) == 15))
959 {
960 ARMul_UndefInstr (state, instr);
961 return ARMul_DONE;
962 }
963
964 a = state->Reg [BITS (0, 3)];
965 b = state->Reg [BITS (12, 15)];
966
967 a = EXTEND32 (a);
968 b = EXTEND32 (b);
969
970 wR [BITS (5, 8)] += a * b;
971 wC [wCon] |= WCON_MUP;
972
973 return ARMul_DONE;
974}
975
976static int
977TMIAPH (ARMul_State * state, ARMword instr)
978{
979 signed long a, b, result;
980 signed long long r;
981 ARMword Rm = state->Reg [BITS (0, 3)];
982 ARMword Rs = state->Reg [BITS (12, 15)];
454de2ee 983
0f026fd0
NC
984 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
985 return ARMul_CANT;
986
987#ifdef DEBUG
988 fprintf (stderr, "tmiaph\n");
454de2ee 989#endif
0f026fd0
NC
990
991 if (BITS (0, 3) == 15 || BITS (12, 15) == 15)
992 {
993 ARMul_UndefInstr (state, instr);
994 return ARMul_DONE;
995 }
996
997 a = SUBSTR (Rs, ARMword, 16, 31);
998 b = SUBSTR (Rm, ARMword, 16, 31);
999
1000 a = EXTEND16 (a);
1001 b = EXTEND16 (b);
1002
1003 result = a * b;
1004
1005 r = result;
1006 r = EXTEND32 (r);
454de2ee 1007
0f026fd0
NC
1008 wR [BITS (5, 8)] += r;
1009
1010 a = SUBSTR (Rs, ARMword, 0, 15);
1011 b = SUBSTR (Rm, ARMword, 0, 15);
1012
1013 a = EXTEND16 (a);
1014 b = EXTEND16 (b);
1015
1016 result = a * b;
1017
1018 r = result;
1019 r = EXTEND32 (r);
454de2ee 1020
0f026fd0
NC
1021 wR [BITS (5, 8)] += r;
1022 wC [wCon] |= WCON_MUP;
1023
1024 return ARMul_DONE;
1025}
1026
1027static int
1028TMIAxy (ARMul_State * state, ARMword instr)
1029{
1030 ARMword Rm;
1031 ARMword Rs;
1032 long long temp;
454de2ee 1033
0f026fd0
NC
1034 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1035 return ARMul_CANT;
1036
1037#ifdef DEBUG
1038 fprintf (stderr, "tmiaxy\n");
454de2ee 1039#endif
0f026fd0
NC
1040
1041 if (BITS (0, 3) == 15 || BITS (12, 15) == 15)
1042 {
1043 ARMul_UndefInstr (state, instr);
1044 return ARMul_DONE;
1045 }
1046
1047 Rm = state->Reg [BITS (0, 3)];
1048 if (BIT (17))
1049 Rm >>= 16;
1050 else
1051 Rm &= 0xffff;
1052
1053 Rs = state->Reg [BITS (12, 15)];
1054 if (BIT (16))
1055 Rs >>= 16;
1056 else
1057 Rs &= 0xffff;
1058
1059 if (Rm & (1 << 15))
1060 Rm -= 1 << 16;
1061
1062 if (Rs & (1 << 15))
1063 Rs -= 1 << 16;
1064
1065 Rm *= Rs;
1066 temp = Rm;
1067
1068 if (temp & (1 << 31))
1069 temp -= 1ULL << 32;
1070
1071 wR [BITS (5, 8)] += temp;
1072 wC [wCon] |= WCON_MUP;
1073
1074 return ARMul_DONE;
1075}
1076
1077static int
1078TMOVMSK (ARMul_State * state, ARMword instr)
1079{
1080 ARMdword result;
1081 int wRn;
1082
1083 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1084 return ARMul_CANT;
1085
1086#ifdef DEBUG
1087 fprintf (stderr, "tmovmsk\n");
454de2ee 1088#endif
0f026fd0
NC
1089
1090 /* The CRm field must be r0. */
1091 if (BITS (0, 3) != 0)
1092 return ARMul_CANT;
1093
1094 wRn = BITS (16, 19);
1095
1096 switch (BITS (22, 23))
1097 {
1098 case Bqual:
1099 result = ( (wRBITS (wRn, 63, 63) << 7)
1100 | (wRBITS (wRn, 55, 55) << 6)
1101 | (wRBITS (wRn, 47, 47) << 5)
1102 | (wRBITS (wRn, 39, 39) << 4)
1103 | (wRBITS (wRn, 31, 31) << 3)
1104 | (wRBITS (wRn, 23, 23) << 2)
1105 | (wRBITS (wRn, 15, 15) << 1)
1106 | (wRBITS (wRn, 7, 7) << 0));
1107 break;
1108
1109 case Hqual:
1110 result = ( (wRBITS (wRn, 63, 63) << 3)
1111 | (wRBITS (wRn, 47, 47) << 2)
1112 | (wRBITS (wRn, 31, 31) << 1)
1113 | (wRBITS (wRn, 15, 15) << 0));
1114 break;
1115
1116 case Wqual:
1117 result = (wRBITS (wRn, 63, 63) << 1) | wRBITS (wRn, 31, 31);
1118 break;
1119
1120 default:
1121 ARMul_UndefInstr (state, instr);
1122 return ARMul_DONE;
1123 }
1124
1125 state->Reg [BITS (12, 15)] = result;
1126
1127 return ARMul_DONE;
1128}
1129
1130static int
1131TMRC (ARMul_State * state, ARMword instr)
1132{
1133 int reg = BITS (12, 15);
1134
1135 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1136 return ARMul_CANT;
1137
1138#ifdef DEBUG
1139 fprintf (stderr, "tmrc\n");
454de2ee 1140#endif
0f026fd0
NC
1141
1142 if (BITS (0, 3) != 0)
1143 return ARMul_CANT;
1144
1145 if (reg == 15)
1146 ARMul_UndefInstr (state, instr);
1147 else
1148 state->Reg [reg] = wC [BITS (16, 19)];
1149
1150 return ARMul_DONE;
1151}
1152
1153static int
1154TMRRC (ARMul_State * state, ARMword instr)
1155{
1156 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1157 return ARMul_CANT;
1158
1159#ifdef DEBUG
1160 fprintf (stderr, "tmrrc\n");
454de2ee 1161#endif
0f026fd0
NC
1162
1163 if ((BITS (16, 19) == 15) || (BITS (12, 15) == 15) || (BITS (4, 11) != 0))
1164 ARMul_UndefInstr (state, instr);
1165 else
1166 {
1167 state->Reg [BITS (16, 19)] = wRBITS (BITS (0, 3), 32, 63);
1168 state->Reg [BITS (12, 15)] = wRBITS (BITS (0, 3), 0, 31);
1169 }
1170
1171 return ARMul_DONE;
1172}
1173
1174static int
1175TORC (ARMul_State * state, ARMword instr)
1176{
1177 ARMword cpsr = ARMul_GetCPSR (state);
1178
1179 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1180 return ARMul_CANT;
1181
1182#ifdef DEBUG
1183 fprintf (stderr, "torc\n");
454de2ee 1184#endif
0f026fd0
NC
1185
1186 /* The Rd field must be r15. */
1187 if (BITS (12, 15) != 15)
1188 return ARMul_CANT;
454de2ee 1189
0f026fd0
NC
1190 /* The CRn field must be r3. */
1191 if (BITS (16, 19) != 3)
1192 return ARMul_CANT;
454de2ee 1193
0f026fd0
NC
1194 /* The CRm field must be r0. */
1195 if (BITS (0, 3) != 0)
1196 return ARMul_CANT;
1197
1198 cpsr &= 0x0fffffff;
1199
1200 switch (BITS (22, 23))
1201 {
1202 case Bqual:
1203 cpsr |= ( (wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 24, 27)
1204 | wCBITS (wCASF, 20, 23) | wCBITS (wCASF, 16, 19)
1205 | wCBITS (wCASF, 12, 15) | wCBITS (wCASF, 8, 11)
1206 | wCBITS (wCASF, 4, 7) | wCBITS (wCASF, 0, 3)) << 28);
1207 break;
1208
1209 case Hqual:
1210 cpsr |= ( (wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 20, 23)
1211 | wCBITS (wCASF, 12, 15) | wCBITS (wCASF, 4, 7)) << 28);
1212 break;
1213
1214 case Wqual:
1215 cpsr |= ((wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 12, 15)) << 28);
1216 break;
1217
1218 default:
1219 ARMul_UndefInstr (state, instr);
1220 return ARMul_DONE;
1221 }
454de2ee 1222
0f026fd0
NC
1223 ARMul_SetCPSR (state, cpsr);
1224
1225 return ARMul_DONE;
1226}
1227
1228static int
1229WACC (ARMul_State * state, ARMword instr)
1230{
1231 int wRn;
1232
1233 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1234 return ARMul_CANT;
1235
1236#ifdef DEBUG
1237 fprintf (stderr, "wacc\n");
454de2ee 1238#endif
0f026fd0
NC
1239
1240 wRn = BITS (16, 19);
1241
1242 switch (BITS (22, 23))
1243 {
1244 case Bqual:
1245 wR [BITS (12, 15)] =
1246 wRBITS (wRn, 56, 63) + wRBITS (wRn, 48, 55)
1247 + wRBITS (wRn, 40, 47) + wRBITS (wRn, 32, 39)
1248 + wRBITS (wRn, 24, 31) + wRBITS (wRn, 16, 23)
1249 + wRBITS (wRn, 8, 15) + wRBITS (wRn, 0, 7);
1250 break;
1251
1252 case Hqual:
1253 wR [BITS (12, 15)] =
1254 wRBITS (wRn, 48, 63) + wRBITS (wRn, 32, 47)
1255 + wRBITS (wRn, 16, 31) + wRBITS (wRn, 0, 15);
1256 break;
1257
1258 case Wqual:
1259 wR [BITS (12, 15)] = wRBITS (wRn, 32, 63) + wRBITS (wRn, 0, 31);
1260 break;
1261
1262 default:
1263 ARMul_UndefInstr (state, instr);
1264 break;
1265 }
1266
1267 wC [wCon] |= WCON_MUP;
1268 return ARMul_DONE;
1269}
1270
1271static int
1272WADD (ARMul_State * state, ARMword instr)
1273{
1274 ARMdword r = 0;
1275 ARMdword x;
1276 ARMdword s;
1277 ARMword psr = 0;
1278 int i;
1279 int carry;
1280 int overflow;
1281 int satrv[8];
1282
1283 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1284 return ARMul_CANT;
1285
1286#ifdef DEBUG
1287 fprintf (stderr, "wadd\n");
454de2ee 1288#endif
0f026fd0
NC
1289
1290 /* Add two numbers using the specified function,
1291 leaving setting the carry bit as required. */
1292#define ADDx(x, y, m, f) \
1293 (*f) (wRBITS (BITS (16, 19), (x), (y)) & (m), \
1294 wRBITS (BITS ( 0, 3), (x), (y)) & (m), \
1295 & carry, & overflow)
1296
1297 switch (BITS (22, 23))
1298 {
1299 case Bqual:
1300 for (i = 0; i < 8; i++)
1301 {
1302 switch (BITS (20, 21))
1303 {
1304 case NoSaturation:
1305 s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddS8);
1306 satrv [BITIDX8 (i)] = 0;
1307 r |= (s & 0xff) << (i * 8);
1308 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
1309 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
1310 SIMD8_SET (psr, carry, SIMD_CBIT, i);
1311 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
1312 break;
1313
1314 case UnsignedSaturation:
1315 s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddU8);
1316 x = IwmmxtSaturateU8 (s, satrv + BITIDX8 (i));
1317 r |= (x & 0xff) << (i * 8);
1318 SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
1319 SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
1320 if (! satrv [BITIDX8 (i)])
1321 {
1322 SIMD8_SET (psr, carry, SIMD_CBIT, i);
1323 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
1324 }
1325 break;
1326
1327 case SignedSaturation:
1328 s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddS8);
1329 x = IwmmxtSaturateS8 (s, satrv + BITIDX8 (i));
1330 r |= (x & 0xff) << (i * 8);
1331 SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
1332 SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
1333 if (! satrv [BITIDX8 (i)])
1334 {
1335 SIMD8_SET (psr, carry, SIMD_CBIT, i);
1336 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
1337 }
1338 break;
1339
1340 default:
1341 ARMul_UndefInstr (state, instr);
1342 return ARMul_DONE;
1343 }
1344 }
1345 break;
1346
1347 case Hqual:
1348 satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
1349
1350 for (i = 0; i < 4; i++)
1351 {
1352 switch (BITS (20, 21))
1353 {
1354 case NoSaturation:
1355 s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddS16);
1356 satrv [BITIDX16 (i)] = 0;
1357 r |= (s & 0xffff) << (i * 16);
1358 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
1359 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
1360 SIMD16_SET (psr, carry, SIMD_CBIT, i);
1361 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
1362 break;
1363
1364 case UnsignedSaturation:
1365 s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddU16);
1366 x = IwmmxtSaturateU16 (s, satrv + BITIDX16 (i));
1367 r |= (x & 0xffff) << (i * 16);
1368 SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
1369 SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
1370 if (! satrv [BITIDX16 (i)])
1371 {
1372 SIMD16_SET (psr, carry, SIMD_CBIT, i);
1373 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
1374 }
1375 break;
1376
1377 case SignedSaturation:
1378 s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddS16);
1379 x = IwmmxtSaturateS16 (s, satrv + BITIDX16 (i));
1380 r |= (x & 0xffff) << (i * 16);
1381 SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
1382 SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
1383 if (! satrv [BITIDX16 (i)])
1384 {
1385 SIMD16_SET (psr, carry, SIMD_CBIT, i);
1386 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
1387 }
1388 break;
1389
1390 default:
1391 ARMul_UndefInstr (state, instr);
1392 return ARMul_DONE;
1393 }
1394 }
1395 break;
1396
1397 case Wqual:
1398 satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
1399
1400 for (i = 0; i < 2; i++)
1401 {
1402 switch (BITS (20, 21))
1403 {
1404 case NoSaturation:
1405 s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddS32);
1406 satrv [BITIDX32 (i)] = 0;
1407 r |= (s & 0xffffffff) << (i * 32);
1408 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
1409 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
1410 SIMD32_SET (psr, carry, SIMD_CBIT, i);
1411 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
1412 break;
1413
1414 case UnsignedSaturation:
1415 s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddU32);
1416 x = IwmmxtSaturateU32 (s, satrv + BITIDX32 (i));
1417 r |= (x & 0xffffffff) << (i * 32);
1418 SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
1419 SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
1420 if (! satrv [BITIDX32 (i)])
1421 {
1422 SIMD32_SET (psr, carry, SIMD_CBIT, i);
1423 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
1424 }
1425 break;
1426
1427 case SignedSaturation:
1428 s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddS32);
1429 x = IwmmxtSaturateS32 (s, satrv + BITIDX32 (i));
1430 r |= (x & 0xffffffff) << (i * 32);
1431 SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
1432 SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
1433 if (! satrv [BITIDX32 (i)])
1434 {
1435 SIMD32_SET (psr, carry, SIMD_CBIT, i);
1436 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
1437 }
1438 break;
1439
1440 default:
1441 ARMul_UndefInstr (state, instr);
1442 return ARMul_DONE;
1443 }
1444 }
1445 break;
1446
1447 default:
1448 ARMul_UndefInstr (state, instr);
1449 return ARMul_DONE;
1450 }
1451
1452 wC [wCASF] = psr;
1453 wR [BITS (12, 15)] = r;
1454 wC [wCon] |= (WCON_MUP | WCON_CUP);
1455
1456 SET_wCSSFvec (satrv);
454de2ee 1457
0f026fd0
NC
1458#undef ADDx
1459
1460 return ARMul_DONE;
1461}
1462
1463static int
1464WALIGNI (ARMword instr)
1465{
1466 int shift = BITS (20, 22) * 8;
1467
1468 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1469 return ARMul_CANT;
1470
1471#ifdef DEBUG
1472 fprintf (stderr, "waligni\n");
454de2ee 1473#endif
0f026fd0
NC
1474
1475 if (shift)
1476 wR [BITS (12, 15)] =
1477 wRBITS (BITS (16, 19), shift, 63)
1478 | (wRBITS (BITS (0, 3), 0, shift) << ((64 - shift)));
1479 else
1480 wR [BITS (12, 15)] = wR [BITS (16, 19)];
454de2ee 1481
0f026fd0
NC
1482 wC [wCon] |= WCON_MUP;
1483 return ARMul_DONE;
1484}
1485
1486static int
1487WALIGNR (ARMul_State * state, ARMword instr)
1488{
1489 int shift = (wC [BITS (20, 21) + 8] & 0x7) * 8;
1490
1491 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1492 return ARMul_CANT;
1493
1494#ifdef DEBUG
1495 fprintf (stderr, "walignr\n");
454de2ee 1496#endif
0f026fd0
NC
1497
1498 if (shift)
1499 wR [BITS (12, 15)] =
1500 wRBITS (BITS (16, 19), shift, 63)
1501 | (wRBITS (BITS (0, 3), 0, shift) << ((64 - shift)));
1502 else
1503 wR [BITS (12, 15)] = wR [BITS (16, 19)];
1504
1505 wC [wCon] |= WCON_MUP;
1506 return ARMul_DONE;
1507}
1508
1509static int
1510WAND (ARMword instr)
1511{
1512 ARMdword result;
1513 ARMword psr = 0;
1514
1515 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1516 return ARMul_CANT;
1517
1518#ifdef DEBUG
1519 fprintf (stderr, "wand\n");
454de2ee 1520#endif
0f026fd0
NC
1521
1522 result = wR [BITS (16, 19)] & wR [BITS (0, 3)];
1523 wR [BITS (12, 15)] = result;
1524
1525 SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
1526 SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
454de2ee 1527
0f026fd0
NC
1528 wC [wCASF] = psr;
1529 wC [wCon] |= (WCON_CUP | WCON_MUP);
1530
1531 return ARMul_DONE;
1532}
1533
1534static int
1535WANDN (ARMword instr)
1536{
1537 ARMdword result;
1538 ARMword psr = 0;
1539
1540 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1541 return ARMul_CANT;
1542
1543#ifdef DEBUG
1544 fprintf (stderr, "wandn\n");
454de2ee 1545#endif
0f026fd0
NC
1546
1547 result = wR [BITS (16, 19)] & ~ wR [BITS (0, 3)];
1548 wR [BITS (12, 15)] = result;
1549
1550 SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
1551 SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
454de2ee 1552
0f026fd0
NC
1553 wC [wCASF] = psr;
1554 wC [wCon] |= (WCON_CUP | WCON_MUP);
1555
1556 return ARMul_DONE;
1557}
1558
1559static int
1560WAVG2 (ARMword instr)
1561{
1562 ARMdword r = 0;
1563 ARMword psr = 0;
1564 ARMdword s;
1565 int i;
1566 int round = BIT (20) ? 1 : 0;
1567
1568 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1569 return ARMul_CANT;
1570
1571#ifdef DEBUG
1572 fprintf (stderr, "wavg2\n");
454de2ee 1573#endif
0f026fd0
NC
1574
1575#define AVG2x(x, y, m) (((wRBITS (BITS (16, 19), (x), (y)) & (m)) \
1576 + (wRBITS (BITS ( 0, 3), (x), (y)) & (m)) \
1577 + round) / 2)
1578
1579 if (BIT (22))
1580 {
1581 for (i = 0; i < 4; i++)
1582 {
1583 s = AVG2x ((i * 16), (i * 16) + 15, 0xffff) & 0xffff;
1584 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
1585 r |= s << (i * 16);
1586 }
1587 }
1588 else
1589 {
1590 for (i = 0; i < 8; i++)
1591 {
1592 s = AVG2x ((i * 8), (i * 8) + 7, 0xff) & 0xff;
1593 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
1594 r |= s << (i * 8);
1595 }
1596 }
1597
1598 wR [BITS (12, 15)] = r;
1599 wC [wCASF] = psr;
1600 wC [wCon] |= (WCON_CUP | WCON_MUP);
1601
1602 return ARMul_DONE;
1603}
1604
1605static int
1606WCMPEQ (ARMul_State * state, ARMword instr)
1607{
1608 ARMdword r = 0;
1609 ARMword psr = 0;
1610 ARMdword s;
1611 int i;
1612
1613 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1614 return ARMul_CANT;
1615
1616#ifdef DEBUG
1617 fprintf (stderr, "wcmpeq\n");
454de2ee 1618#endif
0f026fd0
NC
1619
1620 switch (BITS (22, 23))
1621 {
1622 case Bqual:
1623 for (i = 0; i < 8; i++)
1624 {
1625 s = wRBYTE (BITS (16, 19), i) == wRBYTE (BITS (0, 3), i) ? 0xff : 0;
1626 r |= s << (i * 8);
1627 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
1628 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
1629 }
1630 break;
1631
1632 case Hqual:
1633 for (i = 0; i < 4; i++)
1634 {
1635 s = wRHALF (BITS (16, 19), i) == wRHALF (BITS (0, 3), i) ? 0xffff : 0;
1636 r |= s << (i * 16);
1637 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
1638 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
1639 }
1640 break;
1641
1642 case Wqual:
1643 for (i = 0; i < 2; i++)
1644 {
1645 s = wRWORD (BITS (16, 19), i) == wRWORD (BITS (0, 3), i) ? 0xffffffff : 0;
1646 r |= s << (i * 32);
1647 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
1648 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
1649 }
1650 break;
1651
1652 default:
1653 ARMul_UndefInstr (state, instr);
1654 return ARMul_DONE;
1655 }
1656
1657 wC [wCASF] = psr;
1658 wR [BITS (12, 15)] = r;
1659 wC [wCon] |= (WCON_CUP | WCON_MUP);
1660
1661 return ARMul_DONE;
1662}
1663
1664static int
1665WCMPGT (ARMul_State * state, ARMword instr)
1666{
1667 ARMdword r = 0;
1668 ARMword psr = 0;
1669 ARMdword s;
1670 int i;
1671
1672 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1673 return ARMul_CANT;
1674
1675#ifdef DEBUG
1676 fprintf (stderr, "wcmpgt\n");
454de2ee 1677#endif
0f026fd0
NC
1678
1679 switch (BITS (22, 23))
1680 {
1681 case Bqual:
1682 if (BIT (21))
1683 {
1684 /* Use a signed comparison. */
1685 for (i = 0; i < 8; i++)
1686 {
1687 signed char a, b;
454de2ee 1688
0f026fd0
NC
1689 a = wRBYTE (BITS (16, 19), i);
1690 b = wRBYTE (BITS (0, 3), i);
1691
1692 s = (a > b) ? 0xff : 0;
1693 r |= s << (i * 8);
1694 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
1695 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
1696 }
1697 }
1698 else
1699 {
1700 for (i = 0; i < 8; i++)
1701 {
1702 s = (wRBYTE (BITS (16, 19), i) > wRBYTE (BITS (0, 3), i))
1703 ? 0xff : 0;
1704 r |= s << (i * 8);
1705 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
1706 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
1707 }
1708 }
1709 break;
1710
1711 case Hqual:
1712 if (BIT (21))
1713 {
1714 for (i = 0; i < 4; i++)
1715 {
1716 signed int a, b;
1717
1718 a = wRHALF (BITS (16, 19), i);
1719 a = EXTEND16 (a);
1720
1721 b = wRHALF (BITS (0, 3), i);
1722 b = EXTEND16 (b);
1723
1724 s = (a > b) ? 0xffff : 0;
1725 r |= s << (i * 16);
1726 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
1727 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
1728 }
1729 }
1730 else
1731 {
1732 for (i = 0; i < 4; i++)
1733 {
1734 s = (wRHALF (BITS (16, 19), i) > wRHALF (BITS (0, 3), i))
1735 ? 0xffff : 0;
1736 r |= s << (i * 16);
1737 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
1738 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
1739 }
1740 }
1741 break;
1742
1743 case Wqual:
1744 if (BIT (21))
1745 {
1746 for (i = 0; i < 2; i++)
1747 {
1748 signed long a, b;
1749
161fc452
NC
1750 a = EXTEND32 (wRWORD (BITS (16, 19), i));
1751 b = EXTEND32 (wRWORD (BITS (0, 3), i));
0f026fd0
NC
1752
1753 s = (a > b) ? 0xffffffff : 0;
1754 r |= s << (i * 32);
161fc452 1755
0f026fd0
NC
1756 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
1757 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
1758 }
1759 }
1760 else
1761 {
1762 for (i = 0; i < 2; i++)
1763 {
1764 s = (wRWORD (BITS (16, 19), i) > wRWORD (BITS (0, 3), i))
1765 ? 0xffffffff : 0;
1766 r |= s << (i * 32);
1767 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
1768 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
1769 }
1770 }
1771 break;
1772
1773 default:
1774 ARMul_UndefInstr (state, instr);
1775 return ARMul_DONE;
1776 }
1777
1778 wC [wCASF] = psr;
1779 wR [BITS (12, 15)] = r;
1780 wC [wCon] |= (WCON_CUP | WCON_MUP);
1781
1782 return ARMul_DONE;
1783}
1784
1785static ARMword
1786Compute_Iwmmxt_Address (ARMul_State * state, ARMword instr, int * pFailed)
1787{
1788 ARMword Rn;
1789 ARMword addr;
1790 ARMword offset;
1791 ARMword multiplier;
1792
1793 * pFailed = 0;
1794 Rn = BITS (16, 19);
1795 addr = state->Reg [Rn];
1796 offset = BITS (0, 7);
1797 multiplier = BIT (8) ? 4 : 1;
1798
1799 if (BIT (24)) /* P */
1800 {
1801 /* Pre Indexed Addressing. */
1802 if (BIT (23))
1803 addr += offset * multiplier;
1804 else
1805 addr -= offset * multiplier;
1806
1807 /* Immediate Pre-Indexed. */
1808 if (BIT (21)) /* W */
1809 {
1810 if (Rn == 15)
1811 {
1812 /* Writeback into R15 is UNPREDICTABLE. */
1813#ifdef DEBUG
1814 fprintf (stderr, "iWMMXt: writeback into r15\n");
1815#endif
1816 * pFailed = 1;
1817 }
1818 else
1819 state->Reg [Rn] = addr;
1820 }
1821 }
1822 else
1823 {
1824 /* Post Indexed Addressing. */
1825 if (BIT (21)) /* W */
1826 {
1827 /* Handle the write back of the final address. */
1828 if (Rn == 15)
1829 {
1830 /* Writeback into R15 is UNPREDICTABLE. */
1831#ifdef DEBUG
1832 fprintf (stderr, "iWMMXt: writeback into r15\n");
454de2ee 1833#endif
0f026fd0
NC
1834 * pFailed = 1;
1835 }
1836 else
1837 {
1838 ARMword increment;
1839
1840 if (BIT (23))
1841 increment = offset * multiplier;
1842 else
1843 increment = - (offset * multiplier);
1844
1845 state->Reg [Rn] = addr + increment;
1846 }
1847 }
1848 else
1849 {
1850 /* P == 0, W == 0, U == 0 is UNPREDICTABLE. */
1851 if (BIT (23) == 0)
1852 {
1853#ifdef DEBUG
1854 fprintf (stderr, "iWMMXt: undefined addressing mode\n");
454de2ee 1855#endif
0f026fd0
NC
1856 * pFailed = 1;
1857 }
1858 }
1859 }
1860
1861 return addr;
1862}
1863
1864static ARMdword
1865Iwmmxt_Load_Double_Word (ARMul_State * state, ARMword address)
1866{
1867 ARMdword value;
454de2ee 1868
0f026fd0
NC
1869 /* The address must be aligned on a 8 byte boundary. */
1870 if (address & 0x7)
1871 {
1872 fprintf (stderr, "iWMMXt: At addr 0x%x: Unaligned double word load from 0x%x\n",
1873 (state->Reg[15] - 8) & ~0x3, address);
1874#ifdef DEBUG
1875#endif
1876 /* No need to check for alignment traps. An unaligned
1877 double word load with alignment trapping disabled is
1878 UNPREDICTABLE. */
1879 ARMul_Abort (state, ARMul_DataAbortV);
1880 }
1881
1882 /* Load the words. */
1883 if (! state->bigendSig)
1884 {
1885 value = ARMul_LoadWordN (state, address + 4);
1886 value <<= 32;
1887 value |= ARMul_LoadWordN (state, address);
1888 }
1889 else
1890 {
1891 value = ARMul_LoadWordN (state, address);
1892 value <<= 32;
1893 value |= ARMul_LoadWordN (state, address + 4);
1894 }
1895
1896 /* Check for data aborts. */
1897 if (state->Aborted)
1898 ARMul_Abort (state, ARMul_DataAbortV);
1899 else
1900 ARMul_Icycles (state, 2, 0L);
1901
1902 return value;
1903}
1904
1905static ARMword
1906Iwmmxt_Load_Word (ARMul_State * state, ARMword address)
1907{
1908 ARMword value;
1909
1910 /* Check for a misaligned address. */
1911 if (address & 3)
1912 {
1913 if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
1914 ARMul_Abort (state, ARMul_DataAbortV);
1915 else
1916 address &= ~ 3;
1917 }
454de2ee 1918
0f026fd0
NC
1919 value = ARMul_LoadWordN (state, address);
1920
1921 if (state->Aborted)
1922 ARMul_Abort (state, ARMul_DataAbortV);
1923 else
1924 ARMul_Icycles (state, 1, 0L);
1925
1926 return value;
1927}
1928
1929static ARMword
1930Iwmmxt_Load_Half_Word (ARMul_State * state, ARMword address)
1931{
1932 ARMword value;
1933
1934 /* Check for a misaligned address. */
1935 if (address & 1)
1936 {
1937 if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
1938 ARMul_Abort (state, ARMul_DataAbortV);
1939 else
1940 address &= ~ 1;
1941 }
1942
1943 value = ARMul_LoadHalfWord (state, address);
1944
1945 if (state->Aborted)
1946 ARMul_Abort (state, ARMul_DataAbortV);
1947 else
1948 ARMul_Icycles (state, 1, 0L);
1949
1950 return value;
1951}
1952
1953static ARMword
1954Iwmmxt_Load_Byte (ARMul_State * state, ARMword address)
1955{
1956 ARMword value;
1957
1958 value = ARMul_LoadByte (state, address);
1959
1960 if (state->Aborted)
1961 ARMul_Abort (state, ARMul_DataAbortV);
1962 else
1963 ARMul_Icycles (state, 1, 0L);
1964
1965 return value;
1966}
1967
1968static void
1969Iwmmxt_Store_Double_Word (ARMul_State * state, ARMword address, ARMdword value)
1970{
1971 /* The address must be aligned on a 8 byte boundary. */
1972 if (address & 0x7)
1973 {
1974 fprintf (stderr, "iWMMXt: At addr 0x%x: Unaligned double word store to 0x%x\n",
1975 (state->Reg[15] - 8) & ~0x3, address);
1976#ifdef DEBUG
1977#endif
1978 /* No need to check for alignment traps. An unaligned
1979 double word store with alignment trapping disabled is
1980 UNPREDICTABLE. */
1981 ARMul_Abort (state, ARMul_DataAbortV);
1982 }
1983
1984 /* Store the words. */
1985 if (! state->bigendSig)
1986 {
1987 ARMul_StoreWordN (state, address, value);
1988 ARMul_StoreWordN (state, address + 4, value >> 32);
1989 }
1990 else
1991 {
1992 ARMul_StoreWordN (state, address + 4, value);
1993 ARMul_StoreWordN (state, address, value >> 32);
1994 }
1995
1996 /* Check for data aborts. */
1997 if (state->Aborted)
1998 ARMul_Abort (state, ARMul_DataAbortV);
1999 else
2000 ARMul_Icycles (state, 2, 0L);
2001}
2002
2003static void
2004Iwmmxt_Store_Word (ARMul_State * state, ARMword address, ARMword value)
2005{
2006 /* Check for a misaligned address. */
2007 if (address & 3)
2008 {
2009 if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
2010 ARMul_Abort (state, ARMul_DataAbortV);
2011 else
2012 address &= ~ 3;
2013 }
2014
2015 ARMul_StoreWordN (state, address, value);
2016
2017 if (state->Aborted)
2018 ARMul_Abort (state, ARMul_DataAbortV);
2019}
2020
2021static void
2022Iwmmxt_Store_Half_Word (ARMul_State * state, ARMword address, ARMword value)
2023{
2024 /* Check for a misaligned address. */
2025 if (address & 1)
2026 {
2027 if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
2028 ARMul_Abort (state, ARMul_DataAbortV);
2029 else
2030 address &= ~ 1;
2031 }
2032
2033 ARMul_StoreHalfWord (state, address, value);
2034
2035 if (state->Aborted)
2036 ARMul_Abort (state, ARMul_DataAbortV);
2037}
2038
2039static void
2040Iwmmxt_Store_Byte (ARMul_State * state, ARMword address, ARMword value)
2041{
2042 ARMul_StoreByte (state, address, value);
2043
2044 if (state->Aborted)
2045 ARMul_Abort (state, ARMul_DataAbortV);
2046}
2047
2048static int
2049WLDR (ARMul_State * state, ARMword instr)
2050{
2051 ARMword address;
2052 int failed;
2053
2054 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2055 return ARMul_CANT;
2056
2057#ifdef DEBUG
2058 fprintf (stderr, "wldr\n");
454de2ee 2059#endif
0f026fd0
NC
2060
2061 address = Compute_Iwmmxt_Address (state, instr, & failed);
2062 if (failed)
2063 return ARMul_CANT;
2064
2065 if (BITS (28, 31) == 0xf)
2066 {
2067 /* WLDRW wCx */
2068 wC [BITS (12, 15)] = Iwmmxt_Load_Word (state, address);
2069 }
2070 else if (BIT (8) == 0)
2071 {
2072 if (BIT (22) == 0)
2073 /* WLDRB */
2074 wR [BITS (12, 15)] = Iwmmxt_Load_Byte (state, address);
2075 else
2076 /* WLDRH */
2077 wR [BITS (12, 15)] = Iwmmxt_Load_Half_Word (state, address);
2078 }
2079 else
2080 {
2081 if (BIT (22) == 0)
2082 /* WLDRW wRd */
2083 wR [BITS (12, 15)] = Iwmmxt_Load_Word (state, address);
2084 else
2085 /* WLDRD */
2086 wR [BITS (12, 15)] = Iwmmxt_Load_Double_Word (state, address);
2087 }
2088
2089 wC [wCon] |= WCON_MUP;
2090
2091 return ARMul_DONE;
2092}
2093
2094static int
2095WMAC (ARMword instr)
2096{
2097 int i;
2098 ARMdword t = 0;
2099 ARMword a, b;
2100
2101 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2102 return ARMul_CANT;
2103
2104#ifdef DEBUG
2105 fprintf (stderr, "wmac\n");
454de2ee 2106#endif
0f026fd0
NC
2107
2108 for (i = 0; i < 4; i++)
2109 {
2110 if (BIT (21))
2111 {
2112 /* Signed. */
2113 signed long s;
2114
2115 a = wRHALF (BITS (16, 19), i);
2116 a = EXTEND16 (a);
2117
2118 b = wRHALF (BITS (0, 3), i);
2119 b = EXTEND16 (b);
2120
2121 s = (signed long) a * (signed long) b;
2122
16d55f14 2123 t = t + (ARMdword) s;
0f026fd0
NC
2124 }
2125 else
2126 {
2127 /* Unsigned. */
2128 a = wRHALF (BITS (16, 19), i);
2129 b = wRHALF (BITS ( 0, 3), i);
2130
2131 t += a * b;
2132 }
2133 }
2134
161fc452
NC
2135 if (BIT (21))
2136 t = EXTEND32 (t);
2137 else
2138 t &= 0xffffffff;
0f026fd0 2139
161fc452
NC
2140 if (BIT (20))
2141 wR [BITS (12, 15)] = t;
0f026fd0 2142 else
161fc452 2143 wR[BITS (12, 15)] += t;
0f026fd0
NC
2144
2145 wC [wCon] |= WCON_MUP;
2146
2147 return ARMul_DONE;
2148}
2149
2150static int
2151WMADD (ARMword instr)
2152{
2153 ARMdword r = 0;
2154 int i;
2155
2156 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2157 return ARMul_CANT;
2158
2159#ifdef DEBUG
2160 fprintf (stderr, "wmadd\n");
454de2ee 2161#endif
0f026fd0
NC
2162
2163 for (i = 0; i < 2; i++)
2164 {
2165 ARMdword s1, s2;
2166
2167 if (BIT (21)) /* Signed. */
2168 {
2169 signed long a, b;
2170
2171 a = wRHALF (BITS (16, 19), i * 2);
2172 a = EXTEND16 (a);
2173
2174 b = wRHALF (BITS (0, 3), i * 2);
2175 b = EXTEND16 (b);
2176
16d55f14 2177 s1 = (ARMdword) (a * b);
0f026fd0
NC
2178
2179 a = wRHALF (BITS (16, 19), i * 2 + 1);
2180 a = EXTEND16 (a);
2181
2182 b = wRHALF (BITS (0, 3), i * 2 + 1);
2183 b = EXTEND16 (b);
2184
16d55f14 2185 s2 = (ARMdword) (a * b);
0f026fd0
NC
2186 }
2187 else /* Unsigned. */
2188 {
2189 unsigned long a, b;
2190
2191 a = wRHALF (BITS (16, 19), i * 2);
2192 b = wRHALF (BITS ( 0, 3), i * 2);
2193
16d55f14 2194 s1 = (ARMdword) (a * b);
0f026fd0
NC
2195
2196 a = wRHALF (BITS (16, 19), i * 2 + 1);
2197 b = wRHALF (BITS ( 0, 3), i * 2 + 1);
2198
16d55f14 2199 s2 = (ARMdword) a * b;
0f026fd0
NC
2200 }
2201
2202 r |= (ARMdword) ((s1 + s2) & 0xffffffff) << (i ? 32 : 0);
2203 }
2204
2205 wR [BITS (12, 15)] = r;
2206 wC [wCon] |= WCON_MUP;
2207
2208 return ARMul_DONE;
2209}
2210
2211static int
2212WMAX (ARMul_State * state, ARMword instr)
2213{
2214 ARMdword r = 0;
2215 ARMdword s;
2216 int i;
2217
2218 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2219 return ARMul_CANT;
2220
2221#ifdef DEBUG
2222 fprintf (stderr, "wmax\n");
454de2ee 2223#endif
0f026fd0
NC
2224
2225 switch (BITS (22, 23))
2226 {
2227 case Bqual:
2228 for (i = 0; i < 8; i++)
2229 if (BIT (21)) /* Signed. */
2230 {
2231 int a, b;
2232
2233 a = wRBYTE (BITS (16, 19), i);
2234 a = EXTEND8 (a);
2235
2236 b = wRBYTE (BITS (0, 3), i);
2237 b = EXTEND8 (b);
2238
2239 if (a > b)
2240 s = a;
2241 else
2242 s = b;
2243
2244 r |= (s & 0xff) << (i * 8);
2245 }
2246 else /* Unsigned. */
2247 {
2248 unsigned int a, b;
2249
2250 a = wRBYTE (BITS (16, 19), i);
2251 b = wRBYTE (BITS (0, 3), i);
2252
2253 if (a > b)
2254 s = a;
2255 else
2256 s = b;
2257
2258 r |= (s & 0xff) << (i * 8);
2259 }
2260 break;
2261
2262 case Hqual:
2263 for (i = 0; i < 4; i++)
2264 if (BIT (21)) /* Signed. */
2265 {
2266 int a, b;
2267
2268 a = wRHALF (BITS (16, 19), i);
2269 a = EXTEND16 (a);
2270
2271 b = wRHALF (BITS (0, 3), i);
2272 b = EXTEND16 (b);
2273
2274 if (a > b)
2275 s = a;
2276 else
2277 s = b;
2278
2279 r |= (s & 0xffff) << (i * 16);
2280 }
2281 else /* Unsigned. */
2282 {
2283 unsigned int a, b;
2284
2285 a = wRHALF (BITS (16, 19), i);
2286 b = wRHALF (BITS (0, 3), i);
2287
2288 if (a > b)
2289 s = a;
2290 else
2291 s = b;
2292
2293 r |= (s & 0xffff) << (i * 16);
2294 }
2295 break;
2296
2297 case Wqual:
2298 for (i = 0; i < 2; i++)
2299 if (BIT (21)) /* Signed. */
2300 {
2301 int a, b;
2302
2303 a = wRWORD (BITS (16, 19), i);
2304 b = wRWORD (BITS (0, 3), i);
2305
2306 if (a > b)
2307 s = a;
2308 else
2309 s = b;
2310
2311 r |= (s & 0xffffffff) << (i * 32);
2312 }
2313 else
2314 {
2315 unsigned int a, b;
2316
2317 a = wRWORD (BITS (16, 19), i);
2318 b = wRWORD (BITS (0, 3), i);
2319
2320 if (a > b)
2321 s = a;
2322 else
2323 s = b;
2324
2325 r |= (s & 0xffffffff) << (i * 32);
2326 }
2327 break;
2328
2329 default:
2330 ARMul_UndefInstr (state, instr);
2331 return ARMul_DONE;
2332 }
2333
2334 wR [BITS (12, 15)] = r;
2335 wC [wCon] |= WCON_MUP;
2336
2337 return ARMul_DONE;
2338}
2339
2340static int
2341WMIN (ARMul_State * state, ARMword instr)
2342{
2343 ARMdword r = 0;
2344 ARMdword s;
2345 int i;
2346
2347 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2348 return ARMul_CANT;
2349
2350#ifdef DEBUG
2351 fprintf (stderr, "wmin\n");
454de2ee 2352#endif
0f026fd0
NC
2353
2354 switch (BITS (22, 23))
2355 {
2356 case Bqual:
2357 for (i = 0; i < 8; i++)
2358 if (BIT (21)) /* Signed. */
2359 {
2360 int a, b;
2361
2362 a = wRBYTE (BITS (16, 19), i);
2363 a = EXTEND8 (a);
2364
2365 b = wRBYTE (BITS (0, 3), i);
2366 b = EXTEND8 (b);
2367
2368 if (a < b)
2369 s = a;
2370 else
2371 s = b;
2372
2373 r |= (s & 0xff) << (i * 8);
2374 }
2375 else /* Unsigned. */
2376 {
2377 unsigned int a, b;
2378
2379 a = wRBYTE (BITS (16, 19), i);
2380 b = wRBYTE (BITS (0, 3), i);
2381
2382 if (a < b)
2383 s = a;
2384 else
2385 s = b;
2386
2387 r |= (s & 0xff) << (i * 8);
2388 }
2389 break;
2390
2391 case Hqual:
2392 for (i = 0; i < 4; i++)
2393 if (BIT (21)) /* Signed. */
2394 {
2395 int a, b;
2396
2397 a = wRHALF (BITS (16, 19), i);
2398 a = EXTEND16 (a);
2399
2400 b = wRHALF (BITS (0, 3), i);
2401 b = EXTEND16 (b);
2402
2403 if (a < b)
2404 s = a;
2405 else
2406 s = b;
2407
2408 r |= (s & 0xffff) << (i * 16);
2409 }
2410 else
2411 {
2412 /* Unsigned. */
2413 unsigned int a, b;
2414
2415 a = wRHALF (BITS (16, 19), i);
2416 b = wRHALF (BITS ( 0, 3), i);
2417
2418 if (a < b)
2419 s = a;
2420 else
2421 s = b;
2422
2423 r |= (s & 0xffff) << (i * 16);
2424 }
2425 break;
2426
2427 case Wqual:
2428 for (i = 0; i < 2; i++)
2429 if (BIT (21)) /* Signed. */
2430 {
2431 int a, b;
2432
2433 a = wRWORD (BITS (16, 19), i);
2434 b = wRWORD (BITS ( 0, 3), i);
2435
2436 if (a < b)
2437 s = a;
2438 else
2439 s = b;
2440
2441 r |= (s & 0xffffffff) << (i * 32);
2442 }
2443 else
2444 {
2445 unsigned int a, b;
2446
2447 a = wRWORD (BITS (16, 19), i);
2448 b = wRWORD (BITS (0, 3), i);
2449
2450 if (a < b)
2451 s = a;
2452 else
2453 s = b;
2454
2455 r |= (s & 0xffffffff) << (i * 32);
2456 }
2457 break;
2458
2459 default:
2460 ARMul_UndefInstr (state, instr);
2461 return ARMul_DONE;
2462 }
2463
2464 wR [BITS (12, 15)] = r;
2465 wC [wCon] |= WCON_MUP;
454de2ee 2466
0f026fd0
NC
2467 return ARMul_DONE;
2468}
2469
2470static int
2471WMUL (ARMword instr)
2472{
2473 ARMdword r = 0;
2474 ARMdword s;
2475 int i;
2476
2477 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2478 return ARMul_CANT;
2479
2480#ifdef DEBUG
2481 fprintf (stderr, "wmul\n");
454de2ee 2482#endif
0f026fd0
NC
2483
2484 for (i = 0; i < 4; i++)
2485 if (BIT (21)) /* Signed. */
2486 {
2487 long a, b;
2488
2489 a = wRHALF (BITS (16, 19), i);
2490 a = EXTEND16 (a);
2491
2492 b = wRHALF (BITS (0, 3), i);
2493 b = EXTEND16 (b);
2494
2495 s = a * b;
2496
2497 if (BIT (20))
2498 r |= ((s >> 16) & 0xffff) << (i * 16);
2499 else
2500 r |= (s & 0xffff) << (i * 16);
2501 }
2502 else /* Unsigned. */
2503 {
2504 unsigned long a, b;
2505
2506 a = wRHALF (BITS (16, 19), i);
2507 b = wRHALF (BITS (0, 3), i);
2508
2509 s = a * b;
2510
2511 if (BIT (20))
2512 r |= ((s >> 16) & 0xffff) << (i * 16);
2513 else
2514 r |= (s & 0xffff) << (i * 16);
2515 }
2516
2517 wR [BITS (12, 15)] = r;
2518 wC [wCon] |= WCON_MUP;
2519
2520 return ARMul_DONE;
2521}
2522
2523static int
2524WOR (ARMword instr)
2525{
2526 ARMword psr = 0;
2527 ARMdword result;
2528
2529 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2530 return ARMul_CANT;
2531
2532#ifdef DEBUG
2533 fprintf (stderr, "wor\n");
454de2ee 2534#endif
0f026fd0
NC
2535
2536 result = wR [BITS (16, 19)] | wR [BITS (0, 3)];
2537 wR [BITS (12, 15)] = result;
2538
2539 SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
2540 SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
454de2ee 2541
0f026fd0
NC
2542 wC [wCASF] = psr;
2543 wC [wCon] |= (WCON_CUP | WCON_MUP);
2544
2545 return ARMul_DONE;
2546}
2547
2548static int
2549WPACK (ARMul_State * state, ARMword instr)
2550{
2551 ARMdword r = 0;
2552 ARMword psr = 0;
2553 ARMdword x;
2554 ARMdword s;
2555 int i;
2556 int satrv[8];
2557
2558 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2559 return ARMul_CANT;
2560
2561#ifdef DEBUG
2562 fprintf (stderr, "wpack\n");
454de2ee
NC
2563#endif
2564
0f026fd0
NC
2565 switch (BITS (22, 23))
2566 {
2567 case Hqual:
2568 for (i = 0; i < 8; i++)
2569 {
2570 x = wRHALF (i < 4 ? BITS (16, 19) : BITS (0, 3), i & 3);
2571
2572 switch (BITS (20, 21))
2573 {
2574 case UnsignedSaturation:
2575 s = IwmmxtSaturateU8 (x, satrv + BITIDX8 (i));
2576 break;
2577
2578 case SignedSaturation:
2579 s = IwmmxtSaturateS8 (x, satrv + BITIDX8 (i));
2580 break;
2581
2582 default:
2583 ARMul_UndefInstr (state, instr);
2584 return ARMul_DONE;
2585 }
2586
2587 r |= (s & 0xff) << (i * 8);
2588 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
2589 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
2590 }
2591 break;
2592
2593 case Wqual:
2594 satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
2595
2596 for (i = 0; i < 4; i++)
2597 {
2598 x = wRWORD (i < 2 ? BITS (16, 19) : BITS (0, 3), i & 1);
2599
2600 switch (BITS (20, 21))
2601 {
2602 case UnsignedSaturation:
2603 s = IwmmxtSaturateU16 (x, satrv + BITIDX16 (i));
2604 break;
2605
2606 case SignedSaturation:
2607 s = IwmmxtSaturateS16 (x, satrv + BITIDX16 (i));
2608 break;
2609
2610 default:
2611 ARMul_UndefInstr (state, instr);
2612 return ARMul_DONE;
2613 }
2614
2615 r |= (s & 0xffff) << (i * 16);
2616 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2617 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2618 }
2619 break;
2620
2621 case Dqual:
2622 satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
2623
2624 for (i = 0; i < 2; i++)
2625 {
2626 x = wR [i ? BITS (0, 3) : BITS (16, 19)];
2627
2628 switch (BITS (20, 21))
2629 {
2630 case UnsignedSaturation:
2631 s = IwmmxtSaturateU32 (x, satrv + BITIDX32 (i));
2632 break;
2633
2634 case SignedSaturation:
2635 s = IwmmxtSaturateS32 (x, satrv + BITIDX32 (i));
2636 break;
2637
2638 default:
2639 ARMul_UndefInstr (state, instr);
2640 return ARMul_DONE;
2641 }
2642
2643 r |= (s & 0xffffffff) << (i * 32);
2644 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
2645 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
2646 }
2647 break;
2648
2649 default:
2650 ARMul_UndefInstr (state, instr);
2651 return ARMul_DONE;
2652 }
2653
2654 wC [wCASF] = psr;
2655 wR [BITS (12, 15)] = r;
2656 SET_wCSSFvec (satrv);
2657 wC [wCon] |= (WCON_CUP | WCON_MUP);
2658
2659 return ARMul_DONE;
2660}
2661
2662static int
2663WROR (ARMul_State * state, ARMword instr)
2664{
2665 ARMdword r = 0;
2666 ARMdword s;
2667 ARMword psr = 0;
2668 int i;
2669 int shift;
2670
2671 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2672 return ARMul_CANT;
2673
2674#ifdef DEBUG
2675 fprintf (stderr, "wror\n");
454de2ee 2676#endif
0f026fd0
NC
2677
2678 DECODE_G_BIT (state, instr, shift);
2679
2680 switch (BITS (22, 23))
2681 {
2682 case Hqual:
2683 shift &= 0xf;
2684 for (i = 0; i < 4; i++)
2685 {
2686 s = ((wRHALF (BITS (16, 19), i) & 0xffff) << (16 - shift))
2687 | ((wRHALF (BITS (16, 19), i) & 0xffff) >> shift);
2688 r |= (s & 0xffff) << (i * 16);
2689 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2690 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2691 }
2692 break;
2693
2694 case Wqual:
2695 shift &= 0x1f;
2696 for (i = 0; i < 2; i++)
2697 {
2698 s = ((wRWORD (BITS (16, 19), i) & 0xffffffff) << (32 - shift))
2699 | ((wRWORD (BITS (16, 19), i) & 0xffffffff) >> shift);
2700 r |= (s & 0xffffffff) << (i * 32);
2701 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
2702 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
2703 }
2704 break;
2705
2706 case Dqual:
2707 shift &= 0x3f;
2708 r = (wR [BITS (16, 19)] >> shift)
2709 | (wR [BITS (16, 19)] << (64 - shift));
2710
2711 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
2712 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
2713 break;
2714
2715 default:
2716 ARMul_UndefInstr (state, instr);
2717 return ARMul_DONE;
2718 }
2719
2720 wC [wCASF] = psr;
2721 wR [BITS (12, 15)] = r;
2722 wC [wCon] |= (WCON_CUP | WCON_MUP);
2723
2724 return ARMul_DONE;
2725}
2726
2727static int
2728WSAD (ARMword instr)
2729{
2730 ARMdword r;
2731 int s;
2732 int i;
2733
2734 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2735 return ARMul_CANT;
2736
2737#ifdef DEBUG
2738 fprintf (stderr, "wsad\n");
454de2ee 2739#endif
0f026fd0
NC
2740
2741 /* Z bit. */
2742 r = BIT (20) ? 0 : (wR [BITS (12, 15)] & 0xffffffff);
2743
2744 if (BIT (22))
2745 /* Half. */
2746 for (i = 0; i < 4; i++)
2747 {
2748 s = (wRHALF (BITS (16, 19), i) - wRHALF (BITS (0, 3), i));
2749 r += abs (s);
2750 }
2751 else
2752 /* Byte. */
2753 for (i = 0; i < 8; i++)
2754 {
2755 s = (wRBYTE (BITS (16, 19), i) - wRBYTE (BITS (0, 3), i));
2756 r += abs (s);
2757 }
2758
2759 wR [BITS (12, 15)] = r;
2760 wC [wCon] |= WCON_MUP;
2761
2762 return ARMul_DONE;
2763}
2764
2765static int
2766WSHUFH (ARMword instr)
2767{
2768 ARMdword r = 0;
2769 ARMword psr = 0;
2770 ARMdword s;
2771 int i;
2772 int imm8;
2773
2774 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2775 return ARMul_CANT;
2776
2777#ifdef DEBUG
2778 fprintf (stderr, "wshufh\n");
454de2ee 2779#endif
0f026fd0
NC
2780
2781 imm8 = (BITS (20, 23) << 4) | BITS (0, 3);
2782
2783 for (i = 0; i < 4; i++)
2784 {
2785 s = wRHALF (BITS (16, 19), ((imm8 >> (i * 2) & 3)) & 0xff);
2786 r |= (s & 0xffff) << (i * 16);
2787 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2788 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2789 }
2790
2791 wC [wCASF] = psr;
2792 wR [BITS (12, 15)] = r;
2793 wC [wCon] |= (WCON_CUP | WCON_MUP);
2794
2795 return ARMul_DONE;
2796}
2797
2798static int
2799WSLL (ARMul_State * state, ARMword instr)
2800{
2801 ARMdword r = 0;
2802 ARMdword s;
2803 ARMword psr = 0;
2804 int i;
2805 unsigned shift;
2806
2807 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2808 return ARMul_CANT;
2809
2810#ifdef DEBUG
2811 fprintf (stderr, "wsll\n");
454de2ee 2812#endif
0f026fd0
NC
2813
2814 DECODE_G_BIT (state, instr, shift);
2815
2816 switch (BITS (22, 23))
2817 {
2818 case Hqual:
2819 for (i = 0; i < 4; i++)
2820 {
2821 if (shift > 15)
2822 s = 0;
2823 else
2824 s = ((wRHALF (BITS (16, 19), i) & 0xffff) << shift);
2825 r |= (s & 0xffff) << (i * 16);
2826 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2827 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2828 }
2829 break;
2830
2831 case Wqual:
2832 for (i = 0; i < 2; i++)
2833 {
2834 if (shift > 31)
2835 s = 0;
2836 else
2837 s = ((wRWORD (BITS (16, 19), i) & 0xffffffff) << shift);
2838 r |= (s & 0xffffffff) << (i * 32);
2839 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
2840 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
2841 }
2842 break;
2843
2844 case Dqual:
2845 if (shift > 63)
2846 r = 0;
2847 else
16d55f14 2848 r = ((wR[BITS (16, 19)] & 0xffffffffffffffffULL) << shift);
0f026fd0
NC
2849
2850 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
2851 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
2852 break;
2853
2854 default:
2855 ARMul_UndefInstr (state, instr);
2856 return ARMul_DONE;
2857 }
2858
2859 wC [wCASF] = psr;
2860 wR [BITS (12, 15)] = r;
2861 wC [wCon] |= (WCON_CUP | WCON_MUP);
2862
2863 return ARMul_DONE;
2864}
2865
2866static int
2867WSRA (ARMul_State * state, ARMword instr)
2868{
2869 ARMdword r = 0;
2870 ARMdword s;
2871 ARMword psr = 0;
2872 int i;
2873 unsigned shift;
2874 signed long t;
2875
2876 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2877 return ARMul_CANT;
2878
2879#ifdef DEBUG
2880 fprintf (stderr, "wsra\n");
454de2ee 2881#endif
0f026fd0
NC
2882
2883 DECODE_G_BIT (state, instr, shift);
2884
2885 switch (BITS (22, 23))
2886 {
2887 case Hqual:
2888 for (i = 0; i < 4; i++)
2889 {
2890 if (shift > 15)
2891 t = (wRHALF (BITS (16, 19), i) & 0x8000) ? 0xffff : 0;
2892 else
2893 {
2894 t = wRHALF (BITS (16, 19), i);
2895 t = EXTEND16 (t);
2896 t >>= shift;
2897 }
2898
2899 s = t;
2900 r |= (s & 0xffff) << (i * 16);
2901 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2902 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2903 }
2904 break;
2905
2906 case Wqual:
2907 for (i = 0; i < 2; i++)
2908 {
2909 if (shift > 31)
2910 t = (wRWORD (BITS (16, 19), i) & 0x80000000) ? 0xffffffff : 0;
2911 else
2912 {
161fc452 2913 t = EXTEND32 (wRWORD (BITS (16, 19), i));
0f026fd0
NC
2914 t >>= shift;
2915 }
2916 s = t;
2917 r |= (s & 0xffffffff) << (i * 32);
2918 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
2919 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
2920 }
2921 break;
454de2ee 2922
0f026fd0
NC
2923 case Dqual:
2924 if (shift > 63)
16d55f14 2925 r = (wR [BITS (16, 19)] & 0x8000000000000000ULL) ? 0xffffffffffffffffULL : 0;
0f026fd0 2926 else
16d55f14 2927 r = ((signed long long) (wR[BITS (16, 19)] & 0xffffffffffffffffULL) >> shift);
0f026fd0
NC
2928 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
2929 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
2930 break;
2931
2932 default:
2933 ARMul_UndefInstr (state, instr);
2934 return ARMul_DONE;
2935 }
2936
2937 wC [wCASF] = psr;
2938 wR [BITS (12, 15)] = r;
2939 wC [wCon] |= (WCON_CUP | WCON_MUP);
2940
2941 return ARMul_DONE;
2942}
2943
2944static int
2945WSRL (ARMul_State * state, ARMword instr)
2946{
2947 ARMdword r = 0;
2948 ARMdword s;
2949 ARMword psr = 0;
2950 int i;
2951 unsigned int shift;
2952
2953 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2954 return ARMul_CANT;
2955
2956#ifdef DEBUG
2957 fprintf (stderr, "wsrl\n");
2958#endif
2959
2960 DECODE_G_BIT (state, instr, shift);
2961
2962 switch (BITS (22, 23))
2963 {
2964 case Hqual:
2965 for (i = 0; i < 4; i++)
2966 {
2967 if (shift > 15)
2968 s = 0;
2969 else
2970 s = ((unsigned) (wRHALF (BITS (16, 19), i) & 0xffff) >> shift);
2971
2972 r |= (s & 0xffff) << (i * 16);
2973 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2974 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2975 }
2976 break;
2977
2978 case Wqual:
2979 for (i = 0; i < 2; i++)
2980 {
2981 if (shift > 31)
2982 s = 0;
2983 else
2984 s = ((unsigned long) (wRWORD (BITS (16, 19), i) & 0xffffffff) >> shift);
2985
2986 r |= (s & 0xffffffff) << (i * 32);
2987 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
2988 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
2989 }
2990 break;
2991
2992 case Dqual:
2993 if (shift > 63)
2994 r = 0;
2995 else
16d55f14 2996 r = (wR [BITS (16, 19)] & 0xffffffffffffffffULL) >> shift;
0f026fd0
NC
2997
2998 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
2999 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
3000 break;
3001
3002 default:
3003 ARMul_UndefInstr (state, instr);
3004 return ARMul_DONE;
3005 }
3006
3007 wC [wCASF] = psr;
3008 wR [BITS (12, 15)] = r;
3009 wC [wCon] |= (WCON_CUP | WCON_MUP);
3010
3011 return ARMul_DONE;
3012}
3013
3014static int
3015WSTR (ARMul_State * state, ARMword instr)
3016{
3017 ARMword address;
3018 int failed;
3019
3020
3021 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3022 return ARMul_CANT;
3023
3024#ifdef DEBUG
3025 fprintf (stderr, "wstr\n");
3026#endif
454de2ee 3027
0f026fd0
NC
3028 address = Compute_Iwmmxt_Address (state, instr, & failed);
3029 if (failed)
3030 return ARMul_CANT;
3031
3032 if (BITS (28, 31) == 0xf)
3033 {
3034 /* WSTRW wCx */
3035 Iwmmxt_Store_Word (state, address, wC [BITS (12, 15)]);
3036 }
3037 else if (BIT (8) == 0)
3038 {
3039 if (BIT (22) == 0)
3040 /* WSTRB */
3041 Iwmmxt_Store_Byte (state, address, wR [BITS (12, 15)]);
3042 else
3043 /* WSTRH */
3044 Iwmmxt_Store_Half_Word (state, address, wR [BITS (12, 15)]);
3045 }
3046 else
3047 {
3048 if (BIT (22) == 0)
3049 /* WSTRW wRd */
3050 Iwmmxt_Store_Word (state, address, wR [BITS (12, 15)]);
3051 else
3052 /* WSTRD */
3053 Iwmmxt_Store_Double_Word (state, address, wR [BITS (12, 15)]);
3054 }
3055
3056 return ARMul_DONE;
3057}
3058
3059static int
3060WSUB (ARMul_State * state, ARMword instr)
3061{
3062 ARMdword r = 0;
3063 ARMword psr = 0;
3064 ARMdword x;
3065 ARMdword s;
3066 int i;
3067 int carry;
3068 int overflow;
3069 int satrv[8];
3070
3071 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3072 return ARMul_CANT;
3073
3074#ifdef DEBUG
3075 fprintf (stderr, "wsub\n");
454de2ee 3076#endif
0f026fd0
NC
3077
3078/* Subtract two numbers using the specified function,
3079 leaving setting the carry bit as required. */
3080#define SUBx(x, y, m, f) \
3081 (*f) (wRBITS (BITS (16, 19), (x), (y)) & (m), \
3082 wRBITS (BITS ( 0, 3), (x), (y)) & (m), & carry, & overflow)
3083
3084 switch (BITS (22, 23))
3085 {
3086 case Bqual:
3087 for (i = 0; i < 8; i++)
3088 {
3089 switch (BITS (20, 21))
3090 {
3091 case NoSaturation:
3092 s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubS8);
3093 satrv [BITIDX8 (i)] = 0;
3094 r |= (s & 0xff) << (i * 8);
3095 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
3096 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
3097 SIMD8_SET (psr, carry, SIMD_CBIT, i);
3098 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
3099 break;
3100
3101 case UnsignedSaturation:
3102 s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubU8);
3103 x = IwmmxtSaturateU8 (s, satrv + BITIDX8 (i));
3104 r |= (x & 0xff) << (i * 8);
3105 SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
3106 SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
3107 if (! satrv [BITIDX8 (i)])
3108 {
3109 SIMD8_SET (psr, carry, SIMD_CBIT, i);
3110 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
3111 }
3112 break;
3113
3114 case SignedSaturation:
3115 s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubS8);
3116 x = IwmmxtSaturateS8 (s, satrv + BITIDX8 (i));
3117 r |= (x & 0xff) << (i * 8);
3118 SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
3119 SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
3120 if (! satrv [BITIDX8 (i)])
3121 {
3122 SIMD8_SET (psr, carry, SIMD_CBIT, i);
3123 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
3124 }
3125 break;
3126
3127 default:
3128 ARMul_UndefInstr (state, instr);
3129 return ARMul_DONE;
3130 }
3131 }
3132 break;
3133
3134 case Hqual:
3135 satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
3136
3137 for (i = 0; i < 4; i++)
3138 {
3139 switch (BITS (20, 21))
3140 {
3141 case NoSaturation:
3142 s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubU16);
3143 satrv [BITIDX16 (i)] = 0;
3144 r |= (s & 0xffff) << (i * 16);
3145 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
3146 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
3147 SIMD16_SET (psr, carry, SIMD_CBIT, i);
3148 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
3149 break;
3150
3151 case UnsignedSaturation:
3152 s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubU16);
3153 x = IwmmxtSaturateU16 (s, satrv + BITIDX16 (i));
3154 r |= (x & 0xffff) << (i * 16);
3155 SIMD16_SET (psr, NBIT16 (x & 0xffff), SIMD_NBIT, i);
3156 SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
3157 if (! satrv [BITIDX16 (i)])
3158 {
3159 SIMD16_SET (psr, carry, SIMD_CBIT, i);
3160 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
3161 }
3162 break;
3163
3164 case SignedSaturation:
3165 s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubS16);
3166 x = IwmmxtSaturateS16 (s, satrv + BITIDX16 (i));
3167 r |= (x & 0xffff) << (i * 16);
3168 SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
3169 SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
3170 if (! satrv [BITIDX16 (i)])
3171 {
3172 SIMD16_SET (psr, carry, SIMD_CBIT, i);
3173 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
3174 }
3175 break;
3176
3177 default:
3178 ARMul_UndefInstr (state, instr);
3179 return ARMul_DONE;
3180 }
3181 }
3182 break;
3183
3184 case Wqual:
3185 satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
3186
3187 for (i = 0; i < 2; i++)
3188 {
3189 switch (BITS (20, 21))
3190 {
3191 case NoSaturation:
3192 s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubU32);
3193 satrv[BITIDX32 (i)] = 0;
3194 r |= (s & 0xffffffff) << (i * 32);
3195 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
3196 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
3197 SIMD32_SET (psr, carry, SIMD_CBIT, i);
3198 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
3199 break;
3200
3201 case UnsignedSaturation:
3202 s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubU32);
3203 x = IwmmxtSaturateU32 (s, satrv + BITIDX32 (i));
3204 r |= (x & 0xffffffff) << (i * 32);
3205 SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
3206 SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
3207 if (! satrv [BITIDX32 (i)])
3208 {
3209 SIMD32_SET (psr, carry, SIMD_CBIT, i);
3210 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
3211 }
3212 break;
3213
3214 case SignedSaturation:
3215 s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubS32);
3216 x = IwmmxtSaturateS32 (s, satrv + BITIDX32 (i));
3217 r |= (x & 0xffffffff) << (i * 32);
3218 SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
3219 SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
3220 if (! satrv [BITIDX32 (i)])
3221 {
3222 SIMD32_SET (psr, carry, SIMD_CBIT, i);
3223 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
3224 }
3225 break;
3226
3227 default:
3228 ARMul_UndefInstr (state, instr);
3229 return ARMul_DONE;
3230 }
3231 }
3232 break;
3233
3234 default:
3235 ARMul_UndefInstr (state, instr);
3236 return ARMul_DONE;
3237 }
3238
3239 wR [BITS (12, 15)] = r;
3240 wC [wCASF] = psr;
3241 SET_wCSSFvec (satrv);
3242 wC [wCon] |= (WCON_CUP | WCON_MUP);
3243
3244#undef SUBx
3245
3246 return ARMul_DONE;
3247}
3248
3249static int
3250WUNPCKEH (ARMul_State * state, ARMword instr)
3251{
3252 ARMdword r = 0;
3253 ARMword psr = 0;
3254 ARMdword s;
3255 int i;
3256
3257 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3258 return ARMul_CANT;
3259
3260#ifdef DEBUG
3261 fprintf (stderr, "wunpckeh\n");
454de2ee 3262#endif
0f026fd0
NC
3263
3264 switch (BITS (22, 23))
3265 {
3266 case Bqual:
3267 for (i = 0; i < 4; i++)
3268 {
3269 s = wRBYTE (BITS (16, 19), i + 4);
3270
3271 if (BIT (21) && NBIT8 (s))
3272 s |= 0xff00;
3273
3274 r |= (s & 0xffff) << (i * 16);
3275 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
3276 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
3277 }
3278 break;
3279
3280 case Hqual:
3281 for (i = 0; i < 2; i++)
3282 {
3283 s = wRHALF (BITS (16, 19), i + 2);
3284
3285 if (BIT (21) && NBIT16 (s))
3286 s |= 0xffff0000;
3287
3288 r |= (s & 0xffffffff) << (i * 32);
3289 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
3290 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
3291 }
3292 break;
3293
3294 case Wqual:
3295 r = wRWORD (BITS (16, 19), 1);
3296
3297 if (BIT (21) && NBIT32 (r))
16d55f14 3298 r |= 0xffffffff00000000ULL;
0f026fd0
NC
3299
3300 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
3301 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
3302 break;
3303
3304 default:
3305 ARMul_UndefInstr (state, instr);
3306 return ARMul_DONE;
3307 }
3308
3309 wC [wCASF] = psr;
3310 wR [BITS (12, 15)] = r;
3311 wC [wCon] |= (WCON_CUP | WCON_MUP);
3312
3313 return ARMul_DONE;
3314}
3315
3316static int
3317WUNPCKEL (ARMul_State * state, ARMword instr)
3318{
3319 ARMdword r = 0;
3320 ARMword psr = 0;
3321 ARMdword s;
3322 int i;
3323
3324 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3325 return ARMul_CANT;
3326
3327#ifdef DEBUG
3328 fprintf (stderr, "wunpckel\n");
454de2ee 3329#endif
0f026fd0
NC
3330
3331 switch (BITS (22, 23))
3332 {
3333 case Bqual:
3334 for (i = 0; i < 4; i++)
3335 {
3336 s = wRBYTE (BITS (16, 19), i);
3337
3338 if (BIT (21) && NBIT8 (s))
3339 s |= 0xff00;
3340
3341 r |= (s & 0xffff) << (i * 16);
3342 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
3343 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
3344 }
3345 break;
3346
3347 case Hqual:
3348 for (i = 0; i < 2; i++)
3349 {
3350 s = wRHALF (BITS (16, 19), i);
3351
3352 if (BIT (21) && NBIT16 (s))
3353 s |= 0xffff0000;
3354
3355 r |= (s & 0xffffffff) << (i * 32);
3356 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
3357 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
3358 }
3359 break;
3360
3361 case Wqual:
3362 r = wRWORD (BITS (16, 19), 0);
3363
3364 if (BIT (21) && NBIT32 (r))
16d55f14 3365 r |= 0xffffffff00000000ULL;
0f026fd0
NC
3366
3367 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
3368 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
3369 break;
3370
3371 default:
3372 ARMul_UndefInstr (state, instr);
3373 return ARMul_DONE;
3374 }
3375
3376 wC [wCASF] = psr;
3377 wR [BITS (12, 15)] = r;
3378 wC [wCon] |= (WCON_CUP | WCON_MUP);
3379
3380 return ARMul_DONE;
3381}
3382
3383static int
3384WUNPCKIH (ARMul_State * state, ARMword instr)
3385{
3386 ARMword a, b;
3387 ARMdword r = 0;
3388 ARMword psr = 0;
3389 ARMdword s;
3390 int i;
3391
3392 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3393 return ARMul_CANT;
3394
3395#ifdef DEBUG
3396 fprintf (stderr, "wunpckih\n");
454de2ee 3397#endif
0f026fd0
NC
3398
3399 switch (BITS (22, 23))
3400 {
3401 case Bqual:
3402 for (i = 0; i < 4; i++)
3403 {
3404 a = wRBYTE (BITS (16, 19), i + 4);
3405 b = wRBYTE (BITS ( 0, 3), i + 4);
3406 s = a | (b << 8);
3407 r |= (s & 0xffff) << (i * 16);
3408 SIMD8_SET (psr, NBIT8 (a), SIMD_NBIT, i * 2);
3409 SIMD8_SET (psr, ZBIT8 (a), SIMD_ZBIT, i * 2);
3410 SIMD8_SET (psr, NBIT8 (b), SIMD_NBIT, (i * 2) + 1);
3411 SIMD8_SET (psr, ZBIT8 (b), SIMD_ZBIT, (i * 2) + 1);
3412 }
3413 break;
454de2ee 3414
0f026fd0
NC
3415 case Hqual:
3416 for (i = 0; i < 2; i++)
3417 {
3418 a = wRHALF (BITS (16, 19), i + 2);
3419 b = wRHALF (BITS ( 0, 3), i + 2);
3420 s = a | (b << 16);
3421 r |= (s & 0xffffffff) << (i * 32);
3422 SIMD16_SET (psr, NBIT16 (a), SIMD_NBIT, (i * 2));
3423 SIMD16_SET (psr, ZBIT16 (a), SIMD_ZBIT, (i * 2));
3424 SIMD16_SET (psr, NBIT16 (b), SIMD_NBIT, (i * 2) + 1);
3425 SIMD16_SET (psr, ZBIT16 (b), SIMD_ZBIT, (i * 2) + 1);
3426 }
3427 break;
3428
3429 case Wqual:
3430 a = wRWORD (BITS (16, 19), 1);
3431 s = wRWORD (BITS ( 0, 3), 1);
3432 r = a | (s << 32);
3433
3434 SIMD32_SET (psr, NBIT32 (a), SIMD_NBIT, 0);
3435 SIMD32_SET (psr, ZBIT32 (a), SIMD_ZBIT, 0);
3436 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, 1);
3437 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, 1);
3438 break;
3439
3440 default:
3441 ARMul_UndefInstr (state, instr);
3442 return ARMul_DONE;
3443 }
3444
3445 wC [wCASF] = psr;
3446 wR [BITS (12, 15)] = r;
3447 wC [wCon] |= (WCON_CUP | WCON_MUP);
3448
3449 return ARMul_DONE;
3450}
3451
3452static int
3453WUNPCKIL (ARMul_State * state, ARMword instr)
3454{
3455 ARMword a, b;
3456 ARMdword r = 0;
3457 ARMword psr = 0;
3458 ARMdword s;
3459 int i;
3460
3461 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3462 return ARMul_CANT;
3463
3464#ifdef DEBUG
3465 fprintf (stderr, "wunpckil\n");
454de2ee 3466#endif
0f026fd0
NC
3467
3468 switch (BITS (22, 23))
3469 {
3470 case Bqual:
3471 for (i = 0; i < 4; i++)
3472 {
3473 a = wRBYTE (BITS (16, 19), i);
3474 b = wRBYTE (BITS ( 0, 3), i);
3475 s = a | (b << 8);
3476 r |= (s & 0xffff) << (i * 16);
3477 SIMD8_SET (psr, NBIT8 (a), SIMD_NBIT, i * 2);
3478 SIMD8_SET (psr, ZBIT8 (a), SIMD_ZBIT, i * 2);
3479 SIMD8_SET (psr, NBIT8 (b), SIMD_NBIT, (i * 2) + 1);
3480 SIMD8_SET (psr, ZBIT8 (b), SIMD_ZBIT, (i * 2) + 1);
3481 }
3482 break;
3483
3484 case Hqual:
3485 for (i = 0; i < 2; i++)
3486 {
3487 a = wRHALF (BITS (16, 19), i);
3488 b = wRHALF (BITS ( 0, 3), i);
3489 s = a | (b << 16);
3490 r |= (s & 0xffffffff) << (i * 32);
3491 SIMD16_SET (psr, NBIT16 (a), SIMD_NBIT, (i * 2));
3492 SIMD16_SET (psr, ZBIT16 (a), SIMD_ZBIT, (i * 2));
3493 SIMD16_SET (psr, NBIT16 (b), SIMD_NBIT, (i * 2) + 1);
3494 SIMD16_SET (psr, ZBIT16 (b), SIMD_ZBIT, (i * 2) + 1);
3495 }
3496 break;
3497
3498 case Wqual:
3499 a = wRWORD (BITS (16, 19), 0);
3500 s = wRWORD (BITS ( 0, 3), 0);
3501 r = a | (s << 32);
3502
3503 SIMD32_SET (psr, NBIT32 (a), SIMD_NBIT, 0);
3504 SIMD32_SET (psr, ZBIT32 (a), SIMD_ZBIT, 0);
3505 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, 1);
3506 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, 1);
3507 break;
3508
3509 default:
3510 ARMul_UndefInstr (state, instr);
3511 return ARMul_DONE;
3512 }
3513
3514 wC [wCASF] = psr;
3515 wR [BITS (12, 15)] = r;
3516 wC [wCon] |= (WCON_CUP | WCON_MUP);
3517
3518 return ARMul_DONE;
3519}
3520
3521static int
3522WXOR (ARMword instr)
3523{
3524 ARMword psr = 0;
3525 ARMdword result;
3526
3527 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3528 return ARMul_CANT;
3529
3530#ifdef DEBUG
3531 fprintf (stderr, "wxor\n");
454de2ee 3532#endif
0f026fd0
NC
3533
3534 result = wR [BITS (16, 19)] ^ wR [BITS (0, 3)];
3535 wR [BITS (12, 15)] = result;
3536
3537 SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
3538 SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
454de2ee 3539
0f026fd0
NC
3540 wC [wCASF] = psr;
3541 wC [wCon] |= (WCON_CUP | WCON_MUP);
3542
3543 return ARMul_DONE;
3544}
3545
07f1f3aa 3546/* This switch table is moved to a separate function in order
0f026fd0
NC
3547 to work around a compiler bug in the host compiler... */
3548
3549static int
3550Process_Instruction (ARMul_State * state, ARMword instr)
3551{
3552 int status = ARMul_BUSY;
3553
3554 switch ((BITS (20, 23) << 8) | BITS (4, 11))
3555 {
3556 case 0x000: status = WOR (instr); break;
3557 case 0x011: status = TMCR (state, instr); break;
3558 case 0x100: status = WXOR (instr); break;
3559 case 0x111: status = TMRC (state, instr); break;
3560 case 0x300: status = WANDN (instr); break;
3561 case 0x200: status = WAND (instr); break;
3562
3563 case 0x810: case 0xa10:
3564 status = WMADD (instr); break;
3565
3566 case 0x10e: case 0x50e: case 0x90e: case 0xd0e:
454de2ee 3567 status = WUNPCKIL (state, instr); break;
0f026fd0
NC
3568 case 0x10c: case 0x50c: case 0x90c: case 0xd0c:
3569 status = WUNPCKIH (state, instr); break;
3570 case 0x012: case 0x112: case 0x412: case 0x512:
3571 status = WSAD (instr); break;
3572 case 0x010: case 0x110: case 0x210: case 0x310:
3573 status = WMUL (instr); break;
3574 case 0x410: case 0x510: case 0x610: case 0x710:
3575 status = WMAC (instr); break;
3576 case 0x006: case 0x406: case 0x806: case 0xc06:
3577 status = WCMPEQ (state, instr); break;
3578 case 0x800: case 0x900: case 0xc00: case 0xd00:
3579 status = WAVG2 (instr); break;
3580 case 0x802: case 0x902: case 0xa02: case 0xb02:
3581 status = WALIGNR (state, instr); break;
3582 case 0x601: case 0x605: case 0x609: case 0x60d:
3583 status = TINSR (state, instr); break;
3584 case 0x107: case 0x507: case 0x907: case 0xd07:
3585 status = TEXTRM (state, instr); break;
3586 case 0x117: case 0x517: case 0x917: case 0xd17:
3587 status = TEXTRC (state, instr); break;
3588 case 0x401: case 0x405: case 0x409: case 0x40d:
3589 status = TBCST (state, instr); break;
3590 case 0x113: case 0x513: case 0x913: case 0xd13:
3591 status = TANDC (state, instr); break;
3592 case 0x01c: case 0x41c: case 0x81c: case 0xc1c:
3593 status = WACC (state, instr); break;
3594 case 0x115: case 0x515: case 0x915: case 0xd15:
3595 status = TORC (state, instr); break;
3596 case 0x103: case 0x503: case 0x903: case 0xd03:
3597 status = TMOVMSK (state, instr); break;
3598 case 0x106: case 0x306: case 0x506: case 0x706:
3599 case 0x906: case 0xb06: case 0xd06: case 0xf06:
3600 status = WCMPGT (state, instr); break;
3601 case 0x00e: case 0x20e: case 0x40e: case 0x60e:
3602 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
3603 status = WUNPCKEL (state, instr); break;
3604 case 0x00c: case 0x20c: case 0x40c: case 0x60c:
3605 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
3606 status = WUNPCKEH (state, instr); break;
3607 case 0x204: case 0x604: case 0xa04: case 0xe04:
3608 case 0x214: case 0x614: case 0xa14: case 0xe14:
3609 status = WSRL (state, instr); break;
3610 case 0x004: case 0x404: case 0x804: case 0xc04:
3611 case 0x014: case 0x414: case 0x814: case 0xc14:
3612 status = WSRA (state, instr); break;
3613 case 0x104: case 0x504: case 0x904: case 0xd04:
3614 case 0x114: case 0x514: case 0x914: case 0xd14:
3615 status = WSLL (state, instr); break;
3616 case 0x304: case 0x704: case 0xb04: case 0xf04:
3617 case 0x314: case 0x714: case 0xb14: case 0xf14:
3618 status = WROR (state, instr); break;
3619 case 0x116: case 0x316: case 0x516: case 0x716:
3620 case 0x916: case 0xb16: case 0xd16: case 0xf16:
3621 status = WMIN (state, instr); break;
3622 case 0x016: case 0x216: case 0x416: case 0x616:
3623 case 0x816: case 0xa16: case 0xc16: case 0xe16:
3624 status = WMAX (state, instr); break;
3625 case 0x002: case 0x102: case 0x202: case 0x302:
3626 case 0x402: case 0x502: case 0x602: case 0x702:
3627 status = WALIGNI (instr); break;
3628 case 0x01a: case 0x11a: case 0x21a: case 0x31a:
3629 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
3630 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
3631 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
3632 status = WSUB (state, instr); break;
454de2ee 3633 case 0x01e: case 0x11e: case 0x21e: case 0x31e:
0f026fd0
NC
3634 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
3635 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
3636 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
3637 status = WSHUFH (instr); break;
3638 case 0x018: case 0x118: case 0x218: case 0x318:
3639 case 0x418: case 0x518: case 0x618: case 0x718:
3640 case 0x818: case 0x918: case 0xa18: case 0xb18:
3641 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
3642 status = WADD (state, instr); break;
3643 case 0x008: case 0x108: case 0x208: case 0x308:
3644 case 0x408: case 0x508: case 0x608: case 0x708:
3645 case 0x808: case 0x908: case 0xa08: case 0xb08:
3646 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
3647 status = WPACK (state, instr); break;
3648 case 0x201: case 0x203: case 0x205: case 0x207:
3649 case 0x209: case 0x20b: case 0x20d: case 0x20f:
454de2ee
NC
3650 case 0x211: case 0x213: case 0x215: case 0x217:
3651 case 0x219: case 0x21b: case 0x21d: case 0x21f:
0f026fd0
NC
3652 switch (BITS (16, 19))
3653 {
3654 case 0x0: status = TMIA (state, instr); break;
3655 case 0x8: status = TMIAPH (state, instr); break;
3656 case 0xc:
3657 case 0xd:
3658 case 0xe:
3659 case 0xf: status = TMIAxy (state, instr); break;
3660 default: break;
3661 }
3662 break;
3663 default:
3664 break;
3665 }
3666 return status;
3667}
3668
3669/* Process a possibly Intel(r) Wireless MMX(tm) technology instruction.
3670 Return true if the instruction was handled. */
3671
3672int
3673ARMul_HandleIwmmxt (ARMul_State * state, ARMword instr)
454de2ee 3674{
0f026fd0
NC
3675 int status = ARMul_BUSY;
3676
3677 if (BITS (24, 27) == 0xe)
3678 {
3679 status = Process_Instruction (state, instr);
3680 }
3681 else if (BITS (25, 27) == 0x6)
3682 {
3683 if (BITS (4, 11) == 0x0 && BITS (20, 24) == 0x4)
3684 status = TMCRR (state, instr);
3685 else if (BITS (9, 11) == 0x0)
3686 {
3687 if (BIT (20) == 0x0)
3688 status = WSTR (state, instr);
3689 else if (BITS (20, 24) == 0x5)
3690 status = TMRRC (state, instr);
3691 else
3692 status = WLDR (state, instr);
3693 }
3694 }
3695
3696 if (status == ARMul_CANT)
3697 {
3698 /* If the instruction was a recognised but illegal,
3699 perform the abort here rather than returning false.
3700 If we return false then ARMul_MRC may be called which
3701 will still abort, but which also perform the register
3702 transfer... */
3703 ARMul_Abort (state, ARMul_UndefinedInstrV);
3704 status = ARMul_DONE;
3705 }
3706
3707 return status == ARMul_DONE;
3708}
3709
3710int
3711Fetch_Iwmmxt_Register (unsigned int regnum, unsigned char * memory)
3712{
3713 if (regnum >= 16)
3714 {
3715 memcpy (memory, wC + (regnum - 16), sizeof wC [0]);
3716 return sizeof wC [0];
3717 }
3718 else
3719 {
3720 memcpy (memory, wR + regnum, sizeof wR [0]);
3721 return sizeof wR [0];
3722 }
3723}
3724
3725int
ed60d3ed 3726Store_Iwmmxt_Register (unsigned int regnum, const unsigned char * memory)
0f026fd0
NC
3727{
3728 if (regnum >= 16)
3729 {
3730 memcpy (wC + (regnum - 16), memory, sizeof wC [0]);
3731 return sizeof wC [0];
3732 }
3733 else
3734 {
3735 memcpy (wR + regnum, memory, sizeof wR [0]);
3736 return sizeof wR [0];
3737 }
3738}