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