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