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 2 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 static ARMword
GetDPRegRHS (ARMul_State
*, ARMword
);
25 static ARMword
GetDPSRegRHS (ARMul_State
*, ARMword
);
26 static void WriteR15 (ARMul_State
*, ARMword
);
27 static void WriteSR15 (ARMul_State
*, ARMword
);
28 static void WriteR15Branch (ARMul_State
*, ARMword
);
29 static ARMword
GetLSRegRHS (ARMul_State
*, ARMword
);
30 static ARMword
GetLS7RHS (ARMul_State
*, ARMword
);
31 static unsigned LoadWord (ARMul_State
*, ARMword
, ARMword
);
32 static unsigned LoadHalfWord (ARMul_State
*, ARMword
, ARMword
, int);
33 static unsigned LoadByte (ARMul_State
*, ARMword
, ARMword
, int);
34 static unsigned StoreWord (ARMul_State
*, ARMword
, ARMword
);
35 static unsigned StoreHalfWord (ARMul_State
*, ARMword
, ARMword
);
36 static unsigned StoreByte (ARMul_State
*, ARMword
, ARMword
);
37 static void LoadMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
38 static void StoreMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
39 static void LoadSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
40 static void StoreSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
41 static unsigned Multiply64 (ARMul_State
*, ARMword
, int, int);
42 static unsigned MultiplyAdd64 (ARMul_State
*, ARMword
, int, int);
43 static void Handle_Load_Double (ARMul_State
*, ARMword
);
44 static void Handle_Store_Double (ARMul_State
*, ARMword
);
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. */
276 handle_v6_insn (ARMul_State
* state
, ARMword instr
)
278 switch (BITS (20, 27))
281 case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
282 case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
283 case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
284 case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
285 case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
286 case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
287 case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
288 case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
289 case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
290 case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
291 case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
292 case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
293 case 0x30: printf ("Unhandled v6 insn: movw\n"); break;
294 case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
295 case 0x34: printf ("Unhandled v6 insn: movt\n"); break;
296 case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
298 case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
299 case 0x62: printf ("Unhandled v6 insn: qadd/qsub\n"); break;
300 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
301 case 0x65: printf ("Unhandled v6 insn: uadd/usub\n"); break;
302 case 0x66: printf ("Unhandled v6 insn: uqadd/uqsub\n"); break;
303 case 0x67: printf ("Unhandled v6 insn: uhadd/uhsub\n"); break;
304 case 0x68: printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); break;
305 case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
306 case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
307 case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
308 case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
309 case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
310 case 0x7a: printf ("Unhandled v6 insn: usbfx\n"); break;
311 case 0x7c: printf ("Unhandled v6 insn: bfc/bfi\n"); break;
318 switch (BITS (4, 11))
320 case 0x07: ror
= 0; break;
321 case 0x47: ror
= 8; break;
322 case 0x87: ror
= 16; break;
323 case 0xc7: ror
= 24; break;
327 printf ("Unhandled v6 insn: ssat\n");
335 if (BITS (4, 6) == 0x7)
337 printf ("Unhandled v6 insn: ssat\n");
343 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
347 if (BITS (16, 19) == 0xf)
349 state
->Reg
[BITS (12, 15)] = Rm
;
352 state
->Reg
[BITS (12, 15)] += Rm
;
361 switch (BITS (4, 11))
363 case 0x07: ror
= 0; break;
364 case 0x47: ror
= 8; break;
365 case 0x87: ror
= 16; break;
366 case 0xc7: ror
= 24; break;
369 printf ("Unhandled v6 insn: rev\n");
378 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
382 if (BITS (16, 19) == 0xf)
384 state
->Reg
[BITS (12, 15)] = Rm
;
387 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
396 switch (BITS (4, 11))
398 case 0x07: ror
= 0; break;
399 case 0x47: ror
= 8; break;
400 case 0x87: ror
= 16; break;
401 case 0xc7: ror
= 24; break;
405 printf ("Unhandled v6 insn: usat\n");
413 if (BITS (4, 6) == 0x7)
415 printf ("Unhandled v6 insn: usat\n");
421 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
423 if (BITS (16, 19) == 0xf)
425 state
->Reg
[BITS (12, 15)] = Rm
;
428 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
437 switch (BITS (4, 11))
439 case 0x07: ror
= 0; break;
440 case 0x47: ror
= 8; break;
441 case 0x87: ror
= 16; break;
442 case 0xc7: ror
= 24; break;
445 printf ("Unhandled v6 insn: revsh\n");
454 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
456 if (BITS (16, 19) == 0xf)
458 state
->Reg
[BITS (12, 15)] = Rm
;
462 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
468 case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
473 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr
);
477 /* EMULATION of ARM6. */
479 /* The PC pipeline value depends on whether ARM
480 or Thumb instructions are being executed. */
485 ARMul_Emulate32 (ARMul_State
* state
)
487 ARMul_Emulate26 (ARMul_State
* state
)
490 ARMword instr
; /* The current instruction. */
491 ARMword dest
= 0; /* Almost the DestBus. */
492 ARMword temp
; /* Ubiquitous third hand. */
493 ARMword pc
= 0; /* The address of the current instruction. */
494 ARMword lhs
; /* Almost the ABus and BBus. */
496 ARMword decoded
= 0; /* Instruction pipeline. */
499 /* Execute the next instruction. */
501 if (state
->NextInstr
< PRIMEPIPE
)
503 decoded
= state
->decoded
;
504 loaded
= state
->loaded
;
510 /* Just keep going. */
513 switch (state
->NextInstr
)
516 /* Advance the pipeline, and an S cycle. */
517 state
->Reg
[15] += isize
;
521 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
525 /* Advance the pipeline, and an N cycle. */
526 state
->Reg
[15] += isize
;
530 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
535 /* Program counter advanced, and an S cycle. */
539 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
544 /* Program counter advanced, and an N cycle. */
548 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
553 /* The program counter has been changed. */
558 state
->Reg
[15] = pc
+ (isize
* 2);
560 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
561 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
562 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
567 /* The program counter has been changed. */
572 state
->Reg
[15] = pc
+ (isize
* 2);
574 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
575 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
576 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
582 ARMul_EnvokeEvent (state
);
583 #if 0 /* Enable this for a helpful bit of debugging when tracing is needed. */
584 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
588 #if 0 /* Enable this code to help track down stack alignment bugs. */
590 static ARMword old_sp
= -1;
592 if (old_sp
!= state
->Reg
[13])
594 old_sp
= state
->Reg
[13];
595 fprintf (stderr
, "pc: %08x: SP set to %08x%s\n",
596 pc
& ~1, old_sp
, (old_sp
% 8) ? " [UNALIGNED!]" : "");
601 if (state
->Exception
)
603 /* Any exceptions ? */
604 if (state
->NresetSig
== LOW
)
606 ARMul_Abort (state
, ARMul_ResetV
);
609 else if (!state
->NfiqSig
&& !FFLAG
)
611 ARMul_Abort (state
, ARMul_FIQV
);
614 else if (!state
->NirqSig
&& !IFLAG
)
616 ARMul_Abort (state
, ARMul_IRQV
);
621 if (state
->CallDebug
> 0)
623 instr
= ARMul_Debug (state
, pc
, instr
);
624 if (state
->Emulate
< ONCE
)
626 state
->NextInstr
= RESUME
;
631 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
633 (void) fgetc (stdin
);
636 else if (state
->Emulate
< ONCE
)
638 state
->NextInstr
= RESUME
;
645 /* Provide Thumb instruction decoding. If the processor is in Thumb
646 mode, then we can simply decode the Thumb instruction, and map it
647 to the corresponding ARM instruction (by directly loading the
648 instr variable, and letting the normal ARM simulator
649 execute). There are some caveats to ensure that the correct
650 pipelined PC value is used when executing Thumb code, and also for
651 dealing with the BL instruction. */
656 /* Check if in Thumb mode. */
657 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
660 /* This is a Thumb instruction. */
661 ARMul_UndefInstr (state
, instr
);
665 /* Already processed. */
669 /* ARM instruction available. */
671 /* So continue instruction decoding. */
679 /* Check the condition codes. */
680 if ((temp
= TOPBITS (28)) == AL
)
681 /* Vile deed in the need for speed. */
684 /* Check the condition code. */
685 switch ((int) TOPBITS (28))
693 if (BITS (25, 27) == 5) /* BLX(1) */
697 state
->Reg
[14] = pc
+ 4;
699 /* Force entry into Thumb mode. */
702 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
704 dest
+= POSBRANCH
+ (BIT (24) << 1);
706 WriteR15Branch (state
, dest
);
709 else if ((instr
& 0xFC70F000) == 0xF450F000)
710 /* The PLD instruction. Ignored. */
712 else if ( ((instr
& 0xfe500f00) == 0xfc100100)
713 || ((instr
& 0xfe500f00) == 0xfc000100))
714 /* wldrw and wstrw are unconditional. */
717 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
718 ARMul_UndefInstr (state
, instr
);
747 temp
= (CFLAG
&& !ZFLAG
);
750 temp
= (!CFLAG
|| ZFLAG
);
753 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
756 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
759 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
762 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
766 /* Handle the Clock counter here. */
767 if (state
->is_XScale
)
772 ok
= state
->CPRead
[14] (state
, 0, & cp14r0
);
774 if (ok
&& (cp14r0
& ARMul_CP14_R0_ENABLE
))
776 unsigned long newcycles
, nowtime
= ARMul_Time (state
);
778 newcycles
= nowtime
- state
->LastTime
;
779 state
->LastTime
= nowtime
;
781 if (cp14r0
& ARMul_CP14_R0_CCD
)
783 if (state
->CP14R0_CCD
== -1)
784 state
->CP14R0_CCD
= newcycles
;
786 state
->CP14R0_CCD
+= newcycles
;
788 if (state
->CP14R0_CCD
>= 64)
792 while (state
->CP14R0_CCD
>= 64)
793 state
->CP14R0_CCD
-= 64, newcycles
++;
803 state
->CP14R0_CCD
= -1;
805 cp14r0
|= ARMul_CP14_R0_FLAG2
;
806 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
808 ok
= state
->CPRead
[14] (state
, 1, & cp14r1
);
810 /* Coded like this for portability. */
811 while (ok
&& newcycles
)
813 if (cp14r1
== 0xffffffff)
824 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
826 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
830 if (state
->CPRead
[13] (state
, 8, & temp
)
831 && (temp
& ARMul_CP13_R8_PMUS
))
832 ARMul_Abort (state
, ARMul_FIQV
);
834 ARMul_Abort (state
, ARMul_IRQV
);
840 /* Handle hardware instructions breakpoints here. */
841 if (state
->is_XScale
)
843 if ( (pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
844 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
846 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
847 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
851 /* Actual execution of instructions begins here. */
852 /* If the condition codes don't match, stop here. */
857 if (state
->is_XScale
)
859 if (BIT (20) == 0 && BITS (25, 27) == 0)
861 if (BITS (4, 7) == 0xD)
863 /* XScale Load Consecutive insn. */
864 ARMword temp
= GetLS7RHS (state
, instr
);
865 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
866 ARMword addr
= BIT (24) ? temp2
: LHS
;
869 ARMul_UndefInstr (state
, instr
);
871 /* Alignment violation. */
872 ARMul_Abort (state
, ARMul_DataAbortV
);
875 int wb
= BIT (21) || (! BIT (24));
877 state
->Reg
[BITS (12, 15)] =
878 ARMul_LoadWordN (state
, addr
);
879 state
->Reg
[BITS (12, 15) + 1] =
880 ARMul_LoadWordN (state
, addr
+ 4);
887 else if (BITS (4, 7) == 0xF)
889 /* XScale Store Consecutive insn. */
890 ARMword temp
= GetLS7RHS (state
, instr
);
891 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
892 ARMword addr
= BIT (24) ? temp2
: LHS
;
895 ARMul_UndefInstr (state
, instr
);
897 /* Alignment violation. */
898 ARMul_Abort (state
, ARMul_DataAbortV
);
901 ARMul_StoreWordN (state
, addr
,
902 state
->Reg
[BITS (12, 15)]);
903 ARMul_StoreWordN (state
, addr
+ 4,
904 state
->Reg
[BITS (12, 15) + 1]);
906 if (BIT (21)|| ! BIT (24))
914 if (ARMul_HandleIwmmxt (state
, instr
))
918 switch ((int) BITS (20, 27))
920 /* Data Processing Register RHS Instructions. */
922 case 0x00: /* AND reg and MUL */
924 if (BITS (4, 11) == 0xB)
926 /* STRH register offset, no write-back, down, post indexed. */
930 if (BITS (4, 7) == 0xD)
932 Handle_Load_Double (state
, instr
);
935 if (BITS (4, 7) == 0xF)
937 Handle_Store_Double (state
, instr
);
941 if (BITS (4, 7) == 9)
944 rhs
= state
->Reg
[MULRHSReg
];
945 if (MULLHSReg
== MULDESTReg
)
948 state
->Reg
[MULDESTReg
] = 0;
950 else if (MULDESTReg
!= 15)
951 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
955 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
956 if (rhs
& (1L << dest
))
959 /* Mult takes this many/2 I cycles. */
960 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
971 case 0x01: /* ANDS reg and MULS */
973 if ((BITS (4, 11) & 0xF9) == 0x9)
974 /* LDR register offset, no write-back, down, post indexed. */
976 /* Fall through to rest of decoding. */
978 if (BITS (4, 7) == 9)
981 rhs
= state
->Reg
[MULRHSReg
];
983 if (MULLHSReg
== MULDESTReg
)
986 state
->Reg
[MULDESTReg
] = 0;
990 else if (MULDESTReg
!= 15)
992 dest
= state
->Reg
[MULLHSReg
] * rhs
;
993 ARMul_NegZero (state
, dest
);
994 state
->Reg
[MULDESTReg
] = dest
;
999 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1000 if (rhs
& (1L << dest
))
1003 /* Mult takes this many/2 I cycles. */
1004 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1015 case 0x02: /* EOR reg and MLA */
1017 if (BITS (4, 11) == 0xB)
1019 /* STRH register offset, write-back, down, post indexed. */
1024 if (BITS (4, 7) == 9)
1026 rhs
= state
->Reg
[MULRHSReg
];
1027 if (MULLHSReg
== MULDESTReg
)
1030 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
1032 else if (MULDESTReg
!= 15)
1033 state
->Reg
[MULDESTReg
] =
1034 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1038 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1039 if (rhs
& (1L << dest
))
1042 /* Mult takes this many/2 I cycles. */
1043 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1053 case 0x03: /* EORS reg and MLAS */
1055 if ((BITS (4, 11) & 0xF9) == 0x9)
1056 /* LDR register offset, write-back, down, post-indexed. */
1058 /* Fall through to rest of the decoding. */
1060 if (BITS (4, 7) == 9)
1063 rhs
= state
->Reg
[MULRHSReg
];
1065 if (MULLHSReg
== MULDESTReg
)
1068 dest
= state
->Reg
[MULACCReg
];
1069 ARMul_NegZero (state
, dest
);
1070 state
->Reg
[MULDESTReg
] = dest
;
1072 else if (MULDESTReg
!= 15)
1075 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1076 ARMul_NegZero (state
, dest
);
1077 state
->Reg
[MULDESTReg
] = dest
;
1082 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1083 if (rhs
& (1L << dest
))
1086 /* Mult takes this many/2 I cycles. */
1087 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1098 case 0x04: /* SUB reg */
1100 if (BITS (4, 7) == 0xB)
1102 /* STRH immediate offset, no write-back, down, post indexed. */
1106 if (BITS (4, 7) == 0xD)
1108 Handle_Load_Double (state
, instr
);
1111 if (BITS (4, 7) == 0xF)
1113 Handle_Store_Double (state
, instr
);
1122 case 0x05: /* SUBS reg */
1124 if ((BITS (4, 7) & 0x9) == 0x9)
1125 /* LDR immediate offset, no write-back, down, post indexed. */
1127 /* Fall through to the rest of the instruction decoding. */
1133 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1135 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1136 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1146 case 0x06: /* RSB reg */
1148 if (BITS (4, 7) == 0xB)
1150 /* STRH immediate offset, write-back, down, post indexed. */
1160 case 0x07: /* RSBS reg */
1162 if ((BITS (4, 7) & 0x9) == 0x9)
1163 /* LDR immediate offset, write-back, down, post indexed. */
1165 /* Fall through to remainder of instruction decoding. */
1171 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1173 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1174 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1184 case 0x08: /* ADD reg */
1186 if (BITS (4, 11) == 0xB)
1188 /* STRH register offset, no write-back, up, post indexed. */
1192 if (BITS (4, 7) == 0xD)
1194 Handle_Load_Double (state
, instr
);
1197 if (BITS (4, 7) == 0xF)
1199 Handle_Store_Double (state
, instr
);
1204 if (BITS (4, 7) == 0x9)
1208 ARMul_Icycles (state
,
1209 Multiply64 (state
, instr
, LUNSIGNED
,
1219 case 0x09: /* ADDS reg */
1221 if ((BITS (4, 11) & 0xF9) == 0x9)
1222 /* LDR register offset, no write-back, up, post indexed. */
1224 /* Fall through to remaining instruction decoding. */
1227 if (BITS (4, 7) == 0x9)
1231 ARMul_Icycles (state
,
1232 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
1240 ASSIGNZ (dest
== 0);
1241 if ((lhs
| rhs
) >> 30)
1243 /* Possible C,V,N to set. */
1244 ASSIGNN (NEG (dest
));
1245 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1246 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1257 case 0x0a: /* ADC reg */
1259 if (BITS (4, 11) == 0xB)
1261 /* STRH register offset, write-back, up, post-indexed. */
1265 if (BITS (4, 7) == 0x9)
1269 ARMul_Icycles (state
,
1270 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1276 dest
= LHS
+ rhs
+ CFLAG
;
1280 case 0x0b: /* ADCS reg */
1282 if ((BITS (4, 11) & 0xF9) == 0x9)
1283 /* LDR register offset, write-back, up, post indexed. */
1285 /* Fall through to remaining instruction decoding. */
1286 if (BITS (4, 7) == 0x9)
1290 ARMul_Icycles (state
,
1291 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1298 dest
= lhs
+ rhs
+ CFLAG
;
1299 ASSIGNZ (dest
== 0);
1300 if ((lhs
| rhs
) >> 30)
1302 /* Possible C,V,N to set. */
1303 ASSIGNN (NEG (dest
));
1304 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1305 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1316 case 0x0c: /* SBC reg */
1318 if (BITS (4, 7) == 0xB)
1320 /* STRH immediate offset, no write-back, up post indexed. */
1324 if (BITS (4, 7) == 0xD)
1326 Handle_Load_Double (state
, instr
);
1329 if (BITS (4, 7) == 0xF)
1331 Handle_Store_Double (state
, instr
);
1334 if (BITS (4, 7) == 0x9)
1338 ARMul_Icycles (state
,
1339 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
1345 dest
= LHS
- rhs
- !CFLAG
;
1349 case 0x0d: /* SBCS reg */
1351 if ((BITS (4, 7) & 0x9) == 0x9)
1352 /* LDR immediate offset, no write-back, up, post indexed. */
1355 if (BITS (4, 7) == 0x9)
1359 ARMul_Icycles (state
,
1360 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
1367 dest
= lhs
- rhs
- !CFLAG
;
1368 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1370 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1371 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1381 case 0x0e: /* RSC reg */
1383 if (BITS (4, 7) == 0xB)
1385 /* STRH immediate offset, write-back, up, post indexed. */
1390 if (BITS (4, 7) == 0x9)
1394 ARMul_Icycles (state
,
1395 MultiplyAdd64 (state
, instr
, LSIGNED
,
1401 dest
= rhs
- LHS
- !CFLAG
;
1405 case 0x0f: /* RSCS reg */
1407 if ((BITS (4, 7) & 0x9) == 0x9)
1408 /* LDR immediate offset, write-back, up, post indexed. */
1410 /* Fall through to remaining instruction decoding. */
1412 if (BITS (4, 7) == 0x9)
1416 ARMul_Icycles (state
,
1417 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
1424 dest
= rhs
- lhs
- !CFLAG
;
1426 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1428 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1429 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1439 case 0x10: /* TST reg and MRS CPSR and SWP word. */
1442 if (BIT (4) == 0 && BIT (7) == 1)
1444 /* ElSegundo SMLAxy insn. */
1445 ARMword op1
= state
->Reg
[BITS (0, 3)];
1446 ARMword op2
= state
->Reg
[BITS (8, 11)];
1447 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1461 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
1463 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
1467 if (BITS (4, 11) == 5)
1469 /* ElSegundo QADD insn. */
1470 ARMword op1
= state
->Reg
[BITS (0, 3)];
1471 ARMword op2
= state
->Reg
[BITS (16, 19)];
1472 ARMword result
= op1
+ op2
;
1473 if (AddOverflow (op1
, op2
, result
))
1475 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1478 state
->Reg
[BITS (12, 15)] = result
;
1483 if (BITS (4, 11) == 0xB)
1485 /* STRH register offset, no write-back, down, pre indexed. */
1489 if (BITS (4, 7) == 0xD)
1491 Handle_Load_Double (state
, instr
);
1494 if (BITS (4, 7) == 0xF)
1496 Handle_Store_Double (state
, instr
);
1500 if (BITS (4, 11) == 9)
1507 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1509 INTERNALABORT (temp
);
1510 (void) ARMul_LoadWordN (state
, temp
);
1511 (void) ARMul_LoadWordN (state
, temp
);
1515 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1517 DEST
= ARMul_Align (state
, temp
, dest
);
1520 if (state
->abortSig
|| state
->Aborted
)
1523 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1526 DEST
= ECC
| EINT
| EMODE
;
1534 case 0x11: /* TSTP reg */
1536 if ((BITS (4, 11) & 0xF9) == 0x9)
1537 /* LDR register offset, no write-back, down, pre indexed. */
1539 /* Continue with remaining instruction decode. */
1545 state
->Cpsr
= GETSPSR (state
->Bank
);
1546 ARMul_CPSRAltered (state
);
1558 ARMul_NegZero (state
, dest
);
1562 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
1565 if (BITS (4, 7) == 3)
1571 temp
= (pc
+ 2) | 1;
1575 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1576 state
->Reg
[14] = temp
;
1583 if (BIT (4) == 0 && BIT (7) == 1
1584 && (BIT (5) == 0 || BITS (12, 15) == 0))
1586 /* ElSegundo SMLAWy/SMULWy insn. */
1587 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1588 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1589 unsigned long long result
;
1593 if (op1
& 0x80000000)
1598 result
= (op1
* op2
) >> 16;
1602 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1604 if (AddOverflow (result
, Rn
, result
+ Rn
))
1608 state
->Reg
[BITS (16, 19)] = result
;
1612 if (BITS (4, 11) == 5)
1614 /* ElSegundo QSUB insn. */
1615 ARMword op1
= state
->Reg
[BITS (0, 3)];
1616 ARMword op2
= state
->Reg
[BITS (16, 19)];
1617 ARMword result
= op1
- op2
;
1619 if (SubOverflow (op1
, op2
, result
))
1621 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1625 state
->Reg
[BITS (12, 15)] = result
;
1630 if (BITS (4, 11) == 0xB)
1632 /* STRH register offset, write-back, down, pre indexed. */
1636 if (BITS (4, 27) == 0x12FFF1)
1639 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1642 if (BITS (4, 7) == 0xD)
1644 Handle_Load_Double (state
, instr
);
1647 if (BITS (4, 7) == 0xF)
1649 Handle_Store_Double (state
, instr
);
1655 if (BITS (4, 7) == 0x7)
1658 extern int SWI_vector_installed
;
1660 /* Hardware is allowed to optionally override this
1661 instruction and treat it as a breakpoint. Since
1662 this is a simulator not hardware, we take the position
1663 that if a SWI vector was not installed, then an Abort
1664 vector was probably not installed either, and so
1665 normally this instruction would be ignored, even if an
1666 Abort is generated. This is a bad thing, since GDB
1667 uses this instruction for its breakpoints (at least in
1668 Thumb mode it does). So intercept the instruction here
1669 and generate a breakpoint SWI instead. */
1670 if (! SWI_vector_installed
)
1671 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1674 /* BKPT - normally this will cause an abort, but on the
1675 XScale we must check the DCSR. */
1676 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
1677 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
1681 /* Force the next instruction to be refetched. */
1682 state
->NextInstr
= RESUME
;
1688 /* MSR reg to CPSR. */
1692 /* Don't allow TBIT to be set by MSR. */
1695 ARMul_FixCPSR (state
, instr
, temp
);
1702 case 0x13: /* TEQP reg */
1704 if ((BITS (4, 11) & 0xF9) == 0x9)
1705 /* LDR register offset, write-back, down, pre indexed. */
1707 /* Continue with remaining instruction decode. */
1713 state
->Cpsr
= GETSPSR (state
->Bank
);
1714 ARMul_CPSRAltered (state
);
1726 ARMul_NegZero (state
, dest
);
1730 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
1733 if (BIT (4) == 0 && BIT (7) == 1)
1735 /* ElSegundo SMLALxy insn. */
1736 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1737 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1738 unsigned long long dest
;
1739 unsigned long long result
;
1752 dest
= (unsigned long long) state
->Reg
[BITS (16, 19)] << 32;
1753 dest
|= state
->Reg
[BITS (12, 15)];
1755 state
->Reg
[BITS (12, 15)] = dest
;
1756 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1760 if (BITS (4, 11) == 5)
1762 /* ElSegundo QDADD insn. */
1763 ARMword op1
= state
->Reg
[BITS (0, 3)];
1764 ARMword op2
= state
->Reg
[BITS (16, 19)];
1765 ARMword op2d
= op2
+ op2
;
1768 if (AddOverflow (op2
, op2
, op2d
))
1771 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1774 result
= op1
+ op2d
;
1775 if (AddOverflow (op1
, op2d
, result
))
1778 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1781 state
->Reg
[BITS (12, 15)] = result
;
1786 if (BITS (4, 7) == 0xB)
1788 /* STRH immediate offset, no write-back, down, pre indexed. */
1792 if (BITS (4, 7) == 0xD)
1794 Handle_Load_Double (state
, instr
);
1797 if (BITS (4, 7) == 0xF)
1799 Handle_Store_Double (state
, instr
);
1803 if (BITS (4, 11) == 9)
1810 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1812 INTERNALABORT (temp
);
1813 (void) ARMul_LoadByte (state
, temp
);
1814 (void) ARMul_LoadByte (state
, temp
);
1818 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1819 if (state
->abortSig
|| state
->Aborted
)
1822 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1826 DEST
= GETSPSR (state
->Bank
);
1833 case 0x15: /* CMPP reg. */
1835 if ((BITS (4, 7) & 0x9) == 0x9)
1836 /* LDR immediate offset, no write-back, down, pre indexed. */
1838 /* Continue with remaining instruction decode. */
1844 state
->Cpsr
= GETSPSR (state
->Bank
);
1845 ARMul_CPSRAltered (state
);
1858 ARMul_NegZero (state
, dest
);
1859 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1861 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1862 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1872 case 0x16: /* CMN reg and MSR reg to SPSR */
1875 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1877 /* ElSegundo SMULxy insn. */
1878 ARMword op1
= state
->Reg
[BITS (0, 3)];
1879 ARMword op2
= state
->Reg
[BITS (8, 11)];
1880 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1893 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1897 if (BITS (4, 11) == 5)
1899 /* ElSegundo QDSUB insn. */
1900 ARMword op1
= state
->Reg
[BITS (0, 3)];
1901 ARMword op2
= state
->Reg
[BITS (16, 19)];
1902 ARMword op2d
= op2
+ op2
;
1905 if (AddOverflow (op2
, op2
, op2d
))
1908 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1911 result
= op1
- op2d
;
1912 if (SubOverflow (op1
, op2d
, result
))
1915 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1918 state
->Reg
[BITS (12, 15)] = result
;
1925 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1927 /* ARM5 CLZ insn. */
1928 ARMword op1
= state
->Reg
[BITS (0, 3)];
1932 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1935 state
->Reg
[BITS (12, 15)] = result
;
1940 if (BITS (4, 7) == 0xB)
1942 /* STRH immediate offset, write-back, down, pre indexed. */
1946 if (BITS (4, 7) == 0xD)
1948 Handle_Load_Double (state
, instr
);
1951 if (BITS (4, 7) == 0xF)
1953 Handle_Store_Double (state
, instr
);
1961 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1969 case 0x17: /* CMNP reg */
1971 if ((BITS (4, 7) & 0x9) == 0x9)
1972 /* LDR immediate offset, write-back, down, pre indexed. */
1974 /* Continue with remaining instruction decoding. */
1979 state
->Cpsr
= GETSPSR (state
->Bank
);
1980 ARMul_CPSRAltered (state
);
1994 ASSIGNZ (dest
== 0);
1995 if ((lhs
| rhs
) >> 30)
1997 /* Possible C,V,N to set. */
1998 ASSIGNN (NEG (dest
));
1999 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2000 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2011 case 0x18: /* ORR reg */
2013 if (BITS (4, 11) == 0xB)
2015 /* STRH register offset, no write-back, up, pre indexed. */
2019 if (BITS (4, 7) == 0xD)
2021 Handle_Load_Double (state
, instr
);
2024 if (BITS (4, 7) == 0xF)
2026 Handle_Store_Double (state
, instr
);
2035 case 0x19: /* ORRS reg */
2037 if ((BITS (4, 11) & 0xF9) == 0x9)
2038 /* LDR register offset, no write-back, up, pre indexed. */
2040 /* Continue with remaining instruction decoding. */
2047 case 0x1a: /* MOV reg */
2049 if (BITS (4, 11) == 0xB)
2051 /* STRH register offset, write-back, up, pre indexed. */
2055 if (BITS (4, 7) == 0xD)
2057 Handle_Load_Double (state
, instr
);
2060 if (BITS (4, 7) == 0xF)
2062 Handle_Store_Double (state
, instr
);
2070 case 0x1b: /* MOVS reg */
2072 if ((BITS (4, 11) & 0xF9) == 0x9)
2073 /* LDR register offset, write-back, up, pre indexed. */
2075 /* Continue with remaining instruction decoding. */
2081 case 0x1c: /* BIC reg */
2083 if (BITS (4, 7) == 0xB)
2085 /* STRH immediate offset, no write-back, up, pre indexed. */
2089 if (BITS (4, 7) == 0xD)
2091 Handle_Load_Double (state
, instr
);
2094 else if (BITS (4, 7) == 0xF)
2096 Handle_Store_Double (state
, instr
);
2105 case 0x1d: /* BICS reg */
2107 if ((BITS (4, 7) & 0x9) == 0x9)
2108 /* LDR immediate offset, no write-back, up, pre indexed. */
2110 /* Continue with instruction decoding. */
2117 case 0x1e: /* MVN reg */
2119 if (BITS (4, 7) == 0xB)
2121 /* STRH immediate offset, write-back, up, pre indexed. */
2125 if (BITS (4, 7) == 0xD)
2127 Handle_Load_Double (state
, instr
);
2130 if (BITS (4, 7) == 0xF)
2132 Handle_Store_Double (state
, instr
);
2140 case 0x1f: /* MVNS reg */
2142 if ((BITS (4, 7) & 0x9) == 0x9)
2143 /* LDR immediate offset, write-back, up, pre indexed. */
2145 /* Continue instruction decoding. */
2152 /* Data Processing Immediate RHS Instructions. */
2154 case 0x20: /* AND immed */
2155 dest
= LHS
& DPImmRHS
;
2159 case 0x21: /* ANDS immed */
2165 case 0x22: /* EOR immed */
2166 dest
= LHS
^ DPImmRHS
;
2170 case 0x23: /* EORS immed */
2176 case 0x24: /* SUB immed */
2177 dest
= LHS
- DPImmRHS
;
2181 case 0x25: /* SUBS immed */
2186 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2188 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2189 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2199 case 0x26: /* RSB immed */
2200 dest
= DPImmRHS
- LHS
;
2204 case 0x27: /* RSBS immed */
2209 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2211 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2212 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2222 case 0x28: /* ADD immed */
2223 dest
= LHS
+ DPImmRHS
;
2227 case 0x29: /* ADDS immed */
2231 ASSIGNZ (dest
== 0);
2233 if ((lhs
| rhs
) >> 30)
2235 /* Possible C,V,N to set. */
2236 ASSIGNN (NEG (dest
));
2237 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2238 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2249 case 0x2a: /* ADC immed */
2250 dest
= LHS
+ DPImmRHS
+ CFLAG
;
2254 case 0x2b: /* ADCS immed */
2257 dest
= lhs
+ rhs
+ CFLAG
;
2258 ASSIGNZ (dest
== 0);
2259 if ((lhs
| rhs
) >> 30)
2261 /* Possible C,V,N to set. */
2262 ASSIGNN (NEG (dest
));
2263 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2264 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2275 case 0x2c: /* SBC immed */
2276 dest
= LHS
- DPImmRHS
- !CFLAG
;
2280 case 0x2d: /* SBCS immed */
2283 dest
= lhs
- rhs
- !CFLAG
;
2284 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2286 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2287 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2297 case 0x2e: /* RSC immed */
2298 dest
= DPImmRHS
- LHS
- !CFLAG
;
2302 case 0x2f: /* RSCS immed */
2305 dest
= rhs
- lhs
- !CFLAG
;
2306 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2308 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2309 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2319 case 0x30: /* TST immed */
2323 case 0x31: /* TSTP immed */
2328 state
->Cpsr
= GETSPSR (state
->Bank
);
2329 ARMul_CPSRAltered (state
);
2331 temp
= LHS
& DPImmRHS
;
2340 ARMul_NegZero (state
, dest
);
2344 case 0x32: /* TEQ immed and MSR immed to CPSR */
2346 /* MSR immed to CPSR. */
2347 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2352 case 0x33: /* TEQP immed */
2357 state
->Cpsr
= GETSPSR (state
->Bank
);
2358 ARMul_CPSRAltered (state
);
2360 temp
= LHS
^ DPImmRHS
;
2366 DPSImmRHS
; /* TEQ immed */
2368 ARMul_NegZero (state
, dest
);
2372 case 0x34: /* CMP immed */
2376 case 0x35: /* CMPP immed */
2381 state
->Cpsr
= GETSPSR (state
->Bank
);
2382 ARMul_CPSRAltered (state
);
2384 temp
= LHS
- DPImmRHS
;
2395 ARMul_NegZero (state
, dest
);
2397 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2399 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2400 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2410 case 0x36: /* CMN immed and MSR immed to SPSR */
2412 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2417 case 0x37: /* CMNP immed. */
2422 state
->Cpsr
= GETSPSR (state
->Bank
);
2423 ARMul_CPSRAltered (state
);
2425 temp
= LHS
+ DPImmRHS
;
2436 ASSIGNZ (dest
== 0);
2437 if ((lhs
| rhs
) >> 30)
2439 /* Possible C,V,N to set. */
2440 ASSIGNN (NEG (dest
));
2441 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2442 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2453 case 0x38: /* ORR immed. */
2454 dest
= LHS
| DPImmRHS
;
2458 case 0x39: /* ORRS immed. */
2464 case 0x3a: /* MOV immed. */
2469 case 0x3b: /* MOVS immed. */
2474 case 0x3c: /* BIC immed. */
2475 dest
= LHS
& ~DPImmRHS
;
2479 case 0x3d: /* BICS immed. */
2485 case 0x3e: /* MVN immed. */
2490 case 0x3f: /* MVNS immed. */
2496 /* Single Data Transfer Immediate RHS Instructions. */
2498 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2500 if (StoreWord (state
, instr
, lhs
))
2501 LSBase
= lhs
- LSImmRHS
;
2504 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2506 if (LoadWord (state
, instr
, lhs
))
2507 LSBase
= lhs
- LSImmRHS
;
2510 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2511 UNDEF_LSRBaseEQDestWb
;
2514 temp
= lhs
- LSImmRHS
;
2515 state
->NtransSig
= LOW
;
2516 if (StoreWord (state
, instr
, lhs
))
2518 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2521 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2522 UNDEF_LSRBaseEQDestWb
;
2525 state
->NtransSig
= LOW
;
2526 if (LoadWord (state
, instr
, lhs
))
2527 LSBase
= lhs
- LSImmRHS
;
2528 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2531 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2533 if (StoreByte (state
, instr
, lhs
))
2534 LSBase
= lhs
- LSImmRHS
;
2537 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2539 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2540 LSBase
= lhs
- LSImmRHS
;
2543 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2544 UNDEF_LSRBaseEQDestWb
;
2547 state
->NtransSig
= LOW
;
2548 if (StoreByte (state
, instr
, lhs
))
2549 LSBase
= lhs
- LSImmRHS
;
2550 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2553 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2554 UNDEF_LSRBaseEQDestWb
;
2557 state
->NtransSig
= LOW
;
2558 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2559 LSBase
= lhs
- LSImmRHS
;
2560 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2563 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2565 if (StoreWord (state
, instr
, lhs
))
2566 LSBase
= lhs
+ LSImmRHS
;
2569 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2571 if (LoadWord (state
, instr
, lhs
))
2572 LSBase
= lhs
+ LSImmRHS
;
2575 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2576 UNDEF_LSRBaseEQDestWb
;
2579 state
->NtransSig
= LOW
;
2580 if (StoreWord (state
, instr
, lhs
))
2581 LSBase
= lhs
+ LSImmRHS
;
2582 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2585 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2586 UNDEF_LSRBaseEQDestWb
;
2589 state
->NtransSig
= LOW
;
2590 if (LoadWord (state
, instr
, lhs
))
2591 LSBase
= lhs
+ LSImmRHS
;
2592 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2595 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2597 if (StoreByte (state
, instr
, lhs
))
2598 LSBase
= lhs
+ LSImmRHS
;
2601 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2603 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2604 LSBase
= lhs
+ LSImmRHS
;
2607 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2608 UNDEF_LSRBaseEQDestWb
;
2611 state
->NtransSig
= LOW
;
2612 if (StoreByte (state
, instr
, lhs
))
2613 LSBase
= lhs
+ LSImmRHS
;
2614 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2617 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2618 UNDEF_LSRBaseEQDestWb
;
2621 state
->NtransSig
= LOW
;
2622 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2623 LSBase
= lhs
+ LSImmRHS
;
2624 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2628 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2629 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2632 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2633 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2636 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2637 UNDEF_LSRBaseEQDestWb
;
2639 temp
= LHS
- LSImmRHS
;
2640 if (StoreWord (state
, instr
, temp
))
2644 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2645 UNDEF_LSRBaseEQDestWb
;
2647 temp
= LHS
- LSImmRHS
;
2648 if (LoadWord (state
, instr
, temp
))
2652 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2653 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2656 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2657 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2660 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2661 UNDEF_LSRBaseEQDestWb
;
2663 temp
= LHS
- LSImmRHS
;
2664 if (StoreByte (state
, instr
, temp
))
2668 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2669 UNDEF_LSRBaseEQDestWb
;
2671 temp
= LHS
- LSImmRHS
;
2672 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2676 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2677 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2680 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2681 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2684 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2685 UNDEF_LSRBaseEQDestWb
;
2687 temp
= LHS
+ LSImmRHS
;
2688 if (StoreWord (state
, instr
, temp
))
2692 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2693 UNDEF_LSRBaseEQDestWb
;
2695 temp
= LHS
+ LSImmRHS
;
2696 if (LoadWord (state
, instr
, temp
))
2700 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2701 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2704 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2705 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2708 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2709 UNDEF_LSRBaseEQDestWb
;
2711 temp
= LHS
+ LSImmRHS
;
2712 if (StoreByte (state
, instr
, temp
))
2716 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2717 UNDEF_LSRBaseEQDestWb
;
2719 temp
= LHS
+ LSImmRHS
;
2720 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2725 /* Single Data Transfer Register RHS Instructions. */
2727 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2730 ARMul_UndefInstr (state
, instr
);
2733 UNDEF_LSRBaseEQOffWb
;
2734 UNDEF_LSRBaseEQDestWb
;
2738 if (StoreWord (state
, instr
, lhs
))
2739 LSBase
= lhs
- LSRegRHS
;
2742 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2747 && handle_v6_insn (state
, instr
))
2750 ARMul_UndefInstr (state
, instr
);
2753 UNDEF_LSRBaseEQOffWb
;
2754 UNDEF_LSRBaseEQDestWb
;
2758 temp
= lhs
- LSRegRHS
;
2759 if (LoadWord (state
, instr
, lhs
))
2763 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2768 && handle_v6_insn (state
, instr
))
2771 ARMul_UndefInstr (state
, instr
);
2774 UNDEF_LSRBaseEQOffWb
;
2775 UNDEF_LSRBaseEQDestWb
;
2779 state
->NtransSig
= LOW
;
2780 if (StoreWord (state
, instr
, lhs
))
2781 LSBase
= lhs
- LSRegRHS
;
2782 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2785 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2790 && handle_v6_insn (state
, instr
))
2793 ARMul_UndefInstr (state
, instr
);
2796 UNDEF_LSRBaseEQOffWb
;
2797 UNDEF_LSRBaseEQDestWb
;
2801 temp
= lhs
- LSRegRHS
;
2802 state
->NtransSig
= LOW
;
2803 if (LoadWord (state
, instr
, lhs
))
2805 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2808 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2811 ARMul_UndefInstr (state
, instr
);
2814 UNDEF_LSRBaseEQOffWb
;
2815 UNDEF_LSRBaseEQDestWb
;
2819 if (StoreByte (state
, instr
, lhs
))
2820 LSBase
= lhs
- LSRegRHS
;
2823 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2828 && handle_v6_insn (state
, instr
))
2831 ARMul_UndefInstr (state
, instr
);
2834 UNDEF_LSRBaseEQOffWb
;
2835 UNDEF_LSRBaseEQDestWb
;
2839 temp
= lhs
- LSRegRHS
;
2840 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2844 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2849 && handle_v6_insn (state
, instr
))
2852 ARMul_UndefInstr (state
, instr
);
2855 UNDEF_LSRBaseEQOffWb
;
2856 UNDEF_LSRBaseEQDestWb
;
2860 state
->NtransSig
= LOW
;
2861 if (StoreByte (state
, instr
, lhs
))
2862 LSBase
= lhs
- LSRegRHS
;
2863 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2866 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2871 && handle_v6_insn (state
, instr
))
2874 ARMul_UndefInstr (state
, instr
);
2877 UNDEF_LSRBaseEQOffWb
;
2878 UNDEF_LSRBaseEQDestWb
;
2882 temp
= lhs
- LSRegRHS
;
2883 state
->NtransSig
= LOW
;
2884 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2886 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2889 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2894 && handle_v6_insn (state
, instr
))
2897 ARMul_UndefInstr (state
, instr
);
2900 UNDEF_LSRBaseEQOffWb
;
2901 UNDEF_LSRBaseEQDestWb
;
2905 if (StoreWord (state
, instr
, lhs
))
2906 LSBase
= lhs
+ LSRegRHS
;
2909 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2912 ARMul_UndefInstr (state
, instr
);
2915 UNDEF_LSRBaseEQOffWb
;
2916 UNDEF_LSRBaseEQDestWb
;
2920 temp
= lhs
+ LSRegRHS
;
2921 if (LoadWord (state
, instr
, lhs
))
2925 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2930 && handle_v6_insn (state
, instr
))
2933 ARMul_UndefInstr (state
, instr
);
2936 UNDEF_LSRBaseEQOffWb
;
2937 UNDEF_LSRBaseEQDestWb
;
2941 state
->NtransSig
= LOW
;
2942 if (StoreWord (state
, instr
, lhs
))
2943 LSBase
= lhs
+ LSRegRHS
;
2944 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2947 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2952 && handle_v6_insn (state
, instr
))
2955 ARMul_UndefInstr (state
, instr
);
2958 UNDEF_LSRBaseEQOffWb
;
2959 UNDEF_LSRBaseEQDestWb
;
2963 temp
= lhs
+ LSRegRHS
;
2964 state
->NtransSig
= LOW
;
2965 if (LoadWord (state
, instr
, lhs
))
2967 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2970 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2975 && handle_v6_insn (state
, instr
))
2978 ARMul_UndefInstr (state
, instr
);
2981 UNDEF_LSRBaseEQOffWb
;
2982 UNDEF_LSRBaseEQDestWb
;
2986 if (StoreByte (state
, instr
, lhs
))
2987 LSBase
= lhs
+ LSRegRHS
;
2990 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
2993 ARMul_UndefInstr (state
, instr
);
2996 UNDEF_LSRBaseEQOffWb
;
2997 UNDEF_LSRBaseEQDestWb
;
3001 temp
= lhs
+ LSRegRHS
;
3002 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3006 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3011 && handle_v6_insn (state
, instr
))
3014 ARMul_UndefInstr (state
, instr
);
3017 UNDEF_LSRBaseEQOffWb
;
3018 UNDEF_LSRBaseEQDestWb
;
3022 state
->NtransSig
= LOW
;
3023 if (StoreByte (state
, instr
, lhs
))
3024 LSBase
= lhs
+ LSRegRHS
;
3025 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3028 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3033 && handle_v6_insn (state
, instr
))
3036 ARMul_UndefInstr (state
, instr
);
3039 UNDEF_LSRBaseEQOffWb
;
3040 UNDEF_LSRBaseEQDestWb
;
3044 temp
= lhs
+ LSRegRHS
;
3045 state
->NtransSig
= LOW
;
3046 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3048 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3052 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3057 && handle_v6_insn (state
, instr
))
3060 ARMul_UndefInstr (state
, instr
);
3063 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
3066 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3069 ARMul_UndefInstr (state
, instr
);
3072 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
3075 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3078 ARMul_UndefInstr (state
, instr
);
3081 UNDEF_LSRBaseEQOffWb
;
3082 UNDEF_LSRBaseEQDestWb
;
3085 temp
= LHS
- LSRegRHS
;
3086 if (StoreWord (state
, instr
, temp
))
3090 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3093 ARMul_UndefInstr (state
, instr
);
3096 UNDEF_LSRBaseEQOffWb
;
3097 UNDEF_LSRBaseEQDestWb
;
3100 temp
= LHS
- LSRegRHS
;
3101 if (LoadWord (state
, instr
, temp
))
3105 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3110 && handle_v6_insn (state
, instr
))
3113 ARMul_UndefInstr (state
, instr
);
3116 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
3119 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3124 && handle_v6_insn (state
, instr
))
3127 ARMul_UndefInstr (state
, instr
);
3130 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
3133 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3136 ARMul_UndefInstr (state
, instr
);
3139 UNDEF_LSRBaseEQOffWb
;
3140 UNDEF_LSRBaseEQDestWb
;
3143 temp
= LHS
- LSRegRHS
;
3144 if (StoreByte (state
, instr
, temp
))
3148 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3151 ARMul_UndefInstr (state
, instr
);
3154 UNDEF_LSRBaseEQOffWb
;
3155 UNDEF_LSRBaseEQDestWb
;
3158 temp
= LHS
- LSRegRHS
;
3159 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3163 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3168 && handle_v6_insn (state
, instr
))
3171 ARMul_UndefInstr (state
, instr
);
3174 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
3177 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
3180 ARMul_UndefInstr (state
, instr
);
3183 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
3186 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
3191 && handle_v6_insn (state
, instr
))
3194 ARMul_UndefInstr (state
, instr
);
3197 UNDEF_LSRBaseEQOffWb
;
3198 UNDEF_LSRBaseEQDestWb
;
3201 temp
= LHS
+ LSRegRHS
;
3202 if (StoreWord (state
, instr
, temp
))
3206 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
3209 ARMul_UndefInstr (state
, instr
);
3212 UNDEF_LSRBaseEQOffWb
;
3213 UNDEF_LSRBaseEQDestWb
;
3216 temp
= LHS
+ LSRegRHS
;
3217 if (LoadWord (state
, instr
, temp
))
3221 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
3226 && handle_v6_insn (state
, instr
))
3229 ARMul_UndefInstr (state
, instr
);
3232 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
3235 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
3238 ARMul_UndefInstr (state
, instr
);
3241 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
3244 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
3247 ARMul_UndefInstr (state
, instr
);
3250 UNDEF_LSRBaseEQOffWb
;
3251 UNDEF_LSRBaseEQDestWb
;
3254 temp
= LHS
+ LSRegRHS
;
3255 if (StoreByte (state
, instr
, temp
))
3259 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
3262 /* Check for the special breakpoint opcode.
3263 This value should correspond to the value defined
3264 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
3265 if (BITS (0, 19) == 0xfdefe)
3267 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
3268 ARMul_Abort (state
, ARMul_SWIV
);
3271 ARMul_UndefInstr (state
, instr
);
3274 UNDEF_LSRBaseEQOffWb
;
3275 UNDEF_LSRBaseEQDestWb
;
3278 temp
= LHS
+ LSRegRHS
;
3279 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3284 /* Multiple Data Transfer Instructions. */
3286 case 0x80: /* Store, No WriteBack, Post Dec. */
3287 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3290 case 0x81: /* Load, No WriteBack, Post Dec. */
3291 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3294 case 0x82: /* Store, WriteBack, Post Dec. */
3295 temp
= LSBase
- LSMNumRegs
;
3296 STOREMULT (instr
, temp
+ 4L, temp
);
3299 case 0x83: /* Load, WriteBack, Post Dec. */
3300 temp
= LSBase
- LSMNumRegs
;
3301 LOADMULT (instr
, temp
+ 4L, temp
);
3304 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
3305 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3308 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
3309 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3312 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
3313 temp
= LSBase
- LSMNumRegs
;
3314 STORESMULT (instr
, temp
+ 4L, temp
);
3317 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3318 temp
= LSBase
- LSMNumRegs
;
3319 LOADSMULT (instr
, temp
+ 4L, temp
);
3322 case 0x88: /* Store, No WriteBack, Post Inc. */
3323 STOREMULT (instr
, LSBase
, 0L);
3326 case 0x89: /* Load, No WriteBack, Post Inc. */
3327 LOADMULT (instr
, LSBase
, 0L);
3330 case 0x8a: /* Store, WriteBack, Post Inc. */
3332 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
3335 case 0x8b: /* Load, WriteBack, Post Inc. */
3337 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
3340 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3341 STORESMULT (instr
, LSBase
, 0L);
3344 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3345 LOADSMULT (instr
, LSBase
, 0L);
3348 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3350 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
3353 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3355 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
3358 case 0x90: /* Store, No WriteBack, Pre Dec. */
3359 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3362 case 0x91: /* Load, No WriteBack, Pre Dec. */
3363 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3366 case 0x92: /* Store, WriteBack, Pre Dec. */
3367 temp
= LSBase
- LSMNumRegs
;
3368 STOREMULT (instr
, temp
, temp
);
3371 case 0x93: /* Load, WriteBack, Pre Dec. */
3372 temp
= LSBase
- LSMNumRegs
;
3373 LOADMULT (instr
, temp
, temp
);
3376 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3377 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3380 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3381 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3384 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3385 temp
= LSBase
- LSMNumRegs
;
3386 STORESMULT (instr
, temp
, temp
);
3389 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3390 temp
= LSBase
- LSMNumRegs
;
3391 LOADSMULT (instr
, temp
, temp
);
3394 case 0x98: /* Store, No WriteBack, Pre Inc. */
3395 STOREMULT (instr
, LSBase
+ 4L, 0L);
3398 case 0x99: /* Load, No WriteBack, Pre Inc. */
3399 LOADMULT (instr
, LSBase
+ 4L, 0L);
3402 case 0x9a: /* Store, WriteBack, Pre Inc. */
3404 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3407 case 0x9b: /* Load, WriteBack, Pre Inc. */
3409 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3412 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3413 STORESMULT (instr
, LSBase
+ 4L, 0L);
3416 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3417 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3420 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3422 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3425 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3427 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3431 /* Branch forward. */
3440 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3445 /* Branch backward. */
3454 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3459 /* Branch and Link forward. */
3468 /* Put PC into Link. */
3470 state
->Reg
[14] = pc
+ 4;
3472 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3474 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3479 /* Branch and Link backward. */
3488 /* Put PC into Link. */
3490 state
->Reg
[14] = pc
+ 4;
3492 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3494 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3499 /* Co-Processor Data Transfers. */
3503 /* Reading from R15 is UNPREDICTABLE. */
3504 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3505 ARMul_UndefInstr (state
, instr
);
3506 /* Is access to coprocessor 0 allowed ? */
3507 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3508 ARMul_UndefInstr (state
, instr
);
3509 /* Special treatment for XScale coprocessors. */
3510 else if (state
->is_XScale
)
3512 /* Only opcode 0 is supported. */
3513 if (BITS (4, 7) != 0x00)
3514 ARMul_UndefInstr (state
, instr
);
3515 /* Only coporcessor 0 is supported. */
3516 else if (CPNum
!= 0x00)
3517 ARMul_UndefInstr (state
, instr
);
3518 /* Only accumulator 0 is supported. */
3519 else if (BITS (0, 3) != 0x00)
3520 ARMul_UndefInstr (state
, instr
);
3523 /* XScale MAR insn. Move two registers into accumulator. */
3524 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3525 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3529 /* FIXME: Not sure what to do for other v5 processors. */
3530 ARMul_UndefInstr (state
, instr
);
3535 case 0xc0: /* Store , No WriteBack , Post Dec. */
3536 ARMul_STC (state
, instr
, LHS
);
3542 /* Writes to R15 are UNPREDICATABLE. */
3543 if (DESTReg
== 15 || LHSReg
== 15)
3544 ARMul_UndefInstr (state
, instr
);
3545 /* Is access to the coprocessor allowed ? */
3546 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3547 ARMul_UndefInstr (state
, instr
);
3548 /* Special handling for XScale coprcoessors. */
3549 else if (state
->is_XScale
)
3551 /* Only opcode 0 is supported. */
3552 if (BITS (4, 7) != 0x00)
3553 ARMul_UndefInstr (state
, instr
);
3554 /* Only coprocessor 0 is supported. */
3555 else if (CPNum
!= 0x00)
3556 ARMul_UndefInstr (state
, instr
);
3557 /* Only accumulator 0 is supported. */
3558 else if (BITS (0, 3) != 0x00)
3559 ARMul_UndefInstr (state
, instr
);
3562 /* XScale MRA insn. Move accumulator into two registers. */
3563 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3568 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3569 state
->Reg
[BITS (16, 19)] = t1
;
3574 /* FIXME: Not sure what to do for other v5 processors. */
3575 ARMul_UndefInstr (state
, instr
);
3580 case 0xc1: /* Load , No WriteBack , Post Dec. */
3581 ARMul_LDC (state
, instr
, LHS
);
3585 case 0xc6: /* Store , WriteBack , Post Dec. */
3587 state
->Base
= lhs
- LSCOff
;
3588 ARMul_STC (state
, instr
, lhs
);
3592 case 0xc7: /* Load , WriteBack , Post Dec. */
3594 state
->Base
= lhs
- LSCOff
;
3595 ARMul_LDC (state
, instr
, lhs
);
3599 case 0xcc: /* Store , No WriteBack , Post Inc. */
3600 ARMul_STC (state
, instr
, LHS
);
3604 case 0xcd: /* Load , No WriteBack , Post Inc. */
3605 ARMul_LDC (state
, instr
, LHS
);
3609 case 0xce: /* Store , WriteBack , Post Inc. */
3611 state
->Base
= lhs
+ LSCOff
;
3612 ARMul_STC (state
, instr
, LHS
);
3616 case 0xcf: /* Load , WriteBack , Post Inc. */
3618 state
->Base
= lhs
+ LSCOff
;
3619 ARMul_LDC (state
, instr
, LHS
);
3623 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3624 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3628 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3629 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3633 case 0xd6: /* Store , WriteBack , Pre Dec. */
3636 ARMul_STC (state
, instr
, lhs
);
3640 case 0xd7: /* Load , WriteBack , Pre Dec. */
3643 ARMul_LDC (state
, instr
, lhs
);
3647 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3648 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3652 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3653 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3657 case 0xde: /* Store , WriteBack , Pre Inc. */
3660 ARMul_STC (state
, instr
, lhs
);
3664 case 0xdf: /* Load , WriteBack , Pre Inc. */
3667 ARMul_LDC (state
, instr
, lhs
);
3671 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3674 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3676 ARMul_UndefInstr (state
, instr
);
3679 if (state
->is_XScale
)
3680 switch (BITS (18, 19))
3683 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3685 /* XScale MIA instruction. Signed multiplication of
3686 two 32 bit values and addition to 40 bit accumulator. */
3687 long long Rm
= state
->Reg
[MULLHSReg
];
3688 long long Rs
= state
->Reg
[MULACCReg
];
3694 state
->Accumulator
+= Rm
* Rs
;
3700 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3702 /* XScale MIAPH instruction. */
3703 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3704 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3705 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3706 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3721 state
->Accumulator
+= t5
;
3726 state
->Accumulator
+= t5
;
3732 if (BITS (4, 11) == 1)
3734 /* XScale MIAxy instruction. */
3740 t1
= state
->Reg
[MULLHSReg
] >> 16;
3742 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3745 t2
= state
->Reg
[MULACCReg
] >> 16;
3747 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3757 state
->Accumulator
+= t5
;
3781 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3783 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3784 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3788 ARMul_MCR (state
, instr
, DEST
);
3792 ARMul_CDP (state
, instr
);
3796 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3808 temp
= ARMul_MRC (state
, instr
);
3811 ASSIGNN ((temp
& NBIT
) != 0);
3812 ASSIGNZ ((temp
& ZBIT
) != 0);
3813 ASSIGNC ((temp
& CBIT
) != 0);
3814 ASSIGNV ((temp
& VBIT
) != 0);
3821 ARMul_CDP (state
, instr
);
3825 /* SWI instruction. */
3842 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3844 /* A prefetch abort. */
3845 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
3846 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3850 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3851 ARMul_Abort (state
, ARMul_SWIV
);
3861 #ifdef NEED_UI_LOOP_HOOK
3862 if (deprecated_ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3864 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3865 deprecated_ui_loop_hook (0);
3867 #endif /* NEED_UI_LOOP_HOOK */
3869 if (state
->Emulate
== ONCE
)
3870 state
->Emulate
= STOP
;
3871 /* If we have changed mode, allow the PC to advance before stopping. */
3872 else if (state
->Emulate
== CHANGEMODE
)
3874 else if (state
->Emulate
!= RUN
)
3877 while (!stop_simulator
);
3879 state
->decoded
= decoded
;
3880 state
->loaded
= loaded
;
3886 /* This routine evaluates most Data Processing register RHS's with the S
3887 bit clear. It is intended to be called from the macro DPRegRHS, which
3888 filters the common case of an unshifted register with in line code. */
3891 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3893 ARMword shamt
, base
;
3898 /* Shift amount in a register. */
3903 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3906 base
= state
->Reg
[base
];
3907 ARMul_Icycles (state
, 1, 0L);
3908 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3909 switch ((int) BITS (5, 6))
3914 else if (shamt
>= 32)
3917 return (base
<< shamt
);
3921 else if (shamt
>= 32)
3924 return (base
>> shamt
);
3928 else if (shamt
>= 32)
3929 return ((ARMword
) ((long int) base
>> 31L));
3931 return ((ARMword
) ((long int) base
>> (int) shamt
));
3937 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3942 /* Shift amount is a constant. */
3945 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3948 base
= state
->Reg
[base
];
3949 shamt
= BITS (7, 11);
3950 switch ((int) BITS (5, 6))
3953 return (base
<< shamt
);
3958 return (base
>> shamt
);
3961 return ((ARMword
) ((long int) base
>> 31L));
3963 return ((ARMword
) ((long int) base
>> (int) shamt
));
3967 return ((base
>> 1) | (CFLAG
<< 31));
3969 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3976 /* This routine evaluates most Logical Data Processing register RHS's
3977 with the S bit set. It is intended to be called from the macro
3978 DPSRegRHS, which filters the common case of an unshifted register
3979 with in line code. */
3982 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3984 ARMword shamt
, base
;
3989 /* Shift amount in a register. */
3994 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3997 base
= state
->Reg
[base
];
3998 ARMul_Icycles (state
, 1, 0L);
3999 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4000 switch ((int) BITS (5, 6))
4005 else if (shamt
== 32)
4010 else if (shamt
> 32)
4017 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4018 return (base
<< shamt
);
4023 else if (shamt
== 32)
4025 ASSIGNC (base
>> 31);
4028 else if (shamt
> 32)
4035 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4036 return (base
>> shamt
);
4041 else if (shamt
>= 32)
4043 ASSIGNC (base
>> 31L);
4044 return ((ARMword
) ((long int) base
>> 31L));
4048 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
4049 return ((ARMword
) ((long int) base
>> (int) shamt
));
4057 ASSIGNC (base
>> 31);
4062 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4063 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4069 /* Shift amount is a constant. */
4072 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4075 base
= state
->Reg
[base
];
4076 shamt
= BITS (7, 11);
4078 switch ((int) BITS (5, 6))
4081 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4082 return (base
<< shamt
);
4086 ASSIGNC (base
>> 31);
4091 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4092 return (base
>> shamt
);
4097 ASSIGNC (base
>> 31L);
4098 return ((ARMword
) ((long int) base
>> 31L));
4102 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
4103 return ((ARMword
) ((long int) base
>> (int) shamt
));
4111 return ((base
>> 1) | (shamt
<< 31));
4115 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4116 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4124 /* This routine handles writes to register 15 when the S bit is not set. */
4127 WriteR15 (ARMul_State
* state
, ARMword src
)
4129 /* The ARM documentation states that the two least significant bits
4130 are discarded when setting PC, except in the cases handled by
4131 WriteR15Branch() below. It's probably an oversight: in THUMB
4132 mode, the second least significant bit should probably not be
4142 state
->Reg
[15] = src
& PCBITS
;
4144 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
4145 ARMul_R15Altered (state
);
4151 /* This routine handles writes to register 15 when the S bit is set. */
4154 WriteSR15 (ARMul_State
* state
, ARMword src
)
4157 if (state
->Bank
> 0)
4159 state
->Cpsr
= state
->Spsr
[state
->Bank
];
4160 ARMul_CPSRAltered (state
);
4168 state
->Reg
[15] = src
& PCBITS
;
4172 /* ARMul_R15Altered would have to support it. */
4178 if (state
->Bank
== USERBANK
)
4179 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
4181 state
->Reg
[15] = src
;
4183 ARMul_R15Altered (state
);
4188 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
4189 will switch to Thumb mode if the least significant bit is set. */
4192 WriteR15Branch (ARMul_State
* state
, ARMword src
)
4199 state
->Reg
[15] = src
& 0xfffffffe;
4204 state
->Reg
[15] = src
& 0xfffffffc;
4208 WriteR15 (state
, src
);
4212 /* This routine evaluates most Load and Store register RHS's. It is
4213 intended to be called from the macro LSRegRHS, which filters the
4214 common case of an unshifted register with in line code. */
4217 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
4219 ARMword shamt
, base
;
4224 /* Now forbidden, but ... */
4225 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4228 base
= state
->Reg
[base
];
4230 shamt
= BITS (7, 11);
4231 switch ((int) BITS (5, 6))
4234 return (base
<< shamt
);
4239 return (base
>> shamt
);
4242 return ((ARMword
) ((long int) base
>> 31L));
4244 return ((ARMword
) ((long int) base
>> (int) shamt
));
4248 return ((base
>> 1) | (CFLAG
<< 31));
4250 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4257 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
4260 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
4267 /* Now forbidden, but ... */
4268 return ECC
| ER15INT
| R15PC
| EMODE
;
4270 return state
->Reg
[RHSReg
];
4274 return BITS (0, 3) | (BITS (8, 11) << 4);
4277 /* This function does the work of loading a word for a LDR instruction. */
4280 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4286 if (ADDREXCEPT (address
))
4287 INTERNALABORT (address
);
4290 dest
= ARMul_LoadWordN (state
, address
);
4295 return state
->lateabtSig
;
4298 dest
= ARMul_Align (state
, address
, dest
);
4300 ARMul_Icycles (state
, 1, 0L);
4302 return (DESTReg
!= LHSReg
);
4306 /* This function does the work of loading a halfword. */
4309 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
4316 if (ADDREXCEPT (address
))
4317 INTERNALABORT (address
);
4319 dest
= ARMul_LoadHalfWord (state
, address
);
4323 return state
->lateabtSig
;
4327 if (dest
& 1 << (16 - 1))
4328 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
4331 ARMul_Icycles (state
, 1, 0L);
4332 return (DESTReg
!= LHSReg
);
4337 /* This function does the work of loading a byte for a LDRB instruction. */
4340 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
4346 if (ADDREXCEPT (address
))
4347 INTERNALABORT (address
);
4349 dest
= ARMul_LoadByte (state
, address
);
4353 return state
->lateabtSig
;
4357 if (dest
& 1 << (8 - 1))
4358 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
4361 ARMul_Icycles (state
, 1, 0L);
4363 return (DESTReg
!= LHSReg
);
4366 /* This function does the work of loading two words for a LDRD instruction. */
4369 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
4373 ARMword write_back
= BIT (21);
4374 ARMword immediate
= BIT (22);
4375 ARMword add_to_base
= BIT (23);
4376 ARMword pre_indexed
= BIT (24);
4386 /* If the writeback bit is set, the pre-index bit must be clear. */
4387 if (write_back
&& ! pre_indexed
)
4389 ARMul_UndefInstr (state
, instr
);
4393 /* Extract the base address register. */
4396 /* Extract the destination register and check it. */
4399 /* Destination register must be even. */
4401 /* Destination register cannot be LR. */
4402 || (dest_reg
== 14))
4404 ARMul_UndefInstr (state
, instr
);
4408 /* Compute the base address. */
4409 base
= state
->Reg
[addr_reg
];
4411 /* Compute the offset. */
4412 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4414 /* Compute the sum of the two. */
4416 sum
= base
+ offset
;
4418 sum
= base
- offset
;
4420 /* If this is a pre-indexed mode use the sum. */
4426 /* The address must be aligned on a 8 byte boundary. */
4430 ARMul_DATAABORT (addr
);
4432 ARMul_UndefInstr (state
, instr
);
4437 /* For pre indexed or post indexed addressing modes,
4438 check that the destination registers do not overlap
4439 the address registers. */
4440 if ((! pre_indexed
|| write_back
)
4441 && ( addr_reg
== dest_reg
4442 || addr_reg
== dest_reg
+ 1))
4444 ARMul_UndefInstr (state
, instr
);
4448 /* Load the words. */
4449 value1
= ARMul_LoadWordN (state
, addr
);
4450 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4452 /* Check for data aborts. */
4459 ARMul_Icycles (state
, 2, 0L);
4461 /* Store the values. */
4462 state
->Reg
[dest_reg
] = value1
;
4463 state
->Reg
[dest_reg
+ 1] = value2
;
4465 /* Do the post addressing and writeback. */
4469 if (! pre_indexed
|| write_back
)
4470 state
->Reg
[addr_reg
] = addr
;
4473 /* This function does the work of storing two words for a STRD instruction. */
4476 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4480 ARMword write_back
= BIT (21);
4481 ARMword immediate
= BIT (22);
4482 ARMword add_to_base
= BIT (23);
4483 ARMword pre_indexed
= BIT (24);
4491 /* If the writeback bit is set, the pre-index bit must be clear. */
4492 if (write_back
&& ! pre_indexed
)
4494 ARMul_UndefInstr (state
, instr
);
4498 /* Extract the base address register. */
4501 /* Base register cannot be PC. */
4504 ARMul_UndefInstr (state
, instr
);
4508 /* Extract the source register. */
4511 /* Source register must be even. */
4514 ARMul_UndefInstr (state
, instr
);
4518 /* Compute the base address. */
4519 base
= state
->Reg
[addr_reg
];
4521 /* Compute the offset. */
4522 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4524 /* Compute the sum of the two. */
4526 sum
= base
+ offset
;
4528 sum
= base
- offset
;
4530 /* If this is a pre-indexed mode use the sum. */
4536 /* The address must be aligned on a 8 byte boundary. */
4540 ARMul_DATAABORT (addr
);
4542 ARMul_UndefInstr (state
, instr
);
4547 /* For pre indexed or post indexed addressing modes,
4548 check that the destination registers do not overlap
4549 the address registers. */
4550 if ((! pre_indexed
|| write_back
)
4551 && ( addr_reg
== src_reg
4552 || addr_reg
== src_reg
+ 1))
4554 ARMul_UndefInstr (state
, instr
);
4558 /* Load the words. */
4559 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4560 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4568 /* Do the post addressing and writeback. */
4572 if (! pre_indexed
|| write_back
)
4573 state
->Reg
[addr_reg
] = addr
;
4576 /* This function does the work of storing a word from a STR instruction. */
4579 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4584 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4587 ARMul_StoreWordN (state
, address
, DEST
);
4589 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4591 INTERNALABORT (address
);
4592 (void) ARMul_LoadWordN (state
, address
);
4595 ARMul_StoreWordN (state
, address
, DEST
);
4600 return state
->lateabtSig
;
4606 /* This function does the work of storing a byte for a STRH instruction. */
4609 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4615 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4619 ARMul_StoreHalfWord (state
, address
, DEST
);
4621 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4623 INTERNALABORT (address
);
4624 (void) ARMul_LoadHalfWord (state
, address
);
4627 ARMul_StoreHalfWord (state
, address
, DEST
);
4633 return state
->lateabtSig
;
4640 /* This function does the work of storing a byte for a STRB instruction. */
4643 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4648 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4651 ARMul_StoreByte (state
, address
, DEST
);
4653 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4655 INTERNALABORT (address
);
4656 (void) ARMul_LoadByte (state
, address
);
4659 ARMul_StoreByte (state
, address
, DEST
);
4664 return state
->lateabtSig
;
4670 /* This function does the work of loading the registers listed in an LDM
4671 instruction, when the S bit is clear. The code here is always increment
4672 after, it's up to the caller to get the input address correct and to
4673 handle base register modification. */
4676 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4682 UNDEF_LSMBaseInListWb
;
4685 if (ADDREXCEPT (address
))
4686 INTERNALABORT (address
);
4688 if (BIT (21) && LHSReg
!= 15)
4691 /* N cycle first. */
4692 for (temp
= 0; !BIT (temp
); temp
++)
4695 dest
= ARMul_LoadWordN (state
, address
);
4697 if (!state
->abortSig
&& !state
->Aborted
)
4698 state
->Reg
[temp
++] = dest
;
4699 else if (!state
->Aborted
)
4701 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4702 state
->Aborted
= ARMul_DataAbortV
;
4705 /* S cycles from here on. */
4706 for (; temp
< 16; temp
++)
4709 /* Load this register. */
4711 dest
= ARMul_LoadWordS (state
, address
);
4713 if (!state
->abortSig
&& !state
->Aborted
)
4714 state
->Reg
[temp
] = dest
;
4715 else if (!state
->Aborted
)
4717 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4718 state
->Aborted
= ARMul_DataAbortV
;
4722 if (BIT (15) && !state
->Aborted
)
4723 /* PC is in the reg list. */
4724 WriteR15Branch (state
, PC
);
4726 /* To write back the final register. */
4727 ARMul_Icycles (state
, 1, 0L);
4731 if (BIT (21) && LHSReg
!= 15)
4737 /* This function does the work of loading the registers listed in an LDM
4738 instruction, when the S bit is set. The code here is always increment
4739 after, it's up to the caller to get the input address correct and to
4740 handle base register modification. */
4743 LoadSMult (ARMul_State
* state
,
4752 UNDEF_LSMBaseInListWb
;
4757 if (ADDREXCEPT (address
))
4758 INTERNALABORT (address
);
4761 if (BIT (21) && LHSReg
!= 15)
4764 if (!BIT (15) && state
->Bank
!= USERBANK
)
4766 /* Temporary reg bank switch. */
4767 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4768 UNDEF_LSMUserBankWb
;
4771 /* N cycle first. */
4772 for (temp
= 0; !BIT (temp
); temp
++)
4775 dest
= ARMul_LoadWordN (state
, address
);
4777 if (!state
->abortSig
)
4778 state
->Reg
[temp
++] = dest
;
4779 else if (!state
->Aborted
)
4781 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4782 state
->Aborted
= ARMul_DataAbortV
;
4785 /* S cycles from here on. */
4786 for (; temp
< 16; temp
++)
4789 /* Load this register. */
4791 dest
= ARMul_LoadWordS (state
, address
);
4793 if (!state
->abortSig
&& !state
->Aborted
)
4794 state
->Reg
[temp
] = dest
;
4795 else if (!state
->Aborted
)
4797 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4798 state
->Aborted
= ARMul_DataAbortV
;
4802 if (BIT (15) && !state
->Aborted
)
4804 /* PC is in the reg list. */
4806 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4808 state
->Cpsr
= GETSPSR (state
->Bank
);
4809 ARMul_CPSRAltered (state
);
4812 WriteR15 (state
, PC
);
4814 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4816 /* Protect bits in user mode. */
4817 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4818 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4819 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4820 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4823 ARMul_R15Altered (state
);
4829 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4830 /* Restore the correct bank. */
4831 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4833 /* To write back the final register. */
4834 ARMul_Icycles (state
, 1, 0L);
4838 if (BIT (21) && LHSReg
!= 15)
4845 /* This function does the work of storing the registers listed in an STM
4846 instruction, when the S bit is clear. The code here is always increment
4847 after, it's up to the caller to get the input address correct and to
4848 handle base register modification. */
4851 StoreMult (ARMul_State
* state
,
4860 UNDEF_LSMBaseInListWb
;
4863 /* N-cycle, increment the PC and update the NextInstr state. */
4867 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4868 INTERNALABORT (address
);
4874 /* N cycle first. */
4875 for (temp
= 0; !BIT (temp
); temp
++)
4879 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4883 (void) ARMul_LoadWordN (state
, address
);
4885 /* Fake the Stores as Loads. */
4886 for (; temp
< 16; temp
++)
4889 /* Save this register. */
4891 (void) ARMul_LoadWordS (state
, address
);
4894 if (BIT (21) && LHSReg
!= 15)
4900 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4903 if (state
->abortSig
&& !state
->Aborted
)
4905 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4906 state
->Aborted
= ARMul_DataAbortV
;
4909 if (BIT (21) && LHSReg
!= 15)
4912 /* S cycles from here on. */
4913 for (; temp
< 16; temp
++)
4916 /* Save this register. */
4919 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4921 if (state
->abortSig
&& !state
->Aborted
)
4923 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4924 state
->Aborted
= ARMul_DataAbortV
;
4932 /* This function does the work of storing the registers listed in an STM
4933 instruction when the S bit is set. The code here is always increment
4934 after, it's up to the caller to get the input address correct and to
4935 handle base register modification. */
4938 StoreSMult (ARMul_State
* state
,
4947 UNDEF_LSMBaseInListWb
;
4952 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4953 INTERNALABORT (address
);
4959 if (state
->Bank
!= USERBANK
)
4961 /* Force User Bank. */
4962 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4963 UNDEF_LSMUserBankWb
;
4966 for (temp
= 0; !BIT (temp
); temp
++)
4967 ; /* N cycle first. */
4970 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4974 (void) ARMul_LoadWordN (state
, address
);
4976 for (; temp
< 16; temp
++)
4977 /* Fake the Stores as Loads. */
4980 /* Save this register. */
4983 (void) ARMul_LoadWordS (state
, address
);
4986 if (BIT (21) && LHSReg
!= 15)
4993 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4996 if (state
->abortSig
&& !state
->Aborted
)
4998 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4999 state
->Aborted
= ARMul_DataAbortV
;
5002 /* S cycles from here on. */
5003 for (; temp
< 16; temp
++)
5006 /* Save this register. */
5009 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5011 if (state
->abortSig
&& !state
->Aborted
)
5013 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5014 state
->Aborted
= ARMul_DataAbortV
;
5018 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5019 /* Restore the correct bank. */
5020 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5022 if (BIT (21) && LHSReg
!= 15)
5029 /* This function does the work of adding two 32bit values
5030 together, and calculating if a carry has occurred. */
5033 Add32 (ARMword a1
, ARMword a2
, int *carry
)
5035 ARMword result
= (a1
+ a2
);
5036 unsigned int uresult
= (unsigned int) result
;
5037 unsigned int ua1
= (unsigned int) a1
;
5039 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5040 or (result > RdLo) then we have no carry. */
5041 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
5049 /* This function does the work of multiplying
5050 two 32bit values to give a 64bit result. */
5053 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5055 /* Operand register numbers. */
5056 int nRdHi
, nRdLo
, nRs
, nRm
;
5057 ARMword RdHi
= 0, RdLo
= 0, Rm
;
5061 nRdHi
= BITS (16, 19);
5062 nRdLo
= BITS (12, 15);
5066 /* Needed to calculate the cycle count. */
5067 Rm
= state
->Reg
[nRm
];
5069 /* Check for illegal operand combinations first. */
5078 /* Intermediate results. */
5079 ARMword lo
, mid1
, mid2
, hi
;
5081 ARMword Rs
= state
->Reg
[nRs
];
5086 /* Compute sign of result and adjust operands if necessary. */
5087 sign
= (Rm
^ Rs
) & 0x80000000;
5089 if (((signed long) Rm
) < 0)
5092 if (((signed long) Rs
) < 0)
5096 /* We can split the 32x32 into four 16x16 operations. This
5097 ensures that we do not lose precision on 32bit only hosts. */
5098 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
5099 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5100 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
5101 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5103 /* We now need to add all of these results together, taking
5104 care to propogate the carries from the additions. */
5105 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
5107 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
5109 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
5113 /* Negate result if necessary. */
5116 if (RdLo
== 0xFFFFFFFF)
5125 state
->Reg
[nRdLo
] = RdLo
;
5126 state
->Reg
[nRdHi
] = RdHi
;
5129 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
5132 /* Ensure that both RdHi and RdLo are used to compute Z,
5133 but don't let RdLo's sign bit make it to N. */
5134 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
5136 /* The cycle count depends on whether the instruction is a signed or
5137 unsigned multiply, and what bits are clear in the multiplier. */
5138 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
5139 /* Invert the bits to make the check against zero. */
5142 if ((Rm
& 0xFFFFFF00) == 0)
5144 else if ((Rm
& 0xFFFF0000) == 0)
5146 else if ((Rm
& 0xFF000000) == 0)
5154 /* This function does the work of multiplying two 32bit
5155 values and adding a 64bit value to give a 64bit result. */
5158 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5165 nRdHi
= BITS (16, 19);
5166 nRdLo
= BITS (12, 15);
5168 RdHi
= state
->Reg
[nRdHi
];
5169 RdLo
= state
->Reg
[nRdLo
];
5171 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
5173 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
5174 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
5176 state
->Reg
[nRdLo
] = RdLo
;
5177 state
->Reg
[nRdHi
] = RdHi
;
5180 /* Ensure that both RdHi and RdLo are used to compute Z,
5181 but don't let RdLo's sign bit make it to N. */
5182 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
5184 /* Extra cycle for addition. */