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