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>.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>. */
23 static ARMword
GetDPRegRHS (ARMul_State
*, ARMword
);
24 static ARMword
GetDPSRegRHS (ARMul_State
*, ARMword
);
25 static void WriteR15 (ARMul_State
*, ARMword
);
26 static void WriteSR15 (ARMul_State
*, ARMword
);
27 static void WriteR15Branch (ARMul_State
*, ARMword
);
28 static ARMword
GetLSRegRHS (ARMul_State
*, ARMword
);
29 static ARMword
GetLS7RHS (ARMul_State
*, ARMword
);
30 static unsigned LoadWord (ARMul_State
*, ARMword
, ARMword
);
31 static unsigned LoadHalfWord (ARMul_State
*, ARMword
, ARMword
, int);
32 static unsigned LoadByte (ARMul_State
*, ARMword
, ARMword
, int);
33 static unsigned StoreWord (ARMul_State
*, ARMword
, ARMword
);
34 static unsigned StoreHalfWord (ARMul_State
*, ARMword
, ARMword
);
35 static unsigned StoreByte (ARMul_State
*, ARMword
, ARMword
);
36 static void LoadMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
37 static void StoreMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
38 static void LoadSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
39 static void StoreSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
40 static unsigned Multiply64 (ARMul_State
*, ARMword
, int, int);
41 static unsigned MultiplyAdd64 (ARMul_State
*, ARMword
, int, int);
42 static void Handle_Load_Double (ARMul_State
*, ARMword
);
43 static void Handle_Store_Double (ARMul_State
*, ARMword
);
45 #define LUNSIGNED (0) /* unsigned operation */
46 #define LSIGNED (1) /* signed operation */
47 #define LDEFAULT (0) /* default : do nothing */
48 #define LSCC (1) /* set condition codes on result */
50 #ifdef NEED_UI_LOOP_HOOK
51 /* How often to run the ui_loop update, when in use. */
52 #define UI_LOOP_POLL_INTERVAL 0x32000
54 /* Counter for the ui_loop_hook update. */
55 static long ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
57 /* Actual hook to call to run through gdb's gui event loop. */
58 extern int (*deprecated_ui_loop_hook
) (int);
59 #endif /* NEED_UI_LOOP_HOOK */
61 extern int stop_simulator
;
63 /* Short-hand macros for LDR/STR. */
65 /* Store post decrement writeback. */
68 if (StoreHalfWord (state, instr, lhs)) \
69 LSBase = lhs - GetLS7RHS (state, instr);
71 /* Store post increment writeback. */
74 if (StoreHalfWord (state, instr, lhs)) \
75 LSBase = lhs + GetLS7RHS (state, instr);
77 /* Store pre decrement. */
79 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
81 /* Store pre decrement writeback. */
82 #define SHPREDOWNWB() \
83 temp = LHS - GetLS7RHS (state, instr); \
84 if (StoreHalfWord (state, instr, temp)) \
87 /* Store pre increment. */
89 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
91 /* Store pre increment writeback. */
93 temp = LHS + GetLS7RHS (state, instr); \
94 if (StoreHalfWord (state, instr, temp)) \
97 /* Load post decrement writeback. */
98 #define LHPOSTDOWN() \
102 temp = lhs - GetLS7RHS (state, instr); \
104 switch (BITS (5, 6)) \
107 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
111 if (LoadByte (state, instr, lhs, LSIGNED)) \
115 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
118 case 0: /* SWP handled elsewhere. */ \
127 /* Load post increment writeback. */
132 temp = lhs + GetLS7RHS (state, instr); \
134 switch (BITS (5, 6)) \
137 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
141 if (LoadByte (state, instr, lhs, LSIGNED)) \
145 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
148 case 0: /* SWP handled elsewhere. */ \
157 /* Load pre decrement. */
158 #define LHPREDOWN() \
162 temp = LHS - GetLS7RHS (state, instr); \
163 switch (BITS (5, 6)) \
166 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
169 (void) LoadByte (state, instr, temp, LSIGNED); \
172 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
175 /* SWP handled elsewhere. */ \
184 /* Load pre decrement writeback. */
185 #define LHPREDOWNWB() \
189 temp = LHS - GetLS7RHS (state, instr); \
190 switch (BITS (5, 6)) \
193 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
197 if (LoadByte (state, instr, temp, LSIGNED)) \
201 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
205 /* SWP handled elsewhere. */ \
214 /* Load pre increment. */
219 temp = LHS + GetLS7RHS (state, instr); \
220 switch (BITS (5, 6)) \
223 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
226 (void) LoadByte (state, instr, temp, LSIGNED); \
229 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
232 /* SWP handled elsewhere. */ \
241 /* Load pre increment writeback. */
242 #define LHPREUPWB() \
246 temp = LHS + GetLS7RHS (state, instr); \
247 switch (BITS (5, 6)) \
250 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
254 if (LoadByte (state, instr, temp, LSIGNED)) \
258 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
262 /* SWP handled elsewhere. */ \
271 /* Attempt to emulate an ARMv6 instruction.
272 Returns non-zero upon success. */
275 handle_v6_insn (ARMul_State
* state
, ARMword instr
)
277 switch (BITS (20, 27))
280 case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
281 case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
282 case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
283 case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
284 case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
285 case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
286 case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
287 case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
288 case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
289 case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
290 case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
291 case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
292 case 0x30: printf ("Unhandled v6 insn: movw\n"); break;
293 case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
294 case 0x34: printf ("Unhandled v6 insn: movt\n"); break;
295 case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
297 case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
298 case 0x62: printf ("Unhandled v6 insn: qadd/qsub\n"); break;
299 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
300 case 0x65: printf ("Unhandled v6 insn: uadd/usub\n"); break;
301 case 0x66: printf ("Unhandled v6 insn: uqadd/uqsub\n"); break;
302 case 0x67: printf ("Unhandled v6 insn: uhadd/uhsub\n"); break;
303 case 0x68: printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); break;
304 case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
305 case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
306 case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
307 case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
308 case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
309 case 0x7a: printf ("Unhandled v6 insn: usbfx\n"); break;
310 case 0x7c: printf ("Unhandled v6 insn: bfc/bfi\n"); break;
317 switch (BITS (4, 11))
319 case 0x07: ror
= 0; break;
320 case 0x47: ror
= 8; break;
321 case 0x87: ror
= 16; break;
322 case 0xc7: ror
= 24; break;
326 printf ("Unhandled v6 insn: ssat\n");
334 if (BITS (4, 6) == 0x7)
336 printf ("Unhandled v6 insn: ssat\n");
342 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
346 if (BITS (16, 19) == 0xf)
348 state
->Reg
[BITS (12, 15)] = Rm
;
351 state
->Reg
[BITS (12, 15)] += Rm
;
360 switch (BITS (4, 11))
362 case 0x07: ror
= 0; break;
363 case 0x47: ror
= 8; break;
364 case 0x87: ror
= 16; break;
365 case 0xc7: ror
= 24; break;
368 printf ("Unhandled v6 insn: rev\n");
377 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
381 if (BITS (16, 19) == 0xf)
383 state
->Reg
[BITS (12, 15)] = Rm
;
386 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
395 switch (BITS (4, 11))
397 case 0x07: ror
= 0; break;
398 case 0x47: ror
= 8; break;
399 case 0x87: ror
= 16; break;
400 case 0xc7: ror
= 24; break;
404 printf ("Unhandled v6 insn: usat\n");
412 if (BITS (4, 6) == 0x7)
414 printf ("Unhandled v6 insn: usat\n");
420 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
422 if (BITS (16, 19) == 0xf)
424 state
->Reg
[BITS (12, 15)] = Rm
;
427 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
436 switch (BITS (4, 11))
438 case 0x07: ror
= 0; break;
439 case 0x47: ror
= 8; break;
440 case 0x87: ror
= 16; break;
441 case 0xc7: ror
= 24; break;
444 printf ("Unhandled v6 insn: revsh\n");
453 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
455 if (BITS (16, 19) == 0xf)
457 state
->Reg
[BITS (12, 15)] = Rm
;
461 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
467 case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
472 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr
);
476 /* EMULATION of ARM6. */
478 /* The PC pipeline value depends on whether ARM
479 or Thumb instructions are being executed. */
484 ARMul_Emulate32 (ARMul_State
* state
)
486 ARMul_Emulate26 (ARMul_State
* state
)
489 ARMword instr
; /* The current instruction. */
490 ARMword dest
= 0; /* Almost the DestBus. */
491 ARMword temp
; /* Ubiquitous third hand. */
492 ARMword pc
= 0; /* The address of the current instruction. */
493 ARMword lhs
; /* Almost the ABus and BBus. */
495 ARMword decoded
= 0; /* Instruction pipeline. */
498 /* Execute the next instruction. */
500 if (state
->NextInstr
< PRIMEPIPE
)
502 decoded
= state
->decoded
;
503 loaded
= state
->loaded
;
509 /* Just keep going. */
512 switch (state
->NextInstr
)
515 /* Advance the pipeline, and an S cycle. */
516 state
->Reg
[15] += isize
;
520 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
524 /* Advance the pipeline, and an N cycle. */
525 state
->Reg
[15] += isize
;
529 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
534 /* Program counter advanced, and an S cycle. */
538 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
543 /* Program counter advanced, and an N cycle. */
547 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
552 /* The program counter has been changed. */
557 state
->Reg
[15] = pc
+ (isize
* 2);
559 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
560 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
561 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
566 /* The program counter has been changed. */
571 state
->Reg
[15] = pc
+ (isize
* 2);
573 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
574 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
575 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
581 ARMul_EnvokeEvent (state
);
582 #if 0 /* Enable this for a helpful bit of debugging when tracing is needed. */
583 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
587 #if 0 /* Enable this code to help track down stack alignment bugs. */
589 static ARMword old_sp
= -1;
591 if (old_sp
!= state
->Reg
[13])
593 old_sp
= state
->Reg
[13];
594 fprintf (stderr
, "pc: %08x: SP set to %08x%s\n",
595 pc
& ~1, old_sp
, (old_sp
% 8) ? " [UNALIGNED!]" : "");
600 if (state
->Exception
)
602 /* Any exceptions ? */
603 if (state
->NresetSig
== LOW
)
605 ARMul_Abort (state
, ARMul_ResetV
);
608 else if (!state
->NfiqSig
&& !FFLAG
)
610 ARMul_Abort (state
, ARMul_FIQV
);
613 else if (!state
->NirqSig
&& !IFLAG
)
615 ARMul_Abort (state
, ARMul_IRQV
);
620 if (state
->CallDebug
> 0)
622 instr
= ARMul_Debug (state
, pc
, instr
);
623 if (state
->Emulate
< ONCE
)
625 state
->NextInstr
= RESUME
;
630 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
632 (void) fgetc (stdin
);
635 else if (state
->Emulate
< ONCE
)
637 state
->NextInstr
= RESUME
;
644 /* Provide Thumb instruction decoding. If the processor is in Thumb
645 mode, then we can simply decode the Thumb instruction, and map it
646 to the corresponding ARM instruction (by directly loading the
647 instr variable, and letting the normal ARM simulator
648 execute). There are some caveats to ensure that the correct
649 pipelined PC value is used when executing Thumb code, and also for
650 dealing with the BL instruction. */
655 /* Check if in Thumb mode. */
656 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
659 /* This is a Thumb instruction. */
660 ARMul_UndefInstr (state
, instr
);
664 /* Already processed. */
668 /* ARM instruction available. */
670 /* So continue instruction decoding. */
678 /* Check the condition codes. */
679 if ((temp
= TOPBITS (28)) == AL
)
680 /* Vile deed in the need for speed. */
683 /* Check the condition code. */
684 switch ((int) TOPBITS (28))
692 if (BITS (25, 27) == 5) /* BLX(1) */
696 state
->Reg
[14] = pc
+ 4;
698 /* Force entry into Thumb mode. */
701 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
703 dest
+= POSBRANCH
+ (BIT (24) << 1);
705 WriteR15Branch (state
, dest
);
708 else if ((instr
& 0xFC70F000) == 0xF450F000)
709 /* The PLD instruction. Ignored. */
711 else if ( ((instr
& 0xfe500f00) == 0xfc100100)
712 || ((instr
& 0xfe500f00) == 0xfc000100))
713 /* wldrw and wstrw are unconditional. */
716 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
717 ARMul_UndefInstr (state
, instr
);
746 temp
= (CFLAG
&& !ZFLAG
);
749 temp
= (!CFLAG
|| ZFLAG
);
752 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
755 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
758 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
761 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
765 /* Handle the Clock counter here. */
766 if (state
->is_XScale
)
771 ok
= state
->CPRead
[14] (state
, 0, & cp14r0
);
773 if (ok
&& (cp14r0
& ARMul_CP14_R0_ENABLE
))
775 unsigned long newcycles
, nowtime
= ARMul_Time (state
);
777 newcycles
= nowtime
- state
->LastTime
;
778 state
->LastTime
= nowtime
;
780 if (cp14r0
& ARMul_CP14_R0_CCD
)
782 if (state
->CP14R0_CCD
== -1)
783 state
->CP14R0_CCD
= newcycles
;
785 state
->CP14R0_CCD
+= newcycles
;
787 if (state
->CP14R0_CCD
>= 64)
791 while (state
->CP14R0_CCD
>= 64)
792 state
->CP14R0_CCD
-= 64, newcycles
++;
802 state
->CP14R0_CCD
= -1;
804 cp14r0
|= ARMul_CP14_R0_FLAG2
;
805 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
807 ok
= state
->CPRead
[14] (state
, 1, & cp14r1
);
809 /* Coded like this for portability. */
810 while (ok
&& newcycles
)
812 if (cp14r1
== 0xffffffff)
823 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
825 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
829 if (state
->CPRead
[13] (state
, 8, & temp
)
830 && (temp
& ARMul_CP13_R8_PMUS
))
831 ARMul_Abort (state
, ARMul_FIQV
);
833 ARMul_Abort (state
, ARMul_IRQV
);
839 /* Handle hardware instructions breakpoints here. */
840 if (state
->is_XScale
)
842 if ( (pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
843 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
845 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
846 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
850 /* Actual execution of instructions begins here. */
851 /* If the condition codes don't match, stop here. */
856 if (state
->is_XScale
)
858 if (BIT (20) == 0 && BITS (25, 27) == 0)
860 if (BITS (4, 7) == 0xD)
862 /* XScale Load Consecutive insn. */
863 ARMword temp
= GetLS7RHS (state
, instr
);
864 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
865 ARMword addr
= BIT (24) ? temp2
: LHS
;
868 ARMul_UndefInstr (state
, instr
);
870 /* Alignment violation. */
871 ARMul_Abort (state
, ARMul_DataAbortV
);
874 int wb
= BIT (21) || (! BIT (24));
876 state
->Reg
[BITS (12, 15)] =
877 ARMul_LoadWordN (state
, addr
);
878 state
->Reg
[BITS (12, 15) + 1] =
879 ARMul_LoadWordN (state
, addr
+ 4);
886 else if (BITS (4, 7) == 0xF)
888 /* XScale Store Consecutive insn. */
889 ARMword temp
= GetLS7RHS (state
, instr
);
890 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
891 ARMword addr
= BIT (24) ? temp2
: LHS
;
894 ARMul_UndefInstr (state
, instr
);
896 /* Alignment violation. */
897 ARMul_Abort (state
, ARMul_DataAbortV
);
900 ARMul_StoreWordN (state
, addr
,
901 state
->Reg
[BITS (12, 15)]);
902 ARMul_StoreWordN (state
, addr
+ 4,
903 state
->Reg
[BITS (12, 15) + 1]);
905 if (BIT (21)|| ! BIT (24))
913 if (ARMul_HandleIwmmxt (state
, instr
))
917 switch ((int) BITS (20, 27))
919 /* Data Processing Register RHS Instructions. */
921 case 0x00: /* AND reg and MUL */
923 if (BITS (4, 11) == 0xB)
925 /* STRH register offset, no write-back, down, post indexed. */
929 if (BITS (4, 7) == 0xD)
931 Handle_Load_Double (state
, instr
);
934 if (BITS (4, 7) == 0xF)
936 Handle_Store_Double (state
, instr
);
940 if (BITS (4, 7) == 9)
943 rhs
= state
->Reg
[MULRHSReg
];
944 if (MULLHSReg
== MULDESTReg
)
947 state
->Reg
[MULDESTReg
] = 0;
949 else if (MULDESTReg
!= 15)
950 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
954 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
955 if (rhs
& (1L << dest
))
958 /* Mult takes this many/2 I cycles. */
959 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
970 case 0x01: /* ANDS reg and MULS */
972 if ((BITS (4, 11) & 0xF9) == 0x9)
973 /* LDR register offset, no write-back, down, post indexed. */
975 /* Fall through to rest of decoding. */
977 if (BITS (4, 7) == 9)
980 rhs
= state
->Reg
[MULRHSReg
];
982 if (MULLHSReg
== MULDESTReg
)
985 state
->Reg
[MULDESTReg
] = 0;
989 else if (MULDESTReg
!= 15)
991 dest
= state
->Reg
[MULLHSReg
] * rhs
;
992 ARMul_NegZero (state
, dest
);
993 state
->Reg
[MULDESTReg
] = dest
;
998 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
999 if (rhs
& (1L << dest
))
1002 /* Mult takes this many/2 I cycles. */
1003 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1014 case 0x02: /* EOR reg and MLA */
1016 if (BITS (4, 11) == 0xB)
1018 /* STRH register offset, write-back, down, post indexed. */
1023 if (BITS (4, 7) == 9)
1025 rhs
= state
->Reg
[MULRHSReg
];
1026 if (MULLHSReg
== MULDESTReg
)
1029 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
1031 else if (MULDESTReg
!= 15)
1032 state
->Reg
[MULDESTReg
] =
1033 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1037 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1038 if (rhs
& (1L << dest
))
1041 /* Mult takes this many/2 I cycles. */
1042 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1052 case 0x03: /* EORS reg and MLAS */
1054 if ((BITS (4, 11) & 0xF9) == 0x9)
1055 /* LDR register offset, write-back, down, post-indexed. */
1057 /* Fall through to rest of the decoding. */
1059 if (BITS (4, 7) == 9)
1062 rhs
= state
->Reg
[MULRHSReg
];
1064 if (MULLHSReg
== MULDESTReg
)
1067 dest
= state
->Reg
[MULACCReg
];
1068 ARMul_NegZero (state
, dest
);
1069 state
->Reg
[MULDESTReg
] = dest
;
1071 else if (MULDESTReg
!= 15)
1074 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1075 ARMul_NegZero (state
, dest
);
1076 state
->Reg
[MULDESTReg
] = dest
;
1081 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1082 if (rhs
& (1L << dest
))
1085 /* Mult takes this many/2 I cycles. */
1086 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1097 case 0x04: /* SUB reg */
1099 if (BITS (4, 7) == 0xB)
1101 /* STRH immediate offset, no write-back, down, post indexed. */
1105 if (BITS (4, 7) == 0xD)
1107 Handle_Load_Double (state
, instr
);
1110 if (BITS (4, 7) == 0xF)
1112 Handle_Store_Double (state
, instr
);
1121 case 0x05: /* SUBS reg */
1123 if ((BITS (4, 7) & 0x9) == 0x9)
1124 /* LDR immediate offset, no write-back, down, post indexed. */
1126 /* Fall through to the rest of the instruction decoding. */
1132 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1134 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1135 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1145 case 0x06: /* RSB reg */
1147 if (BITS (4, 7) == 0xB)
1149 /* STRH immediate offset, write-back, down, post indexed. */
1159 case 0x07: /* RSBS reg */
1161 if ((BITS (4, 7) & 0x9) == 0x9)
1162 /* LDR immediate offset, write-back, down, post indexed. */
1164 /* Fall through to remainder of instruction decoding. */
1170 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1172 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1173 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1183 case 0x08: /* ADD reg */
1185 if (BITS (4, 11) == 0xB)
1187 /* STRH register offset, no write-back, up, post indexed. */
1191 if (BITS (4, 7) == 0xD)
1193 Handle_Load_Double (state
, instr
);
1196 if (BITS (4, 7) == 0xF)
1198 Handle_Store_Double (state
, instr
);
1203 if (BITS (4, 7) == 0x9)
1207 ARMul_Icycles (state
,
1208 Multiply64 (state
, instr
, LUNSIGNED
,
1218 case 0x09: /* ADDS reg */
1220 if ((BITS (4, 11) & 0xF9) == 0x9)
1221 /* LDR register offset, no write-back, up, post indexed. */
1223 /* Fall through to remaining instruction decoding. */
1226 if (BITS (4, 7) == 0x9)
1230 ARMul_Icycles (state
,
1231 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
1239 ASSIGNZ (dest
== 0);
1240 if ((lhs
| rhs
) >> 30)
1242 /* Possible C,V,N to set. */
1243 ASSIGNN (NEG (dest
));
1244 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1245 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1256 case 0x0a: /* ADC reg */
1258 if (BITS (4, 11) == 0xB)
1260 /* STRH register offset, write-back, up, post-indexed. */
1264 if (BITS (4, 7) == 0x9)
1268 ARMul_Icycles (state
,
1269 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1275 dest
= LHS
+ rhs
+ CFLAG
;
1279 case 0x0b: /* ADCS reg */
1281 if ((BITS (4, 11) & 0xF9) == 0x9)
1282 /* LDR register offset, write-back, up, post indexed. */
1284 /* Fall through to remaining instruction decoding. */
1285 if (BITS (4, 7) == 0x9)
1289 ARMul_Icycles (state
,
1290 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1297 dest
= lhs
+ rhs
+ CFLAG
;
1298 ASSIGNZ (dest
== 0);
1299 if ((lhs
| rhs
) >> 30)
1301 /* Possible C,V,N to set. */
1302 ASSIGNN (NEG (dest
));
1303 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1304 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1315 case 0x0c: /* SBC reg */
1317 if (BITS (4, 7) == 0xB)
1319 /* STRH immediate offset, no write-back, up post indexed. */
1323 if (BITS (4, 7) == 0xD)
1325 Handle_Load_Double (state
, instr
);
1328 if (BITS (4, 7) == 0xF)
1330 Handle_Store_Double (state
, instr
);
1333 if (BITS (4, 7) == 0x9)
1337 ARMul_Icycles (state
,
1338 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
1344 dest
= LHS
- rhs
- !CFLAG
;
1348 case 0x0d: /* SBCS reg */
1350 if ((BITS (4, 7) & 0x9) == 0x9)
1351 /* LDR immediate offset, no write-back, up, post indexed. */
1354 if (BITS (4, 7) == 0x9)
1358 ARMul_Icycles (state
,
1359 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
1366 dest
= lhs
- rhs
- !CFLAG
;
1367 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1369 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1370 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1380 case 0x0e: /* RSC reg */
1382 if (BITS (4, 7) == 0xB)
1384 /* STRH immediate offset, write-back, up, post indexed. */
1389 if (BITS (4, 7) == 0x9)
1393 ARMul_Icycles (state
,
1394 MultiplyAdd64 (state
, instr
, LSIGNED
,
1400 dest
= rhs
- LHS
- !CFLAG
;
1404 case 0x0f: /* RSCS reg */
1406 if ((BITS (4, 7) & 0x9) == 0x9)
1407 /* LDR immediate offset, write-back, up, post indexed. */
1409 /* Fall through to remaining instruction decoding. */
1411 if (BITS (4, 7) == 0x9)
1415 ARMul_Icycles (state
,
1416 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
1423 dest
= rhs
- lhs
- !CFLAG
;
1425 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1427 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1428 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1438 case 0x10: /* TST reg and MRS CPSR and SWP word. */
1441 if (BIT (4) == 0 && BIT (7) == 1)
1443 /* ElSegundo SMLAxy insn. */
1444 ARMword op1
= state
->Reg
[BITS (0, 3)];
1445 ARMword op2
= state
->Reg
[BITS (8, 11)];
1446 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1460 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
1462 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
1466 if (BITS (4, 11) == 5)
1468 /* ElSegundo QADD insn. */
1469 ARMword op1
= state
->Reg
[BITS (0, 3)];
1470 ARMword op2
= state
->Reg
[BITS (16, 19)];
1471 ARMword result
= op1
+ op2
;
1472 if (AddOverflow (op1
, op2
, result
))
1474 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1477 state
->Reg
[BITS (12, 15)] = result
;
1482 if (BITS (4, 11) == 0xB)
1484 /* STRH register offset, no write-back, down, pre indexed. */
1488 if (BITS (4, 7) == 0xD)
1490 Handle_Load_Double (state
, instr
);
1493 if (BITS (4, 7) == 0xF)
1495 Handle_Store_Double (state
, instr
);
1499 if (BITS (4, 11) == 9)
1506 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1508 INTERNALABORT (temp
);
1509 (void) ARMul_LoadWordN (state
, temp
);
1510 (void) ARMul_LoadWordN (state
, temp
);
1514 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1516 DEST
= ARMul_Align (state
, temp
, dest
);
1519 if (state
->abortSig
|| state
->Aborted
)
1522 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1525 DEST
= ECC
| EINT
| EMODE
;
1533 case 0x11: /* TSTP reg */
1535 if ((BITS (4, 11) & 0xF9) == 0x9)
1536 /* LDR register offset, no write-back, down, pre indexed. */
1538 /* Continue with remaining instruction decode. */
1544 state
->Cpsr
= GETSPSR (state
->Bank
);
1545 ARMul_CPSRAltered (state
);
1557 ARMul_NegZero (state
, dest
);
1561 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
1564 if (BITS (4, 7) == 3)
1570 temp
= (pc
+ 2) | 1;
1574 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1575 state
->Reg
[14] = temp
;
1582 if (BIT (4) == 0 && BIT (7) == 1
1583 && (BIT (5) == 0 || BITS (12, 15) == 0))
1585 /* ElSegundo SMLAWy/SMULWy insn. */
1586 ARMdword op1
= state
->Reg
[BITS (0, 3)];
1587 ARMdword op2
= state
->Reg
[BITS (8, 11)];
1592 if (op1
& 0x80000000)
1597 result
= (op1
* op2
) >> 16;
1601 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1603 if (AddOverflow (result
, Rn
, result
+ Rn
))
1607 state
->Reg
[BITS (16, 19)] = result
;
1611 if (BITS (4, 11) == 5)
1613 /* ElSegundo QSUB insn. */
1614 ARMword op1
= state
->Reg
[BITS (0, 3)];
1615 ARMword op2
= state
->Reg
[BITS (16, 19)];
1616 ARMword result
= op1
- op2
;
1618 if (SubOverflow (op1
, op2
, result
))
1620 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1624 state
->Reg
[BITS (12, 15)] = result
;
1629 if (BITS (4, 11) == 0xB)
1631 /* STRH register offset, write-back, down, pre indexed. */
1635 if (BITS (4, 27) == 0x12FFF1)
1638 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1641 if (BITS (4, 7) == 0xD)
1643 Handle_Load_Double (state
, instr
);
1646 if (BITS (4, 7) == 0xF)
1648 Handle_Store_Double (state
, instr
);
1654 if (BITS (4, 7) == 0x7)
1657 extern int SWI_vector_installed
;
1659 /* Hardware is allowed to optionally override this
1660 instruction and treat it as a breakpoint. Since
1661 this is a simulator not hardware, we take the position
1662 that if a SWI vector was not installed, then an Abort
1663 vector was probably not installed either, and so
1664 normally this instruction would be ignored, even if an
1665 Abort is generated. This is a bad thing, since GDB
1666 uses this instruction for its breakpoints (at least in
1667 Thumb mode it does). So intercept the instruction here
1668 and generate a breakpoint SWI instead. */
1669 if (! SWI_vector_installed
)
1670 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1673 /* BKPT - normally this will cause an abort, but on the
1674 XScale we must check the DCSR. */
1675 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
1676 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
1680 /* Force the next instruction to be refetched. */
1681 state
->NextInstr
= RESUME
;
1687 /* MSR reg to CPSR. */
1691 /* Don't allow TBIT to be set by MSR. */
1694 ARMul_FixCPSR (state
, instr
, temp
);
1701 case 0x13: /* TEQP reg */
1703 if ((BITS (4, 11) & 0xF9) == 0x9)
1704 /* LDR register offset, write-back, down, pre indexed. */
1706 /* Continue with remaining instruction decode. */
1712 state
->Cpsr
= GETSPSR (state
->Bank
);
1713 ARMul_CPSRAltered (state
);
1725 ARMul_NegZero (state
, dest
);
1729 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
1732 if (BIT (4) == 0 && BIT (7) == 1)
1734 /* ElSegundo SMLALxy insn. */
1735 ARMdword op1
= state
->Reg
[BITS (0, 3)];
1736 ARMdword op2
= state
->Reg
[BITS (8, 11)];
1751 dest
= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
1752 dest
|= state
->Reg
[BITS (12, 15)];
1754 state
->Reg
[BITS (12, 15)] = dest
;
1755 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1759 if (BITS (4, 11) == 5)
1761 /* ElSegundo QDADD insn. */
1762 ARMword op1
= state
->Reg
[BITS (0, 3)];
1763 ARMword op2
= state
->Reg
[BITS (16, 19)];
1764 ARMword op2d
= op2
+ op2
;
1767 if (AddOverflow (op2
, op2
, op2d
))
1770 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1773 result
= op1
+ op2d
;
1774 if (AddOverflow (op1
, op2d
, result
))
1777 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1780 state
->Reg
[BITS (12, 15)] = result
;
1785 if (BITS (4, 7) == 0xB)
1787 /* STRH immediate offset, no write-back, down, pre indexed. */
1791 if (BITS (4, 7) == 0xD)
1793 Handle_Load_Double (state
, instr
);
1796 if (BITS (4, 7) == 0xF)
1798 Handle_Store_Double (state
, instr
);
1802 if (BITS (4, 11) == 9)
1809 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1811 INTERNALABORT (temp
);
1812 (void) ARMul_LoadByte (state
, temp
);
1813 (void) ARMul_LoadByte (state
, temp
);
1817 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1818 if (state
->abortSig
|| state
->Aborted
)
1821 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1825 DEST
= GETSPSR (state
->Bank
);
1832 case 0x15: /* CMPP reg. */
1834 if ((BITS (4, 7) & 0x9) == 0x9)
1835 /* LDR immediate offset, no write-back, down, pre indexed. */
1837 /* Continue with remaining instruction decode. */
1843 state
->Cpsr
= GETSPSR (state
->Bank
);
1844 ARMul_CPSRAltered (state
);
1857 ARMul_NegZero (state
, dest
);
1858 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1860 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1861 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1871 case 0x16: /* CMN reg and MSR reg to SPSR */
1874 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1876 /* ElSegundo SMULxy insn. */
1877 ARMword op1
= state
->Reg
[BITS (0, 3)];
1878 ARMword op2
= state
->Reg
[BITS (8, 11)];
1879 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1892 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1896 if (BITS (4, 11) == 5)
1898 /* ElSegundo QDSUB insn. */
1899 ARMword op1
= state
->Reg
[BITS (0, 3)];
1900 ARMword op2
= state
->Reg
[BITS (16, 19)];
1901 ARMword op2d
= op2
+ op2
;
1904 if (AddOverflow (op2
, op2
, op2d
))
1907 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1910 result
= op1
- op2d
;
1911 if (SubOverflow (op1
, op2d
, result
))
1914 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1917 state
->Reg
[BITS (12, 15)] = result
;
1924 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1926 /* ARM5 CLZ insn. */
1927 ARMword op1
= state
->Reg
[BITS (0, 3)];
1931 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1934 state
->Reg
[BITS (12, 15)] = result
;
1939 if (BITS (4, 7) == 0xB)
1941 /* STRH immediate offset, write-back, down, pre indexed. */
1945 if (BITS (4, 7) == 0xD)
1947 Handle_Load_Double (state
, instr
);
1950 if (BITS (4, 7) == 0xF)
1952 Handle_Store_Double (state
, instr
);
1960 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1968 case 0x17: /* CMNP reg */
1970 if ((BITS (4, 7) & 0x9) == 0x9)
1971 /* LDR immediate offset, write-back, down, pre indexed. */
1973 /* Continue with remaining instruction decoding. */
1978 state
->Cpsr
= GETSPSR (state
->Bank
);
1979 ARMul_CPSRAltered (state
);
1993 ASSIGNZ (dest
== 0);
1994 if ((lhs
| rhs
) >> 30)
1996 /* Possible C,V,N to set. */
1997 ASSIGNN (NEG (dest
));
1998 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1999 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2010 case 0x18: /* ORR reg */
2012 if (BITS (4, 11) == 0xB)
2014 /* STRH register offset, no write-back, up, pre indexed. */
2018 if (BITS (4, 7) == 0xD)
2020 Handle_Load_Double (state
, instr
);
2023 if (BITS (4, 7) == 0xF)
2025 Handle_Store_Double (state
, instr
);
2034 case 0x19: /* ORRS reg */
2036 if ((BITS (4, 11) & 0xF9) == 0x9)
2037 /* LDR register offset, no write-back, up, pre indexed. */
2039 /* Continue with remaining instruction decoding. */
2046 case 0x1a: /* MOV reg */
2048 if (BITS (4, 11) == 0xB)
2050 /* STRH register offset, write-back, up, pre indexed. */
2054 if (BITS (4, 7) == 0xD)
2056 Handle_Load_Double (state
, instr
);
2059 if (BITS (4, 7) == 0xF)
2061 Handle_Store_Double (state
, instr
);
2069 case 0x1b: /* MOVS reg */
2071 if ((BITS (4, 11) & 0xF9) == 0x9)
2072 /* LDR register offset, write-back, up, pre indexed. */
2074 /* Continue with remaining instruction decoding. */
2080 case 0x1c: /* BIC reg */
2082 if (BITS (4, 7) == 0xB)
2084 /* STRH immediate offset, no write-back, up, pre indexed. */
2088 if (BITS (4, 7) == 0xD)
2090 Handle_Load_Double (state
, instr
);
2093 else if (BITS (4, 7) == 0xF)
2095 Handle_Store_Double (state
, instr
);
2104 case 0x1d: /* BICS reg */
2106 if ((BITS (4, 7) & 0x9) == 0x9)
2107 /* LDR immediate offset, no write-back, up, pre indexed. */
2109 /* Continue with instruction decoding. */
2116 case 0x1e: /* MVN reg */
2118 if (BITS (4, 7) == 0xB)
2120 /* STRH immediate offset, write-back, up, pre indexed. */
2124 if (BITS (4, 7) == 0xD)
2126 Handle_Load_Double (state
, instr
);
2129 if (BITS (4, 7) == 0xF)
2131 Handle_Store_Double (state
, instr
);
2139 case 0x1f: /* MVNS reg */
2141 if ((BITS (4, 7) & 0x9) == 0x9)
2142 /* LDR immediate offset, write-back, up, pre indexed. */
2144 /* Continue instruction decoding. */
2151 /* Data Processing Immediate RHS Instructions. */
2153 case 0x20: /* AND immed */
2154 dest
= LHS
& DPImmRHS
;
2158 case 0x21: /* ANDS immed */
2164 case 0x22: /* EOR immed */
2165 dest
= LHS
^ DPImmRHS
;
2169 case 0x23: /* EORS immed */
2175 case 0x24: /* SUB immed */
2176 dest
= LHS
- DPImmRHS
;
2180 case 0x25: /* SUBS immed */
2185 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2187 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2188 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2198 case 0x26: /* RSB immed */
2199 dest
= DPImmRHS
- LHS
;
2203 case 0x27: /* RSBS immed */
2208 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2210 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2211 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2221 case 0x28: /* ADD immed */
2222 dest
= LHS
+ DPImmRHS
;
2226 case 0x29: /* ADDS immed */
2230 ASSIGNZ (dest
== 0);
2232 if ((lhs
| rhs
) >> 30)
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
);
2248 case 0x2a: /* ADC immed */
2249 dest
= LHS
+ DPImmRHS
+ CFLAG
;
2253 case 0x2b: /* ADCS immed */
2256 dest
= lhs
+ rhs
+ CFLAG
;
2257 ASSIGNZ (dest
== 0);
2258 if ((lhs
| rhs
) >> 30)
2260 /* Possible C,V,N to set. */
2261 ASSIGNN (NEG (dest
));
2262 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2263 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2274 case 0x2c: /* SBC immed */
2275 dest
= LHS
- DPImmRHS
- !CFLAG
;
2279 case 0x2d: /* SBCS immed */
2282 dest
= lhs
- rhs
- !CFLAG
;
2283 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2285 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2286 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2296 case 0x2e: /* RSC immed */
2297 dest
= DPImmRHS
- LHS
- !CFLAG
;
2301 case 0x2f: /* RSCS immed */
2304 dest
= rhs
- lhs
- !CFLAG
;
2305 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2307 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2308 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2318 case 0x30: /* TST immed */
2322 case 0x31: /* TSTP immed */
2327 state
->Cpsr
= GETSPSR (state
->Bank
);
2328 ARMul_CPSRAltered (state
);
2330 temp
= LHS
& DPImmRHS
;
2339 ARMul_NegZero (state
, dest
);
2343 case 0x32: /* TEQ immed and MSR immed to CPSR */
2345 /* MSR immed to CPSR. */
2346 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2351 case 0x33: /* TEQP immed */
2356 state
->Cpsr
= GETSPSR (state
->Bank
);
2357 ARMul_CPSRAltered (state
);
2359 temp
= LHS
^ DPImmRHS
;
2365 DPSImmRHS
; /* TEQ immed */
2367 ARMul_NegZero (state
, dest
);
2371 case 0x34: /* CMP immed */
2375 case 0x35: /* CMPP immed */
2380 state
->Cpsr
= GETSPSR (state
->Bank
);
2381 ARMul_CPSRAltered (state
);
2383 temp
= LHS
- DPImmRHS
;
2394 ARMul_NegZero (state
, dest
);
2396 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2398 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2399 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2409 case 0x36: /* CMN immed and MSR immed to SPSR */
2411 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2416 case 0x37: /* CMNP immed. */
2421 state
->Cpsr
= GETSPSR (state
->Bank
);
2422 ARMul_CPSRAltered (state
);
2424 temp
= LHS
+ DPImmRHS
;
2435 ASSIGNZ (dest
== 0);
2436 if ((lhs
| rhs
) >> 30)
2438 /* Possible C,V,N to set. */
2439 ASSIGNN (NEG (dest
));
2440 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2441 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2452 case 0x38: /* ORR immed. */
2453 dest
= LHS
| DPImmRHS
;
2457 case 0x39: /* ORRS immed. */
2463 case 0x3a: /* MOV immed. */
2468 case 0x3b: /* MOVS immed. */
2473 case 0x3c: /* BIC immed. */
2474 dest
= LHS
& ~DPImmRHS
;
2478 case 0x3d: /* BICS immed. */
2484 case 0x3e: /* MVN immed. */
2489 case 0x3f: /* MVNS immed. */
2495 /* Single Data Transfer Immediate RHS Instructions. */
2497 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2499 if (StoreWord (state
, instr
, lhs
))
2500 LSBase
= lhs
- LSImmRHS
;
2503 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2505 if (LoadWord (state
, instr
, lhs
))
2506 LSBase
= lhs
- LSImmRHS
;
2509 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2510 UNDEF_LSRBaseEQDestWb
;
2513 temp
= lhs
- LSImmRHS
;
2514 state
->NtransSig
= LOW
;
2515 if (StoreWord (state
, instr
, lhs
))
2517 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2520 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2521 UNDEF_LSRBaseEQDestWb
;
2524 state
->NtransSig
= LOW
;
2525 if (LoadWord (state
, instr
, lhs
))
2526 LSBase
= lhs
- LSImmRHS
;
2527 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2530 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2532 if (StoreByte (state
, instr
, lhs
))
2533 LSBase
= lhs
- LSImmRHS
;
2536 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2538 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2539 LSBase
= lhs
- LSImmRHS
;
2542 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2543 UNDEF_LSRBaseEQDestWb
;
2546 state
->NtransSig
= LOW
;
2547 if (StoreByte (state
, instr
, lhs
))
2548 LSBase
= lhs
- LSImmRHS
;
2549 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2552 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2553 UNDEF_LSRBaseEQDestWb
;
2556 state
->NtransSig
= LOW
;
2557 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2558 LSBase
= lhs
- LSImmRHS
;
2559 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2562 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2564 if (StoreWord (state
, instr
, lhs
))
2565 LSBase
= lhs
+ LSImmRHS
;
2568 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2570 if (LoadWord (state
, instr
, lhs
))
2571 LSBase
= lhs
+ LSImmRHS
;
2574 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2575 UNDEF_LSRBaseEQDestWb
;
2578 state
->NtransSig
= LOW
;
2579 if (StoreWord (state
, instr
, lhs
))
2580 LSBase
= lhs
+ LSImmRHS
;
2581 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2584 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2585 UNDEF_LSRBaseEQDestWb
;
2588 state
->NtransSig
= LOW
;
2589 if (LoadWord (state
, instr
, lhs
))
2590 LSBase
= lhs
+ LSImmRHS
;
2591 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2594 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2596 if (StoreByte (state
, instr
, lhs
))
2597 LSBase
= lhs
+ LSImmRHS
;
2600 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2602 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2603 LSBase
= lhs
+ LSImmRHS
;
2606 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2607 UNDEF_LSRBaseEQDestWb
;
2610 state
->NtransSig
= LOW
;
2611 if (StoreByte (state
, instr
, lhs
))
2612 LSBase
= lhs
+ LSImmRHS
;
2613 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2616 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2617 UNDEF_LSRBaseEQDestWb
;
2620 state
->NtransSig
= LOW
;
2621 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2622 LSBase
= lhs
+ LSImmRHS
;
2623 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2627 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2628 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2631 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2632 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2635 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2636 UNDEF_LSRBaseEQDestWb
;
2638 temp
= LHS
- LSImmRHS
;
2639 if (StoreWord (state
, instr
, temp
))
2643 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2644 UNDEF_LSRBaseEQDestWb
;
2646 temp
= LHS
- LSImmRHS
;
2647 if (LoadWord (state
, instr
, temp
))
2651 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2652 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2655 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2656 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2659 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2660 UNDEF_LSRBaseEQDestWb
;
2662 temp
= LHS
- LSImmRHS
;
2663 if (StoreByte (state
, instr
, temp
))
2667 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2668 UNDEF_LSRBaseEQDestWb
;
2670 temp
= LHS
- LSImmRHS
;
2671 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2675 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2676 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2679 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2680 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2683 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2684 UNDEF_LSRBaseEQDestWb
;
2686 temp
= LHS
+ LSImmRHS
;
2687 if (StoreWord (state
, instr
, temp
))
2691 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2692 UNDEF_LSRBaseEQDestWb
;
2694 temp
= LHS
+ LSImmRHS
;
2695 if (LoadWord (state
, instr
, temp
))
2699 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2700 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2703 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2704 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2707 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2708 UNDEF_LSRBaseEQDestWb
;
2710 temp
= LHS
+ LSImmRHS
;
2711 if (StoreByte (state
, instr
, temp
))
2715 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2716 UNDEF_LSRBaseEQDestWb
;
2718 temp
= LHS
+ LSImmRHS
;
2719 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2724 /* Single Data Transfer Register RHS Instructions. */
2726 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2729 ARMul_UndefInstr (state
, instr
);
2732 UNDEF_LSRBaseEQOffWb
;
2733 UNDEF_LSRBaseEQDestWb
;
2737 if (StoreWord (state
, instr
, lhs
))
2738 LSBase
= lhs
- LSRegRHS
;
2741 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2746 && handle_v6_insn (state
, instr
))
2749 ARMul_UndefInstr (state
, instr
);
2752 UNDEF_LSRBaseEQOffWb
;
2753 UNDEF_LSRBaseEQDestWb
;
2757 temp
= lhs
- LSRegRHS
;
2758 if (LoadWord (state
, instr
, lhs
))
2762 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2767 && handle_v6_insn (state
, instr
))
2770 ARMul_UndefInstr (state
, instr
);
2773 UNDEF_LSRBaseEQOffWb
;
2774 UNDEF_LSRBaseEQDestWb
;
2778 state
->NtransSig
= LOW
;
2779 if (StoreWord (state
, instr
, lhs
))
2780 LSBase
= lhs
- LSRegRHS
;
2781 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2784 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2789 && handle_v6_insn (state
, instr
))
2792 ARMul_UndefInstr (state
, instr
);
2795 UNDEF_LSRBaseEQOffWb
;
2796 UNDEF_LSRBaseEQDestWb
;
2800 temp
= lhs
- LSRegRHS
;
2801 state
->NtransSig
= LOW
;
2802 if (LoadWord (state
, instr
, lhs
))
2804 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2807 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2810 ARMul_UndefInstr (state
, instr
);
2813 UNDEF_LSRBaseEQOffWb
;
2814 UNDEF_LSRBaseEQDestWb
;
2818 if (StoreByte (state
, instr
, lhs
))
2819 LSBase
= lhs
- LSRegRHS
;
2822 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2827 && handle_v6_insn (state
, instr
))
2830 ARMul_UndefInstr (state
, instr
);
2833 UNDEF_LSRBaseEQOffWb
;
2834 UNDEF_LSRBaseEQDestWb
;
2838 temp
= lhs
- LSRegRHS
;
2839 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2843 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2848 && handle_v6_insn (state
, instr
))
2851 ARMul_UndefInstr (state
, instr
);
2854 UNDEF_LSRBaseEQOffWb
;
2855 UNDEF_LSRBaseEQDestWb
;
2859 state
->NtransSig
= LOW
;
2860 if (StoreByte (state
, instr
, lhs
))
2861 LSBase
= lhs
- LSRegRHS
;
2862 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2865 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2870 && handle_v6_insn (state
, instr
))
2873 ARMul_UndefInstr (state
, instr
);
2876 UNDEF_LSRBaseEQOffWb
;
2877 UNDEF_LSRBaseEQDestWb
;
2881 temp
= lhs
- LSRegRHS
;
2882 state
->NtransSig
= LOW
;
2883 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2885 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2888 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2893 && handle_v6_insn (state
, instr
))
2896 ARMul_UndefInstr (state
, instr
);
2899 UNDEF_LSRBaseEQOffWb
;
2900 UNDEF_LSRBaseEQDestWb
;
2904 if (StoreWord (state
, instr
, lhs
))
2905 LSBase
= lhs
+ LSRegRHS
;
2908 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2911 ARMul_UndefInstr (state
, instr
);
2914 UNDEF_LSRBaseEQOffWb
;
2915 UNDEF_LSRBaseEQDestWb
;
2919 temp
= lhs
+ LSRegRHS
;
2920 if (LoadWord (state
, instr
, lhs
))
2924 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2929 && handle_v6_insn (state
, instr
))
2932 ARMul_UndefInstr (state
, instr
);
2935 UNDEF_LSRBaseEQOffWb
;
2936 UNDEF_LSRBaseEQDestWb
;
2940 state
->NtransSig
= LOW
;
2941 if (StoreWord (state
, instr
, lhs
))
2942 LSBase
= lhs
+ LSRegRHS
;
2943 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2946 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2951 && handle_v6_insn (state
, instr
))
2954 ARMul_UndefInstr (state
, instr
);
2957 UNDEF_LSRBaseEQOffWb
;
2958 UNDEF_LSRBaseEQDestWb
;
2962 temp
= lhs
+ LSRegRHS
;
2963 state
->NtransSig
= LOW
;
2964 if (LoadWord (state
, instr
, lhs
))
2966 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2969 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2974 && handle_v6_insn (state
, instr
))
2977 ARMul_UndefInstr (state
, instr
);
2980 UNDEF_LSRBaseEQOffWb
;
2981 UNDEF_LSRBaseEQDestWb
;
2985 if (StoreByte (state
, instr
, lhs
))
2986 LSBase
= lhs
+ LSRegRHS
;
2989 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
2992 ARMul_UndefInstr (state
, instr
);
2995 UNDEF_LSRBaseEQOffWb
;
2996 UNDEF_LSRBaseEQDestWb
;
3000 temp
= lhs
+ LSRegRHS
;
3001 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3005 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3010 && handle_v6_insn (state
, instr
))
3013 ARMul_UndefInstr (state
, instr
);
3016 UNDEF_LSRBaseEQOffWb
;
3017 UNDEF_LSRBaseEQDestWb
;
3021 state
->NtransSig
= LOW
;
3022 if (StoreByte (state
, instr
, lhs
))
3023 LSBase
= lhs
+ LSRegRHS
;
3024 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3027 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3032 && handle_v6_insn (state
, instr
))
3035 ARMul_UndefInstr (state
, instr
);
3038 UNDEF_LSRBaseEQOffWb
;
3039 UNDEF_LSRBaseEQDestWb
;
3043 temp
= lhs
+ LSRegRHS
;
3044 state
->NtransSig
= LOW
;
3045 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3047 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3051 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3056 && handle_v6_insn (state
, instr
))
3059 ARMul_UndefInstr (state
, instr
);
3062 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
3065 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3068 ARMul_UndefInstr (state
, instr
);
3071 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
3074 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3077 ARMul_UndefInstr (state
, instr
);
3080 UNDEF_LSRBaseEQOffWb
;
3081 UNDEF_LSRBaseEQDestWb
;
3084 temp
= LHS
- LSRegRHS
;
3085 if (StoreWord (state
, instr
, temp
))
3089 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3092 ARMul_UndefInstr (state
, instr
);
3095 UNDEF_LSRBaseEQOffWb
;
3096 UNDEF_LSRBaseEQDestWb
;
3099 temp
= LHS
- LSRegRHS
;
3100 if (LoadWord (state
, instr
, temp
))
3104 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3109 && handle_v6_insn (state
, instr
))
3112 ARMul_UndefInstr (state
, instr
);
3115 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
3118 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3123 && handle_v6_insn (state
, instr
))
3126 ARMul_UndefInstr (state
, instr
);
3129 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
3132 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3135 ARMul_UndefInstr (state
, instr
);
3138 UNDEF_LSRBaseEQOffWb
;
3139 UNDEF_LSRBaseEQDestWb
;
3142 temp
= LHS
- LSRegRHS
;
3143 if (StoreByte (state
, instr
, temp
))
3147 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3150 ARMul_UndefInstr (state
, instr
);
3153 UNDEF_LSRBaseEQOffWb
;
3154 UNDEF_LSRBaseEQDestWb
;
3157 temp
= LHS
- LSRegRHS
;
3158 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3162 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3167 && handle_v6_insn (state
, instr
))
3170 ARMul_UndefInstr (state
, instr
);
3173 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
3176 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
3179 ARMul_UndefInstr (state
, instr
);
3182 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
3185 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
3190 && handle_v6_insn (state
, instr
))
3193 ARMul_UndefInstr (state
, instr
);
3196 UNDEF_LSRBaseEQOffWb
;
3197 UNDEF_LSRBaseEQDestWb
;
3200 temp
= LHS
+ LSRegRHS
;
3201 if (StoreWord (state
, instr
, temp
))
3205 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
3208 ARMul_UndefInstr (state
, instr
);
3211 UNDEF_LSRBaseEQOffWb
;
3212 UNDEF_LSRBaseEQDestWb
;
3215 temp
= LHS
+ LSRegRHS
;
3216 if (LoadWord (state
, instr
, temp
))
3220 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
3225 && handle_v6_insn (state
, instr
))
3228 ARMul_UndefInstr (state
, instr
);
3231 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
3234 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
3237 ARMul_UndefInstr (state
, instr
);
3240 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
3243 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
3246 ARMul_UndefInstr (state
, instr
);
3249 UNDEF_LSRBaseEQOffWb
;
3250 UNDEF_LSRBaseEQDestWb
;
3253 temp
= LHS
+ LSRegRHS
;
3254 if (StoreByte (state
, instr
, temp
))
3258 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
3261 /* Check for the special breakpoint opcode.
3262 This value should correspond to the value defined
3263 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
3264 if (BITS (0, 19) == 0xfdefe)
3266 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
3267 ARMul_Abort (state
, ARMul_SWIV
);
3270 ARMul_UndefInstr (state
, instr
);
3273 UNDEF_LSRBaseEQOffWb
;
3274 UNDEF_LSRBaseEQDestWb
;
3277 temp
= LHS
+ LSRegRHS
;
3278 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3283 /* Multiple Data Transfer Instructions. */
3285 case 0x80: /* Store, No WriteBack, Post Dec. */
3286 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3289 case 0x81: /* Load, No WriteBack, Post Dec. */
3290 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3293 case 0x82: /* Store, WriteBack, Post Dec. */
3294 temp
= LSBase
- LSMNumRegs
;
3295 STOREMULT (instr
, temp
+ 4L, temp
);
3298 case 0x83: /* Load, WriteBack, Post Dec. */
3299 temp
= LSBase
- LSMNumRegs
;
3300 LOADMULT (instr
, temp
+ 4L, temp
);
3303 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
3304 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3307 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
3308 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3311 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
3312 temp
= LSBase
- LSMNumRegs
;
3313 STORESMULT (instr
, temp
+ 4L, temp
);
3316 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3317 temp
= LSBase
- LSMNumRegs
;
3318 LOADSMULT (instr
, temp
+ 4L, temp
);
3321 case 0x88: /* Store, No WriteBack, Post Inc. */
3322 STOREMULT (instr
, LSBase
, 0L);
3325 case 0x89: /* Load, No WriteBack, Post Inc. */
3326 LOADMULT (instr
, LSBase
, 0L);
3329 case 0x8a: /* Store, WriteBack, Post Inc. */
3331 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
3334 case 0x8b: /* Load, WriteBack, Post Inc. */
3336 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
3339 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3340 STORESMULT (instr
, LSBase
, 0L);
3343 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3344 LOADSMULT (instr
, LSBase
, 0L);
3347 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3349 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
3352 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3354 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
3357 case 0x90: /* Store, No WriteBack, Pre Dec. */
3358 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3361 case 0x91: /* Load, No WriteBack, Pre Dec. */
3362 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3365 case 0x92: /* Store, WriteBack, Pre Dec. */
3366 temp
= LSBase
- LSMNumRegs
;
3367 STOREMULT (instr
, temp
, temp
);
3370 case 0x93: /* Load, WriteBack, Pre Dec. */
3371 temp
= LSBase
- LSMNumRegs
;
3372 LOADMULT (instr
, temp
, temp
);
3375 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3376 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3379 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3380 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3383 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3384 temp
= LSBase
- LSMNumRegs
;
3385 STORESMULT (instr
, temp
, temp
);
3388 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3389 temp
= LSBase
- LSMNumRegs
;
3390 LOADSMULT (instr
, temp
, temp
);
3393 case 0x98: /* Store, No WriteBack, Pre Inc. */
3394 STOREMULT (instr
, LSBase
+ 4L, 0L);
3397 case 0x99: /* Load, No WriteBack, Pre Inc. */
3398 LOADMULT (instr
, LSBase
+ 4L, 0L);
3401 case 0x9a: /* Store, WriteBack, Pre Inc. */
3403 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3406 case 0x9b: /* Load, WriteBack, Pre Inc. */
3408 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3411 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3412 STORESMULT (instr
, LSBase
+ 4L, 0L);
3415 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3416 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3419 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3421 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3424 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3426 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3430 /* Branch forward. */
3439 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3444 /* Branch backward. */
3453 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3458 /* Branch and Link forward. */
3467 /* Put PC into Link. */
3469 state
->Reg
[14] = pc
+ 4;
3471 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3473 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3478 /* Branch and Link backward. */
3487 /* Put PC into Link. */
3489 state
->Reg
[14] = pc
+ 4;
3491 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3493 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3498 /* Co-Processor Data Transfers. */
3502 /* Reading from R15 is UNPREDICTABLE. */
3503 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3504 ARMul_UndefInstr (state
, instr
);
3505 /* Is access to coprocessor 0 allowed ? */
3506 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3507 ARMul_UndefInstr (state
, instr
);
3508 /* Special treatment for XScale coprocessors. */
3509 else if (state
->is_XScale
)
3511 /* Only opcode 0 is supported. */
3512 if (BITS (4, 7) != 0x00)
3513 ARMul_UndefInstr (state
, instr
);
3514 /* Only coporcessor 0 is supported. */
3515 else if (CPNum
!= 0x00)
3516 ARMul_UndefInstr (state
, instr
);
3517 /* Only accumulator 0 is supported. */
3518 else if (BITS (0, 3) != 0x00)
3519 ARMul_UndefInstr (state
, instr
);
3522 /* XScale MAR insn. Move two registers into accumulator. */
3523 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3524 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3528 /* FIXME: Not sure what to do for other v5 processors. */
3529 ARMul_UndefInstr (state
, instr
);
3534 case 0xc0: /* Store , No WriteBack , Post Dec. */
3535 ARMul_STC (state
, instr
, LHS
);
3541 /* Writes to R15 are UNPREDICATABLE. */
3542 if (DESTReg
== 15 || LHSReg
== 15)
3543 ARMul_UndefInstr (state
, instr
);
3544 /* Is access to the coprocessor allowed ? */
3545 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3546 ARMul_UndefInstr (state
, instr
);
3547 /* Special handling for XScale coprcoessors. */
3548 else if (state
->is_XScale
)
3550 /* Only opcode 0 is supported. */
3551 if (BITS (4, 7) != 0x00)
3552 ARMul_UndefInstr (state
, instr
);
3553 /* Only coprocessor 0 is supported. */
3554 else if (CPNum
!= 0x00)
3555 ARMul_UndefInstr (state
, instr
);
3556 /* Only accumulator 0 is supported. */
3557 else if (BITS (0, 3) != 0x00)
3558 ARMul_UndefInstr (state
, instr
);
3561 /* XScale MRA insn. Move accumulator into two registers. */
3562 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3567 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3568 state
->Reg
[BITS (16, 19)] = t1
;
3573 /* FIXME: Not sure what to do for other v5 processors. */
3574 ARMul_UndefInstr (state
, instr
);
3579 case 0xc1: /* Load , No WriteBack , Post Dec. */
3580 ARMul_LDC (state
, instr
, LHS
);
3584 case 0xc6: /* Store , WriteBack , Post Dec. */
3586 state
->Base
= lhs
- LSCOff
;
3587 ARMul_STC (state
, instr
, lhs
);
3591 case 0xc7: /* Load , WriteBack , Post Dec. */
3593 state
->Base
= lhs
- LSCOff
;
3594 ARMul_LDC (state
, instr
, lhs
);
3598 case 0xcc: /* Store , No WriteBack , Post Inc. */
3599 ARMul_STC (state
, instr
, LHS
);
3603 case 0xcd: /* Load , No WriteBack , Post Inc. */
3604 ARMul_LDC (state
, instr
, LHS
);
3608 case 0xce: /* Store , WriteBack , Post Inc. */
3610 state
->Base
= lhs
+ LSCOff
;
3611 ARMul_STC (state
, instr
, LHS
);
3615 case 0xcf: /* Load , WriteBack , Post Inc. */
3617 state
->Base
= lhs
+ LSCOff
;
3618 ARMul_LDC (state
, instr
, LHS
);
3622 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3623 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3627 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3628 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3632 case 0xd6: /* Store , WriteBack , Pre Dec. */
3635 ARMul_STC (state
, instr
, lhs
);
3639 case 0xd7: /* Load , WriteBack , Pre Dec. */
3642 ARMul_LDC (state
, instr
, lhs
);
3646 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3647 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3651 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3652 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3656 case 0xde: /* Store , WriteBack , Pre Inc. */
3659 ARMul_STC (state
, instr
, lhs
);
3663 case 0xdf: /* Load , WriteBack , Pre Inc. */
3666 ARMul_LDC (state
, instr
, lhs
);
3670 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3673 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3675 ARMul_UndefInstr (state
, instr
);
3678 if (state
->is_XScale
)
3679 switch (BITS (18, 19))
3682 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3684 /* XScale MIA instruction. Signed multiplication of
3685 two 32 bit values and addition to 40 bit accumulator. */
3686 ARMsdword Rm
= state
->Reg
[MULLHSReg
];
3687 ARMsdword Rs
= state
->Reg
[MULACCReg
];
3693 state
->Accumulator
+= Rm
* Rs
;
3699 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3701 /* XScale MIAPH instruction. */
3702 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3703 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3704 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3705 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3720 state
->Accumulator
+= t5
;
3725 state
->Accumulator
+= t5
;
3731 if (BITS (4, 11) == 1)
3733 /* XScale MIAxy instruction. */
3739 t1
= state
->Reg
[MULLHSReg
] >> 16;
3741 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3744 t2
= state
->Reg
[MULACCReg
] >> 16;
3746 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3756 state
->Accumulator
+= t5
;
3780 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3782 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3783 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3787 ARMul_MCR (state
, instr
, DEST
);
3791 ARMul_CDP (state
, instr
);
3795 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3807 temp
= ARMul_MRC (state
, instr
);
3810 ASSIGNN ((temp
& NBIT
) != 0);
3811 ASSIGNZ ((temp
& ZBIT
) != 0);
3812 ASSIGNC ((temp
& CBIT
) != 0);
3813 ASSIGNV ((temp
& VBIT
) != 0);
3820 ARMul_CDP (state
, instr
);
3824 /* SWI instruction. */
3841 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3843 /* A prefetch abort. */
3844 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
3845 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3849 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3850 ARMul_Abort (state
, ARMul_SWIV
);
3860 #ifdef NEED_UI_LOOP_HOOK
3861 if (deprecated_ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3863 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3864 deprecated_ui_loop_hook (0);
3866 #endif /* NEED_UI_LOOP_HOOK */
3868 if (state
->Emulate
== ONCE
)
3869 state
->Emulate
= STOP
;
3870 /* If we have changed mode, allow the PC to advance before stopping. */
3871 else if (state
->Emulate
== CHANGEMODE
)
3873 else if (state
->Emulate
!= RUN
)
3876 while (!stop_simulator
);
3878 state
->decoded
= decoded
;
3879 state
->loaded
= loaded
;
3885 /* This routine evaluates most Data Processing register RHS's with the S
3886 bit clear. It is intended to be called from the macro DPRegRHS, which
3887 filters the common case of an unshifted register with in line code. */
3890 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3892 ARMword shamt
, base
;
3897 /* Shift amount in a register. */
3902 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3905 base
= state
->Reg
[base
];
3906 ARMul_Icycles (state
, 1, 0L);
3907 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3908 switch ((int) BITS (5, 6))
3913 else if (shamt
>= 32)
3916 return (base
<< shamt
);
3920 else if (shamt
>= 32)
3923 return (base
>> shamt
);
3927 else if (shamt
>= 32)
3928 return ((ARMword
) ((ARMsword
) base
>> 31L));
3930 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
3936 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3941 /* Shift amount is a constant. */
3944 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3947 base
= state
->Reg
[base
];
3948 shamt
= BITS (7, 11);
3949 switch ((int) BITS (5, 6))
3952 return (base
<< shamt
);
3957 return (base
>> shamt
);
3960 return ((ARMword
) ((ARMsword
) base
>> 31L));
3962 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
3966 return ((base
>> 1) | (CFLAG
<< 31));
3968 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3975 /* This routine evaluates most Logical Data Processing register RHS's
3976 with the S bit set. It is intended to be called from the macro
3977 DPSRegRHS, which filters the common case of an unshifted register
3978 with in line code. */
3981 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3983 ARMword shamt
, base
;
3988 /* Shift amount in a register. */
3993 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3996 base
= state
->Reg
[base
];
3997 ARMul_Icycles (state
, 1, 0L);
3998 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3999 switch ((int) BITS (5, 6))
4004 else if (shamt
== 32)
4009 else if (shamt
> 32)
4016 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4017 return (base
<< shamt
);
4022 else if (shamt
== 32)
4024 ASSIGNC (base
>> 31);
4027 else if (shamt
> 32)
4034 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4035 return (base
>> shamt
);
4040 else if (shamt
>= 32)
4042 ASSIGNC (base
>> 31L);
4043 return ((ARMword
) ((ARMsword
) base
>> 31L));
4047 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4048 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4056 ASSIGNC (base
>> 31);
4061 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4062 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4068 /* Shift amount is a constant. */
4071 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4074 base
= state
->Reg
[base
];
4075 shamt
= BITS (7, 11);
4077 switch ((int) BITS (5, 6))
4080 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4081 return (base
<< shamt
);
4085 ASSIGNC (base
>> 31);
4090 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4091 return (base
>> shamt
);
4096 ASSIGNC (base
>> 31L);
4097 return ((ARMword
) ((ARMsword
) base
>> 31L));
4101 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4102 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4110 return ((base
>> 1) | (shamt
<< 31));
4114 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4115 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4123 /* This routine handles writes to register 15 when the S bit is not set. */
4126 WriteR15 (ARMul_State
* state
, ARMword src
)
4128 /* The ARM documentation states that the two least significant bits
4129 are discarded when setting PC, except in the cases handled by
4130 WriteR15Branch() below. It's probably an oversight: in THUMB
4131 mode, the second least significant bit should probably not be
4141 state
->Reg
[15] = src
& PCBITS
;
4143 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
4144 ARMul_R15Altered (state
);
4150 /* This routine handles writes to register 15 when the S bit is set. */
4153 WriteSR15 (ARMul_State
* state
, ARMword src
)
4156 if (state
->Bank
> 0)
4158 state
->Cpsr
= state
->Spsr
[state
->Bank
];
4159 ARMul_CPSRAltered (state
);
4167 state
->Reg
[15] = src
& PCBITS
;
4171 /* ARMul_R15Altered would have to support it. */
4177 if (state
->Bank
== USERBANK
)
4178 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
4180 state
->Reg
[15] = src
;
4182 ARMul_R15Altered (state
);
4187 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
4188 will switch to Thumb mode if the least significant bit is set. */
4191 WriteR15Branch (ARMul_State
* state
, ARMword src
)
4198 state
->Reg
[15] = src
& 0xfffffffe;
4203 state
->Reg
[15] = src
& 0xfffffffc;
4207 WriteR15 (state
, src
);
4211 /* This routine evaluates most Load and Store register RHS's. It is
4212 intended to be called from the macro LSRegRHS, which filters the
4213 common case of an unshifted register with in line code. */
4216 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
4218 ARMword shamt
, base
;
4223 /* Now forbidden, but ... */
4224 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4227 base
= state
->Reg
[base
];
4229 shamt
= BITS (7, 11);
4230 switch ((int) BITS (5, 6))
4233 return (base
<< shamt
);
4238 return (base
>> shamt
);
4241 return ((ARMword
) ((ARMsword
) base
>> 31L));
4243 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4247 return ((base
>> 1) | (CFLAG
<< 31));
4249 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4256 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
4259 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
4266 /* Now forbidden, but ... */
4267 return ECC
| ER15INT
| R15PC
| EMODE
;
4269 return state
->Reg
[RHSReg
];
4273 return BITS (0, 3) | (BITS (8, 11) << 4);
4276 /* This function does the work of loading a word for a LDR instruction. */
4279 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4285 if (ADDREXCEPT (address
))
4286 INTERNALABORT (address
);
4289 dest
= ARMul_LoadWordN (state
, address
);
4294 return state
->lateabtSig
;
4297 dest
= ARMul_Align (state
, address
, dest
);
4299 ARMul_Icycles (state
, 1, 0L);
4301 return (DESTReg
!= LHSReg
);
4305 /* This function does the work of loading a halfword. */
4308 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
4315 if (ADDREXCEPT (address
))
4316 INTERNALABORT (address
);
4318 dest
= ARMul_LoadHalfWord (state
, address
);
4322 return state
->lateabtSig
;
4326 if (dest
& 1 << (16 - 1))
4327 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
4330 ARMul_Icycles (state
, 1, 0L);
4331 return (DESTReg
!= LHSReg
);
4336 /* This function does the work of loading a byte for a LDRB instruction. */
4339 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
4345 if (ADDREXCEPT (address
))
4346 INTERNALABORT (address
);
4348 dest
= ARMul_LoadByte (state
, address
);
4352 return state
->lateabtSig
;
4356 if (dest
& 1 << (8 - 1))
4357 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
4360 ARMul_Icycles (state
, 1, 0L);
4362 return (DESTReg
!= LHSReg
);
4365 /* This function does the work of loading two words for a LDRD instruction. */
4368 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
4372 ARMword write_back
= BIT (21);
4373 ARMword immediate
= BIT (22);
4374 ARMword add_to_base
= BIT (23);
4375 ARMword pre_indexed
= BIT (24);
4385 /* If the writeback bit is set, the pre-index bit must be clear. */
4386 if (write_back
&& ! pre_indexed
)
4388 ARMul_UndefInstr (state
, instr
);
4392 /* Extract the base address register. */
4395 /* Extract the destination register and check it. */
4398 /* Destination register must be even. */
4400 /* Destination register cannot be LR. */
4401 || (dest_reg
== 14))
4403 ARMul_UndefInstr (state
, instr
);
4407 /* Compute the base address. */
4408 base
= state
->Reg
[addr_reg
];
4410 /* Compute the offset. */
4411 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4413 /* Compute the sum of the two. */
4415 sum
= base
+ offset
;
4417 sum
= base
- offset
;
4419 /* If this is a pre-indexed mode use the sum. */
4425 /* The address must be aligned on a 8 byte boundary. */
4429 ARMul_DATAABORT (addr
);
4431 ARMul_UndefInstr (state
, instr
);
4436 /* For pre indexed or post indexed addressing modes,
4437 check that the destination registers do not overlap
4438 the address registers. */
4439 if ((! pre_indexed
|| write_back
)
4440 && ( addr_reg
== dest_reg
4441 || addr_reg
== dest_reg
+ 1))
4443 ARMul_UndefInstr (state
, instr
);
4447 /* Load the words. */
4448 value1
= ARMul_LoadWordN (state
, addr
);
4449 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4451 /* Check for data aborts. */
4458 ARMul_Icycles (state
, 2, 0L);
4460 /* Store the values. */
4461 state
->Reg
[dest_reg
] = value1
;
4462 state
->Reg
[dest_reg
+ 1] = value2
;
4464 /* Do the post addressing and writeback. */
4468 if (! pre_indexed
|| write_back
)
4469 state
->Reg
[addr_reg
] = addr
;
4472 /* This function does the work of storing two words for a STRD instruction. */
4475 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4479 ARMword write_back
= BIT (21);
4480 ARMword immediate
= BIT (22);
4481 ARMword add_to_base
= BIT (23);
4482 ARMword pre_indexed
= BIT (24);
4490 /* If the writeback bit is set, the pre-index bit must be clear. */
4491 if (write_back
&& ! pre_indexed
)
4493 ARMul_UndefInstr (state
, instr
);
4497 /* Extract the base address register. */
4500 /* Base register cannot be PC. */
4503 ARMul_UndefInstr (state
, instr
);
4507 /* Extract the source register. */
4510 /* Source register must be even. */
4513 ARMul_UndefInstr (state
, instr
);
4517 /* Compute the base address. */
4518 base
= state
->Reg
[addr_reg
];
4520 /* Compute the offset. */
4521 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4523 /* Compute the sum of the two. */
4525 sum
= base
+ offset
;
4527 sum
= base
- offset
;
4529 /* If this is a pre-indexed mode use the sum. */
4535 /* The address must be aligned on a 8 byte boundary. */
4539 ARMul_DATAABORT (addr
);
4541 ARMul_UndefInstr (state
, instr
);
4546 /* For pre indexed or post indexed addressing modes,
4547 check that the destination registers do not overlap
4548 the address registers. */
4549 if ((! pre_indexed
|| write_back
)
4550 && ( addr_reg
== src_reg
4551 || addr_reg
== src_reg
+ 1))
4553 ARMul_UndefInstr (state
, instr
);
4557 /* Load the words. */
4558 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4559 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4567 /* Do the post addressing and writeback. */
4571 if (! pre_indexed
|| write_back
)
4572 state
->Reg
[addr_reg
] = addr
;
4575 /* This function does the work of storing a word from a STR instruction. */
4578 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4583 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4586 ARMul_StoreWordN (state
, address
, DEST
);
4588 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4590 INTERNALABORT (address
);
4591 (void) ARMul_LoadWordN (state
, address
);
4594 ARMul_StoreWordN (state
, address
, DEST
);
4599 return state
->lateabtSig
;
4605 /* This function does the work of storing a byte for a STRH instruction. */
4608 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4614 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4618 ARMul_StoreHalfWord (state
, address
, DEST
);
4620 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4622 INTERNALABORT (address
);
4623 (void) ARMul_LoadHalfWord (state
, address
);
4626 ARMul_StoreHalfWord (state
, address
, DEST
);
4632 return state
->lateabtSig
;
4639 /* This function does the work of storing a byte for a STRB instruction. */
4642 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4647 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4650 ARMul_StoreByte (state
, address
, DEST
);
4652 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4654 INTERNALABORT (address
);
4655 (void) ARMul_LoadByte (state
, address
);
4658 ARMul_StoreByte (state
, address
, DEST
);
4663 return state
->lateabtSig
;
4669 /* This function does the work of loading the registers listed in an LDM
4670 instruction, when the S bit is clear. The code here is always increment
4671 after, it's up to the caller to get the input address correct and to
4672 handle base register modification. */
4675 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4681 UNDEF_LSMBaseInListWb
;
4684 if (ADDREXCEPT (address
))
4685 INTERNALABORT (address
);
4687 if (BIT (21) && LHSReg
!= 15)
4690 /* N cycle first. */
4691 for (temp
= 0; !BIT (temp
); temp
++)
4694 dest
= ARMul_LoadWordN (state
, address
);
4696 if (!state
->abortSig
&& !state
->Aborted
)
4697 state
->Reg
[temp
++] = dest
;
4698 else if (!state
->Aborted
)
4700 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4701 state
->Aborted
= ARMul_DataAbortV
;
4704 /* S cycles from here on. */
4705 for (; temp
< 16; temp
++)
4708 /* Load this register. */
4710 dest
= ARMul_LoadWordS (state
, address
);
4712 if (!state
->abortSig
&& !state
->Aborted
)
4713 state
->Reg
[temp
] = dest
;
4714 else if (!state
->Aborted
)
4716 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4717 state
->Aborted
= ARMul_DataAbortV
;
4721 if (BIT (15) && !state
->Aborted
)
4722 /* PC is in the reg list. */
4723 WriteR15Branch (state
, PC
);
4725 /* To write back the final register. */
4726 ARMul_Icycles (state
, 1, 0L);
4730 if (BIT (21) && LHSReg
!= 15)
4736 /* This function does the work of loading the registers listed in an LDM
4737 instruction, when the S bit is set. The code here is always increment
4738 after, it's up to the caller to get the input address correct and to
4739 handle base register modification. */
4742 LoadSMult (ARMul_State
* state
,
4751 UNDEF_LSMBaseInListWb
;
4756 if (ADDREXCEPT (address
))
4757 INTERNALABORT (address
);
4760 if (BIT (21) && LHSReg
!= 15)
4763 if (!BIT (15) && state
->Bank
!= USERBANK
)
4765 /* Temporary reg bank switch. */
4766 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4767 UNDEF_LSMUserBankWb
;
4770 /* N cycle first. */
4771 for (temp
= 0; !BIT (temp
); temp
++)
4774 dest
= ARMul_LoadWordN (state
, address
);
4776 if (!state
->abortSig
)
4777 state
->Reg
[temp
++] = dest
;
4778 else if (!state
->Aborted
)
4780 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4781 state
->Aborted
= ARMul_DataAbortV
;
4784 /* S cycles from here on. */
4785 for (; temp
< 16; temp
++)
4788 /* Load this register. */
4790 dest
= ARMul_LoadWordS (state
, address
);
4792 if (!state
->abortSig
&& !state
->Aborted
)
4793 state
->Reg
[temp
] = dest
;
4794 else if (!state
->Aborted
)
4796 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4797 state
->Aborted
= ARMul_DataAbortV
;
4801 if (BIT (15) && !state
->Aborted
)
4803 /* PC is in the reg list. */
4805 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4807 state
->Cpsr
= GETSPSR (state
->Bank
);
4808 ARMul_CPSRAltered (state
);
4811 WriteR15 (state
, PC
);
4813 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4815 /* Protect bits in user mode. */
4816 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4817 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4818 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4819 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4822 ARMul_R15Altered (state
);
4828 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4829 /* Restore the correct bank. */
4830 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4832 /* To write back the final register. */
4833 ARMul_Icycles (state
, 1, 0L);
4837 if (BIT (21) && LHSReg
!= 15)
4844 /* This function does the work of storing the registers listed in an STM
4845 instruction, when the S bit is clear. The code here is always increment
4846 after, it's up to the caller to get the input address correct and to
4847 handle base register modification. */
4850 StoreMult (ARMul_State
* state
,
4859 UNDEF_LSMBaseInListWb
;
4862 /* N-cycle, increment the PC and update the NextInstr state. */
4866 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4867 INTERNALABORT (address
);
4873 /* N cycle first. */
4874 for (temp
= 0; !BIT (temp
); temp
++)
4878 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4882 (void) ARMul_LoadWordN (state
, address
);
4884 /* Fake the Stores as Loads. */
4885 for (; temp
< 16; temp
++)
4888 /* Save this register. */
4890 (void) ARMul_LoadWordS (state
, address
);
4893 if (BIT (21) && LHSReg
!= 15)
4899 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4902 if (state
->abortSig
&& !state
->Aborted
)
4904 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4905 state
->Aborted
= ARMul_DataAbortV
;
4908 if (BIT (21) && LHSReg
!= 15)
4911 /* S cycles from here on. */
4912 for (; temp
< 16; temp
++)
4915 /* Save this register. */
4918 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4920 if (state
->abortSig
&& !state
->Aborted
)
4922 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4923 state
->Aborted
= ARMul_DataAbortV
;
4931 /* This function does the work of storing the registers listed in an STM
4932 instruction when the S bit is set. The code here is always increment
4933 after, it's up to the caller to get the input address correct and to
4934 handle base register modification. */
4937 StoreSMult (ARMul_State
* state
,
4946 UNDEF_LSMBaseInListWb
;
4951 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4952 INTERNALABORT (address
);
4958 if (state
->Bank
!= USERBANK
)
4960 /* Force User Bank. */
4961 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4962 UNDEF_LSMUserBankWb
;
4965 for (temp
= 0; !BIT (temp
); temp
++)
4966 ; /* N cycle first. */
4969 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4973 (void) ARMul_LoadWordN (state
, address
);
4975 for (; temp
< 16; temp
++)
4976 /* Fake the Stores as Loads. */
4979 /* Save this register. */
4982 (void) ARMul_LoadWordS (state
, address
);
4985 if (BIT (21) && LHSReg
!= 15)
4992 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4995 if (state
->abortSig
&& !state
->Aborted
)
4997 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4998 state
->Aborted
= ARMul_DataAbortV
;
5001 /* S cycles from here on. */
5002 for (; temp
< 16; temp
++)
5005 /* Save this register. */
5008 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5010 if (state
->abortSig
&& !state
->Aborted
)
5012 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5013 state
->Aborted
= ARMul_DataAbortV
;
5017 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5018 /* Restore the correct bank. */
5019 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5021 if (BIT (21) && LHSReg
!= 15)
5028 /* This function does the work of adding two 32bit values
5029 together, and calculating if a carry has occurred. */
5032 Add32 (ARMword a1
, ARMword a2
, int *carry
)
5034 ARMword result
= (a1
+ a2
);
5035 unsigned int uresult
= (unsigned int) result
;
5036 unsigned int ua1
= (unsigned int) a1
;
5038 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5039 or (result > RdLo) then we have no carry. */
5040 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
5048 /* This function does the work of multiplying
5049 two 32bit values to give a 64bit result. */
5052 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5054 /* Operand register numbers. */
5055 int nRdHi
, nRdLo
, nRs
, nRm
;
5056 ARMword RdHi
= 0, RdLo
= 0, Rm
;
5060 nRdHi
= BITS (16, 19);
5061 nRdLo
= BITS (12, 15);
5065 /* Needed to calculate the cycle count. */
5066 Rm
= state
->Reg
[nRm
];
5068 /* Check for illegal operand combinations first. */
5077 /* Intermediate results. */
5078 ARMword lo
, mid1
, mid2
, hi
;
5080 ARMword Rs
= state
->Reg
[nRs
];
5085 /* Compute sign of result and adjust operands if necessary. */
5086 sign
= (Rm
^ Rs
) & 0x80000000;
5088 if (((ARMsword
) Rm
) < 0)
5091 if (((ARMsword
) Rs
) < 0)
5095 /* We can split the 32x32 into four 16x16 operations. This
5096 ensures that we do not lose precision on 32bit only hosts. */
5097 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
5098 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5099 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
5100 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5102 /* We now need to add all of these results together, taking
5103 care to propogate the carries from the additions. */
5104 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
5106 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
5108 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
5112 /* Negate result if necessary. */
5115 if (RdLo
== 0xFFFFFFFF)
5124 state
->Reg
[nRdLo
] = RdLo
;
5125 state
->Reg
[nRdHi
] = RdHi
;
5128 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
5131 /* Ensure that both RdHi and RdLo are used to compute Z,
5132 but don't let RdLo's sign bit make it to N. */
5133 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
5135 /* The cycle count depends on whether the instruction is a signed or
5136 unsigned multiply, and what bits are clear in the multiplier. */
5137 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
5138 /* Invert the bits to make the check against zero. */
5141 if ((Rm
& 0xFFFFFF00) == 0)
5143 else if ((Rm
& 0xFFFF0000) == 0)
5145 else if ((Rm
& 0xFF000000) == 0)
5153 /* This function does the work of multiplying two 32bit
5154 values and adding a 64bit value to give a 64bit result. */
5157 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5164 nRdHi
= BITS (16, 19);
5165 nRdLo
= BITS (12, 15);
5167 RdHi
= state
->Reg
[nRdHi
];
5168 RdLo
= state
->Reg
[nRdLo
];
5170 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
5172 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
5173 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
5175 state
->Reg
[nRdLo
] = RdLo
;
5176 state
->Reg
[nRdHi
] = RdHi
;
5179 /* Ensure that both RdHi and RdLo are used to compute Z,
5180 but don't let RdLo's sign bit make it to N. */
5181 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
5183 /* Extra cycle for addition. */