RISC-V: Don't report warnings when linking different privileged spec objects.
[binutils-gdb.git] / sim / arm / iwmmxt.c
blobf0eaa094b4a758c579510b79b9a95d95a95be011
1 /* iwmmxt.c -- Intel(r) Wireless MMX(tm) technology co-processor interface.
2 Copyright (C) 2002-2024 Free Software Foundation, Inc.
3 Contributed by matthew green (mrg@redhat.com).
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* This must come before any other includes. */
19 #include "defs.h"
21 #include <stdlib.h>
22 #include <string.h>
24 #include "armdefs.h"
25 #include "armos.h"
26 #include "armemu.h"
27 #include "ansidecl.h"
28 #include "iwmmxt.h"
30 /* #define DEBUG 1 */
32 /* Intel(r) Wireless MMX(tm) technology co-processor.
33 It uses co-processor numbers (0 and 1). There are 16 vector registers wRx
34 and 16 control registers wCx. Co-processors 0 and 1 are used in MCR/MRC
35 to access wRx and wCx respectively. */
37 static ARMdword wR[16];
38 static ARMword wC[16] = { 0x69051010 };
40 #define SUBSTR(w,t,m,n) ((t)(w << ((sizeof (t) * 8 - 1) - (n))) \
41 >> (((sizeof (t) * 8 - 1) - (n)) + (m)))
42 #define wCBITS(w,x,y) SUBSTR (wC[w], ARMword, x, y)
43 #define wRBITS(w,x,y) SUBSTR (wR[w], ARMdword, x, y)
44 #define wCID 0
45 #define wCon 1
46 #define wCSSF 2
47 #define wCASF 3
48 #define wCGR0 8
49 #define wCGR1 9
50 #define wCGR2 10
51 #define wCGR3 11
53 /* Bits in the wCon register. */
54 #define WCON_CUP (1 << 0)
55 #define WCON_MUP (1 << 1)
57 /* Set the SIMD wCASF flags for 8, 16, 32 or 64-bit operations. */
58 #define SIMD8_SET(x, v, n, b) (x) |= ((v != 0) << ((((b) + 1) * 4) + (n)))
59 #define SIMD16_SET(x, v, n, h) (x) |= ((v != 0) << ((((h) + 1) * 8) + (n)))
60 #define SIMD32_SET(x, v, n, w) (x) |= ((v != 0) << ((((w) + 1) * 16) + (n)))
61 #define SIMD64_SET(x, v, n) (x) |= ((v != 0) << (32 + (n)))
63 /* Flags to pass as "n" above. */
64 #define SIMD_NBIT -1
65 #define SIMD_ZBIT -2
66 #define SIMD_CBIT -3
67 #define SIMD_VBIT -4
69 /* Various status bit macros. */
70 #define NBIT8(x) ((x) & 0x80)
71 #define NBIT16(x) ((x) & 0x8000)
72 #define NBIT32(x) ((x) & 0x80000000)
73 #define NBIT64(x) ((x) & 0x8000000000000000ULL)
74 #define ZBIT8(x) (((x) & 0xff) == 0)
75 #define ZBIT16(x) (((x) & 0xffff) == 0)
76 #define ZBIT32(x) (((x) & 0xffffffff) == 0)
77 #define ZBIT64(x) (x == 0)
79 /* Access byte/half/word "n" of register "x". */
80 #define wRBYTE(x,n) wRBITS ((x), (n) * 8, (n) * 8 + 7)
81 #define wRHALF(x,n) wRBITS ((x), (n) * 16, (n) * 16 + 15)
82 #define wRWORD(x,n) wRBITS ((x), (n) * 32, (n) * 32 + 31)
84 /* Macro to handle how the G bit selects wCGR registers. */
85 #define DECODE_G_BIT(state, instr, shift) \
86 { \
87 unsigned int reg; \
89 reg = BITS (0, 3); \
91 if (BIT (8)) /* G */ \
92 { \
93 if (reg < wCGR0 || reg > wCGR3) \
94 { \
95 ARMul_UndefInstr (state, instr); \
96 return ARMul_DONE; \
97 } \
98 shift = wC [reg]; \
99 } \
100 else \
101 shift = wR [reg]; \
103 shift &= 0xff; \
106 /* Index calculations for the satrv[] array. */
107 #define BITIDX8(x) (x)
108 #define BITIDX16(x) (((x) + 1) * 2 - 1)
109 #define BITIDX32(x) (((x) + 1) * 4 - 1)
111 /* Sign extension macros. */
112 #define EXTEND8(a) ((a) & 0x80 ? ((a) | 0xffffff00) : (a))
113 #define EXTEND16(a) ((a) & 0x8000 ? ((a) | 0xffff0000) : (a))
114 #define EXTEND32(a) ((a) & 0x80000000ULL ? ((a) | 0xffffffff00000000ULL) : (a))
116 /* Set the wCSSF from 8 values. */
117 #define SET_wCSSF(a,b,c,d,e,f,g,h) \
118 wC[wCSSF] = (((h) != 0) << 7) | (((g) != 0) << 6) \
119 | (((f) != 0) << 5) | (((e) != 0) << 4) \
120 | (((d) != 0) << 3) | (((c) != 0) << 2) \
121 | (((b) != 0) << 1) | (((a) != 0) << 0);
123 /* Set the wCSSR from an array with 8 values. */
124 #define SET_wCSSFvec(v) \
125 SET_wCSSF((v)[0],(v)[1],(v)[2],(v)[3],(v)[4],(v)[5],(v)[6],(v)[7])
127 /* Size qualifiers for vector operations. */
128 #define Bqual 0
129 #define Hqual 1
130 #define Wqual 2
131 #define Dqual 3
133 /* Saturation qualifiers for vector operations. */
134 #define NoSaturation 0
135 #define UnsignedSaturation 1
136 #define SignedSaturation 3
139 /* Prototypes. */
140 static ARMword Add32 (ARMword, ARMword, int *, int *, ARMword);
141 static ARMdword AddS32 (ARMdword, ARMdword, int *, int *);
142 static ARMdword AddU32 (ARMdword, ARMdword, int *, int *);
143 static ARMword AddS16 (ARMword, ARMword, int *, int *);
144 static ARMword AddU16 (ARMword, ARMword, int *, int *);
145 static ARMword AddS8 (ARMword, ARMword, int *, int *);
146 static ARMword AddU8 (ARMword, ARMword, int *, int *);
147 static ARMword Sub32 (ARMword, ARMword, int *, int *, ARMword);
148 static ARMdword SubS32 (ARMdword, ARMdword, int *, int *);
149 static ARMdword SubU32 (ARMdword, ARMdword, int *, int *);
150 static ARMword SubS16 (ARMword, ARMword, int *, int *);
151 static ARMword SubS8 (ARMword, ARMword, int *, int *);
152 static ARMword SubU16 (ARMword, ARMword, int *, int *);
153 static ARMword SubU8 (ARMword, ARMword, int *, int *);
154 static unsigned char IwmmxtSaturateU8 (signed short, int *);
155 static signed char IwmmxtSaturateS8 (signed short, int *);
156 static unsigned short IwmmxtSaturateU16 (signed int, int *);
157 static signed short IwmmxtSaturateS16 (signed int, int *);
158 static unsigned long IwmmxtSaturateU32 (signed long long, int *);
159 static signed long IwmmxtSaturateS32 (signed long long, int *);
160 static ARMword Compute_Iwmmxt_Address (ARMul_State *, ARMword, int *);
161 static ARMdword Iwmmxt_Load_Double_Word (ARMul_State *, ARMword);
162 static ARMword Iwmmxt_Load_Word (ARMul_State *, ARMword);
163 static ARMword Iwmmxt_Load_Half_Word (ARMul_State *, ARMword);
164 static ARMword Iwmmxt_Load_Byte (ARMul_State *, ARMword);
165 static void Iwmmxt_Store_Double_Word (ARMul_State *, ARMword, ARMdword);
166 static void Iwmmxt_Store_Word (ARMul_State *, ARMword, ARMword);
167 static void Iwmmxt_Store_Half_Word (ARMul_State *, ARMword, ARMword);
168 static void Iwmmxt_Store_Byte (ARMul_State *, ARMword, ARMword);
169 static int Process_Instruction (ARMul_State *, ARMword);
171 static int TANDC (ARMul_State *, ARMword);
172 static int TBCST (ARMul_State *, ARMword);
173 static int TEXTRC (ARMul_State *, ARMword);
174 static int TEXTRM (ARMul_State *, ARMword);
175 static int TINSR (ARMul_State *, ARMword);
176 static int TMCR (ARMul_State *, ARMword);
177 static int TMCRR (ARMul_State *, ARMword);
178 static int TMIA (ARMul_State *, ARMword);
179 static int TMIAPH (ARMul_State *, ARMword);
180 static int TMIAxy (ARMul_State *, ARMword);
181 static int TMOVMSK (ARMul_State *, ARMword);
182 static int TMRC (ARMul_State *, ARMword);
183 static int TMRRC (ARMul_State *, ARMword);
184 static int TORC (ARMul_State *, ARMword);
185 static int WACC (ARMul_State *, ARMword);
186 static int WADD (ARMul_State *, ARMword);
187 static int WALIGNI (ARMword);
188 static int WALIGNR (ARMul_State *, ARMword);
189 static int WAND (ARMword);
190 static int WANDN (ARMword);
191 static int WAVG2 (ARMword);
192 static int WCMPEQ (ARMul_State *, ARMword);
193 static int WCMPGT (ARMul_State *, ARMword);
194 static int WLDR (ARMul_State *, ARMword);
195 static int WMAC (ARMword);
196 static int WMADD (ARMword);
197 static int WMAX (ARMul_State *, ARMword);
198 static int WMIN (ARMul_State *, ARMword);
199 static int WMUL (ARMword);
200 static int WOR (ARMword);
201 static int WPACK (ARMul_State *, ARMword);
202 static int WROR (ARMul_State *, ARMword);
203 static int WSAD (ARMword);
204 static int WSHUFH (ARMword);
205 static int WSLL (ARMul_State *, ARMword);
206 static int WSRA (ARMul_State *, ARMword);
207 static int WSRL (ARMul_State *, ARMword);
208 static int WSTR (ARMul_State *, ARMword);
209 static int WSUB (ARMul_State *, ARMword);
210 static int WUNPCKEH (ARMul_State *, ARMword);
211 static int WUNPCKEL (ARMul_State *, ARMword);
212 static int WUNPCKIH (ARMul_State *, ARMword);
213 static int WUNPCKIL (ARMul_State *, ARMword);
214 static int WXOR (ARMword);
216 /* This function does the work of adding two 32bit values
217 together, and calculating if a carry has occurred. */
219 static ARMword
220 Add32 (ARMword a1,
221 ARMword a2,
222 int * carry_ptr,
223 int * overflow_ptr,
224 ARMword sign_mask)
226 ARMword result = (a1 + a2);
227 unsigned int uresult = (unsigned int) result;
228 unsigned int ua1 = (unsigned int) a1;
230 /* If (result == a1) and (a2 == 0),
231 or (result > a2) then we have no carry. */
232 * carry_ptr = ((uresult == ua1) ? (a2 != 0) : (uresult < ua1));
234 /* Overflow occurs when both arguments are the
235 same sign, but the result is a different sign. */
236 * overflow_ptr = ( ( (result & sign_mask) && !(a1 & sign_mask) && !(a2 & sign_mask))
237 || (!(result & sign_mask) && (a1 & sign_mask) && (a2 & sign_mask)));
239 return result;
242 static ARMdword
243 AddS32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr)
245 ARMdword result;
246 unsigned int uresult;
247 unsigned int ua1;
249 a1 = EXTEND32 (a1);
250 a2 = EXTEND32 (a2);
252 result = a1 + a2;
253 uresult = (unsigned int) result;
254 ua1 = (unsigned int) a1;
256 * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1));
258 * overflow_ptr = ( ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL))
259 || (!(result & 0x80000000ULL) && (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL)));
261 return result;
264 static ARMdword
265 AddU32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr)
267 ARMdword result;
268 unsigned int uresult;
269 unsigned int ua1;
271 a1 &= 0xffffffff;
272 a2 &= 0xffffffff;
274 result = a1 + a2;
275 uresult = (unsigned int) result;
276 ua1 = (unsigned int) a1;
278 * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1));
280 * overflow_ptr = ( ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL))
281 || (!(result & 0x80000000ULL) && (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL)));
283 return result;
286 static ARMword
287 AddS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
289 a1 = EXTEND16 (a1);
290 a2 = EXTEND16 (a2);
292 return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
295 static ARMword
296 AddU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
298 a1 &= 0xffff;
299 a2 &= 0xffff;
301 return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
304 static ARMword
305 AddS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
307 a1 = EXTEND8 (a1);
308 a2 = EXTEND8 (a2);
310 return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
313 static ARMword
314 AddU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
316 a1 &= 0xff;
317 a2 &= 0xff;
319 return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
322 static ARMword
323 Sub32 (ARMword a1,
324 ARMword a2,
325 int * borrow_ptr,
326 int * overflow_ptr,
327 ARMword sign_mask)
329 ARMword result = (a1 - a2);
330 unsigned int ua1 = (unsigned int) a1;
331 unsigned int ua2 = (unsigned int) a2;
333 /* A borrow occurs if a2 is (unsigned) larger than a1.
334 However the carry flag is *cleared* if a borrow occurs. */
335 * borrow_ptr = ! (ua2 > ua1);
337 /* Overflow occurs when a negative number is subtracted from a
338 positive number and the result is negative or a positive
339 number is subtracted from a negative number and the result is
340 positive. */
341 * overflow_ptr = ( (! (a1 & sign_mask) && (a2 & sign_mask) && (result & sign_mask))
342 || ((a1 & sign_mask) && ! (a2 & sign_mask) && ! (result & sign_mask)));
344 return result;
347 static ARMdword
348 SubS32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr)
350 ARMdword result;
351 unsigned int ua1;
352 unsigned int ua2;
354 a1 = EXTEND32 (a1);
355 a2 = EXTEND32 (a2);
357 result = a1 - a2;
358 ua1 = (unsigned int) a1;
359 ua2 = (unsigned int) a2;
361 * borrow_ptr = ! (ua2 > ua1);
363 * overflow_ptr = ( (! (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL) && (result & 0x80000000ULL))
364 || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL)));
366 return result;
369 static ARMword
370 SubS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
372 a1 = EXTEND16 (a1);
373 a2 = EXTEND16 (a2);
375 return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
378 static ARMword
379 SubS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
381 a1 = EXTEND8 (a1);
382 a2 = EXTEND8 (a2);
384 return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
387 static ARMword
388 SubU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
390 a1 &= 0xffff;
391 a2 &= 0xffff;
393 return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
396 static ARMword
397 SubU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
399 a1 &= 0xff;
400 a2 &= 0xff;
402 return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
405 static ARMdword
406 SubU32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr)
408 ARMdword result;
409 unsigned int ua1;
410 unsigned int ua2;
412 a1 &= 0xffffffff;
413 a2 &= 0xffffffff;
415 result = a1 - a2;
416 ua1 = (unsigned int) a1;
417 ua2 = (unsigned int) a2;
419 * borrow_ptr = ! (ua2 > ua1);
421 * overflow_ptr = ( (! (a1 & 0x80000000ULL) && (a2 & 0x80000000ULL) && (result & 0x80000000ULL))
422 || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL)));
424 return result;
427 /* For the saturation. */
429 static unsigned char
430 IwmmxtSaturateU8 (signed short val, int * sat)
432 unsigned char rv;
434 if (val < 0)
436 rv = 0;
437 *sat = 1;
439 else if (val > 0xff)
441 rv = 0xff;
442 *sat = 1;
444 else
446 rv = val & 0xff;
447 *sat = 0;
449 return rv;
452 static signed char
453 IwmmxtSaturateS8 (signed short val, int * sat)
455 signed char rv;
457 if (val < -0x80)
459 rv = -0x80;
460 *sat = 1;
462 else if (val > 0x7f)
464 rv = 0x7f;
465 *sat = 1;
467 else
469 rv = val & 0xff;
470 *sat = 0;
472 return rv;
475 static unsigned short
476 IwmmxtSaturateU16 (signed int val, int * sat)
478 unsigned short rv;
480 if (val < 0)
482 rv = 0;
483 *sat = 1;
485 else if (val > 0xffff)
487 rv = 0xffff;
488 *sat = 1;
490 else
492 rv = val & 0xffff;
493 *sat = 0;
495 return rv;
498 static signed short
499 IwmmxtSaturateS16 (signed int val, int * sat)
501 signed short rv;
503 if (val < -0x8000)
505 rv = - 0x8000;
506 *sat = 1;
508 else if (val > 0x7fff)
510 rv = 0x7fff;
511 *sat = 1;
513 else
515 rv = val & 0xffff;
516 *sat = 0;
518 return rv;
521 static unsigned long
522 IwmmxtSaturateU32 (signed long long val, int * sat)
524 unsigned long rv;
526 if (val < 0)
528 rv = 0;
529 *sat = 1;
531 else if (val > 0xffffffff)
533 rv = 0xffffffff;
534 *sat = 1;
536 else
538 rv = val & 0xffffffff;
539 *sat = 0;
541 return rv;
544 static signed long
545 IwmmxtSaturateS32 (signed long long val, int * sat)
547 signed long rv;
549 if (val < -0x80000000LL)
551 rv = -0x80000000;
552 *sat = 1;
554 else if (val > 0x7fffffff)
556 rv = 0x7fffffff;
557 *sat = 1;
559 else
561 rv = val & 0xffffffff;
562 *sat = 0;
564 return rv;
567 /* Intel(r) Wireless MMX(tm) technology Acessor functions. */
569 unsigned
570 IwmmxtLDC (ARMul_State * state ATTRIBUTE_UNUSED,
571 unsigned type ATTRIBUTE_UNUSED,
572 ARMword instr,
573 ARMword data)
575 return ARMul_CANT;
578 unsigned
579 IwmmxtSTC (ARMul_State * state ATTRIBUTE_UNUSED,
580 unsigned type ATTRIBUTE_UNUSED,
581 ARMword instr,
582 ARMword * data)
584 return ARMul_CANT;
587 unsigned
588 IwmmxtMRC (ARMul_State * state ATTRIBUTE_UNUSED,
589 unsigned type ATTRIBUTE_UNUSED,
590 ARMword instr,
591 ARMword * value)
593 return ARMul_CANT;
596 unsigned
597 IwmmxtMCR (ARMul_State * state ATTRIBUTE_UNUSED,
598 unsigned type ATTRIBUTE_UNUSED,
599 ARMword instr,
600 ARMword value)
602 return ARMul_CANT;
605 unsigned
606 IwmmxtCDP (ARMul_State * state, unsigned type, ARMword instr)
608 return ARMul_CANT;
611 /* Intel(r) Wireless MMX(tm) technology instruction implementations. */
613 static int
614 TANDC (ARMul_State * state, ARMword instr)
616 ARMword cpsr;
618 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
619 return ARMul_CANT;
621 #ifdef DEBUG
622 fprintf (stderr, "tandc\n");
623 #endif
625 /* The Rd field must be r15. */
626 if (BITS (12, 15) != 15)
627 return ARMul_CANT;
629 /* The CRn field must be r3. */
630 if (BITS (16, 19) != 3)
631 return ARMul_CANT;
633 /* The CRm field must be r0. */
634 if (BITS (0, 3) != 0)
635 return ARMul_CANT;
637 cpsr = ARMul_GetCPSR (state) & 0x0fffffff;
639 switch (BITS (22, 23))
641 case Bqual:
642 cpsr |= ( (wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 24, 27)
643 & wCBITS (wCASF, 20, 23) & wCBITS (wCASF, 16, 19)
644 & wCBITS (wCASF, 12, 15) & wCBITS (wCASF, 8, 11)
645 & wCBITS (wCASF, 4, 7) & wCBITS (wCASF, 0, 3)) << 28);
646 break;
648 case Hqual:
649 cpsr |= ( (wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 20, 23)
650 & wCBITS (wCASF, 12, 15) & wCBITS (wCASF, 4, 7)) << 28);
651 break;
653 case Wqual:
654 cpsr |= ((wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 12, 15)) << 28);
655 break;
657 default:
658 ARMul_UndefInstr (state, instr);
659 return ARMul_DONE;
662 ARMul_SetCPSR (state, cpsr);
664 return ARMul_DONE;
667 static int
668 TBCST (ARMul_State * state, ARMword instr)
670 ARMdword Rn;
671 int wRd;
673 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
674 return ARMul_CANT;
676 #ifdef DEBUG
677 fprintf (stderr, "tbcst\n");
678 #endif
680 Rn = state->Reg [BITS (12, 15)];
681 if (BITS (12, 15) == 15)
682 Rn &= 0xfffffffc;
684 wRd = BITS (16, 19);
686 switch (BITS (6, 7))
688 case Bqual:
689 Rn &= 0xff;
690 wR [wRd] = (Rn << 56) | (Rn << 48) | (Rn << 40) | (Rn << 32)
691 | (Rn << 24) | (Rn << 16) | (Rn << 8) | Rn;
692 break;
694 case Hqual:
695 Rn &= 0xffff;
696 wR [wRd] = (Rn << 48) | (Rn << 32) | (Rn << 16) | Rn;
697 break;
699 case Wqual:
700 Rn &= 0xffffffff;
701 wR [wRd] = (Rn << 32) | Rn;
702 break;
704 default:
705 ARMul_UndefInstr (state, instr);
706 break;
709 wC [wCon] |= WCON_MUP;
710 return ARMul_DONE;
713 static int
714 TEXTRC (ARMul_State * state, ARMword instr)
716 ARMword cpsr;
717 ARMword selector;
719 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
720 return ARMul_CANT;
722 #ifdef DEBUG
723 fprintf (stderr, "textrc\n");
724 #endif
726 /* The Rd field must be r15. */
727 if (BITS (12, 15) != 15)
728 return ARMul_CANT;
730 /* The CRn field must be r3. */
731 if (BITS (16, 19) != 3)
732 return ARMul_CANT;
734 /* The CRm field must be 0xxx. */
735 if (BIT (3) != 0)
736 return ARMul_CANT;
738 selector = BITS (0, 2);
739 cpsr = ARMul_GetCPSR (state) & 0x0fffffff;
741 switch (BITS (22, 23))
743 case Bqual: selector *= 4; break;
744 case Hqual: selector = ((selector & 3) * 8) + 4; break;
745 case Wqual: selector = ((selector & 1) * 16) + 12; break;
747 default:
748 ARMul_UndefInstr (state, instr);
749 return ARMul_DONE;
752 cpsr |= wCBITS (wCASF, selector, selector + 3) << 28;
753 ARMul_SetCPSR (state, cpsr);
755 return ARMul_DONE;
758 static int
759 TEXTRM (ARMul_State * state, ARMword instr)
761 ARMword Rd;
762 int offset;
763 int wRn;
764 int sign;
766 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
767 return ARMul_CANT;
769 #ifdef DEBUG
770 fprintf (stderr, "textrm\n");
771 #endif
773 wRn = BITS (16, 19);
774 sign = BIT (3);
775 offset = BITS (0, 2);
777 switch (BITS (22, 23))
779 case Bqual:
780 offset *= 8;
781 Rd = wRBITS (wRn, offset, offset + 7);
782 if (sign)
783 Rd = EXTEND8 (Rd);
784 break;
786 case Hqual:
787 offset = (offset & 3) * 16;
788 Rd = wRBITS (wRn, offset, offset + 15);
789 if (sign)
790 Rd = EXTEND16 (Rd);
791 break;
793 case Wqual:
794 offset = (offset & 1) * 32;
795 Rd = wRBITS (wRn, offset, offset + 31);
796 break;
798 default:
799 ARMul_UndefInstr (state, instr);
800 return ARMul_DONE;
803 if (BITS (12, 15) == 15)
804 ARMul_UndefInstr (state, instr);
805 else
806 state->Reg [BITS (12, 15)] = Rd;
808 return ARMul_DONE;
811 static int
812 TINSR (ARMul_State * state, ARMword instr)
814 ARMdword data;
815 ARMword offset;
816 int wRd;
818 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
819 return ARMul_CANT;
821 #ifdef DEBUG
822 fprintf (stderr, "tinsr\n");
823 #endif
825 wRd = BITS (16, 19);
826 data = state->Reg [BITS (12, 15)];
827 offset = BITS (0, 2);
829 switch (BITS (6, 7))
831 case Bqual:
832 data &= 0xff;
833 switch (offset)
835 case 0: wR [wRd] = data | (wRBITS (wRd, 8, 63) << 8); break;
836 case 1: wR [wRd] = wRBITS (wRd, 0, 7) | (data << 8) | (wRBITS (wRd, 16, 63) << 16); break;
837 case 2: wR [wRd] = wRBITS (wRd, 0, 15) | (data << 16) | (wRBITS (wRd, 24, 63) << 24); break;
838 case 3: wR [wRd] = wRBITS (wRd, 0, 23) | (data << 24) | (wRBITS (wRd, 32, 63) << 32); break;
839 case 4: wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32) | (wRBITS (wRd, 40, 63) << 40); break;
840 case 5: wR [wRd] = wRBITS (wRd, 0, 39) | (data << 40) | (wRBITS (wRd, 48, 63) << 48); break;
841 case 6: wR [wRd] = wRBITS (wRd, 0, 47) | (data << 48) | (wRBITS (wRd, 56, 63) << 56); break;
842 case 7: wR [wRd] = wRBITS (wRd, 0, 55) | (data << 56); break;
844 break;
846 case Hqual:
847 data &= 0xffff;
849 switch (offset & 3)
851 case 0: wR [wRd] = data | (wRBITS (wRd, 16, 63) << 16); break;
852 case 1: wR [wRd] = wRBITS (wRd, 0, 15) | (data << 16) | (wRBITS (wRd, 32, 63) << 32); break;
853 case 2: wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32) | (wRBITS (wRd, 48, 63) << 48); break;
854 case 3: wR [wRd] = wRBITS (wRd, 0, 47) | (data << 48); break;
856 break;
858 case Wqual:
859 if (offset & 1)
860 wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32);
861 else
862 wR [wRd] = (wRBITS (wRd, 32, 63) << 32) | data;
863 break;
865 default:
866 ARMul_UndefInstr (state, instr);
867 break;
870 wC [wCon] |= WCON_MUP;
871 return ARMul_DONE;
874 static int
875 TMCR (ARMul_State * state, ARMword instr)
877 ARMword val;
878 int wCreg;
880 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
881 return ARMul_CANT;
883 #ifdef DEBUG
884 fprintf (stderr, "tmcr\n");
885 #endif
887 if (BITS (0, 3) != 0)
888 return ARMul_CANT;
890 val = state->Reg [BITS (12, 15)];
891 if (BITS (12, 15) == 15)
892 val &= 0xfffffffc;
894 wCreg = BITS (16, 19);
896 switch (wCreg)
898 case wCID:
899 /* The wCID register is read only. */
900 break;
902 case wCon:
903 /* Writing to the MUP or CUP bits clears them. */
904 wC [wCon] &= ~ (val & 0x3);
905 break;
907 case wCSSF:
908 /* Only the bottom 8 bits can be written to.
909 The higher bits write as zero. */
910 wC [wCSSF] = (val & 0xff);
911 wC [wCon] |= WCON_CUP;
912 break;
914 default:
915 wC [wCreg] = val;
916 wC [wCon] |= WCON_CUP;
917 break;
920 return ARMul_DONE;
923 static int
924 TMCRR (ARMul_State * state, ARMword instr)
926 ARMdword RdHi = state->Reg [BITS (16, 19)];
927 ARMword RdLo = state->Reg [BITS (12, 15)];
929 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
930 return ARMul_CANT;
932 #ifdef DEBUG
933 fprintf (stderr, "tmcrr\n");
934 #endif
936 if ((BITS (16, 19) == 15) || (BITS (12, 15) == 15))
937 return ARMul_CANT;
939 wR [BITS (0, 3)] = (RdHi << 32) | RdLo;
941 wC [wCon] |= WCON_MUP;
943 return ARMul_DONE;
946 static int
947 TMIA (ARMul_State * state, ARMword instr)
949 signed long long a, b;
951 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
952 return ARMul_CANT;
954 #ifdef DEBUG
955 fprintf (stderr, "tmia\n");
956 #endif
958 if ((BITS (0, 3) == 15) || (BITS (12, 15) == 15))
960 ARMul_UndefInstr (state, instr);
961 return ARMul_DONE;
964 a = state->Reg [BITS (0, 3)];
965 b = state->Reg [BITS (12, 15)];
967 a = EXTEND32 (a);
968 b = EXTEND32 (b);
970 wR [BITS (5, 8)] += a * b;
971 wC [wCon] |= WCON_MUP;
973 return ARMul_DONE;
976 static int
977 TMIAPH (ARMul_State * state, ARMword instr)
979 signed long a, b, result;
980 signed long long r;
981 ARMword Rm = state->Reg [BITS (0, 3)];
982 ARMword Rs = state->Reg [BITS (12, 15)];
984 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
985 return ARMul_CANT;
987 #ifdef DEBUG
988 fprintf (stderr, "tmiaph\n");
989 #endif
991 if (BITS (0, 3) == 15 || BITS (12, 15) == 15)
993 ARMul_UndefInstr (state, instr);
994 return ARMul_DONE;
997 a = SUBSTR (Rs, ARMword, 16, 31);
998 b = SUBSTR (Rm, ARMword, 16, 31);
1000 a = EXTEND16 (a);
1001 b = EXTEND16 (b);
1003 result = a * b;
1005 r = result;
1006 r = EXTEND32 (r);
1008 wR [BITS (5, 8)] += r;
1010 a = SUBSTR (Rs, ARMword, 0, 15);
1011 b = SUBSTR (Rm, ARMword, 0, 15);
1013 a = EXTEND16 (a);
1014 b = EXTEND16 (b);
1016 result = a * b;
1018 r = result;
1019 r = EXTEND32 (r);
1021 wR [BITS (5, 8)] += r;
1022 wC [wCon] |= WCON_MUP;
1024 return ARMul_DONE;
1027 static int
1028 TMIAxy (ARMul_State * state, ARMword instr)
1030 ARMword Rm;
1031 ARMword Rs;
1032 long long temp;
1034 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1035 return ARMul_CANT;
1037 #ifdef DEBUG
1038 fprintf (stderr, "tmiaxy\n");
1039 #endif
1041 if (BITS (0, 3) == 15 || BITS (12, 15) == 15)
1043 ARMul_UndefInstr (state, instr);
1044 return ARMul_DONE;
1047 Rm = state->Reg [BITS (0, 3)];
1048 if (BIT (17))
1049 Rm >>= 16;
1050 else
1051 Rm &= 0xffff;
1053 Rs = state->Reg [BITS (12, 15)];
1054 if (BIT (16))
1055 Rs >>= 16;
1056 else
1057 Rs &= 0xffff;
1059 if (Rm & (1 << 15))
1060 Rm -= 1 << 16;
1062 if (Rs & (1 << 15))
1063 Rs -= 1 << 16;
1065 Rm *= Rs;
1066 temp = Rm;
1068 if (temp & (1 << 31))
1069 temp -= 1ULL << 32;
1071 wR [BITS (5, 8)] += temp;
1072 wC [wCon] |= WCON_MUP;
1074 return ARMul_DONE;
1077 static int
1078 TMOVMSK (ARMul_State * state, ARMword instr)
1080 ARMdword result;
1081 int wRn;
1083 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1084 return ARMul_CANT;
1086 #ifdef DEBUG
1087 fprintf (stderr, "tmovmsk\n");
1088 #endif
1090 /* The CRm field must be r0. */
1091 if (BITS (0, 3) != 0)
1092 return ARMul_CANT;
1094 wRn = BITS (16, 19);
1096 switch (BITS (22, 23))
1098 case Bqual:
1099 result = ( (wRBITS (wRn, 63, 63) << 7)
1100 | (wRBITS (wRn, 55, 55) << 6)
1101 | (wRBITS (wRn, 47, 47) << 5)
1102 | (wRBITS (wRn, 39, 39) << 4)
1103 | (wRBITS (wRn, 31, 31) << 3)
1104 | (wRBITS (wRn, 23, 23) << 2)
1105 | (wRBITS (wRn, 15, 15) << 1)
1106 | (wRBITS (wRn, 7, 7) << 0));
1107 break;
1109 case Hqual:
1110 result = ( (wRBITS (wRn, 63, 63) << 3)
1111 | (wRBITS (wRn, 47, 47) << 2)
1112 | (wRBITS (wRn, 31, 31) << 1)
1113 | (wRBITS (wRn, 15, 15) << 0));
1114 break;
1116 case Wqual:
1117 result = (wRBITS (wRn, 63, 63) << 1) | wRBITS (wRn, 31, 31);
1118 break;
1120 default:
1121 ARMul_UndefInstr (state, instr);
1122 return ARMul_DONE;
1125 state->Reg [BITS (12, 15)] = result;
1127 return ARMul_DONE;
1130 static int
1131 TMRC (ARMul_State * state, ARMword instr)
1133 int reg = BITS (12, 15);
1135 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1136 return ARMul_CANT;
1138 #ifdef DEBUG
1139 fprintf (stderr, "tmrc\n");
1140 #endif
1142 if (BITS (0, 3) != 0)
1143 return ARMul_CANT;
1145 if (reg == 15)
1146 ARMul_UndefInstr (state, instr);
1147 else
1148 state->Reg [reg] = wC [BITS (16, 19)];
1150 return ARMul_DONE;
1153 static int
1154 TMRRC (ARMul_State * state, ARMword instr)
1156 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1157 return ARMul_CANT;
1159 #ifdef DEBUG
1160 fprintf (stderr, "tmrrc\n");
1161 #endif
1163 if ((BITS (16, 19) == 15) || (BITS (12, 15) == 15) || (BITS (4, 11) != 0))
1164 ARMul_UndefInstr (state, instr);
1165 else
1167 state->Reg [BITS (16, 19)] = wRBITS (BITS (0, 3), 32, 63);
1168 state->Reg [BITS (12, 15)] = wRBITS (BITS (0, 3), 0, 31);
1171 return ARMul_DONE;
1174 static int
1175 TORC (ARMul_State * state, ARMword instr)
1177 ARMword cpsr = ARMul_GetCPSR (state);
1179 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1180 return ARMul_CANT;
1182 #ifdef DEBUG
1183 fprintf (stderr, "torc\n");
1184 #endif
1186 /* The Rd field must be r15. */
1187 if (BITS (12, 15) != 15)
1188 return ARMul_CANT;
1190 /* The CRn field must be r3. */
1191 if (BITS (16, 19) != 3)
1192 return ARMul_CANT;
1194 /* The CRm field must be r0. */
1195 if (BITS (0, 3) != 0)
1196 return ARMul_CANT;
1198 cpsr &= 0x0fffffff;
1200 switch (BITS (22, 23))
1202 case Bqual:
1203 cpsr |= ( (wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 24, 27)
1204 | wCBITS (wCASF, 20, 23) | wCBITS (wCASF, 16, 19)
1205 | wCBITS (wCASF, 12, 15) | wCBITS (wCASF, 8, 11)
1206 | wCBITS (wCASF, 4, 7) | wCBITS (wCASF, 0, 3)) << 28);
1207 break;
1209 case Hqual:
1210 cpsr |= ( (wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 20, 23)
1211 | wCBITS (wCASF, 12, 15) | wCBITS (wCASF, 4, 7)) << 28);
1212 break;
1214 case Wqual:
1215 cpsr |= ((wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 12, 15)) << 28);
1216 break;
1218 default:
1219 ARMul_UndefInstr (state, instr);
1220 return ARMul_DONE;
1223 ARMul_SetCPSR (state, cpsr);
1225 return ARMul_DONE;
1228 static int
1229 WACC (ARMul_State * state, ARMword instr)
1231 int wRn;
1233 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1234 return ARMul_CANT;
1236 #ifdef DEBUG
1237 fprintf (stderr, "wacc\n");
1238 #endif
1240 wRn = BITS (16, 19);
1242 switch (BITS (22, 23))
1244 case Bqual:
1245 wR [BITS (12, 15)] =
1246 wRBITS (wRn, 56, 63) + wRBITS (wRn, 48, 55)
1247 + wRBITS (wRn, 40, 47) + wRBITS (wRn, 32, 39)
1248 + wRBITS (wRn, 24, 31) + wRBITS (wRn, 16, 23)
1249 + wRBITS (wRn, 8, 15) + wRBITS (wRn, 0, 7);
1250 break;
1252 case Hqual:
1253 wR [BITS (12, 15)] =
1254 wRBITS (wRn, 48, 63) + wRBITS (wRn, 32, 47)
1255 + wRBITS (wRn, 16, 31) + wRBITS (wRn, 0, 15);
1256 break;
1258 case Wqual:
1259 wR [BITS (12, 15)] = wRBITS (wRn, 32, 63) + wRBITS (wRn, 0, 31);
1260 break;
1262 default:
1263 ARMul_UndefInstr (state, instr);
1264 break;
1267 wC [wCon] |= WCON_MUP;
1268 return ARMul_DONE;
1271 static int
1272 WADD (ARMul_State * state, ARMword instr)
1274 ARMdword r = 0;
1275 ARMdword x;
1276 ARMdword s;
1277 ARMword psr = 0;
1278 int i;
1279 int carry;
1280 int overflow;
1281 int satrv[8];
1283 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1284 return ARMul_CANT;
1286 #ifdef DEBUG
1287 fprintf (stderr, "wadd\n");
1288 #endif
1290 /* Add two numbers using the specified function,
1291 leaving setting the carry bit as required. */
1292 #define ADDx(x, y, m, f) \
1293 (*f) (wRBITS (BITS (16, 19), (x), (y)) & (m), \
1294 wRBITS (BITS ( 0, 3), (x), (y)) & (m), \
1295 & carry, & overflow)
1297 switch (BITS (22, 23))
1299 case Bqual:
1300 for (i = 0; i < 8; i++)
1302 switch (BITS (20, 21))
1304 case NoSaturation:
1305 s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddS8);
1306 satrv [BITIDX8 (i)] = 0;
1307 r |= (s & 0xff) << (i * 8);
1308 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
1309 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
1310 SIMD8_SET (psr, carry, SIMD_CBIT, i);
1311 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
1312 break;
1314 case UnsignedSaturation:
1315 s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddU8);
1316 x = IwmmxtSaturateU8 (s, satrv + BITIDX8 (i));
1317 r |= (x & 0xff) << (i * 8);
1318 SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
1319 SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
1320 if (! satrv [BITIDX8 (i)])
1322 SIMD8_SET (psr, carry, SIMD_CBIT, i);
1323 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
1325 break;
1327 case SignedSaturation:
1328 s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddS8);
1329 x = IwmmxtSaturateS8 (s, satrv + BITIDX8 (i));
1330 r |= (x & 0xff) << (i * 8);
1331 SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
1332 SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
1333 if (! satrv [BITIDX8 (i)])
1335 SIMD8_SET (psr, carry, SIMD_CBIT, i);
1336 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
1338 break;
1340 default:
1341 ARMul_UndefInstr (state, instr);
1342 return ARMul_DONE;
1345 break;
1347 case Hqual:
1348 satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
1350 for (i = 0; i < 4; i++)
1352 switch (BITS (20, 21))
1354 case NoSaturation:
1355 s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddS16);
1356 satrv [BITIDX16 (i)] = 0;
1357 r |= (s & 0xffff) << (i * 16);
1358 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
1359 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
1360 SIMD16_SET (psr, carry, SIMD_CBIT, i);
1361 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
1362 break;
1364 case UnsignedSaturation:
1365 s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddU16);
1366 x = IwmmxtSaturateU16 (s, satrv + BITIDX16 (i));
1367 r |= (x & 0xffff) << (i * 16);
1368 SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
1369 SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
1370 if (! satrv [BITIDX16 (i)])
1372 SIMD16_SET (psr, carry, SIMD_CBIT, i);
1373 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
1375 break;
1377 case SignedSaturation:
1378 s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddS16);
1379 x = IwmmxtSaturateS16 (s, satrv + BITIDX16 (i));
1380 r |= (x & 0xffff) << (i * 16);
1381 SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
1382 SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
1383 if (! satrv [BITIDX16 (i)])
1385 SIMD16_SET (psr, carry, SIMD_CBIT, i);
1386 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
1388 break;
1390 default:
1391 ARMul_UndefInstr (state, instr);
1392 return ARMul_DONE;
1395 break;
1397 case Wqual:
1398 satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
1400 for (i = 0; i < 2; i++)
1402 switch (BITS (20, 21))
1404 case NoSaturation:
1405 s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddS32);
1406 satrv [BITIDX32 (i)] = 0;
1407 r |= (s & 0xffffffff) << (i * 32);
1408 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
1409 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
1410 SIMD32_SET (psr, carry, SIMD_CBIT, i);
1411 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
1412 break;
1414 case UnsignedSaturation:
1415 s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddU32);
1416 x = IwmmxtSaturateU32 (s, satrv + BITIDX32 (i));
1417 r |= (x & 0xffffffff) << (i * 32);
1418 SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
1419 SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
1420 if (! satrv [BITIDX32 (i)])
1422 SIMD32_SET (psr, carry, SIMD_CBIT, i);
1423 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
1425 break;
1427 case SignedSaturation:
1428 s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddS32);
1429 x = IwmmxtSaturateS32 (s, satrv + BITIDX32 (i));
1430 r |= (x & 0xffffffff) << (i * 32);
1431 SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
1432 SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
1433 if (! satrv [BITIDX32 (i)])
1435 SIMD32_SET (psr, carry, SIMD_CBIT, i);
1436 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
1438 break;
1440 default:
1441 ARMul_UndefInstr (state, instr);
1442 return ARMul_DONE;
1445 break;
1447 default:
1448 ARMul_UndefInstr (state, instr);
1449 return ARMul_DONE;
1452 wC [wCASF] = psr;
1453 wR [BITS (12, 15)] = r;
1454 wC [wCon] |= (WCON_MUP | WCON_CUP);
1456 SET_wCSSFvec (satrv);
1458 #undef ADDx
1460 return ARMul_DONE;
1463 static int
1464 WALIGNI (ARMword instr)
1466 int shift = BITS (20, 22) * 8;
1468 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1469 return ARMul_CANT;
1471 #ifdef DEBUG
1472 fprintf (stderr, "waligni\n");
1473 #endif
1475 if (shift)
1476 wR [BITS (12, 15)] =
1477 wRBITS (BITS (16, 19), shift, 63)
1478 | (wRBITS (BITS (0, 3), 0, shift) << ((64 - shift)));
1479 else
1480 wR [BITS (12, 15)] = wR [BITS (16, 19)];
1482 wC [wCon] |= WCON_MUP;
1483 return ARMul_DONE;
1486 static int
1487 WALIGNR (ARMul_State * state, ARMword instr)
1489 int shift = (wC [BITS (20, 21) + 8] & 0x7) * 8;
1491 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1492 return ARMul_CANT;
1494 #ifdef DEBUG
1495 fprintf (stderr, "walignr\n");
1496 #endif
1498 if (shift)
1499 wR [BITS (12, 15)] =
1500 wRBITS (BITS (16, 19), shift, 63)
1501 | (wRBITS (BITS (0, 3), 0, shift) << ((64 - shift)));
1502 else
1503 wR [BITS (12, 15)] = wR [BITS (16, 19)];
1505 wC [wCon] |= WCON_MUP;
1506 return ARMul_DONE;
1509 static int
1510 WAND (ARMword instr)
1512 ARMdword result;
1513 ARMword psr = 0;
1515 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1516 return ARMul_CANT;
1518 #ifdef DEBUG
1519 fprintf (stderr, "wand\n");
1520 #endif
1522 result = wR [BITS (16, 19)] & wR [BITS (0, 3)];
1523 wR [BITS (12, 15)] = result;
1525 SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
1526 SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
1528 wC [wCASF] = psr;
1529 wC [wCon] |= (WCON_CUP | WCON_MUP);
1531 return ARMul_DONE;
1534 static int
1535 WANDN (ARMword instr)
1537 ARMdword result;
1538 ARMword psr = 0;
1540 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1541 return ARMul_CANT;
1543 #ifdef DEBUG
1544 fprintf (stderr, "wandn\n");
1545 #endif
1547 result = wR [BITS (16, 19)] & ~ wR [BITS (0, 3)];
1548 wR [BITS (12, 15)] = result;
1550 SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
1551 SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
1553 wC [wCASF] = psr;
1554 wC [wCon] |= (WCON_CUP | WCON_MUP);
1556 return ARMul_DONE;
1559 static int
1560 WAVG2 (ARMword instr)
1562 ARMdword r = 0;
1563 ARMword psr = 0;
1564 ARMdword s;
1565 int i;
1566 int round = BIT (20) ? 1 : 0;
1568 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1569 return ARMul_CANT;
1571 #ifdef DEBUG
1572 fprintf (stderr, "wavg2\n");
1573 #endif
1575 #define AVG2x(x, y, m) (((wRBITS (BITS (16, 19), (x), (y)) & (m)) \
1576 + (wRBITS (BITS ( 0, 3), (x), (y)) & (m)) \
1577 + round) / 2)
1579 if (BIT (22))
1581 for (i = 0; i < 4; i++)
1583 s = AVG2x ((i * 16), (i * 16) + 15, 0xffff) & 0xffff;
1584 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
1585 r |= s << (i * 16);
1588 else
1590 for (i = 0; i < 8; i++)
1592 s = AVG2x ((i * 8), (i * 8) + 7, 0xff) & 0xff;
1593 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
1594 r |= s << (i * 8);
1598 wR [BITS (12, 15)] = r;
1599 wC [wCASF] = psr;
1600 wC [wCon] |= (WCON_CUP | WCON_MUP);
1602 return ARMul_DONE;
1605 static int
1606 WCMPEQ (ARMul_State * state, ARMword instr)
1608 ARMdword r = 0;
1609 ARMword psr = 0;
1610 ARMdword s;
1611 int i;
1613 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1614 return ARMul_CANT;
1616 #ifdef DEBUG
1617 fprintf (stderr, "wcmpeq\n");
1618 #endif
1620 switch (BITS (22, 23))
1622 case Bqual:
1623 for (i = 0; i < 8; i++)
1625 s = wRBYTE (BITS (16, 19), i) == wRBYTE (BITS (0, 3), i) ? 0xff : 0;
1626 r |= s << (i * 8);
1627 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
1628 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
1630 break;
1632 case Hqual:
1633 for (i = 0; i < 4; i++)
1635 s = wRHALF (BITS (16, 19), i) == wRHALF (BITS (0, 3), i) ? 0xffff : 0;
1636 r |= s << (i * 16);
1637 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
1638 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
1640 break;
1642 case Wqual:
1643 for (i = 0; i < 2; i++)
1645 s = wRWORD (BITS (16, 19), i) == wRWORD (BITS (0, 3), i) ? 0xffffffff : 0;
1646 r |= s << (i * 32);
1647 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
1648 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
1650 break;
1652 default:
1653 ARMul_UndefInstr (state, instr);
1654 return ARMul_DONE;
1657 wC [wCASF] = psr;
1658 wR [BITS (12, 15)] = r;
1659 wC [wCon] |= (WCON_CUP | WCON_MUP);
1661 return ARMul_DONE;
1664 static int
1665 WCMPGT (ARMul_State * state, ARMword instr)
1667 ARMdword r = 0;
1668 ARMword psr = 0;
1669 ARMdword s;
1670 int i;
1672 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
1673 return ARMul_CANT;
1675 #ifdef DEBUG
1676 fprintf (stderr, "wcmpgt\n");
1677 #endif
1679 switch (BITS (22, 23))
1681 case Bqual:
1682 if (BIT (21))
1684 /* Use a signed comparison. */
1685 for (i = 0; i < 8; i++)
1687 signed char a, b;
1689 a = wRBYTE (BITS (16, 19), i);
1690 b = wRBYTE (BITS (0, 3), i);
1692 s = (a > b) ? 0xff : 0;
1693 r |= s << (i * 8);
1694 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
1695 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
1698 else
1700 for (i = 0; i < 8; i++)
1702 s = (wRBYTE (BITS (16, 19), i) > wRBYTE (BITS (0, 3), i))
1703 ? 0xff : 0;
1704 r |= s << (i * 8);
1705 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
1706 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
1709 break;
1711 case Hqual:
1712 if (BIT (21))
1714 for (i = 0; i < 4; i++)
1716 signed int a, b;
1718 a = wRHALF (BITS (16, 19), i);
1719 a = EXTEND16 (a);
1721 b = wRHALF (BITS (0, 3), i);
1722 b = EXTEND16 (b);
1724 s = (a > b) ? 0xffff : 0;
1725 r |= s << (i * 16);
1726 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
1727 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
1730 else
1732 for (i = 0; i < 4; i++)
1734 s = (wRHALF (BITS (16, 19), i) > wRHALF (BITS (0, 3), i))
1735 ? 0xffff : 0;
1736 r |= s << (i * 16);
1737 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
1738 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
1741 break;
1743 case Wqual:
1744 if (BIT (21))
1746 for (i = 0; i < 2; i++)
1748 signed long a, b;
1750 a = EXTEND32 (wRWORD (BITS (16, 19), i));
1751 b = EXTEND32 (wRWORD (BITS (0, 3), i));
1753 s = (a > b) ? 0xffffffff : 0;
1754 r |= s << (i * 32);
1756 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
1757 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
1760 else
1762 for (i = 0; i < 2; i++)
1764 s = (wRWORD (BITS (16, 19), i) > wRWORD (BITS (0, 3), i))
1765 ? 0xffffffff : 0;
1766 r |= s << (i * 32);
1767 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
1768 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
1771 break;
1773 default:
1774 ARMul_UndefInstr (state, instr);
1775 return ARMul_DONE;
1778 wC [wCASF] = psr;
1779 wR [BITS (12, 15)] = r;
1780 wC [wCon] |= (WCON_CUP | WCON_MUP);
1782 return ARMul_DONE;
1785 static ARMword
1786 Compute_Iwmmxt_Address (ARMul_State * state, ARMword instr, int * pFailed)
1788 ARMword Rn;
1789 ARMword addr;
1790 ARMword offset;
1791 ARMword multiplier;
1793 * pFailed = 0;
1794 Rn = BITS (16, 19);
1795 addr = state->Reg [Rn];
1796 offset = BITS (0, 7);
1797 multiplier = BIT (8) ? 4 : 1;
1799 if (BIT (24)) /* P */
1801 /* Pre Indexed Addressing. */
1802 if (BIT (23))
1803 addr += offset * multiplier;
1804 else
1805 addr -= offset * multiplier;
1807 /* Immediate Pre-Indexed. */
1808 if (BIT (21)) /* W */
1810 if (Rn == 15)
1812 /* Writeback into R15 is UNPREDICTABLE. */
1813 #ifdef DEBUG
1814 fprintf (stderr, "iWMMXt: writeback into r15\n");
1815 #endif
1816 * pFailed = 1;
1818 else
1819 state->Reg [Rn] = addr;
1822 else
1824 /* Post Indexed Addressing. */
1825 if (BIT (21)) /* W */
1827 /* Handle the write back of the final address. */
1828 if (Rn == 15)
1830 /* Writeback into R15 is UNPREDICTABLE. */
1831 #ifdef DEBUG
1832 fprintf (stderr, "iWMMXt: writeback into r15\n");
1833 #endif
1834 * pFailed = 1;
1836 else
1838 ARMword increment;
1840 if (BIT (23))
1841 increment = offset * multiplier;
1842 else
1843 increment = - (offset * multiplier);
1845 state->Reg [Rn] = addr + increment;
1848 else
1850 /* P == 0, W == 0, U == 0 is UNPREDICTABLE. */
1851 if (BIT (23) == 0)
1853 #ifdef DEBUG
1854 fprintf (stderr, "iWMMXt: undefined addressing mode\n");
1855 #endif
1856 * pFailed = 1;
1861 return addr;
1864 static ARMdword
1865 Iwmmxt_Load_Double_Word (ARMul_State * state, ARMword address)
1867 ARMdword value;
1869 /* The address must be aligned on a 8 byte boundary. */
1870 if (address & 0x7)
1872 fprintf (stderr, "iWMMXt: At addr 0x%x: Unaligned double word load from 0x%x\n",
1873 (state->Reg[15] - 8) & ~0x3, address);
1874 #ifdef DEBUG
1875 #endif
1876 /* No need to check for alignment traps. An unaligned
1877 double word load with alignment trapping disabled is
1878 UNPREDICTABLE. */
1879 ARMul_Abort (state, ARMul_DataAbortV);
1882 /* Load the words. */
1883 if (! state->bigendSig)
1885 value = ARMul_LoadWordN (state, address + 4);
1886 value <<= 32;
1887 value |= ARMul_LoadWordN (state, address);
1889 else
1891 value = ARMul_LoadWordN (state, address);
1892 value <<= 32;
1893 value |= ARMul_LoadWordN (state, address + 4);
1896 /* Check for data aborts. */
1897 if (state->Aborted)
1898 ARMul_Abort (state, ARMul_DataAbortV);
1899 else
1900 ARMul_Icycles (state, 2, 0L);
1902 return value;
1905 static ARMword
1906 Iwmmxt_Load_Word (ARMul_State * state, ARMword address)
1908 ARMword value;
1910 /* Check for a misaligned address. */
1911 if (address & 3)
1913 if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
1914 ARMul_Abort (state, ARMul_DataAbortV);
1915 else
1916 address &= ~ 3;
1919 value = ARMul_LoadWordN (state, address);
1921 if (state->Aborted)
1922 ARMul_Abort (state, ARMul_DataAbortV);
1923 else
1924 ARMul_Icycles (state, 1, 0L);
1926 return value;
1929 static ARMword
1930 Iwmmxt_Load_Half_Word (ARMul_State * state, ARMword address)
1932 ARMword value;
1934 /* Check for a misaligned address. */
1935 if (address & 1)
1937 if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
1938 ARMul_Abort (state, ARMul_DataAbortV);
1939 else
1940 address &= ~ 1;
1943 value = ARMul_LoadHalfWord (state, address);
1945 if (state->Aborted)
1946 ARMul_Abort (state, ARMul_DataAbortV);
1947 else
1948 ARMul_Icycles (state, 1, 0L);
1950 return value;
1953 static ARMword
1954 Iwmmxt_Load_Byte (ARMul_State * state, ARMword address)
1956 ARMword value;
1958 value = ARMul_LoadByte (state, address);
1960 if (state->Aborted)
1961 ARMul_Abort (state, ARMul_DataAbortV);
1962 else
1963 ARMul_Icycles (state, 1, 0L);
1965 return value;
1968 static void
1969 Iwmmxt_Store_Double_Word (ARMul_State * state, ARMword address, ARMdword value)
1971 /* The address must be aligned on a 8 byte boundary. */
1972 if (address & 0x7)
1974 fprintf (stderr, "iWMMXt: At addr 0x%x: Unaligned double word store to 0x%x\n",
1975 (state->Reg[15] - 8) & ~0x3, address);
1976 #ifdef DEBUG
1977 #endif
1978 /* No need to check for alignment traps. An unaligned
1979 double word store with alignment trapping disabled is
1980 UNPREDICTABLE. */
1981 ARMul_Abort (state, ARMul_DataAbortV);
1984 /* Store the words. */
1985 if (! state->bigendSig)
1987 ARMul_StoreWordN (state, address, value);
1988 ARMul_StoreWordN (state, address + 4, value >> 32);
1990 else
1992 ARMul_StoreWordN (state, address + 4, value);
1993 ARMul_StoreWordN (state, address, value >> 32);
1996 /* Check for data aborts. */
1997 if (state->Aborted)
1998 ARMul_Abort (state, ARMul_DataAbortV);
1999 else
2000 ARMul_Icycles (state, 2, 0L);
2003 static void
2004 Iwmmxt_Store_Word (ARMul_State * state, ARMword address, ARMword value)
2006 /* Check for a misaligned address. */
2007 if (address & 3)
2009 if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
2010 ARMul_Abort (state, ARMul_DataAbortV);
2011 else
2012 address &= ~ 3;
2015 ARMul_StoreWordN (state, address, value);
2017 if (state->Aborted)
2018 ARMul_Abort (state, ARMul_DataAbortV);
2021 static void
2022 Iwmmxt_Store_Half_Word (ARMul_State * state, ARMword address, ARMword value)
2024 /* Check for a misaligned address. */
2025 if (address & 1)
2027 if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
2028 ARMul_Abort (state, ARMul_DataAbortV);
2029 else
2030 address &= ~ 1;
2033 ARMul_StoreHalfWord (state, address, value);
2035 if (state->Aborted)
2036 ARMul_Abort (state, ARMul_DataAbortV);
2039 static void
2040 Iwmmxt_Store_Byte (ARMul_State * state, ARMword address, ARMword value)
2042 ARMul_StoreByte (state, address, value);
2044 if (state->Aborted)
2045 ARMul_Abort (state, ARMul_DataAbortV);
2048 static int
2049 WLDR (ARMul_State * state, ARMword instr)
2051 ARMword address;
2052 int failed;
2054 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2055 return ARMul_CANT;
2057 #ifdef DEBUG
2058 fprintf (stderr, "wldr\n");
2059 #endif
2061 address = Compute_Iwmmxt_Address (state, instr, & failed);
2062 if (failed)
2063 return ARMul_CANT;
2065 if (BITS (28, 31) == 0xf)
2067 /* WLDRW wCx */
2068 wC [BITS (12, 15)] = Iwmmxt_Load_Word (state, address);
2070 else if (BIT (8) == 0)
2072 if (BIT (22) == 0)
2073 /* WLDRB */
2074 wR [BITS (12, 15)] = Iwmmxt_Load_Byte (state, address);
2075 else
2076 /* WLDRH */
2077 wR [BITS (12, 15)] = Iwmmxt_Load_Half_Word (state, address);
2079 else
2081 if (BIT (22) == 0)
2082 /* WLDRW wRd */
2083 wR [BITS (12, 15)] = Iwmmxt_Load_Word (state, address);
2084 else
2085 /* WLDRD */
2086 wR [BITS (12, 15)] = Iwmmxt_Load_Double_Word (state, address);
2089 wC [wCon] |= WCON_MUP;
2091 return ARMul_DONE;
2094 static int
2095 WMAC (ARMword instr)
2097 int i;
2098 ARMdword t = 0;
2099 ARMword a, b;
2101 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2102 return ARMul_CANT;
2104 #ifdef DEBUG
2105 fprintf (stderr, "wmac\n");
2106 #endif
2108 for (i = 0; i < 4; i++)
2110 if (BIT (21))
2112 /* Signed. */
2113 signed long s;
2115 a = wRHALF (BITS (16, 19), i);
2116 a = EXTEND16 (a);
2118 b = wRHALF (BITS (0, 3), i);
2119 b = EXTEND16 (b);
2121 s = (signed long) a * (signed long) b;
2123 t = t + (ARMdword) s;
2125 else
2127 /* Unsigned. */
2128 a = wRHALF (BITS (16, 19), i);
2129 b = wRHALF (BITS ( 0, 3), i);
2131 t += a * b;
2135 if (BIT (21))
2136 t = EXTEND32 (t);
2137 else
2138 t &= 0xffffffff;
2140 if (BIT (20))
2141 wR [BITS (12, 15)] = t;
2142 else
2143 wR[BITS (12, 15)] += t;
2145 wC [wCon] |= WCON_MUP;
2147 return ARMul_DONE;
2150 static int
2151 WMADD (ARMword instr)
2153 ARMdword r = 0;
2154 int i;
2156 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2157 return ARMul_CANT;
2159 #ifdef DEBUG
2160 fprintf (stderr, "wmadd\n");
2161 #endif
2163 for (i = 0; i < 2; i++)
2165 ARMdword s1, s2;
2167 if (BIT (21)) /* Signed. */
2169 signed long a, b;
2171 a = wRHALF (BITS (16, 19), i * 2);
2172 a = EXTEND16 (a);
2174 b = wRHALF (BITS (0, 3), i * 2);
2175 b = EXTEND16 (b);
2177 s1 = (ARMdword) (a * b);
2179 a = wRHALF (BITS (16, 19), i * 2 + 1);
2180 a = EXTEND16 (a);
2182 b = wRHALF (BITS (0, 3), i * 2 + 1);
2183 b = EXTEND16 (b);
2185 s2 = (ARMdword) (a * b);
2187 else /* Unsigned. */
2189 unsigned long a, b;
2191 a = wRHALF (BITS (16, 19), i * 2);
2192 b = wRHALF (BITS ( 0, 3), i * 2);
2194 s1 = (ARMdword) (a * b);
2196 a = wRHALF (BITS (16, 19), i * 2 + 1);
2197 b = wRHALF (BITS ( 0, 3), i * 2 + 1);
2199 s2 = (ARMdword) a * b;
2202 r |= (ARMdword) ((s1 + s2) & 0xffffffff) << (i ? 32 : 0);
2205 wR [BITS (12, 15)] = r;
2206 wC [wCon] |= WCON_MUP;
2208 return ARMul_DONE;
2211 static int
2212 WMAX (ARMul_State * state, ARMword instr)
2214 ARMdword r = 0;
2215 ARMdword s;
2216 int i;
2218 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2219 return ARMul_CANT;
2221 #ifdef DEBUG
2222 fprintf (stderr, "wmax\n");
2223 #endif
2225 switch (BITS (22, 23))
2227 case Bqual:
2228 for (i = 0; i < 8; i++)
2229 if (BIT (21)) /* Signed. */
2231 int a, b;
2233 a = wRBYTE (BITS (16, 19), i);
2234 a = EXTEND8 (a);
2236 b = wRBYTE (BITS (0, 3), i);
2237 b = EXTEND8 (b);
2239 if (a > b)
2240 s = a;
2241 else
2242 s = b;
2244 r |= (s & 0xff) << (i * 8);
2246 else /* Unsigned. */
2248 unsigned int a, b;
2250 a = wRBYTE (BITS (16, 19), i);
2251 b = wRBYTE (BITS (0, 3), i);
2253 if (a > b)
2254 s = a;
2255 else
2256 s = b;
2258 r |= (s & 0xff) << (i * 8);
2260 break;
2262 case Hqual:
2263 for (i = 0; i < 4; i++)
2264 if (BIT (21)) /* Signed. */
2266 int a, b;
2268 a = wRHALF (BITS (16, 19), i);
2269 a = EXTEND16 (a);
2271 b = wRHALF (BITS (0, 3), i);
2272 b = EXTEND16 (b);
2274 if (a > b)
2275 s = a;
2276 else
2277 s = b;
2279 r |= (s & 0xffff) << (i * 16);
2281 else /* Unsigned. */
2283 unsigned int a, b;
2285 a = wRHALF (BITS (16, 19), i);
2286 b = wRHALF (BITS (0, 3), i);
2288 if (a > b)
2289 s = a;
2290 else
2291 s = b;
2293 r |= (s & 0xffff) << (i * 16);
2295 break;
2297 case Wqual:
2298 for (i = 0; i < 2; i++)
2299 if (BIT (21)) /* Signed. */
2301 int a, b;
2303 a = wRWORD (BITS (16, 19), i);
2304 b = wRWORD (BITS (0, 3), i);
2306 if (a > b)
2307 s = a;
2308 else
2309 s = b;
2311 r |= (s & 0xffffffff) << (i * 32);
2313 else
2315 unsigned int a, b;
2317 a = wRWORD (BITS (16, 19), i);
2318 b = wRWORD (BITS (0, 3), i);
2320 if (a > b)
2321 s = a;
2322 else
2323 s = b;
2325 r |= (s & 0xffffffff) << (i * 32);
2327 break;
2329 default:
2330 ARMul_UndefInstr (state, instr);
2331 return ARMul_DONE;
2334 wR [BITS (12, 15)] = r;
2335 wC [wCon] |= WCON_MUP;
2337 return ARMul_DONE;
2340 static int
2341 WMIN (ARMul_State * state, ARMword instr)
2343 ARMdword r = 0;
2344 ARMdword s;
2345 int i;
2347 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2348 return ARMul_CANT;
2350 #ifdef DEBUG
2351 fprintf (stderr, "wmin\n");
2352 #endif
2354 switch (BITS (22, 23))
2356 case Bqual:
2357 for (i = 0; i < 8; i++)
2358 if (BIT (21)) /* Signed. */
2360 int a, b;
2362 a = wRBYTE (BITS (16, 19), i);
2363 a = EXTEND8 (a);
2365 b = wRBYTE (BITS (0, 3), i);
2366 b = EXTEND8 (b);
2368 if (a < b)
2369 s = a;
2370 else
2371 s = b;
2373 r |= (s & 0xff) << (i * 8);
2375 else /* Unsigned. */
2377 unsigned int a, b;
2379 a = wRBYTE (BITS (16, 19), i);
2380 b = wRBYTE (BITS (0, 3), i);
2382 if (a < b)
2383 s = a;
2384 else
2385 s = b;
2387 r |= (s & 0xff) << (i * 8);
2389 break;
2391 case Hqual:
2392 for (i = 0; i < 4; i++)
2393 if (BIT (21)) /* Signed. */
2395 int a, b;
2397 a = wRHALF (BITS (16, 19), i);
2398 a = EXTEND16 (a);
2400 b = wRHALF (BITS (0, 3), i);
2401 b = EXTEND16 (b);
2403 if (a < b)
2404 s = a;
2405 else
2406 s = b;
2408 r |= (s & 0xffff) << (i * 16);
2410 else
2412 /* Unsigned. */
2413 unsigned int a, b;
2415 a = wRHALF (BITS (16, 19), i);
2416 b = wRHALF (BITS ( 0, 3), i);
2418 if (a < b)
2419 s = a;
2420 else
2421 s = b;
2423 r |= (s & 0xffff) << (i * 16);
2425 break;
2427 case Wqual:
2428 for (i = 0; i < 2; i++)
2429 if (BIT (21)) /* Signed. */
2431 int a, b;
2433 a = wRWORD (BITS (16, 19), i);
2434 b = wRWORD (BITS ( 0, 3), i);
2436 if (a < b)
2437 s = a;
2438 else
2439 s = b;
2441 r |= (s & 0xffffffff) << (i * 32);
2443 else
2445 unsigned int a, b;
2447 a = wRWORD (BITS (16, 19), i);
2448 b = wRWORD (BITS (0, 3), i);
2450 if (a < b)
2451 s = a;
2452 else
2453 s = b;
2455 r |= (s & 0xffffffff) << (i * 32);
2457 break;
2459 default:
2460 ARMul_UndefInstr (state, instr);
2461 return ARMul_DONE;
2464 wR [BITS (12, 15)] = r;
2465 wC [wCon] |= WCON_MUP;
2467 return ARMul_DONE;
2470 static int
2471 WMUL (ARMword instr)
2473 ARMdword r = 0;
2474 ARMdword s;
2475 int i;
2477 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2478 return ARMul_CANT;
2480 #ifdef DEBUG
2481 fprintf (stderr, "wmul\n");
2482 #endif
2484 for (i = 0; i < 4; i++)
2485 if (BIT (21)) /* Signed. */
2487 long a, b;
2489 a = wRHALF (BITS (16, 19), i);
2490 a = EXTEND16 (a);
2492 b = wRHALF (BITS (0, 3), i);
2493 b = EXTEND16 (b);
2495 s = a * b;
2497 if (BIT (20))
2498 r |= ((s >> 16) & 0xffff) << (i * 16);
2499 else
2500 r |= (s & 0xffff) << (i * 16);
2502 else /* Unsigned. */
2504 unsigned long a, b;
2506 a = wRHALF (BITS (16, 19), i);
2507 b = wRHALF (BITS (0, 3), i);
2509 s = a * b;
2511 if (BIT (20))
2512 r |= ((s >> 16) & 0xffff) << (i * 16);
2513 else
2514 r |= (s & 0xffff) << (i * 16);
2517 wR [BITS (12, 15)] = r;
2518 wC [wCon] |= WCON_MUP;
2520 return ARMul_DONE;
2523 static int
2524 WOR (ARMword instr)
2526 ARMword psr = 0;
2527 ARMdword result;
2529 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2530 return ARMul_CANT;
2532 #ifdef DEBUG
2533 fprintf (stderr, "wor\n");
2534 #endif
2536 result = wR [BITS (16, 19)] | wR [BITS (0, 3)];
2537 wR [BITS (12, 15)] = result;
2539 SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
2540 SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
2542 wC [wCASF] = psr;
2543 wC [wCon] |= (WCON_CUP | WCON_MUP);
2545 return ARMul_DONE;
2548 static int
2549 WPACK (ARMul_State * state, ARMword instr)
2551 ARMdword r = 0;
2552 ARMword psr = 0;
2553 ARMdword x;
2554 ARMdword s;
2555 int i;
2556 int satrv[8];
2558 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2559 return ARMul_CANT;
2561 #ifdef DEBUG
2562 fprintf (stderr, "wpack\n");
2563 #endif
2565 switch (BITS (22, 23))
2567 case Hqual:
2568 for (i = 0; i < 8; i++)
2570 x = wRHALF (i < 4 ? BITS (16, 19) : BITS (0, 3), i & 3);
2572 switch (BITS (20, 21))
2574 case UnsignedSaturation:
2575 s = IwmmxtSaturateU8 (x, satrv + BITIDX8 (i));
2576 break;
2578 case SignedSaturation:
2579 s = IwmmxtSaturateS8 (x, satrv + BITIDX8 (i));
2580 break;
2582 default:
2583 ARMul_UndefInstr (state, instr);
2584 return ARMul_DONE;
2587 r |= (s & 0xff) << (i * 8);
2588 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
2589 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
2591 break;
2593 case Wqual:
2594 satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
2596 for (i = 0; i < 4; i++)
2598 x = wRWORD (i < 2 ? BITS (16, 19) : BITS (0, 3), i & 1);
2600 switch (BITS (20, 21))
2602 case UnsignedSaturation:
2603 s = IwmmxtSaturateU16 (x, satrv + BITIDX16 (i));
2604 break;
2606 case SignedSaturation:
2607 s = IwmmxtSaturateS16 (x, satrv + BITIDX16 (i));
2608 break;
2610 default:
2611 ARMul_UndefInstr (state, instr);
2612 return ARMul_DONE;
2615 r |= (s & 0xffff) << (i * 16);
2616 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2617 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2619 break;
2621 case Dqual:
2622 satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
2624 for (i = 0; i < 2; i++)
2626 x = wR [i ? BITS (0, 3) : BITS (16, 19)];
2628 switch (BITS (20, 21))
2630 case UnsignedSaturation:
2631 s = IwmmxtSaturateU32 (x, satrv + BITIDX32 (i));
2632 break;
2634 case SignedSaturation:
2635 s = IwmmxtSaturateS32 (x, satrv + BITIDX32 (i));
2636 break;
2638 default:
2639 ARMul_UndefInstr (state, instr);
2640 return ARMul_DONE;
2643 r |= (s & 0xffffffff) << (i * 32);
2644 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
2645 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
2647 break;
2649 default:
2650 ARMul_UndefInstr (state, instr);
2651 return ARMul_DONE;
2654 wC [wCASF] = psr;
2655 wR [BITS (12, 15)] = r;
2656 SET_wCSSFvec (satrv);
2657 wC [wCon] |= (WCON_CUP | WCON_MUP);
2659 return ARMul_DONE;
2662 static int
2663 WROR (ARMul_State * state, ARMword instr)
2665 ARMdword r = 0;
2666 ARMdword s;
2667 ARMword psr = 0;
2668 int i;
2669 int shift;
2671 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2672 return ARMul_CANT;
2674 #ifdef DEBUG
2675 fprintf (stderr, "wror\n");
2676 #endif
2678 DECODE_G_BIT (state, instr, shift);
2680 switch (BITS (22, 23))
2682 case Hqual:
2683 shift &= 0xf;
2684 for (i = 0; i < 4; i++)
2686 s = ((wRHALF (BITS (16, 19), i) & 0xffff) << (16 - shift))
2687 | ((wRHALF (BITS (16, 19), i) & 0xffff) >> shift);
2688 r |= (s & 0xffff) << (i * 16);
2689 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2690 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2692 break;
2694 case Wqual:
2695 shift &= 0x1f;
2696 for (i = 0; i < 2; i++)
2698 s = ((wRWORD (BITS (16, 19), i) & 0xffffffff) << (32 - shift))
2699 | ((wRWORD (BITS (16, 19), i) & 0xffffffff) >> shift);
2700 r |= (s & 0xffffffff) << (i * 32);
2701 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
2702 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
2704 break;
2706 case Dqual:
2707 shift &= 0x3f;
2708 r = (wR [BITS (16, 19)] >> shift)
2709 | (wR [BITS (16, 19)] << (64 - shift));
2711 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
2712 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
2713 break;
2715 default:
2716 ARMul_UndefInstr (state, instr);
2717 return ARMul_DONE;
2720 wC [wCASF] = psr;
2721 wR [BITS (12, 15)] = r;
2722 wC [wCon] |= (WCON_CUP | WCON_MUP);
2724 return ARMul_DONE;
2727 static int
2728 WSAD (ARMword instr)
2730 ARMdword r;
2731 int s;
2732 int i;
2734 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2735 return ARMul_CANT;
2737 #ifdef DEBUG
2738 fprintf (stderr, "wsad\n");
2739 #endif
2741 /* Z bit. */
2742 r = BIT (20) ? 0 : (wR [BITS (12, 15)] & 0xffffffff);
2744 if (BIT (22))
2745 /* Half. */
2746 for (i = 0; i < 4; i++)
2748 s = (wRHALF (BITS (16, 19), i) - wRHALF (BITS (0, 3), i));
2749 r += abs (s);
2751 else
2752 /* Byte. */
2753 for (i = 0; i < 8; i++)
2755 s = (wRBYTE (BITS (16, 19), i) - wRBYTE (BITS (0, 3), i));
2756 r += abs (s);
2759 wR [BITS (12, 15)] = r;
2760 wC [wCon] |= WCON_MUP;
2762 return ARMul_DONE;
2765 static int
2766 WSHUFH (ARMword instr)
2768 ARMdword r = 0;
2769 ARMword psr = 0;
2770 ARMdword s;
2771 int i;
2772 int imm8;
2774 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2775 return ARMul_CANT;
2777 #ifdef DEBUG
2778 fprintf (stderr, "wshufh\n");
2779 #endif
2781 imm8 = (BITS (20, 23) << 4) | BITS (0, 3);
2783 for (i = 0; i < 4; i++)
2785 s = wRHALF (BITS (16, 19), ((imm8 >> (i * 2) & 3)) & 0xff);
2786 r |= (s & 0xffff) << (i * 16);
2787 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2788 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2791 wC [wCASF] = psr;
2792 wR [BITS (12, 15)] = r;
2793 wC [wCon] |= (WCON_CUP | WCON_MUP);
2795 return ARMul_DONE;
2798 static int
2799 WSLL (ARMul_State * state, ARMword instr)
2801 ARMdword r = 0;
2802 ARMdword s;
2803 ARMword psr = 0;
2804 int i;
2805 unsigned shift;
2807 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2808 return ARMul_CANT;
2810 #ifdef DEBUG
2811 fprintf (stderr, "wsll\n");
2812 #endif
2814 DECODE_G_BIT (state, instr, shift);
2816 switch (BITS (22, 23))
2818 case Hqual:
2819 for (i = 0; i < 4; i++)
2821 if (shift > 15)
2822 s = 0;
2823 else
2824 s = ((wRHALF (BITS (16, 19), i) & 0xffff) << shift);
2825 r |= (s & 0xffff) << (i * 16);
2826 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2827 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2829 break;
2831 case Wqual:
2832 for (i = 0; i < 2; i++)
2834 if (shift > 31)
2835 s = 0;
2836 else
2837 s = ((wRWORD (BITS (16, 19), i) & 0xffffffff) << shift);
2838 r |= (s & 0xffffffff) << (i * 32);
2839 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
2840 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
2842 break;
2844 case Dqual:
2845 if (shift > 63)
2846 r = 0;
2847 else
2848 r = ((wR[BITS (16, 19)] & 0xffffffffffffffffULL) << shift);
2850 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
2851 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
2852 break;
2854 default:
2855 ARMul_UndefInstr (state, instr);
2856 return ARMul_DONE;
2859 wC [wCASF] = psr;
2860 wR [BITS (12, 15)] = r;
2861 wC [wCon] |= (WCON_CUP | WCON_MUP);
2863 return ARMul_DONE;
2866 static int
2867 WSRA (ARMul_State * state, ARMword instr)
2869 ARMdword r = 0;
2870 ARMdword s;
2871 ARMword psr = 0;
2872 int i;
2873 unsigned shift;
2874 signed long t;
2876 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2877 return ARMul_CANT;
2879 #ifdef DEBUG
2880 fprintf (stderr, "wsra\n");
2881 #endif
2883 DECODE_G_BIT (state, instr, shift);
2885 switch (BITS (22, 23))
2887 case Hqual:
2888 for (i = 0; i < 4; i++)
2890 if (shift > 15)
2891 t = (wRHALF (BITS (16, 19), i) & 0x8000) ? 0xffff : 0;
2892 else
2894 t = wRHALF (BITS (16, 19), i);
2895 t = EXTEND16 (t);
2896 t >>= shift;
2899 s = t;
2900 r |= (s & 0xffff) << (i * 16);
2901 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2902 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2904 break;
2906 case Wqual:
2907 for (i = 0; i < 2; i++)
2909 if (shift > 31)
2910 t = (wRWORD (BITS (16, 19), i) & 0x80000000) ? 0xffffffff : 0;
2911 else
2913 t = EXTEND32 (wRWORD (BITS (16, 19), i));
2914 t >>= shift;
2916 s = t;
2917 r |= (s & 0xffffffff) << (i * 32);
2918 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
2919 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
2921 break;
2923 case Dqual:
2924 if (shift > 63)
2925 r = (wR [BITS (16, 19)] & 0x8000000000000000ULL) ? 0xffffffffffffffffULL : 0;
2926 else
2927 r = ((signed long long) (wR[BITS (16, 19)] & 0xffffffffffffffffULL) >> shift);
2928 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
2929 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
2930 break;
2932 default:
2933 ARMul_UndefInstr (state, instr);
2934 return ARMul_DONE;
2937 wC [wCASF] = psr;
2938 wR [BITS (12, 15)] = r;
2939 wC [wCon] |= (WCON_CUP | WCON_MUP);
2941 return ARMul_DONE;
2944 static int
2945 WSRL (ARMul_State * state, ARMword instr)
2947 ARMdword r = 0;
2948 ARMdword s;
2949 ARMword psr = 0;
2950 int i;
2951 unsigned int shift;
2953 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
2954 return ARMul_CANT;
2956 #ifdef DEBUG
2957 fprintf (stderr, "wsrl\n");
2958 #endif
2960 DECODE_G_BIT (state, instr, shift);
2962 switch (BITS (22, 23))
2964 case Hqual:
2965 for (i = 0; i < 4; i++)
2967 if (shift > 15)
2968 s = 0;
2969 else
2970 s = ((unsigned) (wRHALF (BITS (16, 19), i) & 0xffff) >> shift);
2972 r |= (s & 0xffff) << (i * 16);
2973 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
2974 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
2976 break;
2978 case Wqual:
2979 for (i = 0; i < 2; i++)
2981 if (shift > 31)
2982 s = 0;
2983 else
2984 s = ((unsigned long) (wRWORD (BITS (16, 19), i) & 0xffffffff) >> shift);
2986 r |= (s & 0xffffffff) << (i * 32);
2987 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
2988 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
2990 break;
2992 case Dqual:
2993 if (shift > 63)
2994 r = 0;
2995 else
2996 r = (wR [BITS (16, 19)] & 0xffffffffffffffffULL) >> shift;
2998 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
2999 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
3000 break;
3002 default:
3003 ARMul_UndefInstr (state, instr);
3004 return ARMul_DONE;
3007 wC [wCASF] = psr;
3008 wR [BITS (12, 15)] = r;
3009 wC [wCon] |= (WCON_CUP | WCON_MUP);
3011 return ARMul_DONE;
3014 static int
3015 WSTR (ARMul_State * state, ARMword instr)
3017 ARMword address;
3018 int failed;
3021 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3022 return ARMul_CANT;
3024 #ifdef DEBUG
3025 fprintf (stderr, "wstr\n");
3026 #endif
3028 address = Compute_Iwmmxt_Address (state, instr, & failed);
3029 if (failed)
3030 return ARMul_CANT;
3032 if (BITS (28, 31) == 0xf)
3034 /* WSTRW wCx */
3035 Iwmmxt_Store_Word (state, address, wC [BITS (12, 15)]);
3037 else if (BIT (8) == 0)
3039 if (BIT (22) == 0)
3040 /* WSTRB */
3041 Iwmmxt_Store_Byte (state, address, wR [BITS (12, 15)]);
3042 else
3043 /* WSTRH */
3044 Iwmmxt_Store_Half_Word (state, address, wR [BITS (12, 15)]);
3046 else
3048 if (BIT (22) == 0)
3049 /* WSTRW wRd */
3050 Iwmmxt_Store_Word (state, address, wR [BITS (12, 15)]);
3051 else
3052 /* WSTRD */
3053 Iwmmxt_Store_Double_Word (state, address, wR [BITS (12, 15)]);
3056 return ARMul_DONE;
3059 static int
3060 WSUB (ARMul_State * state, ARMword instr)
3062 ARMdword r = 0;
3063 ARMword psr = 0;
3064 ARMdword x;
3065 ARMdword s;
3066 int i;
3067 int carry;
3068 int overflow;
3069 int satrv[8];
3071 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3072 return ARMul_CANT;
3074 #ifdef DEBUG
3075 fprintf (stderr, "wsub\n");
3076 #endif
3078 /* Subtract two numbers using the specified function,
3079 leaving setting the carry bit as required. */
3080 #define SUBx(x, y, m, f) \
3081 (*f) (wRBITS (BITS (16, 19), (x), (y)) & (m), \
3082 wRBITS (BITS ( 0, 3), (x), (y)) & (m), & carry, & overflow)
3084 switch (BITS (22, 23))
3086 case Bqual:
3087 for (i = 0; i < 8; i++)
3089 switch (BITS (20, 21))
3091 case NoSaturation:
3092 s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubS8);
3093 satrv [BITIDX8 (i)] = 0;
3094 r |= (s & 0xff) << (i * 8);
3095 SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
3096 SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
3097 SIMD8_SET (psr, carry, SIMD_CBIT, i);
3098 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
3099 break;
3101 case UnsignedSaturation:
3102 s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubU8);
3103 x = IwmmxtSaturateU8 (s, satrv + BITIDX8 (i));
3104 r |= (x & 0xff) << (i * 8);
3105 SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
3106 SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
3107 if (! satrv [BITIDX8 (i)])
3109 SIMD8_SET (psr, carry, SIMD_CBIT, i);
3110 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
3112 break;
3114 case SignedSaturation:
3115 s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubS8);
3116 x = IwmmxtSaturateS8 (s, satrv + BITIDX8 (i));
3117 r |= (x & 0xff) << (i * 8);
3118 SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
3119 SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
3120 if (! satrv [BITIDX8 (i)])
3122 SIMD8_SET (psr, carry, SIMD_CBIT, i);
3123 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
3125 break;
3127 default:
3128 ARMul_UndefInstr (state, instr);
3129 return ARMul_DONE;
3132 break;
3134 case Hqual:
3135 satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
3137 for (i = 0; i < 4; i++)
3139 switch (BITS (20, 21))
3141 case NoSaturation:
3142 s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubU16);
3143 satrv [BITIDX16 (i)] = 0;
3144 r |= (s & 0xffff) << (i * 16);
3145 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
3146 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
3147 SIMD16_SET (psr, carry, SIMD_CBIT, i);
3148 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
3149 break;
3151 case UnsignedSaturation:
3152 s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubU16);
3153 x = IwmmxtSaturateU16 (s, satrv + BITIDX16 (i));
3154 r |= (x & 0xffff) << (i * 16);
3155 SIMD16_SET (psr, NBIT16 (x & 0xffff), SIMD_NBIT, i);
3156 SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
3157 if (! satrv [BITIDX16 (i)])
3159 SIMD16_SET (psr, carry, SIMD_CBIT, i);
3160 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
3162 break;
3164 case SignedSaturation:
3165 s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubS16);
3166 x = IwmmxtSaturateS16 (s, satrv + BITIDX16 (i));
3167 r |= (x & 0xffff) << (i * 16);
3168 SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
3169 SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
3170 if (! satrv [BITIDX16 (i)])
3172 SIMD16_SET (psr, carry, SIMD_CBIT, i);
3173 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
3175 break;
3177 default:
3178 ARMul_UndefInstr (state, instr);
3179 return ARMul_DONE;
3182 break;
3184 case Wqual:
3185 satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
3187 for (i = 0; i < 2; i++)
3189 switch (BITS (20, 21))
3191 case NoSaturation:
3192 s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubU32);
3193 satrv[BITIDX32 (i)] = 0;
3194 r |= (s & 0xffffffff) << (i * 32);
3195 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
3196 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
3197 SIMD32_SET (psr, carry, SIMD_CBIT, i);
3198 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
3199 break;
3201 case UnsignedSaturation:
3202 s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubU32);
3203 x = IwmmxtSaturateU32 (s, satrv + BITIDX32 (i));
3204 r |= (x & 0xffffffff) << (i * 32);
3205 SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
3206 SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
3207 if (! satrv [BITIDX32 (i)])
3209 SIMD32_SET (psr, carry, SIMD_CBIT, i);
3210 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
3212 break;
3214 case SignedSaturation:
3215 s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubS32);
3216 x = IwmmxtSaturateS32 (s, satrv + BITIDX32 (i));
3217 r |= (x & 0xffffffff) << (i * 32);
3218 SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
3219 SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
3220 if (! satrv [BITIDX32 (i)])
3222 SIMD32_SET (psr, carry, SIMD_CBIT, i);
3223 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
3225 break;
3227 default:
3228 ARMul_UndefInstr (state, instr);
3229 return ARMul_DONE;
3232 break;
3234 default:
3235 ARMul_UndefInstr (state, instr);
3236 return ARMul_DONE;
3239 wR [BITS (12, 15)] = r;
3240 wC [wCASF] = psr;
3241 SET_wCSSFvec (satrv);
3242 wC [wCon] |= (WCON_CUP | WCON_MUP);
3244 #undef SUBx
3246 return ARMul_DONE;
3249 static int
3250 WUNPCKEH (ARMul_State * state, ARMword instr)
3252 ARMdword r = 0;
3253 ARMword psr = 0;
3254 ARMdword s;
3255 int i;
3257 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3258 return ARMul_CANT;
3260 #ifdef DEBUG
3261 fprintf (stderr, "wunpckeh\n");
3262 #endif
3264 switch (BITS (22, 23))
3266 case Bqual:
3267 for (i = 0; i < 4; i++)
3269 s = wRBYTE (BITS (16, 19), i + 4);
3271 if (BIT (21) && NBIT8 (s))
3272 s |= 0xff00;
3274 r |= (s & 0xffff) << (i * 16);
3275 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
3276 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
3278 break;
3280 case Hqual:
3281 for (i = 0; i < 2; i++)
3283 s = wRHALF (BITS (16, 19), i + 2);
3285 if (BIT (21) && NBIT16 (s))
3286 s |= 0xffff0000;
3288 r |= (s & 0xffffffff) << (i * 32);
3289 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
3290 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
3292 break;
3294 case Wqual:
3295 r = wRWORD (BITS (16, 19), 1);
3297 if (BIT (21) && NBIT32 (r))
3298 r |= 0xffffffff00000000ULL;
3300 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
3301 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
3302 break;
3304 default:
3305 ARMul_UndefInstr (state, instr);
3306 return ARMul_DONE;
3309 wC [wCASF] = psr;
3310 wR [BITS (12, 15)] = r;
3311 wC [wCon] |= (WCON_CUP | WCON_MUP);
3313 return ARMul_DONE;
3316 static int
3317 WUNPCKEL (ARMul_State * state, ARMword instr)
3319 ARMdword r = 0;
3320 ARMword psr = 0;
3321 ARMdword s;
3322 int i;
3324 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3325 return ARMul_CANT;
3327 #ifdef DEBUG
3328 fprintf (stderr, "wunpckel\n");
3329 #endif
3331 switch (BITS (22, 23))
3333 case Bqual:
3334 for (i = 0; i < 4; i++)
3336 s = wRBYTE (BITS (16, 19), i);
3338 if (BIT (21) && NBIT8 (s))
3339 s |= 0xff00;
3341 r |= (s & 0xffff) << (i * 16);
3342 SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
3343 SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
3345 break;
3347 case Hqual:
3348 for (i = 0; i < 2; i++)
3350 s = wRHALF (BITS (16, 19), i);
3352 if (BIT (21) && NBIT16 (s))
3353 s |= 0xffff0000;
3355 r |= (s & 0xffffffff) << (i * 32);
3356 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
3357 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
3359 break;
3361 case Wqual:
3362 r = wRWORD (BITS (16, 19), 0);
3364 if (BIT (21) && NBIT32 (r))
3365 r |= 0xffffffff00000000ULL;
3367 SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
3368 SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
3369 break;
3371 default:
3372 ARMul_UndefInstr (state, instr);
3373 return ARMul_DONE;
3376 wC [wCASF] = psr;
3377 wR [BITS (12, 15)] = r;
3378 wC [wCon] |= (WCON_CUP | WCON_MUP);
3380 return ARMul_DONE;
3383 static int
3384 WUNPCKIH (ARMul_State * state, ARMword instr)
3386 ARMword a, b;
3387 ARMdword r = 0;
3388 ARMword psr = 0;
3389 ARMdword s;
3390 int i;
3392 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3393 return ARMul_CANT;
3395 #ifdef DEBUG
3396 fprintf (stderr, "wunpckih\n");
3397 #endif
3399 switch (BITS (22, 23))
3401 case Bqual:
3402 for (i = 0; i < 4; i++)
3404 a = wRBYTE (BITS (16, 19), i + 4);
3405 b = wRBYTE (BITS ( 0, 3), i + 4);
3406 s = a | (b << 8);
3407 r |= (s & 0xffff) << (i * 16);
3408 SIMD8_SET (psr, NBIT8 (a), SIMD_NBIT, i * 2);
3409 SIMD8_SET (psr, ZBIT8 (a), SIMD_ZBIT, i * 2);
3410 SIMD8_SET (psr, NBIT8 (b), SIMD_NBIT, (i * 2) + 1);
3411 SIMD8_SET (psr, ZBIT8 (b), SIMD_ZBIT, (i * 2) + 1);
3413 break;
3415 case Hqual:
3416 for (i = 0; i < 2; i++)
3418 a = wRHALF (BITS (16, 19), i + 2);
3419 b = wRHALF (BITS ( 0, 3), i + 2);
3420 s = a | (b << 16);
3421 r |= (s & 0xffffffff) << (i * 32);
3422 SIMD16_SET (psr, NBIT16 (a), SIMD_NBIT, (i * 2));
3423 SIMD16_SET (psr, ZBIT16 (a), SIMD_ZBIT, (i * 2));
3424 SIMD16_SET (psr, NBIT16 (b), SIMD_NBIT, (i * 2) + 1);
3425 SIMD16_SET (psr, ZBIT16 (b), SIMD_ZBIT, (i * 2) + 1);
3427 break;
3429 case Wqual:
3430 a = wRWORD (BITS (16, 19), 1);
3431 s = wRWORD (BITS ( 0, 3), 1);
3432 r = a | (s << 32);
3434 SIMD32_SET (psr, NBIT32 (a), SIMD_NBIT, 0);
3435 SIMD32_SET (psr, ZBIT32 (a), SIMD_ZBIT, 0);
3436 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, 1);
3437 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, 1);
3438 break;
3440 default:
3441 ARMul_UndefInstr (state, instr);
3442 return ARMul_DONE;
3445 wC [wCASF] = psr;
3446 wR [BITS (12, 15)] = r;
3447 wC [wCon] |= (WCON_CUP | WCON_MUP);
3449 return ARMul_DONE;
3452 static int
3453 WUNPCKIL (ARMul_State * state, ARMword instr)
3455 ARMword a, b;
3456 ARMdword r = 0;
3457 ARMword psr = 0;
3458 ARMdword s;
3459 int i;
3461 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3462 return ARMul_CANT;
3464 #ifdef DEBUG
3465 fprintf (stderr, "wunpckil\n");
3466 #endif
3468 switch (BITS (22, 23))
3470 case Bqual:
3471 for (i = 0; i < 4; i++)
3473 a = wRBYTE (BITS (16, 19), i);
3474 b = wRBYTE (BITS ( 0, 3), i);
3475 s = a | (b << 8);
3476 r |= (s & 0xffff) << (i * 16);
3477 SIMD8_SET (psr, NBIT8 (a), SIMD_NBIT, i * 2);
3478 SIMD8_SET (psr, ZBIT8 (a), SIMD_ZBIT, i * 2);
3479 SIMD8_SET (psr, NBIT8 (b), SIMD_NBIT, (i * 2) + 1);
3480 SIMD8_SET (psr, ZBIT8 (b), SIMD_ZBIT, (i * 2) + 1);
3482 break;
3484 case Hqual:
3485 for (i = 0; i < 2; i++)
3487 a = wRHALF (BITS (16, 19), i);
3488 b = wRHALF (BITS ( 0, 3), i);
3489 s = a | (b << 16);
3490 r |= (s & 0xffffffff) << (i * 32);
3491 SIMD16_SET (psr, NBIT16 (a), SIMD_NBIT, (i * 2));
3492 SIMD16_SET (psr, ZBIT16 (a), SIMD_ZBIT, (i * 2));
3493 SIMD16_SET (psr, NBIT16 (b), SIMD_NBIT, (i * 2) + 1);
3494 SIMD16_SET (psr, ZBIT16 (b), SIMD_ZBIT, (i * 2) + 1);
3496 break;
3498 case Wqual:
3499 a = wRWORD (BITS (16, 19), 0);
3500 s = wRWORD (BITS ( 0, 3), 0);
3501 r = a | (s << 32);
3503 SIMD32_SET (psr, NBIT32 (a), SIMD_NBIT, 0);
3504 SIMD32_SET (psr, ZBIT32 (a), SIMD_ZBIT, 0);
3505 SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, 1);
3506 SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, 1);
3507 break;
3509 default:
3510 ARMul_UndefInstr (state, instr);
3511 return ARMul_DONE;
3514 wC [wCASF] = psr;
3515 wR [BITS (12, 15)] = r;
3516 wC [wCon] |= (WCON_CUP | WCON_MUP);
3518 return ARMul_DONE;
3521 static int
3522 WXOR (ARMword instr)
3524 ARMword psr = 0;
3525 ARMdword result;
3527 if ((read_cp15_reg (15, 0, 1) & 3) != 3)
3528 return ARMul_CANT;
3530 #ifdef DEBUG
3531 fprintf (stderr, "wxor\n");
3532 #endif
3534 result = wR [BITS (16, 19)] ^ wR [BITS (0, 3)];
3535 wR [BITS (12, 15)] = result;
3537 SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
3538 SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
3540 wC [wCASF] = psr;
3541 wC [wCon] |= (WCON_CUP | WCON_MUP);
3543 return ARMul_DONE;
3546 /* This switch table is moved to a separate function in order
3547 to work around a compiler bug in the host compiler... */
3549 static int
3550 Process_Instruction (ARMul_State * state, ARMword instr)
3552 int status = ARMul_BUSY;
3554 switch ((BITS (20, 23) << 8) | BITS (4, 11))
3556 case 0x000: status = WOR (instr); break;
3557 case 0x011: status = TMCR (state, instr); break;
3558 case 0x100: status = WXOR (instr); break;
3559 case 0x111: status = TMRC (state, instr); break;
3560 case 0x300: status = WANDN (instr); break;
3561 case 0x200: status = WAND (instr); break;
3563 case 0x810: case 0xa10:
3564 status = WMADD (instr); break;
3566 case 0x10e: case 0x50e: case 0x90e: case 0xd0e:
3567 status = WUNPCKIL (state, instr); break;
3568 case 0x10c: case 0x50c: case 0x90c: case 0xd0c:
3569 status = WUNPCKIH (state, instr); break;
3570 case 0x012: case 0x112: case 0x412: case 0x512:
3571 status = WSAD (instr); break;
3572 case 0x010: case 0x110: case 0x210: case 0x310:
3573 status = WMUL (instr); break;
3574 case 0x410: case 0x510: case 0x610: case 0x710:
3575 status = WMAC (instr); break;
3576 case 0x006: case 0x406: case 0x806: case 0xc06:
3577 status = WCMPEQ (state, instr); break;
3578 case 0x800: case 0x900: case 0xc00: case 0xd00:
3579 status = WAVG2 (instr); break;
3580 case 0x802: case 0x902: case 0xa02: case 0xb02:
3581 status = WALIGNR (state, instr); break;
3582 case 0x601: case 0x605: case 0x609: case 0x60d:
3583 status = TINSR (state, instr); break;
3584 case 0x107: case 0x507: case 0x907: case 0xd07:
3585 status = TEXTRM (state, instr); break;
3586 case 0x117: case 0x517: case 0x917: case 0xd17:
3587 status = TEXTRC (state, instr); break;
3588 case 0x401: case 0x405: case 0x409: case 0x40d:
3589 status = TBCST (state, instr); break;
3590 case 0x113: case 0x513: case 0x913: case 0xd13:
3591 status = TANDC (state, instr); break;
3592 case 0x01c: case 0x41c: case 0x81c: case 0xc1c:
3593 status = WACC (state, instr); break;
3594 case 0x115: case 0x515: case 0x915: case 0xd15:
3595 status = TORC (state, instr); break;
3596 case 0x103: case 0x503: case 0x903: case 0xd03:
3597 status = TMOVMSK (state, instr); break;
3598 case 0x106: case 0x306: case 0x506: case 0x706:
3599 case 0x906: case 0xb06: case 0xd06: case 0xf06:
3600 status = WCMPGT (state, instr); break;
3601 case 0x00e: case 0x20e: case 0x40e: case 0x60e:
3602 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
3603 status = WUNPCKEL (state, instr); break;
3604 case 0x00c: case 0x20c: case 0x40c: case 0x60c:
3605 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
3606 status = WUNPCKEH (state, instr); break;
3607 case 0x204: case 0x604: case 0xa04: case 0xe04:
3608 case 0x214: case 0x614: case 0xa14: case 0xe14:
3609 status = WSRL (state, instr); break;
3610 case 0x004: case 0x404: case 0x804: case 0xc04:
3611 case 0x014: case 0x414: case 0x814: case 0xc14:
3612 status = WSRA (state, instr); break;
3613 case 0x104: case 0x504: case 0x904: case 0xd04:
3614 case 0x114: case 0x514: case 0x914: case 0xd14:
3615 status = WSLL (state, instr); break;
3616 case 0x304: case 0x704: case 0xb04: case 0xf04:
3617 case 0x314: case 0x714: case 0xb14: case 0xf14:
3618 status = WROR (state, instr); break;
3619 case 0x116: case 0x316: case 0x516: case 0x716:
3620 case 0x916: case 0xb16: case 0xd16: case 0xf16:
3621 status = WMIN (state, instr); break;
3622 case 0x016: case 0x216: case 0x416: case 0x616:
3623 case 0x816: case 0xa16: case 0xc16: case 0xe16:
3624 status = WMAX (state, instr); break;
3625 case 0x002: case 0x102: case 0x202: case 0x302:
3626 case 0x402: case 0x502: case 0x602: case 0x702:
3627 status = WALIGNI (instr); break;
3628 case 0x01a: case 0x11a: case 0x21a: case 0x31a:
3629 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
3630 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
3631 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
3632 status = WSUB (state, instr); break;
3633 case 0x01e: case 0x11e: case 0x21e: case 0x31e:
3634 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
3635 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
3636 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
3637 status = WSHUFH (instr); break;
3638 case 0x018: case 0x118: case 0x218: case 0x318:
3639 case 0x418: case 0x518: case 0x618: case 0x718:
3640 case 0x818: case 0x918: case 0xa18: case 0xb18:
3641 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
3642 status = WADD (state, instr); break;
3643 case 0x008: case 0x108: case 0x208: case 0x308:
3644 case 0x408: case 0x508: case 0x608: case 0x708:
3645 case 0x808: case 0x908: case 0xa08: case 0xb08:
3646 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
3647 status = WPACK (state, instr); break;
3648 case 0x201: case 0x203: case 0x205: case 0x207:
3649 case 0x209: case 0x20b: case 0x20d: case 0x20f:
3650 case 0x211: case 0x213: case 0x215: case 0x217:
3651 case 0x219: case 0x21b: case 0x21d: case 0x21f:
3652 switch (BITS (16, 19))
3654 case 0x0: status = TMIA (state, instr); break;
3655 case 0x8: status = TMIAPH (state, instr); break;
3656 case 0xc:
3657 case 0xd:
3658 case 0xe:
3659 case 0xf: status = TMIAxy (state, instr); break;
3660 default: break;
3662 break;
3663 default:
3664 break;
3666 return status;
3669 /* Process a possibly Intel(r) Wireless MMX(tm) technology instruction.
3670 Return true if the instruction was handled. */
3673 ARMul_HandleIwmmxt (ARMul_State * state, ARMword instr)
3675 int status = ARMul_BUSY;
3677 if (BITS (24, 27) == 0xe)
3679 status = Process_Instruction (state, instr);
3681 else if (BITS (25, 27) == 0x6)
3683 if (BITS (4, 11) == 0x0 && BITS (20, 24) == 0x4)
3684 status = TMCRR (state, instr);
3685 else if (BITS (9, 11) == 0x0)
3687 if (BIT (20) == 0x0)
3688 status = WSTR (state, instr);
3689 else if (BITS (20, 24) == 0x5)
3690 status = TMRRC (state, instr);
3691 else
3692 status = WLDR (state, instr);
3696 if (status == ARMul_CANT)
3698 /* If the instruction was a recognised but illegal,
3699 perform the abort here rather than returning false.
3700 If we return false then ARMul_MRC may be called which
3701 will still abort, but which also perform the register
3702 transfer... */
3703 ARMul_Abort (state, ARMul_UndefinedInstrV);
3704 status = ARMul_DONE;
3707 return status == ARMul_DONE;
3711 Fetch_Iwmmxt_Register (unsigned int regnum, unsigned char * memory)
3713 if (regnum >= 16)
3715 memcpy (memory, wC + (regnum - 16), sizeof wC [0]);
3716 return sizeof wC [0];
3718 else
3720 memcpy (memory, wR + regnum, sizeof wR [0]);
3721 return sizeof wR [0];
3726 Store_Iwmmxt_Register (unsigned int regnum, const unsigned char * memory)
3728 if (regnum >= 16)
3730 memcpy (wC + (regnum - 16), memory, sizeof wC [0]);
3731 return sizeof wC [0];
3733 else
3735 memcpy (wR + regnum, memory, sizeof wR [0]);
3736 return sizeof wR [0];