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