20a36bca7b6f4b8efbed131bf87b1c24e046dfdd
[deliverable/binutils-gdb.git] / sim / arm / armemu.c
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
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
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: /* MOVW immed */
2319 dest = BITS (0, 11);
2320 dest |= (BITS (16, 19) << 12);
2321 WRITEDEST (dest);
2322 break;
2323
2324 case 0x31: /* TSTP immed */
2325 if (DESTReg == 15)
2326 {
2327 /* TSTP immed. */
2328 #ifdef MODE32
2329 state->Cpsr = GETSPSR (state->Bank);
2330 ARMul_CPSRAltered (state);
2331 #else
2332 temp = LHS & DPImmRHS;
2333 SETR15PSR (temp);
2334 #endif
2335 }
2336 else
2337 {
2338 /* TST immed. */
2339 DPSImmRHS;
2340 dest = LHS & rhs;
2341 ARMul_NegZero (state, dest);
2342 }
2343 break;
2344
2345 case 0x32: /* TEQ immed and MSR immed to CPSR */
2346 if (DESTReg == 15)
2347 /* MSR immed to CPSR. */
2348 ARMul_FixCPSR (state, instr, DPImmRHS);
2349 else
2350 UNDEF_Test;
2351 break;
2352
2353 case 0x33: /* TEQP immed */
2354 if (DESTReg == 15)
2355 {
2356 /* TEQP immed. */
2357 #ifdef MODE32
2358 state->Cpsr = GETSPSR (state->Bank);
2359 ARMul_CPSRAltered (state);
2360 #else
2361 temp = LHS ^ DPImmRHS;
2362 SETR15PSR (temp);
2363 #endif
2364 }
2365 else
2366 {
2367 DPSImmRHS; /* TEQ immed */
2368 dest = LHS ^ rhs;
2369 ARMul_NegZero (state, dest);
2370 }
2371 break;
2372
2373 case 0x34: /* MOVT immed */
2374 dest = BITS (0, 11);
2375 dest |= (BITS (16, 19) << 12);
2376 DEST |= (dest << 16);
2377 break;
2378
2379 case 0x35: /* CMPP immed */
2380 if (DESTReg == 15)
2381 {
2382 /* CMPP immed. */
2383 #ifdef MODE32
2384 state->Cpsr = GETSPSR (state->Bank);
2385 ARMul_CPSRAltered (state);
2386 #else
2387 temp = LHS - DPImmRHS;
2388 SETR15PSR (temp);
2389 #endif
2390 break;
2391 }
2392 else
2393 {
2394 /* CMP immed. */
2395 lhs = LHS;
2396 rhs = DPImmRHS;
2397 dest = lhs - rhs;
2398 ARMul_NegZero (state, dest);
2399
2400 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2401 {
2402 ARMul_SubCarry (state, lhs, rhs, dest);
2403 ARMul_SubOverflow (state, lhs, rhs, dest);
2404 }
2405 else
2406 {
2407 CLEARC;
2408 CLEARV;
2409 }
2410 }
2411 break;
2412
2413 case 0x36: /* CMN immed and MSR immed to SPSR */
2414 if (DESTReg == 15)
2415 ARMul_FixSPSR (state, instr, DPImmRHS);
2416 else
2417 UNDEF_Test;
2418 break;
2419
2420 case 0x37: /* CMNP immed. */
2421 if (DESTReg == 15)
2422 {
2423 /* CMNP immed. */
2424 #ifdef MODE32
2425 state->Cpsr = GETSPSR (state->Bank);
2426 ARMul_CPSRAltered (state);
2427 #else
2428 temp = LHS + DPImmRHS;
2429 SETR15PSR (temp);
2430 #endif
2431 break;
2432 }
2433 else
2434 {
2435 /* CMN immed. */
2436 lhs = LHS;
2437 rhs = DPImmRHS;
2438 dest = lhs + rhs;
2439 ASSIGNZ (dest == 0);
2440 if ((lhs | rhs) >> 30)
2441 {
2442 /* Possible C,V,N to set. */
2443 ASSIGNN (NEG (dest));
2444 ARMul_AddCarry (state, lhs, rhs, dest);
2445 ARMul_AddOverflow (state, lhs, rhs, dest);
2446 }
2447 else
2448 {
2449 CLEARN;
2450 CLEARC;
2451 CLEARV;
2452 }
2453 }
2454 break;
2455
2456 case 0x38: /* ORR immed. */
2457 dest = LHS | DPImmRHS;
2458 WRITEDEST (dest);
2459 break;
2460
2461 case 0x39: /* ORRS immed. */
2462 DPSImmRHS;
2463 dest = LHS | rhs;
2464 WRITESDEST (dest);
2465 break;
2466
2467 case 0x3a: /* MOV immed. */
2468 dest = DPImmRHS;
2469 WRITEDEST (dest);
2470 break;
2471
2472 case 0x3b: /* MOVS immed. */
2473 DPSImmRHS;
2474 WRITESDEST (rhs);
2475 break;
2476
2477 case 0x3c: /* BIC immed. */
2478 dest = LHS & ~DPImmRHS;
2479 WRITEDEST (dest);
2480 break;
2481
2482 case 0x3d: /* BICS immed. */
2483 DPSImmRHS;
2484 dest = LHS & ~rhs;
2485 WRITESDEST (dest);
2486 break;
2487
2488 case 0x3e: /* MVN immed. */
2489 dest = ~DPImmRHS;
2490 WRITEDEST (dest);
2491 break;
2492
2493 case 0x3f: /* MVNS immed. */
2494 DPSImmRHS;
2495 WRITESDEST (~rhs);
2496 break;
2497
2498
2499 /* Single Data Transfer Immediate RHS Instructions. */
2500
2501 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2502 lhs = LHS;
2503 if (StoreWord (state, instr, lhs))
2504 LSBase = lhs - LSImmRHS;
2505 break;
2506
2507 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2508 lhs = LHS;
2509 if (LoadWord (state, instr, lhs))
2510 LSBase = lhs - LSImmRHS;
2511 break;
2512
2513 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2514 UNDEF_LSRBaseEQDestWb;
2515 UNDEF_LSRPCBaseWb;
2516 lhs = LHS;
2517 temp = lhs - LSImmRHS;
2518 state->NtransSig = LOW;
2519 if (StoreWord (state, instr, lhs))
2520 LSBase = temp;
2521 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2522 break;
2523
2524 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2525 UNDEF_LSRBaseEQDestWb;
2526 UNDEF_LSRPCBaseWb;
2527 lhs = LHS;
2528 state->NtransSig = LOW;
2529 if (LoadWord (state, instr, lhs))
2530 LSBase = lhs - LSImmRHS;
2531 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2532 break;
2533
2534 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2535 lhs = LHS;
2536 if (StoreByte (state, instr, lhs))
2537 LSBase = lhs - LSImmRHS;
2538 break;
2539
2540 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2541 lhs = LHS;
2542 if (LoadByte (state, instr, lhs, LUNSIGNED))
2543 LSBase = lhs - LSImmRHS;
2544 break;
2545
2546 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2547 UNDEF_LSRBaseEQDestWb;
2548 UNDEF_LSRPCBaseWb;
2549 lhs = LHS;
2550 state->NtransSig = LOW;
2551 if (StoreByte (state, instr, lhs))
2552 LSBase = lhs - LSImmRHS;
2553 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2554 break;
2555
2556 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2557 UNDEF_LSRBaseEQDestWb;
2558 UNDEF_LSRPCBaseWb;
2559 lhs = LHS;
2560 state->NtransSig = LOW;
2561 if (LoadByte (state, instr, lhs, LUNSIGNED))
2562 LSBase = lhs - LSImmRHS;
2563 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2564 break;
2565
2566 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2567 lhs = LHS;
2568 if (StoreWord (state, instr, lhs))
2569 LSBase = lhs + LSImmRHS;
2570 break;
2571
2572 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2573 lhs = LHS;
2574 if (LoadWord (state, instr, lhs))
2575 LSBase = lhs + LSImmRHS;
2576 break;
2577
2578 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2579 UNDEF_LSRBaseEQDestWb;
2580 UNDEF_LSRPCBaseWb;
2581 lhs = LHS;
2582 state->NtransSig = LOW;
2583 if (StoreWord (state, instr, lhs))
2584 LSBase = lhs + LSImmRHS;
2585 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2586 break;
2587
2588 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2589 UNDEF_LSRBaseEQDestWb;
2590 UNDEF_LSRPCBaseWb;
2591 lhs = LHS;
2592 state->NtransSig = LOW;
2593 if (LoadWord (state, instr, lhs))
2594 LSBase = lhs + LSImmRHS;
2595 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2596 break;
2597
2598 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2599 lhs = LHS;
2600 if (StoreByte (state, instr, lhs))
2601 LSBase = lhs + LSImmRHS;
2602 break;
2603
2604 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2605 lhs = LHS;
2606 if (LoadByte (state, instr, lhs, LUNSIGNED))
2607 LSBase = lhs + LSImmRHS;
2608 break;
2609
2610 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2611 UNDEF_LSRBaseEQDestWb;
2612 UNDEF_LSRPCBaseWb;
2613 lhs = LHS;
2614 state->NtransSig = LOW;
2615 if (StoreByte (state, instr, lhs))
2616 LSBase = lhs + LSImmRHS;
2617 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2618 break;
2619
2620 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2621 UNDEF_LSRBaseEQDestWb;
2622 UNDEF_LSRPCBaseWb;
2623 lhs = LHS;
2624 state->NtransSig = LOW;
2625 if (LoadByte (state, instr, lhs, LUNSIGNED))
2626 LSBase = lhs + LSImmRHS;
2627 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2628 break;
2629
2630
2631 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2632 (void) StoreWord (state, instr, LHS - LSImmRHS);
2633 break;
2634
2635 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2636 (void) LoadWord (state, instr, LHS - LSImmRHS);
2637 break;
2638
2639 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2640 UNDEF_LSRBaseEQDestWb;
2641 UNDEF_LSRPCBaseWb;
2642 temp = LHS - LSImmRHS;
2643 if (StoreWord (state, instr, temp))
2644 LSBase = temp;
2645 break;
2646
2647 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2648 UNDEF_LSRBaseEQDestWb;
2649 UNDEF_LSRPCBaseWb;
2650 temp = LHS - LSImmRHS;
2651 if (LoadWord (state, instr, temp))
2652 LSBase = temp;
2653 break;
2654
2655 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2656 (void) StoreByte (state, instr, LHS - LSImmRHS);
2657 break;
2658
2659 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2660 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
2661 break;
2662
2663 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2664 UNDEF_LSRBaseEQDestWb;
2665 UNDEF_LSRPCBaseWb;
2666 temp = LHS - LSImmRHS;
2667 if (StoreByte (state, instr, temp))
2668 LSBase = temp;
2669 break;
2670
2671 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2672 UNDEF_LSRBaseEQDestWb;
2673 UNDEF_LSRPCBaseWb;
2674 temp = LHS - LSImmRHS;
2675 if (LoadByte (state, instr, temp, LUNSIGNED))
2676 LSBase = temp;
2677 break;
2678
2679 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2680 (void) StoreWord (state, instr, LHS + LSImmRHS);
2681 break;
2682
2683 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2684 (void) LoadWord (state, instr, LHS + LSImmRHS);
2685 break;
2686
2687 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2688 UNDEF_LSRBaseEQDestWb;
2689 UNDEF_LSRPCBaseWb;
2690 temp = LHS + LSImmRHS;
2691 if (StoreWord (state, instr, temp))
2692 LSBase = temp;
2693 break;
2694
2695 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2696 UNDEF_LSRBaseEQDestWb;
2697 UNDEF_LSRPCBaseWb;
2698 temp = LHS + LSImmRHS;
2699 if (LoadWord (state, instr, temp))
2700 LSBase = temp;
2701 break;
2702
2703 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2704 (void) StoreByte (state, instr, LHS + LSImmRHS);
2705 break;
2706
2707 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2708 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
2709 break;
2710
2711 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2712 UNDEF_LSRBaseEQDestWb;
2713 UNDEF_LSRPCBaseWb;
2714 temp = LHS + LSImmRHS;
2715 if (StoreByte (state, instr, temp))
2716 LSBase = temp;
2717 break;
2718
2719 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2720 UNDEF_LSRBaseEQDestWb;
2721 UNDEF_LSRPCBaseWb;
2722 temp = LHS + LSImmRHS;
2723 if (LoadByte (state, instr, temp, LUNSIGNED))
2724 LSBase = temp;
2725 break;
2726
2727
2728 /* Single Data Transfer Register RHS Instructions. */
2729
2730 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2731 if (BIT (4))
2732 {
2733 ARMul_UndefInstr (state, instr);
2734 break;
2735 }
2736 UNDEF_LSRBaseEQOffWb;
2737 UNDEF_LSRBaseEQDestWb;
2738 UNDEF_LSRPCBaseWb;
2739 UNDEF_LSRPCOffWb;
2740 lhs = LHS;
2741 if (StoreWord (state, instr, lhs))
2742 LSBase = lhs - LSRegRHS;
2743 break;
2744
2745 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2746 if (BIT (4))
2747 {
2748 #ifdef MODE32
2749 if (state->is_v6
2750 && handle_v6_insn (state, instr))
2751 break;
2752 #endif
2753 ARMul_UndefInstr (state, instr);
2754 break;
2755 }
2756 UNDEF_LSRBaseEQOffWb;
2757 UNDEF_LSRBaseEQDestWb;
2758 UNDEF_LSRPCBaseWb;
2759 UNDEF_LSRPCOffWb;
2760 lhs = LHS;
2761 temp = lhs - LSRegRHS;
2762 if (LoadWord (state, instr, lhs))
2763 LSBase = temp;
2764 break;
2765
2766 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2767 if (BIT (4))
2768 {
2769 #ifdef MODE32
2770 if (state->is_v6
2771 && handle_v6_insn (state, instr))
2772 break;
2773 #endif
2774 ARMul_UndefInstr (state, instr);
2775 break;
2776 }
2777 UNDEF_LSRBaseEQOffWb;
2778 UNDEF_LSRBaseEQDestWb;
2779 UNDEF_LSRPCBaseWb;
2780 UNDEF_LSRPCOffWb;
2781 lhs = LHS;
2782 state->NtransSig = LOW;
2783 if (StoreWord (state, instr, lhs))
2784 LSBase = lhs - LSRegRHS;
2785 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2786 break;
2787
2788 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2789 if (BIT (4))
2790 {
2791 #ifdef MODE32
2792 if (state->is_v6
2793 && handle_v6_insn (state, instr))
2794 break;
2795 #endif
2796 ARMul_UndefInstr (state, instr);
2797 break;
2798 }
2799 UNDEF_LSRBaseEQOffWb;
2800 UNDEF_LSRBaseEQDestWb;
2801 UNDEF_LSRPCBaseWb;
2802 UNDEF_LSRPCOffWb;
2803 lhs = LHS;
2804 temp = lhs - LSRegRHS;
2805 state->NtransSig = LOW;
2806 if (LoadWord (state, instr, lhs))
2807 LSBase = temp;
2808 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2809 break;
2810
2811 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2812 if (BIT (4))
2813 {
2814 ARMul_UndefInstr (state, instr);
2815 break;
2816 }
2817 UNDEF_LSRBaseEQOffWb;
2818 UNDEF_LSRBaseEQDestWb;
2819 UNDEF_LSRPCBaseWb;
2820 UNDEF_LSRPCOffWb;
2821 lhs = LHS;
2822 if (StoreByte (state, instr, lhs))
2823 LSBase = lhs - LSRegRHS;
2824 break;
2825
2826 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2827 if (BIT (4))
2828 {
2829 #ifdef MODE32
2830 if (state->is_v6
2831 && handle_v6_insn (state, instr))
2832 break;
2833 #endif
2834 ARMul_UndefInstr (state, instr);
2835 break;
2836 }
2837 UNDEF_LSRBaseEQOffWb;
2838 UNDEF_LSRBaseEQDestWb;
2839 UNDEF_LSRPCBaseWb;
2840 UNDEF_LSRPCOffWb;
2841 lhs = LHS;
2842 temp = lhs - LSRegRHS;
2843 if (LoadByte (state, instr, lhs, LUNSIGNED))
2844 LSBase = temp;
2845 break;
2846
2847 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2848 if (BIT (4))
2849 {
2850 #ifdef MODE32
2851 if (state->is_v6
2852 && handle_v6_insn (state, instr))
2853 break;
2854 #endif
2855 ARMul_UndefInstr (state, instr);
2856 break;
2857 }
2858 UNDEF_LSRBaseEQOffWb;
2859 UNDEF_LSRBaseEQDestWb;
2860 UNDEF_LSRPCBaseWb;
2861 UNDEF_LSRPCOffWb;
2862 lhs = LHS;
2863 state->NtransSig = LOW;
2864 if (StoreByte (state, instr, lhs))
2865 LSBase = lhs - LSRegRHS;
2866 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2867 break;
2868
2869 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2870 if (BIT (4))
2871 {
2872 #ifdef MODE32
2873 if (state->is_v6
2874 && handle_v6_insn (state, instr))
2875 break;
2876 #endif
2877 ARMul_UndefInstr (state, instr);
2878 break;
2879 }
2880 UNDEF_LSRBaseEQOffWb;
2881 UNDEF_LSRBaseEQDestWb;
2882 UNDEF_LSRPCBaseWb;
2883 UNDEF_LSRPCOffWb;
2884 lhs = LHS;
2885 temp = lhs - LSRegRHS;
2886 state->NtransSig = LOW;
2887 if (LoadByte (state, instr, lhs, LUNSIGNED))
2888 LSBase = temp;
2889 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2890 break;
2891
2892 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2893 if (BIT (4))
2894 {
2895 #ifdef MODE32
2896 if (state->is_v6
2897 && handle_v6_insn (state, instr))
2898 break;
2899 #endif
2900 ARMul_UndefInstr (state, instr);
2901 break;
2902 }
2903 UNDEF_LSRBaseEQOffWb;
2904 UNDEF_LSRBaseEQDestWb;
2905 UNDEF_LSRPCBaseWb;
2906 UNDEF_LSRPCOffWb;
2907 lhs = LHS;
2908 if (StoreWord (state, instr, lhs))
2909 LSBase = lhs + LSRegRHS;
2910 break;
2911
2912 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2913 if (BIT (4))
2914 {
2915 ARMul_UndefInstr (state, instr);
2916 break;
2917 }
2918 UNDEF_LSRBaseEQOffWb;
2919 UNDEF_LSRBaseEQDestWb;
2920 UNDEF_LSRPCBaseWb;
2921 UNDEF_LSRPCOffWb;
2922 lhs = LHS;
2923 temp = lhs + LSRegRHS;
2924 if (LoadWord (state, instr, lhs))
2925 LSBase = temp;
2926 break;
2927
2928 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2929 if (BIT (4))
2930 {
2931 #ifdef MODE32
2932 if (state->is_v6
2933 && handle_v6_insn (state, instr))
2934 break;
2935 #endif
2936 ARMul_UndefInstr (state, instr);
2937 break;
2938 }
2939 UNDEF_LSRBaseEQOffWb;
2940 UNDEF_LSRBaseEQDestWb;
2941 UNDEF_LSRPCBaseWb;
2942 UNDEF_LSRPCOffWb;
2943 lhs = LHS;
2944 state->NtransSig = LOW;
2945 if (StoreWord (state, instr, lhs))
2946 LSBase = lhs + LSRegRHS;
2947 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2948 break;
2949
2950 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2951 if (BIT (4))
2952 {
2953 #ifdef MODE32
2954 if (state->is_v6
2955 && handle_v6_insn (state, instr))
2956 break;
2957 #endif
2958 ARMul_UndefInstr (state, instr);
2959 break;
2960 }
2961 UNDEF_LSRBaseEQOffWb;
2962 UNDEF_LSRBaseEQDestWb;
2963 UNDEF_LSRPCBaseWb;
2964 UNDEF_LSRPCOffWb;
2965 lhs = LHS;
2966 temp = lhs + LSRegRHS;
2967 state->NtransSig = LOW;
2968 if (LoadWord (state, instr, lhs))
2969 LSBase = temp;
2970 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2971 break;
2972
2973 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2974 if (BIT (4))
2975 {
2976 #ifdef MODE32
2977 if (state->is_v6
2978 && handle_v6_insn (state, instr))
2979 break;
2980 #endif
2981 ARMul_UndefInstr (state, instr);
2982 break;
2983 }
2984 UNDEF_LSRBaseEQOffWb;
2985 UNDEF_LSRBaseEQDestWb;
2986 UNDEF_LSRPCBaseWb;
2987 UNDEF_LSRPCOffWb;
2988 lhs = LHS;
2989 if (StoreByte (state, instr, lhs))
2990 LSBase = lhs + LSRegRHS;
2991 break;
2992
2993 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
2994 if (BIT (4))
2995 {
2996 ARMul_UndefInstr (state, instr);
2997 break;
2998 }
2999 UNDEF_LSRBaseEQOffWb;
3000 UNDEF_LSRBaseEQDestWb;
3001 UNDEF_LSRPCBaseWb;
3002 UNDEF_LSRPCOffWb;
3003 lhs = LHS;
3004 temp = lhs + LSRegRHS;
3005 if (LoadByte (state, instr, lhs, LUNSIGNED))
3006 LSBase = temp;
3007 break;
3008
3009 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3010 if (BIT (4))
3011 {
3012 #ifdef MODE32
3013 if (state->is_v6
3014 && handle_v6_insn (state, instr))
3015 break;
3016 #endif
3017 ARMul_UndefInstr (state, instr);
3018 break;
3019 }
3020 UNDEF_LSRBaseEQOffWb;
3021 UNDEF_LSRBaseEQDestWb;
3022 UNDEF_LSRPCBaseWb;
3023 UNDEF_LSRPCOffWb;
3024 lhs = LHS;
3025 state->NtransSig = LOW;
3026 if (StoreByte (state, instr, lhs))
3027 LSBase = lhs + LSRegRHS;
3028 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3029 break;
3030
3031 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3032 if (BIT (4))
3033 {
3034 #ifdef MODE32
3035 if (state->is_v6
3036 && handle_v6_insn (state, instr))
3037 break;
3038 #endif
3039 ARMul_UndefInstr (state, instr);
3040 break;
3041 }
3042 UNDEF_LSRBaseEQOffWb;
3043 UNDEF_LSRBaseEQDestWb;
3044 UNDEF_LSRPCBaseWb;
3045 UNDEF_LSRPCOffWb;
3046 lhs = LHS;
3047 temp = lhs + LSRegRHS;
3048 state->NtransSig = LOW;
3049 if (LoadByte (state, instr, lhs, LUNSIGNED))
3050 LSBase = temp;
3051 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
3052 break;
3053
3054
3055 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3056 if (BIT (4))
3057 {
3058 #ifdef MODE32
3059 if (state->is_v6
3060 && handle_v6_insn (state, instr))
3061 break;
3062 #endif
3063 ARMul_UndefInstr (state, instr);
3064 break;
3065 }
3066 (void) StoreWord (state, instr, LHS - LSRegRHS);
3067 break;
3068
3069 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3070 if (BIT (4))
3071 {
3072 ARMul_UndefInstr (state, instr);
3073 break;
3074 }
3075 (void) LoadWord (state, instr, LHS - LSRegRHS);
3076 break;
3077
3078 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3079 if (BIT (4))
3080 {
3081 ARMul_UndefInstr (state, instr);
3082 break;
3083 }
3084 UNDEF_LSRBaseEQOffWb;
3085 UNDEF_LSRBaseEQDestWb;
3086 UNDEF_LSRPCBaseWb;
3087 UNDEF_LSRPCOffWb;
3088 temp = LHS - LSRegRHS;
3089 if (StoreWord (state, instr, temp))
3090 LSBase = temp;
3091 break;
3092
3093 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3094 if (BIT (4))
3095 {
3096 ARMul_UndefInstr (state, instr);
3097 break;
3098 }
3099 UNDEF_LSRBaseEQOffWb;
3100 UNDEF_LSRBaseEQDestWb;
3101 UNDEF_LSRPCBaseWb;
3102 UNDEF_LSRPCOffWb;
3103 temp = LHS - LSRegRHS;
3104 if (LoadWord (state, instr, temp))
3105 LSBase = temp;
3106 break;
3107
3108 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3109 if (BIT (4))
3110 {
3111 #ifdef MODE32
3112 if (state->is_v6
3113 && handle_v6_insn (state, instr))
3114 break;
3115 #endif
3116 ARMul_UndefInstr (state, instr);
3117 break;
3118 }
3119 (void) StoreByte (state, instr, LHS - LSRegRHS);
3120 break;
3121
3122 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3123 if (BIT (4))
3124 {
3125 #ifdef MODE32
3126 if (state->is_v6
3127 && handle_v6_insn (state, instr))
3128 break;
3129 #endif
3130 ARMul_UndefInstr (state, instr);
3131 break;
3132 }
3133 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
3134 break;
3135
3136 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3137 if (BIT (4))
3138 {
3139 ARMul_UndefInstr (state, instr);
3140 break;
3141 }
3142 UNDEF_LSRBaseEQOffWb;
3143 UNDEF_LSRBaseEQDestWb;
3144 UNDEF_LSRPCBaseWb;
3145 UNDEF_LSRPCOffWb;
3146 temp = LHS - LSRegRHS;
3147 if (StoreByte (state, instr, temp))
3148 LSBase = temp;
3149 break;
3150
3151 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3152 if (BIT (4))
3153 {
3154 ARMul_UndefInstr (state, instr);
3155 break;
3156 }
3157 UNDEF_LSRBaseEQOffWb;
3158 UNDEF_LSRBaseEQDestWb;
3159 UNDEF_LSRPCBaseWb;
3160 UNDEF_LSRPCOffWb;
3161 temp = LHS - LSRegRHS;
3162 if (LoadByte (state, instr, temp, LUNSIGNED))
3163 LSBase = temp;
3164 break;
3165
3166 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3167 if (BIT (4))
3168 {
3169 #ifdef MODE32
3170 if (state->is_v6
3171 && handle_v6_insn (state, instr))
3172 break;
3173 #endif
3174 ARMul_UndefInstr (state, instr);
3175 break;
3176 }
3177 (void) StoreWord (state, instr, LHS + LSRegRHS);
3178 break;
3179
3180 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
3181 if (BIT (4))
3182 {
3183 ARMul_UndefInstr (state, instr);
3184 break;
3185 }
3186 (void) LoadWord (state, instr, LHS + LSRegRHS);
3187 break;
3188
3189 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
3190 if (BIT (4))
3191 {
3192 #ifdef MODE32
3193 if (state->is_v6
3194 && handle_v6_insn (state, instr))
3195 break;
3196 #endif
3197 ARMul_UndefInstr (state, instr);
3198 break;
3199 }
3200 UNDEF_LSRBaseEQOffWb;
3201 UNDEF_LSRBaseEQDestWb;
3202 UNDEF_LSRPCBaseWb;
3203 UNDEF_LSRPCOffWb;
3204 temp = LHS + LSRegRHS;
3205 if (StoreWord (state, instr, temp))
3206 LSBase = temp;
3207 break;
3208
3209 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
3210 if (BIT (4))
3211 {
3212 ARMul_UndefInstr (state, instr);
3213 break;
3214 }
3215 UNDEF_LSRBaseEQOffWb;
3216 UNDEF_LSRBaseEQDestWb;
3217 UNDEF_LSRPCBaseWb;
3218 UNDEF_LSRPCOffWb;
3219 temp = LHS + LSRegRHS;
3220 if (LoadWord (state, instr, temp))
3221 LSBase = temp;
3222 break;
3223
3224 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
3225 if (BIT (4))
3226 {
3227 #ifdef MODE32
3228 if (state->is_v6
3229 && handle_v6_insn (state, instr))
3230 break;
3231 #endif
3232 ARMul_UndefInstr (state, instr);
3233 break;
3234 }
3235 (void) StoreByte (state, instr, LHS + LSRegRHS);
3236 break;
3237
3238 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
3239 if (BIT (4))
3240 {
3241 ARMul_UndefInstr (state, instr);
3242 break;
3243 }
3244 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
3245 break;
3246
3247 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
3248 if (BIT (4))
3249 {
3250 ARMul_UndefInstr (state, instr);
3251 break;
3252 }
3253 UNDEF_LSRBaseEQOffWb;
3254 UNDEF_LSRBaseEQDestWb;
3255 UNDEF_LSRPCBaseWb;
3256 UNDEF_LSRPCOffWb;
3257 temp = LHS + LSRegRHS;
3258 if (StoreByte (state, instr, temp))
3259 LSBase = temp;
3260 break;
3261
3262 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
3263 if (BIT (4))
3264 {
3265 /* Check for the special breakpoint opcode.
3266 This value should correspond to the value defined
3267 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
3268 if (BITS (0, 19) == 0xfdefe)
3269 {
3270 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
3271 ARMul_Abort (state, ARMul_SWIV);
3272 }
3273 else
3274 ARMul_UndefInstr (state, instr);
3275 break;
3276 }
3277 UNDEF_LSRBaseEQOffWb;
3278 UNDEF_LSRBaseEQDestWb;
3279 UNDEF_LSRPCBaseWb;
3280 UNDEF_LSRPCOffWb;
3281 temp = LHS + LSRegRHS;
3282 if (LoadByte (state, instr, temp, LUNSIGNED))
3283 LSBase = temp;
3284 break;
3285
3286
3287 /* Multiple Data Transfer Instructions. */
3288
3289 case 0x80: /* Store, No WriteBack, Post Dec. */
3290 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3291 break;
3292
3293 case 0x81: /* Load, No WriteBack, Post Dec. */
3294 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3295 break;
3296
3297 case 0x82: /* Store, WriteBack, Post Dec. */
3298 temp = LSBase - LSMNumRegs;
3299 STOREMULT (instr, temp + 4L, temp);
3300 break;
3301
3302 case 0x83: /* Load, WriteBack, Post Dec. */
3303 temp = LSBase - LSMNumRegs;
3304 LOADMULT (instr, temp + 4L, temp);
3305 break;
3306
3307 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
3308 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3309 break;
3310
3311 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
3312 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3313 break;
3314
3315 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
3316 temp = LSBase - LSMNumRegs;
3317 STORESMULT (instr, temp + 4L, temp);
3318 break;
3319
3320 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3321 temp = LSBase - LSMNumRegs;
3322 LOADSMULT (instr, temp + 4L, temp);
3323 break;
3324
3325 case 0x88: /* Store, No WriteBack, Post Inc. */
3326 STOREMULT (instr, LSBase, 0L);
3327 break;
3328
3329 case 0x89: /* Load, No WriteBack, Post Inc. */
3330 LOADMULT (instr, LSBase, 0L);
3331 break;
3332
3333 case 0x8a: /* Store, WriteBack, Post Inc. */
3334 temp = LSBase;
3335 STOREMULT (instr, temp, temp + LSMNumRegs);
3336 break;
3337
3338 case 0x8b: /* Load, WriteBack, Post Inc. */
3339 temp = LSBase;
3340 LOADMULT (instr, temp, temp + LSMNumRegs);
3341 break;
3342
3343 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3344 STORESMULT (instr, LSBase, 0L);
3345 break;
3346
3347 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3348 LOADSMULT (instr, LSBase, 0L);
3349 break;
3350
3351 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3352 temp = LSBase;
3353 STORESMULT (instr, temp, temp + LSMNumRegs);
3354 break;
3355
3356 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3357 temp = LSBase;
3358 LOADSMULT (instr, temp, temp + LSMNumRegs);
3359 break;
3360
3361 case 0x90: /* Store, No WriteBack, Pre Dec. */
3362 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
3363 break;
3364
3365 case 0x91: /* Load, No WriteBack, Pre Dec. */
3366 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
3367 break;
3368
3369 case 0x92: /* Store, WriteBack, Pre Dec. */
3370 temp = LSBase - LSMNumRegs;
3371 STOREMULT (instr, temp, temp);
3372 break;
3373
3374 case 0x93: /* Load, WriteBack, Pre Dec. */
3375 temp = LSBase - LSMNumRegs;
3376 LOADMULT (instr, temp, temp);
3377 break;
3378
3379 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3380 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
3381 break;
3382
3383 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3384 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
3385 break;
3386
3387 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3388 temp = LSBase - LSMNumRegs;
3389 STORESMULT (instr, temp, temp);
3390 break;
3391
3392 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3393 temp = LSBase - LSMNumRegs;
3394 LOADSMULT (instr, temp, temp);
3395 break;
3396
3397 case 0x98: /* Store, No WriteBack, Pre Inc. */
3398 STOREMULT (instr, LSBase + 4L, 0L);
3399 break;
3400
3401 case 0x99: /* Load, No WriteBack, Pre Inc. */
3402 LOADMULT (instr, LSBase + 4L, 0L);
3403 break;
3404
3405 case 0x9a: /* Store, WriteBack, Pre Inc. */
3406 temp = LSBase;
3407 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
3408 break;
3409
3410 case 0x9b: /* Load, WriteBack, Pre Inc. */
3411 temp = LSBase;
3412 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
3413 break;
3414
3415 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3416 STORESMULT (instr, LSBase + 4L, 0L);
3417 break;
3418
3419 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3420 LOADSMULT (instr, LSBase + 4L, 0L);
3421 break;
3422
3423 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3424 temp = LSBase;
3425 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
3426 break;
3427
3428 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3429 temp = LSBase;
3430 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
3431 break;
3432
3433
3434 /* Branch forward. */
3435 case 0xa0:
3436 case 0xa1:
3437 case 0xa2:
3438 case 0xa3:
3439 case 0xa4:
3440 case 0xa5:
3441 case 0xa6:
3442 case 0xa7:
3443 state->Reg[15] = pc + 8 + POSBRANCH;
3444 FLUSHPIPE;
3445 break;
3446
3447
3448 /* Branch backward. */
3449 case 0xa8:
3450 case 0xa9:
3451 case 0xaa:
3452 case 0xab:
3453 case 0xac:
3454 case 0xad:
3455 case 0xae:
3456 case 0xaf:
3457 state->Reg[15] = pc + 8 + NEGBRANCH;
3458 FLUSHPIPE;
3459 break;
3460
3461
3462 /* Branch and Link forward. */
3463 case 0xb0:
3464 case 0xb1:
3465 case 0xb2:
3466 case 0xb3:
3467 case 0xb4:
3468 case 0xb5:
3469 case 0xb6:
3470 case 0xb7:
3471 /* Put PC into Link. */
3472 #ifdef MODE32
3473 state->Reg[14] = pc + 4;
3474 #else
3475 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3476 #endif
3477 state->Reg[15] = pc + 8 + POSBRANCH;
3478 FLUSHPIPE;
3479 break;
3480
3481
3482 /* Branch and Link backward. */
3483 case 0xb8:
3484 case 0xb9:
3485 case 0xba:
3486 case 0xbb:
3487 case 0xbc:
3488 case 0xbd:
3489 case 0xbe:
3490 case 0xbf:
3491 /* Put PC into Link. */
3492 #ifdef MODE32
3493 state->Reg[14] = pc + 4;
3494 #else
3495 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3496 #endif
3497 state->Reg[15] = pc + 8 + NEGBRANCH;
3498 FLUSHPIPE;
3499 break;
3500
3501
3502 /* Co-Processor Data Transfers. */
3503 case 0xc4:
3504 if (state->is_v5)
3505 {
3506 /* Reading from R15 is UNPREDICTABLE. */
3507 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3508 ARMul_UndefInstr (state, instr);
3509 /* Is access to coprocessor 0 allowed ? */
3510 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3511 ARMul_UndefInstr (state, instr);
3512 /* Special treatment for XScale coprocessors. */
3513 else if (state->is_XScale)
3514 {
3515 /* Only opcode 0 is supported. */
3516 if (BITS (4, 7) != 0x00)
3517 ARMul_UndefInstr (state, instr);
3518 /* Only coporcessor 0 is supported. */
3519 else if (CPNum != 0x00)
3520 ARMul_UndefInstr (state, instr);
3521 /* Only accumulator 0 is supported. */
3522 else if (BITS (0, 3) != 0x00)
3523 ARMul_UndefInstr (state, instr);
3524 else
3525 {
3526 /* XScale MAR insn. Move two registers into accumulator. */
3527 state->Accumulator = state->Reg[BITS (12, 15)];
3528 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
3529 }
3530 }
3531 else
3532 /* FIXME: Not sure what to do for other v5 processors. */
3533 ARMul_UndefInstr (state, instr);
3534 break;
3535 }
3536 /* Drop through. */
3537
3538 case 0xc0: /* Store , No WriteBack , Post Dec. */
3539 ARMul_STC (state, instr, LHS);
3540 break;
3541
3542 case 0xc5:
3543 if (state->is_v5)
3544 {
3545 /* Writes to R15 are UNPREDICATABLE. */
3546 if (DESTReg == 15 || LHSReg == 15)
3547 ARMul_UndefInstr (state, instr);
3548 /* Is access to the coprocessor allowed ? */
3549 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3550 ARMul_UndefInstr (state, instr);
3551 /* Special handling for XScale coprcoessors. */
3552 else if (state->is_XScale)
3553 {
3554 /* Only opcode 0 is supported. */
3555 if (BITS (4, 7) != 0x00)
3556 ARMul_UndefInstr (state, instr);
3557 /* Only coprocessor 0 is supported. */
3558 else if (CPNum != 0x00)
3559 ARMul_UndefInstr (state, instr);
3560 /* Only accumulator 0 is supported. */
3561 else if (BITS (0, 3) != 0x00)
3562 ARMul_UndefInstr (state, instr);
3563 else
3564 {
3565 /* XScale MRA insn. Move accumulator into two registers. */
3566 ARMword t1 = (state->Accumulator >> 32) & 255;
3567
3568 if (t1 & 128)
3569 t1 -= 256;
3570
3571 state->Reg[BITS (12, 15)] = state->Accumulator;
3572 state->Reg[BITS (16, 19)] = t1;
3573 break;
3574 }
3575 }
3576 else
3577 /* FIXME: Not sure what to do for other v5 processors. */
3578 ARMul_UndefInstr (state, instr);
3579 break;
3580 }
3581 /* Drop through. */
3582
3583 case 0xc1: /* Load , No WriteBack , Post Dec. */
3584 ARMul_LDC (state, instr, LHS);
3585 break;
3586
3587 case 0xc2:
3588 case 0xc6: /* Store , WriteBack , Post Dec. */
3589 lhs = LHS;
3590 state->Base = lhs - LSCOff;
3591 ARMul_STC (state, instr, lhs);
3592 break;
3593
3594 case 0xc3:
3595 case 0xc7: /* Load , WriteBack , Post Dec. */
3596 lhs = LHS;
3597 state->Base = lhs - LSCOff;
3598 ARMul_LDC (state, instr, lhs);
3599 break;
3600
3601 case 0xc8:
3602 case 0xcc: /* Store , No WriteBack , Post Inc. */
3603 ARMul_STC (state, instr, LHS);
3604 break;
3605
3606 case 0xc9:
3607 case 0xcd: /* Load , No WriteBack , Post Inc. */
3608 ARMul_LDC (state, instr, LHS);
3609 break;
3610
3611 case 0xca:
3612 case 0xce: /* Store , WriteBack , Post Inc. */
3613 lhs = LHS;
3614 state->Base = lhs + LSCOff;
3615 ARMul_STC (state, instr, LHS);
3616 break;
3617
3618 case 0xcb:
3619 case 0xcf: /* Load , WriteBack , Post Inc. */
3620 lhs = LHS;
3621 state->Base = lhs + LSCOff;
3622 ARMul_LDC (state, instr, LHS);
3623 break;
3624
3625 case 0xd0:
3626 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3627 ARMul_STC (state, instr, LHS - LSCOff);
3628 break;
3629
3630 case 0xd1:
3631 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3632 ARMul_LDC (state, instr, LHS - LSCOff);
3633 break;
3634
3635 case 0xd2:
3636 case 0xd6: /* Store , WriteBack , Pre Dec. */
3637 lhs = LHS - LSCOff;
3638 state->Base = lhs;
3639 ARMul_STC (state, instr, lhs);
3640 break;
3641
3642 case 0xd3:
3643 case 0xd7: /* Load , WriteBack , Pre Dec. */
3644 lhs = LHS - LSCOff;
3645 state->Base = lhs;
3646 ARMul_LDC (state, instr, lhs);
3647 break;
3648
3649 case 0xd8:
3650 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3651 ARMul_STC (state, instr, LHS + LSCOff);
3652 break;
3653
3654 case 0xd9:
3655 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3656 ARMul_LDC (state, instr, LHS + LSCOff);
3657 break;
3658
3659 case 0xda:
3660 case 0xde: /* Store , WriteBack , Pre Inc. */
3661 lhs = LHS + LSCOff;
3662 state->Base = lhs;
3663 ARMul_STC (state, instr, lhs);
3664 break;
3665
3666 case 0xdb:
3667 case 0xdf: /* Load , WriteBack , Pre Inc. */
3668 lhs = LHS + LSCOff;
3669 state->Base = lhs;
3670 ARMul_LDC (state, instr, lhs);
3671 break;
3672
3673
3674 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3675
3676 case 0xe2:
3677 if (! CP_ACCESS_ALLOWED (state, CPNum))
3678 {
3679 ARMul_UndefInstr (state, instr);
3680 break;
3681 }
3682 if (state->is_XScale)
3683 switch (BITS (18, 19))
3684 {
3685 case 0x0:
3686 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3687 {
3688 /* XScale MIA instruction. Signed multiplication of
3689 two 32 bit values and addition to 40 bit accumulator. */
3690 ARMsdword Rm = state->Reg[MULLHSReg];
3691 ARMsdword Rs = state->Reg[MULACCReg];
3692
3693 if (Rm & (1 << 31))
3694 Rm -= 1ULL << 32;
3695 if (Rs & (1 << 31))
3696 Rs -= 1ULL << 32;
3697 state->Accumulator += Rm * Rs;
3698 goto donext;
3699 }
3700 break;
3701
3702 case 0x2:
3703 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3704 {
3705 /* XScale MIAPH instruction. */
3706 ARMword t1 = state->Reg[MULLHSReg] >> 16;
3707 ARMword t2 = state->Reg[MULACCReg] >> 16;
3708 ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
3709 ARMword t4 = state->Reg[MULACCReg] & 0xffff;
3710 ARMsdword t5;
3711
3712 if (t1 & (1 << 15))
3713 t1 -= 1 << 16;
3714 if (t2 & (1 << 15))
3715 t2 -= 1 << 16;
3716 if (t3 & (1 << 15))
3717 t3 -= 1 << 16;
3718 if (t4 & (1 << 15))
3719 t4 -= 1 << 16;
3720 t1 *= t2;
3721 t5 = t1;
3722 if (t5 & (1 << 31))
3723 t5 -= 1ULL << 32;
3724 state->Accumulator += t5;
3725 t3 *= t4;
3726 t5 = t3;
3727 if (t5 & (1 << 31))
3728 t5 -= 1ULL << 32;
3729 state->Accumulator += t5;
3730 goto donext;
3731 }
3732 break;
3733
3734 case 0x3:
3735 if (BITS (4, 11) == 1)
3736 {
3737 /* XScale MIAxy instruction. */
3738 ARMword t1;
3739 ARMword t2;
3740 ARMsdword t5;
3741
3742 if (BIT (17))
3743 t1 = state->Reg[MULLHSReg] >> 16;
3744 else
3745 t1 = state->Reg[MULLHSReg] & 0xffff;
3746
3747 if (BIT (16))
3748 t2 = state->Reg[MULACCReg] >> 16;
3749 else
3750 t2 = state->Reg[MULACCReg] & 0xffff;
3751
3752 if (t1 & (1 << 15))
3753 t1 -= 1 << 16;
3754 if (t2 & (1 << 15))
3755 t2 -= 1 << 16;
3756 t1 *= t2;
3757 t5 = t1;
3758 if (t5 & (1 << 31))
3759 t5 -= 1ULL << 32;
3760 state->Accumulator += t5;
3761 goto donext;
3762 }
3763 break;
3764
3765 default:
3766 break;
3767 }
3768 /* Drop through. */
3769
3770 case 0xe0:
3771 case 0xe4:
3772 case 0xe6:
3773 case 0xe8:
3774 case 0xea:
3775 case 0xec:
3776 case 0xee:
3777 if (BIT (4))
3778 {
3779 /* MCR. */
3780 if (DESTReg == 15)
3781 {
3782 UNDEF_MCRPC;
3783 #ifdef MODE32
3784 ARMul_MCR (state, instr, state->Reg[15] + isize);
3785 #else
3786 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
3787 ((state->Reg[15] + isize) & R15PCBITS));
3788 #endif
3789 }
3790 else
3791 ARMul_MCR (state, instr, DEST);
3792 }
3793 else
3794 /* CDP Part 1. */
3795 ARMul_CDP (state, instr);
3796 break;
3797
3798
3799 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3800 case 0xe1:
3801 case 0xe3:
3802 case 0xe5:
3803 case 0xe7:
3804 case 0xe9:
3805 case 0xeb:
3806 case 0xed:
3807 case 0xef:
3808 if (BIT (4))
3809 {
3810 /* MRC */
3811 temp = ARMul_MRC (state, instr);
3812 if (DESTReg == 15)
3813 {
3814 ASSIGNN ((temp & NBIT) != 0);
3815 ASSIGNZ ((temp & ZBIT) != 0);
3816 ASSIGNC ((temp & CBIT) != 0);
3817 ASSIGNV ((temp & VBIT) != 0);
3818 }
3819 else
3820 DEST = temp;
3821 }
3822 else
3823 /* CDP Part 2. */
3824 ARMul_CDP (state, instr);
3825 break;
3826
3827
3828 /* SWI instruction. */
3829 case 0xf0:
3830 case 0xf1:
3831 case 0xf2:
3832 case 0xf3:
3833 case 0xf4:
3834 case 0xf5:
3835 case 0xf6:
3836 case 0xf7:
3837 case 0xf8:
3838 case 0xf9:
3839 case 0xfa:
3840 case 0xfb:
3841 case 0xfc:
3842 case 0xfd:
3843 case 0xfe:
3844 case 0xff:
3845 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
3846 {
3847 /* A prefetch abort. */
3848 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
3849 ARMul_Abort (state, ARMul_PrefetchAbortV);
3850 break;
3851 }
3852
3853 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
3854 ARMul_Abort (state, ARMul_SWIV);
3855
3856 break;
3857 }
3858 }
3859
3860 #ifdef MODET
3861 donext:
3862 #endif
3863
3864 #ifdef NEED_UI_LOOP_HOOK
3865 if (deprecated_ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
3866 {
3867 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
3868 deprecated_ui_loop_hook (0);
3869 }
3870 #endif /* NEED_UI_LOOP_HOOK */
3871
3872 if (state->Emulate == ONCE)
3873 state->Emulate = STOP;
3874 /* If we have changed mode, allow the PC to advance before stopping. */
3875 else if (state->Emulate == CHANGEMODE)
3876 continue;
3877 else if (state->Emulate != RUN)
3878 break;
3879 }
3880 while (!stop_simulator);
3881
3882 state->decoded = decoded;
3883 state->loaded = loaded;
3884 state->pc = pc;
3885
3886 return pc;
3887 }
3888
3889 /* This routine evaluates most Data Processing register RHS's with the S
3890 bit clear. It is intended to be called from the macro DPRegRHS, which
3891 filters the common case of an unshifted register with in line code. */
3892
3893 static ARMword
3894 GetDPRegRHS (ARMul_State * state, ARMword instr)
3895 {
3896 ARMword shamt, base;
3897
3898 base = RHSReg;
3899 if (BIT (4))
3900 {
3901 /* Shift amount in a register. */
3902 UNDEF_Shift;
3903 INCPC;
3904 #ifndef MODE32
3905 if (base == 15)
3906 base = ECC | ER15INT | R15PC | EMODE;
3907 else
3908 #endif
3909 base = state->Reg[base];
3910 ARMul_Icycles (state, 1, 0L);
3911 shamt = state->Reg[BITS (8, 11)] & 0xff;
3912 switch ((int) BITS (5, 6))
3913 {
3914 case LSL:
3915 if (shamt == 0)
3916 return (base);
3917 else if (shamt >= 32)
3918 return (0);
3919 else
3920 return (base << shamt);
3921 case LSR:
3922 if (shamt == 0)
3923 return (base);
3924 else if (shamt >= 32)
3925 return (0);
3926 else
3927 return (base >> shamt);
3928 case ASR:
3929 if (shamt == 0)
3930 return (base);
3931 else if (shamt >= 32)
3932 return ((ARMword) ((ARMsword) base >> 31L));
3933 else
3934 return ((ARMword) ((ARMsword) base >> (int) shamt));
3935 case ROR:
3936 shamt &= 0x1f;
3937 if (shamt == 0)
3938 return (base);
3939 else
3940 return ((base << (32 - shamt)) | (base >> shamt));
3941 }
3942 }
3943 else
3944 {
3945 /* Shift amount is a constant. */
3946 #ifndef MODE32
3947 if (base == 15)
3948 base = ECC | ER15INT | R15PC | EMODE;
3949 else
3950 #endif
3951 base = state->Reg[base];
3952 shamt = BITS (7, 11);
3953 switch ((int) BITS (5, 6))
3954 {
3955 case LSL:
3956 return (base << shamt);
3957 case LSR:
3958 if (shamt == 0)
3959 return (0);
3960 else
3961 return (base >> shamt);
3962 case ASR:
3963 if (shamt == 0)
3964 return ((ARMword) ((ARMsword) base >> 31L));
3965 else
3966 return ((ARMword) ((ARMsword) base >> (int) shamt));
3967 case ROR:
3968 if (shamt == 0)
3969 /* It's an RRX. */
3970 return ((base >> 1) | (CFLAG << 31));
3971 else
3972 return ((base << (32 - shamt)) | (base >> shamt));
3973 }
3974 }
3975
3976 return 0;
3977 }
3978
3979 /* This routine evaluates most Logical Data Processing register RHS's
3980 with the S bit set. It is intended to be called from the macro
3981 DPSRegRHS, which filters the common case of an unshifted register
3982 with in line code. */
3983
3984 static ARMword
3985 GetDPSRegRHS (ARMul_State * state, ARMword instr)
3986 {
3987 ARMword shamt, base;
3988
3989 base = RHSReg;
3990 if (BIT (4))
3991 {
3992 /* Shift amount in a register. */
3993 UNDEF_Shift;
3994 INCPC;
3995 #ifndef MODE32
3996 if (base == 15)
3997 base = ECC | ER15INT | R15PC | EMODE;
3998 else
3999 #endif
4000 base = state->Reg[base];
4001 ARMul_Icycles (state, 1, 0L);
4002 shamt = state->Reg[BITS (8, 11)] & 0xff;
4003 switch ((int) BITS (5, 6))
4004 {
4005 case LSL:
4006 if (shamt == 0)
4007 return (base);
4008 else if (shamt == 32)
4009 {
4010 ASSIGNC (base & 1);
4011 return (0);
4012 }
4013 else if (shamt > 32)
4014 {
4015 CLEARC;
4016 return (0);
4017 }
4018 else
4019 {
4020 ASSIGNC ((base >> (32 - shamt)) & 1);
4021 return (base << shamt);
4022 }
4023 case LSR:
4024 if (shamt == 0)
4025 return (base);
4026 else if (shamt == 32)
4027 {
4028 ASSIGNC (base >> 31);
4029 return (0);
4030 }
4031 else if (shamt > 32)
4032 {
4033 CLEARC;
4034 return (0);
4035 }
4036 else
4037 {
4038 ASSIGNC ((base >> (shamt - 1)) & 1);
4039 return (base >> shamt);
4040 }
4041 case ASR:
4042 if (shamt == 0)
4043 return (base);
4044 else if (shamt >= 32)
4045 {
4046 ASSIGNC (base >> 31L);
4047 return ((ARMword) ((ARMsword) base >> 31L));
4048 }
4049 else
4050 {
4051 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
4052 return ((ARMword) ((ARMsword) base >> (int) shamt));
4053 }
4054 case ROR:
4055 if (shamt == 0)
4056 return (base);
4057 shamt &= 0x1f;
4058 if (shamt == 0)
4059 {
4060 ASSIGNC (base >> 31);
4061 return (base);
4062 }
4063 else
4064 {
4065 ASSIGNC ((base >> (shamt - 1)) & 1);
4066 return ((base << (32 - shamt)) | (base >> shamt));
4067 }
4068 }
4069 }
4070 else
4071 {
4072 /* Shift amount is a constant. */
4073 #ifndef MODE32
4074 if (base == 15)
4075 base = ECC | ER15INT | R15PC | EMODE;
4076 else
4077 #endif
4078 base = state->Reg[base];
4079 shamt = BITS (7, 11);
4080
4081 switch ((int) BITS (5, 6))
4082 {
4083 case LSL:
4084 ASSIGNC ((base >> (32 - shamt)) & 1);
4085 return (base << shamt);
4086 case LSR:
4087 if (shamt == 0)
4088 {
4089 ASSIGNC (base >> 31);
4090 return (0);
4091 }
4092 else
4093 {
4094 ASSIGNC ((base >> (shamt - 1)) & 1);
4095 return (base >> shamt);
4096 }
4097 case ASR:
4098 if (shamt == 0)
4099 {
4100 ASSIGNC (base >> 31L);
4101 return ((ARMword) ((ARMsword) base >> 31L));
4102 }
4103 else
4104 {
4105 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
4106 return ((ARMword) ((ARMsword) base >> (int) shamt));
4107 }
4108 case ROR:
4109 if (shamt == 0)
4110 {
4111 /* It's an RRX. */
4112 shamt = CFLAG;
4113 ASSIGNC (base & 1);
4114 return ((base >> 1) | (shamt << 31));
4115 }
4116 else
4117 {
4118 ASSIGNC ((base >> (shamt - 1)) & 1);
4119 return ((base << (32 - shamt)) | (base >> shamt));
4120 }
4121 }
4122 }
4123
4124 return 0;
4125 }
4126
4127 /* This routine handles writes to register 15 when the S bit is not set. */
4128
4129 static void
4130 WriteR15 (ARMul_State * state, ARMword src)
4131 {
4132 /* The ARM documentation states that the two least significant bits
4133 are discarded when setting PC, except in the cases handled by
4134 WriteR15Branch() below. It's probably an oversight: in THUMB
4135 mode, the second least significant bit should probably not be
4136 discarded. */
4137 #ifdef MODET
4138 if (TFLAG)
4139 src &= 0xfffffffe;
4140 else
4141 #endif
4142 src &= 0xfffffffc;
4143
4144 #ifdef MODE32
4145 state->Reg[15] = src & PCBITS;
4146 #else
4147 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
4148 ARMul_R15Altered (state);
4149 #endif
4150
4151 FLUSHPIPE;
4152 }
4153
4154 /* This routine handles writes to register 15 when the S bit is set. */
4155
4156 static void
4157 WriteSR15 (ARMul_State * state, ARMword src)
4158 {
4159 #ifdef MODE32
4160 if (state->Bank > 0)
4161 {
4162 state->Cpsr = state->Spsr[state->Bank];
4163 ARMul_CPSRAltered (state);
4164 }
4165 #ifdef MODET
4166 if (TFLAG)
4167 src &= 0xfffffffe;
4168 else
4169 #endif
4170 src &= 0xfffffffc;
4171 state->Reg[15] = src & PCBITS;
4172 #else
4173 #ifdef MODET
4174 if (TFLAG)
4175 /* ARMul_R15Altered would have to support it. */
4176 abort ();
4177 else
4178 #endif
4179 src &= 0xfffffffc;
4180
4181 if (state->Bank == USERBANK)
4182 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
4183 else
4184 state->Reg[15] = src;
4185
4186 ARMul_R15Altered (state);
4187 #endif
4188 FLUSHPIPE;
4189 }
4190
4191 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
4192 will switch to Thumb mode if the least significant bit is set. */
4193
4194 static void
4195 WriteR15Branch (ARMul_State * state, ARMword src)
4196 {
4197 #ifdef MODET
4198 if (src & 1)
4199 {
4200 /* Thumb bit. */
4201 SETT;
4202 state->Reg[15] = src & 0xfffffffe;
4203 }
4204 else
4205 {
4206 CLEART;
4207 state->Reg[15] = src & 0xfffffffc;
4208 }
4209 FLUSHPIPE;
4210 #else
4211 WriteR15 (state, src);
4212 #endif
4213 }
4214
4215 /* This routine evaluates most Load and Store register RHS's. It is
4216 intended to be called from the macro LSRegRHS, which filters the
4217 common case of an unshifted register with in line code. */
4218
4219 static ARMword
4220 GetLSRegRHS (ARMul_State * state, ARMword instr)
4221 {
4222 ARMword shamt, base;
4223
4224 base = RHSReg;
4225 #ifndef MODE32
4226 if (base == 15)
4227 /* Now forbidden, but ... */
4228 base = ECC | ER15INT | R15PC | EMODE;
4229 else
4230 #endif
4231 base = state->Reg[base];
4232
4233 shamt = BITS (7, 11);
4234 switch ((int) BITS (5, 6))
4235 {
4236 case LSL:
4237 return (base << shamt);
4238 case LSR:
4239 if (shamt == 0)
4240 return (0);
4241 else
4242 return (base >> shamt);
4243 case ASR:
4244 if (shamt == 0)
4245 return ((ARMword) ((ARMsword) base >> 31L));
4246 else
4247 return ((ARMword) ((ARMsword) base >> (int) shamt));
4248 case ROR:
4249 if (shamt == 0)
4250 /* It's an RRX. */
4251 return ((base >> 1) | (CFLAG << 31));
4252 else
4253 return ((base << (32 - shamt)) | (base >> shamt));
4254 default:
4255 break;
4256 }
4257 return 0;
4258 }
4259
4260 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
4261
4262 static ARMword
4263 GetLS7RHS (ARMul_State * state, ARMword instr)
4264 {
4265 if (BIT (22) == 0)
4266 {
4267 /* Register. */
4268 #ifndef MODE32
4269 if (RHSReg == 15)
4270 /* Now forbidden, but ... */
4271 return ECC | ER15INT | R15PC | EMODE;
4272 #endif
4273 return state->Reg[RHSReg];
4274 }
4275
4276 /* Immediate. */
4277 return BITS (0, 3) | (BITS (8, 11) << 4);
4278 }
4279
4280 /* This function does the work of loading a word for a LDR instruction. */
4281
4282 static unsigned
4283 LoadWord (ARMul_State * state, ARMword instr, ARMword address)
4284 {
4285 ARMword dest;
4286
4287 BUSUSEDINCPCS;
4288 #ifndef MODE32
4289 if (ADDREXCEPT (address))
4290 INTERNALABORT (address);
4291 #endif
4292
4293 dest = ARMul_LoadWordN (state, address);
4294
4295 if (state->Aborted)
4296 {
4297 TAKEABORT;
4298 return state->lateabtSig;
4299 }
4300 if (address & 3)
4301 dest = ARMul_Align (state, address, dest);
4302 WRITEDESTB (dest);
4303 ARMul_Icycles (state, 1, 0L);
4304
4305 return (DESTReg != LHSReg);
4306 }
4307
4308 #ifdef MODET
4309 /* This function does the work of loading a halfword. */
4310
4311 static unsigned
4312 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
4313 int signextend)
4314 {
4315 ARMword dest;
4316
4317 BUSUSEDINCPCS;
4318 #ifndef MODE32
4319 if (ADDREXCEPT (address))
4320 INTERNALABORT (address);
4321 #endif
4322 dest = ARMul_LoadHalfWord (state, address);
4323 if (state->Aborted)
4324 {
4325 TAKEABORT;
4326 return state->lateabtSig;
4327 }
4328 UNDEF_LSRBPC;
4329 if (signextend)
4330 if (dest & 1 << (16 - 1))
4331 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
4332
4333 WRITEDEST (dest);
4334 ARMul_Icycles (state, 1, 0L);
4335 return (DESTReg != LHSReg);
4336 }
4337
4338 #endif /* MODET */
4339
4340 /* This function does the work of loading a byte for a LDRB instruction. */
4341
4342 static unsigned
4343 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
4344 {
4345 ARMword dest;
4346
4347 BUSUSEDINCPCS;
4348 #ifndef MODE32
4349 if (ADDREXCEPT (address))
4350 INTERNALABORT (address);
4351 #endif
4352 dest = ARMul_LoadByte (state, address);
4353 if (state->Aborted)
4354 {
4355 TAKEABORT;
4356 return state->lateabtSig;
4357 }
4358 UNDEF_LSRBPC;
4359 if (signextend)
4360 if (dest & 1 << (8 - 1))
4361 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
4362
4363 WRITEDEST (dest);
4364 ARMul_Icycles (state, 1, 0L);
4365
4366 return (DESTReg != LHSReg);
4367 }
4368
4369 /* This function does the work of loading two words for a LDRD instruction. */
4370
4371 static void
4372 Handle_Load_Double (ARMul_State * state, ARMword instr)
4373 {
4374 ARMword dest_reg;
4375 ARMword addr_reg;
4376 ARMword write_back = BIT (21);
4377 ARMword immediate = BIT (22);
4378 ARMword add_to_base = BIT (23);
4379 ARMword pre_indexed = BIT (24);
4380 ARMword offset;
4381 ARMword addr;
4382 ARMword sum;
4383 ARMword base;
4384 ARMword value1;
4385 ARMword value2;
4386
4387 BUSUSEDINCPCS;
4388
4389 /* If the writeback bit is set, the pre-index bit must be clear. */
4390 if (write_back && ! pre_indexed)
4391 {
4392 ARMul_UndefInstr (state, instr);
4393 return;
4394 }
4395
4396 /* Extract the base address register. */
4397 addr_reg = LHSReg;
4398
4399 /* Extract the destination register and check it. */
4400 dest_reg = DESTReg;
4401
4402 /* Destination register must be even. */
4403 if ((dest_reg & 1)
4404 /* Destination register cannot be LR. */
4405 || (dest_reg == 14))
4406 {
4407 ARMul_UndefInstr (state, instr);
4408 return;
4409 }
4410
4411 /* Compute the base address. */
4412 base = state->Reg[addr_reg];
4413
4414 /* Compute the offset. */
4415 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4416
4417 /* Compute the sum of the two. */
4418 if (add_to_base)
4419 sum = base + offset;
4420 else
4421 sum = base - offset;
4422
4423 /* If this is a pre-indexed mode use the sum. */
4424 if (pre_indexed)
4425 addr = sum;
4426 else
4427 addr = base;
4428
4429 /* The address must be aligned on a 8 byte boundary. */
4430 if (addr & 0x7)
4431 {
4432 #ifdef ABORTS
4433 ARMul_DATAABORT (addr);
4434 #else
4435 ARMul_UndefInstr (state, instr);
4436 #endif
4437 return;
4438 }
4439
4440 /* For pre indexed or post indexed addressing modes,
4441 check that the destination registers do not overlap
4442 the address registers. */
4443 if ((! pre_indexed || write_back)
4444 && ( addr_reg == dest_reg
4445 || addr_reg == dest_reg + 1))
4446 {
4447 ARMul_UndefInstr (state, instr);
4448 return;
4449 }
4450
4451 /* Load the words. */
4452 value1 = ARMul_LoadWordN (state, addr);
4453 value2 = ARMul_LoadWordN (state, addr + 4);
4454
4455 /* Check for data aborts. */
4456 if (state->Aborted)
4457 {
4458 TAKEABORT;
4459 return;
4460 }
4461
4462 ARMul_Icycles (state, 2, 0L);
4463
4464 /* Store the values. */
4465 state->Reg[dest_reg] = value1;
4466 state->Reg[dest_reg + 1] = value2;
4467
4468 /* Do the post addressing and writeback. */
4469 if (! pre_indexed)
4470 addr = sum;
4471
4472 if (! pre_indexed || write_back)
4473 state->Reg[addr_reg] = addr;
4474 }
4475
4476 /* This function does the work of storing two words for a STRD instruction. */
4477
4478 static void
4479 Handle_Store_Double (ARMul_State * state, ARMword instr)
4480 {
4481 ARMword src_reg;
4482 ARMword addr_reg;
4483 ARMword write_back = BIT (21);
4484 ARMword immediate = BIT (22);
4485 ARMword add_to_base = BIT (23);
4486 ARMword pre_indexed = BIT (24);
4487 ARMword offset;
4488 ARMword addr;
4489 ARMword sum;
4490 ARMword base;
4491
4492 BUSUSEDINCPCS;
4493
4494 /* If the writeback bit is set, the pre-index bit must be clear. */
4495 if (write_back && ! pre_indexed)
4496 {
4497 ARMul_UndefInstr (state, instr);
4498 return;
4499 }
4500
4501 /* Extract the base address register. */
4502 addr_reg = LHSReg;
4503
4504 /* Base register cannot be PC. */
4505 if (addr_reg == 15)
4506 {
4507 ARMul_UndefInstr (state, instr);
4508 return;
4509 }
4510
4511 /* Extract the source register. */
4512 src_reg = DESTReg;
4513
4514 /* Source register must be even. */
4515 if (src_reg & 1)
4516 {
4517 ARMul_UndefInstr (state, instr);
4518 return;
4519 }
4520
4521 /* Compute the base address. */
4522 base = state->Reg[addr_reg];
4523
4524 /* Compute the offset. */
4525 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4526
4527 /* Compute the sum of the two. */
4528 if (add_to_base)
4529 sum = base + offset;
4530 else
4531 sum = base - offset;
4532
4533 /* If this is a pre-indexed mode use the sum. */
4534 if (pre_indexed)
4535 addr = sum;
4536 else
4537 addr = base;
4538
4539 /* The address must be aligned on a 8 byte boundary. */
4540 if (addr & 0x7)
4541 {
4542 #ifdef ABORTS
4543 ARMul_DATAABORT (addr);
4544 #else
4545 ARMul_UndefInstr (state, instr);
4546 #endif
4547 return;
4548 }
4549
4550 /* For pre indexed or post indexed addressing modes,
4551 check that the destination registers do not overlap
4552 the address registers. */
4553 if ((! pre_indexed || write_back)
4554 && ( addr_reg == src_reg
4555 || addr_reg == src_reg + 1))
4556 {
4557 ARMul_UndefInstr (state, instr);
4558 return;
4559 }
4560
4561 /* Load the words. */
4562 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
4563 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
4564
4565 if (state->Aborted)
4566 {
4567 TAKEABORT;
4568 return;
4569 }
4570
4571 /* Do the post addressing and writeback. */
4572 if (! pre_indexed)
4573 addr = sum;
4574
4575 if (! pre_indexed || write_back)
4576 state->Reg[addr_reg] = addr;
4577 }
4578
4579 /* This function does the work of storing a word from a STR instruction. */
4580
4581 static unsigned
4582 StoreWord (ARMul_State * state, ARMword instr, ARMword address)
4583 {
4584 BUSUSEDINCPCN;
4585 #ifndef MODE32
4586 if (DESTReg == 15)
4587 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4588 #endif
4589 #ifdef MODE32
4590 ARMul_StoreWordN (state, address, DEST);
4591 #else
4592 if (VECTORACCESS (address) || ADDREXCEPT (address))
4593 {
4594 INTERNALABORT (address);
4595 (void) ARMul_LoadWordN (state, address);
4596 }
4597 else
4598 ARMul_StoreWordN (state, address, DEST);
4599 #endif
4600 if (state->Aborted)
4601 {
4602 TAKEABORT;
4603 return state->lateabtSig;
4604 }
4605 return TRUE;
4606 }
4607
4608 #ifdef MODET
4609 /* This function does the work of storing a byte for a STRH instruction. */
4610
4611 static unsigned
4612 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
4613 {
4614 BUSUSEDINCPCN;
4615
4616 #ifndef MODE32
4617 if (DESTReg == 15)
4618 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4619 #endif
4620
4621 #ifdef MODE32
4622 ARMul_StoreHalfWord (state, address, DEST);
4623 #else
4624 if (VECTORACCESS (address) || ADDREXCEPT (address))
4625 {
4626 INTERNALABORT (address);
4627 (void) ARMul_LoadHalfWord (state, address);
4628 }
4629 else
4630 ARMul_StoreHalfWord (state, address, DEST);
4631 #endif
4632
4633 if (state->Aborted)
4634 {
4635 TAKEABORT;
4636 return state->lateabtSig;
4637 }
4638 return TRUE;
4639 }
4640
4641 #endif /* MODET */
4642
4643 /* This function does the work of storing a byte for a STRB instruction. */
4644
4645 static unsigned
4646 StoreByte (ARMul_State * state, ARMword instr, ARMword address)
4647 {
4648 BUSUSEDINCPCN;
4649 #ifndef MODE32
4650 if (DESTReg == 15)
4651 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4652 #endif
4653 #ifdef MODE32
4654 ARMul_StoreByte (state, address, DEST);
4655 #else
4656 if (VECTORACCESS (address) || ADDREXCEPT (address))
4657 {
4658 INTERNALABORT (address);
4659 (void) ARMul_LoadByte (state, address);
4660 }
4661 else
4662 ARMul_StoreByte (state, address, DEST);
4663 #endif
4664 if (state->Aborted)
4665 {
4666 TAKEABORT;
4667 return state->lateabtSig;
4668 }
4669 UNDEF_LSRBPC;
4670 return TRUE;
4671 }
4672
4673 /* This function does the work of loading the registers listed in an LDM
4674 instruction, when the S bit is clear. The code here is always increment
4675 after, it's up to the caller to get the input address correct and to
4676 handle base register modification. */
4677
4678 static void
4679 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
4680 {
4681 ARMword dest, temp;
4682
4683 UNDEF_LSMNoRegs;
4684 UNDEF_LSMPCBase;
4685 UNDEF_LSMBaseInListWb;
4686 BUSUSEDINCPCS;
4687 #ifndef MODE32
4688 if (ADDREXCEPT (address))
4689 INTERNALABORT (address);
4690 #endif
4691 if (BIT (21) && LHSReg != 15)
4692 LSBase = WBBase;
4693
4694 /* N cycle first. */
4695 for (temp = 0; !BIT (temp); temp++)
4696 ;
4697
4698 dest = ARMul_LoadWordN (state, address);
4699
4700 if (!state->abortSig && !state->Aborted)
4701 state->Reg[temp++] = dest;
4702 else if (!state->Aborted)
4703 {
4704 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4705 state->Aborted = ARMul_DataAbortV;
4706 }
4707
4708 /* S cycles from here on. */
4709 for (; temp < 16; temp ++)
4710 if (BIT (temp))
4711 {
4712 /* Load this register. */
4713 address += 4;
4714 dest = ARMul_LoadWordS (state, address);
4715
4716 if (!state->abortSig && !state->Aborted)
4717 state->Reg[temp] = dest;
4718 else if (!state->Aborted)
4719 {
4720 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4721 state->Aborted = ARMul_DataAbortV;
4722 }
4723 }
4724
4725 if (BIT (15) && !state->Aborted)
4726 /* PC is in the reg list. */
4727 WriteR15Branch (state, PC);
4728
4729 /* To write back the final register. */
4730 ARMul_Icycles (state, 1, 0L);
4731
4732 if (state->Aborted)
4733 {
4734 if (BIT (21) && LHSReg != 15)
4735 LSBase = WBBase;
4736 TAKEABORT;
4737 }
4738 }
4739
4740 /* This function does the work of loading the registers listed in an LDM
4741 instruction, when the S bit is set. The code here is always increment
4742 after, it's up to the caller to get the input address correct and to
4743 handle base register modification. */
4744
4745 static void
4746 LoadSMult (ARMul_State * state,
4747 ARMword instr,
4748 ARMword address,
4749 ARMword WBBase)
4750 {
4751 ARMword dest, temp;
4752
4753 UNDEF_LSMNoRegs;
4754 UNDEF_LSMPCBase;
4755 UNDEF_LSMBaseInListWb;
4756
4757 BUSUSEDINCPCS;
4758
4759 #ifndef MODE32
4760 if (ADDREXCEPT (address))
4761 INTERNALABORT (address);
4762 #endif
4763
4764 if (BIT (21) && LHSReg != 15)
4765 LSBase = WBBase;
4766
4767 if (!BIT (15) && state->Bank != USERBANK)
4768 {
4769 /* Temporary reg bank switch. */
4770 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4771 UNDEF_LSMUserBankWb;
4772 }
4773
4774 /* N cycle first. */
4775 for (temp = 0; !BIT (temp); temp ++)
4776 ;
4777
4778 dest = ARMul_LoadWordN (state, address);
4779
4780 if (!state->abortSig)
4781 state->Reg[temp++] = dest;
4782 else if (!state->Aborted)
4783 {
4784 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4785 state->Aborted = ARMul_DataAbortV;
4786 }
4787
4788 /* S cycles from here on. */
4789 for (; temp < 16; temp++)
4790 if (BIT (temp))
4791 {
4792 /* Load this register. */
4793 address += 4;
4794 dest = ARMul_LoadWordS (state, address);
4795
4796 if (!state->abortSig && !state->Aborted)
4797 state->Reg[temp] = dest;
4798 else if (!state->Aborted)
4799 {
4800 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4801 state->Aborted = ARMul_DataAbortV;
4802 }
4803 }
4804
4805 if (BIT (15) && !state->Aborted)
4806 {
4807 /* PC is in the reg list. */
4808 #ifdef MODE32
4809 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4810 {
4811 state->Cpsr = GETSPSR (state->Bank);
4812 ARMul_CPSRAltered (state);
4813 }
4814
4815 WriteR15 (state, PC);
4816 #else
4817 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
4818 {
4819 /* Protect bits in user mode. */
4820 ASSIGNN ((state->Reg[15] & NBIT) != 0);
4821 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
4822 ASSIGNC ((state->Reg[15] & CBIT) != 0);
4823 ASSIGNV ((state->Reg[15] & VBIT) != 0);
4824 }
4825 else
4826 ARMul_R15Altered (state);
4827
4828 FLUSHPIPE;
4829 #endif
4830 }
4831
4832 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
4833 /* Restore the correct bank. */
4834 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4835
4836 /* To write back the final register. */
4837 ARMul_Icycles (state, 1, 0L);
4838
4839 if (state->Aborted)
4840 {
4841 if (BIT (21) && LHSReg != 15)
4842 LSBase = WBBase;
4843
4844 TAKEABORT;
4845 }
4846 }
4847
4848 /* This function does the work of storing the registers listed in an STM
4849 instruction, when the S bit is clear. The code here is always increment
4850 after, it's up to the caller to get the input address correct and to
4851 handle base register modification. */
4852
4853 static void
4854 StoreMult (ARMul_State * state,
4855 ARMword instr,
4856 ARMword address,
4857 ARMword WBBase)
4858 {
4859 ARMword temp;
4860
4861 UNDEF_LSMNoRegs;
4862 UNDEF_LSMPCBase;
4863 UNDEF_LSMBaseInListWb;
4864
4865 if (!TFLAG)
4866 /* N-cycle, increment the PC and update the NextInstr state. */
4867 BUSUSEDINCPCN;
4868
4869 #ifndef MODE32
4870 if (VECTORACCESS (address) || ADDREXCEPT (address))
4871 INTERNALABORT (address);
4872
4873 if (BIT (15))
4874 PATCHR15;
4875 #endif
4876
4877 /* N cycle first. */
4878 for (temp = 0; !BIT (temp); temp ++)
4879 ;
4880
4881 #ifdef MODE32
4882 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4883 #else
4884 if (state->Aborted)
4885 {
4886 (void) ARMul_LoadWordN (state, address);
4887
4888 /* Fake the Stores as Loads. */
4889 for (; temp < 16; temp++)
4890 if (BIT (temp))
4891 {
4892 /* Save this register. */
4893 address += 4;
4894 (void) ARMul_LoadWordS (state, address);
4895 }
4896
4897 if (BIT (21) && LHSReg != 15)
4898 LSBase = WBBase;
4899 TAKEABORT;
4900 return;
4901 }
4902 else
4903 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4904 #endif
4905
4906 if (state->abortSig && !state->Aborted)
4907 {
4908 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4909 state->Aborted = ARMul_DataAbortV;
4910 }
4911
4912 if (BIT (21) && LHSReg != 15)
4913 LSBase = WBBase;
4914
4915 /* S cycles from here on. */
4916 for (; temp < 16; temp ++)
4917 if (BIT (temp))
4918 {
4919 /* Save this register. */
4920 address += 4;
4921
4922 ARMul_StoreWordS (state, address, state->Reg[temp]);
4923
4924 if (state->abortSig && !state->Aborted)
4925 {
4926 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4927 state->Aborted = ARMul_DataAbortV;
4928 }
4929 }
4930
4931 if (state->Aborted)
4932 TAKEABORT;
4933 }
4934
4935 /* This function does the work of storing the registers listed in an STM
4936 instruction when the S bit is set. The code here is always increment
4937 after, it's up to the caller to get the input address correct and to
4938 handle base register modification. */
4939
4940 static void
4941 StoreSMult (ARMul_State * state,
4942 ARMword instr,
4943 ARMword address,
4944 ARMword WBBase)
4945 {
4946 ARMword temp;
4947
4948 UNDEF_LSMNoRegs;
4949 UNDEF_LSMPCBase;
4950 UNDEF_LSMBaseInListWb;
4951
4952 BUSUSEDINCPCN;
4953
4954 #ifndef MODE32
4955 if (VECTORACCESS (address) || ADDREXCEPT (address))
4956 INTERNALABORT (address);
4957
4958 if (BIT (15))
4959 PATCHR15;
4960 #endif
4961
4962 if (state->Bank != USERBANK)
4963 {
4964 /* Force User Bank. */
4965 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4966 UNDEF_LSMUserBankWb;
4967 }
4968
4969 for (temp = 0; !BIT (temp); temp++)
4970 ; /* N cycle first. */
4971
4972 #ifdef MODE32
4973 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4974 #else
4975 if (state->Aborted)
4976 {
4977 (void) ARMul_LoadWordN (state, address);
4978
4979 for (; temp < 16; temp++)
4980 /* Fake the Stores as Loads. */
4981 if (BIT (temp))
4982 {
4983 /* Save this register. */
4984 address += 4;
4985
4986 (void) ARMul_LoadWordS (state, address);
4987 }
4988
4989 if (BIT (21) && LHSReg != 15)
4990 LSBase = WBBase;
4991
4992 TAKEABORT;
4993 return;
4994 }
4995 else
4996 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4997 #endif
4998
4999 if (state->abortSig && !state->Aborted)
5000 {
5001 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5002 state->Aborted = ARMul_DataAbortV;
5003 }
5004
5005 /* S cycles from here on. */
5006 for (; temp < 16; temp++)
5007 if (BIT (temp))
5008 {
5009 /* Save this register. */
5010 address += 4;
5011
5012 ARMul_StoreWordS (state, address, state->Reg[temp]);
5013
5014 if (state->abortSig && !state->Aborted)
5015 {
5016 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
5017 state->Aborted = ARMul_DataAbortV;
5018 }
5019 }
5020
5021 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
5022 /* Restore the correct bank. */
5023 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
5024
5025 if (BIT (21) && LHSReg != 15)
5026 LSBase = WBBase;
5027
5028 if (state->Aborted)
5029 TAKEABORT;
5030 }
5031
5032 /* This function does the work of adding two 32bit values
5033 together, and calculating if a carry has occurred. */
5034
5035 static ARMword
5036 Add32 (ARMword a1, ARMword a2, int *carry)
5037 {
5038 ARMword result = (a1 + a2);
5039 unsigned int uresult = (unsigned int) result;
5040 unsigned int ua1 = (unsigned int) a1;
5041
5042 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5043 or (result > RdLo) then we have no carry. */
5044 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
5045 *carry = 1;
5046 else
5047 *carry = 0;
5048
5049 return result;
5050 }
5051
5052 /* This function does the work of multiplying
5053 two 32bit values to give a 64bit result. */
5054
5055 static unsigned
5056 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
5057 {
5058 /* Operand register numbers. */
5059 int nRdHi, nRdLo, nRs, nRm;
5060 ARMword RdHi = 0, RdLo = 0, Rm;
5061 /* Cycle count. */
5062 int scount;
5063
5064 nRdHi = BITS (16, 19);
5065 nRdLo = BITS (12, 15);
5066 nRs = BITS (8, 11);
5067 nRm = BITS (0, 3);
5068
5069 /* Needed to calculate the cycle count. */
5070 Rm = state->Reg[nRm];
5071
5072 /* Check for illegal operand combinations first. */
5073 if ( nRdHi != 15
5074 && nRdLo != 15
5075 && nRs != 15
5076 && nRm != 15
5077 && nRdHi != nRdLo
5078 && nRdHi != nRm
5079 && nRdLo != nRm)
5080 {
5081 /* Intermediate results. */
5082 ARMword lo, mid1, mid2, hi;
5083 int carry;
5084 ARMword Rs = state->Reg[nRs];
5085 int sign = 0;
5086
5087 if (msigned)
5088 {
5089 /* Compute sign of result and adjust operands if necessary. */
5090 sign = (Rm ^ Rs) & 0x80000000;
5091
5092 if (((ARMsword) Rm) < 0)
5093 Rm = -Rm;
5094
5095 if (((ARMsword) Rs) < 0)
5096 Rs = -Rs;
5097 }
5098
5099 /* We can split the 32x32 into four 16x16 operations. This
5100 ensures that we do not lose precision on 32bit only hosts. */
5101 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
5102 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
5103 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
5104 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
5105
5106 /* We now need to add all of these results together, taking
5107 care to propogate the carries from the additions. */
5108 RdLo = Add32 (lo, (mid1 << 16), &carry);
5109 RdHi = carry;
5110 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
5111 RdHi +=
5112 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
5113
5114 if (sign)
5115 {
5116 /* Negate result if necessary. */
5117 RdLo = ~RdLo;
5118 RdHi = ~RdHi;
5119 if (RdLo == 0xFFFFFFFF)
5120 {
5121 RdLo = 0;
5122 RdHi += 1;
5123 }
5124 else
5125 RdLo += 1;
5126 }
5127
5128 state->Reg[nRdLo] = RdLo;
5129 state->Reg[nRdHi] = RdHi;
5130 }
5131 else
5132 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
5133
5134 if (scc)
5135 /* Ensure that both RdHi and RdLo are used to compute Z,
5136 but don't let RdLo's sign bit make it to N. */
5137 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
5138
5139 /* The cycle count depends on whether the instruction is a signed or
5140 unsigned multiply, and what bits are clear in the multiplier. */
5141 if (msigned && (Rm & ((unsigned) 1 << 31)))
5142 /* Invert the bits to make the check against zero. */
5143 Rm = ~Rm;
5144
5145 if ((Rm & 0xFFFFFF00) == 0)
5146 scount = 1;
5147 else if ((Rm & 0xFFFF0000) == 0)
5148 scount = 2;
5149 else if ((Rm & 0xFF000000) == 0)
5150 scount = 3;
5151 else
5152 scount = 4;
5153
5154 return 2 + scount;
5155 }
5156
5157 /* This function does the work of multiplying two 32bit
5158 values and adding a 64bit value to give a 64bit result. */
5159
5160 static unsigned
5161 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
5162 {
5163 unsigned scount;
5164 ARMword RdLo, RdHi;
5165 int nRdHi, nRdLo;
5166 int carry = 0;
5167
5168 nRdHi = BITS (16, 19);
5169 nRdLo = BITS (12, 15);
5170
5171 RdHi = state->Reg[nRdHi];
5172 RdLo = state->Reg[nRdLo];
5173
5174 scount = Multiply64 (state, instr, msigned, LDEFAULT);
5175
5176 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
5177 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
5178
5179 state->Reg[nRdLo] = RdLo;
5180 state->Reg[nRdHi] = RdHi;
5181
5182 if (scc)
5183 /* Ensure that both RdHi and RdLo are used to compute Z,
5184 but don't let RdLo's sign bit make it to N. */
5185 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
5186
5187 /* Extra cycle for addition. */
5188 return scount + 1;
5189 }
This page took 0.136269 seconds and 4 git commands to generate.