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