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: /* MOVW immed */
2319 dest
= BITS (0, 11);
2320 dest
|= (BITS (16, 19) << 12);
2324 case 0x31: /* TSTP immed */
2329 state
->Cpsr
= GETSPSR (state
->Bank
);
2330 ARMul_CPSRAltered (state
);
2332 temp
= LHS
& DPImmRHS
;
2341 ARMul_NegZero (state
, dest
);
2345 case 0x32: /* TEQ immed and MSR immed to CPSR */
2347 /* MSR immed to CPSR. */
2348 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2353 case 0x33: /* TEQP immed */
2358 state
->Cpsr
= GETSPSR (state
->Bank
);
2359 ARMul_CPSRAltered (state
);
2361 temp
= LHS
^ DPImmRHS
;
2367 DPSImmRHS
; /* TEQ immed */
2369 ARMul_NegZero (state
, dest
);
2373 case 0x34: /* MOVT immed */
2374 dest
= BITS (0, 11);
2375 dest
|= (BITS (16, 19) << 12);
2376 DEST
|= (dest
<< 16);
2379 case 0x35: /* CMPP immed */
2384 state
->Cpsr
= GETSPSR (state
->Bank
);
2385 ARMul_CPSRAltered (state
);
2387 temp
= LHS
- DPImmRHS
;
2398 ARMul_NegZero (state
, dest
);
2400 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2402 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2403 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2413 case 0x36: /* CMN immed and MSR immed to SPSR */
2415 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2420 case 0x37: /* CMNP immed. */
2425 state
->Cpsr
= GETSPSR (state
->Bank
);
2426 ARMul_CPSRAltered (state
);
2428 temp
= LHS
+ DPImmRHS
;
2439 ASSIGNZ (dest
== 0);
2440 if ((lhs
| rhs
) >> 30)
2442 /* Possible C,V,N to set. */
2443 ASSIGNN (NEG (dest
));
2444 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2445 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2456 case 0x38: /* ORR immed. */
2457 dest
= LHS
| DPImmRHS
;
2461 case 0x39: /* ORRS immed. */
2467 case 0x3a: /* MOV immed. */
2472 case 0x3b: /* MOVS immed. */
2477 case 0x3c: /* BIC immed. */
2478 dest
= LHS
& ~DPImmRHS
;
2482 case 0x3d: /* BICS immed. */
2488 case 0x3e: /* MVN immed. */
2493 case 0x3f: /* MVNS immed. */
2499 /* Single Data Transfer Immediate RHS Instructions. */
2501 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2503 if (StoreWord (state
, instr
, lhs
))
2504 LSBase
= lhs
- LSImmRHS
;
2507 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2509 if (LoadWord (state
, instr
, lhs
))
2510 LSBase
= lhs
- LSImmRHS
;
2513 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2514 UNDEF_LSRBaseEQDestWb
;
2517 temp
= lhs
- LSImmRHS
;
2518 state
->NtransSig
= LOW
;
2519 if (StoreWord (state
, instr
, lhs
))
2521 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2524 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2525 UNDEF_LSRBaseEQDestWb
;
2528 state
->NtransSig
= LOW
;
2529 if (LoadWord (state
, instr
, lhs
))
2530 LSBase
= lhs
- LSImmRHS
;
2531 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2534 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2536 if (StoreByte (state
, instr
, lhs
))
2537 LSBase
= lhs
- LSImmRHS
;
2540 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2542 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2543 LSBase
= lhs
- LSImmRHS
;
2546 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2547 UNDEF_LSRBaseEQDestWb
;
2550 state
->NtransSig
= LOW
;
2551 if (StoreByte (state
, instr
, lhs
))
2552 LSBase
= lhs
- LSImmRHS
;
2553 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2556 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2557 UNDEF_LSRBaseEQDestWb
;
2560 state
->NtransSig
= LOW
;
2561 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2562 LSBase
= lhs
- LSImmRHS
;
2563 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2566 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2568 if (StoreWord (state
, instr
, lhs
))
2569 LSBase
= lhs
+ LSImmRHS
;
2572 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2574 if (LoadWord (state
, instr
, lhs
))
2575 LSBase
= lhs
+ LSImmRHS
;
2578 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2579 UNDEF_LSRBaseEQDestWb
;
2582 state
->NtransSig
= LOW
;
2583 if (StoreWord (state
, instr
, lhs
))
2584 LSBase
= lhs
+ LSImmRHS
;
2585 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2588 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2589 UNDEF_LSRBaseEQDestWb
;
2592 state
->NtransSig
= LOW
;
2593 if (LoadWord (state
, instr
, lhs
))
2594 LSBase
= lhs
+ LSImmRHS
;
2595 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2598 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2600 if (StoreByte (state
, instr
, lhs
))
2601 LSBase
= lhs
+ LSImmRHS
;
2604 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2606 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2607 LSBase
= lhs
+ LSImmRHS
;
2610 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2611 UNDEF_LSRBaseEQDestWb
;
2614 state
->NtransSig
= LOW
;
2615 if (StoreByte (state
, instr
, lhs
))
2616 LSBase
= lhs
+ LSImmRHS
;
2617 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2620 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2621 UNDEF_LSRBaseEQDestWb
;
2624 state
->NtransSig
= LOW
;
2625 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2626 LSBase
= lhs
+ LSImmRHS
;
2627 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2631 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2632 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2635 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2636 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2639 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2640 UNDEF_LSRBaseEQDestWb
;
2642 temp
= LHS
- LSImmRHS
;
2643 if (StoreWord (state
, instr
, temp
))
2647 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2648 UNDEF_LSRBaseEQDestWb
;
2650 temp
= LHS
- LSImmRHS
;
2651 if (LoadWord (state
, instr
, temp
))
2655 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2656 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2659 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2660 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2663 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2664 UNDEF_LSRBaseEQDestWb
;
2666 temp
= LHS
- LSImmRHS
;
2667 if (StoreByte (state
, instr
, temp
))
2671 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2672 UNDEF_LSRBaseEQDestWb
;
2674 temp
= LHS
- LSImmRHS
;
2675 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2679 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2680 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2683 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2684 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2687 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2688 UNDEF_LSRBaseEQDestWb
;
2690 temp
= LHS
+ LSImmRHS
;
2691 if (StoreWord (state
, instr
, temp
))
2695 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2696 UNDEF_LSRBaseEQDestWb
;
2698 temp
= LHS
+ LSImmRHS
;
2699 if (LoadWord (state
, instr
, temp
))
2703 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2704 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2707 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2708 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2711 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2712 UNDEF_LSRBaseEQDestWb
;
2714 temp
= LHS
+ LSImmRHS
;
2715 if (StoreByte (state
, instr
, temp
))
2719 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2720 UNDEF_LSRBaseEQDestWb
;
2722 temp
= LHS
+ LSImmRHS
;
2723 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2728 /* Single Data Transfer Register RHS Instructions. */
2730 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2733 ARMul_UndefInstr (state
, instr
);
2736 UNDEF_LSRBaseEQOffWb
;
2737 UNDEF_LSRBaseEQDestWb
;
2741 if (StoreWord (state
, instr
, lhs
))
2742 LSBase
= lhs
- LSRegRHS
;
2745 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2750 && handle_v6_insn (state
, instr
))
2753 ARMul_UndefInstr (state
, instr
);
2756 UNDEF_LSRBaseEQOffWb
;
2757 UNDEF_LSRBaseEQDestWb
;
2761 temp
= lhs
- LSRegRHS
;
2762 if (LoadWord (state
, instr
, lhs
))
2766 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2771 && handle_v6_insn (state
, instr
))
2774 ARMul_UndefInstr (state
, instr
);
2777 UNDEF_LSRBaseEQOffWb
;
2778 UNDEF_LSRBaseEQDestWb
;
2782 state
->NtransSig
= LOW
;
2783 if (StoreWord (state
, instr
, lhs
))
2784 LSBase
= lhs
- LSRegRHS
;
2785 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2788 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2793 && handle_v6_insn (state
, instr
))
2796 ARMul_UndefInstr (state
, instr
);
2799 UNDEF_LSRBaseEQOffWb
;
2800 UNDEF_LSRBaseEQDestWb
;
2804 temp
= lhs
- LSRegRHS
;
2805 state
->NtransSig
= LOW
;
2806 if (LoadWord (state
, instr
, lhs
))
2808 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2811 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2814 ARMul_UndefInstr (state
, instr
);
2817 UNDEF_LSRBaseEQOffWb
;
2818 UNDEF_LSRBaseEQDestWb
;
2822 if (StoreByte (state
, instr
, lhs
))
2823 LSBase
= lhs
- LSRegRHS
;
2826 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2831 && handle_v6_insn (state
, instr
))
2834 ARMul_UndefInstr (state
, instr
);
2837 UNDEF_LSRBaseEQOffWb
;
2838 UNDEF_LSRBaseEQDestWb
;
2842 temp
= lhs
- LSRegRHS
;
2843 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2847 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2852 && handle_v6_insn (state
, instr
))
2855 ARMul_UndefInstr (state
, instr
);
2858 UNDEF_LSRBaseEQOffWb
;
2859 UNDEF_LSRBaseEQDestWb
;
2863 state
->NtransSig
= LOW
;
2864 if (StoreByte (state
, instr
, lhs
))
2865 LSBase
= lhs
- LSRegRHS
;
2866 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2869 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2874 && handle_v6_insn (state
, instr
))
2877 ARMul_UndefInstr (state
, instr
);
2880 UNDEF_LSRBaseEQOffWb
;
2881 UNDEF_LSRBaseEQDestWb
;
2885 temp
= lhs
- LSRegRHS
;
2886 state
->NtransSig
= LOW
;
2887 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2889 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2892 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2897 && handle_v6_insn (state
, instr
))
2900 ARMul_UndefInstr (state
, instr
);
2903 UNDEF_LSRBaseEQOffWb
;
2904 UNDEF_LSRBaseEQDestWb
;
2908 if (StoreWord (state
, instr
, lhs
))
2909 LSBase
= lhs
+ LSRegRHS
;
2912 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2915 ARMul_UndefInstr (state
, instr
);
2918 UNDEF_LSRBaseEQOffWb
;
2919 UNDEF_LSRBaseEQDestWb
;
2923 temp
= lhs
+ LSRegRHS
;
2924 if (LoadWord (state
, instr
, lhs
))
2928 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2933 && handle_v6_insn (state
, instr
))
2936 ARMul_UndefInstr (state
, instr
);
2939 UNDEF_LSRBaseEQOffWb
;
2940 UNDEF_LSRBaseEQDestWb
;
2944 state
->NtransSig
= LOW
;
2945 if (StoreWord (state
, instr
, lhs
))
2946 LSBase
= lhs
+ LSRegRHS
;
2947 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2950 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2955 && handle_v6_insn (state
, instr
))
2958 ARMul_UndefInstr (state
, instr
);
2961 UNDEF_LSRBaseEQOffWb
;
2962 UNDEF_LSRBaseEQDestWb
;
2966 temp
= lhs
+ LSRegRHS
;
2967 state
->NtransSig
= LOW
;
2968 if (LoadWord (state
, instr
, lhs
))
2970 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2973 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2978 && handle_v6_insn (state
, instr
))
2981 ARMul_UndefInstr (state
, instr
);
2984 UNDEF_LSRBaseEQOffWb
;
2985 UNDEF_LSRBaseEQDestWb
;
2989 if (StoreByte (state
, instr
, lhs
))
2990 LSBase
= lhs
+ LSRegRHS
;
2993 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
2996 ARMul_UndefInstr (state
, instr
);
2999 UNDEF_LSRBaseEQOffWb
;
3000 UNDEF_LSRBaseEQDestWb
;
3004 temp
= lhs
+ LSRegRHS
;
3005 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3009 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3014 && handle_v6_insn (state
, instr
))
3017 ARMul_UndefInstr (state
, instr
);
3020 UNDEF_LSRBaseEQOffWb
;
3021 UNDEF_LSRBaseEQDestWb
;
3025 state
->NtransSig
= LOW
;
3026 if (StoreByte (state
, instr
, lhs
))
3027 LSBase
= lhs
+ LSRegRHS
;
3028 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3031 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3036 && handle_v6_insn (state
, instr
))
3039 ARMul_UndefInstr (state
, instr
);
3042 UNDEF_LSRBaseEQOffWb
;
3043 UNDEF_LSRBaseEQDestWb
;
3047 temp
= lhs
+ LSRegRHS
;
3048 state
->NtransSig
= LOW
;
3049 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3051 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3055 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3060 && handle_v6_insn (state
, instr
))
3063 ARMul_UndefInstr (state
, instr
);
3066 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
3069 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3072 ARMul_UndefInstr (state
, instr
);
3075 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
3078 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3081 ARMul_UndefInstr (state
, instr
);
3084 UNDEF_LSRBaseEQOffWb
;
3085 UNDEF_LSRBaseEQDestWb
;
3088 temp
= LHS
- LSRegRHS
;
3089 if (StoreWord (state
, instr
, temp
))
3093 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3096 ARMul_UndefInstr (state
, instr
);
3099 UNDEF_LSRBaseEQOffWb
;
3100 UNDEF_LSRBaseEQDestWb
;
3103 temp
= LHS
- LSRegRHS
;
3104 if (LoadWord (state
, instr
, temp
))
3108 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3113 && handle_v6_insn (state
, instr
))
3116 ARMul_UndefInstr (state
, instr
);
3119 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
3122 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3127 && handle_v6_insn (state
, instr
))
3130 ARMul_UndefInstr (state
, instr
);
3133 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
3136 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3139 ARMul_UndefInstr (state
, instr
);
3142 UNDEF_LSRBaseEQOffWb
;
3143 UNDEF_LSRBaseEQDestWb
;
3146 temp
= LHS
- LSRegRHS
;
3147 if (StoreByte (state
, instr
, temp
))
3151 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3154 ARMul_UndefInstr (state
, instr
);
3157 UNDEF_LSRBaseEQOffWb
;
3158 UNDEF_LSRBaseEQDestWb
;
3161 temp
= LHS
- LSRegRHS
;
3162 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3166 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3171 && handle_v6_insn (state
, instr
))
3174 ARMul_UndefInstr (state
, instr
);
3177 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
3180 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
3183 ARMul_UndefInstr (state
, instr
);
3186 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
3189 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
3194 && handle_v6_insn (state
, instr
))
3197 ARMul_UndefInstr (state
, instr
);
3200 UNDEF_LSRBaseEQOffWb
;
3201 UNDEF_LSRBaseEQDestWb
;
3204 temp
= LHS
+ LSRegRHS
;
3205 if (StoreWord (state
, instr
, temp
))
3209 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
3212 ARMul_UndefInstr (state
, instr
);
3215 UNDEF_LSRBaseEQOffWb
;
3216 UNDEF_LSRBaseEQDestWb
;
3219 temp
= LHS
+ LSRegRHS
;
3220 if (LoadWord (state
, instr
, temp
))
3224 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
3229 && handle_v6_insn (state
, instr
))
3232 ARMul_UndefInstr (state
, instr
);
3235 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
3238 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
3241 ARMul_UndefInstr (state
, instr
);
3244 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
3247 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
3250 ARMul_UndefInstr (state
, instr
);
3253 UNDEF_LSRBaseEQOffWb
;
3254 UNDEF_LSRBaseEQDestWb
;
3257 temp
= LHS
+ LSRegRHS
;
3258 if (StoreByte (state
, instr
, temp
))
3262 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
3265 /* Check for the special breakpoint opcode.
3266 This value should correspond to the value defined
3267 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
3268 if (BITS (0, 19) == 0xfdefe)
3270 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
3271 ARMul_Abort (state
, ARMul_SWIV
);
3274 ARMul_UndefInstr (state
, instr
);
3277 UNDEF_LSRBaseEQOffWb
;
3278 UNDEF_LSRBaseEQDestWb
;
3281 temp
= LHS
+ LSRegRHS
;
3282 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3287 /* Multiple Data Transfer Instructions. */
3289 case 0x80: /* Store, No WriteBack, Post Dec. */
3290 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3293 case 0x81: /* Load, No WriteBack, Post Dec. */
3294 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3297 case 0x82: /* Store, WriteBack, Post Dec. */
3298 temp
= LSBase
- LSMNumRegs
;
3299 STOREMULT (instr
, temp
+ 4L, temp
);
3302 case 0x83: /* Load, WriteBack, Post Dec. */
3303 temp
= LSBase
- LSMNumRegs
;
3304 LOADMULT (instr
, temp
+ 4L, temp
);
3307 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
3308 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3311 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
3312 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3315 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
3316 temp
= LSBase
- LSMNumRegs
;
3317 STORESMULT (instr
, temp
+ 4L, temp
);
3320 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3321 temp
= LSBase
- LSMNumRegs
;
3322 LOADSMULT (instr
, temp
+ 4L, temp
);
3325 case 0x88: /* Store, No WriteBack, Post Inc. */
3326 STOREMULT (instr
, LSBase
, 0L);
3329 case 0x89: /* Load, No WriteBack, Post Inc. */
3330 LOADMULT (instr
, LSBase
, 0L);
3333 case 0x8a: /* Store, WriteBack, Post Inc. */
3335 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
3338 case 0x8b: /* Load, WriteBack, Post Inc. */
3340 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
3343 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3344 STORESMULT (instr
, LSBase
, 0L);
3347 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3348 LOADSMULT (instr
, LSBase
, 0L);
3351 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3353 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
3356 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3358 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
3361 case 0x90: /* Store, No WriteBack, Pre Dec. */
3362 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3365 case 0x91: /* Load, No WriteBack, Pre Dec. */
3366 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3369 case 0x92: /* Store, WriteBack, Pre Dec. */
3370 temp
= LSBase
- LSMNumRegs
;
3371 STOREMULT (instr
, temp
, temp
);
3374 case 0x93: /* Load, WriteBack, Pre Dec. */
3375 temp
= LSBase
- LSMNumRegs
;
3376 LOADMULT (instr
, temp
, temp
);
3379 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3380 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3383 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3384 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3387 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3388 temp
= LSBase
- LSMNumRegs
;
3389 STORESMULT (instr
, temp
, temp
);
3392 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3393 temp
= LSBase
- LSMNumRegs
;
3394 LOADSMULT (instr
, temp
, temp
);
3397 case 0x98: /* Store, No WriteBack, Pre Inc. */
3398 STOREMULT (instr
, LSBase
+ 4L, 0L);
3401 case 0x99: /* Load, No WriteBack, Pre Inc. */
3402 LOADMULT (instr
, LSBase
+ 4L, 0L);
3405 case 0x9a: /* Store, WriteBack, Pre Inc. */
3407 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3410 case 0x9b: /* Load, WriteBack, Pre Inc. */
3412 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3415 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3416 STORESMULT (instr
, LSBase
+ 4L, 0L);
3419 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3420 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3423 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3425 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3428 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3430 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3434 /* Branch forward. */
3443 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3448 /* Branch backward. */
3457 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3462 /* Branch and Link forward. */
3471 /* Put PC into Link. */
3473 state
->Reg
[14] = pc
+ 4;
3475 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3477 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3482 /* Branch and Link backward. */
3491 /* Put PC into Link. */
3493 state
->Reg
[14] = pc
+ 4;
3495 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3497 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3502 /* Co-Processor Data Transfers. */
3506 /* Reading from R15 is UNPREDICTABLE. */
3507 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3508 ARMul_UndefInstr (state
, instr
);
3509 /* Is access to coprocessor 0 allowed ? */
3510 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3511 ARMul_UndefInstr (state
, instr
);
3512 /* Special treatment for XScale coprocessors. */
3513 else if (state
->is_XScale
)
3515 /* Only opcode 0 is supported. */
3516 if (BITS (4, 7) != 0x00)
3517 ARMul_UndefInstr (state
, instr
);
3518 /* Only coporcessor 0 is supported. */
3519 else if (CPNum
!= 0x00)
3520 ARMul_UndefInstr (state
, instr
);
3521 /* Only accumulator 0 is supported. */
3522 else if (BITS (0, 3) != 0x00)
3523 ARMul_UndefInstr (state
, instr
);
3526 /* XScale MAR insn. Move two registers into accumulator. */
3527 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3528 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3532 /* FIXME: Not sure what to do for other v5 processors. */
3533 ARMul_UndefInstr (state
, instr
);
3538 case 0xc0: /* Store , No WriteBack , Post Dec. */
3539 ARMul_STC (state
, instr
, LHS
);
3545 /* Writes to R15 are UNPREDICATABLE. */
3546 if (DESTReg
== 15 || LHSReg
== 15)
3547 ARMul_UndefInstr (state
, instr
);
3548 /* Is access to the coprocessor allowed ? */
3549 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3550 ARMul_UndefInstr (state
, instr
);
3551 /* Special handling for XScale coprcoessors. */
3552 else if (state
->is_XScale
)
3554 /* Only opcode 0 is supported. */
3555 if (BITS (4, 7) != 0x00)
3556 ARMul_UndefInstr (state
, instr
);
3557 /* Only coprocessor 0 is supported. */
3558 else if (CPNum
!= 0x00)
3559 ARMul_UndefInstr (state
, instr
);
3560 /* Only accumulator 0 is supported. */
3561 else if (BITS (0, 3) != 0x00)
3562 ARMul_UndefInstr (state
, instr
);
3565 /* XScale MRA insn. Move accumulator into two registers. */
3566 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3571 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3572 state
->Reg
[BITS (16, 19)] = t1
;
3577 /* FIXME: Not sure what to do for other v5 processors. */
3578 ARMul_UndefInstr (state
, instr
);
3583 case 0xc1: /* Load , No WriteBack , Post Dec. */
3584 ARMul_LDC (state
, instr
, LHS
);
3588 case 0xc6: /* Store , WriteBack , Post Dec. */
3590 state
->Base
= lhs
- LSCOff
;
3591 ARMul_STC (state
, instr
, lhs
);
3595 case 0xc7: /* Load , WriteBack , Post Dec. */
3597 state
->Base
= lhs
- LSCOff
;
3598 ARMul_LDC (state
, instr
, lhs
);
3602 case 0xcc: /* Store , No WriteBack , Post Inc. */
3603 ARMul_STC (state
, instr
, LHS
);
3607 case 0xcd: /* Load , No WriteBack , Post Inc. */
3608 ARMul_LDC (state
, instr
, LHS
);
3612 case 0xce: /* Store , WriteBack , Post Inc. */
3614 state
->Base
= lhs
+ LSCOff
;
3615 ARMul_STC (state
, instr
, LHS
);
3619 case 0xcf: /* Load , WriteBack , Post Inc. */
3621 state
->Base
= lhs
+ LSCOff
;
3622 ARMul_LDC (state
, instr
, LHS
);
3626 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3627 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3631 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3632 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3636 case 0xd6: /* Store , WriteBack , Pre Dec. */
3639 ARMul_STC (state
, instr
, lhs
);
3643 case 0xd7: /* Load , WriteBack , Pre Dec. */
3646 ARMul_LDC (state
, instr
, lhs
);
3650 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3651 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3655 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3656 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3660 case 0xde: /* Store , WriteBack , Pre Inc. */
3663 ARMul_STC (state
, instr
, lhs
);
3667 case 0xdf: /* Load , WriteBack , Pre Inc. */
3670 ARMul_LDC (state
, instr
, lhs
);
3674 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3677 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3679 ARMul_UndefInstr (state
, instr
);
3682 if (state
->is_XScale
)
3683 switch (BITS (18, 19))
3686 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3688 /* XScale MIA instruction. Signed multiplication of
3689 two 32 bit values and addition to 40 bit accumulator. */
3690 ARMsdword Rm
= state
->Reg
[MULLHSReg
];
3691 ARMsdword Rs
= state
->Reg
[MULACCReg
];
3697 state
->Accumulator
+= Rm
* Rs
;
3703 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3705 /* XScale MIAPH instruction. */
3706 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3707 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3708 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3709 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3724 state
->Accumulator
+= t5
;
3729 state
->Accumulator
+= t5
;
3735 if (BITS (4, 11) == 1)
3737 /* XScale MIAxy instruction. */
3743 t1
= state
->Reg
[MULLHSReg
] >> 16;
3745 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3748 t2
= state
->Reg
[MULACCReg
] >> 16;
3750 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3760 state
->Accumulator
+= t5
;
3784 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3786 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3787 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3791 ARMul_MCR (state
, instr
, DEST
);
3795 ARMul_CDP (state
, instr
);
3799 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3811 temp
= ARMul_MRC (state
, instr
);
3814 ASSIGNN ((temp
& NBIT
) != 0);
3815 ASSIGNZ ((temp
& ZBIT
) != 0);
3816 ASSIGNC ((temp
& CBIT
) != 0);
3817 ASSIGNV ((temp
& VBIT
) != 0);
3824 ARMul_CDP (state
, instr
);
3828 /* SWI instruction. */
3845 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3847 /* A prefetch abort. */
3848 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
3849 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3853 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3854 ARMul_Abort (state
, ARMul_SWIV
);
3864 #ifdef NEED_UI_LOOP_HOOK
3865 if (deprecated_ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3867 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3868 deprecated_ui_loop_hook (0);
3870 #endif /* NEED_UI_LOOP_HOOK */
3872 if (state
->Emulate
== ONCE
)
3873 state
->Emulate
= STOP
;
3874 /* If we have changed mode, allow the PC to advance before stopping. */
3875 else if (state
->Emulate
== CHANGEMODE
)
3877 else if (state
->Emulate
!= RUN
)
3880 while (!stop_simulator
);
3882 state
->decoded
= decoded
;
3883 state
->loaded
= loaded
;
3889 /* This routine evaluates most Data Processing register RHS's with the S
3890 bit clear. It is intended to be called from the macro DPRegRHS, which
3891 filters the common case of an unshifted register with in line code. */
3894 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3896 ARMword shamt
, base
;
3901 /* Shift amount in a register. */
3906 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3909 base
= state
->Reg
[base
];
3910 ARMul_Icycles (state
, 1, 0L);
3911 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3912 switch ((int) BITS (5, 6))
3917 else if (shamt
>= 32)
3920 return (base
<< shamt
);
3924 else if (shamt
>= 32)
3927 return (base
>> shamt
);
3931 else if (shamt
>= 32)
3932 return ((ARMword
) ((ARMsword
) base
>> 31L));
3934 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
3940 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3945 /* Shift amount is a constant. */
3948 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3951 base
= state
->Reg
[base
];
3952 shamt
= BITS (7, 11);
3953 switch ((int) BITS (5, 6))
3956 return (base
<< shamt
);
3961 return (base
>> shamt
);
3964 return ((ARMword
) ((ARMsword
) base
>> 31L));
3966 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
3970 return ((base
>> 1) | (CFLAG
<< 31));
3972 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3979 /* This routine evaluates most Logical Data Processing register RHS's
3980 with the S bit set. It is intended to be called from the macro
3981 DPSRegRHS, which filters the common case of an unshifted register
3982 with in line code. */
3985 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3987 ARMword shamt
, base
;
3992 /* Shift amount in a register. */
3997 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4000 base
= state
->Reg
[base
];
4001 ARMul_Icycles (state
, 1, 0L);
4002 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4003 switch ((int) BITS (5, 6))
4008 else if (shamt
== 32)
4013 else if (shamt
> 32)
4020 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4021 return (base
<< shamt
);
4026 else if (shamt
== 32)
4028 ASSIGNC (base
>> 31);
4031 else if (shamt
> 32)
4038 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4039 return (base
>> shamt
);
4044 else if (shamt
>= 32)
4046 ASSIGNC (base
>> 31L);
4047 return ((ARMword
) ((ARMsword
) base
>> 31L));
4051 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4052 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4060 ASSIGNC (base
>> 31);
4065 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4066 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4072 /* Shift amount is a constant. */
4075 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4078 base
= state
->Reg
[base
];
4079 shamt
= BITS (7, 11);
4081 switch ((int) BITS (5, 6))
4084 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4085 return (base
<< shamt
);
4089 ASSIGNC (base
>> 31);
4094 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4095 return (base
>> shamt
);
4100 ASSIGNC (base
>> 31L);
4101 return ((ARMword
) ((ARMsword
) base
>> 31L));
4105 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4106 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4114 return ((base
>> 1) | (shamt
<< 31));
4118 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4119 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4127 /* This routine handles writes to register 15 when the S bit is not set. */
4130 WriteR15 (ARMul_State
* state
, ARMword src
)
4132 /* The ARM documentation states that the two least significant bits
4133 are discarded when setting PC, except in the cases handled by
4134 WriteR15Branch() below. It's probably an oversight: in THUMB
4135 mode, the second least significant bit should probably not be
4145 state
->Reg
[15] = src
& PCBITS
;
4147 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
4148 ARMul_R15Altered (state
);
4154 /* This routine handles writes to register 15 when the S bit is set. */
4157 WriteSR15 (ARMul_State
* state
, ARMword src
)
4160 if (state
->Bank
> 0)
4162 state
->Cpsr
= state
->Spsr
[state
->Bank
];
4163 ARMul_CPSRAltered (state
);
4171 state
->Reg
[15] = src
& PCBITS
;
4175 /* ARMul_R15Altered would have to support it. */
4181 if (state
->Bank
== USERBANK
)
4182 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
4184 state
->Reg
[15] = src
;
4186 ARMul_R15Altered (state
);
4191 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
4192 will switch to Thumb mode if the least significant bit is set. */
4195 WriteR15Branch (ARMul_State
* state
, ARMword src
)
4202 state
->Reg
[15] = src
& 0xfffffffe;
4207 state
->Reg
[15] = src
& 0xfffffffc;
4211 WriteR15 (state
, src
);
4215 /* This routine evaluates most Load and Store register RHS's. It is
4216 intended to be called from the macro LSRegRHS, which filters the
4217 common case of an unshifted register with in line code. */
4220 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
4222 ARMword shamt
, base
;
4227 /* Now forbidden, but ... */
4228 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4231 base
= state
->Reg
[base
];
4233 shamt
= BITS (7, 11);
4234 switch ((int) BITS (5, 6))
4237 return (base
<< shamt
);
4242 return (base
>> shamt
);
4245 return ((ARMword
) ((ARMsword
) base
>> 31L));
4247 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4251 return ((base
>> 1) | (CFLAG
<< 31));
4253 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4260 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
4263 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
4270 /* Now forbidden, but ... */
4271 return ECC
| ER15INT
| R15PC
| EMODE
;
4273 return state
->Reg
[RHSReg
];
4277 return BITS (0, 3) | (BITS (8, 11) << 4);
4280 /* This function does the work of loading a word for a LDR instruction. */
4283 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4289 if (ADDREXCEPT (address
))
4290 INTERNALABORT (address
);
4293 dest
= ARMul_LoadWordN (state
, address
);
4298 return state
->lateabtSig
;
4301 dest
= ARMul_Align (state
, address
, dest
);
4303 ARMul_Icycles (state
, 1, 0L);
4305 return (DESTReg
!= LHSReg
);
4309 /* This function does the work of loading a halfword. */
4312 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
4319 if (ADDREXCEPT (address
))
4320 INTERNALABORT (address
);
4322 dest
= ARMul_LoadHalfWord (state
, address
);
4326 return state
->lateabtSig
;
4330 if (dest
& 1 << (16 - 1))
4331 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
4334 ARMul_Icycles (state
, 1, 0L);
4335 return (DESTReg
!= LHSReg
);
4340 /* This function does the work of loading a byte for a LDRB instruction. */
4343 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
4349 if (ADDREXCEPT (address
))
4350 INTERNALABORT (address
);
4352 dest
= ARMul_LoadByte (state
, address
);
4356 return state
->lateabtSig
;
4360 if (dest
& 1 << (8 - 1))
4361 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
4364 ARMul_Icycles (state
, 1, 0L);
4366 return (DESTReg
!= LHSReg
);
4369 /* This function does the work of loading two words for a LDRD instruction. */
4372 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
4376 ARMword write_back
= BIT (21);
4377 ARMword immediate
= BIT (22);
4378 ARMword add_to_base
= BIT (23);
4379 ARMword pre_indexed
= BIT (24);
4389 /* If the writeback bit is set, the pre-index bit must be clear. */
4390 if (write_back
&& ! pre_indexed
)
4392 ARMul_UndefInstr (state
, instr
);
4396 /* Extract the base address register. */
4399 /* Extract the destination register and check it. */
4402 /* Destination register must be even. */
4404 /* Destination register cannot be LR. */
4405 || (dest_reg
== 14))
4407 ARMul_UndefInstr (state
, instr
);
4411 /* Compute the base address. */
4412 base
= state
->Reg
[addr_reg
];
4414 /* Compute the offset. */
4415 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4417 /* Compute the sum of the two. */
4419 sum
= base
+ offset
;
4421 sum
= base
- offset
;
4423 /* If this is a pre-indexed mode use the sum. */
4429 /* The address must be aligned on a 8 byte boundary. */
4433 ARMul_DATAABORT (addr
);
4435 ARMul_UndefInstr (state
, instr
);
4440 /* For pre indexed or post indexed addressing modes,
4441 check that the destination registers do not overlap
4442 the address registers. */
4443 if ((! pre_indexed
|| write_back
)
4444 && ( addr_reg
== dest_reg
4445 || addr_reg
== dest_reg
+ 1))
4447 ARMul_UndefInstr (state
, instr
);
4451 /* Load the words. */
4452 value1
= ARMul_LoadWordN (state
, addr
);
4453 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4455 /* Check for data aborts. */
4462 ARMul_Icycles (state
, 2, 0L);
4464 /* Store the values. */
4465 state
->Reg
[dest_reg
] = value1
;
4466 state
->Reg
[dest_reg
+ 1] = value2
;
4468 /* Do the post addressing and writeback. */
4472 if (! pre_indexed
|| write_back
)
4473 state
->Reg
[addr_reg
] = addr
;
4476 /* This function does the work of storing two words for a STRD instruction. */
4479 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4483 ARMword write_back
= BIT (21);
4484 ARMword immediate
= BIT (22);
4485 ARMword add_to_base
= BIT (23);
4486 ARMword pre_indexed
= BIT (24);
4494 /* If the writeback bit is set, the pre-index bit must be clear. */
4495 if (write_back
&& ! pre_indexed
)
4497 ARMul_UndefInstr (state
, instr
);
4501 /* Extract the base address register. */
4504 /* Base register cannot be PC. */
4507 ARMul_UndefInstr (state
, instr
);
4511 /* Extract the source register. */
4514 /* Source register must be even. */
4517 ARMul_UndefInstr (state
, instr
);
4521 /* Compute the base address. */
4522 base
= state
->Reg
[addr_reg
];
4524 /* Compute the offset. */
4525 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4527 /* Compute the sum of the two. */
4529 sum
= base
+ offset
;
4531 sum
= base
- offset
;
4533 /* If this is a pre-indexed mode use the sum. */
4539 /* The address must be aligned on a 8 byte boundary. */
4543 ARMul_DATAABORT (addr
);
4545 ARMul_UndefInstr (state
, instr
);
4550 /* For pre indexed or post indexed addressing modes,
4551 check that the destination registers do not overlap
4552 the address registers. */
4553 if ((! pre_indexed
|| write_back
)
4554 && ( addr_reg
== src_reg
4555 || addr_reg
== src_reg
+ 1))
4557 ARMul_UndefInstr (state
, instr
);
4561 /* Load the words. */
4562 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4563 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4571 /* Do the post addressing and writeback. */
4575 if (! pre_indexed
|| write_back
)
4576 state
->Reg
[addr_reg
] = addr
;
4579 /* This function does the work of storing a word from a STR instruction. */
4582 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4587 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4590 ARMul_StoreWordN (state
, address
, DEST
);
4592 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4594 INTERNALABORT (address
);
4595 (void) ARMul_LoadWordN (state
, address
);
4598 ARMul_StoreWordN (state
, address
, DEST
);
4603 return state
->lateabtSig
;
4609 /* This function does the work of storing a byte for a STRH instruction. */
4612 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4618 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4622 ARMul_StoreHalfWord (state
, address
, DEST
);
4624 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4626 INTERNALABORT (address
);
4627 (void) ARMul_LoadHalfWord (state
, address
);
4630 ARMul_StoreHalfWord (state
, address
, DEST
);
4636 return state
->lateabtSig
;
4643 /* This function does the work of storing a byte for a STRB instruction. */
4646 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4651 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4654 ARMul_StoreByte (state
, address
, DEST
);
4656 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4658 INTERNALABORT (address
);
4659 (void) ARMul_LoadByte (state
, address
);
4662 ARMul_StoreByte (state
, address
, DEST
);
4667 return state
->lateabtSig
;
4673 /* This function does the work of loading the registers listed in an LDM
4674 instruction, when the S bit is clear. The code here is always increment
4675 after, it's up to the caller to get the input address correct and to
4676 handle base register modification. */
4679 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4685 UNDEF_LSMBaseInListWb
;
4688 if (ADDREXCEPT (address
))
4689 INTERNALABORT (address
);
4691 if (BIT (21) && LHSReg
!= 15)
4694 /* N cycle first. */
4695 for (temp
= 0; !BIT (temp
); temp
++)
4698 dest
= ARMul_LoadWordN (state
, address
);
4700 if (!state
->abortSig
&& !state
->Aborted
)
4701 state
->Reg
[temp
++] = dest
;
4702 else if (!state
->Aborted
)
4704 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4705 state
->Aborted
= ARMul_DataAbortV
;
4708 /* S cycles from here on. */
4709 for (; temp
< 16; temp
++)
4712 /* Load this register. */
4714 dest
= ARMul_LoadWordS (state
, address
);
4716 if (!state
->abortSig
&& !state
->Aborted
)
4717 state
->Reg
[temp
] = dest
;
4718 else if (!state
->Aborted
)
4720 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4721 state
->Aborted
= ARMul_DataAbortV
;
4725 if (BIT (15) && !state
->Aborted
)
4726 /* PC is in the reg list. */
4727 WriteR15Branch (state
, PC
);
4729 /* To write back the final register. */
4730 ARMul_Icycles (state
, 1, 0L);
4734 if (BIT (21) && LHSReg
!= 15)
4740 /* This function does the work of loading the registers listed in an LDM
4741 instruction, when the S bit is set. The code here is always increment
4742 after, it's up to the caller to get the input address correct and to
4743 handle base register modification. */
4746 LoadSMult (ARMul_State
* state
,
4755 UNDEF_LSMBaseInListWb
;
4760 if (ADDREXCEPT (address
))
4761 INTERNALABORT (address
);
4764 if (BIT (21) && LHSReg
!= 15)
4767 if (!BIT (15) && state
->Bank
!= USERBANK
)
4769 /* Temporary reg bank switch. */
4770 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4771 UNDEF_LSMUserBankWb
;
4774 /* N cycle first. */
4775 for (temp
= 0; !BIT (temp
); temp
++)
4778 dest
= ARMul_LoadWordN (state
, address
);
4780 if (!state
->abortSig
)
4781 state
->Reg
[temp
++] = dest
;
4782 else if (!state
->Aborted
)
4784 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4785 state
->Aborted
= ARMul_DataAbortV
;
4788 /* S cycles from here on. */
4789 for (; temp
< 16; temp
++)
4792 /* Load this register. */
4794 dest
= ARMul_LoadWordS (state
, address
);
4796 if (!state
->abortSig
&& !state
->Aborted
)
4797 state
->Reg
[temp
] = dest
;
4798 else if (!state
->Aborted
)
4800 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4801 state
->Aborted
= ARMul_DataAbortV
;
4805 if (BIT (15) && !state
->Aborted
)
4807 /* PC is in the reg list. */
4809 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4811 state
->Cpsr
= GETSPSR (state
->Bank
);
4812 ARMul_CPSRAltered (state
);
4815 WriteR15 (state
, PC
);
4817 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4819 /* Protect bits in user mode. */
4820 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4821 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4822 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4823 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4826 ARMul_R15Altered (state
);
4832 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4833 /* Restore the correct bank. */
4834 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4836 /* To write back the final register. */
4837 ARMul_Icycles (state
, 1, 0L);
4841 if (BIT (21) && LHSReg
!= 15)
4848 /* This function does the work of storing the registers listed in an STM
4849 instruction, when the S bit is clear. The code here is always increment
4850 after, it's up to the caller to get the input address correct and to
4851 handle base register modification. */
4854 StoreMult (ARMul_State
* state
,
4863 UNDEF_LSMBaseInListWb
;
4866 /* N-cycle, increment the PC and update the NextInstr state. */
4870 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4871 INTERNALABORT (address
);
4877 /* N cycle first. */
4878 for (temp
= 0; !BIT (temp
); temp
++)
4882 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4886 (void) ARMul_LoadWordN (state
, address
);
4888 /* Fake the Stores as Loads. */
4889 for (; temp
< 16; temp
++)
4892 /* Save this register. */
4894 (void) ARMul_LoadWordS (state
, address
);
4897 if (BIT (21) && LHSReg
!= 15)
4903 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4906 if (state
->abortSig
&& !state
->Aborted
)
4908 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4909 state
->Aborted
= ARMul_DataAbortV
;
4912 if (BIT (21) && LHSReg
!= 15)
4915 /* S cycles from here on. */
4916 for (; temp
< 16; temp
++)
4919 /* Save this register. */
4922 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4924 if (state
->abortSig
&& !state
->Aborted
)
4926 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4927 state
->Aborted
= ARMul_DataAbortV
;
4935 /* This function does the work of storing the registers listed in an STM
4936 instruction when the S bit is set. The code here is always increment
4937 after, it's up to the caller to get the input address correct and to
4938 handle base register modification. */
4941 StoreSMult (ARMul_State
* state
,
4950 UNDEF_LSMBaseInListWb
;
4955 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4956 INTERNALABORT (address
);
4962 if (state
->Bank
!= USERBANK
)
4964 /* Force User Bank. */
4965 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4966 UNDEF_LSMUserBankWb
;
4969 for (temp
= 0; !BIT (temp
); temp
++)
4970 ; /* N cycle first. */
4973 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4977 (void) ARMul_LoadWordN (state
, address
);
4979 for (; temp
< 16; temp
++)
4980 /* Fake the Stores as Loads. */
4983 /* Save this register. */
4986 (void) ARMul_LoadWordS (state
, address
);
4989 if (BIT (21) && LHSReg
!= 15)
4996 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4999 if (state
->abortSig
&& !state
->Aborted
)
5001 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5002 state
->Aborted
= ARMul_DataAbortV
;
5005 /* S cycles from here on. */
5006 for (; temp
< 16; temp
++)
5009 /* Save this register. */
5012 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5014 if (state
->abortSig
&& !state
->Aborted
)
5016 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5017 state
->Aborted
= ARMul_DataAbortV
;
5021 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5022 /* Restore the correct bank. */
5023 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5025 if (BIT (21) && LHSReg
!= 15)
5032 /* This function does the work of adding two 32bit values
5033 together, and calculating if a carry has occurred. */
5036 Add32 (ARMword a1
, ARMword a2
, int *carry
)
5038 ARMword result
= (a1
+ a2
);
5039 unsigned int uresult
= (unsigned int) result
;
5040 unsigned int ua1
= (unsigned int) a1
;
5042 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5043 or (result > RdLo) then we have no carry. */
5044 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
5052 /* This function does the work of multiplying
5053 two 32bit values to give a 64bit result. */
5056 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5058 /* Operand register numbers. */
5059 int nRdHi
, nRdLo
, nRs
, nRm
;
5060 ARMword RdHi
= 0, RdLo
= 0, Rm
;
5064 nRdHi
= BITS (16, 19);
5065 nRdLo
= BITS (12, 15);
5069 /* Needed to calculate the cycle count. */
5070 Rm
= state
->Reg
[nRm
];
5072 /* Check for illegal operand combinations first. */
5081 /* Intermediate results. */
5082 ARMword lo
, mid1
, mid2
, hi
;
5084 ARMword Rs
= state
->Reg
[nRs
];
5089 /* Compute sign of result and adjust operands if necessary. */
5090 sign
= (Rm
^ Rs
) & 0x80000000;
5092 if (((ARMsword
) Rm
) < 0)
5095 if (((ARMsword
) Rs
) < 0)
5099 /* We can split the 32x32 into four 16x16 operations. This
5100 ensures that we do not lose precision on 32bit only hosts. */
5101 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
5102 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5103 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
5104 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5106 /* We now need to add all of these results together, taking
5107 care to propogate the carries from the additions. */
5108 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
5110 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
5112 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
5116 /* Negate result if necessary. */
5119 if (RdLo
== 0xFFFFFFFF)
5128 state
->Reg
[nRdLo
] = RdLo
;
5129 state
->Reg
[nRdHi
] = RdHi
;
5132 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
5135 /* Ensure that both RdHi and RdLo are used to compute Z,
5136 but don't let RdLo's sign bit make it to N. */
5137 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
5139 /* The cycle count depends on whether the instruction is a signed or
5140 unsigned multiply, and what bits are clear in the multiplier. */
5141 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
5142 /* Invert the bits to make the check against zero. */
5145 if ((Rm
& 0xFFFFFF00) == 0)
5147 else if ((Rm
& 0xFFFF0000) == 0)
5149 else if ((Rm
& 0xFF000000) == 0)
5157 /* This function does the work of multiplying two 32bit
5158 values and adding a 64bit value to give a 64bit result. */
5161 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5168 nRdHi
= BITS (16, 19);
5169 nRdLo
= BITS (12, 15);
5171 RdHi
= state
->Reg
[nRdHi
];
5172 RdLo
= state
->Reg
[nRdLo
];
5174 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
5176 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
5177 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
5179 state
->Reg
[nRdLo
] = RdLo
;
5180 state
->Reg
[nRdHi
] = RdHi
;
5183 /* Ensure that both RdHi and RdLo are used to compute Z,
5184 but don't let RdLo's sign bit make it to N. */
5185 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
5187 /* Extra cycle for addition. */
This page took 0.142233 seconds and 4 git commands to generate.