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>.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>. */
17
18 #include "armdefs.h"
19 #include "armemu.h"
20 #include "armos.h"
21 #include "iwmmxt.h"
22
23 static ARMword GetDPRegRHS (ARMul_State *, ARMword);
24 static ARMword GetDPSRegRHS (ARMul_State *, ARMword);
25 static void WriteR15 (ARMul_State *, ARMword);
26 static void WriteSR15 (ARMul_State *, ARMword);
27 static void WriteR15Branch (ARMul_State *, ARMword);
28 static ARMword GetLSRegRHS (ARMul_State *, ARMword);
29 static ARMword GetLS7RHS (ARMul_State *, ARMword);
30 static unsigned LoadWord (ARMul_State *, ARMword, ARMword);
31 static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int);
32 static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int);
33 static unsigned StoreWord (ARMul_State *, ARMword, ARMword);
34 static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword);
35 static unsigned StoreByte (ARMul_State *, ARMword, ARMword);
36 static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword);
37 static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword);
38 static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword);
39 static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword);
40 static unsigned Multiply64 (ARMul_State *, ARMword, int, int);
41 static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int);
42 static void Handle_Load_Double (ARMul_State *, ARMword);
43 static void Handle_Store_Double (ARMul_State *, ARMword);
44
45 #define LUNSIGNED (0) /* unsigned operation */
46 #define LSIGNED (1) /* signed operation */
47 #define LDEFAULT (0) /* default : do nothing */
48 #define LSCC (1) /* set condition codes on result */
49
50 #ifdef NEED_UI_LOOP_HOOK
51 /* How often to run the ui_loop update, when in use. */
52 #define UI_LOOP_POLL_INTERVAL 0x32000
53
54 /* Counter for the ui_loop_hook update. */
55 static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
56
57 /* Actual hook to call to run through gdb's gui event loop. */
58 extern int (*deprecated_ui_loop_hook) (int);
59 #endif /* NEED_UI_LOOP_HOOK */
60
61 extern int stop_simulator;
62
63 /* Short-hand macros for LDR/STR. */
64
65 /* Store post decrement writeback. */
66 #define SHDOWNWB() \
67 lhs = LHS ; \
68 if (StoreHalfWord (state, instr, lhs)) \
69 LSBase = lhs - GetLS7RHS (state, instr);
70
71 /* Store post increment writeback. */
72 #define SHUPWB() \
73 lhs = LHS ; \
74 if (StoreHalfWord (state, instr, lhs)) \
75 LSBase = lhs + GetLS7RHS (state, instr);
76
77 /* Store pre decrement. */
78 #define SHPREDOWN() \
79 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
80
81 /* Store pre decrement writeback. */
82 #define SHPREDOWNWB() \
83 temp = LHS - GetLS7RHS (state, instr); \
84 if (StoreHalfWord (state, instr, temp)) \
85 LSBase = temp;
86
87 /* Store pre increment. */
88 #define SHPREUP() \
89 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
90
91 /* Store pre increment writeback. */
92 #define SHPREUPWB() \
93 temp = LHS + GetLS7RHS (state, instr); \
94 if (StoreHalfWord (state, instr, temp)) \
95 LSBase = temp;
96
97 /* Load post decrement writeback. */
98 #define LHPOSTDOWN() \
99 { \
100 int done = 1; \
101 lhs = LHS; \
102 temp = lhs - GetLS7RHS (state, instr); \
103 \
104 switch (BITS (5, 6)) \
105 { \
106 case 1: /* H */ \
107 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
108 LSBase = temp; \
109 break; \
110 case 2: /* SB */ \
111 if (LoadByte (state, instr, lhs, LSIGNED)) \
112 LSBase = temp; \
113 break; \
114 case 3: /* SH */ \
115 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
116 LSBase = temp; \
117 break; \
118 case 0: /* SWP handled elsewhere. */ \
119 default: \
120 done = 0; \
121 break; \
122 } \
123 if (done) \
124 break; \
125 }
126
127 /* Load post increment writeback. */
128 #define LHPOSTUP() \
129 { \
130 int done = 1; \
131 lhs = LHS; \
132 temp = lhs + GetLS7RHS (state, instr); \
133 \
134 switch (BITS (5, 6)) \
135 { \
136 case 1: /* H */ \
137 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
138 LSBase = temp; \
139 break; \
140 case 2: /* SB */ \
141 if (LoadByte (state, instr, lhs, LSIGNED)) \
142 LSBase = temp; \
143 break; \
144 case 3: /* SH */ \
145 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
146 LSBase = temp; \
147 break; \
148 case 0: /* SWP handled elsewhere. */ \
149 default: \
150 done = 0; \
151 break; \
152 } \
153 if (done) \
154 break; \
155 }
156
157 /* Load pre decrement. */
158 #define LHPREDOWN() \
159 { \
160 int done = 1; \
161 \
162 temp = LHS - GetLS7RHS (state, instr); \
163 switch (BITS (5, 6)) \
164 { \
165 case 1: /* H */ \
166 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
167 break; \
168 case 2: /* SB */ \
169 (void) LoadByte (state, instr, temp, LSIGNED); \
170 break; \
171 case 3: /* SH */ \
172 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
173 break; \
174 case 0: \
175 /* SWP handled elsewhere. */ \
176 default: \
177 done = 0; \
178 break; \
179 } \
180 if (done) \
181 break; \
182 }
183
184 /* Load pre decrement writeback. */
185 #define LHPREDOWNWB() \
186 { \
187 int done = 1; \
188 \
189 temp = LHS - GetLS7RHS (state, instr); \
190 switch (BITS (5, 6)) \
191 { \
192 case 1: /* H */ \
193 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
194 LSBase = temp; \
195 break; \
196 case 2: /* SB */ \
197 if (LoadByte (state, instr, temp, LSIGNED)) \
198 LSBase = temp; \
199 break; \
200 case 3: /* SH */ \
201 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
202 LSBase = temp; \
203 break; \
204 case 0: \
205 /* SWP handled elsewhere. */ \
206 default: \
207 done = 0; \
208 break; \
209 } \
210 if (done) \
211 break; \
212 }
213
214 /* Load pre increment. */
215 #define LHPREUP() \
216 { \
217 int done = 1; \
218 \
219 temp = LHS + GetLS7RHS (state, instr); \
220 switch (BITS (5, 6)) \
221 { \
222 case 1: /* H */ \
223 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
224 break; \
225 case 2: /* SB */ \
226 (void) LoadByte (state, instr, temp, LSIGNED); \
227 break; \
228 case 3: /* SH */ \
229 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
230 break; \
231 case 0: \
232 /* SWP handled elsewhere. */ \
233 default: \
234 done = 0; \
235 break; \
236 } \
237 if (done) \
238 break; \
239 }
240
241 /* Load pre increment writeback. */
242 #define LHPREUPWB() \
243 { \
244 int done = 1; \
245 \
246 temp = LHS + GetLS7RHS (state, instr); \
247 switch (BITS (5, 6)) \
248 { \
249 case 1: /* H */ \
250 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
251 LSBase = temp; \
252 break; \
253 case 2: /* SB */ \
254 if (LoadByte (state, instr, temp, LSIGNED)) \
255 LSBase = temp; \
256 break; \
257 case 3: /* SH */ \
258 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
259 LSBase = temp; \
260 break; \
261 case 0: \
262 /* SWP handled elsewhere. */ \
263 default: \
264 done = 0; \
265 break; \
266 } \
267 if (done) \
268 break; \
269 }
270
271 /* Attempt to emulate an ARMv6 instruction.
272 Returns non-zero upon success. */
273
274 static int
handle_v6_insn(ARMul_State * state,ARMword instr)275 handle_v6_insn (ARMul_State * state, ARMword instr)
276 {
277 switch (BITS (20, 27))
278 {
279 #if 0
280 case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
281 case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
282 case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
283 case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
284 case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
285 case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
286 case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
287 case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
288 case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
289 case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
290 case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
291 case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
292 case 0x30: printf ("Unhandled v6 insn: movw\n"); break;
293 case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
294 case 0x34: printf ("Unhandled v6 insn: movt\n"); break;
295 case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
296 #endif
297 case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
298 case 0x62: printf ("Unhandled v6 insn: qadd/qsub\n"); break;
299 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
300 case 0x65: printf ("Unhandled v6 insn: uadd/usub\n"); break;
301 case 0x66: printf ("Unhandled v6 insn: uqadd/uqsub\n"); break;
302 case 0x67: printf ("Unhandled v6 insn: uhadd/uhsub\n"); break;
303 case 0x68: printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); break;
304 case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
305 case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
306 case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
307 case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
308 case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
309 case 0x7a: printf ("Unhandled v6 insn: usbfx\n"); break;
310 case 0x7c: printf ("Unhandled v6 insn: bfc/bfi\n"); break;
311
312 case 0x6a:
313 {
314 ARMword Rm;
315 int ror = -1;
316
317 switch (BITS (4, 11))
318 {
319 case 0x07: ror = 0; break;
320 case 0x47: ror = 8; break;
321 case 0x87: ror = 16; break;
322 case 0xc7: ror = 24; break;
323
324 case 0x01:
325 case 0xf3:
326 printf ("Unhandled v6 insn: ssat\n");
327 return 0;
328 default:
329 break;
330 }
331
332 if (ror == -1)
333 {
334 if (BITS (4, 6) == 0x7)
335 {
336 printf ("Unhandled v6 insn: ssat\n");
337 return 0;
338 }
339 break;
340 }
341
342 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
343 if (Rm & 0x80)
344 Rm |= 0xffffff00;
345
346 if (BITS (16, 19) == 0xf)
347 /* SXTB */
348 state->Reg[BITS (12, 15)] = Rm;
349 else
350 /* SXTAB */
351 state->Reg[BITS (12, 15)] += Rm;
352 }
353 return 1;
354
355 case 0x6b:
356 {
357 ARMword Rm;
358 int ror = -1;
359
360 switch (BITS (4, 11))
361 {
362 case 0x07: ror = 0; break;
363 case 0x47: ror = 8; break;
364 case 0x87: ror = 16; break;
365 case 0xc7: ror = 24; break;
366
367 case 0xfb:
368 printf ("Unhandled v6 insn: rev\n");
369 return 0;
370 default:
371 break;
372 }
373
374 if (ror == -1)
375 break;
376
377 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
378 if (Rm & 0x8000)
379 Rm |= 0xffff0000;
380
381 if (BITS (16, 19) == 0xf)
382 /* SXTH */
383 state->Reg[BITS (12, 15)] = Rm;
384 else
385 /* SXTAH */
386 state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
387 }
388 return 1;
389
390 case 0x6e:
391 {
392 ARMword Rm;
393 int ror = -1;
394
395 switch (BITS (4, 11))
396 {
397 case 0x07: ror = 0; break;
398 case 0x47: ror = 8; break;
399 case 0x87: ror = 16; break;
400 case 0xc7: ror = 24; break;
401
402 case 0x01:
403 case 0xf3:
404 printf ("Unhandled v6 insn: usat\n");
405 return 0;
406 default:
407 break;
408 }
409
410 if (ror == -1)
411 {
412 if (BITS (4, 6) == 0x7)
413 {
414 printf ("Unhandled v6 insn: usat\n");
415 return 0;
416 }
417 break;
418 }
419
420 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
421
422 if (BITS (16, 19) == 0xf)
423 /* UXTB */
424 state->Reg[BITS (12, 15)] = Rm;
425 else
426 /* UXTAB */
427 state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
428 }
429 return 1;
430
431 case 0x6f:
432 {
433 ARMword Rm;
434 int ror = -1;
435
436 switch (BITS (4, 11))
437 {
438 case 0x07: ror = 0; break;
439 case 0x47: ror = 8; break;
440 case 0x87: ror = 16; break;
441 case 0xc7: ror = 24; break;
442
443 case 0xfb:
444 printf ("Unhandled v6 insn: revsh\n");
445 return 0;
446 default:
447 break;
448 }
449
450 if (ror == -1)
451 break;
452
453 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
454
455 if (BITS (16, 19) == 0xf)
456 /* UXT */
457 state->Reg[BITS (12, 15)] = Rm;
458 else
459 {
460 /* UXTAH */
461 state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm;
462 }
463 }
464 return 1;
465
466 #if 0
467 case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
468 #endif
469 default:
470 break;
471 }
472 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr);
473 return 0;
474 }
475
476 /* EMULATION of ARM6. */
477
478 /* The PC pipeline value depends on whether ARM
479 or Thumb instructions are being executed. */
480 ARMword isize;
481
482 ARMword
483 #ifdef MODE32
ARMul_Emulate32(ARMul_State * state)484 ARMul_Emulate32 (ARMul_State * state)
485 #else
486 ARMul_Emulate26 (ARMul_State * state)
487 #endif
488 {
489 ARMword instr; /* The current instruction. */
490 ARMword dest = 0; /* Almost the DestBus. */
491 ARMword temp; /* Ubiquitous third hand. */
492 ARMword pc = 0; /* The address of the current instruction. */
493 ARMword lhs; /* Almost the ABus and BBus. */
494 ARMword rhs;
495 ARMword decoded = 0; /* Instruction pipeline. */
496 ARMword loaded = 0;
497
498 /* Execute the next instruction. */
499
500 if (state->NextInstr < PRIMEPIPE)
501 {
502 decoded = state->decoded;
503 loaded = state->loaded;
504 pc = state->pc;
505 }
506
507 do
508 {
509 /* Just keep going. */
510 isize = INSN_SIZE;
511
512 switch (state->NextInstr)
513 {
514 case SEQ:
515 /* Advance the pipeline, and an S cycle. */
516 state->Reg[15] += isize;
517 pc += isize;
518 instr = decoded;
519 decoded = loaded;
520 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
521 break;
522
523 case NONSEQ:
524 /* Advance the pipeline, and an N cycle. */
525 state->Reg[15] += isize;
526 pc += isize;
527 instr = decoded;
528 decoded = loaded;
529 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
530 NORMALCYCLE;
531 break;
532
533 case PCINCEDSEQ:
534 /* Program counter advanced, and an S cycle. */
535 pc += isize;
536 instr = decoded;
537 decoded = loaded;
538 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
539 NORMALCYCLE;
540 break;
541
542 case PCINCEDNONSEQ:
543 /* Program counter advanced, and an N cycle. */
544 pc += isize;
545 instr = decoded;
546 decoded = loaded;
547 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
548 NORMALCYCLE;
549 break;
550
551 case RESUME:
552 /* The program counter has been changed. */
553 pc = state->Reg[15];
554 #ifndef MODE32
555 pc = pc & R15PCBITS;
556 #endif
557 state->Reg[15] = pc + (isize * 2);
558 state->Aborted = 0;
559 instr = ARMul_ReLoadInstr (state, pc, isize);
560 decoded = ARMul_ReLoadInstr (state, pc + isize, isize);
561 loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize);
562 NORMALCYCLE;
563 break;
564
565 default:
566 /* The program counter has been changed. */
567 pc = state->Reg[15];
568 #ifndef MODE32
569 pc = pc & R15PCBITS;
570 #endif
571 state->Reg[15] = pc + (isize * 2);
572 state->Aborted = 0;
573 instr = ARMul_LoadInstrN (state, pc, isize);
574 decoded = ARMul_LoadInstrS (state, pc + (isize), isize);
575 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
576 NORMALCYCLE;
577 break;
578 }
579
580 if (state->EventSet)
581 ARMul_EnvokeEvent (state);
582 #if 0 /* Enable this for a helpful bit of debugging when tracing is needed. */
583 fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr);
584 if (instr == 0)
585 abort ();
586 #endif
587 #if 0 /* Enable this code to help track down stack alignment bugs. */
588 {
589 static ARMword old_sp = -1;
590
591 if (old_sp != state->Reg[13])
592 {
593 old_sp = state->Reg[13];
594 fprintf (stderr, "pc: %08x: SP set to %08x%s\n",
595 pc & ~1, old_sp, (old_sp % 8) ? " [UNALIGNED!]" : "");
596 }
597 }
598 #endif
599
600 if (state->Exception)
601 {
602 /* Any exceptions ? */
603 if (state->NresetSig == LOW)
604 {
605 ARMul_Abort (state, ARMul_ResetV);
606 break;
607 }
608 else if (!state->NfiqSig && !FFLAG)
609 {
610 ARMul_Abort (state, ARMul_FIQV);
611 break;
612 }
613 else if (!state->NirqSig && !IFLAG)
614 {
615 ARMul_Abort (state, ARMul_IRQV);
616 break;
617 }
618 }
619
620 if (state->CallDebug > 0)
621 {
622 instr = ARMul_Debug (state, pc, instr);
623 if (state->Emulate < ONCE)
624 {
625 state->NextInstr = RESUME;
626 break;
627 }
628 if (state->Debug)
629 {
630 fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n", pc, instr,
631 state->Mode);
632 (void) fgetc (stdin);
633 }
634 }
635 else if (state->Emulate < ONCE)
636 {
637 state->NextInstr = RESUME;
638 break;
639 }
640
641 state->NumInstrs++;
642
643 #ifdef MODET
644 /* Provide Thumb instruction decoding. If the processor is in Thumb
645 mode, then we can simply decode the Thumb instruction, and map it
646 to the corresponding ARM instruction (by directly loading the
647 instr variable, and letting the normal ARM simulator
648 execute). There are some caveats to ensure that the correct
649 pipelined PC value is used when executing Thumb code, and also for
650 dealing with the BL instruction. */
651 if (TFLAG)
652 {
653 ARMword new;
654
655 /* Check if in Thumb mode. */
656 switch (ARMul_ThumbDecode (state, pc, instr, &new))
657 {
658 case t_undefined:
659 /* This is a Thumb instruction. */
660 ARMul_UndefInstr (state, instr);
661 goto donext;
662
663 case t_branch:
664 /* Already processed. */
665 goto donext;
666
667 case t_decoded:
668 /* ARM instruction available. */
669 instr = new;
670 /* So continue instruction decoding. */
671 break;
672 default:
673 break;
674 }
675 }
676 #endif
677
678 /* Check the condition codes. */
679 if ((temp = TOPBITS (28)) == AL)
680 /* Vile deed in the need for speed. */
681 goto mainswitch;
682
683 /* Check the condition code. */
684 switch ((int) TOPBITS (28))
685 {
686 case AL:
687 temp = TRUE;
688 break;
689 case NV:
690 if (state->is_v5)
691 {
692 if (BITS (25, 27) == 5) /* BLX(1) */
693 {
694 ARMword dest;
695
696 state->Reg[14] = pc + 4;
697
698 /* Force entry into Thumb mode. */
699 dest = pc + 8 + 1;
700 if (BIT (23))
701 dest += (NEGBRANCH + (BIT (24) << 1));
702 else
703 dest += POSBRANCH + (BIT (24) << 1);
704
705 WriteR15Branch (state, dest);
706 goto donext;
707 }
708 else if ((instr & 0xFC70F000) == 0xF450F000)
709 /* The PLD instruction. Ignored. */
710 goto donext;
711 else if ( ((instr & 0xfe500f00) == 0xfc100100)
712 || ((instr & 0xfe500f00) == 0xfc000100))
713 /* wldrw and wstrw are unconditional. */
714 goto mainswitch;
715 else
716 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
717 ARMul_UndefInstr (state, instr);
718 }
719 temp = FALSE;
720 break;
721 case EQ:
722 temp = ZFLAG;
723 break;
724 case NE:
725 temp = !ZFLAG;
726 break;
727 case VS:
728 temp = VFLAG;
729 break;
730 case VC:
731 temp = !VFLAG;
732 break;
733 case MI:
734 temp = NFLAG;
735 break;
736 case PL:
737 temp = !NFLAG;
738 break;
739 case CS:
740 temp = CFLAG;
741 break;
742 case CC:
743 temp = !CFLAG;
744 break;
745 case HI:
746 temp = (CFLAG && !ZFLAG);
747 break;
748 case LS:
749 temp = (!CFLAG || ZFLAG);
750 break;
751 case GE:
752 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
753 break;
754 case LT:
755 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
756 break;
757 case GT:
758 temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
759 break;
760 case LE:
761 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
762 break;
763 } /* cc check */
764
765 /* Handle the Clock counter here. */
766 if (state->is_XScale)
767 {
768 ARMword cp14r0;
769 int ok;
770
771 ok = state->CPRead[14] (state, 0, & cp14r0);
772
773 if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE))
774 {
775 unsigned long newcycles, nowtime = ARMul_Time (state);
776
777 newcycles = nowtime - state->LastTime;
778 state->LastTime = nowtime;
779
780 if (cp14r0 & ARMul_CP14_R0_CCD)
781 {
782 if (state->CP14R0_CCD == -1)
783 state->CP14R0_CCD = newcycles;
784 else
785 state->CP14R0_CCD += newcycles;
786
787 if (state->CP14R0_CCD >= 64)
788 {
789 newcycles = 0;
790
791 while (state->CP14R0_CCD >= 64)
792 state->CP14R0_CCD -= 64, newcycles++;
793
794 goto check_PMUintr;
795 }
796 }
797 else
798 {
799 ARMword cp14r1;
800 int do_int = 0;
801
802 state->CP14R0_CCD = -1;
803 check_PMUintr:
804 cp14r0 |= ARMul_CP14_R0_FLAG2;
805 (void) state->CPWrite[14] (state, 0, cp14r0);
806
807 ok = state->CPRead[14] (state, 1, & cp14r1);
808
809 /* Coded like this for portability. */
810 while (ok && newcycles)
811 {
812 if (cp14r1 == 0xffffffff)
813 {
814 cp14r1 = 0;
815 do_int = 1;
816 }
817 else
818 cp14r1 ++;
819
820 newcycles --;
821 }
822
823 (void) state->CPWrite[14] (state, 1, cp14r1);
824
825 if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2))
826 {
827 ARMword temp;
828
829 if (state->CPRead[13] (state, 8, & temp)
830 && (temp & ARMul_CP13_R8_PMUS))
831 ARMul_Abort (state, ARMul_FIQV);
832 else
833 ARMul_Abort (state, ARMul_IRQV);
834 }
835 }
836 }
837 }
838
839 /* Handle hardware instructions breakpoints here. */
840 if (state->is_XScale)
841 {
842 if ( (pc | 3) == (read_cp15_reg (14, 0, 8) | 2)
843 || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2))
844 {
845 if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB))
846 ARMul_OSHandleSWI (state, SWI_Breakpoint);
847 }
848 }
849
850 /* Actual execution of instructions begins here. */
851 /* If the condition codes don't match, stop here. */
852 if (temp)
853 {
854 mainswitch:
855
856 if (state->is_XScale)
857 {
858 if (BIT (20) == 0 && BITS (25, 27) == 0)
859 {
860 if (BITS (4, 7) == 0xD)
861 {
862 /* XScale Load Consecutive insn. */
863 ARMword temp = GetLS7RHS (state, instr);
864 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
865 ARMword addr = BIT (24) ? temp2 : LHS;
866
867 if (BIT (12))
868 ARMul_UndefInstr (state, instr);
869 else if (addr & 7)
870 /* Alignment violation. */
871 ARMul_Abort (state, ARMul_DataAbortV);
872 else
873 {
874 int wb = BIT (21) || (! BIT (24));
875
876 state->Reg[BITS (12, 15)] =
877 ARMul_LoadWordN (state, addr);
878 state->Reg[BITS (12, 15) + 1] =
879 ARMul_LoadWordN (state, addr + 4);
880 if (wb)
881 LSBase = temp2;
882 }
883
884 goto donext;
885 }
886 else if (BITS (4, 7) == 0xF)
887 {
888 /* XScale Store Consecutive insn. */
889 ARMword temp = GetLS7RHS (state, instr);
890 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
891 ARMword addr = BIT (24) ? temp2 : LHS;
892
893 if (BIT (12))
894 ARMul_UndefInstr (state, instr);
895 else if (addr & 7)
896 /* Alignment violation. */
897 ARMul_Abort (state, ARMul_DataAbortV);
898 else
899 {
900 ARMul_StoreWordN (state, addr,
901 state->Reg[BITS (12, 15)]);
902 ARMul_StoreWordN (state, addr + 4,
903 state->Reg[BITS (12, 15) + 1]);
904
905 if (BIT (21)|| ! BIT (24))
906 LSBase = temp2;
907 }
908
909 goto donext;
910 }
911 }
912
913 if (ARMul_HandleIwmmxt (state, instr))
914 goto donext;
915 }
916
917 switch ((int) BITS (20, 27))
918 {
919 /* Data Processing Register RHS Instructions. */
920
921 case 0x00: /* AND reg and MUL */
922 #ifdef MODET
923 if (BITS (4, 11) == 0xB)
924 {
925 /* STRH register offset, no write-back, down, post indexed. */
926 SHDOWNWB ();
927 break;
928 }
929 if (BITS (4, 7) == 0xD)
930 {
931 Handle_Load_Double (state, instr);
932 break;
933 }
934 if (BITS (4, 7) == 0xF)
935 {
936 Handle_Store_Double (state, instr);
937 break;
938 }
939 #endif
940 if (BITS (4, 7) == 9)
941 {
942 /* MUL */
943 rhs = state->Reg[MULRHSReg];
944 if (MULLHSReg == MULDESTReg)
945 {
946 UNDEF_MULDestEQOp1;
947 state->Reg[MULDESTReg] = 0;
948 }
949 else if (MULDESTReg != 15)
950 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
951 else
952 UNDEF_MULPCDest;
953
954 for (dest = 0, temp = 0; dest < 32; dest ++)
955 if (rhs & (1L << dest))
956 temp = dest;
957
958 /* Mult takes this many/2 I cycles. */
959 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
960 }
961 else
962 {
963 /* AND reg. */
964 rhs = DPRegRHS;
965 dest = LHS & rhs;
966 WRITEDEST (dest);
967 }
968 break;
969
970 case 0x01: /* ANDS reg and MULS */
971 #ifdef MODET
972 if ((BITS (4, 11) & 0xF9) == 0x9)
973 /* LDR register offset, no write-back, down, post indexed. */
974 LHPOSTDOWN ();
975 /* Fall through to rest of decoding. */
976 #endif
977 if (BITS (4, 7) == 9)
978 {
979 /* MULS */
980 rhs = state->Reg[MULRHSReg];
981
982 if (MULLHSReg == MULDESTReg)
983 {
984 UNDEF_MULDestEQOp1;
985 state->Reg[MULDESTReg] = 0;
986 CLEARN;
987 SETZ;
988 }
989 else if (MULDESTReg != 15)
990 {
991 dest = state->Reg[MULLHSReg] * rhs;
992 ARMul_NegZero (state, dest);
993 state->Reg[MULDESTReg] = dest;
994 }
995 else
996 UNDEF_MULPCDest;
997
998 for (dest = 0, temp = 0; dest < 32; dest ++)
999 if (rhs & (1L << dest))
1000 temp = dest;
1001
1002 /* Mult takes this many/2 I cycles. */
1003 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
1004 }
1005 else
1006 {
1007 /* ANDS reg. */
1008 rhs = DPSRegRHS;
1009 dest = LHS & rhs;
1010 WRITESDEST (dest);
1011 }
1012 break;
1013
1014 case 0x02: /* EOR reg and MLA */
1015 #ifdef MODET
1016 if (BITS (4, 11) == 0xB)
1017 {
1018 /* STRH register offset, write-back, down, post indexed. */
1019 SHDOWNWB ();
1020 break;
1021 }
1022 #endif
1023 if (BITS (4, 7) == 9)
1024 { /* MLA */
1025 rhs = state->Reg[MULRHSReg];
1026 if (MULLHSReg == MULDESTReg)
1027 {
1028 UNDEF_MULDestEQOp1;
1029 state->Reg[MULDESTReg] = state->Reg[MULACCReg];
1030 }
1031 else if (MULDESTReg != 15)
1032 state->Reg[MULDESTReg] =
1033 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
1034 else
1035 UNDEF_MULPCDest;
1036
1037 for (dest = 0, temp = 0; dest < 32; dest ++)
1038 if (rhs & (1L << dest))
1039 temp = dest;
1040
1041 /* Mult takes this many/2 I cycles. */
1042 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
1043 }
1044 else
1045 {
1046 rhs = DPRegRHS;
1047 dest = LHS ^ rhs;
1048 WRITEDEST (dest);
1049 }
1050 break;
1051
1052 case 0x03: /* EORS reg and MLAS */
1053 #ifdef MODET
1054 if ((BITS (4, 11) & 0xF9) == 0x9)
1055 /* LDR register offset, write-back, down, post-indexed. */
1056 LHPOSTDOWN ();
1057 /* Fall through to rest of the decoding. */
1058 #endif
1059 if (BITS (4, 7) == 9)
1060 {
1061 /* MLAS */
1062 rhs = state->Reg[MULRHSReg];
1063
1064 if (MULLHSReg == MULDESTReg)
1065 {
1066 UNDEF_MULDestEQOp1;
1067 dest = state->Reg[MULACCReg];
1068 ARMul_NegZero (state, dest);
1069 state->Reg[MULDESTReg] = dest;
1070 }
1071 else if (MULDESTReg != 15)
1072 {
1073 dest =
1074 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
1075 ARMul_NegZero (state, dest);
1076 state->Reg[MULDESTReg] = dest;
1077 }
1078 else
1079 UNDEF_MULPCDest;
1080
1081 for (dest = 0, temp = 0; dest < 32; dest ++)
1082 if (rhs & (1L << dest))
1083 temp = dest;
1084
1085 /* Mult takes this many/2 I cycles. */
1086 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
1087 }
1088 else
1089 {
1090 /* EORS Reg. */
1091 rhs = DPSRegRHS;
1092 dest = LHS ^ rhs;
1093 WRITESDEST (dest);
1094 }
1095 break;
1096
1097 case 0x04: /* SUB reg */
1098 #ifdef MODET
1099 if (BITS (4, 7) == 0xB)
1100 {
1101 /* STRH immediate offset, no write-back, down, post indexed. */
1102 SHDOWNWB ();
1103 break;
1104 }
1105 if (BITS (4, 7) == 0xD)
1106 {
1107 Handle_Load_Double (state, instr);
1108 break;
1109 }
1110 if (BITS (4, 7) == 0xF)
1111 {
1112 Handle_Store_Double (state, instr);
1113 break;
1114 }
1115 #endif
1116 rhs = DPRegRHS;
1117 dest = LHS - rhs;
1118 WRITEDEST (dest);
1119 break;
1120
1121 case 0x05: /* SUBS reg */
1122 #ifdef MODET
1123 if ((BITS (4, 7) & 0x9) == 0x9)
1124 /* LDR immediate offset, no write-back, down, post indexed. */
1125 LHPOSTDOWN ();
1126 /* Fall through to the rest of the instruction decoding. */
1127 #endif
1128 lhs = LHS;
1129 rhs = DPRegRHS;
1130 dest = lhs - rhs;
1131
1132 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1133 {
1134 ARMul_SubCarry (state, lhs, rhs, dest);
1135 ARMul_SubOverflow (state, lhs, rhs, dest);
1136 }
1137 else
1138 {
1139 CLEARC;
1140 CLEARV;
1141 }
1142 WRITESDEST (dest);
1143 break;
1144
1145 case 0x06: /* RSB reg */
1146 #ifdef MODET
1147 if (BITS (4, 7) == 0xB)
1148 {
1149 /* STRH immediate offset, write-back, down, post indexed. */
1150 SHDOWNWB ();
1151 break;
1152 }
1153 #endif
1154 rhs = DPRegRHS;
1155 dest = rhs - LHS;
1156 WRITEDEST (dest);
1157 break;
1158
1159 case 0x07: /* RSBS reg */
1160 #ifdef MODET
1161 if ((BITS (4, 7) & 0x9) == 0x9)
1162 /* LDR immediate offset, write-back, down, post indexed. */
1163 LHPOSTDOWN ();
1164 /* Fall through to remainder of instruction decoding. */
1165 #endif
1166 lhs = LHS;
1167 rhs = DPRegRHS;
1168 dest = rhs - lhs;
1169
1170 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1171 {
1172 ARMul_SubCarry (state, rhs, lhs, dest);
1173 ARMul_SubOverflow (state, rhs, lhs, dest);
1174 }
1175 else
1176 {
1177 CLEARC;
1178 CLEARV;
1179 }
1180 WRITESDEST (dest);
1181 break;
1182
1183 case 0x08: /* ADD reg */
1184 #ifdef MODET
1185 if (BITS (4, 11) == 0xB)
1186 {
1187 /* STRH register offset, no write-back, up, post indexed. */
1188 SHUPWB ();
1189 break;
1190 }
1191 if (BITS (4, 7) == 0xD)
1192 {
1193 Handle_Load_Double (state, instr);
1194 break;
1195 }
1196 if (BITS (4, 7) == 0xF)
1197 {
1198 Handle_Store_Double (state, instr);
1199 break;
1200 }
1201 #endif
1202 #ifdef MODET
1203 if (BITS (4, 7) == 0x9)
1204 {
1205 /* MULL */
1206 /* 32x32 = 64 */
1207 ARMul_Icycles (state,
1208 Multiply64 (state, instr, LUNSIGNED,
1209 LDEFAULT), 0L);
1210 break;
1211 }
1212 #endif
1213 rhs = DPRegRHS;
1214 dest = LHS + rhs;
1215 WRITEDEST (dest);
1216 break;
1217
1218 case 0x09: /* ADDS reg */
1219 #ifdef MODET
1220 if ((BITS (4, 11) & 0xF9) == 0x9)
1221 /* LDR register offset, no write-back, up, post indexed. */
1222 LHPOSTUP ();
1223 /* Fall through to remaining instruction decoding. */
1224 #endif
1225 #ifdef MODET
1226 if (BITS (4, 7) == 0x9)
1227 {
1228 /* MULL */
1229 /* 32x32=64 */
1230 ARMul_Icycles (state,
1231 Multiply64 (state, instr, LUNSIGNED, LSCC),
1232 0L);
1233 break;
1234 }
1235 #endif
1236 lhs = LHS;
1237 rhs = DPRegRHS;
1238 dest = lhs + rhs;
1239 ASSIGNZ (dest == 0);
1240 if ((lhs | rhs) >> 30)
1241 {
1242 /* Possible C,V,N to set. */
1243 ASSIGNN (NEG (dest));
1244 ARMul_AddCarry (state, lhs, rhs, dest);
1245 ARMul_AddOverflow (state, lhs, rhs, dest);
1246 }
1247 else
1248 {
1249 CLEARN;
1250 CLEARC;
1251 CLEARV;
1252 }
1253 WRITESDEST (dest);
1254 break;
1255
1256 case 0x0a: /* ADC reg */
1257 #ifdef MODET
1258 if (BITS (4, 11) == 0xB)
1259 {
1260 /* STRH register offset, write-back, up, post-indexed. */
1261 SHUPWB ();
1262 break;
1263 }
1264 if (BITS (4, 7) == 0x9)
1265 {
1266 /* MULL */
1267 /* 32x32=64 */
1268 ARMul_Icycles (state,
1269 MultiplyAdd64 (state, instr, LUNSIGNED,
1270 LDEFAULT), 0L);
1271 break;
1272 }
1273 #endif
1274 rhs = DPRegRHS;
1275 dest = LHS + rhs + CFLAG;
1276 WRITEDEST (dest);
1277 break;
1278
1279 case 0x0b: /* ADCS reg */
1280 #ifdef MODET
1281 if ((BITS (4, 11) & 0xF9) == 0x9)
1282 /* LDR register offset, write-back, up, post indexed. */
1283 LHPOSTUP ();
1284 /* Fall through to remaining instruction decoding. */
1285 if (BITS (4, 7) == 0x9)
1286 {
1287 /* MULL */
1288 /* 32x32=64 */
1289 ARMul_Icycles (state,
1290 MultiplyAdd64 (state, instr, LUNSIGNED,
1291 LSCC), 0L);
1292 break;
1293 }
1294 #endif
1295 lhs = LHS;
1296 rhs = DPRegRHS;
1297 dest = lhs + rhs + CFLAG;
1298 ASSIGNZ (dest == 0);
1299 if ((lhs | rhs) >> 30)
1300 {
1301 /* Possible C,V,N to set. */
1302 ASSIGNN (NEG (dest));
1303 ARMul_AddCarry (state, lhs, rhs, dest);
1304 ARMul_AddOverflow (state, lhs, rhs, dest);
1305 }
1306 else
1307 {
1308 CLEARN;
1309 CLEARC;
1310 CLEARV;
1311 }
1312 WRITESDEST (dest);
1313 break;
1314
1315 case 0x0c: /* SBC reg */
1316 #ifdef MODET
1317 if (BITS (4, 7) == 0xB)
1318 {
1319 /* STRH immediate offset, no write-back, up post indexed. */
1320 SHUPWB ();
1321 break;
1322 }
1323 if (BITS (4, 7) == 0xD)
1324 {
1325 Handle_Load_Double (state, instr);
1326 break;
1327 }
1328 if (BITS (4, 7) == 0xF)
1329 {
1330 Handle_Store_Double (state, instr);
1331 break;
1332 }
1333 if (BITS (4, 7) == 0x9)
1334 {
1335 /* MULL */
1336 /* 32x32=64 */
1337 ARMul_Icycles (state,
1338 Multiply64 (state, instr, LSIGNED, LDEFAULT),
1339 0L);
1340 break;
1341 }
1342 #endif
1343 rhs = DPRegRHS;
1344 dest = LHS - rhs - !CFLAG;
1345 WRITEDEST (dest);
1346 break;
1347
1348 case 0x0d: /* SBCS reg */
1349 #ifdef MODET
1350 if ((BITS (4, 7) & 0x9) == 0x9)
1351 /* LDR immediate offset, no write-back, up, post indexed. */
1352 LHPOSTUP ();
1353
1354 if (BITS (4, 7) == 0x9)
1355 {
1356 /* MULL */
1357 /* 32x32=64 */
1358 ARMul_Icycles (state,
1359 Multiply64 (state, instr, LSIGNED, LSCC),
1360 0L);
1361 break;
1362 }
1363 #endif
1364 lhs = LHS;
1365 rhs = DPRegRHS;
1366 dest = lhs - rhs - !CFLAG;
1367 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1368 {
1369 ARMul_SubCarry (state, lhs, rhs, dest);
1370 ARMul_SubOverflow (state, lhs, rhs, dest);
1371 }
1372 else
1373 {
1374 CLEARC;
1375 CLEARV;
1376 }
1377 WRITESDEST (dest);
1378 break;
1379
1380 case 0x0e: /* RSC reg */
1381 #ifdef MODET
1382 if (BITS (4, 7) == 0xB)
1383 {
1384 /* STRH immediate offset, write-back, up, post indexed. */
1385 SHUPWB ();
1386 break;
1387 }
1388
1389 if (BITS (4, 7) == 0x9)
1390 {
1391 /* MULL */
1392 /* 32x32=64 */
1393 ARMul_Icycles (state,
1394 MultiplyAdd64 (state, instr, LSIGNED,
1395 LDEFAULT), 0L);
1396 break;
1397 }
1398 #endif
1399 rhs = DPRegRHS;
1400 dest = rhs - LHS - !CFLAG;
1401 WRITEDEST (dest);
1402 break;
1403
1404 case 0x0f: /* RSCS reg */
1405 #ifdef MODET
1406 if ((BITS (4, 7) & 0x9) == 0x9)
1407 /* LDR immediate offset, write-back, up, post indexed. */
1408 LHPOSTUP ();
1409 /* Fall through to remaining instruction decoding. */
1410
1411 if (BITS (4, 7) == 0x9)
1412 {
1413 /* MULL */
1414 /* 32x32=64 */
1415 ARMul_Icycles (state,
1416 MultiplyAdd64 (state, instr, LSIGNED, LSCC),
1417 0L);
1418 break;
1419 }
1420 #endif
1421 lhs = LHS;
1422 rhs = DPRegRHS;
1423 dest = rhs - lhs - !CFLAG;
1424
1425 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1426 {
1427 ARMul_SubCarry (state, rhs, lhs, dest);
1428 ARMul_SubOverflow (state, rhs, lhs, dest);
1429 }
1430 else
1431 {
1432 CLEARC;
1433 CLEARV;
1434 }
1435 WRITESDEST (dest);
1436 break;
1437
1438 case 0x10: /* TST reg and MRS CPSR and SWP word. */
1439 if (state->is_v5e)
1440 {
1441 if (BIT (4) == 0 && BIT (7) == 1)
1442 {
1443 /* ElSegundo SMLAxy insn. */
1444 ARMword op1 = state->Reg[BITS (0, 3)];
1445 ARMword op2 = state->Reg[BITS (8, 11)];
1446 ARMword Rn = state->Reg[BITS (12, 15)];
1447
1448 if (BIT (5))
1449 op1 >>= 16;
1450 if (BIT (6))
1451 op2 >>= 16;
1452 op1 &= 0xFFFF;
1453 op2 &= 0xFFFF;
1454 if (op1 & 0x8000)
1455 op1 -= 65536;
1456 if (op2 & 0x8000)
1457 op2 -= 65536;
1458 op1 *= op2;
1459
1460 if (AddOverflow (op1, Rn, op1 + Rn))
1461 SETS;
1462 state->Reg[BITS (16, 19)] = op1 + Rn;
1463 break;
1464 }
1465
1466 if (BITS (4, 11) == 5)
1467 {
1468 /* ElSegundo QADD insn. */
1469 ARMword op1 = state->Reg[BITS (0, 3)];
1470 ARMword op2 = state->Reg[BITS (16, 19)];
1471 ARMword result = op1 + op2;
1472 if (AddOverflow (op1, op2, result))
1473 {
1474 result = POS (result) ? 0x80000000 : 0x7fffffff;
1475 SETS;
1476 }
1477 state->Reg[BITS (12, 15)] = result;
1478 break;
1479 }
1480 }
1481 #ifdef MODET
1482 if (BITS (4, 11) == 0xB)
1483 {
1484 /* STRH register offset, no write-back, down, pre indexed. */
1485 SHPREDOWN ();
1486 break;
1487 }
1488 if (BITS (4, 7) == 0xD)
1489 {
1490 Handle_Load_Double (state, instr);
1491 break;
1492 }
1493 if (BITS (4, 7) == 0xF)
1494 {
1495 Handle_Store_Double (state, instr);
1496 break;
1497 }
1498 #endif
1499 if (BITS (4, 11) == 9)
1500 {
1501 /* SWP */
1502 UNDEF_SWPPC;
1503 temp = LHS;
1504 BUSUSEDINCPCS;
1505 #ifndef MODE32
1506 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
1507 {
1508 INTERNALABORT (temp);
1509 (void) ARMul_LoadWordN (state, temp);
1510 (void) ARMul_LoadWordN (state, temp);
1511 }
1512 else
1513 #endif
1514 dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
1515 if (temp & 3)
1516 DEST = ARMul_Align (state, temp, dest);
1517 else
1518 DEST = dest;
1519 if (state->abortSig || state->Aborted)
1520 TAKEABORT;
1521 }
1522 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
1523 { /* MRS CPSR */
1524 UNDEF_MRSPC;
1525 DEST = ECC | EINT | EMODE;
1526 }
1527 else
1528 {
1529 UNDEF_Test;
1530 }
1531 break;
1532
1533 case 0x11: /* TSTP reg */
1534 #ifdef MODET
1535 if ((BITS (4, 11) & 0xF9) == 0x9)
1536 /* LDR register offset, no write-back, down, pre indexed. */
1537 LHPREDOWN ();
1538 /* Continue with remaining instruction decode. */
1539 #endif
1540 if (DESTReg == 15)
1541 {
1542 /* TSTP reg */
1543 #ifdef MODE32
1544 state->Cpsr = GETSPSR (state->Bank);
1545 ARMul_CPSRAltered (state);
1546 #else
1547 rhs = DPRegRHS;
1548 temp = LHS & rhs;
1549 SETR15PSR (temp);
1550 #endif
1551 }
1552 else
1553 {
1554 /* TST reg */
1555 rhs = DPSRegRHS;
1556 dest = LHS & rhs;
1557 ARMul_NegZero (state, dest);
1558 }
1559 break;
1560
1561 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
1562 if (state->is_v5)
1563 {
1564 if (BITS (4, 7) == 3)
1565 {
1566 /* BLX(2) */
1567 ARMword temp;
1568
1569 if (TFLAG)
1570 temp = (pc + 2) | 1;
1571 else
1572 temp = pc + 4;
1573
1574 WriteR15Branch (state, state->Reg[RHSReg]);
1575 state->Reg[14] = temp;
1576 break;
1577 }
1578 }
1579
1580 if (state->is_v5e)
1581 {
1582 if (BIT (4) == 0 && BIT (7) == 1
1583 && (BIT (5) == 0 || BITS (12, 15) == 0))
1584 {
1585 /* ElSegundo SMLAWy/SMULWy insn. */
1586 ARMdword op1 = state->Reg[BITS (0, 3)];
1587 ARMdword op2 = state->Reg[BITS (8, 11)];
1588 ARMdword result;
1589
1590 if (BIT (6))
1591 op2 >>= 16;
1592 if (op1 & 0x80000000)
1593 op1 -= 1ULL << 32;
1594 op2 &= 0xFFFF;
1595 if (op2 & 0x8000)
1596 op2 -= 65536;
1597 result = (op1 * op2) >> 16;
1598
1599 if (BIT (5) == 0)
1600 {
1601 ARMword Rn = state->Reg[BITS (12, 15)];
1602
1603 if (AddOverflow (result, Rn, result + Rn))
1604 SETS;
1605 result += Rn;
1606 }
1607 state->Reg[BITS (16, 19)] = result;
1608 break;
1609 }
1610
1611 if (BITS (4, 11) == 5)
1612 {
1613 /* ElSegundo QSUB insn. */
1614 ARMword op1 = state->Reg[BITS (0, 3)];
1615 ARMword op2 = state->Reg[BITS (16, 19)];
1616 ARMword result = op1 - op2;
1617
1618 if (SubOverflow (op1, op2, result))
1619 {
1620 result = POS (result) ? 0x80000000 : 0x7fffffff;
1621 SETS;
1622 }
1623
1624 state->Reg[BITS (12, 15)] = result;
1625 break;
1626 }
1627 }
1628 #ifdef MODET
1629 if (BITS (4, 11) == 0xB)
1630 {
1631 /* STRH register offset, write-back, down, pre indexed. */
1632 SHPREDOWNWB ();
1633 break;
1634 }
1635 if (BITS (4, 27) == 0x12FFF1)
1636 {
1637 /* BX */
1638 WriteR15Branch (state, state->Reg[RHSReg]);
1639 break;
1640 }
1641 if (BITS (4, 7) == 0xD)
1642 {
1643 Handle_Load_Double (state, instr);
1644 break;
1645 }
1646 if (BITS (4, 7) == 0xF)
1647 {
1648 Handle_Store_Double (state, instr);
1649 break;
1650 }
1651 #endif
1652 if (state->is_v5)
1653 {
1654 if (BITS (4, 7) == 0x7)
1655 {
1656 ARMword value;
1657 extern int SWI_vector_installed;
1658
1659 /* Hardware is allowed to optionally override this
1660 instruction and treat it as a breakpoint. Since
1661 this is a simulator not hardware, we take the position
1662 that if a SWI vector was not installed, then an Abort
1663 vector was probably not installed either, and so
1664 normally this instruction would be ignored, even if an
1665 Abort is generated. This is a bad thing, since GDB
1666 uses this instruction for its breakpoints (at least in
1667 Thumb mode it does). So intercept the instruction here
1668 and generate a breakpoint SWI instead. */
1669 if (! SWI_vector_installed)
1670 ARMul_OSHandleSWI (state, SWI_Breakpoint);
1671 else
1672 {
1673 /* BKPT - normally this will cause an abort, but on the
1674 XScale we must check the DCSR. */
1675 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
1676 if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT))
1677 break;
1678 }
1679
1680 /* Force the next instruction to be refetched. */
1681 state->NextInstr = RESUME;
1682 break;
1683 }
1684 }
1685 if (DESTReg == 15)
1686 {
1687 /* MSR reg to CPSR. */
1688 UNDEF_MSRPC;
1689 temp = DPRegRHS;
1690 #ifdef MODET
1691 /* Don't allow TBIT to be set by MSR. */
1692 temp &= ~ TBIT;
1693 #endif
1694 ARMul_FixCPSR (state, instr, temp);
1695 }
1696 else
1697 UNDEF_Test;
1698
1699 break;
1700
1701 case 0x13: /* TEQP reg */
1702 #ifdef MODET
1703 if ((BITS (4, 11) & 0xF9) == 0x9)
1704 /* LDR register offset, write-back, down, pre indexed. */
1705 LHPREDOWNWB ();
1706 /* Continue with remaining instruction decode. */
1707 #endif
1708 if (DESTReg == 15)
1709 {
1710 /* TEQP reg */
1711 #ifdef MODE32
1712 state->Cpsr = GETSPSR (state->Bank);
1713 ARMul_CPSRAltered (state);
1714 #else
1715 rhs = DPRegRHS;
1716 temp = LHS ^ rhs;
1717 SETR15PSR (temp);
1718 #endif
1719 }
1720 else
1721 {
1722 /* TEQ Reg. */
1723 rhs = DPSRegRHS;
1724 dest = LHS ^ rhs;
1725 ARMul_NegZero (state, dest);
1726 }
1727 break;
1728
1729 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
1730 if (state->is_v5e)
1731 {
1732 if (BIT (4) == 0 && BIT (7) == 1)
1733 {
1734 /* ElSegundo SMLALxy insn. */
1735 ARMdword op1 = state->Reg[BITS (0, 3)];
1736 ARMdword op2 = state->Reg[BITS (8, 11)];
1737 ARMdword dest;
1738 ARMdword result;
1739
1740 if (BIT (5))
1741 op1 >>= 16;
1742 if (BIT (6))
1743 op2 >>= 16;
1744 op1 &= 0xFFFF;
1745 if (op1 & 0x8000)
1746 op1 -= 65536;
1747 op2 &= 0xFFFF;
1748 if (op2 & 0x8000)
1749 op2 -= 65536;
1750
1751 dest = (ARMdword) state->Reg[BITS (16, 19)] << 32;
1752 dest |= state->Reg[BITS (12, 15)];
1753 dest += op1 * op2;
1754 state->Reg[BITS (12, 15)] = dest;
1755 state->Reg[BITS (16, 19)] = dest >> 32;
1756 break;
1757 }
1758
1759 if (BITS (4, 11) == 5)
1760 {
1761 /* ElSegundo QDADD insn. */
1762 ARMword op1 = state->Reg[BITS (0, 3)];
1763 ARMword op2 = state->Reg[BITS (16, 19)];
1764 ARMword op2d = op2 + op2;
1765 ARMword result;
1766
1767 if (AddOverflow (op2, op2, op2d))
1768 {
1769 SETS;
1770 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1771 }
1772
1773 result = op1 + op2d;
1774 if (AddOverflow (op1, op2d, result))
1775 {
1776 SETS;
1777 result = POS (result) ? 0x80000000 : 0x7fffffff;
1778 }
1779
1780 state->Reg[BITS (12, 15)] = result;
1781 break;
1782 }
1783 }
1784 #ifdef MODET
1785 if (BITS (4, 7) == 0xB)
1786 {
1787 /* STRH immediate offset, no write-back, down, pre indexed. */
1788 SHPREDOWN ();
1789 break;
1790 }
1791 if (BITS (4, 7) == 0xD)
1792 {
1793 Handle_Load_Double (state, instr);
1794 break;
1795 }
1796 if (BITS (4, 7) == 0xF)
1797 {
1798 Handle_Store_Double (state, instr);
1799 break;
1800 }
1801 #endif
1802 if (BITS (4, 11) == 9)
1803 {
1804 /* SWP */
1805 UNDEF_SWPPC;
1806 temp = LHS;
1807 BUSUSEDINCPCS;
1808 #ifndef MODE32
1809 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
1810 {
1811 INTERNALABORT (temp);
1812 (void) ARMul_LoadByte (state, temp);
1813 (void) ARMul_LoadByte (state, temp);
1814 }
1815 else
1816 #endif
1817 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
1818 if (state->abortSig || state->Aborted)
1819 TAKEABORT;
1820 }
1821 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
1822 {
1823 /* MRS SPSR */
1824 UNDEF_MRSPC;
1825 DEST = GETSPSR (state->Bank);
1826 }
1827 else
1828 UNDEF_Test;
1829
1830 break;
1831
1832 case 0x15: /* CMPP reg. */
1833 #ifdef MODET
1834 if ((BITS (4, 7) & 0x9) == 0x9)
1835 /* LDR immediate offset, no write-back, down, pre indexed. */
1836 LHPREDOWN ();
1837 /* Continue with remaining instruction decode. */
1838 #endif
1839 if (DESTReg == 15)
1840 {
1841 /* CMPP reg. */
1842 #ifdef MODE32
1843 state->Cpsr = GETSPSR (state->Bank);
1844 ARMul_CPSRAltered (state);
1845 #else
1846 rhs = DPRegRHS;
1847 temp = LHS - rhs;
1848 SETR15PSR (temp);
1849 #endif
1850 }
1851 else
1852 {
1853 /* CMP reg. */
1854 lhs = LHS;
1855 rhs = DPRegRHS;
1856 dest = lhs - rhs;
1857 ARMul_NegZero (state, dest);
1858 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1859 {
1860 ARMul_SubCarry (state, lhs, rhs, dest);
1861 ARMul_SubOverflow (state, lhs, rhs, dest);
1862 }
1863 else
1864 {
1865 CLEARC;
1866 CLEARV;
1867 }
1868 }
1869 break;
1870
1871 case 0x16: /* CMN reg and MSR reg to SPSR */
1872 if (state->is_v5e)
1873 {
1874 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1875 {
1876 /* ElSegundo SMULxy insn. */
1877 ARMword op1 = state->Reg[BITS (0, 3)];
1878 ARMword op2 = state->Reg[BITS (8, 11)];
1879 ARMword Rn = state->Reg[BITS (12, 15)];
1880
1881 if (BIT (5))
1882 op1 >>= 16;
1883 if (BIT (6))
1884 op2 >>= 16;
1885 op1 &= 0xFFFF;
1886 op2 &= 0xFFFF;
1887 if (op1 & 0x8000)
1888 op1 -= 65536;
1889 if (op2 & 0x8000)
1890 op2 -= 65536;
1891
1892 state->Reg[BITS (16, 19)] = op1 * op2;
1893 break;
1894 }
1895
1896 if (BITS (4, 11) == 5)
1897 {
1898 /* ElSegundo QDSUB insn. */
1899 ARMword op1 = state->Reg[BITS (0, 3)];
1900 ARMword op2 = state->Reg[BITS (16, 19)];
1901 ARMword op2d = op2 + op2;
1902 ARMword result;
1903
1904 if (AddOverflow (op2, op2, op2d))
1905 {
1906 SETS;
1907 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1908 }
1909
1910 result = op1 - op2d;
1911 if (SubOverflow (op1, op2d, result))
1912 {
1913 SETS;
1914 result = POS (result) ? 0x80000000 : 0x7fffffff;
1915 }
1916
1917 state->Reg[BITS (12, 15)] = result;
1918 break;
1919 }
1920 }
1921
1922 if (state->is_v5)
1923 {
1924 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1925 {
1926 /* ARM5 CLZ insn. */
1927 ARMword op1 = state->Reg[BITS (0, 3)];
1928 int result = 32;
1929
1930 if (op1)
1931 for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
1932 result++;
1933
1934 state->Reg[BITS (12, 15)] = result;
1935 break;
1936 }
1937 }
1938 #ifdef MODET
1939 if (BITS (4, 7) == 0xB)
1940 {
1941 /* STRH immediate offset, write-back, down, pre indexed. */
1942 SHPREDOWNWB ();
1943 break;
1944 }
1945 if (BITS (4, 7) == 0xD)
1946 {
1947 Handle_Load_Double (state, instr);
1948 break;
1949 }
1950 if (BITS (4, 7) == 0xF)
1951 {
1952 Handle_Store_Double (state, instr);
1953 break;
1954 }
1955 #endif
1956 if (DESTReg == 15)
1957 {
1958 /* MSR */
1959 UNDEF_MSRPC;
1960 ARMul_FixSPSR (state, instr, DPRegRHS);
1961 }
1962 else
1963 {
1964 UNDEF_Test;
1965 }
1966 break;
1967
1968 case 0x17: /* CMNP reg */
1969 #ifdef MODET
1970 if ((BITS (4, 7) & 0x9) == 0x9)
1971 /* LDR immediate offset, write-back, down, pre indexed. */
1972 LHPREDOWNWB ();
1973 /* Continue with remaining instruction decoding. */
1974 #endif
1975 if (DESTReg == 15)
1976 {
1977 #ifdef MODE32
1978 state->Cpsr = GETSPSR (state->Bank);
1979 ARMul_CPSRAltered (state);
1980 #else
1981 rhs = DPRegRHS;
1982 temp = LHS + rhs;
1983 SETR15PSR (temp);
1984 #endif
1985 break;
1986 }
1987 else
1988 {
1989 /* CMN reg. */
1990 lhs = LHS;
1991 rhs = DPRegRHS;
1992 dest = lhs + rhs;
1993 ASSIGNZ (dest == 0);
1994 if ((lhs | rhs) >> 30)
1995 {
1996 /* Possible C,V,N to set. */
1997 ASSIGNN (NEG (dest));
1998 ARMul_AddCarry (state, lhs, rhs, dest);
1999 ARMul_AddOverflow (state, lhs, rhs, dest);
2000 }
2001 else
2002 {
2003 CLEARN;
2004 CLEARC;
2005 CLEARV;
2006 }
2007 }
2008 break;
2009
2010 case 0x18: /* ORR reg */
2011 #ifdef MODET
2012 if (BITS (4, 11) == 0xB)
2013 {
2014 /* STRH register offset, no write-back, up, pre indexed. */
2015 SHPREUP ();
2016 break;
2017 }
2018 if (BITS (4, 7) == 0xD)
2019 {
2020 Handle_Load_Double (state, instr);
2021 break;
2022 }
2023 if (BITS (4, 7) == 0xF)
2024 {
2025 Handle_Store_Double (state, instr);
2026 break;
2027 }
2028 #endif
2029 rhs = DPRegRHS;
2030 dest = LHS | rhs;
2031 WRITEDEST (dest);
2032 break;
2033
2034 case 0x19: /* ORRS reg */
2035 #ifdef MODET
2036 if ((BITS (4, 11) & 0xF9) == 0x9)
2037 /* LDR register offset, no write-back, up, pre indexed. */
2038 LHPREUP ();
2039 /* Continue with remaining instruction decoding. */
2040 #endif
2041 rhs = DPSRegRHS;
2042 dest = LHS | rhs;
2043 WRITESDEST (dest);
2044 break;
2045
2046 case 0x1a: /* MOV reg */
2047 #ifdef MODET
2048 if (BITS (4, 11) == 0xB)
2049 {
2050 /* STRH register offset, write-back, up, pre indexed. */
2051 SHPREUPWB ();
2052 break;
2053 }
2054 if (BITS (4, 7) == 0xD)
2055 {
2056 Handle_Load_Double (state, instr);
2057 break;
2058 }
2059 if (BITS (4, 7) == 0xF)
2060 {
2061 Handle_Store_Double (state, instr);
2062 break;
2063 }
2064 #endif
2065 dest = DPRegRHS;
2066 WRITEDEST (dest);
2067 break;
2068
2069 case 0x1b: /* MOVS reg */
2070 #ifdef MODET
2071 if ((BITS (4, 11) & 0xF9) == 0x9)
2072 /* LDR register offset, write-back, up, pre indexed. */
2073 LHPREUPWB ();
2074 /* Continue with remaining instruction decoding. */
2075 #endif
2076 dest = DPSRegRHS;
2077 WRITESDEST (dest);
2078 break;
2079
2080 case 0x1c: /* BIC reg */
2081 #ifdef MODET
2082 if (BITS (4, 7) == 0xB)
2083 {
2084 /* STRH immediate offset, no write-back, up, pre indexed. */
2085 SHPREUP ();
2086 break;
2087 }
2088 if (BITS (4, 7) == 0xD)
2089 {
2090 Handle_Load_Double (state, instr);
2091 break;
2092 }
2093 else if (BITS (4, 7) == 0xF)
2094 {
2095 Handle_Store_Double (state, instr);
2096 break;
2097 }
2098 #endif
2099 rhs = DPRegRHS;
2100 dest = LHS & ~rhs;
2101 WRITEDEST (dest);
2102 break;
2103
2104 case 0x1d: /* BICS reg */
2105 #ifdef MODET
2106 if ((BITS (4, 7) & 0x9) == 0x9)
2107 /* LDR immediate offset, no write-back, up, pre indexed. */
2108 LHPREUP ();
2109 /* Continue with instruction decoding. */
2110 #endif
2111 rhs = DPSRegRHS;
2112 dest = LHS & ~rhs;
2113 WRITESDEST (dest);
2114 break;
2115
2116 case 0x1e: /* MVN reg */
2117 #ifdef MODET
2118 if (BITS (4, 7) == 0xB)
2119 {
2120 /* STRH immediate offset, write-back, up, pre indexed. */
2121 SHPREUPWB ();
2122 break;
2123 }
2124 if (BITS (4, 7) == 0xD)
2125 {
2126 Handle_Load_Double (state, instr);
2127 break;
2128 }
2129 if (BITS (4, 7) == 0xF)
2130 {
2131 Handle_Store_Double (state, instr);
2132 break;
2133 }
2134 #endif
2135 dest = ~DPRegRHS;
2136 WRITEDEST (dest);
2137 break;
2138
2139 case 0x1f: /* MVNS reg */
2140 #ifdef MODET
2141 if ((BITS (4, 7) & 0x9) == 0x9)
2142 /* LDR immediate offset, write-back, up, pre indexed. */
2143 LHPREUPWB ();
2144 /* Continue instruction decoding. */
2145 #endif
2146 dest = ~DPSRegRHS;
2147 WRITESDEST (dest);
2148 break;
2149
2150
2151 /* Data Processing Immediate RHS Instructions. */
2152
2153 case 0x20: /* AND immed */
2154 dest = LHS & DPImmRHS;
2155 WRITEDEST (dest);
2156 break;
2157
2158 case 0x21: /* ANDS immed */
2159 DPSImmRHS;
2160 dest = LHS & rhs;
2161 WRITESDEST (dest);
2162 break;
2163
2164 case 0x22: /* EOR immed */
2165 dest = LHS ^ DPImmRHS;
2166 WRITEDEST (dest);
2167 break;
2168
2169 case 0x23: /* EORS immed */
2170 DPSImmRHS;
2171 dest = LHS ^ rhs;
2172 WRITESDEST (dest);
2173 break;
2174
2175 case 0x24: /* SUB immed */
2176 dest = LHS - DPImmRHS;
2177 WRITEDEST (dest);
2178 break;
2179
2180 case 0x25: /* SUBS immed */
2181 lhs = LHS;
2182 rhs = DPImmRHS;
2183 dest = lhs - rhs;
2184
2185 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2186 {
2187 ARMul_SubCarry (state, lhs, rhs, dest);
2188 ARMul_SubOverflow (state, lhs, rhs, dest);
2189 }
2190 else
2191 {
2192 CLEARC;
2193 CLEARV;
2194 }
2195 WRITESDEST (dest);
2196 break;
2197
2198 case 0x26: /* RSB immed */
2199 dest = DPImmRHS - LHS;
2200 WRITEDEST (dest);
2201 break;
2202
2203 case 0x27: /* RSBS immed */
2204 lhs = LHS;
2205 rhs = DPImmRHS;
2206 dest = rhs - lhs;
2207
2208 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
2209 {
2210 ARMul_SubCarry (state, rhs, lhs, dest);
2211 ARMul_SubOverflow (state, rhs, lhs, dest);
2212 }
2213 else
2214 {
2215 CLEARC;
2216 CLEARV;
2217 }
2218 WRITESDEST (dest);
2219 break;
2220
2221 case 0x28: /* ADD immed */
2222 dest = LHS + DPImmRHS;
2223 WRITEDEST (dest);
2224 break;
2225
2226 case 0x29: /* ADDS immed */
2227 lhs = LHS;
2228 rhs = DPImmRHS;
2229 dest = lhs + rhs;
2230 ASSIGNZ (dest == 0);
2231
2232 if ((lhs | rhs) >> 30)
2233 {
2234 /* Possible C,V,N to set. */
2235 ASSIGNN (NEG (dest));
2236 ARMul_AddCarry (state, lhs, rhs, dest);
2237 ARMul_AddOverflow (state, lhs, rhs, dest);
2238 }
2239 else
2240 {
2241 CLEARN;
2242 CLEARC;
2243 CLEARV;
2244 }
2245 WRITESDEST (dest);
2246 break;
2247
2248 case 0x2a: /* ADC immed */
2249 dest = LHS + DPImmRHS + CFLAG;
2250 WRITEDEST (dest);
2251 break;
2252
2253 case 0x2b: /* ADCS immed */
2254 lhs = LHS;
2255 rhs = DPImmRHS;
2256 dest = lhs + rhs + CFLAG;
2257 ASSIGNZ (dest == 0);
2258 if ((lhs | rhs) >> 30)
2259 {
2260 /* Possible C,V,N to set. */
2261 ASSIGNN (NEG (dest));
2262 ARMul_AddCarry (state, lhs, rhs, dest);
2263 ARMul_AddOverflow (state, lhs, rhs, dest);
2264 }
2265 else
2266 {
2267 CLEARN;
2268 CLEARC;
2269 CLEARV;
2270 }
2271 WRITESDEST (dest);
2272 break;
2273
2274 case 0x2c: /* SBC immed */
2275 dest = LHS - DPImmRHS - !CFLAG;
2276 WRITEDEST (dest);
2277 break;
2278
2279 case 0x2d: /* SBCS immed */
2280 lhs = LHS;
2281 rhs = DPImmRHS;
2282 dest = lhs - rhs - !CFLAG;
2283 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2284 {
2285 ARMul_SubCarry (state, lhs, rhs, dest);
2286 ARMul_SubOverflow (state, lhs, rhs, dest);
2287 }
2288 else
2289 {
2290 CLEARC;
2291 CLEARV;
2292 }
2293 WRITESDEST (dest);
2294 break;
2295
2296 case 0x2e: /* RSC immed */
2297 dest = DPImmRHS - LHS - !CFLAG;
2298 WRITEDEST (dest);
2299 break;
2300
2301 case 0x2f: /* RSCS immed */
2302 lhs = LHS;
2303 rhs = DPImmRHS;
2304 dest = rhs - lhs - !CFLAG;
2305 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
2306 {
2307 ARMul_SubCarry (state, rhs, lhs, dest);
2308 ARMul_SubOverflow (state, rhs, lhs, dest);
2309 }
2310 else
2311 {
2312 CLEARC;
2313 CLEARV;
2314 }
2315 WRITESDEST (dest);
2316 break;
2317
2318 case 0x30: /* TST immed */
2319 UNDEF_Test;
2320 break;
2321
2322 case 0x31: /* TSTP immed */
2323 if (DESTReg == 15)
2324 {
2325 /* TSTP immed. */
2326 #ifdef MODE32
2327 state->Cpsr = GETSPSR (state->Bank);
2328 ARMul_CPSRAltered (state);
2329 #else
2330 temp = LHS & DPImmRHS;
2331 SETR15PSR (temp);
2332 #endif
2333 }
2334 else
2335 {
2336 /* TST immed. */
2337 DPSImmRHS;
2338 dest = LHS & rhs;
2339 ARMul_NegZero (state, dest);
2340 }
2341 break;
2342
2343 case 0x32: /* TEQ immed and MSR immed to CPSR */
2344 if (DESTReg == 15)
2345 /* MSR immed to CPSR. */
2346 ARMul_FixCPSR (state, instr, DPImmRHS);
2347 else
2348 UNDEF_Test;
2349 break;
2350
2351 case 0x33: /* TEQP immed */
2352 if (DESTReg == 15)
2353 {
2354 /* TEQP immed. */
2355 #ifdef MODE32
2356 state->Cpsr = GETSPSR (state->Bank);
2357 ARMul_CPSRAltered (state);
2358 #else
2359 temp = LHS ^ DPImmRHS;
2360 SETR15PSR (temp);
2361 #endif
2362 }
2363 else
2364 {
2365 DPSImmRHS; /* TEQ immed */
2366 dest = LHS ^ rhs;
2367 ARMul_NegZero (state, dest);
2368 }
2369 break;
2370
2371 case 0x34: /* CMP immed */
2372 UNDEF_Test;
2373 break;
2374
2375 case 0x35: /* CMPP immed */
2376 if (DESTReg == 15)
2377 {
2378 /* CMPP immed. */
2379 #ifdef MODE32
2380 state->Cpsr = GETSPSR (state->Bank);
2381 ARMul_CPSRAltered (state);
2382 #else
2383 temp = LHS - DPImmRHS;
2384 SETR15PSR (temp);
2385 #endif
2386 break;
2387 }
2388 else
2389 {
2390 /* CMP immed. */
2391 lhs = LHS;
2392 rhs = DPImmRHS;
2393 dest = lhs - rhs;
2394 ARMul_NegZero (state, dest);
2395
2396 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2397 {
2398 ARMul_SubCarry (state, lhs, rhs, dest);
2399 ARMul_SubOverflow (state, lhs, rhs, dest);
2400 }
2401 else
2402 {
2403 CLEARC;
2404 CLEARV;
2405 }
2406 }
2407 break;
2408
2409 case 0x36: /* CMN immed and MSR immed to SPSR */
2410 if (DESTReg == 15)
2411 ARMul_FixSPSR (state, instr, DPImmRHS);
2412 else
2413 UNDEF_Test;
2414 break;
2415
2416 case 0x37: /* CMNP immed. */
2417 if (DESTReg == 15)
2418 {
2419 /* CMNP immed. */
2420 #ifdef MODE32
2421 state->Cpsr = GETSPSR (state->Bank);
2422 ARMul_CPSRAltered (state);
2423 #else
2424 temp = LHS + DPImmRHS;
2425 SETR15PSR (temp);
2426 #endif
2427 break;
2428 }
2429 else
2430 {
2431 /* CMN immed. */
2432 lhs = LHS;
2433 rhs = DPImmRHS;
2434 dest = lhs + rhs;
2435 ASSIGNZ (dest == 0);
2436 if ((lhs | rhs) >> 30)
2437 {
2438 /* Possible C,V,N to set. */
2439 ASSIGNN (NEG (dest));
2440 ARMul_AddCarry (state, lhs, rhs, dest);
2441 ARMul_AddOverflow (state, lhs, rhs, dest);
2442 }
2443 else
2444 {
2445 CLEARN;
2446 CLEARC;
2447 CLEARV;
2448 }
2449 }
2450 break;
2451
2452 case 0x38: /* ORR immed. */
2453 dest = LHS | DPImmRHS;
2454 WRITEDEST (dest);
2455 break;
2456
2457 case 0x39: /* ORRS immed. */
2458 DPSImmRHS;
2459 dest = LHS | rhs;
2460 WRITESDEST (dest);
2461 break;
2462
2463 case 0x3a: /* MOV immed. */
2464 dest = DPImmRHS;
2465 WRITEDEST (dest);
2466 break;
2467
2468 case 0x3b: /* MOVS immed. */
2469 DPSImmRHS;
2470 WRITESDEST (rhs);
2471 break;
2472
2473 case 0x3c: /* BIC immed. */
2474 dest = LHS & ~DPImmRHS;
2475 WRITEDEST (dest);
2476 break;
2477
2478 case 0x3d: /* BICS immed. */
2479 DPSImmRHS;
2480 dest = LHS & ~rhs;
2481 WRITESDEST (dest);
2482 break;
2483
2484 case 0x3e: /* MVN immed. */
2485 dest = ~DPImmRHS;
2486 WRITEDEST (dest);
2487 break;
2488
2489 case 0x3f: /* MVNS immed. */
2490 DPSImmRHS;
2491 WRITESDEST (~rhs);
2492 break;
2493
2494
2495 /* Single Data Transfer Immediate RHS Instructions. */
2496
2497 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2498 lhs = LHS;
2499 if (StoreWord (state, instr, lhs))
2500 LSBase = lhs - LSImmRHS;
2501 break;
2502
2503 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2504 lhs = LHS;
2505 if (LoadWord (state, instr, lhs))
2506 LSBase = lhs - LSImmRHS;
2507 break;
2508
2509 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2510 UNDEF_LSRBaseEQDestWb;
2511 UNDEF_LSRPCBaseWb;
2512 lhs = LHS;
2513 temp = lhs - LSImmRHS;
2514 state->NtransSig = LOW;
2515 if (StoreWord (state, instr, lhs))
2516 LSBase = temp;
2517 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2518 break;
2519
2520 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2521 UNDEF_LSRBaseEQDestWb;
2522 UNDEF_LSRPCBaseWb;
2523 lhs = LHS;
2524 state->NtransSig = LOW;
2525 if (LoadWord (state, instr, lhs))
2526 LSBase = lhs - LSImmRHS;
2527 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2528 break;
2529
2530 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2531 lhs = LHS;
2532 if (StoreByte (state, instr, lhs))
2533 LSBase = lhs - LSImmRHS;
2534 break;
2535
2536 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2537 lhs = LHS;
2538 if (LoadByte (state, instr, lhs, LUNSIGNED))
2539 LSBase = lhs - LSImmRHS;
2540 break;
2541
2542 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2543 UNDEF_LSRBaseEQDestWb;
2544 UNDEF_LSRPCBaseWb;
2545 lhs = LHS;
2546 state->NtransSig = LOW;
2547 if (StoreByte (state, instr, lhs))
2548 LSBase = lhs - LSImmRHS;
2549 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2550 break;
2551
2552 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2553 UNDEF_LSRBaseEQDestWb;
2554 UNDEF_LSRPCBaseWb;
2555 lhs = LHS;
2556 state->NtransSig = LOW;
2557 if (LoadByte (state, instr, lhs, LUNSIGNED))
2558 LSBase = lhs - LSImmRHS;
2559 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2560 break;
2561
2562 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2563 lhs = LHS;
2564 if (StoreWord (state, instr, lhs))
2565 LSBase = lhs + LSImmRHS;
2566 break;
2567
2568 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2569 lhs = LHS;
2570 if (LoadWord (state, instr, lhs))
2571 LSBase = lhs + LSImmRHS;
2572 break;
2573
2574 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2575 UNDEF_LSRBaseEQDestWb;
2576 UNDEF_LSRPCBaseWb;
2577 lhs = LHS;
2578 state->NtransSig = LOW;
2579 if (StoreWord (state, instr, lhs))
2580 LSBase = lhs + LSImmRHS;
2581 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2582 break;
2583
2584 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2585 UNDEF_LSRBaseEQDestWb;
2586 UNDEF_LSRPCBaseWb;
2587 lhs = LHS;
2588 state->NtransSig = LOW;
2589 if (LoadWord (state, instr, lhs))
2590 LSBase = lhs + LSImmRHS;
2591 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2592 break;
2593
2594 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2595 lhs = LHS;
2596 if (StoreByte (state, instr, lhs))
2597 LSBase = lhs + LSImmRHS;
2598 break;
2599
2600 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2601 lhs = LHS;
2602 if (LoadByte (state, instr, lhs, LUNSIGNED))
2603 LSBase = lhs + LSImmRHS;
2604 break;
2605
2606 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2607 UNDEF_LSRBaseEQDestWb;
2608 UNDEF_LSRPCBaseWb;
2609 lhs = LHS;
2610 state->NtransSig = LOW;
2611 if (StoreByte (state, instr, lhs))
2612 LSBase = lhs + LSImmRHS;
2613 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2614 break;
2615
2616 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2617 UNDEF_LSRBaseEQDestWb;
2618 UNDEF_LSRPCBaseWb;
2619 lhs = LHS;
2620 state->NtransSig = LOW;
2621 if (LoadByte (state, instr, lhs, LUNSIGNED))
2622 LSBase = lhs + LSImmRHS;
2623 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2624 break;
2625
2626
2627 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2628 (void) StoreWord (state, instr, LHS - LSImmRHS);
2629 break;
2630
2631 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2632 (void) LoadWord (state, instr, LHS - LSImmRHS);
2633 break;
2634
2635 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2636 UNDEF_LSRBaseEQDestWb;
2637 UNDEF_LSRPCBaseWb;
2638 temp = LHS - LSImmRHS;
2639 if (StoreWord (state, instr, temp))
2640 LSBase = temp;
2641 break;
2642
2643 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2644 UNDEF_LSRBaseEQDestWb;
2645 UNDEF_LSRPCBaseWb;
2646 temp = LHS - LSImmRHS;
2647 if (LoadWord (state, instr, temp))
2648 LSBase = temp;
2649 break;
2650
2651 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2652 (void) StoreByte (state, instr, LHS - LSImmRHS);
2653 break;
2654
2655 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2656 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
2657 break;
2658
2659 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2660 UNDEF_LSRBaseEQDestWb;
2661 UNDEF_LSRPCBaseWb;
2662 temp = LHS - LSImmRHS;
2663 if (StoreByte (state, instr, temp))
2664 LSBase = temp;
2665 break;
2666
2667 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2668 UNDEF_LSRBaseEQDestWb;
2669 UNDEF_LSRPCBaseWb;
2670 temp = LHS - LSImmRHS;
2671 if (LoadByte (state, instr, temp, LUNSIGNED))
2672 LSBase = temp;
2673 break;
2674
2675 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2676 (void) StoreWord (state, instr, LHS + LSImmRHS);
2677 break;
2678
2679 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2680 (void) LoadWord (state, instr, LHS + LSImmRHS);
2681 break;
2682
2683 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2684 UNDEF_LSRBaseEQDestWb;
2685 UNDEF_LSRPCBaseWb;
2686 temp = LHS + LSImmRHS;
2687 if (StoreWord (state, instr, temp))
2688 LSBase = temp;
2689 break;
2690
2691 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2692 UNDEF_LSRBaseEQDestWb;
2693 UNDEF_LSRPCBaseWb;
2694 temp = LHS + LSImmRHS;
2695 if (LoadWord (state, instr, temp))
2696 LSBase = temp;
2697 break;
2698
2699 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2700 (void) StoreByte (state, instr, LHS + LSImmRHS);
2701 break;
2702
2703 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2704 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
2705 break;
2706
2707 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2708 UNDEF_LSRBaseEQDestWb;
2709 UNDEF_LSRPCBaseWb;
2710 temp = LHS + LSImmRHS;
2711 if (StoreByte (state, instr, temp))
2712 LSBase = temp;
2713 break;
2714
2715 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2716 UNDEF_LSRBaseEQDestWb;
2717 UNDEF_LSRPCBaseWb;
2718 temp = LHS + LSImmRHS;
2719 if (LoadByte (state, instr, temp, LUNSIGNED))
2720 LSBase = temp;
2721 break;
2722
2723
2724 /* Single Data Transfer Register RHS Instructions. */
2725
2726 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2727 if (BIT (4))
2728 {
2729 ARMul_UndefInstr (state, instr);
2730 break;
2731 }
2732 UNDEF_LSRBaseEQOffWb;
2733 UNDEF_LSRBaseEQDestWb;
2734 UNDEF_LSRPCBaseWb;
2735 UNDEF_LSRPCOffWb;
2736 lhs = LHS;
2737 if (StoreWord (state, instr, lhs))
2738 LSBase = lhs - LSRegRHS;
2739 break;
2740
2741 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2742 if (BIT (4))
2743 {
2744 #ifdef MODE32
2745 if (state->is_v6
2746 && handle_v6_insn (state, instr))
2747 break;
2748 #endif
2749 ARMul_UndefInstr (state, instr);
2750 break;
2751 }
2752 UNDEF_LSRBaseEQOffWb;
2753 UNDEF_LSRBaseEQDestWb;
2754 UNDEF_LSRPCBaseWb;
2755 UNDEF_LSRPCOffWb;
2756 lhs = LHS;
2757 temp = lhs - LSRegRHS;
2758 if (LoadWord (state, instr, lhs))
2759 LSBase = temp;
2760 break;
2761
2762 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2763 if (BIT (4))
2764 {
2765 #ifdef MODE32
2766 if (state->is_v6
2767 && handle_v6_insn (state, instr))
2768 break;
2769 #endif
2770 ARMul_UndefInstr (state, instr);
2771 break;
2772 }
2773 UNDEF_LSRBaseEQOffWb;
2774 UNDEF_LSRBaseEQDestWb;
2775 UNDEF_LSRPCBaseWb;
2776 UNDEF_LSRPCOffWb;
2777 lhs = LHS;
2778 state->NtransSig = LOW;
2779 if (StoreWord (state, instr, lhs))
2780 LSBase = lhs - LSRegRHS;
2781 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2782 break;
2783
2784 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2785 if (BIT (4))
2786 {
2787 #ifdef MODE32
2788 if (state->is_v6
2789 && handle_v6_insn (state, instr))
2790 break;
2791 #endif
2792 ARMul_UndefInstr (state, instr);
2793 break;
2794 }
2795 UNDEF_LSRBaseEQOffWb;
2796 UNDEF_LSRBaseEQDestWb;
2797 UNDEF_LSRPCBaseWb;
2798 UNDEF_LSRPCOffWb;
2799 lhs = LHS;
2800 temp = lhs - LSRegRHS;
2801 state->NtransSig = LOW;
2802 if (LoadWord (state, instr, lhs))
2803 LSBase = temp;
2804 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2805 break;
2806
2807 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2808 if (BIT (4))
2809 {
2810 ARMul_UndefInstr (state, instr);
2811 break;
2812 }
2813 UNDEF_LSRBaseEQOffWb;
2814 UNDEF_LSRBaseEQDestWb;
2815 UNDEF_LSRPCBaseWb;
2816 UNDEF_LSRPCOffWb;
2817 lhs = LHS;
2818 if (StoreByte (state, instr, lhs))
2819 LSBase = lhs - LSRegRHS;
2820 break;
2821
2822 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2823 if (BIT (4))
2824 {
2825 #ifdef MODE32
2826 if (state->is_v6
2827 && handle_v6_insn (state, instr))
2828 break;
2829 #endif
2830 ARMul_UndefInstr (state, instr);
2831 break;
2832 }
2833 UNDEF_LSRBaseEQOffWb;
2834 UNDEF_LSRBaseEQDestWb;
2835 UNDEF_LSRPCBaseWb;
2836 UNDEF_LSRPCOffWb;
2837 lhs = LHS;
2838 temp = lhs - LSRegRHS;
2839 if (LoadByte (state, instr, lhs, LUNSIGNED))
2840 LSBase = temp;
2841 break;
2842
2843 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2844 if (BIT (4))
2845 {
2846 #ifdef MODE32
2847 if (state->is_v6
2848 && handle_v6_insn (state, instr))
2849 break;
2850 #endif
2851 ARMul_UndefInstr (state, instr);
2852 break;
2853 }
2854 UNDEF_LSRBaseEQOffWb;
2855 UNDEF_LSRBaseEQDestWb;
2856 UNDEF_LSRPCBaseWb;
2857 UNDEF_LSRPCOffWb;
2858 lhs = LHS;
2859 state->NtransSig = LOW;
2860 if (StoreByte (state, instr, lhs))
2861 LSBase = lhs - LSRegRHS;
2862 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2863 break;
2864
2865 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2866 if (BIT (4))
2867 {
2868 #ifdef MODE32
2869 if (state->is_v6
2870 && handle_v6_insn (state, instr))
2871 break;
2872 #endif
2873 ARMul_UndefInstr (state, instr);
2874 break;
2875 }
2876 UNDEF_LSRBaseEQOffWb;
2877 UNDEF_LSRBaseEQDestWb;
2878 UNDEF_LSRPCBaseWb;
2879 UNDEF_LSRPCOffWb;
2880 lhs = LHS;
2881 temp = lhs - LSRegRHS;
2882 state->NtransSig = LOW;
2883 if (LoadByte (state, instr, lhs, LUNSIGNED))
2884 LSBase = temp;
2885 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2886 break;
2887
2888 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2889 if (BIT (4))
2890 {
2891 #ifdef MODE32
2892 if (state->is_v6
2893 && handle_v6_insn (state, instr))
2894 break;
2895 #endif
2896 ARMul_UndefInstr (state, instr);
2897 break;
2898 }
2899 UNDEF_LSRBaseEQOffWb;
2900 UNDEF_LSRBaseEQDestWb;
2901 UNDEF_LSRPCBaseWb;
2902 UNDEF_LSRPCOffWb;
2903 lhs = LHS;
2904 if (StoreWord (state, instr, lhs))
2905 LSBase = lhs + LSRegRHS;
2906 break;
2907
2908 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2909 if (BIT (4))
2910 {
2911 ARMul_UndefInstr (state, instr);
2912 break;
2913 }
2914 UNDEF_LSRBaseEQOffWb;
2915 UNDEF_LSRBaseEQDestWb;
2916 UNDEF_LSRPCBaseWb;
2917 UNDEF_LSRPCOffWb;
2918 lhs = LHS;
2919 temp = lhs + LSRegRHS;
2920 if (LoadWord (state, instr, lhs))
2921 LSBase = temp;
2922 break;
2923
2924 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2925 if (BIT (4))
2926 {
2927 #ifdef MODE32
2928 if (state->is_v6
2929 && handle_v6_insn (state, instr))
2930 break;
2931 #endif
2932 ARMul_UndefInstr (state, instr);
2933 break;
2934 }
2935 UNDEF_LSRBaseEQOffWb;
2936 UNDEF_LSRBaseEQDestWb;
2937 UNDEF_LSRPCBaseWb;
2938 UNDEF_LSRPCOffWb;
2939 lhs = LHS;
2940 state->NtransSig = LOW;
2941 if (StoreWord (state, instr, lhs))
2942 LSBase = lhs + LSRegRHS;
2943 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2944 break;
2945
2946 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2947 if (BIT (4))
2948 {
2949 #ifdef MODE32
2950 if (state->is_v6
2951 && handle_v6_insn (state, instr))
2952 break;
2953 #endif
2954 ARMul_UndefInstr (state, instr);
2955 break;
2956 }
2957 UNDEF_LSRBaseEQOffWb;
2958 UNDEF_LSRBaseEQDestWb;
2959 UNDEF_LSRPCBaseWb;
2960 UNDEF_LSRPCOffWb;
2961 lhs = LHS;
2962 temp = lhs + LSRegRHS;
2963 state->NtransSig = LOW;
2964 if (LoadWord (state, instr, lhs))
2965 LSBase = temp;
2966 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2967 break;
2968
2969 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2970 if (BIT (4))
2971 {
2972 #ifdef MODE32
2973 if (state->is_v6
2974 && handle_v6_insn (state, instr))
2975 break;
2976 #endif
2977 ARMul_UndefInstr (state, instr);
2978 break;
2979 }
2980 UNDEF_LSRBaseEQOffWb;
2981 UNDEF_LSRBaseEQDestWb;
2982 UNDEF_LSRPCBaseWb;
2983 UNDEF_LSRPCOffWb;
2984 lhs = LHS;
2985 if (StoreByte (state, instr, lhs))
2986 LSBase = lhs + LSRegRHS;
2987 break;
2988
2989 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
2990 if (BIT (4))
2991 {
2992 ARMul_UndefInstr (state, instr);
2993 break;
2994 }
2995 UNDEF_LSRBaseEQOffWb;
2996 UNDEF_LSRBaseEQDestWb;
2997 UNDEF_LSRPCBaseWb;
2998 UNDEF_LSRPCOffWb;
2999 lhs = LHS;
3000 temp = lhs + LSRegRHS;
3001 if (LoadByte (state, instr, lhs, LUNSIGNED))
3002 LSBase = temp;
3003 break;
3004
3005 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3006 if (BIT (4))
3007 {
3008 #ifdef MODE32
3009 if (state->is_v6
3010 && handle_v6_insn (state, instr))
3011 break;
3012 #endif
3013 ARMul_UndefInstr (state, instr);
3014 break;
3015 }
3016 UNDEF_LSRBaseEQOffWb;
3017 UNDEF_LSRBaseEQDestWb;
3018 UNDEF_LSRPCBaseWb;
3019 UNDEF_LSRPCOffWb;
3020 lhs = LHS;
3021 state->NtransSig = LOW;
3022 if (StoreByte (state, instr, lhs))
3023 LSBase = lhs + LSRegRHS;
3024 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3025 break;
3026
3027 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3028 if (BIT (4))
3029 {
3030 #ifdef MODE32
3031 if (state->is_v6
3032 && handle_v6_insn (state, instr))
3033 break;
3034 #endif
3035 ARMul_UndefInstr (state, instr);
3036 break;
3037 }
3038 UNDEF_LSRBaseEQOffWb;
3039 UNDEF_LSRBaseEQDestWb;
3040 UNDEF_LSRPCBaseWb;
3041 UNDEF_LSRPCOffWb;
3042 lhs = LHS;
3043 temp = lhs + LSRegRHS;
3044 state->NtransSig = LOW;
3045 if (LoadByte (state, instr, lhs, LUNSIGNED))
3046 LSBase = temp;
3047 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3048 break;
3049
3050
3051 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3052 if (BIT (4))
3053 {
3054 #ifdef MODE32
3055 if (state->is_v6
3056 && handle_v6_insn (state, instr))
3057 break;
3058 #endif
3059 ARMul_UndefInstr (state, instr);
3060 break;
3061 }
3062 (void) StoreWord (state, instr, LHS - LSRegRHS);
3063 break;
3064
3065 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3066 if (BIT (4))
3067 {
3068 ARMul_UndefInstr (state, instr);
3069 break;
3070 }
3071 (void) LoadWord (state, instr, LHS - LSRegRHS);
3072 break;
3073
3074 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3075 if (BIT (4))
3076 {
3077 ARMul_UndefInstr (state, instr);
3078 break;
3079 }
3080 UNDEF_LSRBaseEQOffWb;
3081 UNDEF_LSRBaseEQDestWb;
3082 UNDEF_LSRPCBaseWb;
3083 UNDEF_LSRPCOffWb;
3084 temp = LHS - LSRegRHS;
3085 if (StoreWord (state, instr, temp))
3086 LSBase = temp;
3087 break;
3088
3089 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3090 if (BIT (4))
3091 {
3092 ARMul_UndefInstr (state, instr);
3093 break;
3094 }
3095 UNDEF_LSRBaseEQOffWb;
3096 UNDEF_LSRBaseEQDestWb;
3097 UNDEF_LSRPCBaseWb;
3098 UNDEF_LSRPCOffWb;
3099 temp = LHS - LSRegRHS;
3100 if (LoadWord (state, instr, temp))
3101 LSBase = temp;
3102 break;
3103
3104 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3105 if (BIT (4))
3106 {
3107 #ifdef MODE32
3108 if (state->is_v6
3109 && handle_v6_insn (state, instr))
3110 break;
3111 #endif
3112 ARMul_UndefInstr (state, instr);
3113 break;
3114 }
3115 (void) StoreByte (state, instr, LHS - LSRegRHS);
3116 break;
3117
3118 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3119 if (BIT (4))
3120 {
3121 #ifdef MODE32
3122 if (state->is_v6
3123 && handle_v6_insn (state, instr))
3124 break;
3125 #endif
3126 ARMul_UndefInstr (state, instr);
3127 break;
3128 }
3129 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
3130 break;
3131
3132 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3133 if (BIT (4))
3134 {
3135 ARMul_UndefInstr (state, instr);
3136 break;
3137 }
3138 UNDEF_LSRBaseEQOffWb;
3139 UNDEF_LSRBaseEQDestWb;
3140 UNDEF_LSRPCBaseWb;
3141 UNDEF_LSRPCOffWb;
3142 temp = LHS - LSRegRHS;
3143 if (StoreByte (state, instr, temp))
3144 LSBase = temp;
3145 break;
3146
3147 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3148 if (BIT (4))
3149 {
3150 ARMul_UndefInstr (state, instr);
3151 break;
3152 }
3153 UNDEF_LSRBaseEQOffWb;
3154 UNDEF_LSRBaseEQDestWb;
3155 UNDEF_LSRPCBaseWb;
3156 UNDEF_LSRPCOffWb;
3157 temp = LHS - LSRegRHS;
3158 if (LoadByte (state, instr, temp, LUNSIGNED))
3159 LSBase = temp;
3160 break;
3161
3162 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3163 if (BIT (4))
3164 {
3165 #ifdef MODE32
3166 if (state->is_v6
3167 && handle_v6_insn (state, instr))
3168 break;
3169 #endif
3170 ARMul_UndefInstr (state, instr);
3171 break;
3172 }
3173 (void) StoreWord (state, instr, LHS + LSRegRHS);
3174 break;
3175
3176 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
3177 if (BIT (4))
3178 {
3179 ARMul_UndefInstr (state, instr);
3180 break;
3181 }
3182 (void) LoadWord (state, instr, LHS + LSRegRHS);
3183 break;
3184
3185 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
3186 if (BIT (4))
3187 {
3188 #ifdef MODE32
3189 if (state->is_v6
3190 && handle_v6_insn (state, instr))
3191 break;
3192 #endif
3193 ARMul_UndefInstr (state, instr);
3194 break;
3195 }
3196 UNDEF_LSRBaseEQOffWb;
3197 UNDEF_LSRBaseEQDestWb;
3198 UNDEF_LSRPCBaseWb;
3199 UNDEF_LSRPCOffWb;
3200 temp = LHS + LSRegRHS;
3201 if (StoreWord (state, instr, temp))
3202 LSBase = temp;
3203 break;
3204
3205 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
3206 if (BIT (4))
3207 {
3208 ARMul_UndefInstr (state, instr);
3209 break;
3210 }
3211 UNDEF_LSRBaseEQOffWb;
3212 UNDEF_LSRBaseEQDestWb;
3213 UNDEF_LSRPCBaseWb;
3214 UNDEF_LSRPCOffWb;
3215 temp = LHS + LSRegRHS;
3216 if (LoadWord (state, instr, temp))
3217 LSBase = temp;
3218 break;
3219
3220 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
3221 if (BIT (4))
3222 {
3223 #ifdef MODE32
3224 if (state->is_v6
3225 && handle_v6_insn (state, instr))
3226 break;
3227 #endif
3228 ARMul_UndefInstr (state, instr);
3229 break;
3230 }
3231 (void) StoreByte (state, instr, LHS + LSRegRHS);
3232 break;
3233
3234 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
3235 if (BIT (4))
3236 {
3237 ARMul_UndefInstr (state, instr);
3238 break;
3239 }
3240 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
3241 break;
3242
3243 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
3244 if (BIT (4))
3245 {
3246 ARMul_UndefInstr (state, instr);
3247 break;
3248 }
3249 UNDEF_LSRBaseEQOffWb;
3250 UNDEF_LSRBaseEQDestWb;
3251 UNDEF_LSRPCBaseWb;
3252 UNDEF_LSRPCOffWb;
3253 temp = LHS + LSRegRHS;
3254 if (StoreByte (state, instr, temp))
3255 LSBase = temp;
3256 break;
3257
3258 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
3259 if (BIT (4))
3260 {
3261 /* Check for the special breakpoint opcode.
3262 This value should correspond to the value defined
3263 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
3264 if (BITS (0, 19) == 0xfdefe)
3265 {
3266 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
3267 ARMul_Abort (state, ARMul_SWIV);
3268 }
3269 else
3270 ARMul_UndefInstr (state, instr);
3271 break;
3272 }
3273 UNDEF_LSRBaseEQOffWb;
3274 UNDEF_LSRBaseEQDestWb;
3275 UNDEF_LSRPCBaseWb;
3276 UNDEF_LSRPCOffWb;
3277 temp = LHS + LSRegRHS;
3278 if (LoadByte (state, instr, temp, LUNSIGNED))
3279 LSBase = temp;
3280 break;
3281
3282
3283 /* Multiple Data Transfer Instructions. */
3284
3285 case 0x80: /* Store, No WriteBack, Post Dec. */
3286 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3287 break;
3288
3289 case 0x81: /* Load, No WriteBack, Post Dec. */
3290 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3291 break;
3292
3293 case 0x82: /* Store, WriteBack, Post Dec. */
3294 temp = LSBase - LSMNumRegs;
3295 STOREMULT (instr, temp + 4L, temp);
3296 break;
3297
3298 case 0x83: /* Load, WriteBack, Post Dec. */
3299 temp = LSBase - LSMNumRegs;
3300 LOADMULT (instr, temp + 4L, temp);
3301 break;
3302
3303 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
3304 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3305 break;
3306
3307 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
3308 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3309 break;
3310
3311 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
3312 temp = LSBase - LSMNumRegs;
3313 STORESMULT (instr, temp + 4L, temp);
3314 break;
3315
3316 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3317 temp = LSBase - LSMNumRegs;
3318 LOADSMULT (instr, temp + 4L, temp);
3319 break;
3320
3321 case 0x88: /* Store, No WriteBack, Post Inc. */
3322 STOREMULT (instr, LSBase, 0L);
3323 break;
3324
3325 case 0x89: /* Load, No WriteBack, Post Inc. */
3326 LOADMULT (instr, LSBase, 0L);
3327 break;
3328
3329 case 0x8a: /* Store, WriteBack, Post Inc. */
3330 temp = LSBase;
3331 STOREMULT (instr, temp, temp + LSMNumRegs);
3332 break;
3333
3334 case 0x8b: /* Load, WriteBack, Post Inc. */
3335 temp = LSBase;
3336 LOADMULT (instr, temp, temp + LSMNumRegs);
3337 break;
3338
3339 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3340 STORESMULT (instr, LSBase, 0L);
3341 break;
3342
3343 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3344 LOADSMULT (instr, LSBase, 0L);
3345 break;
3346
3347 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3348 temp = LSBase;
3349 STORESMULT (instr, temp, temp + LSMNumRegs);
3350 break;
3351
3352 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3353 temp = LSBase;
3354 LOADSMULT (instr, temp, temp + LSMNumRegs);
3355 break;
3356
3357 case 0x90: /* Store, No WriteBack, Pre Dec. */
3358 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
3359 break;
3360
3361 case 0x91: /* Load, No WriteBack, Pre Dec. */
3362 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
3363 break;
3364
3365 case 0x92: /* Store, WriteBack, Pre Dec. */
3366 temp = LSBase - LSMNumRegs;
3367 STOREMULT (instr, temp, temp);
3368 break;
3369
3370 case 0x93: /* Load, WriteBack, Pre Dec. */
3371 temp = LSBase - LSMNumRegs;
3372 LOADMULT (instr, temp, temp);
3373 break;
3374
3375 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3376 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
3377 break;
3378
3379 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3380 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
3381 break;
3382
3383 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3384 temp = LSBase - LSMNumRegs;
3385 STORESMULT (instr, temp, temp);
3386 break;
3387
3388 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3389 temp = LSBase - LSMNumRegs;
3390 LOADSMULT (instr, temp, temp);
3391 break;
3392
3393 case 0x98: /* Store, No WriteBack, Pre Inc. */
3394 STOREMULT (instr, LSBase + 4L, 0L);
3395 break;
3396
3397 case 0x99: /* Load, No WriteBack, Pre Inc. */
3398 LOADMULT (instr, LSBase + 4L, 0L);
3399 break;
3400
3401 case 0x9a: /* Store, WriteBack, Pre Inc. */
3402 temp = LSBase;
3403 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
3404 break;
3405
3406 case 0x9b: /* Load, WriteBack, Pre Inc. */
3407 temp = LSBase;
3408 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
3409 break;
3410
3411 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3412 STORESMULT (instr, LSBase + 4L, 0L);
3413 break;
3414
3415 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3416 LOADSMULT (instr, LSBase + 4L, 0L);
3417 break;
3418
3419 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3420 temp = LSBase;
3421 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
3422 break;
3423
3424 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3425 temp = LSBase;
3426 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
3427 break;
3428
3429
3430 /* Branch forward. */
3431 case 0xa0:
3432 case 0xa1:
3433 case 0xa2:
3434 case 0xa3:
3435 case 0xa4:
3436 case 0xa5:
3437 case 0xa6:
3438 case 0xa7:
3439 state->Reg[15] = pc + 8 + POSBRANCH;
3440 FLUSHPIPE;
3441 break;
3442
3443
3444 /* Branch backward. */
3445 case 0xa8:
3446 case 0xa9:
3447 case 0xaa:
3448 case 0xab:
3449 case 0xac:
3450 case 0xad:
3451 case 0xae:
3452 case 0xaf:
3453 state->Reg[15] = pc + 8 + NEGBRANCH;
3454 FLUSHPIPE;
3455 break;
3456
3457
3458 /* Branch and Link forward. */
3459 case 0xb0:
3460 case 0xb1:
3461 case 0xb2:
3462 case 0xb3:
3463 case 0xb4:
3464 case 0xb5:
3465 case 0xb6:
3466 case 0xb7:
3467 /* Put PC into Link. */
3468 #ifdef MODE32
3469 state->Reg[14] = pc + 4;
3470 #else
3471 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3472 #endif
3473 state->Reg[15] = pc + 8 + POSBRANCH;
3474 FLUSHPIPE;
3475 break;
3476
3477
3478 /* Branch and Link backward. */
3479 case 0xb8:
3480 case 0xb9:
3481 case 0xba:
3482 case 0xbb:
3483 case 0xbc:
3484 case 0xbd:
3485 case 0xbe:
3486 case 0xbf:
3487 /* Put PC into Link. */
3488 #ifdef MODE32
3489 state->Reg[14] = pc + 4;
3490 #else
3491 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3492 #endif
3493 state->Reg[15] = pc + 8 + NEGBRANCH;
3494 FLUSHPIPE;
3495 break;
3496
3497
3498 /* Co-Processor Data Transfers. */
3499 case 0xc4:
3500 if (state->is_v5)
3501 {
3502 /* Reading from R15 is UNPREDICTABLE. */
3503 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3504 ARMul_UndefInstr (state, instr);
3505 /* Is access to coprocessor 0 allowed ? */
3506 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3507 ARMul_UndefInstr (state, instr);
3508 /* Special treatment for XScale coprocessors. */
3509 else if (state->is_XScale)
3510 {
3511 /* Only opcode 0 is supported. */
3512 if (BITS (4, 7) != 0x00)
3513 ARMul_UndefInstr (state, instr);
3514 /* Only coporcessor 0 is supported. */
3515 else if (CPNum != 0x00)
3516 ARMul_UndefInstr (state, instr);
3517 /* Only accumulator 0 is supported. */
3518 else if (BITS (0, 3) != 0x00)
3519 ARMul_UndefInstr (state, instr);
3520 else
3521 {
3522 /* XScale MAR insn. Move two registers into accumulator. */
3523 state->Accumulator = state->Reg[BITS (12, 15)];
3524 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
3525 }
3526 }
3527 else
3528 /* FIXME: Not sure what to do for other v5 processors. */
3529 ARMul_UndefInstr (state, instr);
3530 break;
3531 }
3532 /* Drop through. */
3533
3534 case 0xc0: /* Store , No WriteBack , Post Dec. */
3535 ARMul_STC (state, instr, LHS);
3536 break;
3537
3538 case 0xc5:
3539 if (state->is_v5)
3540 {
3541 /* Writes to R15 are UNPREDICATABLE. */
3542 if (DESTReg == 15 || LHSReg == 15)
3543 ARMul_UndefInstr (state, instr);
3544 /* Is access to the coprocessor allowed ? */
3545 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3546 ARMul_UndefInstr (state, instr);
3547 /* Special handling for XScale coprcoessors. */
3548 else if (state->is_XScale)
3549 {
3550 /* Only opcode 0 is supported. */
3551 if (BITS (4, 7) != 0x00)
3552 ARMul_UndefInstr (state, instr);
3553 /* Only coprocessor 0 is supported. */
3554 else if (CPNum != 0x00)
3555 ARMul_UndefInstr (state, instr);
3556 /* Only accumulator 0 is supported. */
3557 else if (BITS (0, 3) != 0x00)
3558 ARMul_UndefInstr (state, instr);
3559 else
3560 {
3561 /* XScale MRA insn. Move accumulator into two registers. */
3562 ARMword t1 = (state->Accumulator >> 32) & 255;
3563
3564 if (t1 & 128)
3565 t1 -= 256;
3566
3567 state->Reg[BITS (12, 15)] = state->Accumulator;
3568 state->Reg[BITS (16, 19)] = t1;
3569 break;
3570 }
3571 }
3572 else
3573 /* FIXME: Not sure what to do for other v5 processors. */
3574 ARMul_UndefInstr (state, instr);
3575 break;
3576 }
3577 /* Drop through. */
3578
3579 case 0xc1: /* Load , No WriteBack , Post Dec. */
3580 ARMul_LDC (state, instr, LHS);
3581 break;
3582
3583 case 0xc2:
3584 case 0xc6: /* Store , WriteBack , Post Dec. */
3585 lhs = LHS;
3586 state->Base = lhs - LSCOff;
3587 ARMul_STC (state, instr, lhs);
3588 break;
3589
3590 case 0xc3:
3591 case 0xc7: /* Load , WriteBack , Post Dec. */
3592 lhs = LHS;
3593 state->Base = lhs - LSCOff;
3594 ARMul_LDC (state, instr, lhs);
3595 break;
3596
3597 case 0xc8:
3598 case 0xcc: /* Store , No WriteBack , Post Inc. */
3599 ARMul_STC (state, instr, LHS);
3600 break;
3601
3602 case 0xc9:
3603 case 0xcd: /* Load , No WriteBack , Post Inc. */
3604 ARMul_LDC (state, instr, LHS);
3605 break;
3606
3607 case 0xca:
3608 case 0xce: /* Store , WriteBack , Post Inc. */
3609 lhs = LHS;
3610 state->Base = lhs + LSCOff;
3611 ARMul_STC (state, instr, LHS);
3612 break;
3613
3614 case 0xcb:
3615 case 0xcf: /* Load , WriteBack , Post Inc. */
3616 lhs = LHS;
3617 state->Base = lhs + LSCOff;
3618 ARMul_LDC (state, instr, LHS);
3619 break;
3620
3621 case 0xd0:
3622 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3623 ARMul_STC (state, instr, LHS - LSCOff);
3624 break;
3625
3626 case 0xd1:
3627 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3628 ARMul_LDC (state, instr, LHS - LSCOff);
3629 break;
3630
3631 case 0xd2:
3632 case 0xd6: /* Store , WriteBack , Pre Dec. */
3633 lhs = LHS - LSCOff;
3634 state->Base = lhs;
3635 ARMul_STC (state, instr, lhs);
3636 break;
3637
3638 case 0xd3:
3639 case 0xd7: /* Load , WriteBack , Pre Dec. */
3640 lhs = LHS - LSCOff;
3641 state->Base = lhs;
3642 ARMul_LDC (state, instr, lhs);
3643 break;
3644
3645 case 0xd8:
3646 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3647 ARMul_STC (state, instr, LHS + LSCOff);
3648 break;
3649
3650 case 0xd9:
3651 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3652 ARMul_LDC (state, instr, LHS + LSCOff);
3653 break;
3654
3655 case 0xda:
3656 case 0xde: /* Store , WriteBack , Pre Inc. */
3657 lhs = LHS + LSCOff;
3658 state->Base = lhs;
3659 ARMul_STC (state, instr, lhs);
3660 break;
3661
3662 case 0xdb:
3663 case 0xdf: /* Load , WriteBack , Pre Inc. */
3664 lhs = LHS + LSCOff;
3665 state->Base = lhs;
3666 ARMul_LDC (state, instr, lhs);
3667 break;
3668
3669
3670 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3671
3672 case 0xe2:
3673 if (! CP_ACCESS_ALLOWED (state, CPNum))
3674 {
3675 ARMul_UndefInstr (state, instr);
3676 break;
3677 }
3678 if (state->is_XScale)
3679 switch (BITS (18, 19))
3680 {
3681 case 0x0:
3682 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3683 {
3684 /* XScale MIA instruction. Signed multiplication of
3685 two 32 bit values and addition to 40 bit accumulator. */
3686 ARMsdword Rm = state->Reg[MULLHSReg];
3687 ARMsdword Rs = state->Reg[MULACCReg];
3688
3689 if (Rm & (1 << 31))
3690 Rm -= 1ULL << 32;
3691 if (Rs & (1 << 31))
3692 Rs -= 1ULL << 32;
3693 state->Accumulator += Rm * Rs;
3694 goto donext;
3695 }
3696 break;
3697
3698 case 0x2:
3699 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3700 {
3701 /* XScale MIAPH instruction. */
3702 ARMword t1 = state->Reg[MULLHSReg] >> 16;
3703 ARMword t2 = state->Reg[MULACCReg] >> 16;
3704 ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
3705 ARMword t4 = state->Reg[MULACCReg] & 0xffff;
3706 ARMsdword t5;
3707
3708 if (t1 & (1 << 15))
3709 t1 -= 1 << 16;
3710 if (t2 & (1 << 15))
3711 t2 -= 1 << 16;
3712 if (t3 & (1 << 15))
3713 t3 -= 1 << 16;
3714 if (t4 & (1 << 15))
3715 t4 -= 1 << 16;
3716 t1 *= t2;
3717 t5 = t1;
3718 if (t5 & (1 << 31))
3719 t5 -= 1ULL << 32;
3720 state->Accumulator += t5;
3721 t3 *= t4;
3722 t5 = t3;
3723 if (t5 & (1 << 31))
3724 t5 -= 1ULL << 32;
3725 state->Accumulator += t5;
3726 goto donext;
3727 }
3728 break;
3729
3730 case 0x3:
3731 if (BITS (4, 11) == 1)
3732 {
3733 /* XScale MIAxy instruction. */
3734 ARMword t1;
3735 ARMword t2;
3736 ARMsdword t5;
3737
3738 if (BIT (17))
3739 t1 = state->Reg[MULLHSReg] >> 16;
3740 else
3741 t1 = state->Reg[MULLHSReg] & 0xffff;
3742
3743 if (BIT (16))
3744 t2 = state->Reg[MULACCReg] >> 16;
3745 else
3746 t2 = state->Reg[MULACCReg] & 0xffff;
3747
3748 if (t1 & (1 << 15))
3749 t1 -= 1 << 16;
3750 if (t2 & (1 << 15))
3751 t2 -= 1 << 16;
3752 t1 *= t2;
3753 t5 = t1;
3754 if (t5 & (1 << 31))
3755 t5 -= 1ULL << 32;
3756 state->Accumulator += t5;
3757 goto donext;
3758 }
3759 break;
3760
3761 default:
3762 break;
3763 }
3764 /* Drop through. */
3765
3766 case 0xe0:
3767 case 0xe4:
3768 case 0xe6:
3769 case 0xe8:
3770 case 0xea:
3771 case 0xec:
3772 case 0xee:
3773 if (BIT (4))
3774 {
3775 /* MCR. */
3776 if (DESTReg == 15)
3777 {
3778 UNDEF_MCRPC;
3779 #ifdef MODE32
3780 ARMul_MCR (state, instr, state->Reg[15] + isize);
3781 #else
3782 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
3783 ((state->Reg[15] + isize) & R15PCBITS));
3784 #endif
3785 }
3786 else
3787 ARMul_MCR (state, instr, DEST);
3788 }
3789 else
3790 /* CDP Part 1. */
3791 ARMul_CDP (state, instr);
3792 break;
3793
3794
3795 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3796 case 0xe1:
3797 case 0xe3:
3798 case 0xe5:
3799 case 0xe7:
3800 case 0xe9:
3801 case 0xeb:
3802 case 0xed:
3803 case 0xef:
3804 if (BIT (4))
3805 {
3806 /* MRC */
3807 temp = ARMul_MRC (state, instr);
3808 if (DESTReg == 15)
3809 {
3810 ASSIGNN ((temp & NBIT) != 0);
3811 ASSIGNZ ((temp & ZBIT) != 0);
3812 ASSIGNC ((temp & CBIT) != 0);
3813 ASSIGNV ((temp & VBIT) != 0);
3814 }
3815 else
3816 DEST = temp;
3817 }
3818 else
3819 /* CDP Part 2. */
3820 ARMul_CDP (state, instr);
3821 break;
3822
3823
3824 /* SWI instruction. */
3825 case 0xf0:
3826 case 0xf1:
3827 case 0xf2:
3828 case 0xf3:
3829 case 0xf4:
3830 case 0xf5:
3831 case 0xf6:
3832 case 0xf7:
3833 case 0xf8:
3834 case 0xf9:
3835 case 0xfa:
3836 case 0xfb:
3837 case 0xfc:
3838 case 0xfd:
3839 case 0xfe:
3840 case 0xff:
3841 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
3842 {
3843 /* A prefetch abort. */
3844 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
3845 ARMul_Abort (state, ARMul_PrefetchAbortV);
3846 break;
3847 }
3848
3849 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
3850 ARMul_Abort (state, ARMul_SWIV);
3851
3852 break;
3853 }
3854 }
3855
3856 #ifdef MODET
3857 donext:
3858 #endif
3859
3860 #ifdef NEED_UI_LOOP_HOOK
3861 if (deprecated_ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
3862 {
3863 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
3864 deprecated_ui_loop_hook (0);
3865 }
3866 #endif /* NEED_UI_LOOP_HOOK */
3867
3868 if (state->Emulate == ONCE)
3869 state->Emulate = STOP;
3870 /* If we have changed mode, allow the PC to advance before stopping. */
3871 else if (state->Emulate == CHANGEMODE)
3872 continue;
3873 else if (state->Emulate != RUN)
3874 break;
3875 }
3876 while (!stop_simulator);
3877
3878 state->decoded = decoded;
3879 state->loaded = loaded;
3880 state->pc = pc;
3881
3882 return pc;
3883 }
3884
3885 /* This routine evaluates most Data Processing register RHS's with the S
3886 bit clear. It is intended to be called from the macro DPRegRHS, which
3887 filters the common case of an unshifted register with in line code. */
3888
3889 static ARMword
GetDPRegRHS(ARMul_State * state,ARMword instr)3890 GetDPRegRHS (ARMul_State * state, ARMword instr)
3891 {
3892 ARMword shamt, base;
3893
3894 base = RHSReg;
3895 if (BIT (4))
3896 {
3897 /* Shift amount in a register. */
3898 UNDEF_Shift;
3899 INCPC;
3900 #ifndef MODE32
3901 if (base == 15)
3902 base = ECC | ER15INT | R15PC | EMODE;
3903 else
3904 #endif
3905 base = state->Reg[base];
3906 ARMul_Icycles (state, 1, 0L);
3907 shamt = state->Reg[BITS (8, 11)] & 0xff;
3908 switch ((int) BITS (5, 6))
3909 {
3910 case LSL:
3911 if (shamt == 0)
3912 return (base);
3913 else if (shamt >= 32)
3914 return (0);
3915 else
3916 return (base << shamt);
3917 case LSR:
3918 if (shamt == 0)
3919 return (base);
3920 else if (shamt >= 32)
3921 return (0);
3922 else
3923 return (base >> shamt);
3924 case ASR:
3925 if (shamt == 0)
3926 return (base);
3927 else if (shamt >= 32)
3928 return ((ARMword) ((ARMsword) base >> 31L));
3929 else
3930 return ((ARMword) ((ARMsword) base >> (int) shamt));
3931 case ROR:
3932 shamt &= 0x1f;
3933 if (shamt == 0)
3934 return (base);
3935 else
3936 return ((base << (32 - shamt)) | (base >> shamt));
3937 }
3938 }
3939 else
3940 {
3941 /* Shift amount is a constant. */
3942 #ifndef MODE32
3943 if (base == 15)
3944 base = ECC | ER15INT | R15PC | EMODE;
3945 else
3946 #endif
3947 base = state->Reg[base];
3948 shamt = BITS (7, 11);
3949 switch ((int) BITS (5, 6))
3950 {
3951 case LSL:
3952 return (base << shamt);
3953 case LSR:
3954 if (shamt == 0)
3955 return (0);
3956 else
3957 return (base >> shamt);
3958 case ASR:
3959 if (shamt == 0)
3960 return ((ARMword) ((ARMsword) base >> 31L));
3961 else
3962 return ((ARMword) ((ARMsword) base >> (int) shamt));
3963 case ROR:
3964 if (shamt == 0)
3965 /* It's an RRX. */
3966 return ((base >> 1) | (CFLAG << 31));
3967 else
3968 return ((base << (32 - shamt)) | (base >> shamt));
3969 }
3970 }
3971
3972 return 0;
3973 }
3974
3975 /* This routine evaluates most Logical Data Processing register RHS's
3976 with the S bit set. It is intended to be called from the macro
3977 DPSRegRHS, which filters the common case of an unshifted register
3978 with in line code. */
3979
3980 static ARMword
GetDPSRegRHS(ARMul_State * state,ARMword instr)3981 GetDPSRegRHS (ARMul_State * state, ARMword instr)
3982 {
3983 ARMword shamt, base;
3984
3985 base = RHSReg;
3986 if (BIT (4))
3987 {
3988 /* Shift amount in a register. */
3989 UNDEF_Shift;
3990 INCPC;
3991 #ifndef MODE32
3992 if (base == 15)
3993 base = ECC | ER15INT | R15PC | EMODE;
3994 else
3995 #endif
3996 base = state->Reg[base];
3997 ARMul_Icycles (state, 1, 0L);
3998 shamt = state->Reg[BITS (8, 11)] & 0xff;
3999 switch ((int) BITS (5, 6))
4000 {
4001 case LSL:
4002 if (shamt == 0)
4003 return (base);
4004 else if (shamt == 32)
4005 {
4006 ASSIGNC (base & 1);
4007 return (0);
4008 }
4009 else if (shamt > 32)
4010 {
4011 CLEARC;
4012 return (0);
4013 }
4014 else
4015 {
4016 ASSIGNC ((base >> (32 - shamt)) & 1);
4017 return (base << shamt);
4018 }
4019 case LSR:
4020 if (shamt == 0)
4021 return (base);
4022 else if (shamt == 32)
4023 {
4024 ASSIGNC (base >> 31);
4025 return (0);
4026 }
4027 else if (shamt > 32)
4028 {
4029 CLEARC;
4030 return (0);
4031 }
4032 else
4033 {
4034 ASSIGNC ((base >> (shamt - 1)) & 1);
4035 return (base >> shamt);
4036 }
4037 case ASR:
4038 if (shamt == 0)
4039 return (base);
4040 else if (shamt >= 32)
4041 {
4042 ASSIGNC (base >> 31L);
4043 return ((ARMword) ((ARMsword) base >> 31L));
4044 }
4045 else
4046 {
4047 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
4048 return ((ARMword) ((ARMsword) base >> (int) shamt));
4049 }
4050 case ROR:
4051 if (shamt == 0)
4052 return (base);
4053 shamt &= 0x1f;
4054 if (shamt == 0)
4055 {
4056 ASSIGNC (base >> 31);
4057 return (base);
4058 }
4059 else
4060 {
4061 ASSIGNC ((base >> (shamt - 1)) & 1);
4062 return ((base << (32 - shamt)) | (base >> shamt));
4063 }
4064 }
4065 }
4066 else
4067 {
4068 /* Shift amount is a constant. */
4069 #ifndef MODE32
4070 if (base == 15)
4071 base = ECC | ER15INT | R15PC | EMODE;
4072 else
4073 #endif
4074 base = state->Reg[base];
4075 shamt = BITS (7, 11);
4076
4077 switch ((int) BITS (5, 6))
4078 {
4079 case LSL:
4080 ASSIGNC ((base >> (32 - shamt)) & 1);
4081 return (base << shamt);
4082 case LSR:
4083 if (shamt == 0)
4084 {
4085 ASSIGNC (base >> 31);
4086 return (0);
4087 }
4088 else
4089 {
4090 ASSIGNC ((base >> (shamt - 1)) & 1);
4091 return (base >> shamt);
4092 }
4093 case ASR:
4094 if (shamt == 0)
4095 {
4096 ASSIGNC (base >> 31L);
4097 return ((ARMword) ((ARMsword) base >> 31L));
4098 }
4099 else
4100 {
4101 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
4102 return ((ARMword) ((ARMsword) base >> (int) shamt));
4103 }
4104 case ROR:
4105 if (shamt == 0)
4106 {
4107 /* It's an RRX. */
4108 shamt = CFLAG;
4109 ASSIGNC (base & 1);
4110 return ((base >> 1) | (shamt << 31));
4111 }
4112 else
4113 {
4114 ASSIGNC ((base >> (shamt - 1)) & 1);
4115 return ((base << (32 - shamt)) | (base >> shamt));
4116 }
4117 }
4118 }
4119
4120 return 0;
4121 }
4122
4123 /* This routine handles writes to register 15 when the S bit is not set. */
4124
4125 static void
WriteR15(ARMul_State * state,ARMword src)4126 WriteR15 (ARMul_State * state, ARMword src)
4127 {
4128 /* The ARM documentation states that the two least significant bits
4129 are discarded when setting PC, except in the cases handled by
4130 WriteR15Branch() below. It's probably an oversight: in THUMB
4131 mode, the second least significant bit should probably not be
4132 discarded. */
4133 #ifdef MODET
4134 if (TFLAG)
4135 src &= 0xfffffffe;
4136 else
4137 #endif
4138 src &= 0xfffffffc;
4139
4140 #ifdef MODE32
4141 state->Reg[15] = src & PCBITS;
4142 #else
4143 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
4144 ARMul_R15Altered (state);
4145 #endif
4146
4147 FLUSHPIPE;
4148 }
4149
4150 /* This routine handles writes to register 15 when the S bit is set. */
4151
4152 static void
WriteSR15(ARMul_State * state,ARMword src)4153 WriteSR15 (ARMul_State * state, ARMword src)
4154 {
4155 #ifdef MODE32
4156 if (state->Bank > 0)
4157 {
4158 state->Cpsr = state->Spsr[state->Bank];
4159 ARMul_CPSRAltered (state);
4160 }
4161 #ifdef MODET
4162 if (TFLAG)
4163 src &= 0xfffffffe;
4164 else
4165 #endif
4166 src &= 0xfffffffc;
4167 state->Reg[15] = src & PCBITS;
4168 #else
4169 #ifdef MODET
4170 if (TFLAG)
4171 /* ARMul_R15Altered would have to support it. */
4172 abort ();
4173 else
4174 #endif
4175 src &= 0xfffffffc;
4176
4177 if (state->Bank == USERBANK)
4178 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
4179 else
4180 state->Reg[15] = src;
4181
4182 ARMul_R15Altered (state);
4183 #endif
4184 FLUSHPIPE;
4185 }
4186
4187 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
4188 will switch to Thumb mode if the least significant bit is set. */
4189
4190 static void
WriteR15Branch(ARMul_State * state,ARMword src)4191 WriteR15Branch (ARMul_State * state, ARMword src)
4192 {
4193 #ifdef MODET
4194 if (src & 1)
4195 {
4196 /* Thumb bit. */
4197 SETT;
4198 state->Reg[15] = src & 0xfffffffe;
4199 }
4200 else
4201 {
4202 CLEART;
4203 state->Reg[15] = src & 0xfffffffc;
4204 }
4205 FLUSHPIPE;
4206 #else
4207 WriteR15 (state, src);
4208 #endif
4209 }
4210
4211 /* This routine evaluates most Load and Store register RHS's. It is
4212 intended to be called from the macro LSRegRHS, which filters the
4213 common case of an unshifted register with in line code. */
4214
4215 static ARMword
GetLSRegRHS(ARMul_State * state,ARMword instr)4216 GetLSRegRHS (ARMul_State * state, ARMword instr)
4217 {
4218 ARMword shamt, base;
4219
4220 base = RHSReg;
4221 #ifndef MODE32
4222 if (base == 15)
4223 /* Now forbidden, but ... */
4224 base = ECC | ER15INT | R15PC | EMODE;
4225 else
4226 #endif
4227 base = state->Reg[base];
4228
4229 shamt = BITS (7, 11);
4230 switch ((int) BITS (5, 6))
4231 {
4232 case LSL:
4233 return (base << shamt);
4234 case LSR:
4235 if (shamt == 0)
4236 return (0);
4237 else
4238 return (base >> shamt);
4239 case ASR:
4240 if (shamt == 0)
4241 return ((ARMword) ((ARMsword) base >> 31L));
4242 else
4243 return ((ARMword) ((ARMsword) base >> (int) shamt));
4244 case ROR:
4245 if (shamt == 0)
4246 /* It's an RRX. */
4247 return ((base >> 1) | (CFLAG << 31));
4248 else
4249 return ((base << (32 - shamt)) | (base >> shamt));
4250 default:
4251 break;
4252 }
4253 return 0;
4254 }
4255
4256 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
4257
4258 static ARMword
GetLS7RHS(ARMul_State * state,ARMword instr)4259 GetLS7RHS (ARMul_State * state, ARMword instr)
4260 {
4261 if (BIT (22) == 0)
4262 {
4263 /* Register. */
4264 #ifndef MODE32
4265 if (RHSReg == 15)
4266 /* Now forbidden, but ... */
4267 return ECC | ER15INT | R15PC | EMODE;
4268 #endif
4269 return state->Reg[RHSReg];
4270 }
4271
4272 /* Immediate. */
4273 return BITS (0, 3) | (BITS (8, 11) << 4);
4274 }
4275
4276 /* This function does the work of loading a word for a LDR instruction. */
4277
4278 static unsigned
LoadWord(ARMul_State * state,ARMword instr,ARMword address)4279 LoadWord (ARMul_State * state, ARMword instr, ARMword address)
4280 {
4281 ARMword dest;
4282
4283 BUSUSEDINCPCS;
4284 #ifndef MODE32
4285 if (ADDREXCEPT (address))
4286 INTERNALABORT (address);
4287 #endif
4288
4289 dest = ARMul_LoadWordN (state, address);
4290
4291 if (state->Aborted)
4292 {
4293 TAKEABORT;
4294 return state->lateabtSig;
4295 }
4296 if (address & 3)
4297 dest = ARMul_Align (state, address, dest);
4298 WRITEDESTB (dest);
4299 ARMul_Icycles (state, 1, 0L);
4300
4301 return (DESTReg != LHSReg);
4302 }
4303
4304 #ifdef MODET
4305 /* This function does the work of loading a halfword. */
4306
4307 static unsigned
LoadHalfWord(ARMul_State * state,ARMword instr,ARMword address,int signextend)4308 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
4309 int signextend)
4310 {
4311 ARMword dest;
4312
4313 BUSUSEDINCPCS;
4314 #ifndef MODE32
4315 if (ADDREXCEPT (address))
4316 INTERNALABORT (address);
4317 #endif
4318 dest = ARMul_LoadHalfWord (state, address);
4319 if (state->Aborted)
4320 {
4321 TAKEABORT;
4322 return state->lateabtSig;
4323 }
4324 UNDEF_LSRBPC;
4325 if (signextend)
4326 if (dest & 1 << (16 - 1))
4327 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
4328
4329 WRITEDEST (dest);
4330 ARMul_Icycles (state, 1, 0L);
4331 return (DESTReg != LHSReg);
4332 }
4333
4334 #endif /* MODET */
4335
4336 /* This function does the work of loading a byte for a LDRB instruction. */
4337
4338 static unsigned
LoadByte(ARMul_State * state,ARMword instr,ARMword address,int signextend)4339 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
4340 {
4341 ARMword dest;
4342
4343 BUSUSEDINCPCS;
4344 #ifndef MODE32
4345 if (ADDREXCEPT (address))
4346 INTERNALABORT (address);
4347 #endif
4348 dest = ARMul_LoadByte (state, address);
4349 if (state->Aborted)
4350 {
4351 TAKEABORT;
4352 return state->lateabtSig;
4353 }
4354 UNDEF_LSRBPC;
4355 if (signextend)
4356 if (dest & 1 << (8 - 1))
4357 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
4358
4359 WRITEDEST (dest);
4360 ARMul_Icycles (state, 1, 0L);
4361
4362 return (DESTReg != LHSReg);
4363 }
4364
4365 /* This function does the work of loading two words for a LDRD instruction. */
4366
4367 static void
Handle_Load_Double(ARMul_State * state,ARMword instr)4368 Handle_Load_Double (ARMul_State * state, ARMword instr)
4369 {
4370 ARMword dest_reg;
4371 ARMword addr_reg;
4372 ARMword write_back = BIT (21);
4373 ARMword immediate = BIT (22);
4374 ARMword add_to_base = BIT (23);
4375 ARMword pre_indexed = BIT (24);
4376 ARMword offset;
4377 ARMword addr;
4378 ARMword sum;
4379 ARMword base;
4380 ARMword value1;
4381 ARMword value2;
4382
4383 BUSUSEDINCPCS;
4384
4385 /* If the writeback bit is set, the pre-index bit must be clear. */
4386 if (write_back && ! pre_indexed)
4387 {
4388 ARMul_UndefInstr (state, instr);
4389 return;
4390 }
4391
4392 /* Extract the base address register. */
4393 addr_reg = LHSReg;
4394
4395 /* Extract the destination register and check it. */
4396 dest_reg = DESTReg;
4397
4398 /* Destination register must be even. */
4399 if ((dest_reg & 1)
4400 /* Destination register cannot be LR. */
4401 || (dest_reg == 14))
4402 {
4403 ARMul_UndefInstr (state, instr);
4404 return;
4405 }
4406
4407 /* Compute the base address. */
4408 base = state->Reg[addr_reg];
4409
4410 /* Compute the offset. */
4411 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4412
4413 /* Compute the sum of the two. */
4414 if (add_to_base)
4415 sum = base + offset;
4416 else
4417 sum = base - offset;
4418
4419 /* If this is a pre-indexed mode use the sum. */
4420 if (pre_indexed)
4421 addr = sum;
4422 else
4423 addr = base;
4424
4425 /* The address must be aligned on a 8 byte boundary. */
4426 if (addr & 0x7)
4427 {
4428 #ifdef ABORTS
4429 ARMul_DATAABORT (addr);
4430 #else
4431 ARMul_UndefInstr (state, instr);
4432 #endif
4433 return;
4434 }
4435
4436 /* For pre indexed or post indexed addressing modes,
4437 check that the destination registers do not overlap
4438 the address registers. */
4439 if ((! pre_indexed || write_back)
4440 && ( addr_reg == dest_reg
4441 || addr_reg == dest_reg + 1))
4442 {
4443 ARMul_UndefInstr (state, instr);
4444 return;
4445 }
4446
4447 /* Load the words. */
4448 value1 = ARMul_LoadWordN (state, addr);
4449 value2 = ARMul_LoadWordN (state, addr + 4);
4450
4451 /* Check for data aborts. */
4452 if (state->Aborted)
4453 {
4454 TAKEABORT;
4455 return;
4456 }
4457
4458 ARMul_Icycles (state, 2, 0L);
4459
4460 /* Store the values. */
4461 state->Reg[dest_reg] = value1;
4462 state->Reg[dest_reg + 1] = value2;
4463
4464 /* Do the post addressing and writeback. */
4465 if (! pre_indexed)
4466 addr = sum;
4467
4468 if (! pre_indexed || write_back)
4469 state->Reg[addr_reg] = addr;
4470 }
4471
4472 /* This function does the work of storing two words for a STRD instruction. */
4473
4474 static void
Handle_Store_Double(ARMul_State * state,ARMword instr)4475 Handle_Store_Double (ARMul_State * state, ARMword instr)
4476 {
4477 ARMword src_reg;
4478 ARMword addr_reg;
4479 ARMword write_back = BIT (21);
4480 ARMword immediate = BIT (22);
4481 ARMword add_to_base = BIT (23);
4482 ARMword pre_indexed = BIT (24);
4483 ARMword offset;
4484 ARMword addr;
4485 ARMword sum;
4486 ARMword base;
4487
4488 BUSUSEDINCPCS;
4489
4490 /* If the writeback bit is set, the pre-index bit must be clear. */
4491 if (write_back && ! pre_indexed)
4492 {
4493 ARMul_UndefInstr (state, instr);
4494 return;
4495 }
4496
4497 /* Extract the base address register. */
4498 addr_reg = LHSReg;
4499
4500 /* Base register cannot be PC. */
4501 if (addr_reg == 15)
4502 {
4503 ARMul_UndefInstr (state, instr);
4504 return;
4505 }
4506
4507 /* Extract the source register. */
4508 src_reg = DESTReg;
4509
4510 /* Source register must be even. */
4511 if (src_reg & 1)
4512 {
4513 ARMul_UndefInstr (state, instr);
4514 return;
4515 }
4516
4517 /* Compute the base address. */
4518 base = state->Reg[addr_reg];
4519
4520 /* Compute the offset. */
4521 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4522
4523 /* Compute the sum of the two. */
4524 if (add_to_base)
4525 sum = base + offset;
4526 else
4527 sum = base - offset;
4528
4529 /* If this is a pre-indexed mode use the sum. */
4530 if (pre_indexed)
4531 addr = sum;
4532 else
4533 addr = base;
4534
4535 /* The address must be aligned on a 8 byte boundary. */
4536 if (addr & 0x7)
4537 {
4538 #ifdef ABORTS
4539 ARMul_DATAABORT (addr);
4540 #else
4541 ARMul_UndefInstr (state, instr);
4542 #endif
4543 return;
4544 }
4545
4546 /* For pre indexed or post indexed addressing modes,
4547 check that the destination registers do not overlap
4548 the address registers. */
4549 if ((! pre_indexed || write_back)
4550 && ( addr_reg == src_reg
4551 || addr_reg == src_reg + 1))
4552 {
4553 ARMul_UndefInstr (state, instr);
4554 return;
4555 }
4556
4557 /* Load the words. */
4558 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
4559 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
4560
4561 if (state->Aborted)
4562 {
4563 TAKEABORT;
4564 return;
4565 }
4566
4567 /* Do the post addressing and writeback. */
4568 if (! pre_indexed)
4569 addr = sum;
4570
4571 if (! pre_indexed || write_back)
4572 state->Reg[addr_reg] = addr;
4573 }
4574
4575 /* This function does the work of storing a word from a STR instruction. */
4576
4577 static unsigned
StoreWord(ARMul_State * state,ARMword instr,ARMword address)4578 StoreWord (ARMul_State * state, ARMword instr, ARMword address)
4579 {
4580 BUSUSEDINCPCN;
4581 #ifndef MODE32
4582 if (DESTReg == 15)
4583 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4584 #endif
4585 #ifdef MODE32
4586 ARMul_StoreWordN (state, address, DEST);
4587 #else
4588 if (VECTORACCESS (address) || ADDREXCEPT (address))
4589 {
4590 INTERNALABORT (address);
4591 (void) ARMul_LoadWordN (state, address);
4592 }
4593 else
4594 ARMul_StoreWordN (state, address, DEST);
4595 #endif
4596 if (state->Aborted)
4597 {
4598 TAKEABORT;
4599 return state->lateabtSig;
4600 }
4601 return TRUE;
4602 }
4603
4604 #ifdef MODET
4605 /* This function does the work of storing a byte for a STRH instruction. */
4606
4607 static unsigned
StoreHalfWord(ARMul_State * state,ARMword instr,ARMword address)4608 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
4609 {
4610 BUSUSEDINCPCN;
4611
4612 #ifndef MODE32
4613 if (DESTReg == 15)
4614 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4615 #endif
4616
4617 #ifdef MODE32
4618 ARMul_StoreHalfWord (state, address, DEST);
4619 #else
4620 if (VECTORACCESS (address) || ADDREXCEPT (address))
4621 {
4622 INTERNALABORT (address);
4623 (void) ARMul_LoadHalfWord (state, address);
4624 }
4625 else
4626 ARMul_StoreHalfWord (state, address, DEST);
4627 #endif
4628
4629 if (state->Aborted)
4630 {
4631 TAKEABORT;
4632 return state->lateabtSig;
4633 }
4634 return TRUE;
4635 }
4636
4637 #endif /* MODET */
4638
4639 /* This function does the work of storing a byte for a STRB instruction. */
4640
4641 static unsigned
StoreByte(ARMul_State * state,ARMword instr,ARMword address)4642 StoreByte (ARMul_State * state, ARMword instr, ARMword address)
4643 {
4644 BUSUSEDINCPCN;
4645 #ifndef MODE32
4646 if (DESTReg == 15)
4647 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4648 #endif
4649 #ifdef MODE32
4650 ARMul_StoreByte (state, address, DEST);
4651 #else
4652 if (VECTORACCESS (address) || ADDREXCEPT (address))
4653 {
4654 INTERNALABORT (address);
4655 (void) ARMul_LoadByte (state, address);
4656 }
4657 else
4658 ARMul_StoreByte (state, address, DEST);
4659 #endif
4660 if (state->Aborted)
4661 {
4662 TAKEABORT;
4663 return state->lateabtSig;
4664 }
4665 UNDEF_LSRBPC;
4666 return TRUE;
4667 }
4668
4669 /* This function does the work of loading the registers listed in an LDM
4670 instruction, when the S bit is clear. The code here is always increment
4671 after, it's up to the caller to get the input address correct and to
4672 handle base register modification. */
4673
4674 static void
LoadMult(ARMul_State * state,ARMword instr,ARMword address,ARMword WBBase)4675 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
4676 {
4677 ARMword dest, temp;
4678
4679 UNDEF_LSMNoRegs;
4680 UNDEF_LSMPCBase;
4681 UNDEF_LSMBaseInListWb;
4682 BUSUSEDINCPCS;
4683 #ifndef MODE32
4684 if (ADDREXCEPT (address))
4685 INTERNALABORT (address);
4686 #endif
4687 if (BIT (21) && LHSReg != 15)
4688 LSBase = WBBase;
4689
4690 /* N cycle first. */
4691 for (temp = 0; !BIT (temp); temp++)
4692 ;
4693
4694 dest = ARMul_LoadWordN (state, address);
4695
4696 if (!state->abortSig && !state->Aborted)
4697 state->Reg[temp++] = dest;
4698 else if (!state->Aborted)
4699 {
4700 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4701 state->Aborted = ARMul_DataAbortV;
4702 }
4703
4704 /* S cycles from here on. */
4705 for (; temp < 16; temp ++)
4706 if (BIT (temp))
4707 {
4708 /* Load this register. */
4709 address += 4;
4710 dest = ARMul_LoadWordS (state, address);
4711
4712 if (!state->abortSig && !state->Aborted)
4713 state->Reg[temp] = dest;
4714 else if (!state->Aborted)
4715 {
4716 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4717 state->Aborted = ARMul_DataAbortV;
4718 }
4719 }
4720
4721 if (BIT (15) && !state->Aborted)
4722 /* PC is in the reg list. */
4723 WriteR15Branch (state, PC);
4724
4725 /* To write back the final register. */
4726 ARMul_Icycles (state, 1, 0L);
4727
4728 if (state->Aborted)
4729 {
4730 if (BIT (21) && LHSReg != 15)
4731 LSBase = WBBase;
4732 TAKEABORT;
4733 }
4734 }
4735
4736 /* This function does the work of loading the registers listed in an LDM
4737 instruction, when the S bit is set. The code here is always increment
4738 after, it's up to the caller to get the input address correct and to
4739 handle base register modification. */
4740
4741 static void
LoadSMult(ARMul_State * state,ARMword instr,ARMword address,ARMword WBBase)4742 LoadSMult (ARMul_State * state,
4743 ARMword instr,
4744 ARMword address,
4745 ARMword WBBase)
4746 {
4747 ARMword dest, temp;
4748
4749 UNDEF_LSMNoRegs;
4750 UNDEF_LSMPCBase;
4751 UNDEF_LSMBaseInListWb;
4752
4753 BUSUSEDINCPCS;
4754
4755 #ifndef MODE32
4756 if (ADDREXCEPT (address))
4757 INTERNALABORT (address);
4758 #endif
4759
4760 if (BIT (21) && LHSReg != 15)
4761 LSBase = WBBase;
4762
4763 if (!BIT (15) && state->Bank != USERBANK)
4764 {
4765 /* Temporary reg bank switch. */
4766 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4767 UNDEF_LSMUserBankWb;
4768 }
4769
4770 /* N cycle first. */
4771 for (temp = 0; !BIT (temp); temp ++)
4772 ;
4773
4774 dest = ARMul_LoadWordN (state, address);
4775
4776 if (!state->abortSig)
4777 state->Reg[temp++] = dest;
4778 else if (!state->Aborted)
4779 {
4780 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4781 state->Aborted = ARMul_DataAbortV;
4782 }
4783
4784 /* S cycles from here on. */
4785 for (; temp < 16; temp++)
4786 if (BIT (temp))
4787 {
4788 /* Load this register. */
4789 address += 4;
4790 dest = ARMul_LoadWordS (state, address);
4791
4792 if (!state->abortSig && !state->Aborted)
4793 state->Reg[temp] = dest;
4794 else if (!state->Aborted)
4795 {
4796 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4797 state->Aborted = ARMul_DataAbortV;
4798 }
4799 }
4800
4801 if (BIT (15) && !state->Aborted)
4802 {
4803 /* PC is in the reg list. */
4804 #ifdef MODE32
4805 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4806 {
4807 state->Cpsr = GETSPSR (state->Bank);
4808 ARMul_CPSRAltered (state);
4809 }
4810
4811 WriteR15 (state, PC);
4812 #else
4813 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
4814 {
4815 /* Protect bits in user mode. */
4816 ASSIGNN ((state->Reg[15] & NBIT) != 0);
4817 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
4818 ASSIGNC ((state->Reg[15] & CBIT) != 0);
4819 ASSIGNV ((state->Reg[15] & VBIT) != 0);
4820 }
4821 else
4822 ARMul_R15Altered (state);
4823
4824 FLUSHPIPE;
4825 #endif
4826 }
4827
4828 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
4829 /* Restore the correct bank. */
4830 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4831
4832 /* To write back the final register. */
4833 ARMul_Icycles (state, 1, 0L);
4834
4835 if (state->Aborted)
4836 {
4837 if (BIT (21) && LHSReg != 15)
4838 LSBase = WBBase;
4839
4840 TAKEABORT;
4841 }
4842 }
4843
4844 /* This function does the work of storing the registers listed in an STM
4845 instruction, when the S bit is clear. The code here is always increment
4846 after, it's up to the caller to get the input address correct and to
4847 handle base register modification. */
4848
4849 static void
StoreMult(ARMul_State * state,ARMword instr,ARMword address,ARMword WBBase)4850 StoreMult (ARMul_State * state,
4851 ARMword instr,
4852 ARMword address,
4853 ARMword WBBase)
4854 {
4855 ARMword temp;
4856
4857 UNDEF_LSMNoRegs;
4858 UNDEF_LSMPCBase;
4859 UNDEF_LSMBaseInListWb;
4860
4861 if (!TFLAG)
4862 /* N-cycle, increment the PC and update the NextInstr state. */
4863 BUSUSEDINCPCN;
4864
4865 #ifndef MODE32
4866 if (VECTORACCESS (address) || ADDREXCEPT (address))
4867 INTERNALABORT (address);
4868
4869 if (BIT (15))
4870 PATCHR15;
4871 #endif
4872
4873 /* N cycle first. */
4874 for (temp = 0; !BIT (temp); temp ++)
4875 ;
4876
4877 #ifdef MODE32
4878 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4879 #else
4880 if (state->Aborted)
4881 {
4882 (void) ARMul_LoadWordN (state, address);
4883
4884 /* Fake the Stores as Loads. */
4885 for (; temp < 16; temp++)
4886 if (BIT (temp))
4887 {
4888 /* Save this register. */
4889 address += 4;
4890 (void) ARMul_LoadWordS (state, address);
4891 }
4892
4893 if (BIT (21) && LHSReg != 15)
4894 LSBase = WBBase;
4895 TAKEABORT;
4896 return;
4897 }
4898 else
4899 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4900 #endif
4901
4902 if (state->abortSig && !state->Aborted)
4903 {
4904 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4905 state->Aborted = ARMul_DataAbortV;
4906 }
4907
4908 if (BIT (21) && LHSReg != 15)
4909 LSBase = WBBase;
4910
4911 /* S cycles from here on. */
4912 for (; temp < 16; temp ++)
4913 if (BIT (temp))
4914 {
4915 /* Save this register. */
4916 address += 4;
4917
4918 ARMul_StoreWordS (state, address, state->Reg[temp]);
4919
4920 if (state->abortSig && !state->Aborted)
4921 {
4922 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4923 state->Aborted = ARMul_DataAbortV;
4924 }
4925 }
4926
4927 if (state->Aborted)
4928 TAKEABORT;
4929 }
4930
4931 /* This function does the work of storing the registers listed in an STM
4932 instruction when the S bit is set. The code here is always increment
4933 after, it's up to the caller to get the input address correct and to
4934 handle base register modification. */
4935
4936 static void
StoreSMult(ARMul_State * state,ARMword instr,ARMword address,ARMword WBBase)4937 StoreSMult (ARMul_State * state,
4938 ARMword instr,
4939 ARMword address,
4940 ARMword WBBase)
4941 {
4942 ARMword temp;
4943
4944 UNDEF_LSMNoRegs;
4945 UNDEF_LSMPCBase;
4946 UNDEF_LSMBaseInListWb;
4947
4948 BUSUSEDINCPCN;
4949
4950 #ifndef MODE32
4951 if (VECTORACCESS (address) || ADDREXCEPT (address))
4952 INTERNALABORT (address);
4953
4954 if (BIT (15))
4955 PATCHR15;
4956 #endif
4957
4958 if (state->Bank != USERBANK)
4959 {
4960 /* Force User Bank. */
4961 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4962 UNDEF_LSMUserBankWb;
4963 }
4964
4965 for (temp = 0; !BIT (temp); temp++)
4966 ; /* N cycle first. */
4967
4968 #ifdef MODE32
4969 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4970 #else
4971 if (state->Aborted)
4972 {
4973 (void) ARMul_LoadWordN (state, address);
4974
4975 for (; temp < 16; temp++)
4976 /* Fake the Stores as Loads. */
4977 if (BIT (temp))
4978 {
4979 /* Save this register. */
4980 address += 4;
4981
4982 (void) ARMul_LoadWordS (state, address);
4983 }
4984
4985 if (BIT (21) && LHSReg != 15)
4986 LSBase = WBBase;
4987
4988 TAKEABORT;
4989 return;
4990 }
4991 else
4992 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4993 #endif
4994
4995 if (state->abortSig && !state->Aborted)
4996 {
4997 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4998 state->Aborted = ARMul_DataAbortV;
4999 }
5000
5001 /* S cycles from here on. */
5002 for (; temp < 16; temp++)
5003 if (BIT (temp))
5004 {
5005 /* Save this register. */
5006 address += 4;
5007
5008 ARMul_StoreWordS (state, address, state->Reg[temp]);
5009
5010 if (state->abortSig && !state->Aborted)
5011 {
5012 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5013 state->Aborted = ARMul_DataAbortV;
5014 }
5015 }
5016
5017 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
5018 /* Restore the correct bank. */
5019 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
5020
5021 if (BIT (21) && LHSReg != 15)
5022 LSBase = WBBase;
5023
5024 if (state->Aborted)
5025 TAKEABORT;
5026 }
5027
5028 /* This function does the work of adding two 32bit values
5029 together, and calculating if a carry has occurred. */
5030
5031 static ARMword
Add32(ARMword a1,ARMword a2,int * carry)5032 Add32 (ARMword a1, ARMword a2, int *carry)
5033 {
5034 ARMword result = (a1 + a2);
5035 unsigned int uresult = (unsigned int) result;
5036 unsigned int ua1 = (unsigned int) a1;
5037
5038 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5039 or (result > RdLo) then we have no carry. */
5040 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
5041 *carry = 1;
5042 else
5043 *carry = 0;
5044
5045 return result;
5046 }
5047
5048 /* This function does the work of multiplying
5049 two 32bit values to give a 64bit result. */
5050
5051 static unsigned
Multiply64(ARMul_State * state,ARMword instr,int msigned,int scc)5052 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
5053 {
5054 /* Operand register numbers. */
5055 int nRdHi, nRdLo, nRs, nRm;
5056 ARMword RdHi = 0, RdLo = 0, Rm;
5057 /* Cycle count. */
5058 int scount;
5059
5060 nRdHi = BITS (16, 19);
5061 nRdLo = BITS (12, 15);
5062 nRs = BITS (8, 11);
5063 nRm = BITS (0, 3);
5064
5065 /* Needed to calculate the cycle count. */
5066 Rm = state->Reg[nRm];
5067
5068 /* Check for illegal operand combinations first. */
5069 if ( nRdHi != 15
5070 && nRdLo != 15
5071 && nRs != 15
5072 && nRm != 15
5073 && nRdHi != nRdLo
5074 && nRdHi != nRm
5075 && nRdLo != nRm)
5076 {
5077 /* Intermediate results. */
5078 ARMword lo, mid1, mid2, hi;
5079 int carry;
5080 ARMword Rs = state->Reg[nRs];
5081 int sign = 0;
5082
5083 if (msigned)
5084 {
5085 /* Compute sign of result and adjust operands if necessary. */
5086 sign = (Rm ^ Rs) & 0x80000000;
5087
5088 if (((ARMsword) Rm) < 0)
5089 Rm = -Rm;
5090
5091 if (((ARMsword) Rs) < 0)
5092 Rs = -Rs;
5093 }
5094
5095 /* We can split the 32x32 into four 16x16 operations. This
5096 ensures that we do not lose precision on 32bit only hosts. */
5097 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
5098 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
5099 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
5100 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
5101
5102 /* We now need to add all of these results together, taking
5103 care to propogate the carries from the additions. */
5104 RdLo = Add32 (lo, (mid1 << 16), &carry);
5105 RdHi = carry;
5106 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
5107 RdHi +=
5108 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
5109
5110 if (sign)
5111 {
5112 /* Negate result if necessary. */
5113 RdLo = ~RdLo;
5114 RdHi = ~RdHi;
5115 if (RdLo == 0xFFFFFFFF)
5116 {
5117 RdLo = 0;
5118 RdHi += 1;
5119 }
5120 else
5121 RdLo += 1;
5122 }
5123
5124 state->Reg[nRdLo] = RdLo;
5125 state->Reg[nRdHi] = RdHi;
5126 }
5127 else
5128 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
5129
5130 if (scc)
5131 /* Ensure that both RdHi and RdLo are used to compute Z,
5132 but don't let RdLo's sign bit make it to N. */
5133 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
5134
5135 /* The cycle count depends on whether the instruction is a signed or
5136 unsigned multiply, and what bits are clear in the multiplier. */
5137 if (msigned && (Rm & ((unsigned) 1 << 31)))
5138 /* Invert the bits to make the check against zero. */
5139 Rm = ~Rm;
5140
5141 if ((Rm & 0xFFFFFF00) == 0)
5142 scount = 1;
5143 else if ((Rm & 0xFFFF0000) == 0)
5144 scount = 2;
5145 else if ((Rm & 0xFF000000) == 0)
5146 scount = 3;
5147 else
5148 scount = 4;
5149
5150 return 2 + scount;
5151 }
5152
5153 /* This function does the work of multiplying two 32bit
5154 values and adding a 64bit value to give a 64bit result. */
5155
5156 static unsigned
MultiplyAdd64(ARMul_State * state,ARMword instr,int msigned,int scc)5157 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
5158 {
5159 unsigned scount;
5160 ARMword RdLo, RdHi;
5161 int nRdHi, nRdLo;
5162 int carry = 0;
5163
5164 nRdHi = BITS (16, 19);
5165 nRdLo = BITS (12, 15);
5166
5167 RdHi = state->Reg[nRdHi];
5168 RdLo = state->Reg[nRdLo];
5169
5170 scount = Multiply64 (state, instr, msigned, LDEFAULT);
5171
5172 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
5173 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
5174
5175 state->Reg[nRdLo] = RdLo;
5176 state->Reg[nRdHi] = RdHi;
5177
5178 if (scc)
5179 /* Ensure that both RdHi and RdLo are used to compute Z,
5180 but don't let RdLo's sign bit make it to N. */
5181 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
5182
5183 /* Extra cycle for addition. */
5184 return scount + 1;
5185 }
5186