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