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