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