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