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 void WriteR15Load (ARMul_State
*, ARMword
);
29 static ARMword
GetLSRegRHS (ARMul_State
*, ARMword
);
30 static ARMword
GetLS7RHS (ARMul_State
*, ARMword
);
31 static unsigned LoadWord (ARMul_State
*, ARMword
, ARMword
);
32 static unsigned LoadHalfWord (ARMul_State
*, ARMword
, ARMword
, int);
33 static unsigned LoadByte (ARMul_State
*, ARMword
, ARMword
, int);
34 static unsigned StoreWord (ARMul_State
*, ARMword
, ARMword
);
35 static unsigned StoreHalfWord (ARMul_State
*, ARMword
, ARMword
);
36 static unsigned StoreByte (ARMul_State
*, ARMword
, ARMword
);
37 static void LoadMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
38 static void StoreMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
39 static void LoadSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
40 static void StoreSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
41 static unsigned Multiply64 (ARMul_State
*, ARMword
, int, int);
42 static unsigned MultiplyAdd64 (ARMul_State
*, ARMword
, int, int);
43 static void Handle_Load_Double (ARMul_State
*, ARMword
);
44 static void Handle_Store_Double (ARMul_State
*, ARMword
);
46 #define LUNSIGNED (0) /* unsigned operation */
47 #define LSIGNED (1) /* signed operation */
48 #define LDEFAULT (0) /* default : do nothing */
49 #define LSCC (1) /* set condition codes on result */
51 #ifdef NEED_UI_LOOP_HOOK
52 /* How often to run the ui_loop update, when in use. */
53 #define UI_LOOP_POLL_INTERVAL 0x32000
55 /* Counter for the ui_loop_hook update. */
56 static long ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
58 /* Actual hook to call to run through gdb's gui event loop. */
59 extern int (*deprecated_ui_loop_hook
) (int);
60 #endif /* NEED_UI_LOOP_HOOK */
62 extern int stop_simulator
;
64 /* Short-hand macros for LDR/STR. */
66 /* Store post decrement writeback. */
69 if (StoreHalfWord (state, instr, lhs)) \
70 LSBase = lhs - GetLS7RHS (state, instr);
72 /* Store post increment writeback. */
75 if (StoreHalfWord (state, instr, lhs)) \
76 LSBase = lhs + GetLS7RHS (state, instr);
78 /* Store pre decrement. */
80 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
82 /* Store pre decrement writeback. */
83 #define SHPREDOWNWB() \
84 temp = LHS - GetLS7RHS (state, instr); \
85 if (StoreHalfWord (state, instr, temp)) \
88 /* Store pre increment. */
90 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
92 /* Store pre increment writeback. */
94 temp = LHS + GetLS7RHS (state, instr); \
95 if (StoreHalfWord (state, instr, temp)) \
98 /* Load post decrement writeback. */
99 #define LHPOSTDOWN() \
103 temp = lhs - GetLS7RHS (state, instr); \
105 switch (BITS (5, 6)) \
108 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
112 if (LoadByte (state, instr, lhs, LSIGNED)) \
116 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
119 case 0: /* SWP handled elsewhere. */ \
128 /* Load post increment writeback. */
133 temp = lhs + GetLS7RHS (state, instr); \
135 switch (BITS (5, 6)) \
138 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
142 if (LoadByte (state, instr, lhs, LSIGNED)) \
146 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
149 case 0: /* SWP handled elsewhere. */ \
158 /* Load pre decrement. */
159 #define LHPREDOWN() \
163 temp = LHS - GetLS7RHS (state, instr); \
164 switch (BITS (5, 6)) \
167 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
170 (void) LoadByte (state, instr, temp, LSIGNED); \
173 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
176 /* SWP handled elsewhere. */ \
185 /* Load pre decrement writeback. */
186 #define LHPREDOWNWB() \
190 temp = LHS - GetLS7RHS (state, instr); \
191 switch (BITS (5, 6)) \
194 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
198 if (LoadByte (state, instr, temp, LSIGNED)) \
202 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
206 /* SWP handled elsewhere. */ \
215 /* Load pre increment. */
220 temp = LHS + GetLS7RHS (state, instr); \
221 switch (BITS (5, 6)) \
224 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
227 (void) LoadByte (state, instr, temp, LSIGNED); \
230 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
233 /* SWP handled elsewhere. */ \
242 /* Load pre increment writeback. */
243 #define LHPREUPWB() \
247 temp = LHS + GetLS7RHS (state, instr); \
248 switch (BITS (5, 6)) \
251 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
255 if (LoadByte (state, instr, temp, LSIGNED)) \
259 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
263 /* SWP handled elsewhere. */ \
272 /* Attempt to emulate an ARMv6 instruction.
273 Returns non-zero upon success. */
277 handle_v6_insn (ARMul_State
* state
, ARMword instr
)
279 switch (BITS (20, 27))
282 case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
283 case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
284 case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
285 case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
286 case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
287 case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
288 case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
289 case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
290 case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
291 case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
292 case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
293 case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
294 case 0x30: printf ("Unhandled v6 insn: movw\n"); break;
295 case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
296 case 0x34: printf ("Unhandled v6 insn: movt\n"); break;
297 case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
299 case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
300 case 0x62: printf ("Unhandled v6 insn: qadd/qsub\n"); break;
301 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
302 case 0x65: printf ("Unhandled v6 insn: uadd/usub\n"); break;
303 case 0x66: printf ("Unhandled v6 insn: uqadd/uqsub\n"); break;
304 case 0x67: printf ("Unhandled v6 insn: uhadd/uhsub\n"); break;
305 case 0x68: printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); break;
306 case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
307 case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
308 case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
309 case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
310 case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
311 case 0x7a: printf ("Unhandled v6 insn: usbfx\n"); break;
312 case 0x7c: printf ("Unhandled v6 insn: bfc/bfi\n"); break;
319 switch (BITS (4, 11))
321 case 0x07: ror
= 0; break;
322 case 0x47: ror
= 8; break;
323 case 0x87: ror
= 16; break;
324 case 0xc7: ror
= 24; break;
328 printf ("Unhandled v6 insn: ssat\n");
336 if (BITS (4, 6) == 0x7)
338 printf ("Unhandled v6 insn: ssat\n");
344 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
348 if (BITS (16, 19) == 0xf)
350 state
->Reg
[BITS (12, 15)] = Rm
;
353 state
->Reg
[BITS (12, 15)] += Rm
;
362 switch (BITS (4, 11))
364 case 0x07: ror
= 0; break;
365 case 0x47: ror
= 8; break;
366 case 0x87: ror
= 16; break;
367 case 0xc7: ror
= 24; break;
370 printf ("Unhandled v6 insn: rev\n");
379 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
383 if (BITS (16, 19) == 0xf)
385 state
->Reg
[BITS (12, 15)] = Rm
;
388 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
397 switch (BITS (4, 11))
399 case 0x07: ror
= 0; break;
400 case 0x47: ror
= 8; break;
401 case 0x87: ror
= 16; break;
402 case 0xc7: ror
= 24; break;
406 printf ("Unhandled v6 insn: usat\n");
414 if (BITS (4, 6) == 0x7)
416 printf ("Unhandled v6 insn: usat\n");
422 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
424 if (BITS (16, 19) == 0xf)
426 state
->Reg
[BITS (12, 15)] = Rm
;
429 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
438 switch (BITS (4, 11))
440 case 0x07: ror
= 0; break;
441 case 0x47: ror
= 8; break;
442 case 0x87: ror
= 16; break;
443 case 0xc7: ror
= 24; break;
446 printf ("Unhandled v6 insn: revsh\n");
455 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
457 if (BITS (16, 19) == 0xf)
459 state
->Reg
[BITS (12, 15)] = Rm
;
463 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
469 case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
474 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr
);
479 /* EMULATION of ARM6. */
481 /* The PC pipeline value depends on whether ARM
482 or Thumb instructions are being executed. */
487 ARMul_Emulate32 (ARMul_State
* state
)
489 ARMul_Emulate26 (ARMul_State
* state
)
492 ARMword instr
; /* The current instruction. */
493 ARMword dest
= 0; /* Almost the DestBus. */
494 ARMword temp
; /* Ubiquitous third hand. */
495 ARMword pc
= 0; /* The address of the current instruction. */
496 ARMword lhs
; /* Almost the ABus and BBus. */
498 ARMword decoded
= 0; /* Instruction pipeline. */
501 /* Execute the next instruction. */
503 if (state
->NextInstr
< PRIMEPIPE
)
505 decoded
= state
->decoded
;
506 loaded
= state
->loaded
;
512 /* Just keep going. */
515 switch (state
->NextInstr
)
518 /* Advance the pipeline, and an S cycle. */
519 state
->Reg
[15] += isize
;
523 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
527 /* Advance the pipeline, and an N cycle. */
528 state
->Reg
[15] += isize
;
532 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
537 /* Program counter advanced, and an S cycle. */
541 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
546 /* Program counter advanced, and an N cycle. */
550 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
555 /* The program counter has been changed. */
560 state
->Reg
[15] = pc
+ (isize
* 2);
562 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
563 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
564 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
569 /* The program counter has been changed. */
574 state
->Reg
[15] = pc
+ (isize
* 2);
576 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
577 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
578 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
584 ARMul_EnvokeEvent (state
);
586 if (! TFLAG
&& trace
)
588 fprintf (stderr
, "pc: %x, ", pc
& ~1);
590 fprintf (stderr
, "instr: %x\n", instr
);
593 if (instr
== 0 || pc
< 0x10)
595 ARMul_Abort (state
, ARMUndefinedInstrV
);
596 state
->Emulate
= FALSE
;
599 #if 0 /* Enable this code to help track down stack alignment bugs. */
601 static ARMword old_sp
= -1;
603 if (old_sp
!= state
->Reg
[13])
605 old_sp
= state
->Reg
[13];
606 fprintf (stderr
, "pc: %08x: SP set to %08x%s\n",
607 pc
& ~1, old_sp
, (old_sp
% 8) ? " [UNALIGNED!]" : "");
612 if (state
->Exception
)
614 /* Any exceptions ? */
615 if (state
->NresetSig
== LOW
)
617 ARMul_Abort (state
, ARMul_ResetV
);
620 else if (!state
->NfiqSig
&& !FFLAG
)
622 ARMul_Abort (state
, ARMul_FIQV
);
625 else if (!state
->NirqSig
&& !IFLAG
)
627 ARMul_Abort (state
, ARMul_IRQV
);
632 if (state
->CallDebug
> 0)
634 instr
= ARMul_Debug (state
, pc
, instr
);
635 if (state
->Emulate
< ONCE
)
637 state
->NextInstr
= RESUME
;
642 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n",
643 (long) pc
, (long) instr
, (long) state
->Mode
);
644 (void) fgetc (stdin
);
647 else if (state
->Emulate
< ONCE
)
649 state
->NextInstr
= RESUME
;
656 /* Provide Thumb instruction decoding. If the processor is in Thumb
657 mode, then we can simply decode the Thumb instruction, and map it
658 to the corresponding ARM instruction (by directly loading the
659 instr variable, and letting the normal ARM simulator
660 execute). There are some caveats to ensure that the correct
661 pipelined PC value is used when executing Thumb code, and also for
662 dealing with the BL instruction. */
667 /* Check if in Thumb mode. */
668 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
671 /* This is a Thumb instruction. */
672 ARMul_UndefInstr (state
, instr
);
676 /* Already processed. */
680 /* ARM instruction available. */
683 fprintf (stderr
, " emulate as: ");
685 fprintf (stderr
, "%08x ", new);
687 fprintf (stderr
, "\n");
690 /* So continue instruction decoding. */
700 /* Check the condition codes. */
701 if ((temp
= TOPBITS (28)) == AL
)
702 /* Vile deed in the need for speed. */
705 /* Check the condition code. */
706 switch ((int) TOPBITS (28))
714 if (BITS (25, 27) == 5) /* BLX(1) */
718 state
->Reg
[14] = pc
+ 4;
720 /* Force entry into Thumb mode. */
723 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
725 dest
+= POSBRANCH
+ (BIT (24) << 1);
727 WriteR15Branch (state
, dest
);
730 else if ((instr
& 0xFC70F000) == 0xF450F000)
731 /* The PLD instruction. Ignored. */
733 else if ( ((instr
& 0xfe500f00) == 0xfc100100)
734 || ((instr
& 0xfe500f00) == 0xfc000100))
735 /* wldrw and wstrw are unconditional. */
738 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
739 ARMul_UndefInstr (state
, instr
);
768 temp
= (CFLAG
&& !ZFLAG
);
771 temp
= (!CFLAG
|| ZFLAG
);
774 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
777 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
780 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
783 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
787 /* Handle the Clock counter here. */
788 if (state
->is_XScale
)
793 ok
= state
->CPRead
[14] (state
, 0, & cp14r0
);
795 if (ok
&& (cp14r0
& ARMul_CP14_R0_ENABLE
))
797 unsigned long newcycles
, nowtime
= ARMul_Time (state
);
799 newcycles
= nowtime
- state
->LastTime
;
800 state
->LastTime
= nowtime
;
802 if (cp14r0
& ARMul_CP14_R0_CCD
)
804 if (state
->CP14R0_CCD
== -1)
805 state
->CP14R0_CCD
= newcycles
;
807 state
->CP14R0_CCD
+= newcycles
;
809 if (state
->CP14R0_CCD
>= 64)
813 while (state
->CP14R0_CCD
>= 64)
814 state
->CP14R0_CCD
-= 64, newcycles
++;
824 state
->CP14R0_CCD
= -1;
827 cp14r0
|= ARMul_CP14_R0_FLAG2
;
828 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
830 ok
= state
->CPRead
[14] (state
, 1, & cp14r1
);
832 /* Coded like this for portability. */
833 while (ok
&& newcycles
)
835 if (cp14r1
== 0xffffffff)
846 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
848 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
852 if (state
->CPRead
[13] (state
, 8, & temp
)
853 && (temp
& ARMul_CP13_R8_PMUS
))
854 ARMul_Abort (state
, ARMul_FIQV
);
856 ARMul_Abort (state
, ARMul_IRQV
);
862 /* Handle hardware instructions breakpoints here. */
863 if (state
->is_XScale
)
865 if ( (pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
866 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
868 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
869 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
873 /* Actual execution of instructions begins here. */
874 /* If the condition codes don't match, stop here. */
879 if (state
->is_XScale
)
881 if (BIT (20) == 0 && BITS (25, 27) == 0)
883 if (BITS (4, 7) == 0xD)
885 /* XScale Load Consecutive insn. */
886 ARMword temp
= GetLS7RHS (state
, instr
);
887 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
888 ARMword addr
= BIT (24) ? temp2
: LHS
;
891 ARMul_UndefInstr (state
, instr
);
893 /* Alignment violation. */
894 ARMul_Abort (state
, ARMul_DataAbortV
);
897 int wb
= BIT (21) || (! BIT (24));
899 state
->Reg
[BITS (12, 15)] =
900 ARMul_LoadWordN (state
, addr
);
901 state
->Reg
[BITS (12, 15) + 1] =
902 ARMul_LoadWordN (state
, addr
+ 4);
909 else if (BITS (4, 7) == 0xF)
911 /* XScale Store Consecutive insn. */
912 ARMword temp
= GetLS7RHS (state
, instr
);
913 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
914 ARMword addr
= BIT (24) ? temp2
: LHS
;
917 ARMul_UndefInstr (state
, instr
);
919 /* Alignment violation. */
920 ARMul_Abort (state
, ARMul_DataAbortV
);
923 ARMul_StoreWordN (state
, addr
,
924 state
->Reg
[BITS (12, 15)]);
925 ARMul_StoreWordN (state
, addr
+ 4,
926 state
->Reg
[BITS (12, 15) + 1]);
928 if (BIT (21)|| ! BIT (24))
936 if (ARMul_HandleIwmmxt (state
, instr
))
940 switch ((int) BITS (20, 27))
942 /* Data Processing Register RHS Instructions. */
944 case 0x00: /* AND reg and MUL */
946 if (BITS (4, 11) == 0xB)
948 /* STRH register offset, no write-back, down, post indexed. */
952 if (BITS (4, 7) == 0xD)
954 Handle_Load_Double (state
, instr
);
957 if (BITS (4, 7) == 0xF)
959 Handle_Store_Double (state
, instr
);
963 if (BITS (4, 7) == 9)
966 rhs
= state
->Reg
[MULRHSReg
];
967 if (MULLHSReg
== MULDESTReg
)
970 state
->Reg
[MULDESTReg
] = 0;
972 else if (MULDESTReg
!= 15)
973 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
977 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
978 if (rhs
& (1L << dest
))
981 /* Mult takes this many/2 I cycles. */
982 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
993 case 0x01: /* ANDS reg and MULS */
995 if ((BITS (4, 11) & 0xF9) == 0x9)
996 /* LDR register offset, no write-back, down, post indexed. */
998 /* Fall through to rest of decoding. */
1000 if (BITS (4, 7) == 9)
1003 rhs
= state
->Reg
[MULRHSReg
];
1005 if (MULLHSReg
== MULDESTReg
)
1008 state
->Reg
[MULDESTReg
] = 0;
1012 else if (MULDESTReg
!= 15)
1014 dest
= state
->Reg
[MULLHSReg
] * rhs
;
1015 ARMul_NegZero (state
, dest
);
1016 state
->Reg
[MULDESTReg
] = dest
;
1021 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1022 if (rhs
& (1L << dest
))
1025 /* Mult takes this many/2 I cycles. */
1026 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1037 case 0x02: /* EOR reg and MLA */
1039 if (BITS (4, 11) == 0xB)
1041 /* STRH register offset, write-back, down, post indexed. */
1046 if (BITS (4, 7) == 9)
1048 rhs
= state
->Reg
[MULRHSReg
];
1049 if (MULLHSReg
== MULDESTReg
)
1052 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
1054 else if (MULDESTReg
!= 15)
1055 state
->Reg
[MULDESTReg
] =
1056 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1060 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1061 if (rhs
& (1L << dest
))
1064 /* Mult takes this many/2 I cycles. */
1065 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1075 case 0x03: /* EORS reg and MLAS */
1077 if ((BITS (4, 11) & 0xF9) == 0x9)
1078 /* LDR register offset, write-back, down, post-indexed. */
1080 /* Fall through to rest of the decoding. */
1082 if (BITS (4, 7) == 9)
1085 rhs
= state
->Reg
[MULRHSReg
];
1087 if (MULLHSReg
== MULDESTReg
)
1090 dest
= state
->Reg
[MULACCReg
];
1091 ARMul_NegZero (state
, dest
);
1092 state
->Reg
[MULDESTReg
] = dest
;
1094 else if (MULDESTReg
!= 15)
1097 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1098 ARMul_NegZero (state
, dest
);
1099 state
->Reg
[MULDESTReg
] = dest
;
1104 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1105 if (rhs
& (1L << dest
))
1108 /* Mult takes this many/2 I cycles. */
1109 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1120 case 0x04: /* SUB reg */
1122 if (BITS (4, 7) == 0xB)
1124 /* STRH immediate offset, no write-back, down, post indexed. */
1128 if (BITS (4, 7) == 0xD)
1130 Handle_Load_Double (state
, instr
);
1133 if (BITS (4, 7) == 0xF)
1135 Handle_Store_Double (state
, instr
);
1144 case 0x05: /* SUBS reg */
1146 if ((BITS (4, 7) & 0x9) == 0x9)
1147 /* LDR immediate offset, no write-back, down, post indexed. */
1149 /* Fall through to the rest of the instruction decoding. */
1155 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1157 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1158 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1168 case 0x06: /* RSB reg */
1170 if (BITS (4, 7) == 0xB)
1172 /* STRH immediate offset, write-back, down, post indexed. */
1182 case 0x07: /* RSBS reg */
1184 if ((BITS (4, 7) & 0x9) == 0x9)
1185 /* LDR immediate offset, write-back, down, post indexed. */
1187 /* Fall through to remainder of instruction decoding. */
1193 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1195 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1196 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1206 case 0x08: /* ADD reg */
1208 if (BITS (4, 11) == 0xB)
1210 /* STRH register offset, no write-back, up, post indexed. */
1214 if (BITS (4, 7) == 0xD)
1216 Handle_Load_Double (state
, instr
);
1219 if (BITS (4, 7) == 0xF)
1221 Handle_Store_Double (state
, instr
);
1226 if (BITS (4, 7) == 0x9)
1230 ARMul_Icycles (state
,
1231 Multiply64 (state
, instr
, LUNSIGNED
,
1241 case 0x09: /* ADDS reg */
1243 if ((BITS (4, 11) & 0xF9) == 0x9)
1244 /* LDR register offset, no write-back, up, post indexed. */
1246 /* Fall through to remaining instruction decoding. */
1249 if (BITS (4, 7) == 0x9)
1253 ARMul_Icycles (state
,
1254 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
1262 ASSIGNZ (dest
== 0);
1263 if ((lhs
| rhs
) >> 30)
1265 /* Possible C,V,N to set. */
1266 ASSIGNN (NEG (dest
));
1267 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1268 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1279 case 0x0a: /* ADC reg */
1281 if (BITS (4, 11) == 0xB)
1283 /* STRH register offset, write-back, up, post-indexed. */
1287 if (BITS (4, 7) == 0x9)
1291 ARMul_Icycles (state
,
1292 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1298 dest
= LHS
+ rhs
+ CFLAG
;
1302 case 0x0b: /* ADCS reg */
1304 if ((BITS (4, 11) & 0xF9) == 0x9)
1305 /* LDR register offset, write-back, up, post indexed. */
1307 /* Fall through to remaining instruction decoding. */
1308 if (BITS (4, 7) == 0x9)
1312 ARMul_Icycles (state
,
1313 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1320 dest
= lhs
+ rhs
+ CFLAG
;
1321 ASSIGNZ (dest
== 0);
1322 if ((lhs
| rhs
) >> 30)
1324 /* Possible C,V,N to set. */
1325 ASSIGNN (NEG (dest
));
1326 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1327 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1338 case 0x0c: /* SBC reg */
1340 if (BITS (4, 7) == 0xB)
1342 /* STRH immediate offset, no write-back, up post indexed. */
1346 if (BITS (4, 7) == 0xD)
1348 Handle_Load_Double (state
, instr
);
1351 if (BITS (4, 7) == 0xF)
1353 Handle_Store_Double (state
, instr
);
1356 if (BITS (4, 7) == 0x9)
1360 ARMul_Icycles (state
,
1361 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
1367 dest
= LHS
- rhs
- !CFLAG
;
1371 case 0x0d: /* SBCS reg */
1373 if ((BITS (4, 7) & 0x9) == 0x9)
1374 /* LDR immediate offset, no write-back, up, post indexed. */
1377 if (BITS (4, 7) == 0x9)
1381 ARMul_Icycles (state
,
1382 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
1389 dest
= lhs
- rhs
- !CFLAG
;
1390 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1392 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1393 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1403 case 0x0e: /* RSC reg */
1405 if (BITS (4, 7) == 0xB)
1407 /* STRH immediate offset, write-back, up, post indexed. */
1412 if (BITS (4, 7) == 0x9)
1416 ARMul_Icycles (state
,
1417 MultiplyAdd64 (state
, instr
, LSIGNED
,
1423 dest
= rhs
- LHS
- !CFLAG
;
1427 case 0x0f: /* RSCS reg */
1429 if ((BITS (4, 7) & 0x9) == 0x9)
1430 /* LDR immediate offset, write-back, up, post indexed. */
1432 /* Fall through to remaining instruction decoding. */
1434 if (BITS (4, 7) == 0x9)
1438 ARMul_Icycles (state
,
1439 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
1446 dest
= rhs
- lhs
- !CFLAG
;
1448 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1450 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1451 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1461 case 0x10: /* TST reg and MRS CPSR and SWP word. */
1464 if (BIT (4) == 0 && BIT (7) == 1)
1466 /* ElSegundo SMLAxy insn. */
1467 ARMword op1
= state
->Reg
[BITS (0, 3)];
1468 ARMword op2
= state
->Reg
[BITS (8, 11)];
1469 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1483 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
1485 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
1489 if (BITS (4, 11) == 5)
1491 /* ElSegundo QADD insn. */
1492 ARMword op1
= state
->Reg
[BITS (0, 3)];
1493 ARMword op2
= state
->Reg
[BITS (16, 19)];
1494 ARMword result
= op1
+ op2
;
1495 if (AddOverflow (op1
, op2
, result
))
1497 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1500 state
->Reg
[BITS (12, 15)] = result
;
1505 if (BITS (4, 11) == 0xB)
1507 /* STRH register offset, no write-back, down, pre indexed. */
1511 if (BITS (4, 7) == 0xD)
1513 Handle_Load_Double (state
, instr
);
1516 if (BITS (4, 7) == 0xF)
1518 Handle_Store_Double (state
, instr
);
1522 if (BITS (4, 11) == 9)
1529 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1531 INTERNALABORT (temp
);
1532 (void) ARMul_LoadWordN (state
, temp
);
1533 (void) ARMul_LoadWordN (state
, temp
);
1537 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1539 DEST
= ARMul_Align (state
, temp
, dest
);
1542 if (state
->abortSig
|| state
->Aborted
)
1545 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1548 DEST
= ECC
| EINT
| EMODE
;
1556 case 0x11: /* TSTP reg */
1558 if ((BITS (4, 11) & 0xF9) == 0x9)
1559 /* LDR register offset, no write-back, down, pre indexed. */
1561 /* Continue with remaining instruction decode. */
1567 state
->Cpsr
= GETSPSR (state
->Bank
);
1568 ARMul_CPSRAltered (state
);
1580 ARMul_NegZero (state
, dest
);
1584 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
1587 if (BITS (4, 7) == 3)
1593 temp
= (pc
+ 2) | 1;
1597 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1598 state
->Reg
[14] = temp
;
1605 if (BIT (4) == 0 && BIT (7) == 1
1606 && (BIT (5) == 0 || BITS (12, 15) == 0))
1608 /* ElSegundo SMLAWy/SMULWy insn. */
1609 ARMdword op1
= state
->Reg
[BITS (0, 3)];
1610 ARMdword op2
= state
->Reg
[BITS (8, 11)];
1615 if (op1
& 0x80000000)
1620 result
= (op1
* op2
) >> 16;
1624 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1626 if (AddOverflow (result
, Rn
, result
+ Rn
))
1630 state
->Reg
[BITS (16, 19)] = result
;
1634 if (BITS (4, 11) == 5)
1636 /* ElSegundo QSUB insn. */
1637 ARMword op1
= state
->Reg
[BITS (0, 3)];
1638 ARMword op2
= state
->Reg
[BITS (16, 19)];
1639 ARMword result
= op1
- op2
;
1641 if (SubOverflow (op1
, op2
, result
))
1643 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1647 state
->Reg
[BITS (12, 15)] = result
;
1652 if (BITS (4, 11) == 0xB)
1654 /* STRH register offset, write-back, down, pre indexed. */
1658 if (BITS (4, 27) == 0x12FFF1)
1661 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1664 if (BITS (4, 7) == 0xD)
1666 Handle_Load_Double (state
, instr
);
1669 if (BITS (4, 7) == 0xF)
1671 Handle_Store_Double (state
, instr
);
1677 if (BITS (4, 7) == 0x7)
1679 extern int SWI_vector_installed
;
1681 /* Hardware is allowed to optionally override this
1682 instruction and treat it as a breakpoint. Since
1683 this is a simulator not hardware, we take the position
1684 that if a SWI vector was not installed, then an Abort
1685 vector was probably not installed either, and so
1686 normally this instruction would be ignored, even if an
1687 Abort is generated. This is a bad thing, since GDB
1688 uses this instruction for its breakpoints (at least in
1689 Thumb mode it does). So intercept the instruction here
1690 and generate a breakpoint SWI instead. */
1691 if (! SWI_vector_installed
)
1692 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1695 /* BKPT - normally this will cause an abort, but on the
1696 XScale we must check the DCSR. */
1697 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
1698 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
1702 /* Force the next instruction to be refetched. */
1703 state
->NextInstr
= RESUME
;
1709 /* MSR reg to CPSR. */
1713 /* Don't allow TBIT to be set by MSR. */
1716 ARMul_FixCPSR (state
, instr
, temp
);
1723 case 0x13: /* TEQP reg */
1725 if ((BITS (4, 11) & 0xF9) == 0x9)
1726 /* LDR register offset, write-back, down, pre indexed. */
1728 /* Continue with remaining instruction decode. */
1734 state
->Cpsr
= GETSPSR (state
->Bank
);
1735 ARMul_CPSRAltered (state
);
1747 ARMul_NegZero (state
, dest
);
1751 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
1754 if (BIT (4) == 0 && BIT (7) == 1)
1756 /* ElSegundo SMLALxy insn. */
1757 ARMdword op1
= state
->Reg
[BITS (0, 3)];
1758 ARMdword op2
= state
->Reg
[BITS (8, 11)];
1772 dest
= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
1773 dest
|= state
->Reg
[BITS (12, 15)];
1775 state
->Reg
[BITS (12, 15)] = dest
;
1776 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1780 if (BITS (4, 11) == 5)
1782 /* ElSegundo QDADD insn. */
1783 ARMword op1
= state
->Reg
[BITS (0, 3)];
1784 ARMword op2
= state
->Reg
[BITS (16, 19)];
1785 ARMword op2d
= op2
+ op2
;
1788 if (AddOverflow (op2
, op2
, op2d
))
1791 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1794 result
= op1
+ op2d
;
1795 if (AddOverflow (op1
, op2d
, result
))
1798 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1801 state
->Reg
[BITS (12, 15)] = result
;
1806 if (BITS (4, 7) == 0xB)
1808 /* STRH immediate offset, no write-back, down, pre indexed. */
1812 if (BITS (4, 7) == 0xD)
1814 Handle_Load_Double (state
, instr
);
1817 if (BITS (4, 7) == 0xF)
1819 Handle_Store_Double (state
, instr
);
1823 if (BITS (4, 11) == 9)
1830 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1832 INTERNALABORT (temp
);
1833 (void) ARMul_LoadByte (state
, temp
);
1834 (void) ARMul_LoadByte (state
, temp
);
1838 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1839 if (state
->abortSig
|| state
->Aborted
)
1842 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1846 DEST
= GETSPSR (state
->Bank
);
1853 case 0x15: /* CMPP reg. */
1855 if ((BITS (4, 7) & 0x9) == 0x9)
1856 /* LDR immediate offset, no write-back, down, pre indexed. */
1858 /* Continue with remaining instruction decode. */
1864 state
->Cpsr
= GETSPSR (state
->Bank
);
1865 ARMul_CPSRAltered (state
);
1878 ARMul_NegZero (state
, dest
);
1879 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1881 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1882 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1892 case 0x16: /* CMN reg and MSR reg to SPSR */
1895 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1897 /* ElSegundo SMULxy insn. */
1898 ARMword op1
= state
->Reg
[BITS (0, 3)];
1899 ARMword op2
= state
->Reg
[BITS (8, 11)];
1912 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1916 if (BITS (4, 11) == 5)
1918 /* ElSegundo QDSUB insn. */
1919 ARMword op1
= state
->Reg
[BITS (0, 3)];
1920 ARMword op2
= state
->Reg
[BITS (16, 19)];
1921 ARMword op2d
= op2
+ op2
;
1924 if (AddOverflow (op2
, op2
, op2d
))
1927 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1930 result
= op1
- op2d
;
1931 if (SubOverflow (op1
, op2d
, result
))
1934 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1937 state
->Reg
[BITS (12, 15)] = result
;
1944 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1946 /* ARM5 CLZ insn. */
1947 ARMword op1
= state
->Reg
[BITS (0, 3)];
1951 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1954 state
->Reg
[BITS (12, 15)] = result
;
1959 if (BITS (4, 7) == 0xB)
1961 /* STRH immediate offset, write-back, down, pre indexed. */
1965 if (BITS (4, 7) == 0xD)
1967 Handle_Load_Double (state
, instr
);
1970 if (BITS (4, 7) == 0xF)
1972 Handle_Store_Double (state
, instr
);
1980 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1988 case 0x17: /* CMNP reg */
1990 if ((BITS (4, 7) & 0x9) == 0x9)
1991 /* LDR immediate offset, write-back, down, pre indexed. */
1993 /* Continue with remaining instruction decoding. */
1998 state
->Cpsr
= GETSPSR (state
->Bank
);
1999 ARMul_CPSRAltered (state
);
2013 ASSIGNZ (dest
== 0);
2014 if ((lhs
| rhs
) >> 30)
2016 /* Possible C,V,N to set. */
2017 ASSIGNN (NEG (dest
));
2018 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2019 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2030 case 0x18: /* ORR reg */
2032 if (BITS (4, 11) == 0xB)
2034 /* STRH register offset, no write-back, up, pre indexed. */
2038 if (BITS (4, 7) == 0xD)
2040 Handle_Load_Double (state
, instr
);
2043 if (BITS (4, 7) == 0xF)
2045 Handle_Store_Double (state
, instr
);
2054 case 0x19: /* ORRS reg */
2056 if ((BITS (4, 11) & 0xF9) == 0x9)
2057 /* LDR register offset, no write-back, up, pre indexed. */
2059 /* Continue with remaining instruction decoding. */
2066 case 0x1a: /* MOV reg */
2068 if (BITS (4, 11) == 0xB)
2070 /* STRH register offset, write-back, up, pre indexed. */
2074 if (BITS (4, 7) == 0xD)
2076 Handle_Load_Double (state
, instr
);
2079 if (BITS (4, 7) == 0xF)
2081 Handle_Store_Double (state
, instr
);
2089 case 0x1b: /* MOVS reg */
2091 if ((BITS (4, 11) & 0xF9) == 0x9)
2092 /* LDR register offset, write-back, up, pre indexed. */
2094 /* Continue with remaining instruction decoding. */
2100 case 0x1c: /* BIC reg */
2102 if (BITS (4, 7) == 0xB)
2104 /* STRH immediate offset, no write-back, up, pre indexed. */
2108 if (BITS (4, 7) == 0xD)
2110 Handle_Load_Double (state
, instr
);
2113 else if (BITS (4, 7) == 0xF)
2115 Handle_Store_Double (state
, instr
);
2124 case 0x1d: /* BICS reg */
2126 if ((BITS (4, 7) & 0x9) == 0x9)
2127 /* LDR immediate offset, no write-back, up, pre indexed. */
2129 /* Continue with instruction decoding. */
2136 case 0x1e: /* MVN reg */
2138 if (BITS (4, 7) == 0xB)
2140 /* STRH immediate offset, write-back, up, pre indexed. */
2144 if (BITS (4, 7) == 0xD)
2146 Handle_Load_Double (state
, instr
);
2149 if (BITS (4, 7) == 0xF)
2151 Handle_Store_Double (state
, instr
);
2159 case 0x1f: /* MVNS reg */
2161 if ((BITS (4, 7) & 0x9) == 0x9)
2162 /* LDR immediate offset, write-back, up, pre indexed. */
2164 /* Continue instruction decoding. */
2171 /* Data Processing Immediate RHS Instructions. */
2173 case 0x20: /* AND immed */
2174 dest
= LHS
& DPImmRHS
;
2178 case 0x21: /* ANDS immed */
2184 case 0x22: /* EOR immed */
2185 dest
= LHS
^ DPImmRHS
;
2189 case 0x23: /* EORS immed */
2195 case 0x24: /* SUB immed */
2196 dest
= LHS
- DPImmRHS
;
2200 case 0x25: /* SUBS immed */
2205 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2207 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2208 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2218 case 0x26: /* RSB immed */
2219 dest
= DPImmRHS
- LHS
;
2223 case 0x27: /* RSBS immed */
2228 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2230 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2231 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2241 case 0x28: /* ADD immed */
2242 dest
= LHS
+ DPImmRHS
;
2246 case 0x29: /* ADDS immed */
2250 ASSIGNZ (dest
== 0);
2252 if ((lhs
| rhs
) >> 30)
2254 /* Possible C,V,N to set. */
2255 ASSIGNN (NEG (dest
));
2256 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2257 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2268 case 0x2a: /* ADC immed */
2269 dest
= LHS
+ DPImmRHS
+ CFLAG
;
2273 case 0x2b: /* ADCS immed */
2276 dest
= lhs
+ rhs
+ CFLAG
;
2277 ASSIGNZ (dest
== 0);
2278 if ((lhs
| rhs
) >> 30)
2280 /* Possible C,V,N to set. */
2281 ASSIGNN (NEG (dest
));
2282 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2283 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2294 case 0x2c: /* SBC immed */
2295 dest
= LHS
- DPImmRHS
- !CFLAG
;
2299 case 0x2d: /* SBCS immed */
2302 dest
= lhs
- rhs
- !CFLAG
;
2303 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2305 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2306 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2316 case 0x2e: /* RSC immed */
2317 dest
= DPImmRHS
- LHS
- !CFLAG
;
2321 case 0x2f: /* RSCS immed */
2324 dest
= rhs
- lhs
- !CFLAG
;
2325 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2327 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2328 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2338 case 0x30: /* MOVW immed */
2339 dest
= BITS (0, 11);
2340 dest
|= (BITS (16, 19) << 12);
2344 case 0x31: /* TSTP immed */
2349 state
->Cpsr
= GETSPSR (state
->Bank
);
2350 ARMul_CPSRAltered (state
);
2352 temp
= LHS
& DPImmRHS
;
2361 ARMul_NegZero (state
, dest
);
2365 case 0x32: /* TEQ immed and MSR immed to CPSR */
2367 /* MSR immed to CPSR. */
2368 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2373 case 0x33: /* TEQP immed */
2378 state
->Cpsr
= GETSPSR (state
->Bank
);
2379 ARMul_CPSRAltered (state
);
2381 temp
= LHS
^ DPImmRHS
;
2387 DPSImmRHS
; /* TEQ immed */
2389 ARMul_NegZero (state
, dest
);
2393 case 0x34: /* MOVT immed */
2394 dest
= BITS (0, 11);
2395 dest
|= (BITS (16, 19) << 12);
2396 DEST
|= (dest
<< 16);
2399 case 0x35: /* CMPP immed */
2404 state
->Cpsr
= GETSPSR (state
->Bank
);
2405 ARMul_CPSRAltered (state
);
2407 temp
= LHS
- DPImmRHS
;
2418 ARMul_NegZero (state
, dest
);
2420 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2422 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2423 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2433 case 0x36: /* CMN immed and MSR immed to SPSR */
2435 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2440 case 0x37: /* CMNP immed. */
2445 state
->Cpsr
= GETSPSR (state
->Bank
);
2446 ARMul_CPSRAltered (state
);
2448 temp
= LHS
+ DPImmRHS
;
2459 ASSIGNZ (dest
== 0);
2460 if ((lhs
| rhs
) >> 30)
2462 /* Possible C,V,N to set. */
2463 ASSIGNN (NEG (dest
));
2464 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2465 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2476 case 0x38: /* ORR immed. */
2477 dest
= LHS
| DPImmRHS
;
2481 case 0x39: /* ORRS immed. */
2487 case 0x3a: /* MOV immed. */
2492 case 0x3b: /* MOVS immed. */
2497 case 0x3c: /* BIC immed. */
2498 dest
= LHS
& ~DPImmRHS
;
2502 case 0x3d: /* BICS immed. */
2508 case 0x3e: /* MVN immed. */
2513 case 0x3f: /* MVNS immed. */
2519 /* Single Data Transfer Immediate RHS Instructions. */
2521 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2523 if (StoreWord (state
, instr
, lhs
))
2524 LSBase
= lhs
- LSImmRHS
;
2527 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2529 if (LoadWord (state
, instr
, lhs
))
2530 LSBase
= lhs
- LSImmRHS
;
2533 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2534 UNDEF_LSRBaseEQDestWb
;
2537 temp
= lhs
- LSImmRHS
;
2538 state
->NtransSig
= LOW
;
2539 if (StoreWord (state
, instr
, lhs
))
2541 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2544 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2545 UNDEF_LSRBaseEQDestWb
;
2548 state
->NtransSig
= LOW
;
2549 if (LoadWord (state
, instr
, lhs
))
2550 LSBase
= lhs
- LSImmRHS
;
2551 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2554 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2556 if (StoreByte (state
, instr
, lhs
))
2557 LSBase
= lhs
- LSImmRHS
;
2560 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2562 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2563 LSBase
= lhs
- LSImmRHS
;
2566 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2567 UNDEF_LSRBaseEQDestWb
;
2570 state
->NtransSig
= LOW
;
2571 if (StoreByte (state
, instr
, lhs
))
2572 LSBase
= lhs
- LSImmRHS
;
2573 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2576 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2577 UNDEF_LSRBaseEQDestWb
;
2580 state
->NtransSig
= LOW
;
2581 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2582 LSBase
= lhs
- LSImmRHS
;
2583 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2586 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2588 if (StoreWord (state
, instr
, lhs
))
2589 LSBase
= lhs
+ LSImmRHS
;
2592 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2594 if (LoadWord (state
, instr
, lhs
))
2595 LSBase
= lhs
+ LSImmRHS
;
2598 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2599 UNDEF_LSRBaseEQDestWb
;
2602 state
->NtransSig
= LOW
;
2603 if (StoreWord (state
, instr
, lhs
))
2604 LSBase
= lhs
+ LSImmRHS
;
2605 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2608 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2609 UNDEF_LSRBaseEQDestWb
;
2612 state
->NtransSig
= LOW
;
2613 if (LoadWord (state
, instr
, lhs
))
2614 LSBase
= lhs
+ LSImmRHS
;
2615 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2618 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2620 if (StoreByte (state
, instr
, lhs
))
2621 LSBase
= lhs
+ LSImmRHS
;
2624 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2626 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2627 LSBase
= lhs
+ LSImmRHS
;
2630 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2631 UNDEF_LSRBaseEQDestWb
;
2634 state
->NtransSig
= LOW
;
2635 if (StoreByte (state
, instr
, lhs
))
2636 LSBase
= lhs
+ LSImmRHS
;
2637 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2640 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2641 UNDEF_LSRBaseEQDestWb
;
2644 state
->NtransSig
= LOW
;
2645 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2646 LSBase
= lhs
+ LSImmRHS
;
2647 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2651 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2652 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2655 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2656 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2659 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2660 UNDEF_LSRBaseEQDestWb
;
2662 temp
= LHS
- LSImmRHS
;
2663 if (StoreWord (state
, instr
, temp
))
2667 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2668 UNDEF_LSRBaseEQDestWb
;
2670 temp
= LHS
- LSImmRHS
;
2671 if (LoadWord (state
, instr
, temp
))
2675 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2676 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2679 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2680 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2683 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2684 UNDEF_LSRBaseEQDestWb
;
2686 temp
= LHS
- LSImmRHS
;
2687 if (StoreByte (state
, instr
, temp
))
2691 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2692 UNDEF_LSRBaseEQDestWb
;
2694 temp
= LHS
- LSImmRHS
;
2695 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2699 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2700 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2703 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2704 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2707 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2708 UNDEF_LSRBaseEQDestWb
;
2710 temp
= LHS
+ LSImmRHS
;
2711 if (StoreWord (state
, instr
, temp
))
2715 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2716 UNDEF_LSRBaseEQDestWb
;
2718 temp
= LHS
+ LSImmRHS
;
2719 if (LoadWord (state
, instr
, temp
))
2723 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2724 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2727 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2728 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2731 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2732 UNDEF_LSRBaseEQDestWb
;
2734 temp
= LHS
+ LSImmRHS
;
2735 if (StoreByte (state
, instr
, temp
))
2739 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2740 UNDEF_LSRBaseEQDestWb
;
2742 temp
= LHS
+ LSImmRHS
;
2743 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2748 /* Single Data Transfer Register RHS Instructions. */
2750 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2753 ARMul_UndefInstr (state
, instr
);
2756 UNDEF_LSRBaseEQOffWb
;
2757 UNDEF_LSRBaseEQDestWb
;
2761 if (StoreWord (state
, instr
, lhs
))
2762 LSBase
= lhs
- LSRegRHS
;
2765 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2770 && handle_v6_insn (state
, instr
))
2773 ARMul_UndefInstr (state
, instr
);
2776 UNDEF_LSRBaseEQOffWb
;
2777 UNDEF_LSRBaseEQDestWb
;
2781 temp
= lhs
- LSRegRHS
;
2782 if (LoadWord (state
, instr
, lhs
))
2786 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2791 && handle_v6_insn (state
, instr
))
2794 ARMul_UndefInstr (state
, instr
);
2797 UNDEF_LSRBaseEQOffWb
;
2798 UNDEF_LSRBaseEQDestWb
;
2802 state
->NtransSig
= LOW
;
2803 if (StoreWord (state
, instr
, lhs
))
2804 LSBase
= lhs
- LSRegRHS
;
2805 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2808 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2813 && handle_v6_insn (state
, instr
))
2816 ARMul_UndefInstr (state
, instr
);
2819 UNDEF_LSRBaseEQOffWb
;
2820 UNDEF_LSRBaseEQDestWb
;
2824 temp
= lhs
- LSRegRHS
;
2825 state
->NtransSig
= LOW
;
2826 if (LoadWord (state
, instr
, lhs
))
2828 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2831 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2834 ARMul_UndefInstr (state
, instr
);
2837 UNDEF_LSRBaseEQOffWb
;
2838 UNDEF_LSRBaseEQDestWb
;
2842 if (StoreByte (state
, instr
, lhs
))
2843 LSBase
= lhs
- LSRegRHS
;
2846 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2851 && handle_v6_insn (state
, instr
))
2854 ARMul_UndefInstr (state
, instr
);
2857 UNDEF_LSRBaseEQOffWb
;
2858 UNDEF_LSRBaseEQDestWb
;
2862 temp
= lhs
- LSRegRHS
;
2863 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2867 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2872 && handle_v6_insn (state
, instr
))
2875 ARMul_UndefInstr (state
, instr
);
2878 UNDEF_LSRBaseEQOffWb
;
2879 UNDEF_LSRBaseEQDestWb
;
2883 state
->NtransSig
= LOW
;
2884 if (StoreByte (state
, instr
, lhs
))
2885 LSBase
= lhs
- LSRegRHS
;
2886 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2889 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2894 && handle_v6_insn (state
, instr
))
2897 ARMul_UndefInstr (state
, instr
);
2900 UNDEF_LSRBaseEQOffWb
;
2901 UNDEF_LSRBaseEQDestWb
;
2905 temp
= lhs
- LSRegRHS
;
2906 state
->NtransSig
= LOW
;
2907 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2909 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2912 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2917 && handle_v6_insn (state
, instr
))
2920 ARMul_UndefInstr (state
, instr
);
2923 UNDEF_LSRBaseEQOffWb
;
2924 UNDEF_LSRBaseEQDestWb
;
2928 if (StoreWord (state
, instr
, lhs
))
2929 LSBase
= lhs
+ LSRegRHS
;
2932 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2935 ARMul_UndefInstr (state
, instr
);
2938 UNDEF_LSRBaseEQOffWb
;
2939 UNDEF_LSRBaseEQDestWb
;
2943 temp
= lhs
+ LSRegRHS
;
2944 if (LoadWord (state
, instr
, lhs
))
2948 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2953 && handle_v6_insn (state
, instr
))
2956 ARMul_UndefInstr (state
, instr
);
2959 UNDEF_LSRBaseEQOffWb
;
2960 UNDEF_LSRBaseEQDestWb
;
2964 state
->NtransSig
= LOW
;
2965 if (StoreWord (state
, instr
, lhs
))
2966 LSBase
= lhs
+ LSRegRHS
;
2967 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2970 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2975 && handle_v6_insn (state
, instr
))
2978 ARMul_UndefInstr (state
, instr
);
2981 UNDEF_LSRBaseEQOffWb
;
2982 UNDEF_LSRBaseEQDestWb
;
2986 temp
= lhs
+ LSRegRHS
;
2987 state
->NtransSig
= LOW
;
2988 if (LoadWord (state
, instr
, lhs
))
2990 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2993 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2998 && handle_v6_insn (state
, instr
))
3001 ARMul_UndefInstr (state
, instr
);
3004 UNDEF_LSRBaseEQOffWb
;
3005 UNDEF_LSRBaseEQDestWb
;
3009 if (StoreByte (state
, instr
, lhs
))
3010 LSBase
= lhs
+ LSRegRHS
;
3013 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
3016 ARMul_UndefInstr (state
, instr
);
3019 UNDEF_LSRBaseEQOffWb
;
3020 UNDEF_LSRBaseEQDestWb
;
3024 temp
= lhs
+ LSRegRHS
;
3025 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3029 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3034 && handle_v6_insn (state
, instr
))
3037 ARMul_UndefInstr (state
, instr
);
3040 UNDEF_LSRBaseEQOffWb
;
3041 UNDEF_LSRBaseEQDestWb
;
3045 state
->NtransSig
= LOW
;
3046 if (StoreByte (state
, instr
, lhs
))
3047 LSBase
= lhs
+ LSRegRHS
;
3048 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3051 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3056 && handle_v6_insn (state
, instr
))
3059 ARMul_UndefInstr (state
, instr
);
3062 UNDEF_LSRBaseEQOffWb
;
3063 UNDEF_LSRBaseEQDestWb
;
3067 temp
= lhs
+ LSRegRHS
;
3068 state
->NtransSig
= LOW
;
3069 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3071 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3075 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3080 && handle_v6_insn (state
, instr
))
3083 ARMul_UndefInstr (state
, instr
);
3086 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
3089 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3092 ARMul_UndefInstr (state
, instr
);
3095 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
3098 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3101 ARMul_UndefInstr (state
, instr
);
3104 UNDEF_LSRBaseEQOffWb
;
3105 UNDEF_LSRBaseEQDestWb
;
3108 temp
= LHS
- LSRegRHS
;
3109 if (StoreWord (state
, instr
, temp
))
3113 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3116 ARMul_UndefInstr (state
, instr
);
3119 UNDEF_LSRBaseEQOffWb
;
3120 UNDEF_LSRBaseEQDestWb
;
3123 temp
= LHS
- LSRegRHS
;
3124 if (LoadWord (state
, instr
, temp
))
3128 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3133 && handle_v6_insn (state
, instr
))
3136 ARMul_UndefInstr (state
, instr
);
3139 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
3142 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3147 && handle_v6_insn (state
, instr
))
3150 ARMul_UndefInstr (state
, instr
);
3153 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
3156 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3159 ARMul_UndefInstr (state
, instr
);
3162 UNDEF_LSRBaseEQOffWb
;
3163 UNDEF_LSRBaseEQDestWb
;
3166 temp
= LHS
- LSRegRHS
;
3167 if (StoreByte (state
, instr
, temp
))
3171 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3174 ARMul_UndefInstr (state
, instr
);
3177 UNDEF_LSRBaseEQOffWb
;
3178 UNDEF_LSRBaseEQDestWb
;
3181 temp
= LHS
- LSRegRHS
;
3182 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3186 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3191 && handle_v6_insn (state
, instr
))
3194 ARMul_UndefInstr (state
, instr
);
3197 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
3200 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
3203 ARMul_UndefInstr (state
, instr
);
3206 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
3209 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
3214 && handle_v6_insn (state
, instr
))
3217 ARMul_UndefInstr (state
, instr
);
3220 UNDEF_LSRBaseEQOffWb
;
3221 UNDEF_LSRBaseEQDestWb
;
3224 temp
= LHS
+ LSRegRHS
;
3225 if (StoreWord (state
, instr
, temp
))
3229 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
3232 ARMul_UndefInstr (state
, instr
);
3235 UNDEF_LSRBaseEQOffWb
;
3236 UNDEF_LSRBaseEQDestWb
;
3239 temp
= LHS
+ LSRegRHS
;
3240 if (LoadWord (state
, instr
, temp
))
3244 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
3249 && handle_v6_insn (state
, instr
))
3252 ARMul_UndefInstr (state
, instr
);
3255 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
3258 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
3261 ARMul_UndefInstr (state
, instr
);
3264 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
3267 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
3270 ARMul_UndefInstr (state
, instr
);
3273 UNDEF_LSRBaseEQOffWb
;
3274 UNDEF_LSRBaseEQDestWb
;
3277 temp
= LHS
+ LSRegRHS
;
3278 if (StoreByte (state
, instr
, temp
))
3282 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
3285 /* Check for the special breakpoint opcode.
3286 This value should correspond to the value defined
3287 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
3288 if (BITS (0, 19) == 0xfdefe)
3290 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
3291 ARMul_Abort (state
, ARMul_SWIV
);
3294 ARMul_UndefInstr (state
, instr
);
3297 UNDEF_LSRBaseEQOffWb
;
3298 UNDEF_LSRBaseEQDestWb
;
3301 temp
= LHS
+ LSRegRHS
;
3302 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3307 /* Multiple Data Transfer Instructions. */
3309 case 0x80: /* Store, No WriteBack, Post Dec. */
3310 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3313 case 0x81: /* Load, No WriteBack, Post Dec. */
3314 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3317 case 0x82: /* Store, WriteBack, Post Dec. */
3318 temp
= LSBase
- LSMNumRegs
;
3319 STOREMULT (instr
, temp
+ 4L, temp
);
3322 case 0x83: /* Load, WriteBack, Post Dec. */
3323 temp
= LSBase
- LSMNumRegs
;
3324 LOADMULT (instr
, temp
+ 4L, temp
);
3327 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
3328 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3331 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
3332 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3335 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
3336 temp
= LSBase
- LSMNumRegs
;
3337 STORESMULT (instr
, temp
+ 4L, temp
);
3340 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3341 temp
= LSBase
- LSMNumRegs
;
3342 LOADSMULT (instr
, temp
+ 4L, temp
);
3345 case 0x88: /* Store, No WriteBack, Post Inc. */
3346 STOREMULT (instr
, LSBase
, 0L);
3349 case 0x89: /* Load, No WriteBack, Post Inc. */
3350 LOADMULT (instr
, LSBase
, 0L);
3353 case 0x8a: /* Store, WriteBack, Post Inc. */
3355 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
3358 case 0x8b: /* Load, WriteBack, Post Inc. */
3360 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
3363 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3364 STORESMULT (instr
, LSBase
, 0L);
3367 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3368 LOADSMULT (instr
, LSBase
, 0L);
3371 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3373 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
3376 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3378 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
3381 case 0x90: /* Store, No WriteBack, Pre Dec. */
3382 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3385 case 0x91: /* Load, No WriteBack, Pre Dec. */
3386 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3389 case 0x92: /* Store, WriteBack, Pre Dec. */
3390 temp
= LSBase
- LSMNumRegs
;
3391 STOREMULT (instr
, temp
, temp
);
3394 case 0x93: /* Load, WriteBack, Pre Dec. */
3395 temp
= LSBase
- LSMNumRegs
;
3396 LOADMULT (instr
, temp
, temp
);
3399 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3400 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3403 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3404 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3407 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3408 temp
= LSBase
- LSMNumRegs
;
3409 STORESMULT (instr
, temp
, temp
);
3412 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3413 temp
= LSBase
- LSMNumRegs
;
3414 LOADSMULT (instr
, temp
, temp
);
3417 case 0x98: /* Store, No WriteBack, Pre Inc. */
3418 STOREMULT (instr
, LSBase
+ 4L, 0L);
3421 case 0x99: /* Load, No WriteBack, Pre Inc. */
3422 LOADMULT (instr
, LSBase
+ 4L, 0L);
3425 case 0x9a: /* Store, WriteBack, Pre Inc. */
3427 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3430 case 0x9b: /* Load, WriteBack, Pre Inc. */
3432 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3435 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3436 STORESMULT (instr
, LSBase
+ 4L, 0L);
3439 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3440 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3443 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3445 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3448 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3450 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3454 /* Branch forward. */
3463 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3468 /* Branch backward. */
3477 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3481 /* Branch and Link forward. */
3490 /* Put PC into Link. */
3492 state
->Reg
[14] = pc
+ 4;
3494 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3496 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3499 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
3502 /* Branch and Link backward. */
3511 /* Put PC into Link. */
3513 state
->Reg
[14] = pc
+ 4;
3515 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3517 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3520 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
3523 /* Co-Processor Data Transfers. */
3527 /* Reading from R15 is UNPREDICTABLE. */
3528 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3529 ARMul_UndefInstr (state
, instr
);
3530 /* Is access to coprocessor 0 allowed ? */
3531 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3532 ARMul_UndefInstr (state
, instr
);
3533 /* Special treatment for XScale coprocessors. */
3534 else if (state
->is_XScale
)
3536 /* Only opcode 0 is supported. */
3537 if (BITS (4, 7) != 0x00)
3538 ARMul_UndefInstr (state
, instr
);
3539 /* Only coporcessor 0 is supported. */
3540 else if (CPNum
!= 0x00)
3541 ARMul_UndefInstr (state
, instr
);
3542 /* Only accumulator 0 is supported. */
3543 else if (BITS (0, 3) != 0x00)
3544 ARMul_UndefInstr (state
, instr
);
3547 /* XScale MAR insn. Move two registers into accumulator. */
3548 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3549 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3553 /* FIXME: Not sure what to do for other v5 processors. */
3554 ARMul_UndefInstr (state
, instr
);
3559 case 0xc0: /* Store , No WriteBack , Post Dec. */
3560 ARMul_STC (state
, instr
, LHS
);
3566 /* Writes to R15 are UNPREDICATABLE. */
3567 if (DESTReg
== 15 || LHSReg
== 15)
3568 ARMul_UndefInstr (state
, instr
);
3569 /* Is access to the coprocessor allowed ? */
3570 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3571 ARMul_UndefInstr (state
, instr
);
3572 /* Special handling for XScale coprcoessors. */
3573 else if (state
->is_XScale
)
3575 /* Only opcode 0 is supported. */
3576 if (BITS (4, 7) != 0x00)
3577 ARMul_UndefInstr (state
, instr
);
3578 /* Only coprocessor 0 is supported. */
3579 else if (CPNum
!= 0x00)
3580 ARMul_UndefInstr (state
, instr
);
3581 /* Only accumulator 0 is supported. */
3582 else if (BITS (0, 3) != 0x00)
3583 ARMul_UndefInstr (state
, instr
);
3586 /* XScale MRA insn. Move accumulator into two registers. */
3587 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3592 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3593 state
->Reg
[BITS (16, 19)] = t1
;
3598 /* FIXME: Not sure what to do for other v5 processors. */
3599 ARMul_UndefInstr (state
, instr
);
3604 case 0xc1: /* Load , No WriteBack , Post Dec. */
3605 ARMul_LDC (state
, instr
, LHS
);
3609 case 0xc6: /* Store , WriteBack , Post Dec. */
3611 state
->Base
= lhs
- LSCOff
;
3612 ARMul_STC (state
, instr
, lhs
);
3616 case 0xc7: /* Load , WriteBack , Post Dec. */
3618 state
->Base
= lhs
- LSCOff
;
3619 ARMul_LDC (state
, instr
, lhs
);
3623 case 0xcc: /* Store , No WriteBack , Post Inc. */
3624 ARMul_STC (state
, instr
, LHS
);
3628 case 0xcd: /* Load , No WriteBack , Post Inc. */
3629 ARMul_LDC (state
, instr
, LHS
);
3633 case 0xce: /* Store , WriteBack , Post Inc. */
3635 state
->Base
= lhs
+ LSCOff
;
3636 ARMul_STC (state
, instr
, LHS
);
3640 case 0xcf: /* Load , WriteBack , Post Inc. */
3642 state
->Base
= lhs
+ LSCOff
;
3643 ARMul_LDC (state
, instr
, LHS
);
3647 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3648 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3652 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3653 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3657 case 0xd6: /* Store , WriteBack , Pre Dec. */
3660 ARMul_STC (state
, instr
, lhs
);
3664 case 0xd7: /* Load , WriteBack , Pre Dec. */
3667 ARMul_LDC (state
, instr
, lhs
);
3671 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3672 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3676 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3677 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3681 case 0xde: /* Store , WriteBack , Pre Inc. */
3684 ARMul_STC (state
, instr
, lhs
);
3688 case 0xdf: /* Load , WriteBack , Pre Inc. */
3691 ARMul_LDC (state
, instr
, lhs
);
3695 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3698 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3700 ARMul_UndefInstr (state
, instr
);
3703 if (state
->is_XScale
)
3704 switch (BITS (18, 19))
3707 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3709 /* XScale MIA instruction. Signed multiplication of
3710 two 32 bit values and addition to 40 bit accumulator. */
3711 ARMsdword Rm
= state
->Reg
[MULLHSReg
];
3712 ARMsdword Rs
= state
->Reg
[MULACCReg
];
3718 state
->Accumulator
+= Rm
* Rs
;
3724 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3726 /* XScale MIAPH instruction. */
3727 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3728 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3729 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3730 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3745 state
->Accumulator
+= t5
;
3750 state
->Accumulator
+= t5
;
3756 if (BITS (4, 11) == 1)
3758 /* XScale MIAxy instruction. */
3764 t1
= state
->Reg
[MULLHSReg
] >> 16;
3766 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3769 t2
= state
->Reg
[MULACCReg
] >> 16;
3771 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3781 state
->Accumulator
+= t5
;
3805 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3807 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3808 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3812 ARMul_MCR (state
, instr
, DEST
);
3816 ARMul_CDP (state
, instr
);
3820 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3832 temp
= ARMul_MRC (state
, instr
);
3835 ASSIGNN ((temp
& NBIT
) != 0);
3836 ASSIGNZ ((temp
& ZBIT
) != 0);
3837 ASSIGNC ((temp
& CBIT
) != 0);
3838 ASSIGNV ((temp
& VBIT
) != 0);
3845 ARMul_CDP (state
, instr
);
3849 /* SWI instruction. */
3866 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3868 /* A prefetch abort. */
3869 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
3870 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3874 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3875 ARMul_Abort (state
, ARMul_SWIV
);
3885 #ifdef NEED_UI_LOOP_HOOK
3886 if (deprecated_ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3888 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3889 deprecated_ui_loop_hook (0);
3891 #endif /* NEED_UI_LOOP_HOOK */
3893 if (state
->Emulate
== ONCE
)
3894 state
->Emulate
= STOP
;
3895 /* If we have changed mode, allow the PC to advance before stopping. */
3896 else if (state
->Emulate
== CHANGEMODE
)
3898 else if (state
->Emulate
!= RUN
)
3901 while (!stop_simulator
);
3903 state
->decoded
= decoded
;
3904 state
->loaded
= loaded
;
3910 /* This routine evaluates most Data Processing register RHS's with the S
3911 bit clear. It is intended to be called from the macro DPRegRHS, which
3912 filters the common case of an unshifted register with in line code. */
3915 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3917 ARMword shamt
, base
;
3922 /* Shift amount in a register. */
3927 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3930 base
= state
->Reg
[base
];
3931 ARMul_Icycles (state
, 1, 0L);
3932 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3933 switch ((int) BITS (5, 6))
3938 else if (shamt
>= 32)
3941 return (base
<< shamt
);
3945 else if (shamt
>= 32)
3948 return (base
>> shamt
);
3952 else if (shamt
>= 32)
3953 return ((ARMword
) ((ARMsword
) base
>> 31L));
3955 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
3961 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3966 /* Shift amount is a constant. */
3969 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3972 base
= state
->Reg
[base
];
3973 shamt
= BITS (7, 11);
3974 switch ((int) BITS (5, 6))
3977 return (base
<< shamt
);
3982 return (base
>> shamt
);
3985 return ((ARMword
) ((ARMsword
) base
>> 31L));
3987 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
3991 return ((base
>> 1) | (CFLAG
<< 31));
3993 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4000 /* This routine evaluates most Logical Data Processing register RHS's
4001 with the S bit set. It is intended to be called from the macro
4002 DPSRegRHS, which filters the common case of an unshifted register
4003 with in line code. */
4006 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
4008 ARMword shamt
, base
;
4013 /* Shift amount in a register. */
4018 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4021 base
= state
->Reg
[base
];
4022 ARMul_Icycles (state
, 1, 0L);
4023 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4024 switch ((int) BITS (5, 6))
4029 else if (shamt
== 32)
4034 else if (shamt
> 32)
4041 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4042 return (base
<< shamt
);
4047 else if (shamt
== 32)
4049 ASSIGNC (base
>> 31);
4052 else if (shamt
> 32)
4059 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4060 return (base
>> shamt
);
4065 else if (shamt
>= 32)
4067 ASSIGNC (base
>> 31L);
4068 return ((ARMword
) ((ARMsword
) base
>> 31L));
4072 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4073 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4081 ASSIGNC (base
>> 31);
4086 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4087 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4093 /* Shift amount is a constant. */
4096 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4099 base
= state
->Reg
[base
];
4100 shamt
= BITS (7, 11);
4102 switch ((int) BITS (5, 6))
4105 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4106 return (base
<< shamt
);
4110 ASSIGNC (base
>> 31);
4115 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4116 return (base
>> shamt
);
4121 ASSIGNC (base
>> 31L);
4122 return ((ARMword
) ((ARMsword
) base
>> 31L));
4126 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4127 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4135 return ((base
>> 1) | (shamt
<< 31));
4139 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4140 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4148 /* This routine handles writes to register 15 when the S bit is not set. */
4151 WriteR15 (ARMul_State
* state
, ARMword src
)
4153 /* The ARM documentation states that the two least significant bits
4154 are discarded when setting PC, except in the cases handled by
4155 WriteR15Branch() below. It's probably an oversight: in THUMB
4156 mode, the second least significant bit should probably not be
4166 state
->Reg
[15] = src
& PCBITS
;
4168 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
4169 ARMul_R15Altered (state
);
4174 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4177 /* This routine handles writes to register 15 when the S bit is set. */
4180 WriteSR15 (ARMul_State
* state
, ARMword src
)
4183 if (state
->Bank
> 0)
4185 state
->Cpsr
= state
->Spsr
[state
->Bank
];
4186 ARMul_CPSRAltered (state
);
4194 state
->Reg
[15] = src
& PCBITS
;
4198 /* ARMul_R15Altered would have to support it. */
4204 if (state
->Bank
== USERBANK
)
4205 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
4207 state
->Reg
[15] = src
;
4209 ARMul_R15Altered (state
);
4213 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4216 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
4217 will switch to Thumb mode if the least significant bit is set. */
4220 WriteR15Branch (ARMul_State
* state
, ARMword src
)
4227 state
->Reg
[15] = src
& 0xfffffffe;
4232 state
->Reg
[15] = src
& 0xfffffffc;
4236 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4238 WriteR15 (state
, src
);
4242 /* Before ARM_v5 LDR and LDM of pc did not change mode. */
4245 WriteR15Load (ARMul_State
* state
, ARMword src
)
4248 WriteR15Branch (state
, src
);
4250 WriteR15 (state
, src
);
4253 /* This routine evaluates most Load and Store register RHS's. It is
4254 intended to be called from the macro LSRegRHS, which filters the
4255 common case of an unshifted register with in line code. */
4258 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
4260 ARMword shamt
, base
;
4265 /* Now forbidden, but ... */
4266 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4269 base
= state
->Reg
[base
];
4271 shamt
= BITS (7, 11);
4272 switch ((int) BITS (5, 6))
4275 return (base
<< shamt
);
4280 return (base
>> shamt
);
4283 return ((ARMword
) ((ARMsword
) base
>> 31L));
4285 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4289 return ((base
>> 1) | (CFLAG
<< 31));
4291 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4298 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
4301 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
4308 /* Now forbidden, but ... */
4309 return ECC
| ER15INT
| R15PC
| EMODE
;
4311 return state
->Reg
[RHSReg
];
4315 return BITS (0, 3) | (BITS (8, 11) << 4);
4318 /* This function does the work of loading a word for a LDR instruction. */
4321 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4327 if (ADDREXCEPT (address
))
4328 INTERNALABORT (address
);
4331 dest
= ARMul_LoadWordN (state
, address
);
4336 return state
->lateabtSig
;
4339 dest
= ARMul_Align (state
, address
, dest
);
4341 ARMul_Icycles (state
, 1, 0L);
4343 return (DESTReg
!= LHSReg
);
4347 /* This function does the work of loading a halfword. */
4350 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
4357 if (ADDREXCEPT (address
))
4358 INTERNALABORT (address
);
4360 dest
= ARMul_LoadHalfWord (state
, address
);
4364 return state
->lateabtSig
;
4368 if (dest
& 1 << (16 - 1))
4369 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
4372 ARMul_Icycles (state
, 1, 0L);
4373 return (DESTReg
!= LHSReg
);
4378 /* This function does the work of loading a byte for a LDRB instruction. */
4381 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
4387 if (ADDREXCEPT (address
))
4388 INTERNALABORT (address
);
4390 dest
= ARMul_LoadByte (state
, address
);
4394 return state
->lateabtSig
;
4398 if (dest
& 1 << (8 - 1))
4399 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
4402 ARMul_Icycles (state
, 1, 0L);
4404 return (DESTReg
!= LHSReg
);
4407 /* This function does the work of loading two words for a LDRD instruction. */
4410 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
4414 ARMword write_back
= BIT (21);
4415 ARMword immediate
= BIT (22);
4416 ARMword add_to_base
= BIT (23);
4417 ARMword pre_indexed
= BIT (24);
4427 /* If the writeback bit is set, the pre-index bit must be clear. */
4428 if (write_back
&& ! pre_indexed
)
4430 ARMul_UndefInstr (state
, instr
);
4434 /* Extract the base address register. */
4437 /* Extract the destination register and check it. */
4440 /* Destination register must be even. */
4442 /* Destination register cannot be LR. */
4443 || (dest_reg
== 14))
4445 ARMul_UndefInstr (state
, instr
);
4449 /* Compute the base address. */
4450 base
= state
->Reg
[addr_reg
];
4452 /* Compute the offset. */
4453 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4455 /* Compute the sum of the two. */
4457 sum
= base
+ offset
;
4459 sum
= base
- offset
;
4461 /* If this is a pre-indexed mode use the sum. */
4467 /* The address must be aligned on a 8 byte boundary. */
4471 ARMul_DATAABORT (addr
);
4473 ARMul_UndefInstr (state
, instr
);
4478 /* For pre indexed or post indexed addressing modes,
4479 check that the destination registers do not overlap
4480 the address registers. */
4481 if ((! pre_indexed
|| write_back
)
4482 && ( addr_reg
== dest_reg
4483 || addr_reg
== dest_reg
+ 1))
4485 ARMul_UndefInstr (state
, instr
);
4489 /* Load the words. */
4490 value1
= ARMul_LoadWordN (state
, addr
);
4491 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4493 /* Check for data aborts. */
4500 ARMul_Icycles (state
, 2, 0L);
4502 /* Store the values. */
4503 state
->Reg
[dest_reg
] = value1
;
4504 state
->Reg
[dest_reg
+ 1] = value2
;
4506 /* Do the post addressing and writeback. */
4510 if (! pre_indexed
|| write_back
)
4511 state
->Reg
[addr_reg
] = addr
;
4514 /* This function does the work of storing two words for a STRD instruction. */
4517 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4521 ARMword write_back
= BIT (21);
4522 ARMword immediate
= BIT (22);
4523 ARMword add_to_base
= BIT (23);
4524 ARMword pre_indexed
= BIT (24);
4532 /* If the writeback bit is set, the pre-index bit must be clear. */
4533 if (write_back
&& ! pre_indexed
)
4535 ARMul_UndefInstr (state
, instr
);
4539 /* Extract the base address register. */
4542 /* Base register cannot be PC. */
4545 ARMul_UndefInstr (state
, instr
);
4549 /* Extract the source register. */
4552 /* Source register must be even. */
4555 ARMul_UndefInstr (state
, instr
);
4559 /* Compute the base address. */
4560 base
= state
->Reg
[addr_reg
];
4562 /* Compute the offset. */
4563 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4565 /* Compute the sum of the two. */
4567 sum
= base
+ offset
;
4569 sum
= base
- offset
;
4571 /* If this is a pre-indexed mode use the sum. */
4577 /* The address must be aligned on a 8 byte boundary. */
4581 ARMul_DATAABORT (addr
);
4583 ARMul_UndefInstr (state
, instr
);
4588 /* For pre indexed or post indexed addressing modes,
4589 check that the destination registers do not overlap
4590 the address registers. */
4591 if ((! pre_indexed
|| write_back
)
4592 && ( addr_reg
== src_reg
4593 || addr_reg
== src_reg
+ 1))
4595 ARMul_UndefInstr (state
, instr
);
4599 /* Load the words. */
4600 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4601 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4609 /* Do the post addressing and writeback. */
4613 if (! pre_indexed
|| write_back
)
4614 state
->Reg
[addr_reg
] = addr
;
4617 /* This function does the work of storing a word from a STR instruction. */
4620 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4625 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4628 ARMul_StoreWordN (state
, address
, DEST
);
4630 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4632 INTERNALABORT (address
);
4633 (void) ARMul_LoadWordN (state
, address
);
4636 ARMul_StoreWordN (state
, address
, DEST
);
4641 return state
->lateabtSig
;
4647 /* This function does the work of storing a byte for a STRH instruction. */
4650 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4656 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4660 ARMul_StoreHalfWord (state
, address
, DEST
);
4662 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4664 INTERNALABORT (address
);
4665 (void) ARMul_LoadHalfWord (state
, address
);
4668 ARMul_StoreHalfWord (state
, address
, DEST
);
4674 return state
->lateabtSig
;
4681 /* This function does the work of storing a byte for a STRB instruction. */
4684 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4689 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4692 ARMul_StoreByte (state
, address
, DEST
);
4694 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4696 INTERNALABORT (address
);
4697 (void) ARMul_LoadByte (state
, address
);
4700 ARMul_StoreByte (state
, address
, DEST
);
4705 return state
->lateabtSig
;
4711 /* This function does the work of loading the registers listed in an LDM
4712 instruction, when the S bit is clear. The code here is always increment
4713 after, it's up to the caller to get the input address correct and to
4714 handle base register modification. */
4717 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4723 UNDEF_LSMBaseInListWb
;
4726 if (ADDREXCEPT (address
))
4727 INTERNALABORT (address
);
4729 if (BIT (21) && LHSReg
!= 15)
4732 /* N cycle first. */
4733 for (temp
= 0; !BIT (temp
); temp
++)
4736 dest
= ARMul_LoadWordN (state
, address
);
4738 if (!state
->abortSig
&& !state
->Aborted
)
4739 state
->Reg
[temp
++] = dest
;
4740 else if (!state
->Aborted
)
4742 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4743 state
->Aborted
= ARMul_DataAbortV
;
4746 /* S cycles from here on. */
4747 for (; temp
< 16; temp
++)
4750 /* Load this register. */
4752 dest
= ARMul_LoadWordS (state
, address
);
4754 if (!state
->abortSig
&& !state
->Aborted
)
4755 state
->Reg
[temp
] = dest
;
4756 else if (!state
->Aborted
)
4758 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4759 state
->Aborted
= ARMul_DataAbortV
;
4763 if (BIT (15) && !state
->Aborted
)
4764 /* PC is in the reg list. */
4765 WriteR15Load (state
, PC
);
4767 /* To write back the final register. */
4768 ARMul_Icycles (state
, 1, 0L);
4772 if (BIT (21) && LHSReg
!= 15)
4778 /* This function does the work of loading the registers listed in an LDM
4779 instruction, when the S bit is set. The code here is always increment
4780 after, it's up to the caller to get the input address correct and to
4781 handle base register modification. */
4784 LoadSMult (ARMul_State
* state
,
4793 UNDEF_LSMBaseInListWb
;
4798 if (ADDREXCEPT (address
))
4799 INTERNALABORT (address
);
4802 if (BIT (21) && LHSReg
!= 15)
4805 if (!BIT (15) && state
->Bank
!= USERBANK
)
4807 /* Temporary reg bank switch. */
4808 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4809 UNDEF_LSMUserBankWb
;
4812 /* N cycle first. */
4813 for (temp
= 0; !BIT (temp
); temp
++)
4816 dest
= ARMul_LoadWordN (state
, address
);
4818 if (!state
->abortSig
)
4819 state
->Reg
[temp
++] = dest
;
4820 else if (!state
->Aborted
)
4822 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4823 state
->Aborted
= ARMul_DataAbortV
;
4826 /* S cycles from here on. */
4827 for (; temp
< 16; temp
++)
4830 /* Load this register. */
4832 dest
= ARMul_LoadWordS (state
, address
);
4834 if (!state
->abortSig
&& !state
->Aborted
)
4835 state
->Reg
[temp
] = dest
;
4836 else if (!state
->Aborted
)
4838 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4839 state
->Aborted
= ARMul_DataAbortV
;
4843 if (BIT (15) && !state
->Aborted
)
4845 /* PC is in the reg list. */
4847 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4849 state
->Cpsr
= GETSPSR (state
->Bank
);
4850 ARMul_CPSRAltered (state
);
4853 WriteR15 (state
, PC
);
4855 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4857 /* Protect bits in user mode. */
4858 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4859 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4860 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4861 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4864 ARMul_R15Altered (state
);
4870 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4871 /* Restore the correct bank. */
4872 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4874 /* To write back the final register. */
4875 ARMul_Icycles (state
, 1, 0L);
4879 if (BIT (21) && LHSReg
!= 15)
4886 /* This function does the work of storing the registers listed in an STM
4887 instruction, when the S bit is clear. The code here is always increment
4888 after, it's up to the caller to get the input address correct and to
4889 handle base register modification. */
4892 StoreMult (ARMul_State
* state
,
4901 UNDEF_LSMBaseInListWb
;
4904 /* N-cycle, increment the PC and update the NextInstr state. */
4908 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4909 INTERNALABORT (address
);
4915 /* N cycle first. */
4916 for (temp
= 0; !BIT (temp
); temp
++)
4920 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4924 (void) ARMul_LoadWordN (state
, address
);
4926 /* Fake the Stores as Loads. */
4927 for (; temp
< 16; temp
++)
4930 /* Save this register. */
4932 (void) ARMul_LoadWordS (state
, address
);
4935 if (BIT (21) && LHSReg
!= 15)
4941 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4944 if (state
->abortSig
&& !state
->Aborted
)
4946 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4947 state
->Aborted
= ARMul_DataAbortV
;
4950 if (BIT (21) && LHSReg
!= 15)
4953 /* S cycles from here on. */
4954 for (; temp
< 16; temp
++)
4957 /* Save this register. */
4960 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4962 if (state
->abortSig
&& !state
->Aborted
)
4964 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4965 state
->Aborted
= ARMul_DataAbortV
;
4973 /* This function does the work of storing the registers listed in an STM
4974 instruction when the S bit is set. The code here is always increment
4975 after, it's up to the caller to get the input address correct and to
4976 handle base register modification. */
4979 StoreSMult (ARMul_State
* state
,
4988 UNDEF_LSMBaseInListWb
;
4993 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4994 INTERNALABORT (address
);
5000 if (state
->Bank
!= USERBANK
)
5002 /* Force User Bank. */
5003 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5004 UNDEF_LSMUserBankWb
;
5007 for (temp
= 0; !BIT (temp
); temp
++)
5008 ; /* N cycle first. */
5011 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5015 (void) ARMul_LoadWordN (state
, address
);
5017 for (; temp
< 16; temp
++)
5018 /* Fake the Stores as Loads. */
5021 /* Save this register. */
5024 (void) ARMul_LoadWordS (state
, address
);
5027 if (BIT (21) && LHSReg
!= 15)
5034 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5037 if (state
->abortSig
&& !state
->Aborted
)
5039 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5040 state
->Aborted
= ARMul_DataAbortV
;
5043 /* S cycles from here on. */
5044 for (; temp
< 16; temp
++)
5047 /* Save this register. */
5050 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5052 if (state
->abortSig
&& !state
->Aborted
)
5054 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5055 state
->Aborted
= ARMul_DataAbortV
;
5059 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5060 /* Restore the correct bank. */
5061 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5063 if (BIT (21) && LHSReg
!= 15)
5070 /* This function does the work of adding two 32bit values
5071 together, and calculating if a carry has occurred. */
5074 Add32 (ARMword a1
, ARMword a2
, int *carry
)
5076 ARMword result
= (a1
+ a2
);
5077 unsigned int uresult
= (unsigned int) result
;
5078 unsigned int ua1
= (unsigned int) a1
;
5080 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5081 or (result > RdLo) then we have no carry. */
5082 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
5090 /* This function does the work of multiplying
5091 two 32bit values to give a 64bit result. */
5094 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5096 /* Operand register numbers. */
5097 int nRdHi
, nRdLo
, nRs
, nRm
;
5098 ARMword RdHi
= 0, RdLo
= 0, Rm
;
5102 nRdHi
= BITS (16, 19);
5103 nRdLo
= BITS (12, 15);
5107 /* Needed to calculate the cycle count. */
5108 Rm
= state
->Reg
[nRm
];
5110 /* Check for illegal operand combinations first. */
5119 /* Intermediate results. */
5120 ARMword lo
, mid1
, mid2
, hi
;
5122 ARMword Rs
= state
->Reg
[nRs
];
5127 /* Compute sign of result and adjust operands if necessary. */
5128 sign
= (Rm
^ Rs
) & 0x80000000;
5130 if (((ARMsword
) Rm
) < 0)
5133 if (((ARMsword
) Rs
) < 0)
5137 /* We can split the 32x32 into four 16x16 operations. This
5138 ensures that we do not lose precision on 32bit only hosts. */
5139 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
5140 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5141 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
5142 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5144 /* We now need to add all of these results together, taking
5145 care to propogate the carries from the additions. */
5146 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
5148 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
5150 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
5154 /* Negate result if necessary. */
5157 if (RdLo
== 0xFFFFFFFF)
5166 state
->Reg
[nRdLo
] = RdLo
;
5167 state
->Reg
[nRdHi
] = RdHi
;
5170 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
5173 /* Ensure that both RdHi and RdLo are used to compute Z,
5174 but don't let RdLo's sign bit make it to N. */
5175 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
5177 /* The cycle count depends on whether the instruction is a signed or
5178 unsigned multiply, and what bits are clear in the multiplier. */
5179 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
5180 /* Invert the bits to make the check against zero. */
5183 if ((Rm
& 0xFFFFFF00) == 0)
5185 else if ((Rm
& 0xFFFF0000) == 0)
5187 else if ((Rm
& 0xFF000000) == 0)
5195 /* This function does the work of multiplying two 32bit
5196 values and adding a 64bit value to give a 64bit result. */
5199 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5206 nRdHi
= BITS (16, 19);
5207 nRdLo
= BITS (12, 15);
5209 RdHi
= state
->Reg
[nRdHi
];
5210 RdLo
= state
->Reg
[nRdLo
];
5212 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
5214 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
5215 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
5217 state
->Reg
[nRdLo
] = RdLo
;
5218 state
->Reg
[nRdHi
] = RdHi
;
5221 /* Ensure that both RdHi and RdLo are used to compute Z,
5222 but don't let RdLo's sign bit make it to N. */
5223 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
5225 /* Extra cycle for addition. */