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