Automatic date update in version.in
[binutils-gdb.git] / sim / arm / armemu.c
blob2958977c4fdc08efcf71179d9e6b714f3e1ad918
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 /* This must come before any other includes. */
19 #include "defs.h"
21 #include "armdefs.h"
22 #include "armemu.h"
23 #include "armos.h"
24 #include "iwmmxt.h"
26 static ARMword GetDPRegRHS (ARMul_State *, ARMword);
27 static ARMword GetDPSRegRHS (ARMul_State *, ARMword);
28 static void WriteR15 (ARMul_State *, ARMword);
29 static void WriteSR15 (ARMul_State *, ARMword);
30 static void WriteR15Branch (ARMul_State *, ARMword);
31 static void WriteR15Load (ARMul_State *, ARMword);
32 static ARMword GetLSRegRHS (ARMul_State *, ARMword);
33 static ARMword GetLS7RHS (ARMul_State *, ARMword);
34 static unsigned LoadWord (ARMul_State *, ARMword, ARMword);
35 static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int);
36 static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int);
37 static unsigned StoreWord (ARMul_State *, ARMword, ARMword);
38 static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword);
39 static unsigned StoreByte (ARMul_State *, ARMword, ARMword);
40 static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword);
41 static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword);
42 static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword);
43 static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword);
44 static unsigned Multiply64 (ARMul_State *, ARMword, int, int);
45 static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int);
46 static void Handle_Load_Double (ARMul_State *, ARMword);
47 static void Handle_Store_Double (ARMul_State *, ARMword);
49 #define LUNSIGNED (0) /* unsigned operation */
50 #define LSIGNED (1) /* signed operation */
51 #define LDEFAULT (0) /* default : do nothing */
52 #define LSCC (1) /* set condition codes on result */
54 extern int stop_simulator;
56 /* Short-hand macros for LDR/STR. */
58 /* Store post decrement writeback. */
59 #define SHDOWNWB() \
60 lhs = LHS ; \
61 if (StoreHalfWord (state, instr, lhs)) \
62 LSBase = lhs - GetLS7RHS (state, instr);
64 /* Store post increment writeback. */
65 #define SHUPWB() \
66 lhs = LHS ; \
67 if (StoreHalfWord (state, instr, lhs)) \
68 LSBase = lhs + GetLS7RHS (state, instr);
70 /* Store pre decrement. */
71 #define SHPREDOWN() \
72 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
74 /* Store pre decrement writeback. */
75 #define SHPREDOWNWB() \
76 temp = LHS - GetLS7RHS (state, instr); \
77 if (StoreHalfWord (state, instr, temp)) \
78 LSBase = temp;
80 /* Store pre increment. */
81 #define SHPREUP() \
82 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
84 /* Store pre increment writeback. */
85 #define SHPREUPWB() \
86 temp = LHS + GetLS7RHS (state, instr); \
87 if (StoreHalfWord (state, instr, temp)) \
88 LSBase = temp;
90 /* Load post decrement writeback. */
91 #define LHPOSTDOWN() \
92 { \
93 int done = 1; \
94 lhs = LHS; \
95 temp = lhs - GetLS7RHS (state, instr); \
97 switch (BITS (5, 6)) \
98 { \
99 case 1: /* H */ \
100 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
101 LSBase = temp; \
102 break; \
103 case 2: /* SB */ \
104 if (LoadByte (state, instr, lhs, LSIGNED)) \
105 LSBase = temp; \
106 break; \
107 case 3: /* SH */ \
108 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
109 LSBase = temp; \
110 break; \
111 case 0: /* SWP handled elsewhere. */ \
112 default: \
113 done = 0; \
114 break; \
116 if (done) \
117 break; \
120 /* Load post increment writeback. */
121 #define LHPOSTUP() \
123 int done = 1; \
124 lhs = LHS; \
125 temp = lhs + GetLS7RHS (state, instr); \
127 switch (BITS (5, 6)) \
129 case 1: /* H */ \
130 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
131 LSBase = temp; \
132 break; \
133 case 2: /* SB */ \
134 if (LoadByte (state, instr, lhs, LSIGNED)) \
135 LSBase = temp; \
136 break; \
137 case 3: /* SH */ \
138 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
139 LSBase = temp; \
140 break; \
141 case 0: /* SWP handled elsewhere. */ \
142 default: \
143 done = 0; \
144 break; \
146 if (done) \
147 break; \
150 /* Load pre decrement. */
151 #define LHPREDOWN() \
153 int done = 1; \
155 temp = LHS - GetLS7RHS (state, instr); \
156 switch (BITS (5, 6)) \
158 case 1: /* H */ \
159 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
160 break; \
161 case 2: /* SB */ \
162 (void) LoadByte (state, instr, temp, LSIGNED); \
163 break; \
164 case 3: /* SH */ \
165 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
166 break; \
167 case 0: \
168 /* SWP handled elsewhere. */ \
169 default: \
170 done = 0; \
171 break; \
173 if (done) \
174 break; \
177 /* Load pre decrement writeback. */
178 #define LHPREDOWNWB() \
180 int done = 1; \
182 temp = LHS - GetLS7RHS (state, instr); \
183 switch (BITS (5, 6)) \
185 case 1: /* H */ \
186 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
187 LSBase = temp; \
188 break; \
189 case 2: /* SB */ \
190 if (LoadByte (state, instr, temp, LSIGNED)) \
191 LSBase = temp; \
192 break; \
193 case 3: /* SH */ \
194 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
195 LSBase = temp; \
196 break; \
197 case 0: \
198 /* SWP handled elsewhere. */ \
199 default: \
200 done = 0; \
201 break; \
203 if (done) \
204 break; \
207 /* Load pre increment. */
208 #define LHPREUP() \
210 int done = 1; \
212 temp = LHS + GetLS7RHS (state, instr); \
213 switch (BITS (5, 6)) \
215 case 1: /* H */ \
216 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
217 break; \
218 case 2: /* SB */ \
219 (void) LoadByte (state, instr, temp, LSIGNED); \
220 break; \
221 case 3: /* SH */ \
222 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
223 break; \
224 case 0: \
225 /* SWP handled elsewhere. */ \
226 default: \
227 done = 0; \
228 break; \
230 if (done) \
231 break; \
234 /* Load pre increment writeback. */
235 #define LHPREUPWB() \
237 int done = 1; \
239 temp = LHS + GetLS7RHS (state, instr); \
240 switch (BITS (5, 6)) \
242 case 1: /* H */ \
243 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
244 LSBase = temp; \
245 break; \
246 case 2: /* SB */ \
247 if (LoadByte (state, instr, temp, LSIGNED)) \
248 LSBase = temp; \
249 break; \
250 case 3: /* SH */ \
251 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
252 LSBase = temp; \
253 break; \
254 case 0: \
255 /* SWP handled elsewhere. */ \
256 default: \
257 done = 0; \
258 break; \
260 if (done) \
261 break; \
264 /* Attempt to emulate an ARMv6 instruction.
265 Returns non-zero upon success. */
267 #ifdef MODE32
268 static int
269 handle_v6_insn (ARMul_State * state, ARMword instr)
271 ARMword val;
272 ARMword Rd;
273 ARMword Rm;
274 ARMword Rn;
276 switch (BITS (20, 27))
278 #if 0
279 case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
280 case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
281 case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
282 case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
283 case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
284 case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
285 case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
286 case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
287 case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
288 case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
289 case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
290 case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
291 case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
292 case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
293 #endif
294 case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
295 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
296 case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
297 case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
298 case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
299 case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
300 case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
302 case 0x30:
304 /* MOVW<c> <Rd>,#<imm16>
305 instr[31,28] = cond
306 instr[27,20] = 0011 0000
307 instr[19,16] = imm4
308 instr[15,12] = Rd
309 instr[11, 0] = imm12. */
310 Rd = BITS (12, 15);
311 val = (BITS (16, 19) << 12) | BITS (0, 11);
312 state->Reg[Rd] = val;
313 return 1;
316 case 0x34:
318 /* MOVT<c> <Rd>,#<imm16>
319 instr[31,28] = cond
320 instr[27,20] = 0011 0100
321 instr[19,16] = imm4
322 instr[15,12] = Rd
323 instr[11, 0] = imm12. */
324 Rd = BITS (12, 15);
325 val = (BITS (16, 19) << 12) | BITS (0, 11);
326 state->Reg[Rd] &= 0xFFFF;
327 state->Reg[Rd] |= val << 16;
328 return 1;
331 case 0x62:
333 ARMword val1;
334 ARMword val2;
335 ARMsword n, m, r;
336 int i;
338 Rd = BITS (12, 15);
339 Rn = BITS (16, 19);
340 Rm = BITS (0, 3);
342 if (Rd == 15 || Rn == 15 || Rm == 15)
343 break;
345 val1 = state->Reg[Rn];
346 val2 = state->Reg[Rm];
348 switch (BITS (4, 11))
350 case 0xF1: /* QADD16<c> <Rd>,<Rn>,<Rm>. */
351 state->Reg[Rd] = 0;
353 for (i = 0; i < 32; i+= 16)
355 n = (val1 >> i) & 0xFFFF;
356 if (n & 0x8000)
357 n |= -(1 << 16);
359 m = (val2 >> i) & 0xFFFF;
360 if (m & 0x8000)
361 m |= -(1 << 16);
363 r = n + m;
365 if (r > 0x7FFF)
366 r = 0x7FFF;
367 else if (r < -(0x8000))
368 r = - 0x8000;
370 state->Reg[Rd] |= (r & 0xFFFF) << i;
372 return 1;
374 case 0xF3: /* QASX<c> <Rd>,<Rn>,<Rm>. */
375 n = val1 & 0xFFFF;
376 if (n & 0x8000)
377 n |= -(1 << 16);
379 m = (val2 >> 16) & 0xFFFF;
380 if (m & 0x8000)
381 m |= -(1 << 16);
383 r = n - m;
385 if (r > 0x7FFF)
386 r = 0x7FFF;
387 else if (r < -(0x8000))
388 r = - 0x8000;
390 state->Reg[Rd] = (r & 0xFFFF);
392 n = (val1 >> 16) & 0xFFFF;
393 if (n & 0x8000)
394 n |= -(1 << 16);
396 m = val2 & 0xFFFF;
397 if (m & 0x8000)
398 m |= -(1 << 16);
400 r = n + m;
402 if (r > 0x7FFF)
403 r = 0x7FFF;
404 else if (r < -(0x8000))
405 r = - 0x8000;
407 state->Reg[Rd] |= (r & 0xFFFF) << 16;
408 return 1;
410 case 0xF5: /* QSAX<c> <Rd>,<Rn>,<Rm>. */
411 n = val1 & 0xFFFF;
412 if (n & 0x8000)
413 n |= -(1 << 16);
415 m = (val2 >> 16) & 0xFFFF;
416 if (m & 0x8000)
417 m |= -(1 << 16);
419 r = n + m;
421 if (r > 0x7FFF)
422 r = 0x7FFF;
423 else if (r < -(0x8000))
424 r = - 0x8000;
426 state->Reg[Rd] = (r & 0xFFFF);
428 n = (val1 >> 16) & 0xFFFF;
429 if (n & 0x8000)
430 n |= -(1 << 16);
432 m = val2 & 0xFFFF;
433 if (m & 0x8000)
434 m |= -(1 << 16);
436 r = n - m;
438 if (r > 0x7FFF)
439 r = 0x7FFF;
440 else if (r < -(0x8000))
441 r = - 0x8000;
443 state->Reg[Rd] |= (r & 0xFFFF) << 16;
444 return 1;
446 case 0xF7: /* QSUB16<c> <Rd>,<Rn>,<Rm>. */
447 state->Reg[Rd] = 0;
449 for (i = 0; i < 32; i+= 16)
451 n = (val1 >> i) & 0xFFFF;
452 if (n & 0x8000)
453 n |= -(1 << 16);
455 m = (val2 >> i) & 0xFFFF;
456 if (m & 0x8000)
457 m |= -(1 << 16);
459 r = n - m;
461 if (r > 0x7FFF)
462 r = 0x7FFF;
463 else if (r < -(0x8000))
464 r = - 0x8000;
466 state->Reg[Rd] |= (r & 0xFFFF) << i;
468 return 1;
470 case 0xF9: /* QADD8<c> <Rd>,<Rn>,<Rm>. */
471 state->Reg[Rd] = 0;
473 for (i = 0; i < 32; i+= 8)
475 n = (val1 >> i) & 0xFF;
476 if (n & 0x80)
477 n |= - (1 << 8);
479 m = (val2 >> i) & 0xFF;
480 if (m & 0x80)
481 m |= - (1 << 8);
483 r = n + m;
485 if (r > 127)
486 r = 127;
487 else if (r < -128)
488 r = -128;
490 state->Reg[Rd] |= (r & 0xFF) << i;
492 return 1;
494 case 0xFF: /* QSUB8<c> <Rd>,<Rn>,<Rm>. */
495 state->Reg[Rd] = 0;
497 for (i = 0; i < 32; i+= 8)
499 n = (val1 >> i) & 0xFF;
500 if (n & 0x80)
501 n |= - (1 << 8);
503 m = (val2 >> i) & 0xFF;
504 if (m & 0x80)
505 m |= - (1 << 8);
507 r = n - m;
509 if (r > 127)
510 r = 127;
511 else if (r < -128)
512 r = -128;
514 state->Reg[Rd] |= (r & 0xFF) << i;
516 return 1;
518 default:
519 break;
521 break;
524 case 0x65:
526 ARMword valn;
527 ARMword valm;
528 ARMword res1, res2, res3, res4;
530 /* U{ADD|SUB}{8|16}<c> <Rd>, <Rn>, <Rm>
531 instr[31,28] = cond
532 instr[27,20] = 0110 0101
533 instr[19,16] = Rn
534 instr[15,12] = Rd
535 instr[11, 8] = 1111
536 instr[ 7, 4] = opcode: UADD8 (1001), UADD16 (0001), USUB8 (1111), USUB16 (0111)
537 instr[ 3, 0] = Rm. */
538 if (BITS (8, 11) != 0xF)
539 break;
541 Rn = BITS (16, 19);
542 Rd = BITS (12, 15);
543 Rm = BITS (0, 3);
545 if (Rn == 15 || Rd == 15 || Rm == 15)
547 ARMul_UndefInstr (state, instr);
548 state->Emulate = FALSE;
549 break;
552 valn = state->Reg[Rn];
553 valm = state->Reg[Rm];
555 switch (BITS (4, 7))
557 case 1: /* UADD16. */
558 res1 = (valn & 0xFFFF) + (valm & 0xFFFF);
559 if (res1 > 0xFFFF)
560 state->Cpsr |= (GE0 | GE1);
561 else
562 state->Cpsr &= ~ (GE0 | GE1);
564 res2 = (valn >> 16) + (valm >> 16);
565 if (res2 > 0xFFFF)
566 state->Cpsr |= (GE2 | GE3);
567 else
568 state->Cpsr &= ~ (GE2 | GE3);
570 state->Reg[Rd] = (res1 & 0xFFFF) | (res2 << 16);
571 return 1;
573 case 7: /* USUB16. */
574 res1 = (valn & 0xFFFF) - (valm & 0xFFFF);
575 if (res1 & 0x800000)
576 state->Cpsr |= (GE0 | GE1);
577 else
578 state->Cpsr &= ~ (GE0 | GE1);
580 res2 = (valn >> 16) - (valm >> 16);
581 if (res2 & 0x800000)
582 state->Cpsr |= (GE2 | GE3);
583 else
584 state->Cpsr &= ~ (GE2 | GE3);
586 state->Reg[Rd] = (res1 & 0xFFFF) | (res2 << 16);
587 return 1;
589 case 9: /* UADD8. */
590 res1 = (valn & 0xFF) + (valm & 0xFF);
591 if (res1 > 0xFF)
592 state->Cpsr |= GE0;
593 else
594 state->Cpsr &= ~ GE0;
596 res2 = ((valn >> 8) & 0xFF) + ((valm >> 8) & 0xFF);
597 if (res2 > 0xFF)
598 state->Cpsr |= GE1;
599 else
600 state->Cpsr &= ~ GE1;
602 res3 = ((valn >> 16) & 0xFF) + ((valm >> 16) & 0xFF);
603 if (res3 > 0xFF)
604 state->Cpsr |= GE2;
605 else
606 state->Cpsr &= ~ GE2;
608 res4 = (valn >> 24) + (valm >> 24);
609 if (res4 > 0xFF)
610 state->Cpsr |= GE3;
611 else
612 state->Cpsr &= ~ GE3;
614 state->Reg[Rd] = (res1 & 0xFF) | ((res2 << 8) & 0xFF00)
615 | ((res3 << 16) & 0xFF0000) | (res4 << 24);
616 return 1;
618 case 15: /* USUB8. */
619 res1 = (valn & 0xFF) - (valm & 0xFF);
620 if (res1 & 0x800000)
621 state->Cpsr |= GE0;
622 else
623 state->Cpsr &= ~ GE0;
625 res2 = ((valn >> 8) & 0XFF) - ((valm >> 8) & 0xFF);
626 if (res2 & 0x800000)
627 state->Cpsr |= GE1;
628 else
629 state->Cpsr &= ~ GE1;
631 res3 = ((valn >> 16) & 0XFF) - ((valm >> 16) & 0xFF);
632 if (res3 & 0x800000)
633 state->Cpsr |= GE2;
634 else
635 state->Cpsr &= ~ GE2;
637 res4 = (valn >> 24) - (valm >> 24) ;
638 if (res4 & 0x800000)
639 state->Cpsr |= GE3;
640 else
641 state->Cpsr &= ~ GE3;
643 state->Reg[Rd] = (res1 & 0xFF) | ((res2 << 8) & 0xFF00)
644 | ((res3 << 16) & 0xFF0000) | (res4 << 24);
645 return 1;
647 default:
648 break;
650 break;
653 case 0x68:
655 ARMword res;
657 /* PKHBT<c> <Rd>,<Rn>,<Rm>{,LSL #<imm>}
658 PKHTB<c> <Rd>,<Rn>,<Rm>{,ASR #<imm>}
659 SXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>}
660 SXTB16<c> <Rd>,<Rm>{,<rotation>}
661 SEL<c> <Rd>,<Rn>,<Rm>
663 instr[31,28] = cond
664 instr[27,20] = 0110 1000
665 instr[19,16] = Rn
666 instr[15,12] = Rd
667 instr[11, 7] = imm5 (PKH), 11111 (SEL), rr000 (SXTAB16 & SXTB16),
668 instr[6] = tb (PKH), 0 (SEL), 1 (SXT)
669 instr[5] = opcode: PKH (0), SEL/SXT (1)
670 instr[4] = 1
671 instr[ 3, 0] = Rm. */
673 if (BIT (4) != 1)
674 break;
676 if (BIT (5) == 0)
678 /* FIXME: Add implementation of PKH. */
679 fprintf (stderr, "PKH: NOT YET IMPLEMENTED\n");
680 ARMul_UndefInstr (state, instr);
681 break;
684 if (BIT (6) == 1)
686 /* FIXME: Add implementation of SXT. */
687 fprintf (stderr, "SXT: NOT YET IMPLEMENTED\n");
688 ARMul_UndefInstr (state, instr);
689 break;
692 Rn = BITS (16, 19);
693 Rd = BITS (12, 15);
694 Rm = BITS (0, 3);
695 if (Rn == 15 || Rm == 15 || Rd == 15)
697 ARMul_UndefInstr (state, instr);
698 state->Emulate = FALSE;
699 break;
702 res = (state->Reg[(state->Cpsr & GE0) ? Rn : Rm]) & 0xFF;
703 res |= (state->Reg[(state->Cpsr & GE1) ? Rn : Rm]) & 0xFF00;
704 res |= (state->Reg[(state->Cpsr & GE2) ? Rn : Rm]) & 0xFF0000;
705 res |= (state->Reg[(state->Cpsr & GE3) ? Rn : Rm]) & 0xFF000000;
706 state->Reg[Rd] = res;
707 return 1;
710 case 0x6a:
712 int ror = -1;
714 switch (BITS (4, 11))
716 case 0x07: ror = 0; break;
717 case 0x47: ror = 8; break;
718 case 0x87: ror = 16; break;
719 case 0xc7: ror = 24; break;
721 case 0x01:
722 case 0xf3:
723 printf ("Unhandled v6 insn: ssat\n");
724 return 0;
726 default:
727 break;
730 if (ror == -1)
732 if (BITS (4, 6) == 0x7)
734 printf ("Unhandled v6 insn: ssat\n");
735 return 0;
737 break;
740 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
741 if (Rm & 0x80)
742 Rm |= 0xffffff00;
744 if (BITS (16, 19) == 0xf)
745 /* SXTB */
746 state->Reg[BITS (12, 15)] = Rm;
747 else
748 /* SXTAB */
749 state->Reg[BITS (12, 15)] += Rm;
751 return 1;
753 case 0x6b:
755 int ror = -1;
757 switch (BITS (4, 11))
759 case 0x07: ror = 0; break;
760 case 0x47: ror = 8; break;
761 case 0x87: ror = 16; break;
762 case 0xc7: ror = 24; break;
764 case 0xf3:
766 /* REV<c> <Rd>,<Rm>
767 instr[31,28] = cond
768 instr[27,20] = 0110 1011
769 instr[19,16] = 1111
770 instr[15,12] = Rd
771 instr[11, 4] = 1111 0011
772 instr[ 3, 0] = Rm. */
773 if (BITS (16, 19) != 0xF)
774 break;
776 Rd = BITS (12, 15);
777 Rm = BITS (0, 3);
778 if (Rd == 15 || Rm == 15)
780 ARMul_UndefInstr (state, instr);
781 state->Emulate = FALSE;
782 break;
785 val = state->Reg[Rm] << 24;
786 val |= ((state->Reg[Rm] << 8) & 0xFF0000);
787 val |= ((state->Reg[Rm] >> 8) & 0xFF00);
788 val |= ((state->Reg[Rm] >> 24));
789 state->Reg[Rd] = val;
790 return 1;
793 case 0xfb:
795 /* REV16<c> <Rd>,<Rm>. */
796 if (BITS (16, 19) != 0xF)
797 break;
799 Rd = BITS (12, 15);
800 Rm = BITS (0, 3);
801 if (Rd == 15 || Rm == 15)
803 ARMul_UndefInstr (state, instr);
804 state->Emulate = FALSE;
805 break;
808 val = 0;
809 val |= ((state->Reg[Rm] >> 8) & 0x00FF00FF);
810 val |= ((state->Reg[Rm] << 8) & 0xFF00FF00);
811 state->Reg[Rd] = val;
812 return 1;
815 default:
816 break;
819 if (ror == -1)
820 break;
822 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
823 if (Rm & 0x8000)
824 Rm |= 0xffff0000;
826 if (BITS (16, 19) == 0xf)
827 /* SXTH */
828 state->Reg[BITS (12, 15)] = Rm;
829 else
830 /* SXTAH */
831 state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
833 return 1;
835 case 0x6e:
837 int ror = -1;
839 switch (BITS (4, 11))
841 case 0x07: ror = 0; break;
842 case 0x47: ror = 8; break;
843 case 0x87: ror = 16; break;
844 case 0xc7: ror = 24; break;
846 case 0x01:
847 case 0xf3:
848 printf ("Unhandled v6 insn: usat\n");
849 return 0;
851 default:
852 break;
855 if (ror == -1)
857 if (BITS (4, 6) == 0x7)
859 printf ("Unhandled v6 insn: usat\n");
860 return 0;
862 break;
865 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
867 if (BITS (16, 19) == 0xf)
868 /* UXTB */
869 state->Reg[BITS (12, 15)] = Rm;
870 else
871 /* UXTAB */
872 state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
874 return 1;
876 case 0x6f:
878 int i;
879 int ror = -1;
881 switch (BITS (4, 11))
883 case 0x07: ror = 0; break;
884 case 0x47: ror = 8; break;
885 case 0x87: ror = 16; break;
886 case 0xc7: ror = 24; break;
888 case 0xf3: /* RBIT */
889 if (BITS (16, 19) != 0xF)
890 break;
891 Rd = BITS (12, 15);
892 state->Reg[Rd] = 0;
893 Rm = state->Reg[BITS (0, 3)];
894 for (i = 0; i < 32; i++)
895 if (Rm & (1 << i))
896 state->Reg[Rd] |= (1 << (31 - i));
897 return 1;
899 case 0xfb:
900 printf ("Unhandled v6 insn: revsh\n");
901 return 0;
903 default:
904 break;
907 if (ror == -1)
908 break;
910 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
912 if (BITS (16, 19) == 0xf)
913 /* UXT */
914 state->Reg[BITS (12, 15)] = Rm;
915 else
916 /* UXTAH */
917 state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm;
919 return 1;
921 case 0x71:
922 case 0x73:
924 ARMword valn, valm;
925 /* SDIV<c> <Rd>,<Rn>,<Rm>
926 UDIV<c> <Rd>,<Rn>,<Rm>
927 instr[31,28] = cond
928 instr[27,20] = 0111 0001 (SDIV), 0111 0011 (UDIV)
929 instr[21,21] = sign
930 instr[19,16] = Rn
931 instr[15,12] = 1111
932 instr[11, 8] = Rd
933 instr[ 7, 4] = 1111
934 instr[ 3, 0] = Rm */
935 /* These bit-positions are confusing!
936 instr[15,12] = Rd
937 instr[11, 8] = 1111 */
939 #if 0 /* This is what I would expect: */
940 Rn = BITS (16, 19);
941 Rd = BITS (8, 11);
942 Rm = BITS (0, 3);
943 #else /* This seem to work: */
944 Rd = BITS (16, 19);
945 Rm = BITS (8, 11);
946 Rn = BITS (0, 3);
947 #endif
948 if (Rn == 15 || Rd == 15 || Rm == 15
949 || Rn == 13 || Rd == 13 || Rm == 13)
951 ARMul_UndefInstr (state, instr);
952 state->Emulate = FALSE;
953 break;
956 valn = state->Reg[Rn];
957 valm = state->Reg[Rm];
959 if (valm == 0)
961 #if 0
962 /* Exceptions: UsageFault, address 20
963 Note: UsageFault is for Cortex-M; I don't know what it would be on non-Cortex-M. */
964 ARMul_Abort (state, address);
965 #endif
966 printf ("Unhandled v6 insn: %cDIV divide by zero exception\n", "SU"[BIT(21)]);
968 else
970 if(BIT(21))
972 val = valn / valm;
974 else
976 val = ((ARMsword)valn / (ARMsword)valm);
978 state->Reg[Rd] = val;
980 return 1;
983 case 0x7c:
984 case 0x7d:
986 int lsb;
987 int msb;
988 ARMword mask;
990 /* BFC<c> <Rd>,#<lsb>,#<width>
991 BFI<c> <Rd>,<Rn>,#<lsb>,#<width>
993 instr[31,28] = cond
994 instr[27,21] = 0111 110
995 instr[20,16] = msb
996 instr[15,12] = Rd
997 instr[11, 7] = lsb
998 instr[ 6, 4] = 001 1111
999 instr[ 3, 0] = Rn (BFI) / 1111 (BFC). */
1001 if (BITS (4, 6) != 0x1)
1002 break;
1004 Rd = BITS (12, 15);
1005 if (Rd == 15)
1007 ARMul_UndefInstr (state, instr);
1008 state->Emulate = FALSE;
1011 lsb = BITS (7, 11);
1012 msb = BITS (16, 20);
1013 if (lsb > msb)
1015 ARMul_UndefInstr (state, instr);
1016 state->Emulate = FALSE;
1019 mask = -(1 << lsb);
1020 mask &= ~(-(1 << (msb + 1)));
1021 state->Reg[Rd] &= ~ mask;
1023 Rn = BITS (0, 3);
1024 if (Rn != 0xF)
1026 val = state->Reg[Rn] & ~(-(1 << ((msb + 1) - lsb)));
1027 state->Reg[Rd] |= val << lsb;
1029 return 1;
1031 case 0x7b:
1032 case 0x7a: /* SBFX<c> <Rd>,<Rn>,#<lsb>,#<width>. */
1034 int lsb;
1035 int widthm1;
1036 ARMsword sval;
1038 if (BITS (4, 6) != 0x5)
1039 break;
1041 Rd = BITS (12, 15);
1042 if (Rd == 15)
1044 ARMul_UndefInstr (state, instr);
1045 state->Emulate = FALSE;
1048 Rn = BITS (0, 3);
1049 if (Rn == 15)
1051 ARMul_UndefInstr (state, instr);
1052 state->Emulate = FALSE;
1055 lsb = BITS (7, 11);
1056 widthm1 = BITS (16, 20);
1058 sval = state->Reg[Rn];
1059 sval <<= (31 - (lsb + widthm1));
1060 sval >>= (31 - widthm1);
1061 state->Reg[Rd] = sval;
1063 return 1;
1066 case 0x7f:
1067 case 0x7e:
1069 int lsb;
1070 int widthm1;
1072 /* UBFX<c> <Rd>,<Rn>,#<lsb>,#<width>
1073 instr[31,28] = cond
1074 instr[27,21] = 0111 111
1075 instr[20,16] = widthm1
1076 instr[15,12] = Rd
1077 instr[11, 7] = lsb
1078 instr[ 6, 4] = 101
1079 instr[ 3, 0] = Rn. */
1081 if (BITS (4, 6) != 0x5)
1082 break;
1084 Rd = BITS (12, 15);
1085 if (Rd == 15)
1087 ARMul_UndefInstr (state, instr);
1088 state->Emulate = FALSE;
1091 Rn = BITS (0, 3);
1092 if (Rn == 15)
1094 ARMul_UndefInstr (state, instr);
1095 state->Emulate = FALSE;
1098 lsb = BITS (7, 11);
1099 widthm1 = BITS (16, 20);
1101 val = state->Reg[Rn];
1102 val >>= lsb;
1103 val &= ~(-(1 << (widthm1 + 1)));
1105 state->Reg[Rd] = val;
1107 return 1;
1109 #if 0
1110 case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
1111 #endif
1112 default:
1113 break;
1115 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr);
1116 return 0;
1118 #endif
1120 static void
1121 handle_VFP_move (ARMul_State * state, ARMword instr)
1123 switch (BITS (20, 27))
1125 case 0xC4:
1126 case 0xC5:
1127 switch (BITS (4, 11))
1129 case 0xA1:
1130 case 0xA3:
1132 /* VMOV two core <-> two VFP single precision. */
1133 int sreg = (BITS (0, 3) << 1) | BIT (5);
1135 if (BIT (20))
1137 state->Reg[BITS (12, 15)] = VFP_uword (sreg);
1138 state->Reg[BITS (16, 19)] = VFP_uword (sreg + 1);
1140 else
1142 VFP_uword (sreg) = state->Reg[BITS (12, 15)];
1143 VFP_uword (sreg + 1) = state->Reg[BITS (16, 19)];
1146 break;
1148 case 0xB1:
1149 case 0xB3:
1151 /* VMOV two core <-> VFP double precision. */
1152 int dreg = BITS (0, 3) | (BIT (5) << 4);
1154 if (BIT (20))
1156 if (trace)
1157 fprintf (stderr, " VFP: VMOV: r%d r%d <= d%d\n",
1158 BITS (12, 15), BITS (16, 19), dreg);
1160 state->Reg[BITS (12, 15)] = VFP_dword (dreg);
1161 state->Reg[BITS (16, 19)] = VFP_dword (dreg) >> 32;
1163 else
1165 VFP_dword (dreg) = state->Reg[BITS (16, 19)];
1166 VFP_dword (dreg) <<= 32;
1167 VFP_dword (dreg) |= state->Reg[BITS (12, 15)];
1169 if (trace)
1170 fprintf (stderr, " VFP: VMOV: d%d <= r%d r%d : %g\n",
1171 dreg, BITS (16, 19), BITS (12, 15),
1172 VFP_dval (dreg));
1175 break;
1177 default:
1178 fprintf (stderr, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1179 break;
1181 break;
1183 case 0xe0:
1184 case 0xe1:
1185 /* VMOV single core <-> VFP single precision. */
1186 if (BITS (0, 6) != 0x10 || BITS (8, 11) != 0xA)
1187 fprintf (stderr, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1188 else
1190 int sreg = (BITS (16, 19) << 1) | BIT (7);
1192 if (BIT (20))
1193 state->Reg[DESTReg] = VFP_uword (sreg);
1194 else
1195 VFP_uword (sreg) = state->Reg[DESTReg];
1197 break;
1199 default:
1200 fprintf (stderr, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1201 return;
1205 /* EMULATION of ARM6. */
1207 ARMword
1208 #ifdef MODE32
1209 ARMul_Emulate32 (ARMul_State * state)
1210 #else
1211 ARMul_Emulate26 (ARMul_State * state)
1212 #endif
1214 ARMword instr; /* The current instruction. */
1215 ARMword dest = 0; /* Almost the DestBus. */
1216 ARMword temp; /* Ubiquitous third hand. */
1217 ARMword pc = 0; /* The address of the current instruction. */
1218 ARMword lhs; /* Almost the ABus and BBus. */
1219 ARMword rhs;
1220 ARMword decoded = 0; /* Instruction pipeline. */
1221 ARMword loaded = 0;
1223 /* Execute the next instruction. */
1225 if (state->NextInstr < PRIMEPIPE)
1227 decoded = state->decoded;
1228 loaded = state->loaded;
1229 pc = state->pc;
1234 /* Just keep going. */
1235 isize = INSN_SIZE;
1237 switch (state->NextInstr)
1239 case SEQ:
1240 /* Advance the pipeline, and an S cycle. */
1241 state->Reg[15] += isize;
1242 pc += isize;
1243 instr = decoded;
1244 decoded = loaded;
1245 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
1246 break;
1248 case NONSEQ:
1249 /* Advance the pipeline, and an N cycle. */
1250 state->Reg[15] += isize;
1251 pc += isize;
1252 instr = decoded;
1253 decoded = loaded;
1254 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
1255 NORMALCYCLE;
1256 break;
1258 case PCINCEDSEQ:
1259 /* Program counter advanced, and an S cycle. */
1260 pc += isize;
1261 instr = decoded;
1262 decoded = loaded;
1263 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
1264 NORMALCYCLE;
1265 break;
1267 case PCINCEDNONSEQ:
1268 /* Program counter advanced, and an N cycle. */
1269 pc += isize;
1270 instr = decoded;
1271 decoded = loaded;
1272 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
1273 NORMALCYCLE;
1274 break;
1276 case RESUME:
1277 /* The program counter has been changed. */
1278 pc = state->Reg[15];
1279 #ifndef MODE32
1280 pc = pc & R15PCBITS;
1281 #endif
1282 state->Reg[15] = pc + (isize * 2);
1283 state->Aborted = 0;
1284 instr = ARMul_ReLoadInstr (state, pc, isize);
1285 decoded = ARMul_ReLoadInstr (state, pc + isize, isize);
1286 loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize);
1287 NORMALCYCLE;
1288 break;
1290 default:
1291 /* The program counter has been changed. */
1292 pc = state->Reg[15];
1293 #ifndef MODE32
1294 pc = pc & R15PCBITS;
1295 #endif
1296 state->Reg[15] = pc + (isize * 2);
1297 state->Aborted = 0;
1298 instr = ARMul_LoadInstrN (state, pc, isize);
1299 decoded = ARMul_LoadInstrS (state, pc + (isize), isize);
1300 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
1301 NORMALCYCLE;
1302 break;
1305 if (state->EventSet)
1306 ARMul_EnvokeEvent (state);
1308 if (! TFLAG && trace)
1310 fprintf (stderr, "pc: %x, ", pc & ~1);
1311 if (! disas)
1312 fprintf (stderr, "instr: %x\n", instr);
1315 if (instr == 0 || pc < 0x10)
1317 ARMul_Abort (state, ARMUndefinedInstrV);
1318 state->Emulate = FALSE;
1321 #if 0 /* Enable this code to help track down stack alignment bugs. */
1323 static ARMword old_sp = -1;
1325 if (old_sp != state->Reg[13])
1327 old_sp = state->Reg[13];
1328 fprintf (stderr, "pc: %08x: SP set to %08x%s\n",
1329 pc & ~1, old_sp, (old_sp % 8) ? " [UNALIGNED!]" : "");
1332 #endif
1334 if (state->Exception)
1336 /* Any exceptions ? */
1337 if (state->NresetSig == LOW)
1339 ARMul_Abort (state, ARMul_ResetV);
1340 break;
1342 else if (!state->NfiqSig && !FFLAG)
1344 ARMul_Abort (state, ARMul_FIQV);
1345 break;
1347 else if (!state->NirqSig && !IFLAG)
1349 ARMul_Abort (state, ARMul_IRQV);
1350 break;
1354 if (state->CallDebug > 0)
1356 if (state->Emulate < ONCE)
1358 state->NextInstr = RESUME;
1359 break;
1361 if (state->Debug)
1363 fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n",
1364 (long) pc, (long) instr, (long) state->Mode);
1365 (void) fgetc (stdin);
1368 else if (state->Emulate < ONCE)
1370 state->NextInstr = RESUME;
1371 break;
1374 state->NumInstrs++;
1376 #ifdef MODET
1377 /* Provide Thumb instruction decoding. If the processor is in Thumb
1378 mode, then we can simply decode the Thumb instruction, and map it
1379 to the corresponding ARM instruction (by directly loading the
1380 instr variable, and letting the normal ARM simulator
1381 execute). There are some caveats to ensure that the correct
1382 pipelined PC value is used when executing Thumb code, and also for
1383 dealing with the BL instruction. */
1384 if (TFLAG)
1386 ARMword new;
1388 /* Check if in Thumb mode. */
1389 switch (ARMul_ThumbDecode (state, pc, instr, &new))
1391 case t_undefined:
1392 /* This is a Thumb instruction. */
1393 ARMul_UndefInstr (state, instr);
1394 goto donext;
1396 case t_branch:
1397 /* Already processed. */
1398 goto donext;
1400 case t_decoded:
1401 /* ARM instruction available. */
1402 if (disas || trace)
1404 fprintf (stderr, " emulate as: ");
1405 if (trace)
1406 fprintf (stderr, "%08x ", new);
1407 if (! disas)
1408 fprintf (stderr, "\n");
1410 instr = new;
1411 /* So continue instruction decoding. */
1412 break;
1413 default:
1414 break;
1417 #endif
1418 if (disas)
1419 print_insn (instr);
1421 /* Check the condition codes. */
1422 if ((temp = TOPBITS (28)) == AL)
1423 /* Vile deed in the need for speed. */
1424 goto mainswitch;
1426 /* Check the condition code. */
1427 switch ((int) TOPBITS (28))
1429 case AL:
1430 temp = TRUE;
1431 break;
1432 case NV:
1433 if (state->is_v5)
1435 if (BITS (25, 27) == 5) /* BLX(1) */
1437 state->Reg[14] = pc + 4;
1439 /* Force entry into Thumb mode. */
1440 dest = pc + 8 + 1;
1441 if (BIT (23))
1442 dest += (NEGBRANCH + (BIT (24) << 1));
1443 else
1444 dest += POSBRANCH + (BIT (24) << 1);
1446 WriteR15Branch (state, dest);
1447 goto donext;
1449 else if ((instr & 0xFC70F000) == 0xF450F000)
1450 /* The PLD instruction. Ignored. */
1451 goto donext;
1452 else if ( ((instr & 0xfe500f00) == 0xfc100100)
1453 || ((instr & 0xfe500f00) == 0xfc000100))
1454 /* wldrw and wstrw are unconditional. */
1455 goto mainswitch;
1456 else
1457 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
1458 ARMul_UndefInstr (state, instr);
1460 temp = FALSE;
1461 break;
1462 case EQ:
1463 temp = ZFLAG;
1464 break;
1465 case NE:
1466 temp = !ZFLAG;
1467 break;
1468 case VS:
1469 temp = VFLAG;
1470 break;
1471 case VC:
1472 temp = !VFLAG;
1473 break;
1474 case MI:
1475 temp = NFLAG;
1476 break;
1477 case PL:
1478 temp = !NFLAG;
1479 break;
1480 case CS:
1481 temp = CFLAG;
1482 break;
1483 case CC:
1484 temp = !CFLAG;
1485 break;
1486 case HI:
1487 temp = (CFLAG && !ZFLAG);
1488 break;
1489 case LS:
1490 temp = (!CFLAG || ZFLAG);
1491 break;
1492 case GE:
1493 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
1494 break;
1495 case LT:
1496 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
1497 break;
1498 case GT:
1499 temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
1500 break;
1501 case LE:
1502 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
1503 break;
1504 } /* cc check */
1506 /* Handle the Clock counter here. */
1507 if (state->is_XScale)
1509 ARMword cp14r0;
1510 int ok;
1512 ok = state->CPRead[14] (state, 0, & cp14r0);
1514 if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE))
1516 unsigned long newcycles, nowtime = ARMul_Time (state);
1518 newcycles = nowtime - state->LastTime;
1519 state->LastTime = nowtime;
1521 if (cp14r0 & ARMul_CP14_R0_CCD)
1523 if (state->CP14R0_CCD == -1)
1524 state->CP14R0_CCD = newcycles;
1525 else
1526 state->CP14R0_CCD += newcycles;
1528 if (state->CP14R0_CCD >= 64)
1530 newcycles = 0;
1532 while (state->CP14R0_CCD >= 64)
1533 state->CP14R0_CCD -= 64, newcycles++;
1535 goto check_PMUintr;
1538 else
1540 ARMword cp14r1;
1541 int do_int;
1543 state->CP14R0_CCD = -1;
1544 check_PMUintr:
1545 do_int = 0;
1546 cp14r0 |= ARMul_CP14_R0_FLAG2;
1547 (void) state->CPWrite[14] (state, 0, cp14r0);
1549 ok = state->CPRead[14] (state, 1, & cp14r1);
1551 /* Coded like this for portability. */
1552 while (ok && newcycles)
1554 if (cp14r1 == 0xffffffff)
1556 cp14r1 = 0;
1557 do_int = 1;
1559 else
1560 cp14r1 ++;
1562 newcycles --;
1565 (void) state->CPWrite[14] (state, 1, cp14r1);
1567 if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2))
1569 ARMword cp;
1571 if (state->CPRead[13] (state, 8, & cp)
1572 && (cp & ARMul_CP13_R8_PMUS))
1573 ARMul_Abort (state, ARMul_FIQV);
1574 else
1575 ARMul_Abort (state, ARMul_IRQV);
1581 /* Handle hardware instructions breakpoints here. */
1582 if (state->is_XScale)
1584 if ( (pc | 3) == (read_cp15_reg (14, 0, 8) | 2)
1585 || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2))
1587 if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB))
1588 ARMul_OSHandleSWI (state, SWI_Breakpoint);
1592 /* Actual execution of instructions begins here. */
1593 /* If the condition codes don't match, stop here. */
1594 if (temp)
1596 mainswitch:
1598 if (state->is_XScale)
1600 if (BIT (20) == 0 && BITS (25, 27) == 0)
1602 if (BITS (4, 7) == 0xD)
1604 /* XScale Load Consecutive insn. */
1605 ARMword temp1 = GetLS7RHS (state, instr);
1606 ARMword temp2 = BIT (23) ? LHS + temp1 : LHS - temp1;
1607 ARMword addr = BIT (24) ? temp2 : LHS;
1609 if (BIT (12))
1610 ARMul_UndefInstr (state, instr);
1611 else if (addr & 7)
1612 /* Alignment violation. */
1613 ARMul_Abort (state, ARMul_DataAbortV);
1614 else
1616 int wb = BIT (21) || (! BIT (24));
1618 state->Reg[BITS (12, 15)] =
1619 ARMul_LoadWordN (state, addr);
1620 state->Reg[BITS (12, 15) + 1] =
1621 ARMul_LoadWordN (state, addr + 4);
1622 if (wb)
1623 LSBase = temp2;
1626 goto donext;
1628 else if (BITS (4, 7) == 0xF)
1630 /* XScale Store Consecutive insn. */
1631 ARMword temp1 = GetLS7RHS (state, instr);
1632 ARMword temp2 = BIT (23) ? LHS + temp1 : LHS - temp1;
1633 ARMword addr = BIT (24) ? temp2 : LHS;
1635 if (BIT (12))
1636 ARMul_UndefInstr (state, instr);
1637 else if (addr & 7)
1638 /* Alignment violation. */
1639 ARMul_Abort (state, ARMul_DataAbortV);
1640 else
1642 ARMul_StoreWordN (state, addr,
1643 state->Reg[BITS (12, 15)]);
1644 ARMul_StoreWordN (state, addr + 4,
1645 state->Reg[BITS (12, 15) + 1]);
1647 if (BIT (21)|| ! BIT (24))
1648 LSBase = temp2;
1651 goto donext;
1655 if (ARMul_HandleIwmmxt (state, instr))
1656 goto donext;
1659 switch ((int) BITS (20, 27))
1661 /* Data Processing Register RHS Instructions. */
1663 case 0x00: /* AND reg and MUL */
1664 #ifdef MODET
1665 if (BITS (4, 11) == 0xB)
1667 /* STRH register offset, no write-back, down, post indexed. */
1668 SHDOWNWB ();
1669 break;
1671 if (BITS (4, 7) == 0xD)
1673 Handle_Load_Double (state, instr);
1674 break;
1676 if (BITS (4, 7) == 0xF)
1678 Handle_Store_Double (state, instr);
1679 break;
1681 #endif
1682 if (BITS (4, 7) == 9)
1684 /* MUL */
1685 rhs = state->Reg[MULRHSReg];
1686 if (MULLHSReg == MULDESTReg)
1688 UNDEF_MULDestEQOp1;
1689 state->Reg[MULDESTReg] = 0;
1691 else if (MULDESTReg != 15)
1692 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
1693 else
1694 UNDEF_MULPCDest;
1696 for (dest = 0, temp = 0; dest < 32; dest ++)
1697 if (rhs & (1L << dest))
1698 temp = dest;
1700 /* Mult takes this many/2 I cycles. */
1701 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
1703 else
1705 /* AND reg. */
1706 rhs = DPRegRHS;
1707 dest = LHS & rhs;
1708 WRITEDEST (dest);
1710 break;
1712 case 0x01: /* ANDS reg and MULS */
1713 #ifdef MODET
1714 if ((BITS (4, 11) & 0xF9) == 0x9)
1715 /* LDR register offset, no write-back, down, post indexed. */
1716 LHPOSTDOWN ();
1717 /* Fall through to rest of decoding. */
1718 #endif
1719 if (BITS (4, 7) == 9)
1721 /* MULS */
1722 rhs = state->Reg[MULRHSReg];
1724 if (MULLHSReg == MULDESTReg)
1726 UNDEF_MULDestEQOp1;
1727 state->Reg[MULDESTReg] = 0;
1728 CLEARN;
1729 SETZ;
1731 else if (MULDESTReg != 15)
1733 dest = state->Reg[MULLHSReg] * rhs;
1734 ARMul_NegZero (state, dest);
1735 state->Reg[MULDESTReg] = dest;
1737 else
1738 UNDEF_MULPCDest;
1740 for (dest = 0, temp = 0; dest < 32; dest ++)
1741 if (rhs & (1L << dest))
1742 temp = dest;
1744 /* Mult takes this many/2 I cycles. */
1745 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
1747 else
1749 /* ANDS reg. */
1750 rhs = DPSRegRHS;
1751 dest = LHS & rhs;
1752 WRITESDEST (dest);
1754 break;
1756 case 0x02: /* EOR reg and MLA */
1757 #ifdef MODET
1758 if (BITS (4, 11) == 0xB)
1760 /* STRH register offset, write-back, down, post indexed. */
1761 SHDOWNWB ();
1762 break;
1764 #endif
1765 if (BITS (4, 7) == 9)
1766 { /* MLA */
1767 rhs = state->Reg[MULRHSReg];
1768 if (MULLHSReg == MULDESTReg)
1770 UNDEF_MULDestEQOp1;
1771 state->Reg[MULDESTReg] = state->Reg[MULACCReg];
1773 else if (MULDESTReg != 15)
1774 state->Reg[MULDESTReg] =
1775 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
1776 else
1777 UNDEF_MULPCDest;
1779 for (dest = 0, temp = 0; dest < 32; dest ++)
1780 if (rhs & (1L << dest))
1781 temp = dest;
1783 /* Mult takes this many/2 I cycles. */
1784 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
1786 else
1788 rhs = DPRegRHS;
1789 dest = LHS ^ rhs;
1790 WRITEDEST (dest);
1792 break;
1794 case 0x03: /* EORS reg and MLAS */
1795 #ifdef MODET
1796 if ((BITS (4, 11) & 0xF9) == 0x9)
1797 /* LDR register offset, write-back, down, post-indexed. */
1798 LHPOSTDOWN ();
1799 /* Fall through to rest of the decoding. */
1800 #endif
1801 if (BITS (4, 7) == 9)
1803 /* MLAS */
1804 rhs = state->Reg[MULRHSReg];
1806 if (MULLHSReg == MULDESTReg)
1808 UNDEF_MULDestEQOp1;
1809 dest = state->Reg[MULACCReg];
1810 ARMul_NegZero (state, dest);
1811 state->Reg[MULDESTReg] = dest;
1813 else if (MULDESTReg != 15)
1815 dest =
1816 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
1817 ARMul_NegZero (state, dest);
1818 state->Reg[MULDESTReg] = dest;
1820 else
1821 UNDEF_MULPCDest;
1823 for (dest = 0, temp = 0; dest < 32; dest ++)
1824 if (rhs & (1L << dest))
1825 temp = dest;
1827 /* Mult takes this many/2 I cycles. */
1828 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
1830 else
1832 /* EORS Reg. */
1833 rhs = DPSRegRHS;
1834 dest = LHS ^ rhs;
1835 WRITESDEST (dest);
1837 break;
1839 case 0x04: /* SUB reg */
1840 #ifdef MODET
1841 if (BITS (4, 7) == 0xB)
1843 /* STRH immediate offset, no write-back, down, post indexed. */
1844 SHDOWNWB ();
1845 break;
1847 if (BITS (4, 7) == 0xD)
1849 Handle_Load_Double (state, instr);
1850 break;
1852 if (BITS (4, 7) == 0xF)
1854 Handle_Store_Double (state, instr);
1855 break;
1857 #endif
1858 rhs = DPRegRHS;
1859 dest = LHS - rhs;
1860 WRITEDEST (dest);
1861 break;
1863 case 0x05: /* SUBS reg */
1864 #ifdef MODET
1865 if ((BITS (4, 7) & 0x9) == 0x9)
1866 /* LDR immediate offset, no write-back, down, post indexed. */
1867 LHPOSTDOWN ();
1868 /* Fall through to the rest of the instruction decoding. */
1869 #endif
1870 lhs = LHS;
1871 rhs = DPRegRHS;
1872 dest = lhs - rhs;
1874 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1876 ARMul_SubCarry (state, lhs, rhs, dest);
1877 ARMul_SubOverflow (state, lhs, rhs, dest);
1879 else
1881 CLEARC;
1882 CLEARV;
1884 WRITESDEST (dest);
1885 break;
1887 case 0x06: /* RSB reg */
1888 #ifdef MODET
1889 if (BITS (4, 7) == 0xB)
1891 /* STRH immediate offset, write-back, down, post indexed. */
1892 SHDOWNWB ();
1893 break;
1895 #endif
1896 rhs = DPRegRHS;
1897 dest = rhs - LHS;
1898 WRITEDEST (dest);
1899 break;
1901 case 0x07: /* RSBS reg */
1902 #ifdef MODET
1903 if ((BITS (4, 7) & 0x9) == 0x9)
1904 /* LDR immediate offset, write-back, down, post indexed. */
1905 LHPOSTDOWN ();
1906 /* Fall through to remainder of instruction decoding. */
1907 #endif
1908 lhs = LHS;
1909 rhs = DPRegRHS;
1910 dest = rhs - lhs;
1912 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1914 ARMul_SubCarry (state, rhs, lhs, dest);
1915 ARMul_SubOverflow (state, rhs, lhs, dest);
1917 else
1919 CLEARC;
1920 CLEARV;
1922 WRITESDEST (dest);
1923 break;
1925 case 0x08: /* ADD reg */
1926 #ifdef MODET
1927 if (BITS (4, 11) == 0xB)
1929 /* STRH register offset, no write-back, up, post indexed. */
1930 SHUPWB ();
1931 break;
1933 if (BITS (4, 7) == 0xD)
1935 Handle_Load_Double (state, instr);
1936 break;
1938 if (BITS (4, 7) == 0xF)
1940 Handle_Store_Double (state, instr);
1941 break;
1943 #endif
1944 #ifdef MODET
1945 if (BITS (4, 7) == 0x9)
1947 /* MULL */
1948 /* 32x32 = 64 */
1949 ARMul_Icycles (state,
1950 Multiply64 (state, instr, LUNSIGNED,
1951 LDEFAULT), 0L);
1952 break;
1954 #endif
1955 rhs = DPRegRHS;
1956 dest = LHS + rhs;
1957 WRITEDEST (dest);
1958 break;
1960 case 0x09: /* ADDS reg */
1961 #ifdef MODET
1962 if ((BITS (4, 11) & 0xF9) == 0x9)
1963 /* LDR register offset, no write-back, up, post indexed. */
1964 LHPOSTUP ();
1965 /* Fall through to remaining instruction decoding. */
1966 #endif
1967 #ifdef MODET
1968 if (BITS (4, 7) == 0x9)
1970 /* MULL */
1971 /* 32x32=64 */
1972 ARMul_Icycles (state,
1973 Multiply64 (state, instr, LUNSIGNED, LSCC),
1974 0L);
1975 break;
1977 #endif
1978 lhs = LHS;
1979 rhs = DPRegRHS;
1980 dest = lhs + rhs;
1981 ASSIGNZ (dest == 0);
1982 if ((lhs | rhs) >> 30)
1984 /* Possible C,V,N to set. */
1985 ASSIGNN (NEG (dest));
1986 ARMul_AddCarry (state, lhs, rhs, dest);
1987 ARMul_AddOverflow (state, lhs, rhs, dest);
1989 else
1991 CLEARN;
1992 CLEARC;
1993 CLEARV;
1995 WRITESDEST (dest);
1996 break;
1998 case 0x0a: /* ADC reg */
1999 #ifdef MODET
2000 if (BITS (4, 11) == 0xB)
2002 /* STRH register offset, write-back, up, post-indexed. */
2003 SHUPWB ();
2004 break;
2006 if (BITS (4, 7) == 0x9)
2008 /* MULL */
2009 /* 32x32=64 */
2010 ARMul_Icycles (state,
2011 MultiplyAdd64 (state, instr, LUNSIGNED,
2012 LDEFAULT), 0L);
2013 break;
2015 #endif
2016 rhs = DPRegRHS;
2017 dest = LHS + rhs + CFLAG;
2018 WRITEDEST (dest);
2019 break;
2021 case 0x0b: /* ADCS reg */
2022 #ifdef MODET
2023 if ((BITS (4, 11) & 0xF9) == 0x9)
2024 /* LDR register offset, write-back, up, post indexed. */
2025 LHPOSTUP ();
2026 /* Fall through to remaining instruction decoding. */
2027 if (BITS (4, 7) == 0x9)
2029 /* MULL */
2030 /* 32x32=64 */
2031 ARMul_Icycles (state,
2032 MultiplyAdd64 (state, instr, LUNSIGNED,
2033 LSCC), 0L);
2034 break;
2036 #endif
2037 lhs = LHS;
2038 rhs = DPRegRHS;
2039 dest = lhs + rhs + CFLAG;
2040 ASSIGNZ (dest == 0);
2041 if ((lhs | rhs) >> 30)
2043 /* Possible C,V,N to set. */
2044 ASSIGNN (NEG (dest));
2045 ARMul_AddCarry (state, lhs, rhs, dest);
2046 ARMul_AddOverflow (state, lhs, rhs, dest);
2048 else
2050 CLEARN;
2051 CLEARC;
2052 CLEARV;
2054 WRITESDEST (dest);
2055 break;
2057 case 0x0c: /* SBC reg */
2058 #ifdef MODET
2059 if (BITS (4, 7) == 0xB)
2061 /* STRH immediate offset, no write-back, up post indexed. */
2062 SHUPWB ();
2063 break;
2065 if (BITS (4, 7) == 0xD)
2067 Handle_Load_Double (state, instr);
2068 break;
2070 if (BITS (4, 7) == 0xF)
2072 Handle_Store_Double (state, instr);
2073 break;
2075 if (BITS (4, 7) == 0x9)
2077 /* MULL */
2078 /* 32x32=64 */
2079 ARMul_Icycles (state,
2080 Multiply64 (state, instr, LSIGNED, LDEFAULT),
2081 0L);
2082 break;
2084 #endif
2085 rhs = DPRegRHS;
2086 dest = LHS - rhs - !CFLAG;
2087 WRITEDEST (dest);
2088 break;
2090 case 0x0d: /* SBCS reg */
2091 #ifdef MODET
2092 if ((BITS (4, 7) & 0x9) == 0x9)
2093 /* LDR immediate offset, no write-back, up, post indexed. */
2094 LHPOSTUP ();
2096 if (BITS (4, 7) == 0x9)
2098 /* MULL */
2099 /* 32x32=64 */
2100 ARMul_Icycles (state,
2101 Multiply64 (state, instr, LSIGNED, LSCC),
2102 0L);
2103 break;
2105 #endif
2106 lhs = LHS;
2107 rhs = DPRegRHS;
2108 dest = lhs - rhs - !CFLAG;
2109 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2111 ARMul_SubCarry (state, lhs, rhs, dest);
2112 ARMul_SubOverflow (state, lhs, rhs, dest);
2114 else
2116 CLEARC;
2117 CLEARV;
2119 WRITESDEST (dest);
2120 break;
2122 case 0x0e: /* RSC reg */
2123 #ifdef MODET
2124 if (BITS (4, 7) == 0xB)
2126 /* STRH immediate offset, write-back, up, post indexed. */
2127 SHUPWB ();
2128 break;
2131 if (BITS (4, 7) == 0x9)
2133 /* MULL */
2134 /* 32x32=64 */
2135 ARMul_Icycles (state,
2136 MultiplyAdd64 (state, instr, LSIGNED,
2137 LDEFAULT), 0L);
2138 break;
2140 #endif
2141 rhs = DPRegRHS;
2142 dest = rhs - LHS - !CFLAG;
2143 WRITEDEST (dest);
2144 break;
2146 case 0x0f: /* RSCS reg */
2147 #ifdef MODET
2148 if ((BITS (4, 7) & 0x9) == 0x9)
2149 /* LDR immediate offset, write-back, up, post indexed. */
2150 LHPOSTUP ();
2151 /* Fall through to remaining instruction decoding. */
2153 if (BITS (4, 7) == 0x9)
2155 /* MULL */
2156 /* 32x32=64 */
2157 ARMul_Icycles (state,
2158 MultiplyAdd64 (state, instr, LSIGNED, LSCC),
2159 0L);
2160 break;
2162 #endif
2163 lhs = LHS;
2164 rhs = DPRegRHS;
2165 dest = rhs - lhs - !CFLAG;
2167 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
2169 ARMul_SubCarry (state, rhs, lhs, dest);
2170 ARMul_SubOverflow (state, rhs, lhs, dest);
2172 else
2174 CLEARC;
2175 CLEARV;
2177 WRITESDEST (dest);
2178 break;
2180 case 0x10: /* TST reg and MRS CPSR and SWP word. */
2181 if (state->is_v5e)
2183 if (BIT (4) == 0 && BIT (7) == 1)
2185 /* ElSegundo SMLAxy insn. */
2186 ARMword op1 = state->Reg[BITS (0, 3)];
2187 ARMword op2 = state->Reg[BITS (8, 11)];
2188 ARMword Rn = state->Reg[BITS (12, 15)];
2190 if (BIT (5))
2191 op1 >>= 16;
2192 if (BIT (6))
2193 op2 >>= 16;
2194 op1 &= 0xFFFF;
2195 op2 &= 0xFFFF;
2196 if (op1 & 0x8000)
2197 op1 -= 65536;
2198 if (op2 & 0x8000)
2199 op2 -= 65536;
2200 op1 *= op2;
2202 if (AddOverflow (op1, Rn, op1 + Rn))
2203 SETS;
2204 state->Reg[BITS (16, 19)] = op1 + Rn;
2205 break;
2208 if (BITS (4, 11) == 5)
2210 /* ElSegundo QADD insn. */
2211 ARMword op1 = state->Reg[BITS (0, 3)];
2212 ARMword op2 = state->Reg[BITS (16, 19)];
2213 ARMword result = op1 + op2;
2214 if (AddOverflow (op1, op2, result))
2216 result = POS (result) ? 0x80000000 : 0x7fffffff;
2217 SETS;
2219 state->Reg[BITS (12, 15)] = result;
2220 break;
2223 #ifdef MODET
2224 if (BITS (4, 11) == 0xB)
2226 /* STRH register offset, no write-back, down, pre indexed. */
2227 SHPREDOWN ();
2228 break;
2230 if (BITS (4, 7) == 0xD)
2232 Handle_Load_Double (state, instr);
2233 break;
2235 if (BITS (4, 7) == 0xF)
2237 Handle_Store_Double (state, instr);
2238 break;
2240 #endif
2241 if (BITS (4, 11) == 9)
2243 /* SWP */
2244 UNDEF_SWPPC;
2245 temp = LHS;
2246 BUSUSEDINCPCS;
2247 #ifndef MODE32
2248 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
2250 INTERNALABORT (temp);
2251 (void) ARMul_LoadWordN (state, temp);
2252 (void) ARMul_LoadWordN (state, temp);
2254 else
2255 #endif
2256 dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
2257 if (temp & 3)
2258 DEST = ARMul_Align (state, temp, dest);
2259 else
2260 DEST = dest;
2261 if (state->abortSig || state->Aborted)
2262 TAKEABORT;
2264 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
2265 { /* MRS CPSR */
2266 UNDEF_MRSPC;
2267 DEST = ECC | EINT | EMODE;
2269 else
2271 #ifdef MODE32
2272 if (state->is_v6
2273 && handle_v6_insn (state, instr))
2274 break;
2275 #endif
2276 UNDEF_Test;
2278 break;
2280 case 0x11: /* TSTP reg */
2281 #ifdef MODET
2282 if ((BITS (4, 11) & 0xF9) == 0x9)
2283 /* LDR register offset, no write-back, down, pre indexed. */
2284 LHPREDOWN ();
2285 /* Continue with remaining instruction decode. */
2286 #endif
2287 if (DESTReg == 15)
2289 /* TSTP reg */
2290 #ifdef MODE32
2291 state->Cpsr = GETSPSR (state->Bank);
2292 ARMul_CPSRAltered (state);
2293 #else
2294 rhs = DPRegRHS;
2295 temp = LHS & rhs;
2296 SETR15PSR (temp);
2297 #endif
2299 else
2301 /* TST reg */
2302 rhs = DPSRegRHS;
2303 dest = LHS & rhs;
2304 ARMul_NegZero (state, dest);
2306 break;
2308 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
2309 if (state->is_v5)
2311 if (BITS (4, 7) == 3)
2313 /* BLX(2) */
2314 if (TFLAG)
2315 dest = (pc + 2) | 1;
2316 else
2317 dest = pc + 4;
2319 WriteR15Branch (state, state->Reg[RHSReg]);
2320 state->Reg[14] = dest;
2321 break;
2325 if (state->is_v5e)
2327 if (BIT (4) == 0 && BIT (7) == 1
2328 && (BIT (5) == 0 || BITS (12, 15) == 0))
2330 /* ElSegundo SMLAWy/SMULWy insn. */
2331 ARMdword op1 = state->Reg[BITS (0, 3)];
2332 ARMdword op2 = state->Reg[BITS (8, 11)];
2333 ARMdword result;
2335 if (BIT (6))
2336 op2 >>= 16;
2337 if (op1 & 0x80000000)
2338 op1 -= 1ULL << 32;
2339 op2 &= 0xFFFF;
2340 if (op2 & 0x8000)
2341 op2 -= 65536;
2342 result = (op1 * op2) >> 16;
2344 if (BIT (5) == 0)
2346 ARMword Rn = state->Reg[BITS (12, 15)];
2348 if (AddOverflow (result, Rn, result + Rn))
2349 SETS;
2350 result += Rn;
2352 state->Reg[BITS (16, 19)] = result;
2353 break;
2356 if (BITS (4, 11) == 5)
2358 /* ElSegundo QSUB insn. */
2359 ARMword op1 = state->Reg[BITS (0, 3)];
2360 ARMword op2 = state->Reg[BITS (16, 19)];
2361 ARMword result = op1 - op2;
2363 if (SubOverflow (op1, op2, result))
2365 result = POS (result) ? 0x80000000 : 0x7fffffff;
2366 SETS;
2369 state->Reg[BITS (12, 15)] = result;
2370 break;
2373 #ifdef MODET
2374 if (BITS (4, 11) == 0xB)
2376 /* STRH register offset, write-back, down, pre indexed. */
2377 SHPREDOWNWB ();
2378 break;
2380 if (BITS (4, 27) == 0x12FFF1)
2382 /* BX */
2383 WriteR15Branch (state, state->Reg[RHSReg]);
2384 break;
2386 if (BITS (4, 7) == 0xD)
2388 Handle_Load_Double (state, instr);
2389 break;
2391 if (BITS (4, 7) == 0xF)
2393 Handle_Store_Double (state, instr);
2394 break;
2396 #endif
2397 if (state->is_v5)
2399 if (BITS (4, 7) == 0x7)
2401 extern int SWI_vector_installed;
2403 /* Hardware is allowed to optionally override this
2404 instruction and treat it as a breakpoint. Since
2405 this is a simulator not hardware, we take the position
2406 that if a SWI vector was not installed, then an Abort
2407 vector was probably not installed either, and so
2408 normally this instruction would be ignored, even if an
2409 Abort is generated. This is a bad thing, since GDB
2410 uses this instruction for its breakpoints (at least in
2411 Thumb mode it does). So intercept the instruction here
2412 and generate a breakpoint SWI instead. */
2413 if (! SWI_vector_installed)
2414 ARMul_OSHandleSWI (state, SWI_Breakpoint);
2415 else
2417 /* BKPT - normally this will cause an abort, but on the
2418 XScale we must check the DCSR. */
2419 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
2420 if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT))
2421 break;
2424 /* Force the next instruction to be refetched. */
2425 state->NextInstr = RESUME;
2426 break;
2429 if (DESTReg == 15)
2431 /* MSR reg to CPSR. */
2432 UNDEF_MSRPC;
2433 temp = DPRegRHS;
2434 #ifdef MODET
2435 /* Don't allow TBIT to be set by MSR. */
2436 temp &= ~ TBIT;
2437 #endif
2438 ARMul_FixCPSR (state, instr, temp);
2440 #ifdef MODE32
2441 else if (state->is_v6
2442 && handle_v6_insn (state, instr))
2443 break;
2444 #endif
2445 else
2446 UNDEF_Test;
2448 break;
2450 case 0x13: /* TEQP reg */
2451 #ifdef MODET
2452 if ((BITS (4, 11) & 0xF9) == 0x9)
2453 /* LDR register offset, write-back, down, pre indexed. */
2454 LHPREDOWNWB ();
2455 /* Continue with remaining instruction decode. */
2456 #endif
2457 if (DESTReg == 15)
2459 /* TEQP reg */
2460 #ifdef MODE32
2461 state->Cpsr = GETSPSR (state->Bank);
2462 ARMul_CPSRAltered (state);
2463 #else
2464 rhs = DPRegRHS;
2465 temp = LHS ^ rhs;
2466 SETR15PSR (temp);
2467 #endif
2469 else
2471 /* TEQ Reg. */
2472 rhs = DPSRegRHS;
2473 dest = LHS ^ rhs;
2474 ARMul_NegZero (state, dest);
2476 break;
2478 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
2479 if (state->is_v5e)
2481 if (BIT (4) == 0 && BIT (7) == 1)
2483 /* ElSegundo SMLALxy insn. */
2484 ARMdword op1 = state->Reg[BITS (0, 3)];
2485 ARMdword op2 = state->Reg[BITS (8, 11)];
2486 ARMdword result;
2488 if (BIT (5))
2489 op1 >>= 16;
2490 if (BIT (6))
2491 op2 >>= 16;
2492 op1 &= 0xFFFF;
2493 if (op1 & 0x8000)
2494 op1 -= 65536;
2495 op2 &= 0xFFFF;
2496 if (op2 & 0x8000)
2497 op2 -= 65536;
2499 result = (ARMdword) state->Reg[BITS (16, 19)] << 32;
2500 result |= state->Reg[BITS (12, 15)];
2501 result += op1 * op2;
2502 state->Reg[BITS (12, 15)] = result;
2503 state->Reg[BITS (16, 19)] = result >> 32;
2504 break;
2507 if (BITS (4, 11) == 5)
2509 /* ElSegundo QDADD insn. */
2510 ARMword op1 = state->Reg[BITS (0, 3)];
2511 ARMword op2 = state->Reg[BITS (16, 19)];
2512 ARMword op2d = op2 + op2;
2513 ARMword result;
2515 if (AddOverflow (op2, op2, op2d))
2517 SETS;
2518 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
2521 result = op1 + op2d;
2522 if (AddOverflow (op1, op2d, result))
2524 SETS;
2525 result = POS (result) ? 0x80000000 : 0x7fffffff;
2528 state->Reg[BITS (12, 15)] = result;
2529 break;
2532 #ifdef MODET
2533 if (BITS (4, 7) == 0xB)
2535 /* STRH immediate offset, no write-back, down, pre indexed. */
2536 SHPREDOWN ();
2537 break;
2539 if (BITS (4, 7) == 0xD)
2541 Handle_Load_Double (state, instr);
2542 break;
2544 if (BITS (4, 7) == 0xF)
2546 Handle_Store_Double (state, instr);
2547 break;
2549 #endif
2550 if (BITS (4, 11) == 9)
2552 /* SWP */
2553 UNDEF_SWPPC;
2554 temp = LHS;
2555 BUSUSEDINCPCS;
2556 #ifndef MODE32
2557 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
2559 INTERNALABORT (temp);
2560 (void) ARMul_LoadByte (state, temp);
2561 (void) ARMul_LoadByte (state, temp);
2563 else
2564 #endif
2565 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
2566 if (state->abortSig || state->Aborted)
2567 TAKEABORT;
2569 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
2571 /* MRS SPSR */
2572 UNDEF_MRSPC;
2573 DEST = GETSPSR (state->Bank);
2575 #ifdef MODE32
2576 else if (state->is_v6
2577 && handle_v6_insn (state, instr))
2578 break;
2579 #endif
2580 else
2581 UNDEF_Test;
2583 break;
2585 case 0x15: /* CMPP reg. */
2586 #ifdef MODET
2587 if ((BITS (4, 7) & 0x9) == 0x9)
2588 /* LDR immediate offset, no write-back, down, pre indexed. */
2589 LHPREDOWN ();
2590 /* Continue with remaining instruction decode. */
2591 #endif
2592 if (DESTReg == 15)
2594 /* CMPP reg. */
2595 #ifdef MODE32
2596 state->Cpsr = GETSPSR (state->Bank);
2597 ARMul_CPSRAltered (state);
2598 #else
2599 rhs = DPRegRHS;
2600 temp = LHS - rhs;
2601 SETR15PSR (temp);
2602 #endif
2604 else
2606 /* CMP reg. */
2607 lhs = LHS;
2608 rhs = DPRegRHS;
2609 dest = lhs - rhs;
2610 ARMul_NegZero (state, dest);
2611 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2613 ARMul_SubCarry (state, lhs, rhs, dest);
2614 ARMul_SubOverflow (state, lhs, rhs, dest);
2616 else
2618 CLEARC;
2619 CLEARV;
2622 break;
2624 case 0x16: /* CMN reg and MSR reg to SPSR */
2625 if (state->is_v5e)
2627 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
2629 /* ElSegundo SMULxy insn. */
2630 ARMword op1 = state->Reg[BITS (0, 3)];
2631 ARMword op2 = state->Reg[BITS (8, 11)];
2633 if (BIT (5))
2634 op1 >>= 16;
2635 if (BIT (6))
2636 op2 >>= 16;
2637 op1 &= 0xFFFF;
2638 op2 &= 0xFFFF;
2639 if (op1 & 0x8000)
2640 op1 -= 65536;
2641 if (op2 & 0x8000)
2642 op2 -= 65536;
2644 state->Reg[BITS (16, 19)] = op1 * op2;
2645 break;
2648 if (BITS (4, 11) == 5)
2650 /* ElSegundo QDSUB insn. */
2651 ARMword op1 = state->Reg[BITS (0, 3)];
2652 ARMword op2 = state->Reg[BITS (16, 19)];
2653 ARMword op2d = op2 + op2;
2654 ARMword result;
2656 if (AddOverflow (op2, op2, op2d))
2658 SETS;
2659 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
2662 result = op1 - op2d;
2663 if (SubOverflow (op1, op2d, result))
2665 SETS;
2666 result = POS (result) ? 0x80000000 : 0x7fffffff;
2669 state->Reg[BITS (12, 15)] = result;
2670 break;
2674 if (state->is_v5)
2676 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
2678 /* ARM5 CLZ insn. */
2679 ARMword op1 = state->Reg[BITS (0, 3)];
2680 int result = 32;
2682 if (op1)
2683 for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
2684 result++;
2686 state->Reg[BITS (12, 15)] = result;
2687 break;
2690 #ifdef MODET
2691 if (BITS (4, 7) == 0xB)
2693 /* STRH immediate offset, write-back, down, pre indexed. */
2694 SHPREDOWNWB ();
2695 break;
2697 if (BITS (4, 7) == 0xD)
2699 Handle_Load_Double (state, instr);
2700 break;
2702 if (BITS (4, 7) == 0xF)
2704 Handle_Store_Double (state, instr);
2705 break;
2707 #endif
2708 if (DESTReg == 15)
2710 /* MSR */
2711 UNDEF_MSRPC;
2712 ARMul_FixSPSR (state, instr, DPRegRHS);
2714 else
2716 #ifdef MODE32
2717 if (state->is_v6
2718 && handle_v6_insn (state, instr))
2719 break;
2720 #endif
2721 UNDEF_Test;
2723 break;
2725 case 0x17: /* CMNP reg */
2726 #ifdef MODET
2727 if ((BITS (4, 7) & 0x9) == 0x9)
2728 /* LDR immediate offset, write-back, down, pre indexed. */
2729 LHPREDOWNWB ();
2730 /* Continue with remaining instruction decoding. */
2731 #endif
2732 if (DESTReg == 15)
2734 #ifdef MODE32
2735 state->Cpsr = GETSPSR (state->Bank);
2736 ARMul_CPSRAltered (state);
2737 #else
2738 rhs = DPRegRHS;
2739 temp = LHS + rhs;
2740 SETR15PSR (temp);
2741 #endif
2742 break;
2744 else
2746 /* CMN reg. */
2747 lhs = LHS;
2748 rhs = DPRegRHS;
2749 dest = lhs + rhs;
2750 ASSIGNZ (dest == 0);
2751 if ((lhs | rhs) >> 30)
2753 /* Possible C,V,N to set. */
2754 ASSIGNN (NEG (dest));
2755 ARMul_AddCarry (state, lhs, rhs, dest);
2756 ARMul_AddOverflow (state, lhs, rhs, dest);
2758 else
2760 CLEARN;
2761 CLEARC;
2762 CLEARV;
2765 break;
2767 case 0x18: /* ORR reg */
2768 #ifdef MODET
2769 if (BITS (4, 11) == 0xB)
2771 /* STRH register offset, no write-back, up, pre indexed. */
2772 SHPREUP ();
2773 break;
2775 if (BITS (4, 7) == 0xD)
2777 Handle_Load_Double (state, instr);
2778 break;
2780 if (BITS (4, 7) == 0xF)
2782 Handle_Store_Double (state, instr);
2783 break;
2785 #endif
2786 rhs = DPRegRHS;
2787 dest = LHS | rhs;
2788 WRITEDEST (dest);
2789 break;
2791 case 0x19: /* ORRS reg */
2792 #ifdef MODET
2793 if ((BITS (4, 11) & 0xF9) == 0x9)
2794 /* LDR register offset, no write-back, up, pre indexed. */
2795 LHPREUP ();
2796 /* Continue with remaining instruction decoding. */
2797 #endif
2798 rhs = DPSRegRHS;
2799 dest = LHS | rhs;
2800 WRITESDEST (dest);
2801 break;
2803 case 0x1a: /* MOV reg */
2804 #ifdef MODET
2805 if (BITS (4, 11) == 0xB)
2807 /* STRH register offset, write-back, up, pre indexed. */
2808 SHPREUPWB ();
2809 break;
2811 if (BITS (4, 7) == 0xD)
2813 Handle_Load_Double (state, instr);
2814 break;
2816 if (BITS (4, 7) == 0xF)
2818 Handle_Store_Double (state, instr);
2819 break;
2821 #endif
2822 dest = DPRegRHS;
2823 WRITEDEST (dest);
2824 break;
2826 case 0x1b: /* MOVS reg */
2827 #ifdef MODET
2828 if ((BITS (4, 11) & 0xF9) == 0x9)
2829 /* LDR register offset, write-back, up, pre indexed. */
2830 LHPREUPWB ();
2831 /* Continue with remaining instruction decoding. */
2832 #endif
2833 dest = DPSRegRHS;
2834 WRITESDEST (dest);
2835 break;
2837 case 0x1c: /* BIC reg */
2838 #ifdef MODET
2839 if (BITS (4, 7) == 0xB)
2841 /* STRH immediate offset, no write-back, up, pre indexed. */
2842 SHPREUP ();
2843 break;
2845 if (BITS (4, 7) == 0xD)
2847 Handle_Load_Double (state, instr);
2848 break;
2850 else if (BITS (4, 7) == 0xF)
2852 Handle_Store_Double (state, instr);
2853 break;
2855 #endif
2856 rhs = DPRegRHS;
2857 dest = LHS & ~rhs;
2858 WRITEDEST (dest);
2859 break;
2861 case 0x1d: /* BICS reg */
2862 #ifdef MODET
2863 if ((BITS (4, 7) & 0x9) == 0x9)
2864 /* LDR immediate offset, no write-back, up, pre indexed. */
2865 LHPREUP ();
2866 /* Continue with instruction decoding. */
2867 #endif
2868 rhs = DPSRegRHS;
2869 dest = LHS & ~rhs;
2870 WRITESDEST (dest);
2871 break;
2873 case 0x1e: /* MVN reg */
2874 #ifdef MODET
2875 if (BITS (4, 7) == 0xB)
2877 /* STRH immediate offset, write-back, up, pre indexed. */
2878 SHPREUPWB ();
2879 break;
2881 if (BITS (4, 7) == 0xD)
2883 Handle_Load_Double (state, instr);
2884 break;
2886 if (BITS (4, 7) == 0xF)
2888 Handle_Store_Double (state, instr);
2889 break;
2891 #endif
2892 dest = ~DPRegRHS;
2893 WRITEDEST (dest);
2894 break;
2896 case 0x1f: /* MVNS reg */
2897 #ifdef MODET
2898 if ((BITS (4, 7) & 0x9) == 0x9)
2899 /* LDR immediate offset, write-back, up, pre indexed. */
2900 LHPREUPWB ();
2901 /* Continue instruction decoding. */
2902 #endif
2903 dest = ~DPSRegRHS;
2904 WRITESDEST (dest);
2905 break;
2908 /* Data Processing Immediate RHS Instructions. */
2910 case 0x20: /* AND immed */
2911 dest = LHS & DPImmRHS;
2912 WRITEDEST (dest);
2913 break;
2915 case 0x21: /* ANDS immed */
2916 DPSImmRHS;
2917 dest = LHS & rhs;
2918 WRITESDEST (dest);
2919 break;
2921 case 0x22: /* EOR immed */
2922 dest = LHS ^ DPImmRHS;
2923 WRITEDEST (dest);
2924 break;
2926 case 0x23: /* EORS immed */
2927 DPSImmRHS;
2928 dest = LHS ^ rhs;
2929 WRITESDEST (dest);
2930 break;
2932 case 0x24: /* SUB immed */
2933 dest = LHS - DPImmRHS;
2934 WRITEDEST (dest);
2935 break;
2937 case 0x25: /* SUBS immed */
2938 lhs = LHS;
2939 rhs = DPImmRHS;
2940 dest = lhs - rhs;
2942 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2944 ARMul_SubCarry (state, lhs, rhs, dest);
2945 ARMul_SubOverflow (state, lhs, rhs, dest);
2947 else
2949 CLEARC;
2950 CLEARV;
2952 WRITESDEST (dest);
2953 break;
2955 case 0x26: /* RSB immed */
2956 dest = DPImmRHS - LHS;
2957 WRITEDEST (dest);
2958 break;
2960 case 0x27: /* RSBS immed */
2961 lhs = LHS;
2962 rhs = DPImmRHS;
2963 dest = rhs - lhs;
2965 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
2967 ARMul_SubCarry (state, rhs, lhs, dest);
2968 ARMul_SubOverflow (state, rhs, lhs, dest);
2970 else
2972 CLEARC;
2973 CLEARV;
2975 WRITESDEST (dest);
2976 break;
2978 case 0x28: /* ADD immed */
2979 dest = LHS + DPImmRHS;
2980 WRITEDEST (dest);
2981 break;
2983 case 0x29: /* ADDS immed */
2984 lhs = LHS;
2985 rhs = DPImmRHS;
2986 dest = lhs + rhs;
2987 ASSIGNZ (dest == 0);
2989 if ((lhs | rhs) >> 30)
2991 /* Possible C,V,N to set. */
2992 ASSIGNN (NEG (dest));
2993 ARMul_AddCarry (state, lhs, rhs, dest);
2994 ARMul_AddOverflow (state, lhs, rhs, dest);
2996 else
2998 CLEARN;
2999 CLEARC;
3000 CLEARV;
3002 WRITESDEST (dest);
3003 break;
3005 case 0x2a: /* ADC immed */
3006 dest = LHS + DPImmRHS + CFLAG;
3007 WRITEDEST (dest);
3008 break;
3010 case 0x2b: /* ADCS immed */
3011 lhs = LHS;
3012 rhs = DPImmRHS;
3013 dest = lhs + rhs + CFLAG;
3014 ASSIGNZ (dest == 0);
3015 if ((lhs | rhs) >> 30)
3017 /* Possible C,V,N to set. */
3018 ASSIGNN (NEG (dest));
3019 ARMul_AddCarry (state, lhs, rhs, dest);
3020 ARMul_AddOverflow (state, lhs, rhs, dest);
3022 else
3024 CLEARN;
3025 CLEARC;
3026 CLEARV;
3028 WRITESDEST (dest);
3029 break;
3031 case 0x2c: /* SBC immed */
3032 dest = LHS - DPImmRHS - !CFLAG;
3033 WRITEDEST (dest);
3034 break;
3036 case 0x2d: /* SBCS immed */
3037 lhs = LHS;
3038 rhs = DPImmRHS;
3039 dest = lhs - rhs - !CFLAG;
3040 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
3042 ARMul_SubCarry (state, lhs, rhs, dest);
3043 ARMul_SubOverflow (state, lhs, rhs, dest);
3045 else
3047 CLEARC;
3048 CLEARV;
3050 WRITESDEST (dest);
3051 break;
3053 case 0x2e: /* RSC immed */
3054 dest = DPImmRHS - LHS - !CFLAG;
3055 WRITEDEST (dest);
3056 break;
3058 case 0x2f: /* RSCS immed */
3059 lhs = LHS;
3060 rhs = DPImmRHS;
3061 dest = rhs - lhs - !CFLAG;
3062 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
3064 ARMul_SubCarry (state, rhs, lhs, dest);
3065 ARMul_SubOverflow (state, rhs, lhs, dest);
3067 else
3069 CLEARC;
3070 CLEARV;
3072 WRITESDEST (dest);
3073 break;
3075 case 0x30: /* MOVW immed */
3076 #ifdef MODE32
3077 if (state->is_v6
3078 && handle_v6_insn (state, instr))
3079 break;
3080 #endif
3081 dest = BITS (0, 11);
3082 dest |= (BITS (16, 19) << 12);
3083 WRITEDEST (dest);
3084 break;
3086 case 0x31: /* TSTP immed */
3087 if (DESTReg == 15)
3089 /* TSTP immed. */
3090 #ifdef MODE32
3091 state->Cpsr = GETSPSR (state->Bank);
3092 ARMul_CPSRAltered (state);
3093 #else
3094 temp = LHS & DPImmRHS;
3095 SETR15PSR (temp);
3096 #endif
3098 else
3100 /* TST immed. */
3101 DPSImmRHS;
3102 dest = LHS & rhs;
3103 ARMul_NegZero (state, dest);
3105 break;
3107 case 0x32: /* TEQ immed and MSR immed to CPSR */
3108 if (DESTReg == 15)
3109 /* MSR immed to CPSR. */
3110 ARMul_FixCPSR (state, instr, DPImmRHS);
3111 #ifdef MODE32
3112 else if (state->is_v6
3113 && handle_v6_insn (state, instr))
3114 break;
3115 #endif
3116 else
3117 UNDEF_Test;
3118 break;
3120 case 0x33: /* TEQP immed */
3121 if (DESTReg == 15)
3123 /* TEQP immed. */
3124 #ifdef MODE32
3125 state->Cpsr = GETSPSR (state->Bank);
3126 ARMul_CPSRAltered (state);
3127 #else
3128 temp = LHS ^ DPImmRHS;
3129 SETR15PSR (temp);
3130 #endif
3132 else
3134 DPSImmRHS; /* TEQ immed */
3135 dest = LHS ^ rhs;
3136 ARMul_NegZero (state, dest);
3138 break;
3140 case 0x34: /* MOVT immed */
3141 #ifdef MODE32
3142 if (state->is_v6
3143 && handle_v6_insn (state, instr))
3144 break;
3145 #endif
3146 DEST &= 0xFFFF;
3147 dest = BITS (0, 11);
3148 dest |= (BITS (16, 19) << 12);
3149 DEST |= (dest << 16);
3150 break;
3152 case 0x35: /* CMPP immed */
3153 if (DESTReg == 15)
3155 /* CMPP immed. */
3156 #ifdef MODE32
3157 state->Cpsr = GETSPSR (state->Bank);
3158 ARMul_CPSRAltered (state);
3159 #else
3160 temp = LHS - DPImmRHS;
3161 SETR15PSR (temp);
3162 #endif
3163 break;
3165 else
3167 /* CMP immed. */
3168 lhs = LHS;
3169 rhs = DPImmRHS;
3170 dest = lhs - rhs;
3171 ARMul_NegZero (state, dest);
3173 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
3175 ARMul_SubCarry (state, lhs, rhs, dest);
3176 ARMul_SubOverflow (state, lhs, rhs, dest);
3178 else
3180 CLEARC;
3181 CLEARV;
3184 break;
3186 case 0x36: /* CMN immed and MSR immed to SPSR */
3187 if (DESTReg == 15)
3188 ARMul_FixSPSR (state, instr, DPImmRHS);
3189 #ifdef MODE32
3190 else if (state->is_v6
3191 && handle_v6_insn (state, instr))
3192 break;
3193 #endif
3194 else
3195 UNDEF_Test;
3196 break;
3198 case 0x37: /* CMNP immed. */
3199 if (DESTReg == 15)
3201 /* CMNP immed. */
3202 #ifdef MODE32
3203 state->Cpsr = GETSPSR (state->Bank);
3204 ARMul_CPSRAltered (state);
3205 #else
3206 temp = LHS + DPImmRHS;
3207 SETR15PSR (temp);
3208 #endif
3209 break;
3211 else
3213 /* CMN immed. */
3214 lhs = LHS;
3215 rhs = DPImmRHS;
3216 dest = lhs + rhs;
3217 ASSIGNZ (dest == 0);
3218 if ((lhs | rhs) >> 30)
3220 /* Possible C,V,N to set. */
3221 ASSIGNN (NEG (dest));
3222 ARMul_AddCarry (state, lhs, rhs, dest);
3223 ARMul_AddOverflow (state, lhs, rhs, dest);
3225 else
3227 CLEARN;
3228 CLEARC;
3229 CLEARV;
3232 break;
3234 case 0x38: /* ORR immed. */
3235 dest = LHS | DPImmRHS;
3236 WRITEDEST (dest);
3237 break;
3239 case 0x39: /* ORRS immed. */
3240 DPSImmRHS;
3241 dest = LHS | rhs;
3242 WRITESDEST (dest);
3243 break;
3245 case 0x3a: /* MOV immed. */
3246 dest = DPImmRHS;
3247 WRITEDEST (dest);
3248 break;
3250 case 0x3b: /* MOVS immed. */
3251 DPSImmRHS;
3252 WRITESDEST (rhs);
3253 break;
3255 case 0x3c: /* BIC immed. */
3256 dest = LHS & ~DPImmRHS;
3257 WRITEDEST (dest);
3258 break;
3260 case 0x3d: /* BICS immed. */
3261 DPSImmRHS;
3262 dest = LHS & ~rhs;
3263 WRITESDEST (dest);
3264 break;
3266 case 0x3e: /* MVN immed. */
3267 dest = ~DPImmRHS;
3268 WRITEDEST (dest);
3269 break;
3271 case 0x3f: /* MVNS immed. */
3272 DPSImmRHS;
3273 WRITESDEST (~rhs);
3274 break;
3277 /* Single Data Transfer Immediate RHS Instructions. */
3279 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
3280 lhs = LHS;
3281 if (StoreWord (state, instr, lhs))
3282 LSBase = lhs - LSImmRHS;
3283 break;
3285 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
3286 lhs = LHS;
3287 if (LoadWord (state, instr, lhs))
3288 LSBase = lhs - LSImmRHS;
3289 break;
3291 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
3292 UNDEF_LSRBaseEQDestWb;
3293 UNDEF_LSRPCBaseWb;
3294 lhs = LHS;
3295 temp = lhs - LSImmRHS;
3296 state->NtransSig = LOW;
3297 if (StoreWord (state, instr, lhs))
3298 LSBase = temp;
3299 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3300 break;
3302 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
3303 UNDEF_LSRBaseEQDestWb;
3304 UNDEF_LSRPCBaseWb;
3305 lhs = LHS;
3306 state->NtransSig = LOW;
3307 if (LoadWord (state, instr, lhs))
3308 LSBase = lhs - LSImmRHS;
3309 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3310 break;
3312 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
3313 lhs = LHS;
3314 if (StoreByte (state, instr, lhs))
3315 LSBase = lhs - LSImmRHS;
3316 break;
3318 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
3319 lhs = LHS;
3320 if (LoadByte (state, instr, lhs, LUNSIGNED))
3321 LSBase = lhs - LSImmRHS;
3322 break;
3324 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
3325 UNDEF_LSRBaseEQDestWb;
3326 UNDEF_LSRPCBaseWb;
3327 lhs = LHS;
3328 state->NtransSig = LOW;
3329 if (StoreByte (state, instr, lhs))
3330 LSBase = lhs - LSImmRHS;
3331 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3332 break;
3334 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
3335 UNDEF_LSRBaseEQDestWb;
3336 UNDEF_LSRPCBaseWb;
3337 lhs = LHS;
3338 state->NtransSig = LOW;
3339 if (LoadByte (state, instr, lhs, LUNSIGNED))
3340 LSBase = lhs - LSImmRHS;
3341 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3342 break;
3344 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
3345 lhs = LHS;
3346 if (StoreWord (state, instr, lhs))
3347 LSBase = lhs + LSImmRHS;
3348 break;
3350 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
3351 lhs = LHS;
3352 if (LoadWord (state, instr, lhs))
3353 LSBase = lhs + LSImmRHS;
3354 break;
3356 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
3357 UNDEF_LSRBaseEQDestWb;
3358 UNDEF_LSRPCBaseWb;
3359 lhs = LHS;
3360 state->NtransSig = LOW;
3361 if (StoreWord (state, instr, lhs))
3362 LSBase = lhs + LSImmRHS;
3363 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3364 break;
3366 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
3367 UNDEF_LSRBaseEQDestWb;
3368 UNDEF_LSRPCBaseWb;
3369 lhs = LHS;
3370 state->NtransSig = LOW;
3371 if (LoadWord (state, instr, lhs))
3372 LSBase = lhs + LSImmRHS;
3373 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3374 break;
3376 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
3377 lhs = LHS;
3378 if (StoreByte (state, instr, lhs))
3379 LSBase = lhs + LSImmRHS;
3380 break;
3382 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
3383 lhs = LHS;
3384 if (LoadByte (state, instr, lhs, LUNSIGNED))
3385 LSBase = lhs + LSImmRHS;
3386 break;
3388 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
3389 UNDEF_LSRBaseEQDestWb;
3390 UNDEF_LSRPCBaseWb;
3391 lhs = LHS;
3392 state->NtransSig = LOW;
3393 if (StoreByte (state, instr, lhs))
3394 LSBase = lhs + LSImmRHS;
3395 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3396 break;
3398 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
3399 UNDEF_LSRBaseEQDestWb;
3400 UNDEF_LSRPCBaseWb;
3401 lhs = LHS;
3402 state->NtransSig = LOW;
3403 if (LoadByte (state, instr, lhs, LUNSIGNED))
3404 LSBase = lhs + LSImmRHS;
3405 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3406 break;
3409 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
3410 (void) StoreWord (state, instr, LHS - LSImmRHS);
3411 break;
3413 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
3414 (void) LoadWord (state, instr, LHS - LSImmRHS);
3415 break;
3417 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
3418 UNDEF_LSRBaseEQDestWb;
3419 UNDEF_LSRPCBaseWb;
3420 temp = LHS - LSImmRHS;
3421 if (StoreWord (state, instr, temp))
3422 LSBase = temp;
3423 break;
3425 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
3426 UNDEF_LSRBaseEQDestWb;
3427 UNDEF_LSRPCBaseWb;
3428 temp = LHS - LSImmRHS;
3429 if (LoadWord (state, instr, temp))
3430 LSBase = temp;
3431 break;
3433 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
3434 (void) StoreByte (state, instr, LHS - LSImmRHS);
3435 break;
3437 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
3438 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
3439 break;
3441 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
3442 UNDEF_LSRBaseEQDestWb;
3443 UNDEF_LSRPCBaseWb;
3444 temp = LHS - LSImmRHS;
3445 if (StoreByte (state, instr, temp))
3446 LSBase = temp;
3447 break;
3449 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
3450 UNDEF_LSRBaseEQDestWb;
3451 UNDEF_LSRPCBaseWb;
3452 temp = LHS - LSImmRHS;
3453 if (LoadByte (state, instr, temp, LUNSIGNED))
3454 LSBase = temp;
3455 break;
3457 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
3458 (void) StoreWord (state, instr, LHS + LSImmRHS);
3459 break;
3461 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
3462 (void) LoadWord (state, instr, LHS + LSImmRHS);
3463 break;
3465 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
3466 UNDEF_LSRBaseEQDestWb;
3467 UNDEF_LSRPCBaseWb;
3468 temp = LHS + LSImmRHS;
3469 if (StoreWord (state, instr, temp))
3470 LSBase = temp;
3471 break;
3473 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
3474 UNDEF_LSRBaseEQDestWb;
3475 UNDEF_LSRPCBaseWb;
3476 temp = LHS + LSImmRHS;
3477 if (LoadWord (state, instr, temp))
3478 LSBase = temp;
3479 break;
3481 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
3482 (void) StoreByte (state, instr, LHS + LSImmRHS);
3483 break;
3485 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
3486 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
3487 break;
3489 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
3490 UNDEF_LSRBaseEQDestWb;
3491 UNDEF_LSRPCBaseWb;
3492 temp = LHS + LSImmRHS;
3493 if (StoreByte (state, instr, temp))
3494 LSBase = temp;
3495 break;
3497 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
3498 UNDEF_LSRBaseEQDestWb;
3499 UNDEF_LSRPCBaseWb;
3500 temp = LHS + LSImmRHS;
3501 if (LoadByte (state, instr, temp, LUNSIGNED))
3502 LSBase = temp;
3503 break;
3506 /* Single Data Transfer Register RHS Instructions. */
3508 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
3509 if (BIT (4))
3511 #ifdef MODE32
3512 if (state->is_v6
3513 && handle_v6_insn (state, instr))
3514 break;
3515 #endif
3516 ARMul_UndefInstr (state, instr);
3517 break;
3519 UNDEF_LSRBaseEQOffWb;
3520 UNDEF_LSRBaseEQDestWb;
3521 UNDEF_LSRPCBaseWb;
3522 UNDEF_LSRPCOffWb;
3523 lhs = LHS;
3524 if (StoreWord (state, instr, lhs))
3525 LSBase = lhs - LSRegRHS;
3526 break;
3528 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
3529 if (BIT (4))
3531 #ifdef MODE32
3532 if (state->is_v6
3533 && handle_v6_insn (state, instr))
3534 break;
3535 #endif
3536 ARMul_UndefInstr (state, instr);
3537 break;
3539 UNDEF_LSRBaseEQOffWb;
3540 UNDEF_LSRBaseEQDestWb;
3541 UNDEF_LSRPCBaseWb;
3542 UNDEF_LSRPCOffWb;
3543 lhs = LHS;
3544 temp = lhs - LSRegRHS;
3545 if (LoadWord (state, instr, lhs))
3546 LSBase = temp;
3547 break;
3549 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
3550 if (BIT (4))
3552 #ifdef MODE32
3553 if (state->is_v6
3554 && handle_v6_insn (state, instr))
3555 break;
3556 #endif
3557 ARMul_UndefInstr (state, instr);
3558 break;
3560 UNDEF_LSRBaseEQOffWb;
3561 UNDEF_LSRBaseEQDestWb;
3562 UNDEF_LSRPCBaseWb;
3563 UNDEF_LSRPCOffWb;
3564 lhs = LHS;
3565 state->NtransSig = LOW;
3566 if (StoreWord (state, instr, lhs))
3567 LSBase = lhs - LSRegRHS;
3568 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3569 break;
3571 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
3572 if (BIT (4))
3574 #ifdef MODE32
3575 if (state->is_v6
3576 && handle_v6_insn (state, instr))
3577 break;
3578 #endif
3579 ARMul_UndefInstr (state, instr);
3580 break;
3582 UNDEF_LSRBaseEQOffWb;
3583 UNDEF_LSRBaseEQDestWb;
3584 UNDEF_LSRPCBaseWb;
3585 UNDEF_LSRPCOffWb;
3586 lhs = LHS;
3587 temp = lhs - LSRegRHS;
3588 state->NtransSig = LOW;
3589 if (LoadWord (state, instr, lhs))
3590 LSBase = temp;
3591 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3592 break;
3594 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
3595 if (BIT (4))
3597 #ifdef MODE32
3598 if (state->is_v6
3599 && handle_v6_insn (state, instr))
3600 break;
3601 #endif
3602 ARMul_UndefInstr (state, instr);
3603 break;
3605 UNDEF_LSRBaseEQOffWb;
3606 UNDEF_LSRBaseEQDestWb;
3607 UNDEF_LSRPCBaseWb;
3608 UNDEF_LSRPCOffWb;
3609 lhs = LHS;
3610 if (StoreByte (state, instr, lhs))
3611 LSBase = lhs - LSRegRHS;
3612 break;
3614 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
3615 if (BIT (4))
3617 #ifdef MODE32
3618 if (state->is_v6
3619 && handle_v6_insn (state, instr))
3620 break;
3621 #endif
3622 ARMul_UndefInstr (state, instr);
3623 break;
3625 UNDEF_LSRBaseEQOffWb;
3626 UNDEF_LSRBaseEQDestWb;
3627 UNDEF_LSRPCBaseWb;
3628 UNDEF_LSRPCOffWb;
3629 lhs = LHS;
3630 temp = lhs - LSRegRHS;
3631 if (LoadByte (state, instr, lhs, LUNSIGNED))
3632 LSBase = temp;
3633 break;
3635 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
3636 if (BIT (4))
3638 #ifdef MODE32
3639 if (state->is_v6
3640 && handle_v6_insn (state, instr))
3641 break;
3642 #endif
3643 ARMul_UndefInstr (state, instr);
3644 break;
3646 UNDEF_LSRBaseEQOffWb;
3647 UNDEF_LSRBaseEQDestWb;
3648 UNDEF_LSRPCBaseWb;
3649 UNDEF_LSRPCOffWb;
3650 lhs = LHS;
3651 state->NtransSig = LOW;
3652 if (StoreByte (state, instr, lhs))
3653 LSBase = lhs - LSRegRHS;
3654 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3655 break;
3657 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
3658 if (BIT (4))
3660 #ifdef MODE32
3661 if (state->is_v6
3662 && handle_v6_insn (state, instr))
3663 break;
3664 #endif
3665 ARMul_UndefInstr (state, instr);
3666 break;
3668 UNDEF_LSRBaseEQOffWb;
3669 UNDEF_LSRBaseEQDestWb;
3670 UNDEF_LSRPCBaseWb;
3671 UNDEF_LSRPCOffWb;
3672 lhs = LHS;
3673 temp = lhs - LSRegRHS;
3674 state->NtransSig = LOW;
3675 if (LoadByte (state, instr, lhs, LUNSIGNED))
3676 LSBase = temp;
3677 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3678 break;
3680 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
3681 if (BIT (4))
3683 #ifdef MODE32
3684 if (state->is_v6
3685 && handle_v6_insn (state, instr))
3686 break;
3687 #endif
3688 ARMul_UndefInstr (state, instr);
3689 break;
3691 UNDEF_LSRBaseEQOffWb;
3692 UNDEF_LSRBaseEQDestWb;
3693 UNDEF_LSRPCBaseWb;
3694 UNDEF_LSRPCOffWb;
3695 lhs = LHS;
3696 if (StoreWord (state, instr, lhs))
3697 LSBase = lhs + LSRegRHS;
3698 break;
3700 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
3701 if (BIT (4))
3703 #ifdef MODE32
3704 if (state->is_v6
3705 && handle_v6_insn (state, instr))
3706 break;
3707 #endif
3708 ARMul_UndefInstr (state, instr);
3709 break;
3711 UNDEF_LSRBaseEQOffWb;
3712 UNDEF_LSRBaseEQDestWb;
3713 UNDEF_LSRPCBaseWb;
3714 UNDEF_LSRPCOffWb;
3715 lhs = LHS;
3716 temp = lhs + LSRegRHS;
3717 if (LoadWord (state, instr, lhs))
3718 LSBase = temp;
3719 break;
3721 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
3722 if (BIT (4))
3724 #ifdef MODE32
3725 if (state->is_v6
3726 && handle_v6_insn (state, instr))
3727 break;
3728 #endif
3729 ARMul_UndefInstr (state, instr);
3730 break;
3732 UNDEF_LSRBaseEQOffWb;
3733 UNDEF_LSRBaseEQDestWb;
3734 UNDEF_LSRPCBaseWb;
3735 UNDEF_LSRPCOffWb;
3736 lhs = LHS;
3737 state->NtransSig = LOW;
3738 if (StoreWord (state, instr, lhs))
3739 LSBase = lhs + LSRegRHS;
3740 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3741 break;
3743 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
3744 if (BIT (4))
3746 #ifdef MODE32
3747 if (state->is_v6
3748 && handle_v6_insn (state, instr))
3749 break;
3750 #endif
3751 ARMul_UndefInstr (state, instr);
3752 break;
3754 UNDEF_LSRBaseEQOffWb;
3755 UNDEF_LSRBaseEQDestWb;
3756 UNDEF_LSRPCBaseWb;
3757 UNDEF_LSRPCOffWb;
3758 lhs = LHS;
3759 temp = lhs + LSRegRHS;
3760 state->NtransSig = LOW;
3761 if (LoadWord (state, instr, lhs))
3762 LSBase = temp;
3763 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3764 break;
3766 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
3767 if (BIT (4))
3769 #ifdef MODE32
3770 if (state->is_v6
3771 && handle_v6_insn (state, instr))
3772 break;
3773 #endif
3774 ARMul_UndefInstr (state, instr);
3775 break;
3777 UNDEF_LSRBaseEQOffWb;
3778 UNDEF_LSRBaseEQDestWb;
3779 UNDEF_LSRPCBaseWb;
3780 UNDEF_LSRPCOffWb;
3781 lhs = LHS;
3782 if (StoreByte (state, instr, lhs))
3783 LSBase = lhs + LSRegRHS;
3784 break;
3786 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
3787 if (BIT (4))
3789 #ifdef MODE32
3790 if (state->is_v6
3791 && handle_v6_insn (state, instr))
3792 break;
3793 #endif
3794 ARMul_UndefInstr (state, instr);
3795 break;
3797 UNDEF_LSRBaseEQOffWb;
3798 UNDEF_LSRBaseEQDestWb;
3799 UNDEF_LSRPCBaseWb;
3800 UNDEF_LSRPCOffWb;
3801 lhs = LHS;
3802 temp = lhs + LSRegRHS;
3803 if (LoadByte (state, instr, lhs, LUNSIGNED))
3804 LSBase = temp;
3805 break;
3807 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3808 if (BIT (4))
3810 #ifdef MODE32
3811 if (state->is_v6
3812 && handle_v6_insn (state, instr))
3813 break;
3814 #endif
3815 ARMul_UndefInstr (state, instr);
3816 break;
3818 UNDEF_LSRBaseEQOffWb;
3819 UNDEF_LSRBaseEQDestWb;
3820 UNDEF_LSRPCBaseWb;
3821 UNDEF_LSRPCOffWb;
3822 lhs = LHS;
3823 state->NtransSig = LOW;
3824 if (StoreByte (state, instr, lhs))
3825 LSBase = lhs + LSRegRHS;
3826 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3827 break;
3829 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3830 if (BIT (4))
3832 #ifdef MODE32
3833 if (state->is_v6
3834 && handle_v6_insn (state, instr))
3835 break;
3836 #endif
3837 ARMul_UndefInstr (state, instr);
3838 break;
3840 UNDEF_LSRBaseEQOffWb;
3841 UNDEF_LSRBaseEQDestWb;
3842 UNDEF_LSRPCBaseWb;
3843 UNDEF_LSRPCOffWb;
3844 lhs = LHS;
3845 temp = lhs + LSRegRHS;
3846 state->NtransSig = LOW;
3847 if (LoadByte (state, instr, lhs, LUNSIGNED))
3848 LSBase = temp;
3849 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3850 break;
3853 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3854 if (BIT (4))
3856 #ifdef MODE32
3857 if (state->is_v6
3858 && handle_v6_insn (state, instr))
3859 break;
3860 #endif
3861 ARMul_UndefInstr (state, instr);
3862 break;
3864 (void) StoreWord (state, instr, LHS - LSRegRHS);
3865 break;
3867 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3868 if (BIT (4))
3870 #ifdef MODE32
3871 if (state->is_v6
3872 && handle_v6_insn (state, instr))
3873 break;
3874 #endif
3875 ARMul_UndefInstr (state, instr);
3876 break;
3878 (void) LoadWord (state, instr, LHS - LSRegRHS);
3879 break;
3881 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3882 if (BIT (4))
3884 #ifdef MODE32
3885 if (state->is_v6
3886 && handle_v6_insn (state, instr))
3887 break;
3888 #endif
3889 ARMul_UndefInstr (state, instr);
3890 break;
3892 UNDEF_LSRBaseEQOffWb;
3893 UNDEF_LSRBaseEQDestWb;
3894 UNDEF_LSRPCBaseWb;
3895 UNDEF_LSRPCOffWb;
3896 temp = LHS - LSRegRHS;
3897 if (StoreWord (state, instr, temp))
3898 LSBase = temp;
3899 break;
3901 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3902 if (BIT (4))
3904 #ifdef MODE32
3905 if (state->is_v6
3906 && handle_v6_insn (state, instr))
3907 break;
3908 #endif
3909 ARMul_UndefInstr (state, instr);
3910 break;
3912 UNDEF_LSRBaseEQOffWb;
3913 UNDEF_LSRBaseEQDestWb;
3914 UNDEF_LSRPCBaseWb;
3915 UNDEF_LSRPCOffWb;
3916 temp = LHS - LSRegRHS;
3917 if (LoadWord (state, instr, temp))
3918 LSBase = temp;
3919 break;
3921 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3922 if (BIT (4))
3924 #ifdef MODE32
3925 if (state->is_v6
3926 && handle_v6_insn (state, instr))
3927 break;
3928 #endif
3929 ARMul_UndefInstr (state, instr);
3930 break;
3932 (void) StoreByte (state, instr, LHS - LSRegRHS);
3933 break;
3935 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3936 if (BIT (4))
3938 #ifdef MODE32
3939 if (state->is_v6
3940 && handle_v6_insn (state, instr))
3941 break;
3942 #endif
3943 ARMul_UndefInstr (state, instr);
3944 break;
3946 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
3947 break;
3949 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3950 if (BIT (4))
3952 #ifdef MODE32
3953 if (state->is_v6
3954 && handle_v6_insn (state, instr))
3955 break;
3956 #endif
3957 ARMul_UndefInstr (state, instr);
3958 break;
3960 UNDEF_LSRBaseEQOffWb;
3961 UNDEF_LSRBaseEQDestWb;
3962 UNDEF_LSRPCBaseWb;
3963 UNDEF_LSRPCOffWb;
3964 temp = LHS - LSRegRHS;
3965 if (StoreByte (state, instr, temp))
3966 LSBase = temp;
3967 break;
3969 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3970 if (BIT (4))
3972 #ifdef MODE32
3973 if (state->is_v6
3974 && handle_v6_insn (state, instr))
3975 break;
3976 #endif
3977 ARMul_UndefInstr (state, instr);
3978 break;
3980 UNDEF_LSRBaseEQOffWb;
3981 UNDEF_LSRBaseEQDestWb;
3982 UNDEF_LSRPCBaseWb;
3983 UNDEF_LSRPCOffWb;
3984 temp = LHS - LSRegRHS;
3985 if (LoadByte (state, instr, temp, LUNSIGNED))
3986 LSBase = temp;
3987 break;
3989 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3990 if (BIT (4))
3992 #ifdef MODE32
3993 if (state->is_v6
3994 && handle_v6_insn (state, instr))
3995 break;
3996 #endif
3997 ARMul_UndefInstr (state, instr);
3998 break;
4000 (void) StoreWord (state, instr, LHS + LSRegRHS);
4001 break;
4003 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
4004 if (BIT (4))
4006 #ifdef MODE32
4007 if (state->is_v6
4008 && handle_v6_insn (state, instr))
4009 break;
4010 #endif
4011 ARMul_UndefInstr (state, instr);
4012 break;
4014 (void) LoadWord (state, instr, LHS + LSRegRHS);
4015 break;
4017 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
4018 if (BIT (4))
4020 #ifdef MODE32
4021 if (state->is_v6
4022 && handle_v6_insn (state, instr))
4023 break;
4024 #endif
4025 ARMul_UndefInstr (state, instr);
4026 break;
4028 UNDEF_LSRBaseEQOffWb;
4029 UNDEF_LSRBaseEQDestWb;
4030 UNDEF_LSRPCBaseWb;
4031 UNDEF_LSRPCOffWb;
4032 temp = LHS + LSRegRHS;
4033 if (StoreWord (state, instr, temp))
4034 LSBase = temp;
4035 break;
4037 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
4038 if (BIT (4))
4040 #ifdef MODE32
4041 if (state->is_v6
4042 && handle_v6_insn (state, instr))
4043 break;
4044 #endif
4045 ARMul_UndefInstr (state, instr);
4046 break;
4048 UNDEF_LSRBaseEQOffWb;
4049 UNDEF_LSRBaseEQDestWb;
4050 UNDEF_LSRPCBaseWb;
4051 UNDEF_LSRPCOffWb;
4052 temp = LHS + LSRegRHS;
4053 if (LoadWord (state, instr, temp))
4054 LSBase = temp;
4055 break;
4057 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
4058 if (BIT (4))
4060 #ifdef MODE32
4061 if (state->is_v6
4062 && handle_v6_insn (state, instr))
4063 break;
4064 #endif
4065 ARMul_UndefInstr (state, instr);
4066 break;
4068 (void) StoreByte (state, instr, LHS + LSRegRHS);
4069 break;
4071 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
4072 if (BIT (4))
4074 #ifdef MODE32
4075 if (state->is_v6
4076 && handle_v6_insn (state, instr))
4077 break;
4078 #endif
4079 ARMul_UndefInstr (state, instr);
4080 break;
4082 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
4083 break;
4085 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
4086 if (BIT (4))
4088 #ifdef MODE32
4089 if (state->is_v6
4090 && handle_v6_insn (state, instr))
4091 break;
4092 #endif
4093 ARMul_UndefInstr (state, instr);
4094 break;
4096 UNDEF_LSRBaseEQOffWb;
4097 UNDEF_LSRBaseEQDestWb;
4098 UNDEF_LSRPCBaseWb;
4099 UNDEF_LSRPCOffWb;
4100 temp = LHS + LSRegRHS;
4101 if (StoreByte (state, instr, temp))
4102 LSBase = temp;
4103 break;
4105 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
4106 if (BIT (4))
4108 /* Check for the special breakpoint opcode.
4109 This value should correspond to the value defined
4110 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
4111 if (BITS (0, 19) == 0xfdefe)
4113 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
4114 ARMul_Abort (state, ARMul_SWIV);
4116 #ifdef MODE32
4117 else if (state->is_v6
4118 && handle_v6_insn (state, instr))
4119 break;
4120 #endif
4121 else
4122 ARMul_UndefInstr (state, instr);
4123 break;
4125 UNDEF_LSRBaseEQOffWb;
4126 UNDEF_LSRBaseEQDestWb;
4127 UNDEF_LSRPCBaseWb;
4128 UNDEF_LSRPCOffWb;
4129 temp = LHS + LSRegRHS;
4130 if (LoadByte (state, instr, temp, LUNSIGNED))
4131 LSBase = temp;
4132 break;
4135 /* Multiple Data Transfer Instructions. */
4137 case 0x80: /* Store, No WriteBack, Post Dec. */
4138 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
4139 break;
4141 case 0x81: /* Load, No WriteBack, Post Dec. */
4142 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
4143 break;
4145 case 0x82: /* Store, WriteBack, Post Dec. */
4146 temp = LSBase - LSMNumRegs;
4147 STOREMULT (instr, temp + 4L, temp);
4148 break;
4150 case 0x83: /* Load, WriteBack, Post Dec. */
4151 temp = LSBase - LSMNumRegs;
4152 LOADMULT (instr, temp + 4L, temp);
4153 break;
4155 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
4156 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
4157 break;
4159 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
4160 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
4161 break;
4163 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
4164 temp = LSBase - LSMNumRegs;
4165 STORESMULT (instr, temp + 4L, temp);
4166 break;
4168 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
4169 temp = LSBase - LSMNumRegs;
4170 LOADSMULT (instr, temp + 4L, temp);
4171 break;
4173 case 0x88: /* Store, No WriteBack, Post Inc. */
4174 STOREMULT (instr, LSBase, 0L);
4175 break;
4177 case 0x89: /* Load, No WriteBack, Post Inc. */
4178 LOADMULT (instr, LSBase, 0L);
4179 break;
4181 case 0x8a: /* Store, WriteBack, Post Inc. */
4182 temp = LSBase;
4183 STOREMULT (instr, temp, temp + LSMNumRegs);
4184 break;
4186 case 0x8b: /* Load, WriteBack, Post Inc. */
4187 temp = LSBase;
4188 LOADMULT (instr, temp, temp + LSMNumRegs);
4189 break;
4191 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
4192 STORESMULT (instr, LSBase, 0L);
4193 break;
4195 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
4196 LOADSMULT (instr, LSBase, 0L);
4197 break;
4199 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
4200 temp = LSBase;
4201 STORESMULT (instr, temp, temp + LSMNumRegs);
4202 break;
4204 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
4205 temp = LSBase;
4206 LOADSMULT (instr, temp, temp + LSMNumRegs);
4207 break;
4209 case 0x90: /* Store, No WriteBack, Pre Dec. */
4210 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
4211 break;
4213 case 0x91: /* Load, No WriteBack, Pre Dec. */
4214 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
4215 break;
4217 case 0x92: /* Store, WriteBack, Pre Dec. */
4218 temp = LSBase - LSMNumRegs;
4219 STOREMULT (instr, temp, temp);
4220 break;
4222 case 0x93: /* Load, WriteBack, Pre Dec. */
4223 temp = LSBase - LSMNumRegs;
4224 LOADMULT (instr, temp, temp);
4225 break;
4227 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
4228 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
4229 break;
4231 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
4232 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
4233 break;
4235 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
4236 temp = LSBase - LSMNumRegs;
4237 STORESMULT (instr, temp, temp);
4238 break;
4240 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
4241 temp = LSBase - LSMNumRegs;
4242 LOADSMULT (instr, temp, temp);
4243 break;
4245 case 0x98: /* Store, No WriteBack, Pre Inc. */
4246 STOREMULT (instr, LSBase + 4L, 0L);
4247 break;
4249 case 0x99: /* Load, No WriteBack, Pre Inc. */
4250 LOADMULT (instr, LSBase + 4L, 0L);
4251 break;
4253 case 0x9a: /* Store, WriteBack, Pre Inc. */
4254 temp = LSBase;
4255 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
4256 break;
4258 case 0x9b: /* Load, WriteBack, Pre Inc. */
4259 temp = LSBase;
4260 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
4261 break;
4263 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
4264 STORESMULT (instr, LSBase + 4L, 0L);
4265 break;
4267 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
4268 LOADSMULT (instr, LSBase + 4L, 0L);
4269 break;
4271 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
4272 temp = LSBase;
4273 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
4274 break;
4276 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
4277 temp = LSBase;
4278 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
4279 break;
4282 /* Branch forward. */
4283 case 0xa0:
4284 case 0xa1:
4285 case 0xa2:
4286 case 0xa3:
4287 case 0xa4:
4288 case 0xa5:
4289 case 0xa6:
4290 case 0xa7:
4291 state->Reg[15] = pc + 8 + POSBRANCH;
4292 FLUSHPIPE;
4293 break;
4296 /* Branch backward. */
4297 case 0xa8:
4298 case 0xa9:
4299 case 0xaa:
4300 case 0xab:
4301 case 0xac:
4302 case 0xad:
4303 case 0xae:
4304 case 0xaf:
4305 state->Reg[15] = pc + 8 + NEGBRANCH;
4306 FLUSHPIPE;
4307 break;
4309 /* Branch and Link forward. */
4310 case 0xb0:
4311 case 0xb1:
4312 case 0xb2:
4313 case 0xb3:
4314 case 0xb4:
4315 case 0xb5:
4316 case 0xb6:
4317 case 0xb7:
4318 /* Put PC into Link. */
4319 #ifdef MODE32
4320 state->Reg[14] = pc + 4;
4321 #else
4322 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
4323 #endif
4324 state->Reg[15] = pc + 8 + POSBRANCH;
4325 FLUSHPIPE;
4326 if (trace_funcs)
4327 fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
4328 break;
4330 /* Branch and Link backward. */
4331 case 0xb8:
4332 case 0xb9:
4333 case 0xba:
4334 case 0xbb:
4335 case 0xbc:
4336 case 0xbd:
4337 case 0xbe:
4338 case 0xbf:
4339 /* Put PC into Link. */
4340 #ifdef MODE32
4341 state->Reg[14] = pc + 4;
4342 #else
4343 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
4344 #endif
4345 state->Reg[15] = pc + 8 + NEGBRANCH;
4346 FLUSHPIPE;
4347 if (trace_funcs)
4348 fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
4349 break;
4351 /* Co-Processor Data Transfers. */
4352 case 0xc4:
4353 if (state->is_v5)
4355 if (CPNum == 10 || CPNum == 11)
4356 handle_VFP_move (state, instr);
4357 /* Reading from R15 is UNPREDICTABLE. */
4358 else if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
4359 ARMul_UndefInstr (state, instr);
4360 /* Is access to coprocessor 0 allowed ? */
4361 else if (! CP_ACCESS_ALLOWED (state, CPNum))
4362 ARMul_UndefInstr (state, instr);
4363 /* Special treatment for XScale coprocessors. */
4364 else if (state->is_XScale)
4366 /* Only opcode 0 is supported. */
4367 if (BITS (4, 7) != 0x00)
4368 ARMul_UndefInstr (state, instr);
4369 /* Only coporcessor 0 is supported. */
4370 else if (CPNum != 0x00)
4371 ARMul_UndefInstr (state, instr);
4372 /* Only accumulator 0 is supported. */
4373 else if (BITS (0, 3) != 0x00)
4374 ARMul_UndefInstr (state, instr);
4375 else
4377 /* XScale MAR insn. Move two registers into accumulator. */
4378 state->Accumulator = state->Reg[BITS (12, 15)];
4379 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
4382 else
4383 /* FIXME: Not sure what to do for other v5 processors. */
4384 ARMul_UndefInstr (state, instr);
4385 break;
4387 ATTRIBUTE_FALLTHROUGH;
4389 case 0xc0: /* Store , No WriteBack , Post Dec. */
4390 ARMul_STC (state, instr, LHS);
4391 break;
4393 case 0xc5:
4394 if (state->is_v5)
4396 if (CPNum == 10 || CPNum == 11)
4397 handle_VFP_move (state, instr);
4398 /* Writes to R15 are UNPREDICATABLE. */
4399 else if (DESTReg == 15 || LHSReg == 15)
4400 ARMul_UndefInstr (state, instr);
4401 /* Is access to the coprocessor allowed ? */
4402 else if (! CP_ACCESS_ALLOWED (state, CPNum))
4403 ARMul_UndefInstr (state, instr);
4404 /* Special handling for XScale coprcoessors. */
4405 else if (state->is_XScale)
4407 /* Only opcode 0 is supported. */
4408 if (BITS (4, 7) != 0x00)
4409 ARMul_UndefInstr (state, instr);
4410 /* Only coprocessor 0 is supported. */
4411 else if (CPNum != 0x00)
4412 ARMul_UndefInstr (state, instr);
4413 /* Only accumulator 0 is supported. */
4414 else if (BITS (0, 3) != 0x00)
4415 ARMul_UndefInstr (state, instr);
4416 else
4418 /* XScale MRA insn. Move accumulator into two registers. */
4419 ARMword t1 = (state->Accumulator >> 32) & 255;
4421 if (t1 & 128)
4422 t1 -= 256;
4424 state->Reg[BITS (12, 15)] = state->Accumulator;
4425 state->Reg[BITS (16, 19)] = t1;
4426 break;
4429 else
4430 /* FIXME: Not sure what to do for other v5 processors. */
4431 ARMul_UndefInstr (state, instr);
4432 break;
4434 ATTRIBUTE_FALLTHROUGH;
4436 case 0xc1: /* Load , No WriteBack , Post Dec. */
4437 ARMul_LDC (state, instr, LHS);
4438 break;
4440 case 0xc2:
4441 case 0xc6: /* Store , WriteBack , Post Dec. */
4442 lhs = LHS;
4443 state->Base = lhs - LSCOff;
4444 ARMul_STC (state, instr, lhs);
4445 break;
4447 case 0xc3:
4448 case 0xc7: /* Load , WriteBack , Post Dec. */
4449 lhs = LHS;
4450 state->Base = lhs - LSCOff;
4451 ARMul_LDC (state, instr, lhs);
4452 break;
4454 case 0xc8:
4455 case 0xcc: /* Store , No WriteBack , Post Inc. */
4456 ARMul_STC (state, instr, LHS);
4457 break;
4459 case 0xc9:
4460 case 0xcd: /* Load , No WriteBack , Post Inc. */
4461 ARMul_LDC (state, instr, LHS);
4462 break;
4464 case 0xca:
4465 case 0xce: /* Store , WriteBack , Post Inc. */
4466 lhs = LHS;
4467 state->Base = lhs + LSCOff;
4468 ARMul_STC (state, instr, LHS);
4469 break;
4471 case 0xcb:
4472 case 0xcf: /* Load , WriteBack , Post Inc. */
4473 lhs = LHS;
4474 state->Base = lhs + LSCOff;
4475 ARMul_LDC (state, instr, LHS);
4476 break;
4478 case 0xd0:
4479 case 0xd4: /* Store , No WriteBack , Pre Dec. */
4480 ARMul_STC (state, instr, LHS - LSCOff);
4481 break;
4483 case 0xd1:
4484 case 0xd5: /* Load , No WriteBack , Pre Dec. */
4485 ARMul_LDC (state, instr, LHS - LSCOff);
4486 break;
4488 case 0xd2:
4489 case 0xd6: /* Store , WriteBack , Pre Dec. */
4490 lhs = LHS - LSCOff;
4491 state->Base = lhs;
4492 ARMul_STC (state, instr, lhs);
4493 break;
4495 case 0xd3:
4496 case 0xd7: /* Load , WriteBack , Pre Dec. */
4497 lhs = LHS - LSCOff;
4498 state->Base = lhs;
4499 ARMul_LDC (state, instr, lhs);
4500 break;
4502 case 0xd8:
4503 case 0xdc: /* Store , No WriteBack , Pre Inc. */
4504 ARMul_STC (state, instr, LHS + LSCOff);
4505 break;
4507 case 0xd9:
4508 case 0xdd: /* Load , No WriteBack , Pre Inc. */
4509 ARMul_LDC (state, instr, LHS + LSCOff);
4510 break;
4512 case 0xda:
4513 case 0xde: /* Store , WriteBack , Pre Inc. */
4514 lhs = LHS + LSCOff;
4515 state->Base = lhs;
4516 ARMul_STC (state, instr, lhs);
4517 break;
4519 case 0xdb:
4520 case 0xdf: /* Load , WriteBack , Pre Inc. */
4521 lhs = LHS + LSCOff;
4522 state->Base = lhs;
4523 ARMul_LDC (state, instr, lhs);
4524 break;
4527 /* Co-Processor Register Transfers (MCR) and Data Ops. */
4529 case 0xe2:
4530 if (! CP_ACCESS_ALLOWED (state, CPNum))
4532 ARMul_UndefInstr (state, instr);
4533 break;
4535 if (state->is_XScale)
4536 switch (BITS (18, 19))
4538 case 0x0:
4539 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4541 /* XScale MIA instruction. Signed multiplication of
4542 two 32 bit values and addition to 40 bit accumulator. */
4543 ARMsdword Rm = state->Reg[MULLHSReg];
4544 ARMsdword Rs = state->Reg[MULACCReg];
4546 if (Rm & (1 << 31))
4547 Rm -= 1ULL << 32;
4548 if (Rs & (1 << 31))
4549 Rs -= 1ULL << 32;
4550 state->Accumulator += Rm * Rs;
4551 goto donext;
4553 break;
4555 case 0x2:
4556 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4558 /* XScale MIAPH instruction. */
4559 ARMword t1 = state->Reg[MULLHSReg] >> 16;
4560 ARMword t2 = state->Reg[MULACCReg] >> 16;
4561 ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
4562 ARMword t4 = state->Reg[MULACCReg] & 0xffff;
4563 ARMsdword t5;
4565 if (t1 & (1 << 15))
4566 t1 -= 1 << 16;
4567 if (t2 & (1 << 15))
4568 t2 -= 1 << 16;
4569 if (t3 & (1 << 15))
4570 t3 -= 1 << 16;
4571 if (t4 & (1 << 15))
4572 t4 -= 1 << 16;
4573 t1 *= t2;
4574 t5 = t1;
4575 if (t5 & (1 << 31))
4576 t5 -= 1ULL << 32;
4577 state->Accumulator += t5;
4578 t3 *= t4;
4579 t5 = t3;
4580 if (t5 & (1 << 31))
4581 t5 -= 1ULL << 32;
4582 state->Accumulator += t5;
4583 goto donext;
4585 break;
4587 case 0x3:
4588 if (BITS (4, 11) == 1)
4590 /* XScale MIAxy instruction. */
4591 ARMword t1;
4592 ARMword t2;
4593 ARMsdword t5;
4595 if (BIT (17))
4596 t1 = state->Reg[MULLHSReg] >> 16;
4597 else
4598 t1 = state->Reg[MULLHSReg] & 0xffff;
4600 if (BIT (16))
4601 t2 = state->Reg[MULACCReg] >> 16;
4602 else
4603 t2 = state->Reg[MULACCReg] & 0xffff;
4605 if (t1 & (1 << 15))
4606 t1 -= 1 << 16;
4607 if (t2 & (1 << 15))
4608 t2 -= 1 << 16;
4609 t1 *= t2;
4610 t5 = t1;
4611 if (t5 & (1 << 31))
4612 t5 -= 1ULL << 32;
4613 state->Accumulator += t5;
4614 goto donext;
4616 break;
4618 default:
4619 break;
4621 ATTRIBUTE_FALLTHROUGH;
4623 case 0xe0:
4624 case 0xe4:
4625 case 0xe6:
4626 case 0xe8:
4627 case 0xea:
4628 case 0xec:
4629 case 0xee:
4630 if (BIT (4))
4632 if (CPNum == 10 || CPNum == 11)
4633 handle_VFP_move (state, instr);
4634 /* MCR. */
4635 else if (DESTReg == 15)
4637 UNDEF_MCRPC;
4638 #ifdef MODE32
4639 ARMul_MCR (state, instr, state->Reg[15] + isize);
4640 #else
4641 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
4642 ((state->Reg[15] + isize) & R15PCBITS));
4643 #endif
4645 else
4646 ARMul_MCR (state, instr, DEST);
4648 else
4649 /* CDP Part 1. */
4650 ARMul_CDP (state, instr);
4651 break;
4654 /* Co-Processor Register Transfers (MRC) and Data Ops. */
4655 case 0xe1:
4656 case 0xe3:
4657 case 0xe5:
4658 case 0xe7:
4659 case 0xe9:
4660 case 0xeb:
4661 case 0xed:
4662 case 0xef:
4663 if (BIT (4))
4665 if (CPNum == 10 || CPNum == 11)
4667 switch (BITS (20, 27))
4669 case 0xEF:
4670 if (BITS (16, 19) == 0x1
4671 && BITS (0, 11) == 0xA10)
4673 /* VMRS */
4674 if (DESTReg == 15)
4676 ARMul_SetCPSR (state, (state->FPSCR & 0xF0000000)
4677 | (ARMul_GetCPSR (state) & 0x0FFFFFFF));
4679 if (trace)
4680 fprintf (stderr, " VFP: VMRS: set flags to %c%c%c%c\n",
4681 ARMul_GetCPSR (state) & NBIT ? 'N' : '-',
4682 ARMul_GetCPSR (state) & ZBIT ? 'Z' : '-',
4683 ARMul_GetCPSR (state) & CBIT ? 'C' : '-',
4684 ARMul_GetCPSR (state) & VBIT ? 'V' : '-');
4686 else
4688 state->Reg[DESTReg] = state->FPSCR;
4690 if (trace)
4691 fprintf (stderr, " VFP: VMRS: r%d = %x\n", DESTReg, state->Reg[DESTReg]);
4694 else
4695 fprintf (stderr, "SIM: VFP: Unimplemented: Compare op\n");
4696 break;
4698 case 0xE0:
4699 case 0xE1:
4700 /* VMOV reg <-> single precision. */
4701 if (BITS (0,6) != 0x10 || BITS (8,11) != 0xA)
4702 fprintf (stderr, "SIM: VFP: Unimplemented: move op\n");
4703 else if (BIT (20))
4704 state->Reg[BITS (12, 15)] = VFP_uword (BITS (16, 19) << 1 | BIT (7));
4705 else
4706 VFP_uword (BITS (16, 19) << 1 | BIT (7)) = state->Reg[BITS (12, 15)];
4707 break;
4709 default:
4710 fprintf (stderr, "SIM: VFP: Unimplemented: CDP op\n");
4711 break;
4714 else
4716 /* MRC */
4717 temp = ARMul_MRC (state, instr);
4718 if (DESTReg == 15)
4720 ASSIGNN ((temp & NBIT) != 0);
4721 ASSIGNZ ((temp & ZBIT) != 0);
4722 ASSIGNC ((temp & CBIT) != 0);
4723 ASSIGNV ((temp & VBIT) != 0);
4725 else
4726 DEST = temp;
4729 else
4730 /* CDP Part 2. */
4731 ARMul_CDP (state, instr);
4732 break;
4735 /* SWI instruction. */
4736 case 0xf0:
4737 case 0xf1:
4738 case 0xf2:
4739 case 0xf3:
4740 case 0xf4:
4741 case 0xf5:
4742 case 0xf6:
4743 case 0xf7:
4744 case 0xf8:
4745 case 0xf9:
4746 case 0xfa:
4747 case 0xfb:
4748 case 0xfc:
4749 case 0xfd:
4750 case 0xfe:
4751 case 0xff:
4752 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
4754 /* A prefetch abort. */
4755 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
4756 ARMul_Abort (state, ARMul_PrefetchAbortV);
4757 break;
4760 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
4761 ARMul_Abort (state, ARMul_SWIV);
4763 break;
4767 #ifdef MODET
4768 donext:
4769 #endif
4771 if (state->Emulate == ONCE)
4772 state->Emulate = STOP;
4773 /* If we have changed mode, allow the PC to advance before stopping. */
4774 else if (state->Emulate == CHANGEMODE)
4775 continue;
4776 else if (state->Emulate != RUN)
4777 break;
4779 while (!stop_simulator);
4781 state->decoded = decoded;
4782 state->loaded = loaded;
4783 state->pc = pc;
4785 return pc;
4788 /* This routine evaluates most Data Processing register RHS's with the S
4789 bit clear. It is intended to be called from the macro DPRegRHS, which
4790 filters the common case of an unshifted register with in line code. */
4792 static ARMword
4793 GetDPRegRHS (ARMul_State * state, ARMword instr)
4795 ARMword shamt, base;
4797 base = RHSReg;
4798 if (BIT (4))
4800 /* Shift amount in a register. */
4801 UNDEF_Shift;
4802 INCPC;
4803 #ifndef MODE32
4804 if (base == 15)
4805 base = ECC | ER15INT | R15PC | EMODE;
4806 else
4807 #endif
4808 base = state->Reg[base];
4809 ARMul_Icycles (state, 1, 0L);
4810 shamt = state->Reg[BITS (8, 11)] & 0xff;
4811 switch ((int) BITS (5, 6))
4813 case LSL:
4814 if (shamt == 0)
4815 return (base);
4816 else if (shamt >= 32)
4817 return (0);
4818 else
4819 return (base << shamt);
4820 case LSR:
4821 if (shamt == 0)
4822 return (base);
4823 else if (shamt >= 32)
4824 return (0);
4825 else
4826 return (base >> shamt);
4827 case ASR:
4828 if (shamt == 0)
4829 return (base);
4830 else if (shamt >= 32)
4831 return ((ARMword) ((ARMsword) base >> 31L));
4832 else
4833 return ((ARMword) ((ARMsword) base >> (int) shamt));
4834 case ROR:
4835 shamt &= 0x1f;
4836 if (shamt == 0)
4837 return (base);
4838 else
4839 return ((base << (32 - shamt)) | (base >> shamt));
4842 else
4844 /* Shift amount is a constant. */
4845 #ifndef MODE32
4846 if (base == 15)
4847 base = ECC | ER15INT | R15PC | EMODE;
4848 else
4849 #endif
4850 base = state->Reg[base];
4851 shamt = BITS (7, 11);
4852 switch ((int) BITS (5, 6))
4854 case LSL:
4855 return (base << shamt);
4856 case LSR:
4857 if (shamt == 0)
4858 return (0);
4859 else
4860 return (base >> shamt);
4861 case ASR:
4862 if (shamt == 0)
4863 return ((ARMword) ((ARMsword) base >> 31L));
4864 else
4865 return ((ARMword) ((ARMsword) base >> (int) shamt));
4866 case ROR:
4867 if (shamt == 0)
4868 /* It's an RRX. */
4869 return ((base >> 1) | (CFLAG << 31));
4870 else
4871 return ((base << (32 - shamt)) | (base >> shamt));
4875 return 0;
4878 /* This routine evaluates most Logical Data Processing register RHS's
4879 with the S bit set. It is intended to be called from the macro
4880 DPSRegRHS, which filters the common case of an unshifted register
4881 with in line code. */
4883 static ARMword
4884 GetDPSRegRHS (ARMul_State * state, ARMword instr)
4886 ARMword shamt, base;
4888 base = RHSReg;
4889 if (BIT (4))
4891 /* Shift amount in a register. */
4892 UNDEF_Shift;
4893 INCPC;
4894 #ifndef MODE32
4895 if (base == 15)
4896 base = ECC | ER15INT | R15PC | EMODE;
4897 else
4898 #endif
4899 base = state->Reg[base];
4900 ARMul_Icycles (state, 1, 0L);
4901 shamt = state->Reg[BITS (8, 11)] & 0xff;
4902 switch ((int) BITS (5, 6))
4904 case LSL:
4905 if (shamt == 0)
4906 return (base);
4907 else if (shamt == 32)
4909 ASSIGNC (base & 1);
4910 return (0);
4912 else if (shamt > 32)
4914 CLEARC;
4915 return (0);
4917 else
4919 ASSIGNC ((base >> (32 - shamt)) & 1);
4920 return (base << shamt);
4922 case LSR:
4923 if (shamt == 0)
4924 return (base);
4925 else if (shamt == 32)
4927 ASSIGNC (base >> 31);
4928 return (0);
4930 else if (shamt > 32)
4932 CLEARC;
4933 return (0);
4935 else
4937 ASSIGNC ((base >> (shamt - 1)) & 1);
4938 return (base >> shamt);
4940 case ASR:
4941 if (shamt == 0)
4942 return (base);
4943 else if (shamt >= 32)
4945 ASSIGNC (base >> 31L);
4946 return ((ARMword) ((ARMsword) base >> 31L));
4948 else
4950 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
4951 return ((ARMword) ((ARMsword) base >> (int) shamt));
4953 case ROR:
4954 if (shamt == 0)
4955 return (base);
4956 shamt &= 0x1f;
4957 if (shamt == 0)
4959 ASSIGNC (base >> 31);
4960 return (base);
4962 else
4964 ASSIGNC ((base >> (shamt - 1)) & 1);
4965 return ((base << (32 - shamt)) | (base >> shamt));
4969 else
4971 /* Shift amount is a constant. */
4972 #ifndef MODE32
4973 if (base == 15)
4974 base = ECC | ER15INT | R15PC | EMODE;
4975 else
4976 #endif
4977 base = state->Reg[base];
4978 shamt = BITS (7, 11);
4980 switch ((int) BITS (5, 6))
4982 case LSL:
4983 ASSIGNC ((base >> (32 - shamt)) & 1);
4984 return (base << shamt);
4985 case LSR:
4986 if (shamt == 0)
4988 ASSIGNC (base >> 31);
4989 return (0);
4991 else
4993 ASSIGNC ((base >> (shamt - 1)) & 1);
4994 return (base >> shamt);
4996 case ASR:
4997 if (shamt == 0)
4999 ASSIGNC (base >> 31L);
5000 return ((ARMword) ((ARMsword) base >> 31L));
5002 else
5004 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
5005 return ((ARMword) ((ARMsword) base >> (int) shamt));
5007 case ROR:
5008 if (shamt == 0)
5010 /* It's an RRX. */
5011 shamt = CFLAG;
5012 ASSIGNC (base & 1);
5013 return ((base >> 1) | (shamt << 31));
5015 else
5017 ASSIGNC ((base >> (shamt - 1)) & 1);
5018 return ((base << (32 - shamt)) | (base >> shamt));
5023 return 0;
5026 /* This routine handles writes to register 15 when the S bit is not set. */
5028 static void
5029 WriteR15 (ARMul_State * state, ARMword src)
5031 /* The ARM documentation states that the two least significant bits
5032 are discarded when setting PC, except in the cases handled by
5033 WriteR15Branch() below. It's probably an oversight: in THUMB
5034 mode, the second least significant bit should probably not be
5035 discarded. */
5036 #ifdef MODET
5037 if (TFLAG)
5038 src &= 0xfffffffe;
5039 else
5040 #endif
5041 src &= 0xfffffffc;
5043 #ifdef MODE32
5044 state->Reg[15] = src & PCBITS;
5045 #else
5046 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
5047 ARMul_R15Altered (state);
5048 #endif
5050 FLUSHPIPE;
5051 if (trace_funcs)
5052 fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
5055 /* This routine handles writes to register 15 when the S bit is set. */
5057 static void
5058 WriteSR15 (ARMul_State * state, ARMword src)
5060 #ifdef MODE32
5061 if (state->Bank > 0)
5063 state->Cpsr = state->Spsr[state->Bank];
5064 ARMul_CPSRAltered (state);
5066 #ifdef MODET
5067 if (TFLAG)
5068 src &= 0xfffffffe;
5069 else
5070 #endif
5071 src &= 0xfffffffc;
5072 state->Reg[15] = src & PCBITS;
5073 #else
5074 #ifdef MODET
5075 if (TFLAG)
5076 /* ARMul_R15Altered would have to support it. */
5077 abort ();
5078 else
5079 #endif
5080 src &= 0xfffffffc;
5082 if (state->Bank == USERBANK)
5083 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
5084 else
5085 state->Reg[15] = src;
5087 ARMul_R15Altered (state);
5088 #endif
5089 FLUSHPIPE;
5090 if (trace_funcs)
5091 fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
5094 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
5095 will switch to Thumb mode if the least significant bit is set. */
5097 static void
5098 WriteR15Branch (ARMul_State * state, ARMword src)
5100 #ifdef MODET
5101 if (src & 1)
5103 /* Thumb bit. */
5104 SETT;
5105 state->Reg[15] = src & 0xfffffffe;
5107 else
5109 CLEART;
5110 state->Reg[15] = src & 0xfffffffc;
5112 FLUSHPIPE;
5113 if (trace_funcs)
5114 fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
5115 #else
5116 WriteR15 (state, src);
5117 #endif
5120 /* Before ARM_v5 LDR and LDM of pc did not change mode. */
5122 static void
5123 WriteR15Load (ARMul_State * state, ARMword src)
5125 if (state->is_v5)
5126 WriteR15Branch (state, src);
5127 else
5128 WriteR15 (state, src);
5131 /* This routine evaluates most Load and Store register RHS's. It is
5132 intended to be called from the macro LSRegRHS, which filters the
5133 common case of an unshifted register with in line code. */
5135 static ARMword
5136 GetLSRegRHS (ARMul_State * state, ARMword instr)
5138 ARMword shamt, base;
5140 base = RHSReg;
5141 #ifndef MODE32
5142 if (base == 15)
5143 /* Now forbidden, but ... */
5144 base = ECC | ER15INT | R15PC | EMODE;
5145 else
5146 #endif
5147 base = state->Reg[base];
5149 shamt = BITS (7, 11);
5150 switch ((int) BITS (5, 6))
5152 case LSL:
5153 return (base << shamt);
5154 case LSR:
5155 if (shamt == 0)
5156 return (0);
5157 else
5158 return (base >> shamt);
5159 case ASR:
5160 if (shamt == 0)
5161 return ((ARMword) ((ARMsword) base >> 31L));
5162 else
5163 return ((ARMword) ((ARMsword) base >> (int) shamt));
5164 case ROR:
5165 if (shamt == 0)
5166 /* It's an RRX. */
5167 return ((base >> 1) | (CFLAG << 31));
5168 else
5169 return ((base << (32 - shamt)) | (base >> shamt));
5170 default:
5171 break;
5173 return 0;
5176 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
5178 static ARMword
5179 GetLS7RHS (ARMul_State * state, ARMword instr)
5181 if (BIT (22) == 0)
5183 /* Register. */
5184 #ifndef MODE32
5185 if (RHSReg == 15)
5186 /* Now forbidden, but ... */
5187 return ECC | ER15INT | R15PC | EMODE;
5188 #endif
5189 return state->Reg[RHSReg];
5192 /* Immediate. */
5193 return BITS (0, 3) | (BITS (8, 11) << 4);
5196 /* This function does the work of loading a word for a LDR instruction. */
5198 static unsigned
5199 LoadWord (ARMul_State * state, ARMword instr, ARMword address)
5201 ARMword dest;
5203 BUSUSEDINCPCS;
5204 #ifndef MODE32
5205 if (ADDREXCEPT (address))
5206 INTERNALABORT (address);
5207 #endif
5209 dest = ARMul_LoadWordN (state, address);
5211 if (state->Aborted)
5213 TAKEABORT;
5214 return state->lateabtSig;
5216 if (address & 3)
5217 dest = ARMul_Align (state, address, dest);
5218 WRITEDESTB (dest);
5219 ARMul_Icycles (state, 1, 0L);
5221 return (DESTReg != LHSReg);
5224 #ifdef MODET
5225 /* This function does the work of loading a halfword. */
5227 static unsigned
5228 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
5229 int signextend)
5231 ARMword dest;
5233 BUSUSEDINCPCS;
5234 #ifndef MODE32
5235 if (ADDREXCEPT (address))
5236 INTERNALABORT (address);
5237 #endif
5238 dest = ARMul_LoadHalfWord (state, address);
5239 if (state->Aborted)
5241 TAKEABORT;
5242 return state->lateabtSig;
5244 UNDEF_LSRBPC;
5245 if (signextend)
5246 if (dest & 1 << (16 - 1))
5247 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
5249 WRITEDEST (dest);
5250 ARMul_Icycles (state, 1, 0L);
5251 return (DESTReg != LHSReg);
5254 #endif /* MODET */
5256 /* This function does the work of loading a byte for a LDRB instruction. */
5258 static unsigned
5259 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
5261 ARMword dest;
5263 BUSUSEDINCPCS;
5264 #ifndef MODE32
5265 if (ADDREXCEPT (address))
5266 INTERNALABORT (address);
5267 #endif
5268 dest = ARMul_LoadByte (state, address);
5269 if (state->Aborted)
5271 TAKEABORT;
5272 return state->lateabtSig;
5274 UNDEF_LSRBPC;
5275 if (signextend)
5276 if (dest & 1 << (8 - 1))
5277 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
5279 WRITEDEST (dest);
5280 ARMul_Icycles (state, 1, 0L);
5282 return (DESTReg != LHSReg);
5285 /* This function does the work of loading two words for a LDRD instruction. */
5287 static void
5288 Handle_Load_Double (ARMul_State * state, ARMword instr)
5290 ARMword dest_reg;
5291 ARMword addr_reg;
5292 ARMword write_back = BIT (21);
5293 ARMword immediate = BIT (22);
5294 ARMword add_to_base = BIT (23);
5295 ARMword pre_indexed = BIT (24);
5296 ARMword offset;
5297 ARMword addr;
5298 ARMword sum;
5299 ARMword base;
5300 ARMword value1;
5301 ARMword value2;
5303 BUSUSEDINCPCS;
5305 /* If the writeback bit is set, the pre-index bit must be clear. */
5306 if (write_back && ! pre_indexed)
5308 ARMul_UndefInstr (state, instr);
5309 return;
5312 /* Extract the base address register. */
5313 addr_reg = LHSReg;
5315 /* Extract the destination register and check it. */
5316 dest_reg = DESTReg;
5318 /* Destination register must be even. */
5319 if ((dest_reg & 1)
5320 /* Destination register cannot be LR. */
5321 || (dest_reg == 14))
5323 ARMul_UndefInstr (state, instr);
5324 return;
5327 /* Compute the base address. */
5328 base = state->Reg[addr_reg];
5330 /* Compute the offset. */
5331 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
5333 /* Compute the sum of the two. */
5334 if (add_to_base)
5335 sum = base + offset;
5336 else
5337 sum = base - offset;
5339 /* If this is a pre-indexed mode use the sum. */
5340 if (pre_indexed)
5341 addr = sum;
5342 else
5343 addr = base;
5345 if (state->is_v6 && (addr & 0x3) == 0)
5346 /* Word alignment is enough for v6. */
5348 /* The address must be aligned on a 8 byte boundary. */
5349 else if (addr & 0x7)
5351 #ifdef ABORTS
5352 ARMul_DATAABORT (addr);
5353 #else
5354 ARMul_UndefInstr (state, instr);
5355 #endif
5356 return;
5359 /* For pre indexed or post indexed addressing modes,
5360 check that the destination registers do not overlap
5361 the address registers. */
5362 if ((! pre_indexed || write_back)
5363 && ( addr_reg == dest_reg
5364 || addr_reg == dest_reg + 1))
5366 ARMul_UndefInstr (state, instr);
5367 return;
5370 /* Load the words. */
5371 value1 = ARMul_LoadWordN (state, addr);
5372 value2 = ARMul_LoadWordN (state, addr + 4);
5374 /* Check for data aborts. */
5375 if (state->Aborted)
5377 TAKEABORT;
5378 return;
5381 ARMul_Icycles (state, 2, 0L);
5383 /* Store the values. */
5384 state->Reg[dest_reg] = value1;
5385 state->Reg[dest_reg + 1] = value2;
5387 /* Do the post addressing and writeback. */
5388 if (! pre_indexed)
5389 addr = sum;
5391 if (! pre_indexed || write_back)
5392 state->Reg[addr_reg] = addr;
5395 /* This function does the work of storing two words for a STRD instruction. */
5397 static void
5398 Handle_Store_Double (ARMul_State * state, ARMword instr)
5400 ARMword src_reg;
5401 ARMword addr_reg;
5402 ARMword write_back = BIT (21);
5403 ARMword immediate = BIT (22);
5404 ARMword add_to_base = BIT (23);
5405 ARMword pre_indexed = BIT (24);
5406 ARMword offset;
5407 ARMword addr;
5408 ARMword sum;
5409 ARMword base;
5411 BUSUSEDINCPCS;
5413 /* If the writeback bit is set, the pre-index bit must be clear. */
5414 if (write_back && ! pre_indexed)
5416 ARMul_UndefInstr (state, instr);
5417 return;
5420 /* Extract the base address register. */
5421 addr_reg = LHSReg;
5423 /* Base register cannot be PC. */
5424 if (addr_reg == 15)
5426 ARMul_UndefInstr (state, instr);
5427 return;
5430 /* Extract the source register. */
5431 src_reg = DESTReg;
5433 /* Source register must be even. */
5434 if (src_reg & 1)
5436 ARMul_UndefInstr (state, instr);
5437 return;
5440 /* Compute the base address. */
5441 base = state->Reg[addr_reg];
5443 /* Compute the offset. */
5444 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
5446 /* Compute the sum of the two. */
5447 if (add_to_base)
5448 sum = base + offset;
5449 else
5450 sum = base - offset;
5452 /* If this is a pre-indexed mode use the sum. */
5453 if (pre_indexed)
5454 addr = sum;
5455 else
5456 addr = base;
5458 /* The address must be aligned on a 8 byte boundary. */
5459 if (state->is_v6 && (addr & 0x3) == 0)
5460 /* Word alignment is enough for v6. */
5462 else if (addr & 0x7)
5464 #ifdef ABORTS
5465 ARMul_DATAABORT (addr);
5466 #else
5467 ARMul_UndefInstr (state, instr);
5468 #endif
5469 return;
5472 /* For pre indexed or post indexed addressing modes,
5473 check that the destination registers do not overlap
5474 the address registers. */
5475 if ((! pre_indexed || write_back)
5476 && ( addr_reg == src_reg
5477 || addr_reg == src_reg + 1))
5479 ARMul_UndefInstr (state, instr);
5480 return;
5483 /* Load the words. */
5484 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
5485 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
5487 if (state->Aborted)
5489 TAKEABORT;
5490 return;
5493 /* Do the post addressing and writeback. */
5494 if (! pre_indexed)
5495 addr = sum;
5497 if (! pre_indexed || write_back)
5498 state->Reg[addr_reg] = addr;
5501 /* This function does the work of storing a word from a STR instruction. */
5503 static unsigned
5504 StoreWord (ARMul_State * state, ARMword instr, ARMword address)
5506 BUSUSEDINCPCN;
5507 #ifndef MODE32
5508 if (DESTReg == 15)
5509 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
5510 #endif
5511 #ifdef MODE32
5512 ARMul_StoreWordN (state, address, DEST);
5513 #else
5514 if (VECTORACCESS (address) || ADDREXCEPT (address))
5516 INTERNALABORT (address);
5517 (void) ARMul_LoadWordN (state, address);
5519 else
5520 ARMul_StoreWordN (state, address, DEST);
5521 #endif
5522 if (state->Aborted)
5524 TAKEABORT;
5525 return state->lateabtSig;
5527 return TRUE;
5530 #ifdef MODET
5531 /* This function does the work of storing a byte for a STRH instruction. */
5533 static unsigned
5534 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
5536 BUSUSEDINCPCN;
5538 #ifndef MODE32
5539 if (DESTReg == 15)
5540 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
5541 #endif
5543 #ifdef MODE32
5544 ARMul_StoreHalfWord (state, address, DEST);
5545 #else
5546 if (VECTORACCESS (address) || ADDREXCEPT (address))
5548 INTERNALABORT (address);
5549 (void) ARMul_LoadHalfWord (state, address);
5551 else
5552 ARMul_StoreHalfWord (state, address, DEST);
5553 #endif
5555 if (state->Aborted)
5557 TAKEABORT;
5558 return state->lateabtSig;
5560 return TRUE;
5563 #endif /* MODET */
5565 /* This function does the work of storing a byte for a STRB instruction. */
5567 static unsigned
5568 StoreByte (ARMul_State * state, ARMword instr, ARMword address)
5570 BUSUSEDINCPCN;
5571 #ifndef MODE32
5572 if (DESTReg == 15)
5573 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
5574 #endif
5575 #ifdef MODE32
5576 ARMul_StoreByte (state, address, DEST);
5577 #else
5578 if (VECTORACCESS (address) || ADDREXCEPT (address))
5580 INTERNALABORT (address);
5581 (void) ARMul_LoadByte (state, address);
5583 else
5584 ARMul_StoreByte (state, address, DEST);
5585 #endif
5586 if (state->Aborted)
5588 TAKEABORT;
5589 return state->lateabtSig;
5591 UNDEF_LSRBPC;
5592 return TRUE;
5595 /* This function does the work of loading the registers listed in an LDM
5596 instruction, when the S bit is clear. The code here is always increment
5597 after, it's up to the caller to get the input address correct and to
5598 handle base register modification. */
5600 static void
5601 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
5603 ARMword dest, temp;
5605 UNDEF_LSMNoRegs;
5606 UNDEF_LSMPCBase;
5607 UNDEF_LSMBaseInListWb;
5608 BUSUSEDINCPCS;
5609 #ifndef MODE32
5610 if (ADDREXCEPT (address))
5611 INTERNALABORT (address);
5612 #endif
5613 if (BIT (21) && LHSReg != 15)
5614 LSBase = WBBase;
5616 /* N cycle first. */
5617 for (temp = 0; !BIT (temp); temp++)
5620 dest = ARMul_LoadWordN (state, address);
5622 if (!state->abortSig && !state->Aborted)
5623 state->Reg[temp++] = dest;
5624 else if (!state->Aborted)
5626 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5627 state->Aborted = ARMul_DataAbortV;
5630 /* S cycles from here on. */
5631 for (; temp < 16; temp ++)
5632 if (BIT (temp))
5634 /* Load this register. */
5635 address += 4;
5636 dest = ARMul_LoadWordS (state, address);
5638 if (!state->abortSig && !state->Aborted)
5639 state->Reg[temp] = dest;
5640 else if (!state->Aborted)
5642 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5643 state->Aborted = ARMul_DataAbortV;
5647 if (BIT (15) && !state->Aborted)
5648 /* PC is in the reg list. */
5649 WriteR15Load (state, PC);
5651 /* To write back the final register. */
5652 ARMul_Icycles (state, 1, 0L);
5654 if (state->Aborted)
5656 if (BIT (21) && LHSReg != 15)
5657 LSBase = WBBase;
5658 TAKEABORT;
5662 /* This function does the work of loading the registers listed in an LDM
5663 instruction, when the S bit is set. The code here is always increment
5664 after, it's up to the caller to get the input address correct and to
5665 handle base register modification. */
5667 static void
5668 LoadSMult (ARMul_State * state,
5669 ARMword instr,
5670 ARMword address,
5671 ARMword WBBase)
5673 ARMword dest, temp;
5675 UNDEF_LSMNoRegs;
5676 UNDEF_LSMPCBase;
5677 UNDEF_LSMBaseInListWb;
5679 BUSUSEDINCPCS;
5681 #ifndef MODE32
5682 if (ADDREXCEPT (address))
5683 INTERNALABORT (address);
5684 #endif
5686 if (BIT (21) && LHSReg != 15)
5687 LSBase = WBBase;
5689 if (!BIT (15) && state->Bank != USERBANK)
5691 /* Temporary reg bank switch. */
5692 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
5693 UNDEF_LSMUserBankWb;
5696 /* N cycle first. */
5697 for (temp = 0; !BIT (temp); temp ++)
5700 dest = ARMul_LoadWordN (state, address);
5702 if (!state->abortSig)
5703 state->Reg[temp++] = dest;
5704 else if (!state->Aborted)
5706 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5707 state->Aborted = ARMul_DataAbortV;
5710 /* S cycles from here on. */
5711 for (; temp < 16; temp++)
5712 if (BIT (temp))
5714 /* Load this register. */
5715 address += 4;
5716 dest = ARMul_LoadWordS (state, address);
5718 if (!state->abortSig && !state->Aborted)
5719 state->Reg[temp] = dest;
5720 else if (!state->Aborted)
5722 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5723 state->Aborted = ARMul_DataAbortV;
5727 if (BIT (15) && !state->Aborted)
5729 /* PC is in the reg list. */
5730 #ifdef MODE32
5731 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
5733 state->Cpsr = GETSPSR (state->Bank);
5734 ARMul_CPSRAltered (state);
5737 WriteR15 (state, PC);
5738 #else
5739 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
5741 /* Protect bits in user mode. */
5742 ASSIGNN ((state->Reg[15] & NBIT) != 0);
5743 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
5744 ASSIGNC ((state->Reg[15] & CBIT) != 0);
5745 ASSIGNV ((state->Reg[15] & VBIT) != 0);
5747 else
5748 ARMul_R15Altered (state);
5750 FLUSHPIPE;
5751 #endif
5754 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
5755 /* Restore the correct bank. */
5756 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
5758 /* To write back the final register. */
5759 ARMul_Icycles (state, 1, 0L);
5761 if (state->Aborted)
5763 if (BIT (21) && LHSReg != 15)
5764 LSBase = WBBase;
5766 TAKEABORT;
5770 /* This function does the work of storing the registers listed in an STM
5771 instruction, when the S bit is clear. The code here is always increment
5772 after, it's up to the caller to get the input address correct and to
5773 handle base register modification. */
5775 static void
5776 StoreMult (ARMul_State * state,
5777 ARMword instr,
5778 ARMword address,
5779 ARMword WBBase)
5781 ARMword temp;
5783 UNDEF_LSMNoRegs;
5784 UNDEF_LSMPCBase;
5785 UNDEF_LSMBaseInListWb;
5787 if (!TFLAG)
5788 /* N-cycle, increment the PC and update the NextInstr state. */
5789 BUSUSEDINCPCN;
5791 #ifndef MODE32
5792 if (VECTORACCESS (address) || ADDREXCEPT (address))
5793 INTERNALABORT (address);
5795 if (BIT (15))
5796 PATCHR15;
5797 #endif
5799 /* N cycle first. */
5800 for (temp = 0; !BIT (temp); temp ++)
5803 #ifdef MODE32
5804 ARMul_StoreWordN (state, address, state->Reg[temp++]);
5805 #else
5806 if (state->Aborted)
5808 (void) ARMul_LoadWordN (state, address);
5810 /* Fake the Stores as Loads. */
5811 for (; temp < 16; temp++)
5812 if (BIT (temp))
5814 /* Save this register. */
5815 address += 4;
5816 (void) ARMul_LoadWordS (state, address);
5819 if (BIT (21) && LHSReg != 15)
5820 LSBase = WBBase;
5821 TAKEABORT;
5822 return;
5824 else
5825 ARMul_StoreWordN (state, address, state->Reg[temp++]);
5826 #endif
5828 if (state->abortSig && !state->Aborted)
5830 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5831 state->Aborted = ARMul_DataAbortV;
5834 if (BIT (21) && LHSReg != 15)
5835 LSBase = WBBase;
5837 /* S cycles from here on. */
5838 for (; temp < 16; temp ++)
5839 if (BIT (temp))
5841 /* Save this register. */
5842 address += 4;
5844 ARMul_StoreWordS (state, address, state->Reg[temp]);
5846 if (state->abortSig && !state->Aborted)
5848 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5849 state->Aborted = ARMul_DataAbortV;
5853 if (state->Aborted)
5854 TAKEABORT;
5857 /* This function does the work of storing the registers listed in an STM
5858 instruction when the S bit is set. The code here is always increment
5859 after, it's up to the caller to get the input address correct and to
5860 handle base register modification. */
5862 static void
5863 StoreSMult (ARMul_State * state,
5864 ARMword instr,
5865 ARMword address,
5866 ARMword WBBase)
5868 ARMword temp;
5870 UNDEF_LSMNoRegs;
5871 UNDEF_LSMPCBase;
5872 UNDEF_LSMBaseInListWb;
5874 BUSUSEDINCPCN;
5876 #ifndef MODE32
5877 if (VECTORACCESS (address) || ADDREXCEPT (address))
5878 INTERNALABORT (address);
5880 if (BIT (15))
5881 PATCHR15;
5882 #endif
5884 if (state->Bank != USERBANK)
5886 /* Force User Bank. */
5887 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
5888 UNDEF_LSMUserBankWb;
5891 for (temp = 0; !BIT (temp); temp++)
5892 ; /* N cycle first. */
5894 #ifdef MODE32
5895 ARMul_StoreWordN (state, address, state->Reg[temp++]);
5896 #else
5897 if (state->Aborted)
5899 (void) ARMul_LoadWordN (state, address);
5901 for (; temp < 16; temp++)
5902 /* Fake the Stores as Loads. */
5903 if (BIT (temp))
5905 /* Save this register. */
5906 address += 4;
5908 (void) ARMul_LoadWordS (state, address);
5911 if (BIT (21) && LHSReg != 15)
5912 LSBase = WBBase;
5914 TAKEABORT;
5915 return;
5917 else
5918 ARMul_StoreWordN (state, address, state->Reg[temp++]);
5919 #endif
5921 if (state->abortSig && !state->Aborted)
5923 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5924 state->Aborted = ARMul_DataAbortV;
5927 /* S cycles from here on. */
5928 for (; temp < 16; temp++)
5929 if (BIT (temp))
5931 /* Save this register. */
5932 address += 4;
5934 ARMul_StoreWordS (state, address, state->Reg[temp]);
5936 if (state->abortSig && !state->Aborted)
5938 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5939 state->Aborted = ARMul_DataAbortV;
5943 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
5944 /* Restore the correct bank. */
5945 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
5947 if (BIT (21) && LHSReg != 15)
5948 LSBase = WBBase;
5950 if (state->Aborted)
5951 TAKEABORT;
5954 /* This function does the work of adding two 32bit values
5955 together, and calculating if a carry has occurred. */
5957 static ARMword
5958 Add32 (ARMword a1, ARMword a2, int *carry)
5960 ARMword result = (a1 + a2);
5961 unsigned int uresult = (unsigned int) result;
5962 unsigned int ua1 = (unsigned int) a1;
5964 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5965 or (result > RdLo) then we have no carry. */
5966 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
5967 *carry = 1;
5968 else
5969 *carry = 0;
5971 return result;
5974 /* This function does the work of multiplying
5975 two 32bit values to give a 64bit result. */
5977 static unsigned
5978 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
5980 /* Operand register numbers. */
5981 int nRdHi, nRdLo, nRs, nRm;
5982 ARMword RdHi = 0, RdLo = 0, Rm;
5983 /* Cycle count. */
5984 int scount;
5986 nRdHi = BITS (16, 19);
5987 nRdLo = BITS (12, 15);
5988 nRs = BITS (8, 11);
5989 nRm = BITS (0, 3);
5991 /* Needed to calculate the cycle count. */
5992 Rm = state->Reg[nRm];
5994 /* Check for illegal operand combinations first. */
5995 if ( nRdHi != 15
5996 && nRdLo != 15
5997 && nRs != 15
5998 && nRm != 15
5999 && nRdHi != nRdLo)
6001 /* Intermediate results. */
6002 ARMword lo, mid1, mid2, hi;
6003 int carry;
6004 ARMword Rs = state->Reg[nRs];
6005 int sign = 0;
6007 #ifdef MODE32
6008 if (state->is_v6)
6010 else
6011 #endif
6012 /* BAD code can trigger this result. So only complain if debugging. */
6013 if (state->Debug && (nRdHi == nRm || nRdLo == nRm))
6014 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS: %d %d %d\n",
6015 nRdHi, nRdLo, nRm);
6016 if (msigned)
6018 /* Compute sign of result and adjust operands if necessary. */
6019 sign = (Rm ^ Rs) & 0x80000000;
6021 if (((ARMsword) Rm) < 0)
6022 Rm = -Rm;
6024 if (((ARMsword) Rs) < 0)
6025 Rs = -Rs;
6028 /* We can split the 32x32 into four 16x16 operations. This
6029 ensures that we do not lose precision on 32bit only hosts. */
6030 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
6031 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
6032 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
6033 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
6035 /* We now need to add all of these results together, taking
6036 care to propagate the carries from the additions. */
6037 RdLo = Add32 (lo, (mid1 << 16), &carry);
6038 RdHi = carry;
6039 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
6040 RdHi +=
6041 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
6043 if (sign)
6045 /* Negate result if necessary. */
6046 RdLo = ~RdLo;
6047 RdHi = ~RdHi;
6048 if (RdLo == 0xFFFFFFFF)
6050 RdLo = 0;
6051 RdHi += 1;
6053 else
6054 RdLo += 1;
6057 state->Reg[nRdLo] = RdLo;
6058 state->Reg[nRdHi] = RdHi;
6060 else if (state->Debug)
6061 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
6063 if (scc)
6064 /* Ensure that both RdHi and RdLo are used to compute Z,
6065 but don't let RdLo's sign bit make it to N. */
6066 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
6068 /* The cycle count depends on whether the instruction is a signed or
6069 unsigned multiply, and what bits are clear in the multiplier. */
6070 if (msigned && (Rm & ((unsigned) 1 << 31)))
6071 /* Invert the bits to make the check against zero. */
6072 Rm = ~Rm;
6074 if ((Rm & 0xFFFFFF00) == 0)
6075 scount = 1;
6076 else if ((Rm & 0xFFFF0000) == 0)
6077 scount = 2;
6078 else if ((Rm & 0xFF000000) == 0)
6079 scount = 3;
6080 else
6081 scount = 4;
6083 return 2 + scount;
6086 /* This function does the work of multiplying two 32bit
6087 values and adding a 64bit value to give a 64bit result. */
6089 static unsigned
6090 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
6092 unsigned scount;
6093 ARMword RdLo, RdHi;
6094 int nRdHi, nRdLo;
6095 int carry = 0;
6097 nRdHi = BITS (16, 19);
6098 nRdLo = BITS (12, 15);
6100 RdHi = state->Reg[nRdHi];
6101 RdLo = state->Reg[nRdLo];
6103 scount = Multiply64 (state, instr, msigned, LDEFAULT);
6105 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
6106 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
6108 state->Reg[nRdLo] = RdLo;
6109 state->Reg[nRdHi] = RdHi;
6111 if (scc)
6112 /* Ensure that both RdHi and RdLo are used to compute Z,
6113 but don't let RdLo's sign bit make it to N. */
6114 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
6116 /* Extra cycle for addition. */
6117 return scount + 1;