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