[PATCH 26/57][Arm][GAS] Add support for MVE instructions: vpnot and vpsel
[binutils-gdb.git] / sim / arm / armemu.c
blob76f398b3d7172ac492c23536ed4102ebf77ccde0
1 /* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3 Modifications to add arch. v4 support by <jsmith@cygnus.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 #include "armdefs.h"
19 #include "armemu.h"
20 #include "armos.h"
21 #include "iwmmxt.h"
23 static ARMword GetDPRegRHS (ARMul_State *, ARMword);
24 static ARMword GetDPSRegRHS (ARMul_State *, ARMword);
25 static void WriteR15 (ARMul_State *, ARMword);
26 static void WriteSR15 (ARMul_State *, ARMword);
27 static void WriteR15Branch (ARMul_State *, ARMword);
28 static void WriteR15Load (ARMul_State *, ARMword);
29 static ARMword GetLSRegRHS (ARMul_State *, ARMword);
30 static ARMword GetLS7RHS (ARMul_State *, ARMword);
31 static unsigned LoadWord (ARMul_State *, ARMword, ARMword);
32 static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int);
33 static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int);
34 static unsigned StoreWord (ARMul_State *, ARMword, ARMword);
35 static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword);
36 static unsigned StoreByte (ARMul_State *, ARMword, ARMword);
37 static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword);
38 static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword);
39 static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword);
40 static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword);
41 static unsigned Multiply64 (ARMul_State *, ARMword, int, int);
42 static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int);
43 static void Handle_Load_Double (ARMul_State *, ARMword);
44 static void Handle_Store_Double (ARMul_State *, ARMword);
46 #define LUNSIGNED (0) /* unsigned operation */
47 #define LSIGNED (1) /* signed operation */
48 #define LDEFAULT (0) /* default : do nothing */
49 #define LSCC (1) /* set condition codes on result */
51 extern int stop_simulator;
53 /* Short-hand macros for LDR/STR. */
55 /* Store post decrement writeback. */
56 #define SHDOWNWB() \
57 lhs = LHS ; \
58 if (StoreHalfWord (state, instr, lhs)) \
59 LSBase = lhs - GetLS7RHS (state, instr);
61 /* Store post increment writeback. */
62 #define SHUPWB() \
63 lhs = LHS ; \
64 if (StoreHalfWord (state, instr, lhs)) \
65 LSBase = lhs + GetLS7RHS (state, instr);
67 /* Store pre decrement. */
68 #define SHPREDOWN() \
69 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
71 /* Store pre decrement writeback. */
72 #define SHPREDOWNWB() \
73 temp = LHS - GetLS7RHS (state, instr); \
74 if (StoreHalfWord (state, instr, temp)) \
75 LSBase = temp;
77 /* Store pre increment. */
78 #define SHPREUP() \
79 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
81 /* Store pre increment writeback. */
82 #define SHPREUPWB() \
83 temp = LHS + GetLS7RHS (state, instr); \
84 if (StoreHalfWord (state, instr, temp)) \
85 LSBase = temp;
87 /* Load post decrement writeback. */
88 #define LHPOSTDOWN() \
89 { \
90 int done = 1; \
91 lhs = LHS; \
92 temp = lhs - GetLS7RHS (state, instr); \
94 switch (BITS (5, 6)) \
95 { \
96 case 1: /* H */ \
97 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
98 LSBase = temp; \
99 break; \
100 case 2: /* SB */ \
101 if (LoadByte (state, instr, lhs, LSIGNED)) \
102 LSBase = temp; \
103 break; \
104 case 3: /* SH */ \
105 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
106 LSBase = temp; \
107 break; \
108 case 0: /* SWP handled elsewhere. */ \
109 default: \
110 done = 0; \
111 break; \
113 if (done) \
114 break; \
117 /* Load post increment writeback. */
118 #define LHPOSTUP() \
120 int done = 1; \
121 lhs = LHS; \
122 temp = lhs + GetLS7RHS (state, instr); \
124 switch (BITS (5, 6)) \
126 case 1: /* H */ \
127 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
128 LSBase = temp; \
129 break; \
130 case 2: /* SB */ \
131 if (LoadByte (state, instr, lhs, LSIGNED)) \
132 LSBase = temp; \
133 break; \
134 case 3: /* SH */ \
135 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
136 LSBase = temp; \
137 break; \
138 case 0: /* SWP handled elsewhere. */ \
139 default: \
140 done = 0; \
141 break; \
143 if (done) \
144 break; \
147 /* Load pre decrement. */
148 #define LHPREDOWN() \
150 int done = 1; \
152 temp = LHS - GetLS7RHS (state, instr); \
153 switch (BITS (5, 6)) \
155 case 1: /* H */ \
156 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
157 break; \
158 case 2: /* SB */ \
159 (void) LoadByte (state, instr, temp, LSIGNED); \
160 break; \
161 case 3: /* SH */ \
162 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
163 break; \
164 case 0: \
165 /* SWP handled elsewhere. */ \
166 default: \
167 done = 0; \
168 break; \
170 if (done) \
171 break; \
174 /* Load pre decrement writeback. */
175 #define LHPREDOWNWB() \
177 int done = 1; \
179 temp = LHS - GetLS7RHS (state, instr); \
180 switch (BITS (5, 6)) \
182 case 1: /* H */ \
183 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
184 LSBase = temp; \
185 break; \
186 case 2: /* SB */ \
187 if (LoadByte (state, instr, temp, LSIGNED)) \
188 LSBase = temp; \
189 break; \
190 case 3: /* SH */ \
191 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
192 LSBase = temp; \
193 break; \
194 case 0: \
195 /* SWP handled elsewhere. */ \
196 default: \
197 done = 0; \
198 break; \
200 if (done) \
201 break; \
204 /* Load pre increment. */
205 #define LHPREUP() \
207 int done = 1; \
209 temp = LHS + GetLS7RHS (state, instr); \
210 switch (BITS (5, 6)) \
212 case 1: /* H */ \
213 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
214 break; \
215 case 2: /* SB */ \
216 (void) LoadByte (state, instr, temp, LSIGNED); \
217 break; \
218 case 3: /* SH */ \
219 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
220 break; \
221 case 0: \
222 /* SWP handled elsewhere. */ \
223 default: \
224 done = 0; \
225 break; \
227 if (done) \
228 break; \
231 /* Load pre increment writeback. */
232 #define LHPREUPWB() \
234 int done = 1; \
236 temp = LHS + GetLS7RHS (state, instr); \
237 switch (BITS (5, 6)) \
239 case 1: /* H */ \
240 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
241 LSBase = temp; \
242 break; \
243 case 2: /* SB */ \
244 if (LoadByte (state, instr, temp, LSIGNED)) \
245 LSBase = temp; \
246 break; \
247 case 3: /* SH */ \
248 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
249 LSBase = temp; \
250 break; \
251 case 0: \
252 /* SWP handled elsewhere. */ \
253 default: \
254 done = 0; \
255 break; \
257 if (done) \
258 break; \
261 /* Attempt to emulate an ARMv6 instruction.
262 Returns non-zero upon success. */
264 #ifdef MODE32
265 static int
266 handle_v6_insn (ARMul_State * state, ARMword instr)
268 ARMword val;
269 ARMword Rd;
270 ARMword Rm;
271 ARMword Rn;
273 switch (BITS (20, 27))
275 #if 0
276 case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
277 case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
278 case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
279 case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
280 case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
281 case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
282 case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
283 case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
284 case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
285 case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
286 case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
287 case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
288 case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
289 case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
290 #endif
291 case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
292 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
293 case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
294 case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
295 case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
296 case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
297 case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
299 case 0x30:
301 /* MOVW<c> <Rd>,#<imm16>
302 instr[31,28] = cond
303 instr[27,20] = 0011 0000
304 instr[19,16] = imm4
305 instr[15,12] = Rd
306 instr[11, 0] = imm12. */
307 Rd = BITS (12, 15);
308 val = (BITS (16, 19) << 12) | BITS (0, 11);
309 state->Reg[Rd] = val;
310 return 1;
313 case 0x34:
315 /* MOVT<c> <Rd>,#<imm16>
316 instr[31,28] = cond
317 instr[27,20] = 0011 0100
318 instr[19,16] = imm4
319 instr[15,12] = Rd
320 instr[11, 0] = imm12. */
321 Rd = BITS (12, 15);
322 val = (BITS (16, 19) << 12) | BITS (0, 11);
323 state->Reg[Rd] &= 0xFFFF;
324 state->Reg[Rd] |= val << 16;
325 return 1;
328 case 0x62:
330 ARMword val1;
331 ARMword val2;
332 ARMsword n, m, r;
333 int i;
335 Rd = BITS (12, 15);
336 Rn = BITS (16, 19);
337 Rm = BITS (0, 3);
339 if (Rd == 15 || Rn == 15 || Rm == 15)
340 break;
342 val1 = state->Reg[Rn];
343 val2 = state->Reg[Rm];
345 switch (BITS (4, 11))
347 case 0xF1: /* QADD16<c> <Rd>,<Rn>,<Rm>. */
348 state->Reg[Rd] = 0;
350 for (i = 0; i < 32; i+= 16)
352 n = (val1 >> i) & 0xFFFF;
353 if (n & 0x8000)
354 n |= -(1 << 16);
356 m = (val2 >> i) & 0xFFFF;
357 if (m & 0x8000)
358 m |= -(1 << 16);
360 r = n + m;
362 if (r > 0x7FFF)
363 r = 0x7FFF;
364 else if (r < -(0x8000))
365 r = - 0x8000;
367 state->Reg[Rd] |= (r & 0xFFFF) << i;
369 return 1;
371 case 0xF3: /* QASX<c> <Rd>,<Rn>,<Rm>. */
372 n = val1 & 0xFFFF;
373 if (n & 0x8000)
374 n |= -(1 << 16);
376 m = (val2 >> 16) & 0xFFFF;
377 if (m & 0x8000)
378 m |= -(1 << 16);
380 r = n - m;
382 if (r > 0x7FFF)
383 r = 0x7FFF;
384 else if (r < -(0x8000))
385 r = - 0x8000;
387 state->Reg[Rd] = (r & 0xFFFF);
389 n = (val1 >> 16) & 0xFFFF;
390 if (n & 0x8000)
391 n |= -(1 << 16);
393 m = val2 & 0xFFFF;
394 if (m & 0x8000)
395 m |= -(1 << 16);
397 r = n + m;
399 if (r > 0x7FFF)
400 r = 0x7FFF;
401 else if (r < -(0x8000))
402 r = - 0x8000;
404 state->Reg[Rd] |= (r & 0xFFFF) << 16;
405 return 1;
407 case 0xF5: /* QSAX<c> <Rd>,<Rn>,<Rm>. */
408 n = val1 & 0xFFFF;
409 if (n & 0x8000)
410 n |= -(1 << 16);
412 m = (val2 >> 16) & 0xFFFF;
413 if (m & 0x8000)
414 m |= -(1 << 16);
416 r = n + m;
418 if (r > 0x7FFF)
419 r = 0x7FFF;
420 else if (r < -(0x8000))
421 r = - 0x8000;
423 state->Reg[Rd] = (r & 0xFFFF);
425 n = (val1 >> 16) & 0xFFFF;
426 if (n & 0x8000)
427 n |= -(1 << 16);
429 m = val2 & 0xFFFF;
430 if (m & 0x8000)
431 m |= -(1 << 16);
433 r = n - m;
435 if (r > 0x7FFF)
436 r = 0x7FFF;
437 else if (r < -(0x8000))
438 r = - 0x8000;
440 state->Reg[Rd] |= (r & 0xFFFF) << 16;
441 return 1;
443 case 0xF7: /* QSUB16<c> <Rd>,<Rn>,<Rm>. */
444 state->Reg[Rd] = 0;
446 for (i = 0; i < 32; i+= 16)
448 n = (val1 >> i) & 0xFFFF;
449 if (n & 0x8000)
450 n |= -(1 << 16);
452 m = (val2 >> i) & 0xFFFF;
453 if (m & 0x8000)
454 m |= -(1 << 16);
456 r = n - m;
458 if (r > 0x7FFF)
459 r = 0x7FFF;
460 else if (r < -(0x8000))
461 r = - 0x8000;
463 state->Reg[Rd] |= (r & 0xFFFF) << i;
465 return 1;
467 case 0xF9: /* QADD8<c> <Rd>,<Rn>,<Rm>. */
468 state->Reg[Rd] = 0;
470 for (i = 0; i < 32; i+= 8)
472 n = (val1 >> i) & 0xFF;
473 if (n & 0x80)
474 n |= - (1 << 8);
476 m = (val2 >> i) & 0xFF;
477 if (m & 0x80)
478 m |= - (1 << 8);
480 r = n + m;
482 if (r > 127)
483 r = 127;
484 else if (r < -128)
485 r = -128;
487 state->Reg[Rd] |= (r & 0xFF) << i;
489 return 1;
491 case 0xFF: /* QSUB8<c> <Rd>,<Rn>,<Rm>. */
492 state->Reg[Rd] = 0;
494 for (i = 0; i < 32; i+= 8)
496 n = (val1 >> i) & 0xFF;
497 if (n & 0x80)
498 n |= - (1 << 8);
500 m = (val2 >> i) & 0xFF;
501 if (m & 0x80)
502 m |= - (1 << 8);
504 r = n - m;
506 if (r > 127)
507 r = 127;
508 else if (r < -128)
509 r = -128;
511 state->Reg[Rd] |= (r & 0xFF) << i;
513 return 1;
515 default:
516 break;
518 break;
521 case 0x65:
523 ARMword valn;
524 ARMword valm;
525 ARMword res1, res2, res3, res4;
527 /* U{ADD|SUB}{8|16}<c> <Rd>, <Rn>, <Rm>
528 instr[31,28] = cond
529 instr[27,20] = 0110 0101
530 instr[19,16] = Rn
531 instr[15,12] = Rd
532 instr[11, 8] = 1111
533 instr[ 7, 4] = opcode: UADD8 (1001), UADD16 (0001), USUB8 (1111), USUB16 (0111)
534 instr[ 3, 0] = Rm. */
535 if (BITS (8, 11) != 0xF)
536 break;
538 Rn = BITS (16, 19);
539 Rd = BITS (12, 15);
540 Rm = BITS (0, 3);
542 if (Rn == 15 || Rd == 15 || Rm == 15)
544 ARMul_UndefInstr (state, instr);
545 state->Emulate = FALSE;
546 break;
549 valn = state->Reg[Rn];
550 valm = state->Reg[Rm];
552 switch (BITS (4, 7))
554 case 1: /* UADD16. */
555 res1 = (valn & 0xFFFF) + (valm & 0xFFFF);
556 if (res1 > 0xFFFF)
557 state->Cpsr |= (GE0 | GE1);
558 else
559 state->Cpsr &= ~ (GE0 | GE1);
561 res2 = (valn >> 16) + (valm >> 16);
562 if (res2 > 0xFFFF)
563 state->Cpsr |= (GE2 | GE3);
564 else
565 state->Cpsr &= ~ (GE2 | GE3);
567 state->Reg[Rd] = (res1 & 0xFFFF) | (res2 << 16);
568 return 1;
570 case 7: /* USUB16. */
571 res1 = (valn & 0xFFFF) - (valm & 0xFFFF);
572 if (res1 & 0x800000)
573 state->Cpsr |= (GE0 | GE1);
574 else
575 state->Cpsr &= ~ (GE0 | GE1);
577 res2 = (valn >> 16) - (valm >> 16);
578 if (res2 & 0x800000)
579 state->Cpsr |= (GE2 | GE3);
580 else
581 state->Cpsr &= ~ (GE2 | GE3);
583 state->Reg[Rd] = (res1 & 0xFFFF) | (res2 << 16);
584 return 1;
586 case 9: /* UADD8. */
587 res1 = (valn & 0xFF) + (valm & 0xFF);
588 if (res1 > 0xFF)
589 state->Cpsr |= GE0;
590 else
591 state->Cpsr &= ~ GE0;
593 res2 = ((valn >> 8) & 0xFF) + ((valm >> 8) & 0xFF);
594 if (res2 > 0xFF)
595 state->Cpsr |= GE1;
596 else
597 state->Cpsr &= ~ GE1;
599 res3 = ((valn >> 16) & 0xFF) + ((valm >> 16) & 0xFF);
600 if (res3 > 0xFF)
601 state->Cpsr |= GE2;
602 else
603 state->Cpsr &= ~ GE2;
605 res4 = (valn >> 24) + (valm >> 24);
606 if (res4 > 0xFF)
607 state->Cpsr |= GE3;
608 else
609 state->Cpsr &= ~ GE3;
611 state->Reg[Rd] = (res1 & 0xFF) | ((res2 << 8) & 0xFF00)
612 | ((res3 << 16) & 0xFF0000) | (res4 << 24);
613 return 1;
615 case 15: /* USUB8. */
616 res1 = (valn & 0xFF) - (valm & 0xFF);
617 if (res1 & 0x800000)
618 state->Cpsr |= GE0;
619 else
620 state->Cpsr &= ~ GE0;
622 res2 = ((valn >> 8) & 0XFF) - ((valm >> 8) & 0xFF);
623 if (res2 & 0x800000)
624 state->Cpsr |= GE1;
625 else
626 state->Cpsr &= ~ GE1;
628 res3 = ((valn >> 16) & 0XFF) - ((valm >> 16) & 0xFF);
629 if (res3 & 0x800000)
630 state->Cpsr |= GE2;
631 else
632 state->Cpsr &= ~ GE2;
634 res4 = (valn >> 24) - (valm >> 24) ;
635 if (res4 & 0x800000)
636 state->Cpsr |= GE3;
637 else
638 state->Cpsr &= ~ GE3;
640 state->Reg[Rd] = (res1 & 0xFF) | ((res2 << 8) & 0xFF00)
641 | ((res3 << 16) & 0xFF0000) | (res4 << 24);
642 return 1;
644 default:
645 break;
647 break;
650 case 0x68:
652 ARMword res;
654 /* PKHBT<c> <Rd>,<Rn>,<Rm>{,LSL #<imm>}
655 PKHTB<c> <Rd>,<Rn>,<Rm>{,ASR #<imm>}
656 SXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>}
657 SXTB16<c> <Rd>,<Rm>{,<rotation>}
658 SEL<c> <Rd>,<Rn>,<Rm>
660 instr[31,28] = cond
661 instr[27,20] = 0110 1000
662 instr[19,16] = Rn
663 instr[15,12] = Rd
664 instr[11, 7] = imm5 (PKH), 11111 (SEL), rr000 (SXTAB16 & SXTB16),
665 instr[6] = tb (PKH), 0 (SEL), 1 (SXT)
666 instr[5] = opcode: PKH (0), SEL/SXT (1)
667 instr[4] = 1
668 instr[ 3, 0] = Rm. */
670 if (BIT (4) != 1)
671 break;
673 if (BIT (5) == 0)
675 /* FIXME: Add implementation of PKH. */
676 fprintf (stderr, "PKH: NOT YET IMPLEMENTED\n");
677 ARMul_UndefInstr (state, instr);
678 break;
681 if (BIT (6) == 1)
683 /* FIXME: Add implementation of SXT. */
684 fprintf (stderr, "SXT: NOT YET IMPLEMENTED\n");
685 ARMul_UndefInstr (state, instr);
686 break;
689 Rn = BITS (16, 19);
690 Rd = BITS (12, 15);
691 Rm = BITS (0, 3);
692 if (Rn == 15 || Rm == 15 || Rd == 15)
694 ARMul_UndefInstr (state, instr);
695 state->Emulate = FALSE;
696 break;
699 res = (state->Reg[(state->Cpsr & GE0) ? Rn : Rm]) & 0xFF;
700 res |= (state->Reg[(state->Cpsr & GE1) ? Rn : Rm]) & 0xFF00;
701 res |= (state->Reg[(state->Cpsr & GE2) ? Rn : Rm]) & 0xFF0000;
702 res |= (state->Reg[(state->Cpsr & GE3) ? Rn : Rm]) & 0xFF000000;
703 state->Reg[Rd] = res;
704 return 1;
707 case 0x6a:
709 int ror = -1;
711 switch (BITS (4, 11))
713 case 0x07: ror = 0; break;
714 case 0x47: ror = 8; break;
715 case 0x87: ror = 16; break;
716 case 0xc7: ror = 24; break;
718 case 0x01:
719 case 0xf3:
720 printf ("Unhandled v6 insn: ssat\n");
721 return 0;
723 default:
724 break;
727 if (ror == -1)
729 if (BITS (4, 6) == 0x7)
731 printf ("Unhandled v6 insn: ssat\n");
732 return 0;
734 break;
737 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
738 if (Rm & 0x80)
739 Rm |= 0xffffff00;
741 if (BITS (16, 19) == 0xf)
742 /* SXTB */
743 state->Reg[BITS (12, 15)] = Rm;
744 else
745 /* SXTAB */
746 state->Reg[BITS (12, 15)] += Rm;
748 return 1;
750 case 0x6b:
752 int ror = -1;
754 switch (BITS (4, 11))
756 case 0x07: ror = 0; break;
757 case 0x47: ror = 8; break;
758 case 0x87: ror = 16; break;
759 case 0xc7: ror = 24; break;
761 case 0xf3:
763 /* REV<c> <Rd>,<Rm>
764 instr[31,28] = cond
765 instr[27,20] = 0110 1011
766 instr[19,16] = 1111
767 instr[15,12] = Rd
768 instr[11, 4] = 1111 0011
769 instr[ 3, 0] = Rm. */
770 if (BITS (16, 19) != 0xF)
771 break;
773 Rd = BITS (12, 15);
774 Rm = BITS (0, 3);
775 if (Rd == 15 || Rm == 15)
777 ARMul_UndefInstr (state, instr);
778 state->Emulate = FALSE;
779 break;
782 val = state->Reg[Rm] << 24;
783 val |= ((state->Reg[Rm] << 8) & 0xFF0000);
784 val |= ((state->Reg[Rm] >> 8) & 0xFF00);
785 val |= ((state->Reg[Rm] >> 24));
786 state->Reg[Rd] = val;
787 return 1;
790 case 0xfb:
792 /* REV16<c> <Rd>,<Rm>. */
793 if (BITS (16, 19) != 0xF)
794 break;
796 Rd = BITS (12, 15);
797 Rm = BITS (0, 3);
798 if (Rd == 15 || Rm == 15)
800 ARMul_UndefInstr (state, instr);
801 state->Emulate = FALSE;
802 break;
805 val = 0;
806 val |= ((state->Reg[Rm] >> 8) & 0x00FF00FF);
807 val |= ((state->Reg[Rm] << 8) & 0xFF00FF00);
808 state->Reg[Rd] = val;
809 return 1;
812 default:
813 break;
816 if (ror == -1)
817 break;
819 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
820 if (Rm & 0x8000)
821 Rm |= 0xffff0000;
823 if (BITS (16, 19) == 0xf)
824 /* SXTH */
825 state->Reg[BITS (12, 15)] = Rm;
826 else
827 /* SXTAH */
828 state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
830 return 1;
832 case 0x6e:
834 int ror = -1;
836 switch (BITS (4, 11))
838 case 0x07: ror = 0; break;
839 case 0x47: ror = 8; break;
840 case 0x87: ror = 16; break;
841 case 0xc7: ror = 24; break;
843 case 0x01:
844 case 0xf3:
845 printf ("Unhandled v6 insn: usat\n");
846 return 0;
848 default:
849 break;
852 if (ror == -1)
854 if (BITS (4, 6) == 0x7)
856 printf ("Unhandled v6 insn: usat\n");
857 return 0;
859 break;
862 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
864 if (BITS (16, 19) == 0xf)
865 /* UXTB */
866 state->Reg[BITS (12, 15)] = Rm;
867 else
868 /* UXTAB */
869 state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
871 return 1;
873 case 0x6f:
875 int i;
876 int ror = -1;
878 switch (BITS (4, 11))
880 case 0x07: ror = 0; break;
881 case 0x47: ror = 8; break;
882 case 0x87: ror = 16; break;
883 case 0xc7: ror = 24; break;
885 case 0xf3: /* RBIT */
886 if (BITS (16, 19) != 0xF)
887 break;
888 Rd = BITS (12, 15);
889 state->Reg[Rd] = 0;
890 Rm = state->Reg[BITS (0, 3)];
891 for (i = 0; i < 32; i++)
892 if (Rm & (1 << i))
893 state->Reg[Rd] |= (1 << (31 - i));
894 return 1;
896 case 0xfb:
897 printf ("Unhandled v6 insn: revsh\n");
898 return 0;
900 default:
901 break;
904 if (ror == -1)
905 break;
907 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
909 if (BITS (16, 19) == 0xf)
910 /* UXT */
911 state->Reg[BITS (12, 15)] = Rm;
912 else
913 /* UXTAH */
914 state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm;
916 return 1;
918 case 0x7c:
919 case 0x7d:
921 int lsb;
922 int msb;
923 ARMword mask;
925 /* BFC<c> <Rd>,#<lsb>,#<width>
926 BFI<c> <Rd>,<Rn>,#<lsb>,#<width>
928 instr[31,28] = cond
929 instr[27,21] = 0111 110
930 instr[20,16] = msb
931 instr[15,12] = Rd
932 instr[11, 7] = lsb
933 instr[ 6, 4] = 001 1111
934 instr[ 3, 0] = Rn (BFI) / 1111 (BFC). */
936 if (BITS (4, 6) != 0x1)
937 break;
939 Rd = BITS (12, 15);
940 if (Rd == 15)
942 ARMul_UndefInstr (state, instr);
943 state->Emulate = FALSE;
946 lsb = BITS (7, 11);
947 msb = BITS (16, 20);
948 if (lsb > msb)
950 ARMul_UndefInstr (state, instr);
951 state->Emulate = FALSE;
954 mask = -(1 << lsb);
955 mask &= ~(-(1 << (msb + 1)));
956 state->Reg[Rd] &= ~ mask;
958 Rn = BITS (0, 3);
959 if (Rn != 0xF)
961 ARMword val = state->Reg[Rn] & ~(-(1 << ((msb + 1) - lsb)));
962 state->Reg[Rd] |= val << lsb;
964 return 1;
967 case 0x7b:
968 case 0x7a: /* SBFX<c> <Rd>,<Rn>,#<lsb>,#<width>. */
970 int lsb;
971 int widthm1;
972 ARMsword sval;
974 if (BITS (4, 6) != 0x5)
975 break;
977 Rd = BITS (12, 15);
978 if (Rd == 15)
980 ARMul_UndefInstr (state, instr);
981 state->Emulate = FALSE;
984 Rn = BITS (0, 3);
985 if (Rn == 15)
987 ARMul_UndefInstr (state, instr);
988 state->Emulate = FALSE;
991 lsb = BITS (7, 11);
992 widthm1 = BITS (16, 20);
994 sval = state->Reg[Rn];
995 sval <<= (31 - (lsb + widthm1));
996 sval >>= (31 - widthm1);
997 state->Reg[Rd] = sval;
999 return 1;
1002 case 0x7f:
1003 case 0x7e:
1005 int lsb;
1006 int widthm1;
1008 /* UBFX<c> <Rd>,<Rn>,#<lsb>,#<width>
1009 instr[31,28] = cond
1010 instr[27,21] = 0111 111
1011 instr[20,16] = widthm1
1012 instr[15,12] = Rd
1013 instr[11, 7] = lsb
1014 instr[ 6, 4] = 101
1015 instr[ 3, 0] = Rn. */
1017 if (BITS (4, 6) != 0x5)
1018 break;
1020 Rd = BITS (12, 15);
1021 if (Rd == 15)
1023 ARMul_UndefInstr (state, instr);
1024 state->Emulate = FALSE;
1027 Rn = BITS (0, 3);
1028 if (Rn == 15)
1030 ARMul_UndefInstr (state, instr);
1031 state->Emulate = FALSE;
1034 lsb = BITS (7, 11);
1035 widthm1 = BITS (16, 20);
1037 val = state->Reg[Rn];
1038 val >>= lsb;
1039 val &= ~(-(1 << (widthm1 + 1)));
1041 state->Reg[Rd] = val;
1043 return 1;
1045 #if 0
1046 case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
1047 #endif
1048 default:
1049 break;
1051 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr);
1052 return 0;
1054 #endif
1056 static void
1057 handle_VFP_move (ARMul_State * state, ARMword instr)
1059 switch (BITS (20, 27))
1061 case 0xC4:
1062 case 0xC5:
1063 switch (BITS (4, 11))
1065 case 0xA1:
1066 case 0xA3:
1068 /* VMOV two core <-> two VFP single precision. */
1069 int sreg = (BITS (0, 3) << 1) | BIT (5);
1071 if (BIT (20))
1073 state->Reg[BITS (12, 15)] = VFP_uword (sreg);
1074 state->Reg[BITS (16, 19)] = VFP_uword (sreg + 1);
1076 else
1078 VFP_uword (sreg) = state->Reg[BITS (12, 15)];
1079 VFP_uword (sreg + 1) = state->Reg[BITS (16, 19)];
1082 break;
1084 case 0xB1:
1085 case 0xB3:
1087 /* VMOV two core <-> VFP double precision. */
1088 int dreg = BITS (0, 3) | (BIT (5) << 4);
1090 if (BIT (20))
1092 if (trace)
1093 fprintf (stderr, " VFP: VMOV: r%d r%d <= d%d\n",
1094 BITS (12, 15), BITS (16, 19), dreg);
1096 state->Reg[BITS (12, 15)] = VFP_dword (dreg);
1097 state->Reg[BITS (16, 19)] = VFP_dword (dreg) >> 32;
1099 else
1101 VFP_dword (dreg) = state->Reg[BITS (16, 19)];
1102 VFP_dword (dreg) <<= 32;
1103 VFP_dword (dreg) |= state->Reg[BITS (12, 15)];
1105 if (trace)
1106 fprintf (stderr, " VFP: VMOV: d%d <= r%d r%d : %g\n",
1107 dreg, BITS (16, 19), BITS (12, 15),
1108 VFP_dval (dreg));
1111 break;
1113 default:
1114 fprintf (stderr, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1115 break;
1117 break;
1119 case 0xe0:
1120 case 0xe1:
1121 /* VMOV single core <-> VFP single precision. */
1122 if (BITS (0, 6) != 0x10 || BITS (8, 11) != 0xA)
1123 fprintf (stderr, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1124 else
1126 int sreg = (BITS (16, 19) << 1) | BIT (7);
1128 if (BIT (20))
1129 state->Reg[DESTReg] = VFP_uword (sreg);
1130 else
1131 VFP_uword (sreg) = state->Reg[DESTReg];
1133 break;
1135 default:
1136 fprintf (stderr, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1137 return;
1141 /* EMULATION of ARM6. */
1143 /* The PC pipeline value depends on whether ARM
1144 or Thumb instructions are being executed. */
1145 ARMword isize;
1147 ARMword
1148 #ifdef MODE32
1149 ARMul_Emulate32 (ARMul_State * state)
1150 #else
1151 ARMul_Emulate26 (ARMul_State * state)
1152 #endif
1154 ARMword instr; /* The current instruction. */
1155 ARMword dest = 0; /* Almost the DestBus. */
1156 ARMword temp; /* Ubiquitous third hand. */
1157 ARMword pc = 0; /* The address of the current instruction. */
1158 ARMword lhs; /* Almost the ABus and BBus. */
1159 ARMword rhs;
1160 ARMword decoded = 0; /* Instruction pipeline. */
1161 ARMword loaded = 0;
1163 /* Execute the next instruction. */
1165 if (state->NextInstr < PRIMEPIPE)
1167 decoded = state->decoded;
1168 loaded = state->loaded;
1169 pc = state->pc;
1174 /* Just keep going. */
1175 isize = INSN_SIZE;
1177 switch (state->NextInstr)
1179 case SEQ:
1180 /* Advance the pipeline, and an S cycle. */
1181 state->Reg[15] += isize;
1182 pc += isize;
1183 instr = decoded;
1184 decoded = loaded;
1185 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
1186 break;
1188 case NONSEQ:
1189 /* Advance the pipeline, and an N cycle. */
1190 state->Reg[15] += isize;
1191 pc += isize;
1192 instr = decoded;
1193 decoded = loaded;
1194 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
1195 NORMALCYCLE;
1196 break;
1198 case PCINCEDSEQ:
1199 /* Program counter advanced, and an S cycle. */
1200 pc += isize;
1201 instr = decoded;
1202 decoded = loaded;
1203 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
1204 NORMALCYCLE;
1205 break;
1207 case PCINCEDNONSEQ:
1208 /* Program counter advanced, and an N cycle. */
1209 pc += isize;
1210 instr = decoded;
1211 decoded = loaded;
1212 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
1213 NORMALCYCLE;
1214 break;
1216 case RESUME:
1217 /* The program counter has been changed. */
1218 pc = state->Reg[15];
1219 #ifndef MODE32
1220 pc = pc & R15PCBITS;
1221 #endif
1222 state->Reg[15] = pc + (isize * 2);
1223 state->Aborted = 0;
1224 instr = ARMul_ReLoadInstr (state, pc, isize);
1225 decoded = ARMul_ReLoadInstr (state, pc + isize, isize);
1226 loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize);
1227 NORMALCYCLE;
1228 break;
1230 default:
1231 /* The program counter has been changed. */
1232 pc = state->Reg[15];
1233 #ifndef MODE32
1234 pc = pc & R15PCBITS;
1235 #endif
1236 state->Reg[15] = pc + (isize * 2);
1237 state->Aborted = 0;
1238 instr = ARMul_LoadInstrN (state, pc, isize);
1239 decoded = ARMul_LoadInstrS (state, pc + (isize), isize);
1240 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
1241 NORMALCYCLE;
1242 break;
1245 if (state->EventSet)
1246 ARMul_EnvokeEvent (state);
1248 if (! TFLAG && trace)
1250 fprintf (stderr, "pc: %x, ", pc & ~1);
1251 if (! disas)
1252 fprintf (stderr, "instr: %x\n", instr);
1255 if (instr == 0 || pc < 0x10)
1257 ARMul_Abort (state, ARMUndefinedInstrV);
1258 state->Emulate = FALSE;
1261 #if 0 /* Enable this code to help track down stack alignment bugs. */
1263 static ARMword old_sp = -1;
1265 if (old_sp != state->Reg[13])
1267 old_sp = state->Reg[13];
1268 fprintf (stderr, "pc: %08x: SP set to %08x%s\n",
1269 pc & ~1, old_sp, (old_sp % 8) ? " [UNALIGNED!]" : "");
1272 #endif
1274 if (state->Exception)
1276 /* Any exceptions ? */
1277 if (state->NresetSig == LOW)
1279 ARMul_Abort (state, ARMul_ResetV);
1280 break;
1282 else if (!state->NfiqSig && !FFLAG)
1284 ARMul_Abort (state, ARMul_FIQV);
1285 break;
1287 else if (!state->NirqSig && !IFLAG)
1289 ARMul_Abort (state, ARMul_IRQV);
1290 break;
1294 if (state->CallDebug > 0)
1296 if (state->Emulate < ONCE)
1298 state->NextInstr = RESUME;
1299 break;
1301 if (state->Debug)
1303 fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n",
1304 (long) pc, (long) instr, (long) state->Mode);
1305 (void) fgetc (stdin);
1308 else if (state->Emulate < ONCE)
1310 state->NextInstr = RESUME;
1311 break;
1314 state->NumInstrs++;
1316 #ifdef MODET
1317 /* Provide Thumb instruction decoding. If the processor is in Thumb
1318 mode, then we can simply decode the Thumb instruction, and map it
1319 to the corresponding ARM instruction (by directly loading the
1320 instr variable, and letting the normal ARM simulator
1321 execute). There are some caveats to ensure that the correct
1322 pipelined PC value is used when executing Thumb code, and also for
1323 dealing with the BL instruction. */
1324 if (TFLAG)
1326 ARMword new;
1328 /* Check if in Thumb mode. */
1329 switch (ARMul_ThumbDecode (state, pc, instr, &new))
1331 case t_undefined:
1332 /* This is a Thumb instruction. */
1333 ARMul_UndefInstr (state, instr);
1334 goto donext;
1336 case t_branch:
1337 /* Already processed. */
1338 goto donext;
1340 case t_decoded:
1341 /* ARM instruction available. */
1342 if (disas || trace)
1344 fprintf (stderr, " emulate as: ");
1345 if (trace)
1346 fprintf (stderr, "%08x ", new);
1347 if (! disas)
1348 fprintf (stderr, "\n");
1350 instr = new;
1351 /* So continue instruction decoding. */
1352 break;
1353 default:
1354 break;
1357 #endif
1358 if (disas)
1359 print_insn (instr);
1361 /* Check the condition codes. */
1362 if ((temp = TOPBITS (28)) == AL)
1363 /* Vile deed in the need for speed. */
1364 goto mainswitch;
1366 /* Check the condition code. */
1367 switch ((int) TOPBITS (28))
1369 case AL:
1370 temp = TRUE;
1371 break;
1372 case NV:
1373 if (state->is_v5)
1375 if (BITS (25, 27) == 5) /* BLX(1) */
1377 ARMword dest;
1379 state->Reg[14] = pc + 4;
1381 /* Force entry into Thumb mode. */
1382 dest = pc + 8 + 1;
1383 if (BIT (23))
1384 dest += (NEGBRANCH + (BIT (24) << 1));
1385 else
1386 dest += POSBRANCH + (BIT (24) << 1);
1388 WriteR15Branch (state, dest);
1389 goto donext;
1391 else if ((instr & 0xFC70F000) == 0xF450F000)
1392 /* The PLD instruction. Ignored. */
1393 goto donext;
1394 else if ( ((instr & 0xfe500f00) == 0xfc100100)
1395 || ((instr & 0xfe500f00) == 0xfc000100))
1396 /* wldrw and wstrw are unconditional. */
1397 goto mainswitch;
1398 else
1399 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
1400 ARMul_UndefInstr (state, instr);
1402 temp = FALSE;
1403 break;
1404 case EQ:
1405 temp = ZFLAG;
1406 break;
1407 case NE:
1408 temp = !ZFLAG;
1409 break;
1410 case VS:
1411 temp = VFLAG;
1412 break;
1413 case VC:
1414 temp = !VFLAG;
1415 break;
1416 case MI:
1417 temp = NFLAG;
1418 break;
1419 case PL:
1420 temp = !NFLAG;
1421 break;
1422 case CS:
1423 temp = CFLAG;
1424 break;
1425 case CC:
1426 temp = !CFLAG;
1427 break;
1428 case HI:
1429 temp = (CFLAG && !ZFLAG);
1430 break;
1431 case LS:
1432 temp = (!CFLAG || ZFLAG);
1433 break;
1434 case GE:
1435 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
1436 break;
1437 case LT:
1438 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
1439 break;
1440 case GT:
1441 temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
1442 break;
1443 case LE:
1444 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
1445 break;
1446 } /* cc check */
1448 /* Handle the Clock counter here. */
1449 if (state->is_XScale)
1451 ARMword cp14r0;
1452 int ok;
1454 ok = state->CPRead[14] (state, 0, & cp14r0);
1456 if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE))
1458 unsigned long newcycles, nowtime = ARMul_Time (state);
1460 newcycles = nowtime - state->LastTime;
1461 state->LastTime = nowtime;
1463 if (cp14r0 & ARMul_CP14_R0_CCD)
1465 if (state->CP14R0_CCD == -1)
1466 state->CP14R0_CCD = newcycles;
1467 else
1468 state->CP14R0_CCD += newcycles;
1470 if (state->CP14R0_CCD >= 64)
1472 newcycles = 0;
1474 while (state->CP14R0_CCD >= 64)
1475 state->CP14R0_CCD -= 64, newcycles++;
1477 goto check_PMUintr;
1480 else
1482 ARMword cp14r1;
1483 int do_int;
1485 state->CP14R0_CCD = -1;
1486 check_PMUintr:
1487 do_int = 0;
1488 cp14r0 |= ARMul_CP14_R0_FLAG2;
1489 (void) state->CPWrite[14] (state, 0, cp14r0);
1491 ok = state->CPRead[14] (state, 1, & cp14r1);
1493 /* Coded like this for portability. */
1494 while (ok && newcycles)
1496 if (cp14r1 == 0xffffffff)
1498 cp14r1 = 0;
1499 do_int = 1;
1501 else
1502 cp14r1 ++;
1504 newcycles --;
1507 (void) state->CPWrite[14] (state, 1, cp14r1);
1509 if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2))
1511 ARMword temp;
1513 if (state->CPRead[13] (state, 8, & temp)
1514 && (temp & ARMul_CP13_R8_PMUS))
1515 ARMul_Abort (state, ARMul_FIQV);
1516 else
1517 ARMul_Abort (state, ARMul_IRQV);
1523 /* Handle hardware instructions breakpoints here. */
1524 if (state->is_XScale)
1526 if ( (pc | 3) == (read_cp15_reg (14, 0, 8) | 2)
1527 || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2))
1529 if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB))
1530 ARMul_OSHandleSWI (state, SWI_Breakpoint);
1534 /* Actual execution of instructions begins here. */
1535 /* If the condition codes don't match, stop here. */
1536 if (temp)
1538 mainswitch:
1540 if (state->is_XScale)
1542 if (BIT (20) == 0 && BITS (25, 27) == 0)
1544 if (BITS (4, 7) == 0xD)
1546 /* XScale Load Consecutive insn. */
1547 ARMword temp = GetLS7RHS (state, instr);
1548 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
1549 ARMword addr = BIT (24) ? temp2 : LHS;
1551 if (BIT (12))
1552 ARMul_UndefInstr (state, instr);
1553 else if (addr & 7)
1554 /* Alignment violation. */
1555 ARMul_Abort (state, ARMul_DataAbortV);
1556 else
1558 int wb = BIT (21) || (! BIT (24));
1560 state->Reg[BITS (12, 15)] =
1561 ARMul_LoadWordN (state, addr);
1562 state->Reg[BITS (12, 15) + 1] =
1563 ARMul_LoadWordN (state, addr + 4);
1564 if (wb)
1565 LSBase = temp2;
1568 goto donext;
1570 else if (BITS (4, 7) == 0xF)
1572 /* XScale Store Consecutive insn. */
1573 ARMword temp = GetLS7RHS (state, instr);
1574 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
1575 ARMword addr = BIT (24) ? temp2 : LHS;
1577 if (BIT (12))
1578 ARMul_UndefInstr (state, instr);
1579 else if (addr & 7)
1580 /* Alignment violation. */
1581 ARMul_Abort (state, ARMul_DataAbortV);
1582 else
1584 ARMul_StoreWordN (state, addr,
1585 state->Reg[BITS (12, 15)]);
1586 ARMul_StoreWordN (state, addr + 4,
1587 state->Reg[BITS (12, 15) + 1]);
1589 if (BIT (21)|| ! BIT (24))
1590 LSBase = temp2;
1593 goto donext;
1597 if (ARMul_HandleIwmmxt (state, instr))
1598 goto donext;
1601 switch ((int) BITS (20, 27))
1603 /* Data Processing Register RHS Instructions. */
1605 case 0x00: /* AND reg and MUL */
1606 #ifdef MODET
1607 if (BITS (4, 11) == 0xB)
1609 /* STRH register offset, no write-back, down, post indexed. */
1610 SHDOWNWB ();
1611 break;
1613 if (BITS (4, 7) == 0xD)
1615 Handle_Load_Double (state, instr);
1616 break;
1618 if (BITS (4, 7) == 0xF)
1620 Handle_Store_Double (state, instr);
1621 break;
1623 #endif
1624 if (BITS (4, 7) == 9)
1626 /* MUL */
1627 rhs = state->Reg[MULRHSReg];
1628 if (MULLHSReg == MULDESTReg)
1630 UNDEF_MULDestEQOp1;
1631 state->Reg[MULDESTReg] = 0;
1633 else if (MULDESTReg != 15)
1634 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
1635 else
1636 UNDEF_MULPCDest;
1638 for (dest = 0, temp = 0; dest < 32; dest ++)
1639 if (rhs & (1L << dest))
1640 temp = dest;
1642 /* Mult takes this many/2 I cycles. */
1643 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
1645 else
1647 /* AND reg. */
1648 rhs = DPRegRHS;
1649 dest = LHS & rhs;
1650 WRITEDEST (dest);
1652 break;
1654 case 0x01: /* ANDS reg and MULS */
1655 #ifdef MODET
1656 if ((BITS (4, 11) & 0xF9) == 0x9)
1657 /* LDR register offset, no write-back, down, post indexed. */
1658 LHPOSTDOWN ();
1659 /* Fall through to rest of decoding. */
1660 #endif
1661 if (BITS (4, 7) == 9)
1663 /* MULS */
1664 rhs = state->Reg[MULRHSReg];
1666 if (MULLHSReg == MULDESTReg)
1668 UNDEF_MULDestEQOp1;
1669 state->Reg[MULDESTReg] = 0;
1670 CLEARN;
1671 SETZ;
1673 else if (MULDESTReg != 15)
1675 dest = state->Reg[MULLHSReg] * rhs;
1676 ARMul_NegZero (state, dest);
1677 state->Reg[MULDESTReg] = dest;
1679 else
1680 UNDEF_MULPCDest;
1682 for (dest = 0, temp = 0; dest < 32; dest ++)
1683 if (rhs & (1L << dest))
1684 temp = dest;
1686 /* Mult takes this many/2 I cycles. */
1687 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
1689 else
1691 /* ANDS reg. */
1692 rhs = DPSRegRHS;
1693 dest = LHS & rhs;
1694 WRITESDEST (dest);
1696 break;
1698 case 0x02: /* EOR reg and MLA */
1699 #ifdef MODET
1700 if (BITS (4, 11) == 0xB)
1702 /* STRH register offset, write-back, down, post indexed. */
1703 SHDOWNWB ();
1704 break;
1706 #endif
1707 if (BITS (4, 7) == 9)
1708 { /* MLA */
1709 rhs = state->Reg[MULRHSReg];
1710 if (MULLHSReg == MULDESTReg)
1712 UNDEF_MULDestEQOp1;
1713 state->Reg[MULDESTReg] = state->Reg[MULACCReg];
1715 else if (MULDESTReg != 15)
1716 state->Reg[MULDESTReg] =
1717 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
1718 else
1719 UNDEF_MULPCDest;
1721 for (dest = 0, temp = 0; dest < 32; dest ++)
1722 if (rhs & (1L << dest))
1723 temp = dest;
1725 /* Mult takes this many/2 I cycles. */
1726 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
1728 else
1730 rhs = DPRegRHS;
1731 dest = LHS ^ rhs;
1732 WRITEDEST (dest);
1734 break;
1736 case 0x03: /* EORS reg and MLAS */
1737 #ifdef MODET
1738 if ((BITS (4, 11) & 0xF9) == 0x9)
1739 /* LDR register offset, write-back, down, post-indexed. */
1740 LHPOSTDOWN ();
1741 /* Fall through to rest of the decoding. */
1742 #endif
1743 if (BITS (4, 7) == 9)
1745 /* MLAS */
1746 rhs = state->Reg[MULRHSReg];
1748 if (MULLHSReg == MULDESTReg)
1750 UNDEF_MULDestEQOp1;
1751 dest = state->Reg[MULACCReg];
1752 ARMul_NegZero (state, dest);
1753 state->Reg[MULDESTReg] = dest;
1755 else if (MULDESTReg != 15)
1757 dest =
1758 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
1759 ARMul_NegZero (state, dest);
1760 state->Reg[MULDESTReg] = dest;
1762 else
1763 UNDEF_MULPCDest;
1765 for (dest = 0, temp = 0; dest < 32; dest ++)
1766 if (rhs & (1L << dest))
1767 temp = dest;
1769 /* Mult takes this many/2 I cycles. */
1770 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
1772 else
1774 /* EORS Reg. */
1775 rhs = DPSRegRHS;
1776 dest = LHS ^ rhs;
1777 WRITESDEST (dest);
1779 break;
1781 case 0x04: /* SUB reg */
1782 #ifdef MODET
1783 if (BITS (4, 7) == 0xB)
1785 /* STRH immediate offset, no write-back, down, post indexed. */
1786 SHDOWNWB ();
1787 break;
1789 if (BITS (4, 7) == 0xD)
1791 Handle_Load_Double (state, instr);
1792 break;
1794 if (BITS (4, 7) == 0xF)
1796 Handle_Store_Double (state, instr);
1797 break;
1799 #endif
1800 rhs = DPRegRHS;
1801 dest = LHS - rhs;
1802 WRITEDEST (dest);
1803 break;
1805 case 0x05: /* SUBS reg */
1806 #ifdef MODET
1807 if ((BITS (4, 7) & 0x9) == 0x9)
1808 /* LDR immediate offset, no write-back, down, post indexed. */
1809 LHPOSTDOWN ();
1810 /* Fall through to the rest of the instruction decoding. */
1811 #endif
1812 lhs = LHS;
1813 rhs = DPRegRHS;
1814 dest = lhs - rhs;
1816 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1818 ARMul_SubCarry (state, lhs, rhs, dest);
1819 ARMul_SubOverflow (state, lhs, rhs, dest);
1821 else
1823 CLEARC;
1824 CLEARV;
1826 WRITESDEST (dest);
1827 break;
1829 case 0x06: /* RSB reg */
1830 #ifdef MODET
1831 if (BITS (4, 7) == 0xB)
1833 /* STRH immediate offset, write-back, down, post indexed. */
1834 SHDOWNWB ();
1835 break;
1837 #endif
1838 rhs = DPRegRHS;
1839 dest = rhs - LHS;
1840 WRITEDEST (dest);
1841 break;
1843 case 0x07: /* RSBS reg */
1844 #ifdef MODET
1845 if ((BITS (4, 7) & 0x9) == 0x9)
1846 /* LDR immediate offset, write-back, down, post indexed. */
1847 LHPOSTDOWN ();
1848 /* Fall through to remainder of instruction decoding. */
1849 #endif
1850 lhs = LHS;
1851 rhs = DPRegRHS;
1852 dest = rhs - lhs;
1854 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1856 ARMul_SubCarry (state, rhs, lhs, dest);
1857 ARMul_SubOverflow (state, rhs, lhs, dest);
1859 else
1861 CLEARC;
1862 CLEARV;
1864 WRITESDEST (dest);
1865 break;
1867 case 0x08: /* ADD reg */
1868 #ifdef MODET
1869 if (BITS (4, 11) == 0xB)
1871 /* STRH register offset, no write-back, up, post indexed. */
1872 SHUPWB ();
1873 break;
1875 if (BITS (4, 7) == 0xD)
1877 Handle_Load_Double (state, instr);
1878 break;
1880 if (BITS (4, 7) == 0xF)
1882 Handle_Store_Double (state, instr);
1883 break;
1885 #endif
1886 #ifdef MODET
1887 if (BITS (4, 7) == 0x9)
1889 /* MULL */
1890 /* 32x32 = 64 */
1891 ARMul_Icycles (state,
1892 Multiply64 (state, instr, LUNSIGNED,
1893 LDEFAULT), 0L);
1894 break;
1896 #endif
1897 rhs = DPRegRHS;
1898 dest = LHS + rhs;
1899 WRITEDEST (dest);
1900 break;
1902 case 0x09: /* ADDS reg */
1903 #ifdef MODET
1904 if ((BITS (4, 11) & 0xF9) == 0x9)
1905 /* LDR register offset, no write-back, up, post indexed. */
1906 LHPOSTUP ();
1907 /* Fall through to remaining instruction decoding. */
1908 #endif
1909 #ifdef MODET
1910 if (BITS (4, 7) == 0x9)
1912 /* MULL */
1913 /* 32x32=64 */
1914 ARMul_Icycles (state,
1915 Multiply64 (state, instr, LUNSIGNED, LSCC),
1916 0L);
1917 break;
1919 #endif
1920 lhs = LHS;
1921 rhs = DPRegRHS;
1922 dest = lhs + rhs;
1923 ASSIGNZ (dest == 0);
1924 if ((lhs | rhs) >> 30)
1926 /* Possible C,V,N to set. */
1927 ASSIGNN (NEG (dest));
1928 ARMul_AddCarry (state, lhs, rhs, dest);
1929 ARMul_AddOverflow (state, lhs, rhs, dest);
1931 else
1933 CLEARN;
1934 CLEARC;
1935 CLEARV;
1937 WRITESDEST (dest);
1938 break;
1940 case 0x0a: /* ADC reg */
1941 #ifdef MODET
1942 if (BITS (4, 11) == 0xB)
1944 /* STRH register offset, write-back, up, post-indexed. */
1945 SHUPWB ();
1946 break;
1948 if (BITS (4, 7) == 0x9)
1950 /* MULL */
1951 /* 32x32=64 */
1952 ARMul_Icycles (state,
1953 MultiplyAdd64 (state, instr, LUNSIGNED,
1954 LDEFAULT), 0L);
1955 break;
1957 #endif
1958 rhs = DPRegRHS;
1959 dest = LHS + rhs + CFLAG;
1960 WRITEDEST (dest);
1961 break;
1963 case 0x0b: /* ADCS reg */
1964 #ifdef MODET
1965 if ((BITS (4, 11) & 0xF9) == 0x9)
1966 /* LDR register offset, write-back, up, post indexed. */
1967 LHPOSTUP ();
1968 /* Fall through to remaining instruction decoding. */
1969 if (BITS (4, 7) == 0x9)
1971 /* MULL */
1972 /* 32x32=64 */
1973 ARMul_Icycles (state,
1974 MultiplyAdd64 (state, instr, LUNSIGNED,
1975 LSCC), 0L);
1976 break;
1978 #endif
1979 lhs = LHS;
1980 rhs = DPRegRHS;
1981 dest = lhs + rhs + CFLAG;
1982 ASSIGNZ (dest == 0);
1983 if ((lhs | rhs) >> 30)
1985 /* Possible C,V,N to set. */
1986 ASSIGNN (NEG (dest));
1987 ARMul_AddCarry (state, lhs, rhs, dest);
1988 ARMul_AddOverflow (state, lhs, rhs, dest);
1990 else
1992 CLEARN;
1993 CLEARC;
1994 CLEARV;
1996 WRITESDEST (dest);
1997 break;
1999 case 0x0c: /* SBC reg */
2000 #ifdef MODET
2001 if (BITS (4, 7) == 0xB)
2003 /* STRH immediate offset, no write-back, up post indexed. */
2004 SHUPWB ();
2005 break;
2007 if (BITS (4, 7) == 0xD)
2009 Handle_Load_Double (state, instr);
2010 break;
2012 if (BITS (4, 7) == 0xF)
2014 Handle_Store_Double (state, instr);
2015 break;
2017 if (BITS (4, 7) == 0x9)
2019 /* MULL */
2020 /* 32x32=64 */
2021 ARMul_Icycles (state,
2022 Multiply64 (state, instr, LSIGNED, LDEFAULT),
2023 0L);
2024 break;
2026 #endif
2027 rhs = DPRegRHS;
2028 dest = LHS - rhs - !CFLAG;
2029 WRITEDEST (dest);
2030 break;
2032 case 0x0d: /* SBCS reg */
2033 #ifdef MODET
2034 if ((BITS (4, 7) & 0x9) == 0x9)
2035 /* LDR immediate offset, no write-back, up, post indexed. */
2036 LHPOSTUP ();
2038 if (BITS (4, 7) == 0x9)
2040 /* MULL */
2041 /* 32x32=64 */
2042 ARMul_Icycles (state,
2043 Multiply64 (state, instr, LSIGNED, LSCC),
2044 0L);
2045 break;
2047 #endif
2048 lhs = LHS;
2049 rhs = DPRegRHS;
2050 dest = lhs - rhs - !CFLAG;
2051 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2053 ARMul_SubCarry (state, lhs, rhs, dest);
2054 ARMul_SubOverflow (state, lhs, rhs, dest);
2056 else
2058 CLEARC;
2059 CLEARV;
2061 WRITESDEST (dest);
2062 break;
2064 case 0x0e: /* RSC reg */
2065 #ifdef MODET
2066 if (BITS (4, 7) == 0xB)
2068 /* STRH immediate offset, write-back, up, post indexed. */
2069 SHUPWB ();
2070 break;
2073 if (BITS (4, 7) == 0x9)
2075 /* MULL */
2076 /* 32x32=64 */
2077 ARMul_Icycles (state,
2078 MultiplyAdd64 (state, instr, LSIGNED,
2079 LDEFAULT), 0L);
2080 break;
2082 #endif
2083 rhs = DPRegRHS;
2084 dest = rhs - LHS - !CFLAG;
2085 WRITEDEST (dest);
2086 break;
2088 case 0x0f: /* RSCS reg */
2089 #ifdef MODET
2090 if ((BITS (4, 7) & 0x9) == 0x9)
2091 /* LDR immediate offset, write-back, up, post indexed. */
2092 LHPOSTUP ();
2093 /* Fall through to remaining instruction decoding. */
2095 if (BITS (4, 7) == 0x9)
2097 /* MULL */
2098 /* 32x32=64 */
2099 ARMul_Icycles (state,
2100 MultiplyAdd64 (state, instr, LSIGNED, LSCC),
2101 0L);
2102 break;
2104 #endif
2105 lhs = LHS;
2106 rhs = DPRegRHS;
2107 dest = rhs - lhs - !CFLAG;
2109 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
2111 ARMul_SubCarry (state, rhs, lhs, dest);
2112 ARMul_SubOverflow (state, rhs, lhs, dest);
2114 else
2116 CLEARC;
2117 CLEARV;
2119 WRITESDEST (dest);
2120 break;
2122 case 0x10: /* TST reg and MRS CPSR and SWP word. */
2123 if (state->is_v5e)
2125 if (BIT (4) == 0 && BIT (7) == 1)
2127 /* ElSegundo SMLAxy insn. */
2128 ARMword op1 = state->Reg[BITS (0, 3)];
2129 ARMword op2 = state->Reg[BITS (8, 11)];
2130 ARMword Rn = state->Reg[BITS (12, 15)];
2132 if (BIT (5))
2133 op1 >>= 16;
2134 if (BIT (6))
2135 op2 >>= 16;
2136 op1 &= 0xFFFF;
2137 op2 &= 0xFFFF;
2138 if (op1 & 0x8000)
2139 op1 -= 65536;
2140 if (op2 & 0x8000)
2141 op2 -= 65536;
2142 op1 *= op2;
2144 if (AddOverflow (op1, Rn, op1 + Rn))
2145 SETS;
2146 state->Reg[BITS (16, 19)] = op1 + Rn;
2147 break;
2150 if (BITS (4, 11) == 5)
2152 /* ElSegundo QADD insn. */
2153 ARMword op1 = state->Reg[BITS (0, 3)];
2154 ARMword op2 = state->Reg[BITS (16, 19)];
2155 ARMword result = op1 + op2;
2156 if (AddOverflow (op1, op2, result))
2158 result = POS (result) ? 0x80000000 : 0x7fffffff;
2159 SETS;
2161 state->Reg[BITS (12, 15)] = result;
2162 break;
2165 #ifdef MODET
2166 if (BITS (4, 11) == 0xB)
2168 /* STRH register offset, no write-back, down, pre indexed. */
2169 SHPREDOWN ();
2170 break;
2172 if (BITS (4, 7) == 0xD)
2174 Handle_Load_Double (state, instr);
2175 break;
2177 if (BITS (4, 7) == 0xF)
2179 Handle_Store_Double (state, instr);
2180 break;
2182 #endif
2183 if (BITS (4, 11) == 9)
2185 /* SWP */
2186 UNDEF_SWPPC;
2187 temp = LHS;
2188 BUSUSEDINCPCS;
2189 #ifndef MODE32
2190 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
2192 INTERNALABORT (temp);
2193 (void) ARMul_LoadWordN (state, temp);
2194 (void) ARMul_LoadWordN (state, temp);
2196 else
2197 #endif
2198 dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
2199 if (temp & 3)
2200 DEST = ARMul_Align (state, temp, dest);
2201 else
2202 DEST = dest;
2203 if (state->abortSig || state->Aborted)
2204 TAKEABORT;
2206 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
2207 { /* MRS CPSR */
2208 UNDEF_MRSPC;
2209 DEST = ECC | EINT | EMODE;
2211 else
2213 #ifdef MODE32
2214 if (state->is_v6
2215 && handle_v6_insn (state, instr))
2216 break;
2217 #endif
2218 UNDEF_Test;
2220 break;
2222 case 0x11: /* TSTP reg */
2223 #ifdef MODET
2224 if ((BITS (4, 11) & 0xF9) == 0x9)
2225 /* LDR register offset, no write-back, down, pre indexed. */
2226 LHPREDOWN ();
2227 /* Continue with remaining instruction decode. */
2228 #endif
2229 if (DESTReg == 15)
2231 /* TSTP reg */
2232 #ifdef MODE32
2233 state->Cpsr = GETSPSR (state->Bank);
2234 ARMul_CPSRAltered (state);
2235 #else
2236 rhs = DPRegRHS;
2237 temp = LHS & rhs;
2238 SETR15PSR (temp);
2239 #endif
2241 else
2243 /* TST reg */
2244 rhs = DPSRegRHS;
2245 dest = LHS & rhs;
2246 ARMul_NegZero (state, dest);
2248 break;
2250 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
2251 if (state->is_v5)
2253 if (BITS (4, 7) == 3)
2255 /* BLX(2) */
2256 ARMword temp;
2258 if (TFLAG)
2259 temp = (pc + 2) | 1;
2260 else
2261 temp = pc + 4;
2263 WriteR15Branch (state, state->Reg[RHSReg]);
2264 state->Reg[14] = temp;
2265 break;
2269 if (state->is_v5e)
2271 if (BIT (4) == 0 && BIT (7) == 1
2272 && (BIT (5) == 0 || BITS (12, 15) == 0))
2274 /* ElSegundo SMLAWy/SMULWy insn. */
2275 ARMdword op1 = state->Reg[BITS (0, 3)];
2276 ARMdword op2 = state->Reg[BITS (8, 11)];
2277 ARMdword result;
2279 if (BIT (6))
2280 op2 >>= 16;
2281 if (op1 & 0x80000000)
2282 op1 -= 1ULL << 32;
2283 op2 &= 0xFFFF;
2284 if (op2 & 0x8000)
2285 op2 -= 65536;
2286 result = (op1 * op2) >> 16;
2288 if (BIT (5) == 0)
2290 ARMword Rn = state->Reg[BITS (12, 15)];
2292 if (AddOverflow (result, Rn, result + Rn))
2293 SETS;
2294 result += Rn;
2296 state->Reg[BITS (16, 19)] = result;
2297 break;
2300 if (BITS (4, 11) == 5)
2302 /* ElSegundo QSUB insn. */
2303 ARMword op1 = state->Reg[BITS (0, 3)];
2304 ARMword op2 = state->Reg[BITS (16, 19)];
2305 ARMword result = op1 - op2;
2307 if (SubOverflow (op1, op2, result))
2309 result = POS (result) ? 0x80000000 : 0x7fffffff;
2310 SETS;
2313 state->Reg[BITS (12, 15)] = result;
2314 break;
2317 #ifdef MODET
2318 if (BITS (4, 11) == 0xB)
2320 /* STRH register offset, write-back, down, pre indexed. */
2321 SHPREDOWNWB ();
2322 break;
2324 if (BITS (4, 27) == 0x12FFF1)
2326 /* BX */
2327 WriteR15Branch (state, state->Reg[RHSReg]);
2328 break;
2330 if (BITS (4, 7) == 0xD)
2332 Handle_Load_Double (state, instr);
2333 break;
2335 if (BITS (4, 7) == 0xF)
2337 Handle_Store_Double (state, instr);
2338 break;
2340 #endif
2341 if (state->is_v5)
2343 if (BITS (4, 7) == 0x7)
2345 extern int SWI_vector_installed;
2347 /* Hardware is allowed to optionally override this
2348 instruction and treat it as a breakpoint. Since
2349 this is a simulator not hardware, we take the position
2350 that if a SWI vector was not installed, then an Abort
2351 vector was probably not installed either, and so
2352 normally this instruction would be ignored, even if an
2353 Abort is generated. This is a bad thing, since GDB
2354 uses this instruction for its breakpoints (at least in
2355 Thumb mode it does). So intercept the instruction here
2356 and generate a breakpoint SWI instead. */
2357 if (! SWI_vector_installed)
2358 ARMul_OSHandleSWI (state, SWI_Breakpoint);
2359 else
2361 /* BKPT - normally this will cause an abort, but on the
2362 XScale we must check the DCSR. */
2363 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
2364 if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT))
2365 break;
2368 /* Force the next instruction to be refetched. */
2369 state->NextInstr = RESUME;
2370 break;
2373 if (DESTReg == 15)
2375 /* MSR reg to CPSR. */
2376 UNDEF_MSRPC;
2377 temp = DPRegRHS;
2378 #ifdef MODET
2379 /* Don't allow TBIT to be set by MSR. */
2380 temp &= ~ TBIT;
2381 #endif
2382 ARMul_FixCPSR (state, instr, temp);
2384 #ifdef MODE32
2385 else if (state->is_v6
2386 && handle_v6_insn (state, instr))
2387 break;
2388 #endif
2389 else
2390 UNDEF_Test;
2392 break;
2394 case 0x13: /* TEQP reg */
2395 #ifdef MODET
2396 if ((BITS (4, 11) & 0xF9) == 0x9)
2397 /* LDR register offset, write-back, down, pre indexed. */
2398 LHPREDOWNWB ();
2399 /* Continue with remaining instruction decode. */
2400 #endif
2401 if (DESTReg == 15)
2403 /* TEQP reg */
2404 #ifdef MODE32
2405 state->Cpsr = GETSPSR (state->Bank);
2406 ARMul_CPSRAltered (state);
2407 #else
2408 rhs = DPRegRHS;
2409 temp = LHS ^ rhs;
2410 SETR15PSR (temp);
2411 #endif
2413 else
2415 /* TEQ Reg. */
2416 rhs = DPSRegRHS;
2417 dest = LHS ^ rhs;
2418 ARMul_NegZero (state, dest);
2420 break;
2422 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
2423 if (state->is_v5e)
2425 if (BIT (4) == 0 && BIT (7) == 1)
2427 /* ElSegundo SMLALxy insn. */
2428 ARMdword op1 = state->Reg[BITS (0, 3)];
2429 ARMdword op2 = state->Reg[BITS (8, 11)];
2430 ARMdword dest;
2432 if (BIT (5))
2433 op1 >>= 16;
2434 if (BIT (6))
2435 op2 >>= 16;
2436 op1 &= 0xFFFF;
2437 if (op1 & 0x8000)
2438 op1 -= 65536;
2439 op2 &= 0xFFFF;
2440 if (op2 & 0x8000)
2441 op2 -= 65536;
2443 dest = (ARMdword) state->Reg[BITS (16, 19)] << 32;
2444 dest |= state->Reg[BITS (12, 15)];
2445 dest += op1 * op2;
2446 state->Reg[BITS (12, 15)] = dest;
2447 state->Reg[BITS (16, 19)] = dest >> 32;
2448 break;
2451 if (BITS (4, 11) == 5)
2453 /* ElSegundo QDADD insn. */
2454 ARMword op1 = state->Reg[BITS (0, 3)];
2455 ARMword op2 = state->Reg[BITS (16, 19)];
2456 ARMword op2d = op2 + op2;
2457 ARMword result;
2459 if (AddOverflow (op2, op2, op2d))
2461 SETS;
2462 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
2465 result = op1 + op2d;
2466 if (AddOverflow (op1, op2d, result))
2468 SETS;
2469 result = POS (result) ? 0x80000000 : 0x7fffffff;
2472 state->Reg[BITS (12, 15)] = result;
2473 break;
2476 #ifdef MODET
2477 if (BITS (4, 7) == 0xB)
2479 /* STRH immediate offset, no write-back, down, pre indexed. */
2480 SHPREDOWN ();
2481 break;
2483 if (BITS (4, 7) == 0xD)
2485 Handle_Load_Double (state, instr);
2486 break;
2488 if (BITS (4, 7) == 0xF)
2490 Handle_Store_Double (state, instr);
2491 break;
2493 #endif
2494 if (BITS (4, 11) == 9)
2496 /* SWP */
2497 UNDEF_SWPPC;
2498 temp = LHS;
2499 BUSUSEDINCPCS;
2500 #ifndef MODE32
2501 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
2503 INTERNALABORT (temp);
2504 (void) ARMul_LoadByte (state, temp);
2505 (void) ARMul_LoadByte (state, temp);
2507 else
2508 #endif
2509 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
2510 if (state->abortSig || state->Aborted)
2511 TAKEABORT;
2513 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
2515 /* MRS SPSR */
2516 UNDEF_MRSPC;
2517 DEST = GETSPSR (state->Bank);
2519 #ifdef MODE32
2520 else if (state->is_v6
2521 && handle_v6_insn (state, instr))
2522 break;
2523 #endif
2524 else
2525 UNDEF_Test;
2527 break;
2529 case 0x15: /* CMPP reg. */
2530 #ifdef MODET
2531 if ((BITS (4, 7) & 0x9) == 0x9)
2532 /* LDR immediate offset, no write-back, down, pre indexed. */
2533 LHPREDOWN ();
2534 /* Continue with remaining instruction decode. */
2535 #endif
2536 if (DESTReg == 15)
2538 /* CMPP reg. */
2539 #ifdef MODE32
2540 state->Cpsr = GETSPSR (state->Bank);
2541 ARMul_CPSRAltered (state);
2542 #else
2543 rhs = DPRegRHS;
2544 temp = LHS - rhs;
2545 SETR15PSR (temp);
2546 #endif
2548 else
2550 /* CMP reg. */
2551 lhs = LHS;
2552 rhs = DPRegRHS;
2553 dest = lhs - rhs;
2554 ARMul_NegZero (state, dest);
2555 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2557 ARMul_SubCarry (state, lhs, rhs, dest);
2558 ARMul_SubOverflow (state, lhs, rhs, dest);
2560 else
2562 CLEARC;
2563 CLEARV;
2566 break;
2568 case 0x16: /* CMN reg and MSR reg to SPSR */
2569 if (state->is_v5e)
2571 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
2573 /* ElSegundo SMULxy insn. */
2574 ARMword op1 = state->Reg[BITS (0, 3)];
2575 ARMword op2 = state->Reg[BITS (8, 11)];
2577 if (BIT (5))
2578 op1 >>= 16;
2579 if (BIT (6))
2580 op2 >>= 16;
2581 op1 &= 0xFFFF;
2582 op2 &= 0xFFFF;
2583 if (op1 & 0x8000)
2584 op1 -= 65536;
2585 if (op2 & 0x8000)
2586 op2 -= 65536;
2588 state->Reg[BITS (16, 19)] = op1 * op2;
2589 break;
2592 if (BITS (4, 11) == 5)
2594 /* ElSegundo QDSUB insn. */
2595 ARMword op1 = state->Reg[BITS (0, 3)];
2596 ARMword op2 = state->Reg[BITS (16, 19)];
2597 ARMword op2d = op2 + op2;
2598 ARMword result;
2600 if (AddOverflow (op2, op2, op2d))
2602 SETS;
2603 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
2606 result = op1 - op2d;
2607 if (SubOverflow (op1, op2d, result))
2609 SETS;
2610 result = POS (result) ? 0x80000000 : 0x7fffffff;
2613 state->Reg[BITS (12, 15)] = result;
2614 break;
2618 if (state->is_v5)
2620 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
2622 /* ARM5 CLZ insn. */
2623 ARMword op1 = state->Reg[BITS (0, 3)];
2624 int result = 32;
2626 if (op1)
2627 for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
2628 result++;
2630 state->Reg[BITS (12, 15)] = result;
2631 break;
2634 #ifdef MODET
2635 if (BITS (4, 7) == 0xB)
2637 /* STRH immediate offset, write-back, down, pre indexed. */
2638 SHPREDOWNWB ();
2639 break;
2641 if (BITS (4, 7) == 0xD)
2643 Handle_Load_Double (state, instr);
2644 break;
2646 if (BITS (4, 7) == 0xF)
2648 Handle_Store_Double (state, instr);
2649 break;
2651 #endif
2652 if (DESTReg == 15)
2654 /* MSR */
2655 UNDEF_MSRPC;
2656 ARMul_FixSPSR (state, instr, DPRegRHS);
2658 else
2660 #ifdef MODE32
2661 if (state->is_v6
2662 && handle_v6_insn (state, instr))
2663 break;
2664 #endif
2665 UNDEF_Test;
2667 break;
2669 case 0x17: /* CMNP reg */
2670 #ifdef MODET
2671 if ((BITS (4, 7) & 0x9) == 0x9)
2672 /* LDR immediate offset, write-back, down, pre indexed. */
2673 LHPREDOWNWB ();
2674 /* Continue with remaining instruction decoding. */
2675 #endif
2676 if (DESTReg == 15)
2678 #ifdef MODE32
2679 state->Cpsr = GETSPSR (state->Bank);
2680 ARMul_CPSRAltered (state);
2681 #else
2682 rhs = DPRegRHS;
2683 temp = LHS + rhs;
2684 SETR15PSR (temp);
2685 #endif
2686 break;
2688 else
2690 /* CMN reg. */
2691 lhs = LHS;
2692 rhs = DPRegRHS;
2693 dest = lhs + rhs;
2694 ASSIGNZ (dest == 0);
2695 if ((lhs | rhs) >> 30)
2697 /* Possible C,V,N to set. */
2698 ASSIGNN (NEG (dest));
2699 ARMul_AddCarry (state, lhs, rhs, dest);
2700 ARMul_AddOverflow (state, lhs, rhs, dest);
2702 else
2704 CLEARN;
2705 CLEARC;
2706 CLEARV;
2709 break;
2711 case 0x18: /* ORR reg */
2712 #ifdef MODET
2713 if (BITS (4, 11) == 0xB)
2715 /* STRH register offset, no write-back, up, pre indexed. */
2716 SHPREUP ();
2717 break;
2719 if (BITS (4, 7) == 0xD)
2721 Handle_Load_Double (state, instr);
2722 break;
2724 if (BITS (4, 7) == 0xF)
2726 Handle_Store_Double (state, instr);
2727 break;
2729 #endif
2730 rhs = DPRegRHS;
2731 dest = LHS | rhs;
2732 WRITEDEST (dest);
2733 break;
2735 case 0x19: /* ORRS reg */
2736 #ifdef MODET
2737 if ((BITS (4, 11) & 0xF9) == 0x9)
2738 /* LDR register offset, no write-back, up, pre indexed. */
2739 LHPREUP ();
2740 /* Continue with remaining instruction decoding. */
2741 #endif
2742 rhs = DPSRegRHS;
2743 dest = LHS | rhs;
2744 WRITESDEST (dest);
2745 break;
2747 case 0x1a: /* MOV reg */
2748 #ifdef MODET
2749 if (BITS (4, 11) == 0xB)
2751 /* STRH register offset, write-back, up, pre indexed. */
2752 SHPREUPWB ();
2753 break;
2755 if (BITS (4, 7) == 0xD)
2757 Handle_Load_Double (state, instr);
2758 break;
2760 if (BITS (4, 7) == 0xF)
2762 Handle_Store_Double (state, instr);
2763 break;
2765 #endif
2766 dest = DPRegRHS;
2767 WRITEDEST (dest);
2768 break;
2770 case 0x1b: /* MOVS reg */
2771 #ifdef MODET
2772 if ((BITS (4, 11) & 0xF9) == 0x9)
2773 /* LDR register offset, write-back, up, pre indexed. */
2774 LHPREUPWB ();
2775 /* Continue with remaining instruction decoding. */
2776 #endif
2777 dest = DPSRegRHS;
2778 WRITESDEST (dest);
2779 break;
2781 case 0x1c: /* BIC reg */
2782 #ifdef MODET
2783 if (BITS (4, 7) == 0xB)
2785 /* STRH immediate offset, no write-back, up, pre indexed. */
2786 SHPREUP ();
2787 break;
2789 if (BITS (4, 7) == 0xD)
2791 Handle_Load_Double (state, instr);
2792 break;
2794 else if (BITS (4, 7) == 0xF)
2796 Handle_Store_Double (state, instr);
2797 break;
2799 #endif
2800 rhs = DPRegRHS;
2801 dest = LHS & ~rhs;
2802 WRITEDEST (dest);
2803 break;
2805 case 0x1d: /* BICS reg */
2806 #ifdef MODET
2807 if ((BITS (4, 7) & 0x9) == 0x9)
2808 /* LDR immediate offset, no write-back, up, pre indexed. */
2809 LHPREUP ();
2810 /* Continue with instruction decoding. */
2811 #endif
2812 rhs = DPSRegRHS;
2813 dest = LHS & ~rhs;
2814 WRITESDEST (dest);
2815 break;
2817 case 0x1e: /* MVN reg */
2818 #ifdef MODET
2819 if (BITS (4, 7) == 0xB)
2821 /* STRH immediate offset, write-back, up, pre indexed. */
2822 SHPREUPWB ();
2823 break;
2825 if (BITS (4, 7) == 0xD)
2827 Handle_Load_Double (state, instr);
2828 break;
2830 if (BITS (4, 7) == 0xF)
2832 Handle_Store_Double (state, instr);
2833 break;
2835 #endif
2836 dest = ~DPRegRHS;
2837 WRITEDEST (dest);
2838 break;
2840 case 0x1f: /* MVNS reg */
2841 #ifdef MODET
2842 if ((BITS (4, 7) & 0x9) == 0x9)
2843 /* LDR immediate offset, write-back, up, pre indexed. */
2844 LHPREUPWB ();
2845 /* Continue instruction decoding. */
2846 #endif
2847 dest = ~DPSRegRHS;
2848 WRITESDEST (dest);
2849 break;
2852 /* Data Processing Immediate RHS Instructions. */
2854 case 0x20: /* AND immed */
2855 dest = LHS & DPImmRHS;
2856 WRITEDEST (dest);
2857 break;
2859 case 0x21: /* ANDS immed */
2860 DPSImmRHS;
2861 dest = LHS & rhs;
2862 WRITESDEST (dest);
2863 break;
2865 case 0x22: /* EOR immed */
2866 dest = LHS ^ DPImmRHS;
2867 WRITEDEST (dest);
2868 break;
2870 case 0x23: /* EORS immed */
2871 DPSImmRHS;
2872 dest = LHS ^ rhs;
2873 WRITESDEST (dest);
2874 break;
2876 case 0x24: /* SUB immed */
2877 dest = LHS - DPImmRHS;
2878 WRITEDEST (dest);
2879 break;
2881 case 0x25: /* SUBS immed */
2882 lhs = LHS;
2883 rhs = DPImmRHS;
2884 dest = lhs - rhs;
2886 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2888 ARMul_SubCarry (state, lhs, rhs, dest);
2889 ARMul_SubOverflow (state, lhs, rhs, dest);
2891 else
2893 CLEARC;
2894 CLEARV;
2896 WRITESDEST (dest);
2897 break;
2899 case 0x26: /* RSB immed */
2900 dest = DPImmRHS - LHS;
2901 WRITEDEST (dest);
2902 break;
2904 case 0x27: /* RSBS immed */
2905 lhs = LHS;
2906 rhs = DPImmRHS;
2907 dest = rhs - lhs;
2909 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
2911 ARMul_SubCarry (state, rhs, lhs, dest);
2912 ARMul_SubOverflow (state, rhs, lhs, dest);
2914 else
2916 CLEARC;
2917 CLEARV;
2919 WRITESDEST (dest);
2920 break;
2922 case 0x28: /* ADD immed */
2923 dest = LHS + DPImmRHS;
2924 WRITEDEST (dest);
2925 break;
2927 case 0x29: /* ADDS immed */
2928 lhs = LHS;
2929 rhs = DPImmRHS;
2930 dest = lhs + rhs;
2931 ASSIGNZ (dest == 0);
2933 if ((lhs | rhs) >> 30)
2935 /* Possible C,V,N to set. */
2936 ASSIGNN (NEG (dest));
2937 ARMul_AddCarry (state, lhs, rhs, dest);
2938 ARMul_AddOverflow (state, lhs, rhs, dest);
2940 else
2942 CLEARN;
2943 CLEARC;
2944 CLEARV;
2946 WRITESDEST (dest);
2947 break;
2949 case 0x2a: /* ADC immed */
2950 dest = LHS + DPImmRHS + CFLAG;
2951 WRITEDEST (dest);
2952 break;
2954 case 0x2b: /* ADCS immed */
2955 lhs = LHS;
2956 rhs = DPImmRHS;
2957 dest = lhs + rhs + CFLAG;
2958 ASSIGNZ (dest == 0);
2959 if ((lhs | rhs) >> 30)
2961 /* Possible C,V,N to set. */
2962 ASSIGNN (NEG (dest));
2963 ARMul_AddCarry (state, lhs, rhs, dest);
2964 ARMul_AddOverflow (state, lhs, rhs, dest);
2966 else
2968 CLEARN;
2969 CLEARC;
2970 CLEARV;
2972 WRITESDEST (dest);
2973 break;
2975 case 0x2c: /* SBC immed */
2976 dest = LHS - DPImmRHS - !CFLAG;
2977 WRITEDEST (dest);
2978 break;
2980 case 0x2d: /* SBCS immed */
2981 lhs = LHS;
2982 rhs = DPImmRHS;
2983 dest = lhs - rhs - !CFLAG;
2984 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2986 ARMul_SubCarry (state, lhs, rhs, dest);
2987 ARMul_SubOverflow (state, lhs, rhs, dest);
2989 else
2991 CLEARC;
2992 CLEARV;
2994 WRITESDEST (dest);
2995 break;
2997 case 0x2e: /* RSC immed */
2998 dest = DPImmRHS - LHS - !CFLAG;
2999 WRITEDEST (dest);
3000 break;
3002 case 0x2f: /* RSCS immed */
3003 lhs = LHS;
3004 rhs = DPImmRHS;
3005 dest = rhs - lhs - !CFLAG;
3006 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
3008 ARMul_SubCarry (state, rhs, lhs, dest);
3009 ARMul_SubOverflow (state, rhs, lhs, dest);
3011 else
3013 CLEARC;
3014 CLEARV;
3016 WRITESDEST (dest);
3017 break;
3019 case 0x30: /* MOVW immed */
3020 #ifdef MODE32
3021 if (state->is_v6
3022 && handle_v6_insn (state, instr))
3023 break;
3024 #endif
3025 dest = BITS (0, 11);
3026 dest |= (BITS (16, 19) << 12);
3027 WRITEDEST (dest);
3028 break;
3030 case 0x31: /* TSTP immed */
3031 if (DESTReg == 15)
3033 /* TSTP immed. */
3034 #ifdef MODE32
3035 state->Cpsr = GETSPSR (state->Bank);
3036 ARMul_CPSRAltered (state);
3037 #else
3038 temp = LHS & DPImmRHS;
3039 SETR15PSR (temp);
3040 #endif
3042 else
3044 /* TST immed. */
3045 DPSImmRHS;
3046 dest = LHS & rhs;
3047 ARMul_NegZero (state, dest);
3049 break;
3051 case 0x32: /* TEQ immed and MSR immed to CPSR */
3052 if (DESTReg == 15)
3053 /* MSR immed to CPSR. */
3054 ARMul_FixCPSR (state, instr, DPImmRHS);
3055 #ifdef MODE32
3056 else if (state->is_v6
3057 && handle_v6_insn (state, instr))
3058 break;
3059 #endif
3060 else
3061 UNDEF_Test;
3062 break;
3064 case 0x33: /* TEQP immed */
3065 if (DESTReg == 15)
3067 /* TEQP immed. */
3068 #ifdef MODE32
3069 state->Cpsr = GETSPSR (state->Bank);
3070 ARMul_CPSRAltered (state);
3071 #else
3072 temp = LHS ^ DPImmRHS;
3073 SETR15PSR (temp);
3074 #endif
3076 else
3078 DPSImmRHS; /* TEQ immed */
3079 dest = LHS ^ rhs;
3080 ARMul_NegZero (state, dest);
3082 break;
3084 case 0x34: /* MOVT immed */
3085 #ifdef MODE32
3086 if (state->is_v6
3087 && handle_v6_insn (state, instr))
3088 break;
3089 #endif
3090 DEST &= 0xFFFF;
3091 dest = BITS (0, 11);
3092 dest |= (BITS (16, 19) << 12);
3093 DEST |= (dest << 16);
3094 break;
3096 case 0x35: /* CMPP immed */
3097 if (DESTReg == 15)
3099 /* CMPP immed. */
3100 #ifdef MODE32
3101 state->Cpsr = GETSPSR (state->Bank);
3102 ARMul_CPSRAltered (state);
3103 #else
3104 temp = LHS - DPImmRHS;
3105 SETR15PSR (temp);
3106 #endif
3107 break;
3109 else
3111 /* CMP immed. */
3112 lhs = LHS;
3113 rhs = DPImmRHS;
3114 dest = lhs - rhs;
3115 ARMul_NegZero (state, dest);
3117 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
3119 ARMul_SubCarry (state, lhs, rhs, dest);
3120 ARMul_SubOverflow (state, lhs, rhs, dest);
3122 else
3124 CLEARC;
3125 CLEARV;
3128 break;
3130 case 0x36: /* CMN immed and MSR immed to SPSR */
3131 if (DESTReg == 15)
3132 ARMul_FixSPSR (state, instr, DPImmRHS);
3133 #ifdef MODE32
3134 else if (state->is_v6
3135 && handle_v6_insn (state, instr))
3136 break;
3137 #endif
3138 else
3139 UNDEF_Test;
3140 break;
3142 case 0x37: /* CMNP immed. */
3143 if (DESTReg == 15)
3145 /* CMNP immed. */
3146 #ifdef MODE32
3147 state->Cpsr = GETSPSR (state->Bank);
3148 ARMul_CPSRAltered (state);
3149 #else
3150 temp = LHS + DPImmRHS;
3151 SETR15PSR (temp);
3152 #endif
3153 break;
3155 else
3157 /* CMN immed. */
3158 lhs = LHS;
3159 rhs = DPImmRHS;
3160 dest = lhs + rhs;
3161 ASSIGNZ (dest == 0);
3162 if ((lhs | rhs) >> 30)
3164 /* Possible C,V,N to set. */
3165 ASSIGNN (NEG (dest));
3166 ARMul_AddCarry (state, lhs, rhs, dest);
3167 ARMul_AddOverflow (state, lhs, rhs, dest);
3169 else
3171 CLEARN;
3172 CLEARC;
3173 CLEARV;
3176 break;
3178 case 0x38: /* ORR immed. */
3179 dest = LHS | DPImmRHS;
3180 WRITEDEST (dest);
3181 break;
3183 case 0x39: /* ORRS immed. */
3184 DPSImmRHS;
3185 dest = LHS | rhs;
3186 WRITESDEST (dest);
3187 break;
3189 case 0x3a: /* MOV immed. */
3190 dest = DPImmRHS;
3191 WRITEDEST (dest);
3192 break;
3194 case 0x3b: /* MOVS immed. */
3195 DPSImmRHS;
3196 WRITESDEST (rhs);
3197 break;
3199 case 0x3c: /* BIC immed. */
3200 dest = LHS & ~DPImmRHS;
3201 WRITEDEST (dest);
3202 break;
3204 case 0x3d: /* BICS immed. */
3205 DPSImmRHS;
3206 dest = LHS & ~rhs;
3207 WRITESDEST (dest);
3208 break;
3210 case 0x3e: /* MVN immed. */
3211 dest = ~DPImmRHS;
3212 WRITEDEST (dest);
3213 break;
3215 case 0x3f: /* MVNS immed. */
3216 DPSImmRHS;
3217 WRITESDEST (~rhs);
3218 break;
3221 /* Single Data Transfer Immediate RHS Instructions. */
3223 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
3224 lhs = LHS;
3225 if (StoreWord (state, instr, lhs))
3226 LSBase = lhs - LSImmRHS;
3227 break;
3229 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
3230 lhs = LHS;
3231 if (LoadWord (state, instr, lhs))
3232 LSBase = lhs - LSImmRHS;
3233 break;
3235 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
3236 UNDEF_LSRBaseEQDestWb;
3237 UNDEF_LSRPCBaseWb;
3238 lhs = LHS;
3239 temp = lhs - LSImmRHS;
3240 state->NtransSig = LOW;
3241 if (StoreWord (state, instr, lhs))
3242 LSBase = temp;
3243 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3244 break;
3246 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
3247 UNDEF_LSRBaseEQDestWb;
3248 UNDEF_LSRPCBaseWb;
3249 lhs = LHS;
3250 state->NtransSig = LOW;
3251 if (LoadWord (state, instr, lhs))
3252 LSBase = lhs - LSImmRHS;
3253 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3254 break;
3256 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
3257 lhs = LHS;
3258 if (StoreByte (state, instr, lhs))
3259 LSBase = lhs - LSImmRHS;
3260 break;
3262 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
3263 lhs = LHS;
3264 if (LoadByte (state, instr, lhs, LUNSIGNED))
3265 LSBase = lhs - LSImmRHS;
3266 break;
3268 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
3269 UNDEF_LSRBaseEQDestWb;
3270 UNDEF_LSRPCBaseWb;
3271 lhs = LHS;
3272 state->NtransSig = LOW;
3273 if (StoreByte (state, instr, lhs))
3274 LSBase = lhs - LSImmRHS;
3275 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3276 break;
3278 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
3279 UNDEF_LSRBaseEQDestWb;
3280 UNDEF_LSRPCBaseWb;
3281 lhs = LHS;
3282 state->NtransSig = LOW;
3283 if (LoadByte (state, instr, lhs, LUNSIGNED))
3284 LSBase = lhs - LSImmRHS;
3285 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3286 break;
3288 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
3289 lhs = LHS;
3290 if (StoreWord (state, instr, lhs))
3291 LSBase = lhs + LSImmRHS;
3292 break;
3294 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
3295 lhs = LHS;
3296 if (LoadWord (state, instr, lhs))
3297 LSBase = lhs + LSImmRHS;
3298 break;
3300 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
3301 UNDEF_LSRBaseEQDestWb;
3302 UNDEF_LSRPCBaseWb;
3303 lhs = LHS;
3304 state->NtransSig = LOW;
3305 if (StoreWord (state, instr, lhs))
3306 LSBase = lhs + LSImmRHS;
3307 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3308 break;
3310 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
3311 UNDEF_LSRBaseEQDestWb;
3312 UNDEF_LSRPCBaseWb;
3313 lhs = LHS;
3314 state->NtransSig = LOW;
3315 if (LoadWord (state, instr, lhs))
3316 LSBase = lhs + LSImmRHS;
3317 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3318 break;
3320 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
3321 lhs = LHS;
3322 if (StoreByte (state, instr, lhs))
3323 LSBase = lhs + LSImmRHS;
3324 break;
3326 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
3327 lhs = LHS;
3328 if (LoadByte (state, instr, lhs, LUNSIGNED))
3329 LSBase = lhs + LSImmRHS;
3330 break;
3332 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
3333 UNDEF_LSRBaseEQDestWb;
3334 UNDEF_LSRPCBaseWb;
3335 lhs = LHS;
3336 state->NtransSig = LOW;
3337 if (StoreByte (state, instr, lhs))
3338 LSBase = lhs + LSImmRHS;
3339 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3340 break;
3342 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
3343 UNDEF_LSRBaseEQDestWb;
3344 UNDEF_LSRPCBaseWb;
3345 lhs = LHS;
3346 state->NtransSig = LOW;
3347 if (LoadByte (state, instr, lhs, LUNSIGNED))
3348 LSBase = lhs + LSImmRHS;
3349 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3350 break;
3353 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
3354 (void) StoreWord (state, instr, LHS - LSImmRHS);
3355 break;
3357 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
3358 (void) LoadWord (state, instr, LHS - LSImmRHS);
3359 break;
3361 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
3362 UNDEF_LSRBaseEQDestWb;
3363 UNDEF_LSRPCBaseWb;
3364 temp = LHS - LSImmRHS;
3365 if (StoreWord (state, instr, temp))
3366 LSBase = temp;
3367 break;
3369 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
3370 UNDEF_LSRBaseEQDestWb;
3371 UNDEF_LSRPCBaseWb;
3372 temp = LHS - LSImmRHS;
3373 if (LoadWord (state, instr, temp))
3374 LSBase = temp;
3375 break;
3377 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
3378 (void) StoreByte (state, instr, LHS - LSImmRHS);
3379 break;
3381 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
3382 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
3383 break;
3385 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
3386 UNDEF_LSRBaseEQDestWb;
3387 UNDEF_LSRPCBaseWb;
3388 temp = LHS - LSImmRHS;
3389 if (StoreByte (state, instr, temp))
3390 LSBase = temp;
3391 break;
3393 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
3394 UNDEF_LSRBaseEQDestWb;
3395 UNDEF_LSRPCBaseWb;
3396 temp = LHS - LSImmRHS;
3397 if (LoadByte (state, instr, temp, LUNSIGNED))
3398 LSBase = temp;
3399 break;
3401 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
3402 (void) StoreWord (state, instr, LHS + LSImmRHS);
3403 break;
3405 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
3406 (void) LoadWord (state, instr, LHS + LSImmRHS);
3407 break;
3409 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
3410 UNDEF_LSRBaseEQDestWb;
3411 UNDEF_LSRPCBaseWb;
3412 temp = LHS + LSImmRHS;
3413 if (StoreWord (state, instr, temp))
3414 LSBase = temp;
3415 break;
3417 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
3418 UNDEF_LSRBaseEQDestWb;
3419 UNDEF_LSRPCBaseWb;
3420 temp = LHS + LSImmRHS;
3421 if (LoadWord (state, instr, temp))
3422 LSBase = temp;
3423 break;
3425 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
3426 (void) StoreByte (state, instr, LHS + LSImmRHS);
3427 break;
3429 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
3430 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
3431 break;
3433 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
3434 UNDEF_LSRBaseEQDestWb;
3435 UNDEF_LSRPCBaseWb;
3436 temp = LHS + LSImmRHS;
3437 if (StoreByte (state, instr, temp))
3438 LSBase = temp;
3439 break;
3441 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
3442 UNDEF_LSRBaseEQDestWb;
3443 UNDEF_LSRPCBaseWb;
3444 temp = LHS + LSImmRHS;
3445 if (LoadByte (state, instr, temp, LUNSIGNED))
3446 LSBase = temp;
3447 break;
3450 /* Single Data Transfer Register RHS Instructions. */
3452 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
3453 if (BIT (4))
3455 #ifdef MODE32
3456 if (state->is_v6
3457 && handle_v6_insn (state, instr))
3458 break;
3459 #endif
3460 ARMul_UndefInstr (state, instr);
3461 break;
3463 UNDEF_LSRBaseEQOffWb;
3464 UNDEF_LSRBaseEQDestWb;
3465 UNDEF_LSRPCBaseWb;
3466 UNDEF_LSRPCOffWb;
3467 lhs = LHS;
3468 if (StoreWord (state, instr, lhs))
3469 LSBase = lhs - LSRegRHS;
3470 break;
3472 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
3473 if (BIT (4))
3475 #ifdef MODE32
3476 if (state->is_v6
3477 && handle_v6_insn (state, instr))
3478 break;
3479 #endif
3480 ARMul_UndefInstr (state, instr);
3481 break;
3483 UNDEF_LSRBaseEQOffWb;
3484 UNDEF_LSRBaseEQDestWb;
3485 UNDEF_LSRPCBaseWb;
3486 UNDEF_LSRPCOffWb;
3487 lhs = LHS;
3488 temp = lhs - LSRegRHS;
3489 if (LoadWord (state, instr, lhs))
3490 LSBase = temp;
3491 break;
3493 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
3494 if (BIT (4))
3496 #ifdef MODE32
3497 if (state->is_v6
3498 && handle_v6_insn (state, instr))
3499 break;
3500 #endif
3501 ARMul_UndefInstr (state, instr);
3502 break;
3504 UNDEF_LSRBaseEQOffWb;
3505 UNDEF_LSRBaseEQDestWb;
3506 UNDEF_LSRPCBaseWb;
3507 UNDEF_LSRPCOffWb;
3508 lhs = LHS;
3509 state->NtransSig = LOW;
3510 if (StoreWord (state, instr, lhs))
3511 LSBase = lhs - LSRegRHS;
3512 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3513 break;
3515 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
3516 if (BIT (4))
3518 #ifdef MODE32
3519 if (state->is_v6
3520 && handle_v6_insn (state, instr))
3521 break;
3522 #endif
3523 ARMul_UndefInstr (state, instr);
3524 break;
3526 UNDEF_LSRBaseEQOffWb;
3527 UNDEF_LSRBaseEQDestWb;
3528 UNDEF_LSRPCBaseWb;
3529 UNDEF_LSRPCOffWb;
3530 lhs = LHS;
3531 temp = lhs - LSRegRHS;
3532 state->NtransSig = LOW;
3533 if (LoadWord (state, instr, lhs))
3534 LSBase = temp;
3535 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3536 break;
3538 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
3539 if (BIT (4))
3541 #ifdef MODE32
3542 if (state->is_v6
3543 && handle_v6_insn (state, instr))
3544 break;
3545 #endif
3546 ARMul_UndefInstr (state, instr);
3547 break;
3549 UNDEF_LSRBaseEQOffWb;
3550 UNDEF_LSRBaseEQDestWb;
3551 UNDEF_LSRPCBaseWb;
3552 UNDEF_LSRPCOffWb;
3553 lhs = LHS;
3554 if (StoreByte (state, instr, lhs))
3555 LSBase = lhs - LSRegRHS;
3556 break;
3558 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
3559 if (BIT (4))
3561 #ifdef MODE32
3562 if (state->is_v6
3563 && handle_v6_insn (state, instr))
3564 break;
3565 #endif
3566 ARMul_UndefInstr (state, instr);
3567 break;
3569 UNDEF_LSRBaseEQOffWb;
3570 UNDEF_LSRBaseEQDestWb;
3571 UNDEF_LSRPCBaseWb;
3572 UNDEF_LSRPCOffWb;
3573 lhs = LHS;
3574 temp = lhs - LSRegRHS;
3575 if (LoadByte (state, instr, lhs, LUNSIGNED))
3576 LSBase = temp;
3577 break;
3579 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
3580 if (BIT (4))
3582 #ifdef MODE32
3583 if (state->is_v6
3584 && handle_v6_insn (state, instr))
3585 break;
3586 #endif
3587 ARMul_UndefInstr (state, instr);
3588 break;
3590 UNDEF_LSRBaseEQOffWb;
3591 UNDEF_LSRBaseEQDestWb;
3592 UNDEF_LSRPCBaseWb;
3593 UNDEF_LSRPCOffWb;
3594 lhs = LHS;
3595 state->NtransSig = LOW;
3596 if (StoreByte (state, instr, lhs))
3597 LSBase = lhs - LSRegRHS;
3598 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3599 break;
3601 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
3602 if (BIT (4))
3604 #ifdef MODE32
3605 if (state->is_v6
3606 && handle_v6_insn (state, instr))
3607 break;
3608 #endif
3609 ARMul_UndefInstr (state, instr);
3610 break;
3612 UNDEF_LSRBaseEQOffWb;
3613 UNDEF_LSRBaseEQDestWb;
3614 UNDEF_LSRPCBaseWb;
3615 UNDEF_LSRPCOffWb;
3616 lhs = LHS;
3617 temp = lhs - LSRegRHS;
3618 state->NtransSig = LOW;
3619 if (LoadByte (state, instr, lhs, LUNSIGNED))
3620 LSBase = temp;
3621 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3622 break;
3624 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
3625 if (BIT (4))
3627 #ifdef MODE32
3628 if (state->is_v6
3629 && handle_v6_insn (state, instr))
3630 break;
3631 #endif
3632 ARMul_UndefInstr (state, instr);
3633 break;
3635 UNDEF_LSRBaseEQOffWb;
3636 UNDEF_LSRBaseEQDestWb;
3637 UNDEF_LSRPCBaseWb;
3638 UNDEF_LSRPCOffWb;
3639 lhs = LHS;
3640 if (StoreWord (state, instr, lhs))
3641 LSBase = lhs + LSRegRHS;
3642 break;
3644 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
3645 if (BIT (4))
3647 #ifdef MODE32
3648 if (state->is_v6
3649 && handle_v6_insn (state, instr))
3650 break;
3651 #endif
3652 ARMul_UndefInstr (state, instr);
3653 break;
3655 UNDEF_LSRBaseEQOffWb;
3656 UNDEF_LSRBaseEQDestWb;
3657 UNDEF_LSRPCBaseWb;
3658 UNDEF_LSRPCOffWb;
3659 lhs = LHS;
3660 temp = lhs + LSRegRHS;
3661 if (LoadWord (state, instr, lhs))
3662 LSBase = temp;
3663 break;
3665 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
3666 if (BIT (4))
3668 #ifdef MODE32
3669 if (state->is_v6
3670 && handle_v6_insn (state, instr))
3671 break;
3672 #endif
3673 ARMul_UndefInstr (state, instr);
3674 break;
3676 UNDEF_LSRBaseEQOffWb;
3677 UNDEF_LSRBaseEQDestWb;
3678 UNDEF_LSRPCBaseWb;
3679 UNDEF_LSRPCOffWb;
3680 lhs = LHS;
3681 state->NtransSig = LOW;
3682 if (StoreWord (state, instr, lhs))
3683 LSBase = lhs + LSRegRHS;
3684 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3685 break;
3687 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
3688 if (BIT (4))
3690 #ifdef MODE32
3691 if (state->is_v6
3692 && handle_v6_insn (state, instr))
3693 break;
3694 #endif
3695 ARMul_UndefInstr (state, instr);
3696 break;
3698 UNDEF_LSRBaseEQOffWb;
3699 UNDEF_LSRBaseEQDestWb;
3700 UNDEF_LSRPCBaseWb;
3701 UNDEF_LSRPCOffWb;
3702 lhs = LHS;
3703 temp = lhs + LSRegRHS;
3704 state->NtransSig = LOW;
3705 if (LoadWord (state, instr, lhs))
3706 LSBase = temp;
3707 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3708 break;
3710 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
3711 if (BIT (4))
3713 #ifdef MODE32
3714 if (state->is_v6
3715 && handle_v6_insn (state, instr))
3716 break;
3717 #endif
3718 ARMul_UndefInstr (state, instr);
3719 break;
3721 UNDEF_LSRBaseEQOffWb;
3722 UNDEF_LSRBaseEQDestWb;
3723 UNDEF_LSRPCBaseWb;
3724 UNDEF_LSRPCOffWb;
3725 lhs = LHS;
3726 if (StoreByte (state, instr, lhs))
3727 LSBase = lhs + LSRegRHS;
3728 break;
3730 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
3731 if (BIT (4))
3733 #ifdef MODE32
3734 if (state->is_v6
3735 && handle_v6_insn (state, instr))
3736 break;
3737 #endif
3738 ARMul_UndefInstr (state, instr);
3739 break;
3741 UNDEF_LSRBaseEQOffWb;
3742 UNDEF_LSRBaseEQDestWb;
3743 UNDEF_LSRPCBaseWb;
3744 UNDEF_LSRPCOffWb;
3745 lhs = LHS;
3746 temp = lhs + LSRegRHS;
3747 if (LoadByte (state, instr, lhs, LUNSIGNED))
3748 LSBase = temp;
3749 break;
3751 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3752 if (BIT (4))
3754 #ifdef MODE32
3755 if (state->is_v6
3756 && handle_v6_insn (state, instr))
3757 break;
3758 #endif
3759 ARMul_UndefInstr (state, instr);
3760 break;
3762 UNDEF_LSRBaseEQOffWb;
3763 UNDEF_LSRBaseEQDestWb;
3764 UNDEF_LSRPCBaseWb;
3765 UNDEF_LSRPCOffWb;
3766 lhs = LHS;
3767 state->NtransSig = LOW;
3768 if (StoreByte (state, instr, lhs))
3769 LSBase = lhs + LSRegRHS;
3770 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3771 break;
3773 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3774 if (BIT (4))
3776 #ifdef MODE32
3777 if (state->is_v6
3778 && handle_v6_insn (state, instr))
3779 break;
3780 #endif
3781 ARMul_UndefInstr (state, instr);
3782 break;
3784 UNDEF_LSRBaseEQOffWb;
3785 UNDEF_LSRBaseEQDestWb;
3786 UNDEF_LSRPCBaseWb;
3787 UNDEF_LSRPCOffWb;
3788 lhs = LHS;
3789 temp = lhs + LSRegRHS;
3790 state->NtransSig = LOW;
3791 if (LoadByte (state, instr, lhs, LUNSIGNED))
3792 LSBase = temp;
3793 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3794 break;
3797 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3798 if (BIT (4))
3800 #ifdef MODE32
3801 if (state->is_v6
3802 && handle_v6_insn (state, instr))
3803 break;
3804 #endif
3805 ARMul_UndefInstr (state, instr);
3806 break;
3808 (void) StoreWord (state, instr, LHS - LSRegRHS);
3809 break;
3811 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3812 if (BIT (4))
3814 #ifdef MODE32
3815 if (state->is_v6
3816 && handle_v6_insn (state, instr))
3817 break;
3818 #endif
3819 ARMul_UndefInstr (state, instr);
3820 break;
3822 (void) LoadWord (state, instr, LHS - LSRegRHS);
3823 break;
3825 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3826 if (BIT (4))
3828 #ifdef MODE32
3829 if (state->is_v6
3830 && handle_v6_insn (state, instr))
3831 break;
3832 #endif
3833 ARMul_UndefInstr (state, instr);
3834 break;
3836 UNDEF_LSRBaseEQOffWb;
3837 UNDEF_LSRBaseEQDestWb;
3838 UNDEF_LSRPCBaseWb;
3839 UNDEF_LSRPCOffWb;
3840 temp = LHS - LSRegRHS;
3841 if (StoreWord (state, instr, temp))
3842 LSBase = temp;
3843 break;
3845 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3846 if (BIT (4))
3848 #ifdef MODE32
3849 if (state->is_v6
3850 && handle_v6_insn (state, instr))
3851 break;
3852 #endif
3853 ARMul_UndefInstr (state, instr);
3854 break;
3856 UNDEF_LSRBaseEQOffWb;
3857 UNDEF_LSRBaseEQDestWb;
3858 UNDEF_LSRPCBaseWb;
3859 UNDEF_LSRPCOffWb;
3860 temp = LHS - LSRegRHS;
3861 if (LoadWord (state, instr, temp))
3862 LSBase = temp;
3863 break;
3865 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3866 if (BIT (4))
3868 #ifdef MODE32
3869 if (state->is_v6
3870 && handle_v6_insn (state, instr))
3871 break;
3872 #endif
3873 ARMul_UndefInstr (state, instr);
3874 break;
3876 (void) StoreByte (state, instr, LHS - LSRegRHS);
3877 break;
3879 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3880 if (BIT (4))
3882 #ifdef MODE32
3883 if (state->is_v6
3884 && handle_v6_insn (state, instr))
3885 break;
3886 #endif
3887 ARMul_UndefInstr (state, instr);
3888 break;
3890 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
3891 break;
3893 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3894 if (BIT (4))
3896 #ifdef MODE32
3897 if (state->is_v6
3898 && handle_v6_insn (state, instr))
3899 break;
3900 #endif
3901 ARMul_UndefInstr (state, instr);
3902 break;
3904 UNDEF_LSRBaseEQOffWb;
3905 UNDEF_LSRBaseEQDestWb;
3906 UNDEF_LSRPCBaseWb;
3907 UNDEF_LSRPCOffWb;
3908 temp = LHS - LSRegRHS;
3909 if (StoreByte (state, instr, temp))
3910 LSBase = temp;
3911 break;
3913 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3914 if (BIT (4))
3916 #ifdef MODE32
3917 if (state->is_v6
3918 && handle_v6_insn (state, instr))
3919 break;
3920 #endif
3921 ARMul_UndefInstr (state, instr);
3922 break;
3924 UNDEF_LSRBaseEQOffWb;
3925 UNDEF_LSRBaseEQDestWb;
3926 UNDEF_LSRPCBaseWb;
3927 UNDEF_LSRPCOffWb;
3928 temp = LHS - LSRegRHS;
3929 if (LoadByte (state, instr, temp, LUNSIGNED))
3930 LSBase = temp;
3931 break;
3933 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3934 if (BIT (4))
3936 #ifdef MODE32
3937 if (state->is_v6
3938 && handle_v6_insn (state, instr))
3939 break;
3940 #endif
3941 ARMul_UndefInstr (state, instr);
3942 break;
3944 (void) StoreWord (state, instr, LHS + LSRegRHS);
3945 break;
3947 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
3948 if (BIT (4))
3950 #ifdef MODE32
3951 if (state->is_v6
3952 && handle_v6_insn (state, instr))
3953 break;
3954 #endif
3955 ARMul_UndefInstr (state, instr);
3956 break;
3958 (void) LoadWord (state, instr, LHS + LSRegRHS);
3959 break;
3961 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
3962 if (BIT (4))
3964 #ifdef MODE32
3965 if (state->is_v6
3966 && handle_v6_insn (state, instr))
3967 break;
3968 #endif
3969 ARMul_UndefInstr (state, instr);
3970 break;
3972 UNDEF_LSRBaseEQOffWb;
3973 UNDEF_LSRBaseEQDestWb;
3974 UNDEF_LSRPCBaseWb;
3975 UNDEF_LSRPCOffWb;
3976 temp = LHS + LSRegRHS;
3977 if (StoreWord (state, instr, temp))
3978 LSBase = temp;
3979 break;
3981 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
3982 if (BIT (4))
3984 #ifdef MODE32
3985 if (state->is_v6
3986 && handle_v6_insn (state, instr))
3987 break;
3988 #endif
3989 ARMul_UndefInstr (state, instr);
3990 break;
3992 UNDEF_LSRBaseEQOffWb;
3993 UNDEF_LSRBaseEQDestWb;
3994 UNDEF_LSRPCBaseWb;
3995 UNDEF_LSRPCOffWb;
3996 temp = LHS + LSRegRHS;
3997 if (LoadWord (state, instr, temp))
3998 LSBase = temp;
3999 break;
4001 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
4002 if (BIT (4))
4004 #ifdef MODE32
4005 if (state->is_v6
4006 && handle_v6_insn (state, instr))
4007 break;
4008 #endif
4009 ARMul_UndefInstr (state, instr);
4010 break;
4012 (void) StoreByte (state, instr, LHS + LSRegRHS);
4013 break;
4015 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
4016 if (BIT (4))
4018 #ifdef MODE32
4019 if (state->is_v6
4020 && handle_v6_insn (state, instr))
4021 break;
4022 #endif
4023 ARMul_UndefInstr (state, instr);
4024 break;
4026 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
4027 break;
4029 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
4030 if (BIT (4))
4032 #ifdef MODE32
4033 if (state->is_v6
4034 && handle_v6_insn (state, instr))
4035 break;
4036 #endif
4037 ARMul_UndefInstr (state, instr);
4038 break;
4040 UNDEF_LSRBaseEQOffWb;
4041 UNDEF_LSRBaseEQDestWb;
4042 UNDEF_LSRPCBaseWb;
4043 UNDEF_LSRPCOffWb;
4044 temp = LHS + LSRegRHS;
4045 if (StoreByte (state, instr, temp))
4046 LSBase = temp;
4047 break;
4049 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
4050 if (BIT (4))
4052 /* Check for the special breakpoint opcode.
4053 This value should correspond to the value defined
4054 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
4055 if (BITS (0, 19) == 0xfdefe)
4057 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
4058 ARMul_Abort (state, ARMul_SWIV);
4060 #ifdef MODE32
4061 else if (state->is_v6
4062 && handle_v6_insn (state, instr))
4063 break;
4064 #endif
4065 else
4066 ARMul_UndefInstr (state, instr);
4067 break;
4069 UNDEF_LSRBaseEQOffWb;
4070 UNDEF_LSRBaseEQDestWb;
4071 UNDEF_LSRPCBaseWb;
4072 UNDEF_LSRPCOffWb;
4073 temp = LHS + LSRegRHS;
4074 if (LoadByte (state, instr, temp, LUNSIGNED))
4075 LSBase = temp;
4076 break;
4079 /* Multiple Data Transfer Instructions. */
4081 case 0x80: /* Store, No WriteBack, Post Dec. */
4082 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
4083 break;
4085 case 0x81: /* Load, No WriteBack, Post Dec. */
4086 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
4087 break;
4089 case 0x82: /* Store, WriteBack, Post Dec. */
4090 temp = LSBase - LSMNumRegs;
4091 STOREMULT (instr, temp + 4L, temp);
4092 break;
4094 case 0x83: /* Load, WriteBack, Post Dec. */
4095 temp = LSBase - LSMNumRegs;
4096 LOADMULT (instr, temp + 4L, temp);
4097 break;
4099 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
4100 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
4101 break;
4103 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
4104 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
4105 break;
4107 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
4108 temp = LSBase - LSMNumRegs;
4109 STORESMULT (instr, temp + 4L, temp);
4110 break;
4112 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
4113 temp = LSBase - LSMNumRegs;
4114 LOADSMULT (instr, temp + 4L, temp);
4115 break;
4117 case 0x88: /* Store, No WriteBack, Post Inc. */
4118 STOREMULT (instr, LSBase, 0L);
4119 break;
4121 case 0x89: /* Load, No WriteBack, Post Inc. */
4122 LOADMULT (instr, LSBase, 0L);
4123 break;
4125 case 0x8a: /* Store, WriteBack, Post Inc. */
4126 temp = LSBase;
4127 STOREMULT (instr, temp, temp + LSMNumRegs);
4128 break;
4130 case 0x8b: /* Load, WriteBack, Post Inc. */
4131 temp = LSBase;
4132 LOADMULT (instr, temp, temp + LSMNumRegs);
4133 break;
4135 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
4136 STORESMULT (instr, LSBase, 0L);
4137 break;
4139 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
4140 LOADSMULT (instr, LSBase, 0L);
4141 break;
4143 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
4144 temp = LSBase;
4145 STORESMULT (instr, temp, temp + LSMNumRegs);
4146 break;
4148 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
4149 temp = LSBase;
4150 LOADSMULT (instr, temp, temp + LSMNumRegs);
4151 break;
4153 case 0x90: /* Store, No WriteBack, Pre Dec. */
4154 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
4155 break;
4157 case 0x91: /* Load, No WriteBack, Pre Dec. */
4158 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
4159 break;
4161 case 0x92: /* Store, WriteBack, Pre Dec. */
4162 temp = LSBase - LSMNumRegs;
4163 STOREMULT (instr, temp, temp);
4164 break;
4166 case 0x93: /* Load, WriteBack, Pre Dec. */
4167 temp = LSBase - LSMNumRegs;
4168 LOADMULT (instr, temp, temp);
4169 break;
4171 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
4172 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
4173 break;
4175 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
4176 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
4177 break;
4179 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
4180 temp = LSBase - LSMNumRegs;
4181 STORESMULT (instr, temp, temp);
4182 break;
4184 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
4185 temp = LSBase - LSMNumRegs;
4186 LOADSMULT (instr, temp, temp);
4187 break;
4189 case 0x98: /* Store, No WriteBack, Pre Inc. */
4190 STOREMULT (instr, LSBase + 4L, 0L);
4191 break;
4193 case 0x99: /* Load, No WriteBack, Pre Inc. */
4194 LOADMULT (instr, LSBase + 4L, 0L);
4195 break;
4197 case 0x9a: /* Store, WriteBack, Pre Inc. */
4198 temp = LSBase;
4199 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
4200 break;
4202 case 0x9b: /* Load, WriteBack, Pre Inc. */
4203 temp = LSBase;
4204 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
4205 break;
4207 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
4208 STORESMULT (instr, LSBase + 4L, 0L);
4209 break;
4211 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
4212 LOADSMULT (instr, LSBase + 4L, 0L);
4213 break;
4215 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
4216 temp = LSBase;
4217 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
4218 break;
4220 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
4221 temp = LSBase;
4222 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
4223 break;
4226 /* Branch forward. */
4227 case 0xa0:
4228 case 0xa1:
4229 case 0xa2:
4230 case 0xa3:
4231 case 0xa4:
4232 case 0xa5:
4233 case 0xa6:
4234 case 0xa7:
4235 state->Reg[15] = pc + 8 + POSBRANCH;
4236 FLUSHPIPE;
4237 break;
4240 /* Branch backward. */
4241 case 0xa8:
4242 case 0xa9:
4243 case 0xaa:
4244 case 0xab:
4245 case 0xac:
4246 case 0xad:
4247 case 0xae:
4248 case 0xaf:
4249 state->Reg[15] = pc + 8 + NEGBRANCH;
4250 FLUSHPIPE;
4251 break;
4253 /* Branch and Link forward. */
4254 case 0xb0:
4255 case 0xb1:
4256 case 0xb2:
4257 case 0xb3:
4258 case 0xb4:
4259 case 0xb5:
4260 case 0xb6:
4261 case 0xb7:
4262 /* Put PC into Link. */
4263 #ifdef MODE32
4264 state->Reg[14] = pc + 4;
4265 #else
4266 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
4267 #endif
4268 state->Reg[15] = pc + 8 + POSBRANCH;
4269 FLUSHPIPE;
4270 if (trace_funcs)
4271 fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
4272 break;
4274 /* Branch and Link backward. */
4275 case 0xb8:
4276 case 0xb9:
4277 case 0xba:
4278 case 0xbb:
4279 case 0xbc:
4280 case 0xbd:
4281 case 0xbe:
4282 case 0xbf:
4283 /* Put PC into Link. */
4284 #ifdef MODE32
4285 state->Reg[14] = pc + 4;
4286 #else
4287 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
4288 #endif
4289 state->Reg[15] = pc + 8 + NEGBRANCH;
4290 FLUSHPIPE;
4291 if (trace_funcs)
4292 fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
4293 break;
4295 /* Co-Processor Data Transfers. */
4296 case 0xc4:
4297 if (state->is_v5)
4299 if (CPNum == 10 || CPNum == 11)
4300 handle_VFP_move (state, instr);
4301 /* Reading from R15 is UNPREDICTABLE. */
4302 else if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
4303 ARMul_UndefInstr (state, instr);
4304 /* Is access to coprocessor 0 allowed ? */
4305 else if (! CP_ACCESS_ALLOWED (state, CPNum))
4306 ARMul_UndefInstr (state, instr);
4307 /* Special treatment for XScale coprocessors. */
4308 else if (state->is_XScale)
4310 /* Only opcode 0 is supported. */
4311 if (BITS (4, 7) != 0x00)
4312 ARMul_UndefInstr (state, instr);
4313 /* Only coporcessor 0 is supported. */
4314 else if (CPNum != 0x00)
4315 ARMul_UndefInstr (state, instr);
4316 /* Only accumulator 0 is supported. */
4317 else if (BITS (0, 3) != 0x00)
4318 ARMul_UndefInstr (state, instr);
4319 else
4321 /* XScale MAR insn. Move two registers into accumulator. */
4322 state->Accumulator = state->Reg[BITS (12, 15)];
4323 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
4326 else
4327 /* FIXME: Not sure what to do for other v5 processors. */
4328 ARMul_UndefInstr (state, instr);
4329 break;
4331 /* Drop through. */
4333 case 0xc0: /* Store , No WriteBack , Post Dec. */
4334 ARMul_STC (state, instr, LHS);
4335 break;
4337 case 0xc5:
4338 if (state->is_v5)
4340 if (CPNum == 10 || CPNum == 11)
4341 handle_VFP_move (state, instr);
4342 /* Writes to R15 are UNPREDICATABLE. */
4343 else if (DESTReg == 15 || LHSReg == 15)
4344 ARMul_UndefInstr (state, instr);
4345 /* Is access to the coprocessor allowed ? */
4346 else if (! CP_ACCESS_ALLOWED (state, CPNum))
4347 ARMul_UndefInstr (state, instr);
4348 /* Special handling for XScale coprcoessors. */
4349 else if (state->is_XScale)
4351 /* Only opcode 0 is supported. */
4352 if (BITS (4, 7) != 0x00)
4353 ARMul_UndefInstr (state, instr);
4354 /* Only coprocessor 0 is supported. */
4355 else if (CPNum != 0x00)
4356 ARMul_UndefInstr (state, instr);
4357 /* Only accumulator 0 is supported. */
4358 else if (BITS (0, 3) != 0x00)
4359 ARMul_UndefInstr (state, instr);
4360 else
4362 /* XScale MRA insn. Move accumulator into two registers. */
4363 ARMword t1 = (state->Accumulator >> 32) & 255;
4365 if (t1 & 128)
4366 t1 -= 256;
4368 state->Reg[BITS (12, 15)] = state->Accumulator;
4369 state->Reg[BITS (16, 19)] = t1;
4370 break;
4373 else
4374 /* FIXME: Not sure what to do for other v5 processors. */
4375 ARMul_UndefInstr (state, instr);
4376 break;
4378 /* Drop through. */
4380 case 0xc1: /* Load , No WriteBack , Post Dec. */
4381 ARMul_LDC (state, instr, LHS);
4382 break;
4384 case 0xc2:
4385 case 0xc6: /* Store , WriteBack , Post Dec. */
4386 lhs = LHS;
4387 state->Base = lhs - LSCOff;
4388 ARMul_STC (state, instr, lhs);
4389 break;
4391 case 0xc3:
4392 case 0xc7: /* Load , WriteBack , Post Dec. */
4393 lhs = LHS;
4394 state->Base = lhs - LSCOff;
4395 ARMul_LDC (state, instr, lhs);
4396 break;
4398 case 0xc8:
4399 case 0xcc: /* Store , No WriteBack , Post Inc. */
4400 ARMul_STC (state, instr, LHS);
4401 break;
4403 case 0xc9:
4404 case 0xcd: /* Load , No WriteBack , Post Inc. */
4405 ARMul_LDC (state, instr, LHS);
4406 break;
4408 case 0xca:
4409 case 0xce: /* Store , WriteBack , Post Inc. */
4410 lhs = LHS;
4411 state->Base = lhs + LSCOff;
4412 ARMul_STC (state, instr, LHS);
4413 break;
4415 case 0xcb:
4416 case 0xcf: /* Load , WriteBack , Post Inc. */
4417 lhs = LHS;
4418 state->Base = lhs + LSCOff;
4419 ARMul_LDC (state, instr, LHS);
4420 break;
4422 case 0xd0:
4423 case 0xd4: /* Store , No WriteBack , Pre Dec. */
4424 ARMul_STC (state, instr, LHS - LSCOff);
4425 break;
4427 case 0xd1:
4428 case 0xd5: /* Load , No WriteBack , Pre Dec. */
4429 ARMul_LDC (state, instr, LHS - LSCOff);
4430 break;
4432 case 0xd2:
4433 case 0xd6: /* Store , WriteBack , Pre Dec. */
4434 lhs = LHS - LSCOff;
4435 state->Base = lhs;
4436 ARMul_STC (state, instr, lhs);
4437 break;
4439 case 0xd3:
4440 case 0xd7: /* Load , WriteBack , Pre Dec. */
4441 lhs = LHS - LSCOff;
4442 state->Base = lhs;
4443 ARMul_LDC (state, instr, lhs);
4444 break;
4446 case 0xd8:
4447 case 0xdc: /* Store , No WriteBack , Pre Inc. */
4448 ARMul_STC (state, instr, LHS + LSCOff);
4449 break;
4451 case 0xd9:
4452 case 0xdd: /* Load , No WriteBack , Pre Inc. */
4453 ARMul_LDC (state, instr, LHS + LSCOff);
4454 break;
4456 case 0xda:
4457 case 0xde: /* Store , WriteBack , Pre Inc. */
4458 lhs = LHS + LSCOff;
4459 state->Base = lhs;
4460 ARMul_STC (state, instr, lhs);
4461 break;
4463 case 0xdb:
4464 case 0xdf: /* Load , WriteBack , Pre Inc. */
4465 lhs = LHS + LSCOff;
4466 state->Base = lhs;
4467 ARMul_LDC (state, instr, lhs);
4468 break;
4471 /* Co-Processor Register Transfers (MCR) and Data Ops. */
4473 case 0xe2:
4474 if (! CP_ACCESS_ALLOWED (state, CPNum))
4476 ARMul_UndefInstr (state, instr);
4477 break;
4479 if (state->is_XScale)
4480 switch (BITS (18, 19))
4482 case 0x0:
4483 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4485 /* XScale MIA instruction. Signed multiplication of
4486 two 32 bit values and addition to 40 bit accumulator. */
4487 ARMsdword Rm = state->Reg[MULLHSReg];
4488 ARMsdword Rs = state->Reg[MULACCReg];
4490 if (Rm & (1 << 31))
4491 Rm -= 1ULL << 32;
4492 if (Rs & (1 << 31))
4493 Rs -= 1ULL << 32;
4494 state->Accumulator += Rm * Rs;
4495 goto donext;
4497 break;
4499 case 0x2:
4500 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4502 /* XScale MIAPH instruction. */
4503 ARMword t1 = state->Reg[MULLHSReg] >> 16;
4504 ARMword t2 = state->Reg[MULACCReg] >> 16;
4505 ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
4506 ARMword t4 = state->Reg[MULACCReg] & 0xffff;
4507 ARMsdword t5;
4509 if (t1 & (1 << 15))
4510 t1 -= 1 << 16;
4511 if (t2 & (1 << 15))
4512 t2 -= 1 << 16;
4513 if (t3 & (1 << 15))
4514 t3 -= 1 << 16;
4515 if (t4 & (1 << 15))
4516 t4 -= 1 << 16;
4517 t1 *= t2;
4518 t5 = t1;
4519 if (t5 & (1 << 31))
4520 t5 -= 1ULL << 32;
4521 state->Accumulator += t5;
4522 t3 *= t4;
4523 t5 = t3;
4524 if (t5 & (1 << 31))
4525 t5 -= 1ULL << 32;
4526 state->Accumulator += t5;
4527 goto donext;
4529 break;
4531 case 0x3:
4532 if (BITS (4, 11) == 1)
4534 /* XScale MIAxy instruction. */
4535 ARMword t1;
4536 ARMword t2;
4537 ARMsdword t5;
4539 if (BIT (17))
4540 t1 = state->Reg[MULLHSReg] >> 16;
4541 else
4542 t1 = state->Reg[MULLHSReg] & 0xffff;
4544 if (BIT (16))
4545 t2 = state->Reg[MULACCReg] >> 16;
4546 else
4547 t2 = state->Reg[MULACCReg] & 0xffff;
4549 if (t1 & (1 << 15))
4550 t1 -= 1 << 16;
4551 if (t2 & (1 << 15))
4552 t2 -= 1 << 16;
4553 t1 *= t2;
4554 t5 = t1;
4555 if (t5 & (1 << 31))
4556 t5 -= 1ULL << 32;
4557 state->Accumulator += t5;
4558 goto donext;
4560 break;
4562 default:
4563 break;
4565 /* Drop through. */
4567 case 0xe0:
4568 case 0xe4:
4569 case 0xe6:
4570 case 0xe8:
4571 case 0xea:
4572 case 0xec:
4573 case 0xee:
4574 if (BIT (4))
4576 if (CPNum == 10 || CPNum == 11)
4577 handle_VFP_move (state, instr);
4578 /* MCR. */
4579 else if (DESTReg == 15)
4581 UNDEF_MCRPC;
4582 #ifdef MODE32
4583 ARMul_MCR (state, instr, state->Reg[15] + isize);
4584 #else
4585 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
4586 ((state->Reg[15] + isize) & R15PCBITS));
4587 #endif
4589 else
4590 ARMul_MCR (state, instr, DEST);
4592 else
4593 /* CDP Part 1. */
4594 ARMul_CDP (state, instr);
4595 break;
4598 /* Co-Processor Register Transfers (MRC) and Data Ops. */
4599 case 0xe1:
4600 case 0xe3:
4601 case 0xe5:
4602 case 0xe7:
4603 case 0xe9:
4604 case 0xeb:
4605 case 0xed:
4606 case 0xef:
4607 if (BIT (4))
4609 if (CPNum == 10 || CPNum == 11)
4611 switch (BITS (20, 27))
4613 case 0xEF:
4614 if (BITS (16, 19) == 0x1
4615 && BITS (0, 11) == 0xA10)
4617 /* VMRS */
4618 if (DESTReg == 15)
4620 ARMul_SetCPSR (state, (state->FPSCR & 0xF0000000)
4621 | (ARMul_GetCPSR (state) & 0x0FFFFFFF));
4623 if (trace)
4624 fprintf (stderr, " VFP: VMRS: set flags to %c%c%c%c\n",
4625 ARMul_GetCPSR (state) & NBIT ? 'N' : '-',
4626 ARMul_GetCPSR (state) & ZBIT ? 'Z' : '-',
4627 ARMul_GetCPSR (state) & CBIT ? 'C' : '-',
4628 ARMul_GetCPSR (state) & VBIT ? 'V' : '-');
4630 else
4632 state->Reg[DESTReg] = state->FPSCR;
4634 if (trace)
4635 fprintf (stderr, " VFP: VMRS: r%d = %x\n", DESTReg, state->Reg[DESTReg]);
4638 else
4639 fprintf (stderr, "SIM: VFP: Unimplemented: Compare op\n");
4640 break;
4642 case 0xE0:
4643 case 0xE1:
4644 /* VMOV reg <-> single precision. */
4645 if (BITS (0,6) != 0x10 || BITS (8,11) != 0xA)
4646 fprintf (stderr, "SIM: VFP: Unimplemented: move op\n");
4647 else if (BIT (20))
4648 state->Reg[BITS (12, 15)] = VFP_uword (BITS (16, 19) << 1 | BIT (7));
4649 else
4650 VFP_uword (BITS (16, 19) << 1 | BIT (7)) = state->Reg[BITS (12, 15)];
4651 break;
4653 default:
4654 fprintf (stderr, "SIM: VFP: Unimplemented: CDP op\n");
4655 break;
4658 else
4660 /* MRC */
4661 temp = ARMul_MRC (state, instr);
4662 if (DESTReg == 15)
4664 ASSIGNN ((temp & NBIT) != 0);
4665 ASSIGNZ ((temp & ZBIT) != 0);
4666 ASSIGNC ((temp & CBIT) != 0);
4667 ASSIGNV ((temp & VBIT) != 0);
4669 else
4670 DEST = temp;
4673 else
4674 /* CDP Part 2. */
4675 ARMul_CDP (state, instr);
4676 break;
4679 /* SWI instruction. */
4680 case 0xf0:
4681 case 0xf1:
4682 case 0xf2:
4683 case 0xf3:
4684 case 0xf4:
4685 case 0xf5:
4686 case 0xf6:
4687 case 0xf7:
4688 case 0xf8:
4689 case 0xf9:
4690 case 0xfa:
4691 case 0xfb:
4692 case 0xfc:
4693 case 0xfd:
4694 case 0xfe:
4695 case 0xff:
4696 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
4698 /* A prefetch abort. */
4699 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
4700 ARMul_Abort (state, ARMul_PrefetchAbortV);
4701 break;
4704 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
4705 ARMul_Abort (state, ARMul_SWIV);
4707 break;
4711 #ifdef MODET
4712 donext:
4713 #endif
4715 if (state->Emulate == ONCE)
4716 state->Emulate = STOP;
4717 /* If we have changed mode, allow the PC to advance before stopping. */
4718 else if (state->Emulate == CHANGEMODE)
4719 continue;
4720 else if (state->Emulate != RUN)
4721 break;
4723 while (!stop_simulator);
4725 state->decoded = decoded;
4726 state->loaded = loaded;
4727 state->pc = pc;
4729 return pc;
4732 /* This routine evaluates most Data Processing register RHS's with the S
4733 bit clear. It is intended to be called from the macro DPRegRHS, which
4734 filters the common case of an unshifted register with in line code. */
4736 static ARMword
4737 GetDPRegRHS (ARMul_State * state, ARMword instr)
4739 ARMword shamt, base;
4741 base = RHSReg;
4742 if (BIT (4))
4744 /* Shift amount in a register. */
4745 UNDEF_Shift;
4746 INCPC;
4747 #ifndef MODE32
4748 if (base == 15)
4749 base = ECC | ER15INT | R15PC | EMODE;
4750 else
4751 #endif
4752 base = state->Reg[base];
4753 ARMul_Icycles (state, 1, 0L);
4754 shamt = state->Reg[BITS (8, 11)] & 0xff;
4755 switch ((int) BITS (5, 6))
4757 case LSL:
4758 if (shamt == 0)
4759 return (base);
4760 else if (shamt >= 32)
4761 return (0);
4762 else
4763 return (base << shamt);
4764 case LSR:
4765 if (shamt == 0)
4766 return (base);
4767 else if (shamt >= 32)
4768 return (0);
4769 else
4770 return (base >> shamt);
4771 case ASR:
4772 if (shamt == 0)
4773 return (base);
4774 else if (shamt >= 32)
4775 return ((ARMword) ((ARMsword) base >> 31L));
4776 else
4777 return ((ARMword) ((ARMsword) base >> (int) shamt));
4778 case ROR:
4779 shamt &= 0x1f;
4780 if (shamt == 0)
4781 return (base);
4782 else
4783 return ((base << (32 - shamt)) | (base >> shamt));
4786 else
4788 /* Shift amount is a constant. */
4789 #ifndef MODE32
4790 if (base == 15)
4791 base = ECC | ER15INT | R15PC | EMODE;
4792 else
4793 #endif
4794 base = state->Reg[base];
4795 shamt = BITS (7, 11);
4796 switch ((int) BITS (5, 6))
4798 case LSL:
4799 return (base << shamt);
4800 case LSR:
4801 if (shamt == 0)
4802 return (0);
4803 else
4804 return (base >> shamt);
4805 case ASR:
4806 if (shamt == 0)
4807 return ((ARMword) ((ARMsword) base >> 31L));
4808 else
4809 return ((ARMword) ((ARMsword) base >> (int) shamt));
4810 case ROR:
4811 if (shamt == 0)
4812 /* It's an RRX. */
4813 return ((base >> 1) | (CFLAG << 31));
4814 else
4815 return ((base << (32 - shamt)) | (base >> shamt));
4819 return 0;
4822 /* This routine evaluates most Logical Data Processing register RHS's
4823 with the S bit set. It is intended to be called from the macro
4824 DPSRegRHS, which filters the common case of an unshifted register
4825 with in line code. */
4827 static ARMword
4828 GetDPSRegRHS (ARMul_State * state, ARMword instr)
4830 ARMword shamt, base;
4832 base = RHSReg;
4833 if (BIT (4))
4835 /* Shift amount in a register. */
4836 UNDEF_Shift;
4837 INCPC;
4838 #ifndef MODE32
4839 if (base == 15)
4840 base = ECC | ER15INT | R15PC | EMODE;
4841 else
4842 #endif
4843 base = state->Reg[base];
4844 ARMul_Icycles (state, 1, 0L);
4845 shamt = state->Reg[BITS (8, 11)] & 0xff;
4846 switch ((int) BITS (5, 6))
4848 case LSL:
4849 if (shamt == 0)
4850 return (base);
4851 else if (shamt == 32)
4853 ASSIGNC (base & 1);
4854 return (0);
4856 else if (shamt > 32)
4858 CLEARC;
4859 return (0);
4861 else
4863 ASSIGNC ((base >> (32 - shamt)) & 1);
4864 return (base << shamt);
4866 case LSR:
4867 if (shamt == 0)
4868 return (base);
4869 else if (shamt == 32)
4871 ASSIGNC (base >> 31);
4872 return (0);
4874 else if (shamt > 32)
4876 CLEARC;
4877 return (0);
4879 else
4881 ASSIGNC ((base >> (shamt - 1)) & 1);
4882 return (base >> shamt);
4884 case ASR:
4885 if (shamt == 0)
4886 return (base);
4887 else if (shamt >= 32)
4889 ASSIGNC (base >> 31L);
4890 return ((ARMword) ((ARMsword) base >> 31L));
4892 else
4894 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
4895 return ((ARMword) ((ARMsword) base >> (int) shamt));
4897 case ROR:
4898 if (shamt == 0)
4899 return (base);
4900 shamt &= 0x1f;
4901 if (shamt == 0)
4903 ASSIGNC (base >> 31);
4904 return (base);
4906 else
4908 ASSIGNC ((base >> (shamt - 1)) & 1);
4909 return ((base << (32 - shamt)) | (base >> shamt));
4913 else
4915 /* Shift amount is a constant. */
4916 #ifndef MODE32
4917 if (base == 15)
4918 base = ECC | ER15INT | R15PC | EMODE;
4919 else
4920 #endif
4921 base = state->Reg[base];
4922 shamt = BITS (7, 11);
4924 switch ((int) BITS (5, 6))
4926 case LSL:
4927 ASSIGNC ((base >> (32 - shamt)) & 1);
4928 return (base << shamt);
4929 case LSR:
4930 if (shamt == 0)
4932 ASSIGNC (base >> 31);
4933 return (0);
4935 else
4937 ASSIGNC ((base >> (shamt - 1)) & 1);
4938 return (base >> shamt);
4940 case ASR:
4941 if (shamt == 0)
4943 ASSIGNC (base >> 31L);
4944 return ((ARMword) ((ARMsword) base >> 31L));
4946 else
4948 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
4949 return ((ARMword) ((ARMsword) base >> (int) shamt));
4951 case ROR:
4952 if (shamt == 0)
4954 /* It's an RRX. */
4955 shamt = CFLAG;
4956 ASSIGNC (base & 1);
4957 return ((base >> 1) | (shamt << 31));
4959 else
4961 ASSIGNC ((base >> (shamt - 1)) & 1);
4962 return ((base << (32 - shamt)) | (base >> shamt));
4967 return 0;
4970 /* This routine handles writes to register 15 when the S bit is not set. */
4972 static void
4973 WriteR15 (ARMul_State * state, ARMword src)
4975 /* The ARM documentation states that the two least significant bits
4976 are discarded when setting PC, except in the cases handled by
4977 WriteR15Branch() below. It's probably an oversight: in THUMB
4978 mode, the second least significant bit should probably not be
4979 discarded. */
4980 #ifdef MODET
4981 if (TFLAG)
4982 src &= 0xfffffffe;
4983 else
4984 #endif
4985 src &= 0xfffffffc;
4987 #ifdef MODE32
4988 state->Reg[15] = src & PCBITS;
4989 #else
4990 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
4991 ARMul_R15Altered (state);
4992 #endif
4994 FLUSHPIPE;
4995 if (trace_funcs)
4996 fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
4999 /* This routine handles writes to register 15 when the S bit is set. */
5001 static void
5002 WriteSR15 (ARMul_State * state, ARMword src)
5004 #ifdef MODE32
5005 if (state->Bank > 0)
5007 state->Cpsr = state->Spsr[state->Bank];
5008 ARMul_CPSRAltered (state);
5010 #ifdef MODET
5011 if (TFLAG)
5012 src &= 0xfffffffe;
5013 else
5014 #endif
5015 src &= 0xfffffffc;
5016 state->Reg[15] = src & PCBITS;
5017 #else
5018 #ifdef MODET
5019 if (TFLAG)
5020 /* ARMul_R15Altered would have to support it. */
5021 abort ();
5022 else
5023 #endif
5024 src &= 0xfffffffc;
5026 if (state->Bank == USERBANK)
5027 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
5028 else
5029 state->Reg[15] = src;
5031 ARMul_R15Altered (state);
5032 #endif
5033 FLUSHPIPE;
5034 if (trace_funcs)
5035 fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
5038 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
5039 will switch to Thumb mode if the least significant bit is set. */
5041 static void
5042 WriteR15Branch (ARMul_State * state, ARMword src)
5044 #ifdef MODET
5045 if (src & 1)
5047 /* Thumb bit. */
5048 SETT;
5049 state->Reg[15] = src & 0xfffffffe;
5051 else
5053 CLEART;
5054 state->Reg[15] = src & 0xfffffffc;
5056 FLUSHPIPE;
5057 if (trace_funcs)
5058 fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
5059 #else
5060 WriteR15 (state, src);
5061 #endif
5064 /* Before ARM_v5 LDR and LDM of pc did not change mode. */
5066 static void
5067 WriteR15Load (ARMul_State * state, ARMword src)
5069 if (state->is_v5)
5070 WriteR15Branch (state, src);
5071 else
5072 WriteR15 (state, src);
5075 /* This routine evaluates most Load and Store register RHS's. It is
5076 intended to be called from the macro LSRegRHS, which filters the
5077 common case of an unshifted register with in line code. */
5079 static ARMword
5080 GetLSRegRHS (ARMul_State * state, ARMword instr)
5082 ARMword shamt, base;
5084 base = RHSReg;
5085 #ifndef MODE32
5086 if (base == 15)
5087 /* Now forbidden, but ... */
5088 base = ECC | ER15INT | R15PC | EMODE;
5089 else
5090 #endif
5091 base = state->Reg[base];
5093 shamt = BITS (7, 11);
5094 switch ((int) BITS (5, 6))
5096 case LSL:
5097 return (base << shamt);
5098 case LSR:
5099 if (shamt == 0)
5100 return (0);
5101 else
5102 return (base >> shamt);
5103 case ASR:
5104 if (shamt == 0)
5105 return ((ARMword) ((ARMsword) base >> 31L));
5106 else
5107 return ((ARMword) ((ARMsword) base >> (int) shamt));
5108 case ROR:
5109 if (shamt == 0)
5110 /* It's an RRX. */
5111 return ((base >> 1) | (CFLAG << 31));
5112 else
5113 return ((base << (32 - shamt)) | (base >> shamt));
5114 default:
5115 break;
5117 return 0;
5120 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
5122 static ARMword
5123 GetLS7RHS (ARMul_State * state, ARMword instr)
5125 if (BIT (22) == 0)
5127 /* Register. */
5128 #ifndef MODE32
5129 if (RHSReg == 15)
5130 /* Now forbidden, but ... */
5131 return ECC | ER15INT | R15PC | EMODE;
5132 #endif
5133 return state->Reg[RHSReg];
5136 /* Immediate. */
5137 return BITS (0, 3) | (BITS (8, 11) << 4);
5140 /* This function does the work of loading a word for a LDR instruction. */
5142 static unsigned
5143 LoadWord (ARMul_State * state, ARMword instr, ARMword address)
5145 ARMword dest;
5147 BUSUSEDINCPCS;
5148 #ifndef MODE32
5149 if (ADDREXCEPT (address))
5150 INTERNALABORT (address);
5151 #endif
5153 dest = ARMul_LoadWordN (state, address);
5155 if (state->Aborted)
5157 TAKEABORT;
5158 return state->lateabtSig;
5160 if (address & 3)
5161 dest = ARMul_Align (state, address, dest);
5162 WRITEDESTB (dest);
5163 ARMul_Icycles (state, 1, 0L);
5165 return (DESTReg != LHSReg);
5168 #ifdef MODET
5169 /* This function does the work of loading a halfword. */
5171 static unsigned
5172 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
5173 int signextend)
5175 ARMword dest;
5177 BUSUSEDINCPCS;
5178 #ifndef MODE32
5179 if (ADDREXCEPT (address))
5180 INTERNALABORT (address);
5181 #endif
5182 dest = ARMul_LoadHalfWord (state, address);
5183 if (state->Aborted)
5185 TAKEABORT;
5186 return state->lateabtSig;
5188 UNDEF_LSRBPC;
5189 if (signextend)
5190 if (dest & 1 << (16 - 1))
5191 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
5193 WRITEDEST (dest);
5194 ARMul_Icycles (state, 1, 0L);
5195 return (DESTReg != LHSReg);
5198 #endif /* MODET */
5200 /* This function does the work of loading a byte for a LDRB instruction. */
5202 static unsigned
5203 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
5205 ARMword dest;
5207 BUSUSEDINCPCS;
5208 #ifndef MODE32
5209 if (ADDREXCEPT (address))
5210 INTERNALABORT (address);
5211 #endif
5212 dest = ARMul_LoadByte (state, address);
5213 if (state->Aborted)
5215 TAKEABORT;
5216 return state->lateabtSig;
5218 UNDEF_LSRBPC;
5219 if (signextend)
5220 if (dest & 1 << (8 - 1))
5221 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
5223 WRITEDEST (dest);
5224 ARMul_Icycles (state, 1, 0L);
5226 return (DESTReg != LHSReg);
5229 /* This function does the work of loading two words for a LDRD instruction. */
5231 static void
5232 Handle_Load_Double (ARMul_State * state, ARMword instr)
5234 ARMword dest_reg;
5235 ARMword addr_reg;
5236 ARMword write_back = BIT (21);
5237 ARMword immediate = BIT (22);
5238 ARMword add_to_base = BIT (23);
5239 ARMword pre_indexed = BIT (24);
5240 ARMword offset;
5241 ARMword addr;
5242 ARMword sum;
5243 ARMword base;
5244 ARMword value1;
5245 ARMword value2;
5247 BUSUSEDINCPCS;
5249 /* If the writeback bit is set, the pre-index bit must be clear. */
5250 if (write_back && ! pre_indexed)
5252 ARMul_UndefInstr (state, instr);
5253 return;
5256 /* Extract the base address register. */
5257 addr_reg = LHSReg;
5259 /* Extract the destination register and check it. */
5260 dest_reg = DESTReg;
5262 /* Destination register must be even. */
5263 if ((dest_reg & 1)
5264 /* Destination register cannot be LR. */
5265 || (dest_reg == 14))
5267 ARMul_UndefInstr (state, instr);
5268 return;
5271 /* Compute the base address. */
5272 base = state->Reg[addr_reg];
5274 /* Compute the offset. */
5275 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
5277 /* Compute the sum of the two. */
5278 if (add_to_base)
5279 sum = base + offset;
5280 else
5281 sum = base - offset;
5283 /* If this is a pre-indexed mode use the sum. */
5284 if (pre_indexed)
5285 addr = sum;
5286 else
5287 addr = base;
5289 if (state->is_v6 && (addr & 0x3) == 0)
5290 /* Word alignment is enough for v6. */
5292 /* The address must be aligned on a 8 byte boundary. */
5293 else if (addr & 0x7)
5295 #ifdef ABORTS
5296 ARMul_DATAABORT (addr);
5297 #else
5298 ARMul_UndefInstr (state, instr);
5299 #endif
5300 return;
5303 /* For pre indexed or post indexed addressing modes,
5304 check that the destination registers do not overlap
5305 the address registers. */
5306 if ((! pre_indexed || write_back)
5307 && ( addr_reg == dest_reg
5308 || addr_reg == dest_reg + 1))
5310 ARMul_UndefInstr (state, instr);
5311 return;
5314 /* Load the words. */
5315 value1 = ARMul_LoadWordN (state, addr);
5316 value2 = ARMul_LoadWordN (state, addr + 4);
5318 /* Check for data aborts. */
5319 if (state->Aborted)
5321 TAKEABORT;
5322 return;
5325 ARMul_Icycles (state, 2, 0L);
5327 /* Store the values. */
5328 state->Reg[dest_reg] = value1;
5329 state->Reg[dest_reg + 1] = value2;
5331 /* Do the post addressing and writeback. */
5332 if (! pre_indexed)
5333 addr = sum;
5335 if (! pre_indexed || write_back)
5336 state->Reg[addr_reg] = addr;
5339 /* This function does the work of storing two words for a STRD instruction. */
5341 static void
5342 Handle_Store_Double (ARMul_State * state, ARMword instr)
5344 ARMword src_reg;
5345 ARMword addr_reg;
5346 ARMword write_back = BIT (21);
5347 ARMword immediate = BIT (22);
5348 ARMword add_to_base = BIT (23);
5349 ARMword pre_indexed = BIT (24);
5350 ARMword offset;
5351 ARMword addr;
5352 ARMword sum;
5353 ARMword base;
5355 BUSUSEDINCPCS;
5357 /* If the writeback bit is set, the pre-index bit must be clear. */
5358 if (write_back && ! pre_indexed)
5360 ARMul_UndefInstr (state, instr);
5361 return;
5364 /* Extract the base address register. */
5365 addr_reg = LHSReg;
5367 /* Base register cannot be PC. */
5368 if (addr_reg == 15)
5370 ARMul_UndefInstr (state, instr);
5371 return;
5374 /* Extract the source register. */
5375 src_reg = DESTReg;
5377 /* Source register must be even. */
5378 if (src_reg & 1)
5380 ARMul_UndefInstr (state, instr);
5381 return;
5384 /* Compute the base address. */
5385 base = state->Reg[addr_reg];
5387 /* Compute the offset. */
5388 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
5390 /* Compute the sum of the two. */
5391 if (add_to_base)
5392 sum = base + offset;
5393 else
5394 sum = base - offset;
5396 /* If this is a pre-indexed mode use the sum. */
5397 if (pre_indexed)
5398 addr = sum;
5399 else
5400 addr = base;
5402 /* The address must be aligned on a 8 byte boundary. */
5403 if (addr & 0x7)
5405 #ifdef ABORTS
5406 ARMul_DATAABORT (addr);
5407 #else
5408 ARMul_UndefInstr (state, instr);
5409 #endif
5410 return;
5413 /* For pre indexed or post indexed addressing modes,
5414 check that the destination registers do not overlap
5415 the address registers. */
5416 if ((! pre_indexed || write_back)
5417 && ( addr_reg == src_reg
5418 || addr_reg == src_reg + 1))
5420 ARMul_UndefInstr (state, instr);
5421 return;
5424 /* Load the words. */
5425 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
5426 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
5428 if (state->Aborted)
5430 TAKEABORT;
5431 return;
5434 /* Do the post addressing and writeback. */
5435 if (! pre_indexed)
5436 addr = sum;
5438 if (! pre_indexed || write_back)
5439 state->Reg[addr_reg] = addr;
5442 /* This function does the work of storing a word from a STR instruction. */
5444 static unsigned
5445 StoreWord (ARMul_State * state, ARMword instr, ARMword address)
5447 BUSUSEDINCPCN;
5448 #ifndef MODE32
5449 if (DESTReg == 15)
5450 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
5451 #endif
5452 #ifdef MODE32
5453 ARMul_StoreWordN (state, address, DEST);
5454 #else
5455 if (VECTORACCESS (address) || ADDREXCEPT (address))
5457 INTERNALABORT (address);
5458 (void) ARMul_LoadWordN (state, address);
5460 else
5461 ARMul_StoreWordN (state, address, DEST);
5462 #endif
5463 if (state->Aborted)
5465 TAKEABORT;
5466 return state->lateabtSig;
5468 return TRUE;
5471 #ifdef MODET
5472 /* This function does the work of storing a byte for a STRH instruction. */
5474 static unsigned
5475 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
5477 BUSUSEDINCPCN;
5479 #ifndef MODE32
5480 if (DESTReg == 15)
5481 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
5482 #endif
5484 #ifdef MODE32
5485 ARMul_StoreHalfWord (state, address, DEST);
5486 #else
5487 if (VECTORACCESS (address) || ADDREXCEPT (address))
5489 INTERNALABORT (address);
5490 (void) ARMul_LoadHalfWord (state, address);
5492 else
5493 ARMul_StoreHalfWord (state, address, DEST);
5494 #endif
5496 if (state->Aborted)
5498 TAKEABORT;
5499 return state->lateabtSig;
5501 return TRUE;
5504 #endif /* MODET */
5506 /* This function does the work of storing a byte for a STRB instruction. */
5508 static unsigned
5509 StoreByte (ARMul_State * state, ARMword instr, ARMword address)
5511 BUSUSEDINCPCN;
5512 #ifndef MODE32
5513 if (DESTReg == 15)
5514 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
5515 #endif
5516 #ifdef MODE32
5517 ARMul_StoreByte (state, address, DEST);
5518 #else
5519 if (VECTORACCESS (address) || ADDREXCEPT (address))
5521 INTERNALABORT (address);
5522 (void) ARMul_LoadByte (state, address);
5524 else
5525 ARMul_StoreByte (state, address, DEST);
5526 #endif
5527 if (state->Aborted)
5529 TAKEABORT;
5530 return state->lateabtSig;
5532 UNDEF_LSRBPC;
5533 return TRUE;
5536 /* This function does the work of loading the registers listed in an LDM
5537 instruction, when the S bit is clear. The code here is always increment
5538 after, it's up to the caller to get the input address correct and to
5539 handle base register modification. */
5541 static void
5542 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
5544 ARMword dest, temp;
5546 UNDEF_LSMNoRegs;
5547 UNDEF_LSMPCBase;
5548 UNDEF_LSMBaseInListWb;
5549 BUSUSEDINCPCS;
5550 #ifndef MODE32
5551 if (ADDREXCEPT (address))
5552 INTERNALABORT (address);
5553 #endif
5554 if (BIT (21) && LHSReg != 15)
5555 LSBase = WBBase;
5557 /* N cycle first. */
5558 for (temp = 0; !BIT (temp); temp++)
5561 dest = ARMul_LoadWordN (state, address);
5563 if (!state->abortSig && !state->Aborted)
5564 state->Reg[temp++] = dest;
5565 else if (!state->Aborted)
5567 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5568 state->Aborted = ARMul_DataAbortV;
5571 /* S cycles from here on. */
5572 for (; temp < 16; temp ++)
5573 if (BIT (temp))
5575 /* Load this register. */
5576 address += 4;
5577 dest = ARMul_LoadWordS (state, address);
5579 if (!state->abortSig && !state->Aborted)
5580 state->Reg[temp] = dest;
5581 else if (!state->Aborted)
5583 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5584 state->Aborted = ARMul_DataAbortV;
5588 if (BIT (15) && !state->Aborted)
5589 /* PC is in the reg list. */
5590 WriteR15Load (state, PC);
5592 /* To write back the final register. */
5593 ARMul_Icycles (state, 1, 0L);
5595 if (state->Aborted)
5597 if (BIT (21) && LHSReg != 15)
5598 LSBase = WBBase;
5599 TAKEABORT;
5603 /* This function does the work of loading the registers listed in an LDM
5604 instruction, when the S bit is set. The code here is always increment
5605 after, it's up to the caller to get the input address correct and to
5606 handle base register modification. */
5608 static void
5609 LoadSMult (ARMul_State * state,
5610 ARMword instr,
5611 ARMword address,
5612 ARMword WBBase)
5614 ARMword dest, temp;
5616 UNDEF_LSMNoRegs;
5617 UNDEF_LSMPCBase;
5618 UNDEF_LSMBaseInListWb;
5620 BUSUSEDINCPCS;
5622 #ifndef MODE32
5623 if (ADDREXCEPT (address))
5624 INTERNALABORT (address);
5625 #endif
5627 if (BIT (21) && LHSReg != 15)
5628 LSBase = WBBase;
5630 if (!BIT (15) && state->Bank != USERBANK)
5632 /* Temporary reg bank switch. */
5633 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
5634 UNDEF_LSMUserBankWb;
5637 /* N cycle first. */
5638 for (temp = 0; !BIT (temp); temp ++)
5641 dest = ARMul_LoadWordN (state, address);
5643 if (!state->abortSig)
5644 state->Reg[temp++] = dest;
5645 else if (!state->Aborted)
5647 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5648 state->Aborted = ARMul_DataAbortV;
5651 /* S cycles from here on. */
5652 for (; temp < 16; temp++)
5653 if (BIT (temp))
5655 /* Load this register. */
5656 address += 4;
5657 dest = ARMul_LoadWordS (state, address);
5659 if (!state->abortSig && !state->Aborted)
5660 state->Reg[temp] = dest;
5661 else if (!state->Aborted)
5663 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5664 state->Aborted = ARMul_DataAbortV;
5668 if (BIT (15) && !state->Aborted)
5670 /* PC is in the reg list. */
5671 #ifdef MODE32
5672 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
5674 state->Cpsr = GETSPSR (state->Bank);
5675 ARMul_CPSRAltered (state);
5678 WriteR15 (state, PC);
5679 #else
5680 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
5682 /* Protect bits in user mode. */
5683 ASSIGNN ((state->Reg[15] & NBIT) != 0);
5684 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
5685 ASSIGNC ((state->Reg[15] & CBIT) != 0);
5686 ASSIGNV ((state->Reg[15] & VBIT) != 0);
5688 else
5689 ARMul_R15Altered (state);
5691 FLUSHPIPE;
5692 #endif
5695 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
5696 /* Restore the correct bank. */
5697 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
5699 /* To write back the final register. */
5700 ARMul_Icycles (state, 1, 0L);
5702 if (state->Aborted)
5704 if (BIT (21) && LHSReg != 15)
5705 LSBase = WBBase;
5707 TAKEABORT;
5711 /* This function does the work of storing the registers listed in an STM
5712 instruction, when the S bit is clear. The code here is always increment
5713 after, it's up to the caller to get the input address correct and to
5714 handle base register modification. */
5716 static void
5717 StoreMult (ARMul_State * state,
5718 ARMword instr,
5719 ARMword address,
5720 ARMword WBBase)
5722 ARMword temp;
5724 UNDEF_LSMNoRegs;
5725 UNDEF_LSMPCBase;
5726 UNDEF_LSMBaseInListWb;
5728 if (!TFLAG)
5729 /* N-cycle, increment the PC and update the NextInstr state. */
5730 BUSUSEDINCPCN;
5732 #ifndef MODE32
5733 if (VECTORACCESS (address) || ADDREXCEPT (address))
5734 INTERNALABORT (address);
5736 if (BIT (15))
5737 PATCHR15;
5738 #endif
5740 /* N cycle first. */
5741 for (temp = 0; !BIT (temp); temp ++)
5744 #ifdef MODE32
5745 ARMul_StoreWordN (state, address, state->Reg[temp++]);
5746 #else
5747 if (state->Aborted)
5749 (void) ARMul_LoadWordN (state, address);
5751 /* Fake the Stores as Loads. */
5752 for (; temp < 16; temp++)
5753 if (BIT (temp))
5755 /* Save this register. */
5756 address += 4;
5757 (void) ARMul_LoadWordS (state, address);
5760 if (BIT (21) && LHSReg != 15)
5761 LSBase = WBBase;
5762 TAKEABORT;
5763 return;
5765 else
5766 ARMul_StoreWordN (state, address, state->Reg[temp++]);
5767 #endif
5769 if (state->abortSig && !state->Aborted)
5771 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5772 state->Aborted = ARMul_DataAbortV;
5775 if (BIT (21) && LHSReg != 15)
5776 LSBase = WBBase;
5778 /* S cycles from here on. */
5779 for (; temp < 16; temp ++)
5780 if (BIT (temp))
5782 /* Save this register. */
5783 address += 4;
5785 ARMul_StoreWordS (state, address, state->Reg[temp]);
5787 if (state->abortSig && !state->Aborted)
5789 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5790 state->Aborted = ARMul_DataAbortV;
5794 if (state->Aborted)
5795 TAKEABORT;
5798 /* This function does the work of storing the registers listed in an STM
5799 instruction when the S bit is set. The code here is always increment
5800 after, it's up to the caller to get the input address correct and to
5801 handle base register modification. */
5803 static void
5804 StoreSMult (ARMul_State * state,
5805 ARMword instr,
5806 ARMword address,
5807 ARMword WBBase)
5809 ARMword temp;
5811 UNDEF_LSMNoRegs;
5812 UNDEF_LSMPCBase;
5813 UNDEF_LSMBaseInListWb;
5815 BUSUSEDINCPCN;
5817 #ifndef MODE32
5818 if (VECTORACCESS (address) || ADDREXCEPT (address))
5819 INTERNALABORT (address);
5821 if (BIT (15))
5822 PATCHR15;
5823 #endif
5825 if (state->Bank != USERBANK)
5827 /* Force User Bank. */
5828 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
5829 UNDEF_LSMUserBankWb;
5832 for (temp = 0; !BIT (temp); temp++)
5833 ; /* N cycle first. */
5835 #ifdef MODE32
5836 ARMul_StoreWordN (state, address, state->Reg[temp++]);
5837 #else
5838 if (state->Aborted)
5840 (void) ARMul_LoadWordN (state, address);
5842 for (; temp < 16; temp++)
5843 /* Fake the Stores as Loads. */
5844 if (BIT (temp))
5846 /* Save this register. */
5847 address += 4;
5849 (void) ARMul_LoadWordS (state, address);
5852 if (BIT (21) && LHSReg != 15)
5853 LSBase = WBBase;
5855 TAKEABORT;
5856 return;
5858 else
5859 ARMul_StoreWordN (state, address, state->Reg[temp++]);
5860 #endif
5862 if (state->abortSig && !state->Aborted)
5864 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5865 state->Aborted = ARMul_DataAbortV;
5868 /* S cycles from here on. */
5869 for (; temp < 16; temp++)
5870 if (BIT (temp))
5872 /* Save this register. */
5873 address += 4;
5875 ARMul_StoreWordS (state, address, state->Reg[temp]);
5877 if (state->abortSig && !state->Aborted)
5879 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5880 state->Aborted = ARMul_DataAbortV;
5884 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
5885 /* Restore the correct bank. */
5886 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
5888 if (BIT (21) && LHSReg != 15)
5889 LSBase = WBBase;
5891 if (state->Aborted)
5892 TAKEABORT;
5895 /* This function does the work of adding two 32bit values
5896 together, and calculating if a carry has occurred. */
5898 static ARMword
5899 Add32 (ARMword a1, ARMword a2, int *carry)
5901 ARMword result = (a1 + a2);
5902 unsigned int uresult = (unsigned int) result;
5903 unsigned int ua1 = (unsigned int) a1;
5905 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5906 or (result > RdLo) then we have no carry. */
5907 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
5908 *carry = 1;
5909 else
5910 *carry = 0;
5912 return result;
5915 /* This function does the work of multiplying
5916 two 32bit values to give a 64bit result. */
5918 static unsigned
5919 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
5921 /* Operand register numbers. */
5922 int nRdHi, nRdLo, nRs, nRm;
5923 ARMword RdHi = 0, RdLo = 0, Rm;
5924 /* Cycle count. */
5925 int scount;
5927 nRdHi = BITS (16, 19);
5928 nRdLo = BITS (12, 15);
5929 nRs = BITS (8, 11);
5930 nRm = BITS (0, 3);
5932 /* Needed to calculate the cycle count. */
5933 Rm = state->Reg[nRm];
5935 /* Check for illegal operand combinations first. */
5936 if ( nRdHi != 15
5937 && nRdLo != 15
5938 && nRs != 15
5939 && nRm != 15
5940 && nRdHi != nRdLo)
5942 /* Intermediate results. */
5943 ARMword lo, mid1, mid2, hi;
5944 int carry;
5945 ARMword Rs = state->Reg[nRs];
5946 int sign = 0;
5948 #ifdef MODE32
5949 if (state->is_v6)
5951 else
5952 #endif
5953 /* BAD code can trigger this result. So only complain if debugging. */
5954 if (state->Debug && (nRdHi == nRm || nRdLo == nRm))
5955 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS: %d %d %d\n",
5956 nRdHi, nRdLo, nRm);
5957 if (msigned)
5959 /* Compute sign of result and adjust operands if necessary. */
5960 sign = (Rm ^ Rs) & 0x80000000;
5962 if (((ARMsword) Rm) < 0)
5963 Rm = -Rm;
5965 if (((ARMsword) Rs) < 0)
5966 Rs = -Rs;
5969 /* We can split the 32x32 into four 16x16 operations. This
5970 ensures that we do not lose precision on 32bit only hosts. */
5971 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
5972 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
5973 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
5974 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
5976 /* We now need to add all of these results together, taking
5977 care to propogate the carries from the additions. */
5978 RdLo = Add32 (lo, (mid1 << 16), &carry);
5979 RdHi = carry;
5980 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
5981 RdHi +=
5982 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
5984 if (sign)
5986 /* Negate result if necessary. */
5987 RdLo = ~RdLo;
5988 RdHi = ~RdHi;
5989 if (RdLo == 0xFFFFFFFF)
5991 RdLo = 0;
5992 RdHi += 1;
5994 else
5995 RdLo += 1;
5998 state->Reg[nRdLo] = RdLo;
5999 state->Reg[nRdHi] = RdHi;
6001 else if (state->Debug)
6002 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
6004 if (scc)
6005 /* Ensure that both RdHi and RdLo are used to compute Z,
6006 but don't let RdLo's sign bit make it to N. */
6007 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
6009 /* The cycle count depends on whether the instruction is a signed or
6010 unsigned multiply, and what bits are clear in the multiplier. */
6011 if (msigned && (Rm & ((unsigned) 1 << 31)))
6012 /* Invert the bits to make the check against zero. */
6013 Rm = ~Rm;
6015 if ((Rm & 0xFFFFFF00) == 0)
6016 scount = 1;
6017 else if ((Rm & 0xFFFF0000) == 0)
6018 scount = 2;
6019 else if ((Rm & 0xFF000000) == 0)
6020 scount = 3;
6021 else
6022 scount = 4;
6024 return 2 + scount;
6027 /* This function does the work of multiplying two 32bit
6028 values and adding a 64bit value to give a 64bit result. */
6030 static unsigned
6031 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
6033 unsigned scount;
6034 ARMword RdLo, RdHi;
6035 int nRdHi, nRdLo;
6036 int carry = 0;
6038 nRdHi = BITS (16, 19);
6039 nRdLo = BITS (12, 15);
6041 RdHi = state->Reg[nRdHi];
6042 RdLo = state->Reg[nRdLo];
6044 scount = Multiply64 (state, instr, msigned, LDEFAULT);
6046 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
6047 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
6049 state->Reg[nRdLo] = RdLo;
6050 state->Reg[nRdHi] = RdHi;
6052 if (scc)
6053 /* Ensure that both RdHi and RdLo are used to compute Z,
6054 but don't let RdLo's sign bit make it to N. */
6055 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
6057 /* Extra cycle for addition. */
6058 return scount + 1;