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 extern int stop_simulator
;
53 /* Short-hand macros for LDR/STR. */
55 /* Store post decrement writeback. */
58 if (StoreHalfWord (state, instr, lhs)) \
59 LSBase = lhs - GetLS7RHS (state, instr);
61 /* Store post increment writeback. */
64 if (StoreHalfWord (state, instr, lhs)) \
65 LSBase = lhs + GetLS7RHS (state, instr);
67 /* Store pre decrement. */
69 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
71 /* Store pre decrement writeback. */
72 #define SHPREDOWNWB() \
73 temp = LHS - GetLS7RHS (state, instr); \
74 if (StoreHalfWord (state, instr, temp)) \
77 /* Store pre increment. */
79 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
81 /* Store pre increment writeback. */
83 temp = LHS + GetLS7RHS (state, instr); \
84 if (StoreHalfWord (state, instr, temp)) \
87 /* Load post decrement writeback. */
88 #define LHPOSTDOWN() \
92 temp = lhs - GetLS7RHS (state, instr); \
94 switch (BITS (5, 6)) \
97 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
101 if (LoadByte (state, instr, lhs, LSIGNED)) \
105 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
108 case 0: /* SWP handled elsewhere. */ \
117 /* Load post increment writeback. */
122 temp = lhs + GetLS7RHS (state, instr); \
124 switch (BITS (5, 6)) \
127 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
131 if (LoadByte (state, instr, lhs, LSIGNED)) \
135 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
138 case 0: /* SWP handled elsewhere. */ \
147 /* Load pre decrement. */
148 #define LHPREDOWN() \
152 temp = LHS - GetLS7RHS (state, instr); \
153 switch (BITS (5, 6)) \
156 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
159 (void) LoadByte (state, instr, temp, LSIGNED); \
162 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
165 /* SWP handled elsewhere. */ \
174 /* Load pre decrement writeback. */
175 #define LHPREDOWNWB() \
179 temp = LHS - GetLS7RHS (state, instr); \
180 switch (BITS (5, 6)) \
183 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
187 if (LoadByte (state, instr, temp, LSIGNED)) \
191 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
195 /* SWP handled elsewhere. */ \
204 /* Load pre increment. */
209 temp = LHS + GetLS7RHS (state, instr); \
210 switch (BITS (5, 6)) \
213 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
216 (void) LoadByte (state, instr, temp, LSIGNED); \
219 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
222 /* SWP handled elsewhere. */ \
231 /* Load pre increment writeback. */
232 #define LHPREUPWB() \
236 temp = LHS + GetLS7RHS (state, instr); \
237 switch (BITS (5, 6)) \
240 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
244 if (LoadByte (state, instr, temp, LSIGNED)) \
248 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
252 /* SWP handled elsewhere. */ \
261 /* Attempt to emulate an ARMv6 instruction.
262 Returns non-zero upon success. */
266 handle_v6_insn (ARMul_State
* state
, ARMword instr
)
268 switch (BITS (20, 27))
271 case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
272 case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
273 case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
274 case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
275 case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
276 case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
277 case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
278 case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
279 case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
280 case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
281 case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
282 case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
283 case 0x30: printf ("Unhandled v6 insn: movw\n"); break;
284 case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
285 case 0x34: printf ("Unhandled v6 insn: movt\n"); break;
286 case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
288 case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
289 case 0x62: printf ("Unhandled v6 insn: qadd/qsub\n"); break;
290 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
291 case 0x65: printf ("Unhandled v6 insn: uadd/usub\n"); break;
292 case 0x66: printf ("Unhandled v6 insn: uqadd/uqsub\n"); break;
293 case 0x67: printf ("Unhandled v6 insn: uhadd/uhsub\n"); break;
294 case 0x68: printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); break;
295 case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
296 case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
297 case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
298 case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
299 case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
300 case 0x7a: printf ("Unhandled v6 insn: usbfx\n"); break;
301 case 0x7c: printf ("Unhandled v6 insn: bfc/bfi\n"); break;
308 switch (BITS (4, 11))
310 case 0x07: ror
= 0; break;
311 case 0x47: ror
= 8; break;
312 case 0x87: ror
= 16; break;
313 case 0xc7: ror
= 24; break;
317 printf ("Unhandled v6 insn: ssat\n");
325 if (BITS (4, 6) == 0x7)
327 printf ("Unhandled v6 insn: ssat\n");
333 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
337 if (BITS (16, 19) == 0xf)
339 state
->Reg
[BITS (12, 15)] = Rm
;
342 state
->Reg
[BITS (12, 15)] += Rm
;
351 switch (BITS (4, 11))
353 case 0x07: ror
= 0; break;
354 case 0x47: ror
= 8; break;
355 case 0x87: ror
= 16; break;
356 case 0xc7: ror
= 24; break;
359 printf ("Unhandled v6 insn: rev\n");
368 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
372 if (BITS (16, 19) == 0xf)
374 state
->Reg
[BITS (12, 15)] = Rm
;
377 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
386 switch (BITS (4, 11))
388 case 0x07: ror
= 0; break;
389 case 0x47: ror
= 8; break;
390 case 0x87: ror
= 16; break;
391 case 0xc7: ror
= 24; break;
395 printf ("Unhandled v6 insn: usat\n");
403 if (BITS (4, 6) == 0x7)
405 printf ("Unhandled v6 insn: usat\n");
411 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
413 if (BITS (16, 19) == 0xf)
415 state
->Reg
[BITS (12, 15)] = Rm
;
418 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
427 switch (BITS (4, 11))
429 case 0x07: ror
= 0; break;
430 case 0x47: ror
= 8; break;
431 case 0x87: ror
= 16; break;
432 case 0xc7: ror
= 24; break;
435 printf ("Unhandled v6 insn: revsh\n");
444 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
446 if (BITS (16, 19) == 0xf)
448 state
->Reg
[BITS (12, 15)] = Rm
;
452 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
458 case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
463 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr
);
468 /* EMULATION of ARM6. */
470 /* The PC pipeline value depends on whether ARM
471 or Thumb instructions are being executed. */
476 ARMul_Emulate32 (ARMul_State
* state
)
478 ARMul_Emulate26 (ARMul_State
* state
)
481 ARMword instr
; /* The current instruction. */
482 ARMword dest
= 0; /* Almost the DestBus. */
483 ARMword temp
; /* Ubiquitous third hand. */
484 ARMword pc
= 0; /* The address of the current instruction. */
485 ARMword lhs
; /* Almost the ABus and BBus. */
487 ARMword decoded
= 0; /* Instruction pipeline. */
490 /* Execute the next instruction. */
492 if (state
->NextInstr
< PRIMEPIPE
)
494 decoded
= state
->decoded
;
495 loaded
= state
->loaded
;
501 /* Just keep going. */
504 switch (state
->NextInstr
)
507 /* Advance the pipeline, and an S cycle. */
508 state
->Reg
[15] += isize
;
512 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
516 /* Advance the pipeline, and an N cycle. */
517 state
->Reg
[15] += isize
;
521 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
526 /* Program counter advanced, and an S cycle. */
530 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
535 /* Program counter advanced, and an N cycle. */
539 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
544 /* The program counter has been changed. */
549 state
->Reg
[15] = pc
+ (isize
* 2);
551 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
552 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
553 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
558 /* The program counter has been changed. */
563 state
->Reg
[15] = pc
+ (isize
* 2);
565 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
566 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
567 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
573 ARMul_EnvokeEvent (state
);
575 if (! TFLAG
&& trace
)
577 fprintf (stderr
, "pc: %x, ", pc
& ~1);
579 fprintf (stderr
, "instr: %x\n", instr
);
582 if (instr
== 0 || pc
< 0x10)
584 ARMul_Abort (state
, ARMUndefinedInstrV
);
585 state
->Emulate
= FALSE
;
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",
632 (long) pc
, (long) instr
, (long) state
->Mode
);
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. */
672 fprintf (stderr
, " emulate as: ");
674 fprintf (stderr
, "%08x ", new);
676 fprintf (stderr
, "\n");
679 /* So continue instruction decoding. */
689 /* Check the condition codes. */
690 if ((temp
= TOPBITS (28)) == AL
)
691 /* Vile deed in the need for speed. */
694 /* Check the condition code. */
695 switch ((int) TOPBITS (28))
703 if (BITS (25, 27) == 5) /* BLX(1) */
707 state
->Reg
[14] = pc
+ 4;
709 /* Force entry into Thumb mode. */
712 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
714 dest
+= POSBRANCH
+ (BIT (24) << 1);
716 WriteR15Branch (state
, dest
);
719 else if ((instr
& 0xFC70F000) == 0xF450F000)
720 /* The PLD instruction. Ignored. */
722 else if ( ((instr
& 0xfe500f00) == 0xfc100100)
723 || ((instr
& 0xfe500f00) == 0xfc000100))
724 /* wldrw and wstrw are unconditional. */
727 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
728 ARMul_UndefInstr (state
, instr
);
757 temp
= (CFLAG
&& !ZFLAG
);
760 temp
= (!CFLAG
|| ZFLAG
);
763 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
766 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
769 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
772 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
776 /* Handle the Clock counter here. */
777 if (state
->is_XScale
)
782 ok
= state
->CPRead
[14] (state
, 0, & cp14r0
);
784 if (ok
&& (cp14r0
& ARMul_CP14_R0_ENABLE
))
786 unsigned long newcycles
, nowtime
= ARMul_Time (state
);
788 newcycles
= nowtime
- state
->LastTime
;
789 state
->LastTime
= nowtime
;
791 if (cp14r0
& ARMul_CP14_R0_CCD
)
793 if (state
->CP14R0_CCD
== -1)
794 state
->CP14R0_CCD
= newcycles
;
796 state
->CP14R0_CCD
+= newcycles
;
798 if (state
->CP14R0_CCD
>= 64)
802 while (state
->CP14R0_CCD
>= 64)
803 state
->CP14R0_CCD
-= 64, newcycles
++;
813 state
->CP14R0_CCD
= -1;
816 cp14r0
|= ARMul_CP14_R0_FLAG2
;
817 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
819 ok
= state
->CPRead
[14] (state
, 1, & cp14r1
);
821 /* Coded like this for portability. */
822 while (ok
&& newcycles
)
824 if (cp14r1
== 0xffffffff)
835 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
837 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
841 if (state
->CPRead
[13] (state
, 8, & temp
)
842 && (temp
& ARMul_CP13_R8_PMUS
))
843 ARMul_Abort (state
, ARMul_FIQV
);
845 ARMul_Abort (state
, ARMul_IRQV
);
851 /* Handle hardware instructions breakpoints here. */
852 if (state
->is_XScale
)
854 if ( (pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
855 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
857 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
858 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
862 /* Actual execution of instructions begins here. */
863 /* If the condition codes don't match, stop here. */
868 if (state
->is_XScale
)
870 if (BIT (20) == 0 && BITS (25, 27) == 0)
872 if (BITS (4, 7) == 0xD)
874 /* XScale Load Consecutive insn. */
875 ARMword temp
= GetLS7RHS (state
, instr
);
876 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
877 ARMword addr
= BIT (24) ? temp2
: LHS
;
880 ARMul_UndefInstr (state
, instr
);
882 /* Alignment violation. */
883 ARMul_Abort (state
, ARMul_DataAbortV
);
886 int wb
= BIT (21) || (! BIT (24));
888 state
->Reg
[BITS (12, 15)] =
889 ARMul_LoadWordN (state
, addr
);
890 state
->Reg
[BITS (12, 15) + 1] =
891 ARMul_LoadWordN (state
, addr
+ 4);
898 else if (BITS (4, 7) == 0xF)
900 /* XScale Store Consecutive insn. */
901 ARMword temp
= GetLS7RHS (state
, instr
);
902 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
903 ARMword addr
= BIT (24) ? temp2
: LHS
;
906 ARMul_UndefInstr (state
, instr
);
908 /* Alignment violation. */
909 ARMul_Abort (state
, ARMul_DataAbortV
);
912 ARMul_StoreWordN (state
, addr
,
913 state
->Reg
[BITS (12, 15)]);
914 ARMul_StoreWordN (state
, addr
+ 4,
915 state
->Reg
[BITS (12, 15) + 1]);
917 if (BIT (21)|| ! BIT (24))
925 if (ARMul_HandleIwmmxt (state
, instr
))
929 switch ((int) BITS (20, 27))
931 /* Data Processing Register RHS Instructions. */
933 case 0x00: /* AND reg and MUL */
935 if (BITS (4, 11) == 0xB)
937 /* STRH register offset, no write-back, down, post indexed. */
941 if (BITS (4, 7) == 0xD)
943 Handle_Load_Double (state
, instr
);
946 if (BITS (4, 7) == 0xF)
948 Handle_Store_Double (state
, instr
);
952 if (BITS (4, 7) == 9)
955 rhs
= state
->Reg
[MULRHSReg
];
956 if (MULLHSReg
== MULDESTReg
)
959 state
->Reg
[MULDESTReg
] = 0;
961 else if (MULDESTReg
!= 15)
962 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
966 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
967 if (rhs
& (1L << dest
))
970 /* Mult takes this many/2 I cycles. */
971 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
982 case 0x01: /* ANDS reg and MULS */
984 if ((BITS (4, 11) & 0xF9) == 0x9)
985 /* LDR register offset, no write-back, down, post indexed. */
987 /* Fall through to rest of decoding. */
989 if (BITS (4, 7) == 9)
992 rhs
= state
->Reg
[MULRHSReg
];
994 if (MULLHSReg
== MULDESTReg
)
997 state
->Reg
[MULDESTReg
] = 0;
1001 else if (MULDESTReg
!= 15)
1003 dest
= state
->Reg
[MULLHSReg
] * rhs
;
1004 ARMul_NegZero (state
, dest
);
1005 state
->Reg
[MULDESTReg
] = dest
;
1010 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1011 if (rhs
& (1L << dest
))
1014 /* Mult takes this many/2 I cycles. */
1015 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1026 case 0x02: /* EOR reg and MLA */
1028 if (BITS (4, 11) == 0xB)
1030 /* STRH register offset, write-back, down, post indexed. */
1035 if (BITS (4, 7) == 9)
1037 rhs
= state
->Reg
[MULRHSReg
];
1038 if (MULLHSReg
== MULDESTReg
)
1041 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
1043 else if (MULDESTReg
!= 15)
1044 state
->Reg
[MULDESTReg
] =
1045 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1049 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1050 if (rhs
& (1L << dest
))
1053 /* Mult takes this many/2 I cycles. */
1054 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1064 case 0x03: /* EORS reg and MLAS */
1066 if ((BITS (4, 11) & 0xF9) == 0x9)
1067 /* LDR register offset, write-back, down, post-indexed. */
1069 /* Fall through to rest of the decoding. */
1071 if (BITS (4, 7) == 9)
1074 rhs
= state
->Reg
[MULRHSReg
];
1076 if (MULLHSReg
== MULDESTReg
)
1079 dest
= state
->Reg
[MULACCReg
];
1080 ARMul_NegZero (state
, dest
);
1081 state
->Reg
[MULDESTReg
] = dest
;
1083 else if (MULDESTReg
!= 15)
1086 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1087 ARMul_NegZero (state
, dest
);
1088 state
->Reg
[MULDESTReg
] = dest
;
1093 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1094 if (rhs
& (1L << dest
))
1097 /* Mult takes this many/2 I cycles. */
1098 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1109 case 0x04: /* SUB reg */
1111 if (BITS (4, 7) == 0xB)
1113 /* STRH immediate offset, no write-back, down, post indexed. */
1117 if (BITS (4, 7) == 0xD)
1119 Handle_Load_Double (state
, instr
);
1122 if (BITS (4, 7) == 0xF)
1124 Handle_Store_Double (state
, instr
);
1133 case 0x05: /* SUBS reg */
1135 if ((BITS (4, 7) & 0x9) == 0x9)
1136 /* LDR immediate offset, no write-back, down, post indexed. */
1138 /* Fall through to the rest of the instruction decoding. */
1144 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1146 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1147 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1157 case 0x06: /* RSB reg */
1159 if (BITS (4, 7) == 0xB)
1161 /* STRH immediate offset, write-back, down, post indexed. */
1171 case 0x07: /* RSBS reg */
1173 if ((BITS (4, 7) & 0x9) == 0x9)
1174 /* LDR immediate offset, write-back, down, post indexed. */
1176 /* Fall through to remainder of instruction decoding. */
1182 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1184 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1185 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1195 case 0x08: /* ADD reg */
1197 if (BITS (4, 11) == 0xB)
1199 /* STRH register offset, no write-back, up, post indexed. */
1203 if (BITS (4, 7) == 0xD)
1205 Handle_Load_Double (state
, instr
);
1208 if (BITS (4, 7) == 0xF)
1210 Handle_Store_Double (state
, instr
);
1215 if (BITS (4, 7) == 0x9)
1219 ARMul_Icycles (state
,
1220 Multiply64 (state
, instr
, LUNSIGNED
,
1230 case 0x09: /* ADDS reg */
1232 if ((BITS (4, 11) & 0xF9) == 0x9)
1233 /* LDR register offset, no write-back, up, post indexed. */
1235 /* Fall through to remaining instruction decoding. */
1238 if (BITS (4, 7) == 0x9)
1242 ARMul_Icycles (state
,
1243 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
1251 ASSIGNZ (dest
== 0);
1252 if ((lhs
| rhs
) >> 30)
1254 /* Possible C,V,N to set. */
1255 ASSIGNN (NEG (dest
));
1256 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1257 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1268 case 0x0a: /* ADC reg */
1270 if (BITS (4, 11) == 0xB)
1272 /* STRH register offset, write-back, up, post-indexed. */
1276 if (BITS (4, 7) == 0x9)
1280 ARMul_Icycles (state
,
1281 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1287 dest
= LHS
+ rhs
+ CFLAG
;
1291 case 0x0b: /* ADCS reg */
1293 if ((BITS (4, 11) & 0xF9) == 0x9)
1294 /* LDR register offset, write-back, up, post indexed. */
1296 /* Fall through to remaining instruction decoding. */
1297 if (BITS (4, 7) == 0x9)
1301 ARMul_Icycles (state
,
1302 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1309 dest
= lhs
+ rhs
+ CFLAG
;
1310 ASSIGNZ (dest
== 0);
1311 if ((lhs
| rhs
) >> 30)
1313 /* Possible C,V,N to set. */
1314 ASSIGNN (NEG (dest
));
1315 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1316 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1327 case 0x0c: /* SBC reg */
1329 if (BITS (4, 7) == 0xB)
1331 /* STRH immediate offset, no write-back, up post indexed. */
1335 if (BITS (4, 7) == 0xD)
1337 Handle_Load_Double (state
, instr
);
1340 if (BITS (4, 7) == 0xF)
1342 Handle_Store_Double (state
, instr
);
1345 if (BITS (4, 7) == 0x9)
1349 ARMul_Icycles (state
,
1350 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
1356 dest
= LHS
- rhs
- !CFLAG
;
1360 case 0x0d: /* SBCS reg */
1362 if ((BITS (4, 7) & 0x9) == 0x9)
1363 /* LDR immediate offset, no write-back, up, post indexed. */
1366 if (BITS (4, 7) == 0x9)
1370 ARMul_Icycles (state
,
1371 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
1378 dest
= lhs
- rhs
- !CFLAG
;
1379 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1381 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1382 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1392 case 0x0e: /* RSC reg */
1394 if (BITS (4, 7) == 0xB)
1396 /* STRH immediate offset, write-back, up, post indexed. */
1401 if (BITS (4, 7) == 0x9)
1405 ARMul_Icycles (state
,
1406 MultiplyAdd64 (state
, instr
, LSIGNED
,
1412 dest
= rhs
- LHS
- !CFLAG
;
1416 case 0x0f: /* RSCS reg */
1418 if ((BITS (4, 7) & 0x9) == 0x9)
1419 /* LDR immediate offset, write-back, up, post indexed. */
1421 /* Fall through to remaining instruction decoding. */
1423 if (BITS (4, 7) == 0x9)
1427 ARMul_Icycles (state
,
1428 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
1435 dest
= rhs
- lhs
- !CFLAG
;
1437 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1439 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1440 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1450 case 0x10: /* TST reg and MRS CPSR and SWP word. */
1453 if (BIT (4) == 0 && BIT (7) == 1)
1455 /* ElSegundo SMLAxy insn. */
1456 ARMword op1
= state
->Reg
[BITS (0, 3)];
1457 ARMword op2
= state
->Reg
[BITS (8, 11)];
1458 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1472 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
1474 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
1478 if (BITS (4, 11) == 5)
1480 /* ElSegundo QADD insn. */
1481 ARMword op1
= state
->Reg
[BITS (0, 3)];
1482 ARMword op2
= state
->Reg
[BITS (16, 19)];
1483 ARMword result
= op1
+ op2
;
1484 if (AddOverflow (op1
, op2
, result
))
1486 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1489 state
->Reg
[BITS (12, 15)] = result
;
1494 if (BITS (4, 11) == 0xB)
1496 /* STRH register offset, no write-back, down, pre indexed. */
1500 if (BITS (4, 7) == 0xD)
1502 Handle_Load_Double (state
, instr
);
1505 if (BITS (4, 7) == 0xF)
1507 Handle_Store_Double (state
, instr
);
1511 if (BITS (4, 11) == 9)
1518 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1520 INTERNALABORT (temp
);
1521 (void) ARMul_LoadWordN (state
, temp
);
1522 (void) ARMul_LoadWordN (state
, temp
);
1526 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1528 DEST
= ARMul_Align (state
, temp
, dest
);
1531 if (state
->abortSig
|| state
->Aborted
)
1534 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1537 DEST
= ECC
| EINT
| EMODE
;
1545 case 0x11: /* TSTP reg */
1547 if ((BITS (4, 11) & 0xF9) == 0x9)
1548 /* LDR register offset, no write-back, down, pre indexed. */
1550 /* Continue with remaining instruction decode. */
1556 state
->Cpsr
= GETSPSR (state
->Bank
);
1557 ARMul_CPSRAltered (state
);
1569 ARMul_NegZero (state
, dest
);
1573 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
1576 if (BITS (4, 7) == 3)
1582 temp
= (pc
+ 2) | 1;
1586 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1587 state
->Reg
[14] = temp
;
1594 if (BIT (4) == 0 && BIT (7) == 1
1595 && (BIT (5) == 0 || BITS (12, 15) == 0))
1597 /* ElSegundo SMLAWy/SMULWy insn. */
1598 ARMdword op1
= state
->Reg
[BITS (0, 3)];
1599 ARMdword op2
= state
->Reg
[BITS (8, 11)];
1604 if (op1
& 0x80000000)
1609 result
= (op1
* op2
) >> 16;
1613 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1615 if (AddOverflow (result
, Rn
, result
+ Rn
))
1619 state
->Reg
[BITS (16, 19)] = result
;
1623 if (BITS (4, 11) == 5)
1625 /* ElSegundo QSUB insn. */
1626 ARMword op1
= state
->Reg
[BITS (0, 3)];
1627 ARMword op2
= state
->Reg
[BITS (16, 19)];
1628 ARMword result
= op1
- op2
;
1630 if (SubOverflow (op1
, op2
, result
))
1632 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1636 state
->Reg
[BITS (12, 15)] = result
;
1641 if (BITS (4, 11) == 0xB)
1643 /* STRH register offset, write-back, down, pre indexed. */
1647 if (BITS (4, 27) == 0x12FFF1)
1650 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1653 if (BITS (4, 7) == 0xD)
1655 Handle_Load_Double (state
, instr
);
1658 if (BITS (4, 7) == 0xF)
1660 Handle_Store_Double (state
, instr
);
1666 if (BITS (4, 7) == 0x7)
1668 extern int SWI_vector_installed
;
1670 /* Hardware is allowed to optionally override this
1671 instruction and treat it as a breakpoint. Since
1672 this is a simulator not hardware, we take the position
1673 that if a SWI vector was not installed, then an Abort
1674 vector was probably not installed either, and so
1675 normally this instruction would be ignored, even if an
1676 Abort is generated. This is a bad thing, since GDB
1677 uses this instruction for its breakpoints (at least in
1678 Thumb mode it does). So intercept the instruction here
1679 and generate a breakpoint SWI instead. */
1680 if (! SWI_vector_installed
)
1681 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1684 /* BKPT - normally this will cause an abort, but on the
1685 XScale we must check the DCSR. */
1686 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
1687 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
1691 /* Force the next instruction to be refetched. */
1692 state
->NextInstr
= RESUME
;
1698 /* MSR reg to CPSR. */
1702 /* Don't allow TBIT to be set by MSR. */
1705 ARMul_FixCPSR (state
, instr
, temp
);
1712 case 0x13: /* TEQP reg */
1714 if ((BITS (4, 11) & 0xF9) == 0x9)
1715 /* LDR register offset, write-back, down, pre indexed. */
1717 /* Continue with remaining instruction decode. */
1723 state
->Cpsr
= GETSPSR (state
->Bank
);
1724 ARMul_CPSRAltered (state
);
1736 ARMul_NegZero (state
, dest
);
1740 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
1743 if (BIT (4) == 0 && BIT (7) == 1)
1745 /* ElSegundo SMLALxy insn. */
1746 ARMdword op1
= state
->Reg
[BITS (0, 3)];
1747 ARMdword op2
= state
->Reg
[BITS (8, 11)];
1761 dest
= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
1762 dest
|= state
->Reg
[BITS (12, 15)];
1764 state
->Reg
[BITS (12, 15)] = dest
;
1765 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1769 if (BITS (4, 11) == 5)
1771 /* ElSegundo QDADD insn. */
1772 ARMword op1
= state
->Reg
[BITS (0, 3)];
1773 ARMword op2
= state
->Reg
[BITS (16, 19)];
1774 ARMword op2d
= op2
+ op2
;
1777 if (AddOverflow (op2
, op2
, op2d
))
1780 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1783 result
= op1
+ op2d
;
1784 if (AddOverflow (op1
, op2d
, result
))
1787 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1790 state
->Reg
[BITS (12, 15)] = result
;
1795 if (BITS (4, 7) == 0xB)
1797 /* STRH immediate offset, no write-back, down, pre indexed. */
1801 if (BITS (4, 7) == 0xD)
1803 Handle_Load_Double (state
, instr
);
1806 if (BITS (4, 7) == 0xF)
1808 Handle_Store_Double (state
, instr
);
1812 if (BITS (4, 11) == 9)
1819 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1821 INTERNALABORT (temp
);
1822 (void) ARMul_LoadByte (state
, temp
);
1823 (void) ARMul_LoadByte (state
, temp
);
1827 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1828 if (state
->abortSig
|| state
->Aborted
)
1831 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1835 DEST
= GETSPSR (state
->Bank
);
1842 case 0x15: /* CMPP reg. */
1844 if ((BITS (4, 7) & 0x9) == 0x9)
1845 /* LDR immediate offset, no write-back, down, pre indexed. */
1847 /* Continue with remaining instruction decode. */
1853 state
->Cpsr
= GETSPSR (state
->Bank
);
1854 ARMul_CPSRAltered (state
);
1867 ARMul_NegZero (state
, dest
);
1868 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1870 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1871 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1881 case 0x16: /* CMN reg and MSR reg to SPSR */
1884 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1886 /* ElSegundo SMULxy insn. */
1887 ARMword op1
= state
->Reg
[BITS (0, 3)];
1888 ARMword op2
= state
->Reg
[BITS (8, 11)];
1901 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1905 if (BITS (4, 11) == 5)
1907 /* ElSegundo QDSUB insn. */
1908 ARMword op1
= state
->Reg
[BITS (0, 3)];
1909 ARMword op2
= state
->Reg
[BITS (16, 19)];
1910 ARMword op2d
= op2
+ op2
;
1913 if (AddOverflow (op2
, op2
, op2d
))
1916 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1919 result
= op1
- op2d
;
1920 if (SubOverflow (op1
, op2d
, result
))
1923 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1926 state
->Reg
[BITS (12, 15)] = result
;
1933 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1935 /* ARM5 CLZ insn. */
1936 ARMword op1
= state
->Reg
[BITS (0, 3)];
1940 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1943 state
->Reg
[BITS (12, 15)] = result
;
1948 if (BITS (4, 7) == 0xB)
1950 /* STRH immediate offset, write-back, down, pre indexed. */
1954 if (BITS (4, 7) == 0xD)
1956 Handle_Load_Double (state
, instr
);
1959 if (BITS (4, 7) == 0xF)
1961 Handle_Store_Double (state
, instr
);
1969 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1977 case 0x17: /* CMNP reg */
1979 if ((BITS (4, 7) & 0x9) == 0x9)
1980 /* LDR immediate offset, write-back, down, pre indexed. */
1982 /* Continue with remaining instruction decoding. */
1987 state
->Cpsr
= GETSPSR (state
->Bank
);
1988 ARMul_CPSRAltered (state
);
2002 ASSIGNZ (dest
== 0);
2003 if ((lhs
| rhs
) >> 30)
2005 /* Possible C,V,N to set. */
2006 ASSIGNN (NEG (dest
));
2007 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2008 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2019 case 0x18: /* ORR reg */
2021 if (BITS (4, 11) == 0xB)
2023 /* STRH register offset, no write-back, up, pre indexed. */
2027 if (BITS (4, 7) == 0xD)
2029 Handle_Load_Double (state
, instr
);
2032 if (BITS (4, 7) == 0xF)
2034 Handle_Store_Double (state
, instr
);
2043 case 0x19: /* ORRS reg */
2045 if ((BITS (4, 11) & 0xF9) == 0x9)
2046 /* LDR register offset, no write-back, up, pre indexed. */
2048 /* Continue with remaining instruction decoding. */
2055 case 0x1a: /* MOV reg */
2057 if (BITS (4, 11) == 0xB)
2059 /* STRH register offset, write-back, up, pre indexed. */
2063 if (BITS (4, 7) == 0xD)
2065 Handle_Load_Double (state
, instr
);
2068 if (BITS (4, 7) == 0xF)
2070 Handle_Store_Double (state
, instr
);
2078 case 0x1b: /* MOVS reg */
2080 if ((BITS (4, 11) & 0xF9) == 0x9)
2081 /* LDR register offset, write-back, up, pre indexed. */
2083 /* Continue with remaining instruction decoding. */
2089 case 0x1c: /* BIC reg */
2091 if (BITS (4, 7) == 0xB)
2093 /* STRH immediate offset, no write-back, up, pre indexed. */
2097 if (BITS (4, 7) == 0xD)
2099 Handle_Load_Double (state
, instr
);
2102 else if (BITS (4, 7) == 0xF)
2104 Handle_Store_Double (state
, instr
);
2113 case 0x1d: /* BICS reg */
2115 if ((BITS (4, 7) & 0x9) == 0x9)
2116 /* LDR immediate offset, no write-back, up, pre indexed. */
2118 /* Continue with instruction decoding. */
2125 case 0x1e: /* MVN reg */
2127 if (BITS (4, 7) == 0xB)
2129 /* STRH immediate offset, write-back, up, pre indexed. */
2133 if (BITS (4, 7) == 0xD)
2135 Handle_Load_Double (state
, instr
);
2138 if (BITS (4, 7) == 0xF)
2140 Handle_Store_Double (state
, instr
);
2148 case 0x1f: /* MVNS reg */
2150 if ((BITS (4, 7) & 0x9) == 0x9)
2151 /* LDR immediate offset, write-back, up, pre indexed. */
2153 /* Continue instruction decoding. */
2160 /* Data Processing Immediate RHS Instructions. */
2162 case 0x20: /* AND immed */
2163 dest
= LHS
& DPImmRHS
;
2167 case 0x21: /* ANDS immed */
2173 case 0x22: /* EOR immed */
2174 dest
= LHS
^ DPImmRHS
;
2178 case 0x23: /* EORS immed */
2184 case 0x24: /* SUB immed */
2185 dest
= LHS
- DPImmRHS
;
2189 case 0x25: /* SUBS immed */
2194 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2196 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2197 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2207 case 0x26: /* RSB immed */
2208 dest
= DPImmRHS
- LHS
;
2212 case 0x27: /* RSBS immed */
2217 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2219 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2220 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2230 case 0x28: /* ADD immed */
2231 dest
= LHS
+ DPImmRHS
;
2235 case 0x29: /* ADDS immed */
2239 ASSIGNZ (dest
== 0);
2241 if ((lhs
| rhs
) >> 30)
2243 /* Possible C,V,N to set. */
2244 ASSIGNN (NEG (dest
));
2245 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2246 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2257 case 0x2a: /* ADC immed */
2258 dest
= LHS
+ DPImmRHS
+ CFLAG
;
2262 case 0x2b: /* ADCS immed */
2265 dest
= lhs
+ rhs
+ CFLAG
;
2266 ASSIGNZ (dest
== 0);
2267 if ((lhs
| rhs
) >> 30)
2269 /* Possible C,V,N to set. */
2270 ASSIGNN (NEG (dest
));
2271 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2272 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2283 case 0x2c: /* SBC immed */
2284 dest
= LHS
- DPImmRHS
- !CFLAG
;
2288 case 0x2d: /* SBCS immed */
2291 dest
= lhs
- rhs
- !CFLAG
;
2292 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2294 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2295 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2305 case 0x2e: /* RSC immed */
2306 dest
= DPImmRHS
- LHS
- !CFLAG
;
2310 case 0x2f: /* RSCS immed */
2313 dest
= rhs
- lhs
- !CFLAG
;
2314 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2316 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2317 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2327 case 0x30: /* MOVW immed */
2328 dest
= BITS (0, 11);
2329 dest
|= (BITS (16, 19) << 12);
2333 case 0x31: /* TSTP immed */
2338 state
->Cpsr
= GETSPSR (state
->Bank
);
2339 ARMul_CPSRAltered (state
);
2341 temp
= LHS
& DPImmRHS
;
2350 ARMul_NegZero (state
, dest
);
2354 case 0x32: /* TEQ immed and MSR immed to CPSR */
2356 /* MSR immed to CPSR. */
2357 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2362 case 0x33: /* TEQP immed */
2367 state
->Cpsr
= GETSPSR (state
->Bank
);
2368 ARMul_CPSRAltered (state
);
2370 temp
= LHS
^ DPImmRHS
;
2376 DPSImmRHS
; /* TEQ immed */
2378 ARMul_NegZero (state
, dest
);
2382 case 0x34: /* MOVT immed */
2383 dest
= BITS (0, 11);
2384 dest
|= (BITS (16, 19) << 12);
2385 DEST
|= (dest
<< 16);
2388 case 0x35: /* CMPP immed */
2393 state
->Cpsr
= GETSPSR (state
->Bank
);
2394 ARMul_CPSRAltered (state
);
2396 temp
= LHS
- DPImmRHS
;
2407 ARMul_NegZero (state
, dest
);
2409 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2411 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2412 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2422 case 0x36: /* CMN immed and MSR immed to SPSR */
2424 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2429 case 0x37: /* CMNP immed. */
2434 state
->Cpsr
= GETSPSR (state
->Bank
);
2435 ARMul_CPSRAltered (state
);
2437 temp
= LHS
+ DPImmRHS
;
2448 ASSIGNZ (dest
== 0);
2449 if ((lhs
| rhs
) >> 30)
2451 /* Possible C,V,N to set. */
2452 ASSIGNN (NEG (dest
));
2453 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2454 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2465 case 0x38: /* ORR immed. */
2466 dest
= LHS
| DPImmRHS
;
2470 case 0x39: /* ORRS immed. */
2476 case 0x3a: /* MOV immed. */
2481 case 0x3b: /* MOVS immed. */
2486 case 0x3c: /* BIC immed. */
2487 dest
= LHS
& ~DPImmRHS
;
2491 case 0x3d: /* BICS immed. */
2497 case 0x3e: /* MVN immed. */
2502 case 0x3f: /* MVNS immed. */
2508 /* Single Data Transfer Immediate RHS Instructions. */
2510 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2512 if (StoreWord (state
, instr
, lhs
))
2513 LSBase
= lhs
- LSImmRHS
;
2516 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2518 if (LoadWord (state
, instr
, lhs
))
2519 LSBase
= lhs
- LSImmRHS
;
2522 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2523 UNDEF_LSRBaseEQDestWb
;
2526 temp
= lhs
- LSImmRHS
;
2527 state
->NtransSig
= LOW
;
2528 if (StoreWord (state
, instr
, lhs
))
2530 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2533 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2534 UNDEF_LSRBaseEQDestWb
;
2537 state
->NtransSig
= LOW
;
2538 if (LoadWord (state
, instr
, lhs
))
2539 LSBase
= lhs
- LSImmRHS
;
2540 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2543 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2545 if (StoreByte (state
, instr
, lhs
))
2546 LSBase
= lhs
- LSImmRHS
;
2549 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2551 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2552 LSBase
= lhs
- LSImmRHS
;
2555 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2556 UNDEF_LSRBaseEQDestWb
;
2559 state
->NtransSig
= LOW
;
2560 if (StoreByte (state
, instr
, lhs
))
2561 LSBase
= lhs
- LSImmRHS
;
2562 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2565 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2566 UNDEF_LSRBaseEQDestWb
;
2569 state
->NtransSig
= LOW
;
2570 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2571 LSBase
= lhs
- LSImmRHS
;
2572 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2575 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2577 if (StoreWord (state
, instr
, lhs
))
2578 LSBase
= lhs
+ LSImmRHS
;
2581 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2583 if (LoadWord (state
, instr
, lhs
))
2584 LSBase
= lhs
+ LSImmRHS
;
2587 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2588 UNDEF_LSRBaseEQDestWb
;
2591 state
->NtransSig
= LOW
;
2592 if (StoreWord (state
, instr
, lhs
))
2593 LSBase
= lhs
+ LSImmRHS
;
2594 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2597 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2598 UNDEF_LSRBaseEQDestWb
;
2601 state
->NtransSig
= LOW
;
2602 if (LoadWord (state
, instr
, lhs
))
2603 LSBase
= lhs
+ LSImmRHS
;
2604 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2607 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2609 if (StoreByte (state
, instr
, lhs
))
2610 LSBase
= lhs
+ LSImmRHS
;
2613 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2615 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2616 LSBase
= lhs
+ LSImmRHS
;
2619 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2620 UNDEF_LSRBaseEQDestWb
;
2623 state
->NtransSig
= LOW
;
2624 if (StoreByte (state
, instr
, lhs
))
2625 LSBase
= lhs
+ LSImmRHS
;
2626 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2629 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2630 UNDEF_LSRBaseEQDestWb
;
2633 state
->NtransSig
= LOW
;
2634 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2635 LSBase
= lhs
+ LSImmRHS
;
2636 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2640 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2641 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2644 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2645 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2648 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2649 UNDEF_LSRBaseEQDestWb
;
2651 temp
= LHS
- LSImmRHS
;
2652 if (StoreWord (state
, instr
, temp
))
2656 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2657 UNDEF_LSRBaseEQDestWb
;
2659 temp
= LHS
- LSImmRHS
;
2660 if (LoadWord (state
, instr
, temp
))
2664 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2665 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2668 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2669 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2672 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2673 UNDEF_LSRBaseEQDestWb
;
2675 temp
= LHS
- LSImmRHS
;
2676 if (StoreByte (state
, instr
, temp
))
2680 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2681 UNDEF_LSRBaseEQDestWb
;
2683 temp
= LHS
- LSImmRHS
;
2684 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2688 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2689 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2692 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2693 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2696 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2697 UNDEF_LSRBaseEQDestWb
;
2699 temp
= LHS
+ LSImmRHS
;
2700 if (StoreWord (state
, instr
, temp
))
2704 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2705 UNDEF_LSRBaseEQDestWb
;
2707 temp
= LHS
+ LSImmRHS
;
2708 if (LoadWord (state
, instr
, temp
))
2712 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2713 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2716 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2717 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2720 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2721 UNDEF_LSRBaseEQDestWb
;
2723 temp
= LHS
+ LSImmRHS
;
2724 if (StoreByte (state
, instr
, temp
))
2728 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2729 UNDEF_LSRBaseEQDestWb
;
2731 temp
= LHS
+ LSImmRHS
;
2732 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2737 /* Single Data Transfer Register RHS Instructions. */
2739 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2742 ARMul_UndefInstr (state
, instr
);
2745 UNDEF_LSRBaseEQOffWb
;
2746 UNDEF_LSRBaseEQDestWb
;
2750 if (StoreWord (state
, instr
, lhs
))
2751 LSBase
= lhs
- LSRegRHS
;
2754 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2759 && handle_v6_insn (state
, instr
))
2762 ARMul_UndefInstr (state
, instr
);
2765 UNDEF_LSRBaseEQOffWb
;
2766 UNDEF_LSRBaseEQDestWb
;
2770 temp
= lhs
- LSRegRHS
;
2771 if (LoadWord (state
, instr
, lhs
))
2775 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2780 && handle_v6_insn (state
, instr
))
2783 ARMul_UndefInstr (state
, instr
);
2786 UNDEF_LSRBaseEQOffWb
;
2787 UNDEF_LSRBaseEQDestWb
;
2791 state
->NtransSig
= LOW
;
2792 if (StoreWord (state
, instr
, lhs
))
2793 LSBase
= lhs
- LSRegRHS
;
2794 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2797 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2802 && handle_v6_insn (state
, instr
))
2805 ARMul_UndefInstr (state
, instr
);
2808 UNDEF_LSRBaseEQOffWb
;
2809 UNDEF_LSRBaseEQDestWb
;
2813 temp
= lhs
- LSRegRHS
;
2814 state
->NtransSig
= LOW
;
2815 if (LoadWord (state
, instr
, lhs
))
2817 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2820 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2823 ARMul_UndefInstr (state
, instr
);
2826 UNDEF_LSRBaseEQOffWb
;
2827 UNDEF_LSRBaseEQDestWb
;
2831 if (StoreByte (state
, instr
, lhs
))
2832 LSBase
= lhs
- LSRegRHS
;
2835 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2840 && handle_v6_insn (state
, instr
))
2843 ARMul_UndefInstr (state
, instr
);
2846 UNDEF_LSRBaseEQOffWb
;
2847 UNDEF_LSRBaseEQDestWb
;
2851 temp
= lhs
- LSRegRHS
;
2852 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2856 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2861 && handle_v6_insn (state
, instr
))
2864 ARMul_UndefInstr (state
, instr
);
2867 UNDEF_LSRBaseEQOffWb
;
2868 UNDEF_LSRBaseEQDestWb
;
2872 state
->NtransSig
= LOW
;
2873 if (StoreByte (state
, instr
, lhs
))
2874 LSBase
= lhs
- LSRegRHS
;
2875 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2878 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2883 && handle_v6_insn (state
, instr
))
2886 ARMul_UndefInstr (state
, instr
);
2889 UNDEF_LSRBaseEQOffWb
;
2890 UNDEF_LSRBaseEQDestWb
;
2894 temp
= lhs
- LSRegRHS
;
2895 state
->NtransSig
= LOW
;
2896 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2898 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2901 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2906 && handle_v6_insn (state
, instr
))
2909 ARMul_UndefInstr (state
, instr
);
2912 UNDEF_LSRBaseEQOffWb
;
2913 UNDEF_LSRBaseEQDestWb
;
2917 if (StoreWord (state
, instr
, lhs
))
2918 LSBase
= lhs
+ LSRegRHS
;
2921 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2924 ARMul_UndefInstr (state
, instr
);
2927 UNDEF_LSRBaseEQOffWb
;
2928 UNDEF_LSRBaseEQDestWb
;
2932 temp
= lhs
+ LSRegRHS
;
2933 if (LoadWord (state
, instr
, lhs
))
2937 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2942 && handle_v6_insn (state
, instr
))
2945 ARMul_UndefInstr (state
, instr
);
2948 UNDEF_LSRBaseEQOffWb
;
2949 UNDEF_LSRBaseEQDestWb
;
2953 state
->NtransSig
= LOW
;
2954 if (StoreWord (state
, instr
, lhs
))
2955 LSBase
= lhs
+ LSRegRHS
;
2956 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2959 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2964 && handle_v6_insn (state
, instr
))
2967 ARMul_UndefInstr (state
, instr
);
2970 UNDEF_LSRBaseEQOffWb
;
2971 UNDEF_LSRBaseEQDestWb
;
2975 temp
= lhs
+ LSRegRHS
;
2976 state
->NtransSig
= LOW
;
2977 if (LoadWord (state
, instr
, lhs
))
2979 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2982 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2987 && handle_v6_insn (state
, instr
))
2990 ARMul_UndefInstr (state
, instr
);
2993 UNDEF_LSRBaseEQOffWb
;
2994 UNDEF_LSRBaseEQDestWb
;
2998 if (StoreByte (state
, instr
, lhs
))
2999 LSBase
= lhs
+ LSRegRHS
;
3002 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
3005 ARMul_UndefInstr (state
, instr
);
3008 UNDEF_LSRBaseEQOffWb
;
3009 UNDEF_LSRBaseEQDestWb
;
3013 temp
= lhs
+ LSRegRHS
;
3014 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3018 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3023 && handle_v6_insn (state
, instr
))
3026 ARMul_UndefInstr (state
, instr
);
3029 UNDEF_LSRBaseEQOffWb
;
3030 UNDEF_LSRBaseEQDestWb
;
3034 state
->NtransSig
= LOW
;
3035 if (StoreByte (state
, instr
, lhs
))
3036 LSBase
= lhs
+ LSRegRHS
;
3037 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3040 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3045 && handle_v6_insn (state
, instr
))
3048 ARMul_UndefInstr (state
, instr
);
3051 UNDEF_LSRBaseEQOffWb
;
3052 UNDEF_LSRBaseEQDestWb
;
3056 temp
= lhs
+ LSRegRHS
;
3057 state
->NtransSig
= LOW
;
3058 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3060 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3064 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3069 && handle_v6_insn (state
, instr
))
3072 ARMul_UndefInstr (state
, instr
);
3075 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
3078 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3081 ARMul_UndefInstr (state
, instr
);
3084 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
3087 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3090 ARMul_UndefInstr (state
, instr
);
3093 UNDEF_LSRBaseEQOffWb
;
3094 UNDEF_LSRBaseEQDestWb
;
3097 temp
= LHS
- LSRegRHS
;
3098 if (StoreWord (state
, instr
, temp
))
3102 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3105 ARMul_UndefInstr (state
, instr
);
3108 UNDEF_LSRBaseEQOffWb
;
3109 UNDEF_LSRBaseEQDestWb
;
3112 temp
= LHS
- LSRegRHS
;
3113 if (LoadWord (state
, instr
, temp
))
3117 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3122 && handle_v6_insn (state
, instr
))
3125 ARMul_UndefInstr (state
, instr
);
3128 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
3131 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3136 && handle_v6_insn (state
, instr
))
3139 ARMul_UndefInstr (state
, instr
);
3142 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
3145 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3148 ARMul_UndefInstr (state
, instr
);
3151 UNDEF_LSRBaseEQOffWb
;
3152 UNDEF_LSRBaseEQDestWb
;
3155 temp
= LHS
- LSRegRHS
;
3156 if (StoreByte (state
, instr
, temp
))
3160 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3163 ARMul_UndefInstr (state
, instr
);
3166 UNDEF_LSRBaseEQOffWb
;
3167 UNDEF_LSRBaseEQDestWb
;
3170 temp
= LHS
- LSRegRHS
;
3171 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3175 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3180 && handle_v6_insn (state
, instr
))
3183 ARMul_UndefInstr (state
, instr
);
3186 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
3189 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
3192 ARMul_UndefInstr (state
, instr
);
3195 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
3198 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
3203 && handle_v6_insn (state
, instr
))
3206 ARMul_UndefInstr (state
, instr
);
3209 UNDEF_LSRBaseEQOffWb
;
3210 UNDEF_LSRBaseEQDestWb
;
3213 temp
= LHS
+ LSRegRHS
;
3214 if (StoreWord (state
, instr
, temp
))
3218 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
3221 ARMul_UndefInstr (state
, instr
);
3224 UNDEF_LSRBaseEQOffWb
;
3225 UNDEF_LSRBaseEQDestWb
;
3228 temp
= LHS
+ LSRegRHS
;
3229 if (LoadWord (state
, instr
, temp
))
3233 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
3238 && handle_v6_insn (state
, instr
))
3241 ARMul_UndefInstr (state
, instr
);
3244 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
3247 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
3250 ARMul_UndefInstr (state
, instr
);
3253 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
3256 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
3259 ARMul_UndefInstr (state
, instr
);
3262 UNDEF_LSRBaseEQOffWb
;
3263 UNDEF_LSRBaseEQDestWb
;
3266 temp
= LHS
+ LSRegRHS
;
3267 if (StoreByte (state
, instr
, temp
))
3271 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
3274 /* Check for the special breakpoint opcode.
3275 This value should correspond to the value defined
3276 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
3277 if (BITS (0, 19) == 0xfdefe)
3279 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
3280 ARMul_Abort (state
, ARMul_SWIV
);
3283 ARMul_UndefInstr (state
, instr
);
3286 UNDEF_LSRBaseEQOffWb
;
3287 UNDEF_LSRBaseEQDestWb
;
3290 temp
= LHS
+ LSRegRHS
;
3291 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3296 /* Multiple Data Transfer Instructions. */
3298 case 0x80: /* Store, No WriteBack, Post Dec. */
3299 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3302 case 0x81: /* Load, No WriteBack, Post Dec. */
3303 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3306 case 0x82: /* Store, WriteBack, Post Dec. */
3307 temp
= LSBase
- LSMNumRegs
;
3308 STOREMULT (instr
, temp
+ 4L, temp
);
3311 case 0x83: /* Load, WriteBack, Post Dec. */
3312 temp
= LSBase
- LSMNumRegs
;
3313 LOADMULT (instr
, temp
+ 4L, temp
);
3316 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
3317 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3320 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
3321 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3324 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
3325 temp
= LSBase
- LSMNumRegs
;
3326 STORESMULT (instr
, temp
+ 4L, temp
);
3329 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3330 temp
= LSBase
- LSMNumRegs
;
3331 LOADSMULT (instr
, temp
+ 4L, temp
);
3334 case 0x88: /* Store, No WriteBack, Post Inc. */
3335 STOREMULT (instr
, LSBase
, 0L);
3338 case 0x89: /* Load, No WriteBack, Post Inc. */
3339 LOADMULT (instr
, LSBase
, 0L);
3342 case 0x8a: /* Store, WriteBack, Post Inc. */
3344 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
3347 case 0x8b: /* Load, WriteBack, Post Inc. */
3349 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
3352 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3353 STORESMULT (instr
, LSBase
, 0L);
3356 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3357 LOADSMULT (instr
, LSBase
, 0L);
3360 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3362 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
3365 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3367 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
3370 case 0x90: /* Store, No WriteBack, Pre Dec. */
3371 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3374 case 0x91: /* Load, No WriteBack, Pre Dec. */
3375 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3378 case 0x92: /* Store, WriteBack, Pre Dec. */
3379 temp
= LSBase
- LSMNumRegs
;
3380 STOREMULT (instr
, temp
, temp
);
3383 case 0x93: /* Load, WriteBack, Pre Dec. */
3384 temp
= LSBase
- LSMNumRegs
;
3385 LOADMULT (instr
, temp
, temp
);
3388 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3389 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3392 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3393 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3396 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3397 temp
= LSBase
- LSMNumRegs
;
3398 STORESMULT (instr
, temp
, temp
);
3401 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3402 temp
= LSBase
- LSMNumRegs
;
3403 LOADSMULT (instr
, temp
, temp
);
3406 case 0x98: /* Store, No WriteBack, Pre Inc. */
3407 STOREMULT (instr
, LSBase
+ 4L, 0L);
3410 case 0x99: /* Load, No WriteBack, Pre Inc. */
3411 LOADMULT (instr
, LSBase
+ 4L, 0L);
3414 case 0x9a: /* Store, WriteBack, Pre Inc. */
3416 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3419 case 0x9b: /* Load, WriteBack, Pre Inc. */
3421 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3424 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3425 STORESMULT (instr
, LSBase
+ 4L, 0L);
3428 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3429 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3432 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3434 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3437 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3439 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3443 /* Branch forward. */
3452 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3457 /* Branch backward. */
3466 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3470 /* Branch and Link forward. */
3479 /* Put PC into Link. */
3481 state
->Reg
[14] = pc
+ 4;
3483 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3485 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3488 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
3491 /* Branch and Link backward. */
3500 /* Put PC into Link. */
3502 state
->Reg
[14] = pc
+ 4;
3504 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3506 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3509 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
3512 /* Co-Processor Data Transfers. */
3516 /* Reading from R15 is UNPREDICTABLE. */
3517 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3518 ARMul_UndefInstr (state
, instr
);
3519 /* Is access to coprocessor 0 allowed ? */
3520 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3521 ARMul_UndefInstr (state
, instr
);
3522 /* Special treatment for XScale coprocessors. */
3523 else if (state
->is_XScale
)
3525 /* Only opcode 0 is supported. */
3526 if (BITS (4, 7) != 0x00)
3527 ARMul_UndefInstr (state
, instr
);
3528 /* Only coporcessor 0 is supported. */
3529 else if (CPNum
!= 0x00)
3530 ARMul_UndefInstr (state
, instr
);
3531 /* Only accumulator 0 is supported. */
3532 else if (BITS (0, 3) != 0x00)
3533 ARMul_UndefInstr (state
, instr
);
3536 /* XScale MAR insn. Move two registers into accumulator. */
3537 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3538 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3542 /* FIXME: Not sure what to do for other v5 processors. */
3543 ARMul_UndefInstr (state
, instr
);
3548 case 0xc0: /* Store , No WriteBack , Post Dec. */
3549 ARMul_STC (state
, instr
, LHS
);
3555 /* Writes to R15 are UNPREDICATABLE. */
3556 if (DESTReg
== 15 || LHSReg
== 15)
3557 ARMul_UndefInstr (state
, instr
);
3558 /* Is access to the coprocessor allowed ? */
3559 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3560 ARMul_UndefInstr (state
, instr
);
3561 /* Special handling for XScale coprcoessors. */
3562 else if (state
->is_XScale
)
3564 /* Only opcode 0 is supported. */
3565 if (BITS (4, 7) != 0x00)
3566 ARMul_UndefInstr (state
, instr
);
3567 /* Only coprocessor 0 is supported. */
3568 else if (CPNum
!= 0x00)
3569 ARMul_UndefInstr (state
, instr
);
3570 /* Only accumulator 0 is supported. */
3571 else if (BITS (0, 3) != 0x00)
3572 ARMul_UndefInstr (state
, instr
);
3575 /* XScale MRA insn. Move accumulator into two registers. */
3576 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3581 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3582 state
->Reg
[BITS (16, 19)] = t1
;
3587 /* FIXME: Not sure what to do for other v5 processors. */
3588 ARMul_UndefInstr (state
, instr
);
3593 case 0xc1: /* Load , No WriteBack , Post Dec. */
3594 ARMul_LDC (state
, instr
, LHS
);
3598 case 0xc6: /* Store , WriteBack , Post Dec. */
3600 state
->Base
= lhs
- LSCOff
;
3601 ARMul_STC (state
, instr
, lhs
);
3605 case 0xc7: /* Load , WriteBack , Post Dec. */
3607 state
->Base
= lhs
- LSCOff
;
3608 ARMul_LDC (state
, instr
, lhs
);
3612 case 0xcc: /* Store , No WriteBack , Post Inc. */
3613 ARMul_STC (state
, instr
, LHS
);
3617 case 0xcd: /* Load , No WriteBack , Post Inc. */
3618 ARMul_LDC (state
, instr
, LHS
);
3622 case 0xce: /* Store , WriteBack , Post Inc. */
3624 state
->Base
= lhs
+ LSCOff
;
3625 ARMul_STC (state
, instr
, LHS
);
3629 case 0xcf: /* Load , WriteBack , Post Inc. */
3631 state
->Base
= lhs
+ LSCOff
;
3632 ARMul_LDC (state
, instr
, LHS
);
3636 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3637 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3641 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3642 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3646 case 0xd6: /* Store , WriteBack , Pre Dec. */
3649 ARMul_STC (state
, instr
, lhs
);
3653 case 0xd7: /* Load , WriteBack , Pre Dec. */
3656 ARMul_LDC (state
, instr
, lhs
);
3660 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3661 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3665 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3666 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3670 case 0xde: /* Store , WriteBack , Pre Inc. */
3673 ARMul_STC (state
, instr
, lhs
);
3677 case 0xdf: /* Load , WriteBack , Pre Inc. */
3680 ARMul_LDC (state
, instr
, lhs
);
3684 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3687 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3689 ARMul_UndefInstr (state
, instr
);
3692 if (state
->is_XScale
)
3693 switch (BITS (18, 19))
3696 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3698 /* XScale MIA instruction. Signed multiplication of
3699 two 32 bit values and addition to 40 bit accumulator. */
3700 ARMsdword Rm
= state
->Reg
[MULLHSReg
];
3701 ARMsdword Rs
= state
->Reg
[MULACCReg
];
3707 state
->Accumulator
+= Rm
* Rs
;
3713 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3715 /* XScale MIAPH instruction. */
3716 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3717 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3718 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3719 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3734 state
->Accumulator
+= t5
;
3739 state
->Accumulator
+= t5
;
3745 if (BITS (4, 11) == 1)
3747 /* XScale MIAxy instruction. */
3753 t1
= state
->Reg
[MULLHSReg
] >> 16;
3755 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3758 t2
= state
->Reg
[MULACCReg
] >> 16;
3760 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3770 state
->Accumulator
+= t5
;
3794 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3796 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3797 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3801 ARMul_MCR (state
, instr
, DEST
);
3805 ARMul_CDP (state
, instr
);
3809 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3821 temp
= ARMul_MRC (state
, instr
);
3824 ASSIGNN ((temp
& NBIT
) != 0);
3825 ASSIGNZ ((temp
& ZBIT
) != 0);
3826 ASSIGNC ((temp
& CBIT
) != 0);
3827 ASSIGNV ((temp
& VBIT
) != 0);
3834 ARMul_CDP (state
, instr
);
3838 /* SWI instruction. */
3855 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3857 /* A prefetch abort. */
3858 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
3859 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3863 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3864 ARMul_Abort (state
, ARMul_SWIV
);
3874 if (state
->Emulate
== ONCE
)
3875 state
->Emulate
= STOP
;
3876 /* If we have changed mode, allow the PC to advance before stopping. */
3877 else if (state
->Emulate
== CHANGEMODE
)
3879 else if (state
->Emulate
!= RUN
)
3882 while (!stop_simulator
);
3884 state
->decoded
= decoded
;
3885 state
->loaded
= loaded
;
3891 /* This routine evaluates most Data Processing register RHS's with the S
3892 bit clear. It is intended to be called from the macro DPRegRHS, which
3893 filters the common case of an unshifted register with in line code. */
3896 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3898 ARMword shamt
, base
;
3903 /* Shift amount in a register. */
3908 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3911 base
= state
->Reg
[base
];
3912 ARMul_Icycles (state
, 1, 0L);
3913 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3914 switch ((int) BITS (5, 6))
3919 else if (shamt
>= 32)
3922 return (base
<< shamt
);
3926 else if (shamt
>= 32)
3929 return (base
>> shamt
);
3933 else if (shamt
>= 32)
3934 return ((ARMword
) ((ARMsword
) base
>> 31L));
3936 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
3942 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3947 /* Shift amount is a constant. */
3950 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3953 base
= state
->Reg
[base
];
3954 shamt
= BITS (7, 11);
3955 switch ((int) BITS (5, 6))
3958 return (base
<< shamt
);
3963 return (base
>> shamt
);
3966 return ((ARMword
) ((ARMsword
) base
>> 31L));
3968 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
3972 return ((base
>> 1) | (CFLAG
<< 31));
3974 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3981 /* This routine evaluates most Logical Data Processing register RHS's
3982 with the S bit set. It is intended to be called from the macro
3983 DPSRegRHS, which filters the common case of an unshifted register
3984 with in line code. */
3987 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3989 ARMword shamt
, base
;
3994 /* Shift amount in a register. */
3999 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4002 base
= state
->Reg
[base
];
4003 ARMul_Icycles (state
, 1, 0L);
4004 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4005 switch ((int) BITS (5, 6))
4010 else if (shamt
== 32)
4015 else if (shamt
> 32)
4022 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4023 return (base
<< shamt
);
4028 else if (shamt
== 32)
4030 ASSIGNC (base
>> 31);
4033 else if (shamt
> 32)
4040 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4041 return (base
>> shamt
);
4046 else if (shamt
>= 32)
4048 ASSIGNC (base
>> 31L);
4049 return ((ARMword
) ((ARMsword
) base
>> 31L));
4053 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4054 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4062 ASSIGNC (base
>> 31);
4067 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4068 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4074 /* Shift amount is a constant. */
4077 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4080 base
= state
->Reg
[base
];
4081 shamt
= BITS (7, 11);
4083 switch ((int) BITS (5, 6))
4086 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4087 return (base
<< shamt
);
4091 ASSIGNC (base
>> 31);
4096 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4097 return (base
>> shamt
);
4102 ASSIGNC (base
>> 31L);
4103 return ((ARMword
) ((ARMsword
) base
>> 31L));
4107 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4108 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4116 return ((base
>> 1) | (shamt
<< 31));
4120 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4121 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4129 /* This routine handles writes to register 15 when the S bit is not set. */
4132 WriteR15 (ARMul_State
* state
, ARMword src
)
4134 /* The ARM documentation states that the two least significant bits
4135 are discarded when setting PC, except in the cases handled by
4136 WriteR15Branch() below. It's probably an oversight: in THUMB
4137 mode, the second least significant bit should probably not be
4147 state
->Reg
[15] = src
& PCBITS
;
4149 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
4150 ARMul_R15Altered (state
);
4155 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4158 /* This routine handles writes to register 15 when the S bit is set. */
4161 WriteSR15 (ARMul_State
* state
, ARMword src
)
4164 if (state
->Bank
> 0)
4166 state
->Cpsr
= state
->Spsr
[state
->Bank
];
4167 ARMul_CPSRAltered (state
);
4175 state
->Reg
[15] = src
& PCBITS
;
4179 /* ARMul_R15Altered would have to support it. */
4185 if (state
->Bank
== USERBANK
)
4186 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
4188 state
->Reg
[15] = src
;
4190 ARMul_R15Altered (state
);
4194 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4197 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
4198 will switch to Thumb mode if the least significant bit is set. */
4201 WriteR15Branch (ARMul_State
* state
, ARMword src
)
4208 state
->Reg
[15] = src
& 0xfffffffe;
4213 state
->Reg
[15] = src
& 0xfffffffc;
4217 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4219 WriteR15 (state
, src
);
4223 /* Before ARM_v5 LDR and LDM of pc did not change mode. */
4226 WriteR15Load (ARMul_State
* state
, ARMword src
)
4229 WriteR15Branch (state
, src
);
4231 WriteR15 (state
, src
);
4234 /* This routine evaluates most Load and Store register RHS's. It is
4235 intended to be called from the macro LSRegRHS, which filters the
4236 common case of an unshifted register with in line code. */
4239 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
4241 ARMword shamt
, base
;
4246 /* Now forbidden, but ... */
4247 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4250 base
= state
->Reg
[base
];
4252 shamt
= BITS (7, 11);
4253 switch ((int) BITS (5, 6))
4256 return (base
<< shamt
);
4261 return (base
>> shamt
);
4264 return ((ARMword
) ((ARMsword
) base
>> 31L));
4266 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4270 return ((base
>> 1) | (CFLAG
<< 31));
4272 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4279 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
4282 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
4289 /* Now forbidden, but ... */
4290 return ECC
| ER15INT
| R15PC
| EMODE
;
4292 return state
->Reg
[RHSReg
];
4296 return BITS (0, 3) | (BITS (8, 11) << 4);
4299 /* This function does the work of loading a word for a LDR instruction. */
4302 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4308 if (ADDREXCEPT (address
))
4309 INTERNALABORT (address
);
4312 dest
= ARMul_LoadWordN (state
, address
);
4317 return state
->lateabtSig
;
4320 dest
= ARMul_Align (state
, address
, dest
);
4322 ARMul_Icycles (state
, 1, 0L);
4324 return (DESTReg
!= LHSReg
);
4328 /* This function does the work of loading a halfword. */
4331 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
4338 if (ADDREXCEPT (address
))
4339 INTERNALABORT (address
);
4341 dest
= ARMul_LoadHalfWord (state
, address
);
4345 return state
->lateabtSig
;
4349 if (dest
& 1 << (16 - 1))
4350 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
4353 ARMul_Icycles (state
, 1, 0L);
4354 return (DESTReg
!= LHSReg
);
4359 /* This function does the work of loading a byte for a LDRB instruction. */
4362 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
4368 if (ADDREXCEPT (address
))
4369 INTERNALABORT (address
);
4371 dest
= ARMul_LoadByte (state
, address
);
4375 return state
->lateabtSig
;
4379 if (dest
& 1 << (8 - 1))
4380 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
4383 ARMul_Icycles (state
, 1, 0L);
4385 return (DESTReg
!= LHSReg
);
4388 /* This function does the work of loading two words for a LDRD instruction. */
4391 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
4395 ARMword write_back
= BIT (21);
4396 ARMword immediate
= BIT (22);
4397 ARMword add_to_base
= BIT (23);
4398 ARMword pre_indexed
= BIT (24);
4408 /* If the writeback bit is set, the pre-index bit must be clear. */
4409 if (write_back
&& ! pre_indexed
)
4411 ARMul_UndefInstr (state
, instr
);
4415 /* Extract the base address register. */
4418 /* Extract the destination register and check it. */
4421 /* Destination register must be even. */
4423 /* Destination register cannot be LR. */
4424 || (dest_reg
== 14))
4426 ARMul_UndefInstr (state
, instr
);
4430 /* Compute the base address. */
4431 base
= state
->Reg
[addr_reg
];
4433 /* Compute the offset. */
4434 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4436 /* Compute the sum of the two. */
4438 sum
= base
+ offset
;
4440 sum
= base
- offset
;
4442 /* If this is a pre-indexed mode use the sum. */
4448 /* The address must be aligned on a 8 byte boundary. */
4452 ARMul_DATAABORT (addr
);
4454 ARMul_UndefInstr (state
, instr
);
4459 /* For pre indexed or post indexed addressing modes,
4460 check that the destination registers do not overlap
4461 the address registers. */
4462 if ((! pre_indexed
|| write_back
)
4463 && ( addr_reg
== dest_reg
4464 || addr_reg
== dest_reg
+ 1))
4466 ARMul_UndefInstr (state
, instr
);
4470 /* Load the words. */
4471 value1
= ARMul_LoadWordN (state
, addr
);
4472 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4474 /* Check for data aborts. */
4481 ARMul_Icycles (state
, 2, 0L);
4483 /* Store the values. */
4484 state
->Reg
[dest_reg
] = value1
;
4485 state
->Reg
[dest_reg
+ 1] = value2
;
4487 /* Do the post addressing and writeback. */
4491 if (! pre_indexed
|| write_back
)
4492 state
->Reg
[addr_reg
] = addr
;
4495 /* This function does the work of storing two words for a STRD instruction. */
4498 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4502 ARMword write_back
= BIT (21);
4503 ARMword immediate
= BIT (22);
4504 ARMword add_to_base
= BIT (23);
4505 ARMword pre_indexed
= BIT (24);
4513 /* If the writeback bit is set, the pre-index bit must be clear. */
4514 if (write_back
&& ! pre_indexed
)
4516 ARMul_UndefInstr (state
, instr
);
4520 /* Extract the base address register. */
4523 /* Base register cannot be PC. */
4526 ARMul_UndefInstr (state
, instr
);
4530 /* Extract the source register. */
4533 /* Source register must be even. */
4536 ARMul_UndefInstr (state
, instr
);
4540 /* Compute the base address. */
4541 base
= state
->Reg
[addr_reg
];
4543 /* Compute the offset. */
4544 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4546 /* Compute the sum of the two. */
4548 sum
= base
+ offset
;
4550 sum
= base
- offset
;
4552 /* If this is a pre-indexed mode use the sum. */
4558 /* The address must be aligned on a 8 byte boundary. */
4562 ARMul_DATAABORT (addr
);
4564 ARMul_UndefInstr (state
, instr
);
4569 /* For pre indexed or post indexed addressing modes,
4570 check that the destination registers do not overlap
4571 the address registers. */
4572 if ((! pre_indexed
|| write_back
)
4573 && ( addr_reg
== src_reg
4574 || addr_reg
== src_reg
+ 1))
4576 ARMul_UndefInstr (state
, instr
);
4580 /* Load the words. */
4581 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4582 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4590 /* Do the post addressing and writeback. */
4594 if (! pre_indexed
|| write_back
)
4595 state
->Reg
[addr_reg
] = addr
;
4598 /* This function does the work of storing a word from a STR instruction. */
4601 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4606 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4609 ARMul_StoreWordN (state
, address
, DEST
);
4611 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4613 INTERNALABORT (address
);
4614 (void) ARMul_LoadWordN (state
, address
);
4617 ARMul_StoreWordN (state
, address
, DEST
);
4622 return state
->lateabtSig
;
4628 /* This function does the work of storing a byte for a STRH instruction. */
4631 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4637 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4641 ARMul_StoreHalfWord (state
, address
, DEST
);
4643 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4645 INTERNALABORT (address
);
4646 (void) ARMul_LoadHalfWord (state
, address
);
4649 ARMul_StoreHalfWord (state
, address
, DEST
);
4655 return state
->lateabtSig
;
4662 /* This function does the work of storing a byte for a STRB instruction. */
4665 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4670 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4673 ARMul_StoreByte (state
, address
, DEST
);
4675 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4677 INTERNALABORT (address
);
4678 (void) ARMul_LoadByte (state
, address
);
4681 ARMul_StoreByte (state
, address
, DEST
);
4686 return state
->lateabtSig
;
4692 /* This function does the work of loading the registers listed in an LDM
4693 instruction, when the S bit is clear. The code here is always increment
4694 after, it's up to the caller to get the input address correct and to
4695 handle base register modification. */
4698 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4704 UNDEF_LSMBaseInListWb
;
4707 if (ADDREXCEPT (address
))
4708 INTERNALABORT (address
);
4710 if (BIT (21) && LHSReg
!= 15)
4713 /* N cycle first. */
4714 for (temp
= 0; !BIT (temp
); temp
++)
4717 dest
= ARMul_LoadWordN (state
, address
);
4719 if (!state
->abortSig
&& !state
->Aborted
)
4720 state
->Reg
[temp
++] = dest
;
4721 else if (!state
->Aborted
)
4723 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4724 state
->Aborted
= ARMul_DataAbortV
;
4727 /* S cycles from here on. */
4728 for (; temp
< 16; temp
++)
4731 /* Load this register. */
4733 dest
= ARMul_LoadWordS (state
, address
);
4735 if (!state
->abortSig
&& !state
->Aborted
)
4736 state
->Reg
[temp
] = dest
;
4737 else if (!state
->Aborted
)
4739 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4740 state
->Aborted
= ARMul_DataAbortV
;
4744 if (BIT (15) && !state
->Aborted
)
4745 /* PC is in the reg list. */
4746 WriteR15Load (state
, PC
);
4748 /* To write back the final register. */
4749 ARMul_Icycles (state
, 1, 0L);
4753 if (BIT (21) && LHSReg
!= 15)
4759 /* This function does the work of loading the registers listed in an LDM
4760 instruction, when the S bit is set. The code here is always increment
4761 after, it's up to the caller to get the input address correct and to
4762 handle base register modification. */
4765 LoadSMult (ARMul_State
* state
,
4774 UNDEF_LSMBaseInListWb
;
4779 if (ADDREXCEPT (address
))
4780 INTERNALABORT (address
);
4783 if (BIT (21) && LHSReg
!= 15)
4786 if (!BIT (15) && state
->Bank
!= USERBANK
)
4788 /* Temporary reg bank switch. */
4789 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4790 UNDEF_LSMUserBankWb
;
4793 /* N cycle first. */
4794 for (temp
= 0; !BIT (temp
); temp
++)
4797 dest
= ARMul_LoadWordN (state
, address
);
4799 if (!state
->abortSig
)
4800 state
->Reg
[temp
++] = dest
;
4801 else if (!state
->Aborted
)
4803 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4804 state
->Aborted
= ARMul_DataAbortV
;
4807 /* S cycles from here on. */
4808 for (; temp
< 16; temp
++)
4811 /* Load this register. */
4813 dest
= ARMul_LoadWordS (state
, address
);
4815 if (!state
->abortSig
&& !state
->Aborted
)
4816 state
->Reg
[temp
] = dest
;
4817 else if (!state
->Aborted
)
4819 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4820 state
->Aborted
= ARMul_DataAbortV
;
4824 if (BIT (15) && !state
->Aborted
)
4826 /* PC is in the reg list. */
4828 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4830 state
->Cpsr
= GETSPSR (state
->Bank
);
4831 ARMul_CPSRAltered (state
);
4834 WriteR15 (state
, PC
);
4836 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4838 /* Protect bits in user mode. */
4839 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4840 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4841 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4842 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4845 ARMul_R15Altered (state
);
4851 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4852 /* Restore the correct bank. */
4853 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4855 /* To write back the final register. */
4856 ARMul_Icycles (state
, 1, 0L);
4860 if (BIT (21) && LHSReg
!= 15)
4867 /* This function does the work of storing the registers listed in an STM
4868 instruction, when the S bit is clear. The code here is always increment
4869 after, it's up to the caller to get the input address correct and to
4870 handle base register modification. */
4873 StoreMult (ARMul_State
* state
,
4882 UNDEF_LSMBaseInListWb
;
4885 /* N-cycle, increment the PC and update the NextInstr state. */
4889 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4890 INTERNALABORT (address
);
4896 /* N cycle first. */
4897 for (temp
= 0; !BIT (temp
); temp
++)
4901 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4905 (void) ARMul_LoadWordN (state
, address
);
4907 /* Fake the Stores as Loads. */
4908 for (; temp
< 16; temp
++)
4911 /* Save this register. */
4913 (void) ARMul_LoadWordS (state
, address
);
4916 if (BIT (21) && LHSReg
!= 15)
4922 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4925 if (state
->abortSig
&& !state
->Aborted
)
4927 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4928 state
->Aborted
= ARMul_DataAbortV
;
4931 if (BIT (21) && LHSReg
!= 15)
4934 /* S cycles from here on. */
4935 for (; temp
< 16; temp
++)
4938 /* Save this register. */
4941 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4943 if (state
->abortSig
&& !state
->Aborted
)
4945 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4946 state
->Aborted
= ARMul_DataAbortV
;
4954 /* This function does the work of storing the registers listed in an STM
4955 instruction when the S bit is set. The code here is always increment
4956 after, it's up to the caller to get the input address correct and to
4957 handle base register modification. */
4960 StoreSMult (ARMul_State
* state
,
4969 UNDEF_LSMBaseInListWb
;
4974 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4975 INTERNALABORT (address
);
4981 if (state
->Bank
!= USERBANK
)
4983 /* Force User Bank. */
4984 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4985 UNDEF_LSMUserBankWb
;
4988 for (temp
= 0; !BIT (temp
); temp
++)
4989 ; /* N cycle first. */
4992 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4996 (void) ARMul_LoadWordN (state
, address
);
4998 for (; temp
< 16; temp
++)
4999 /* Fake the Stores as Loads. */
5002 /* Save this register. */
5005 (void) ARMul_LoadWordS (state
, address
);
5008 if (BIT (21) && LHSReg
!= 15)
5015 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5018 if (state
->abortSig
&& !state
->Aborted
)
5020 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5021 state
->Aborted
= ARMul_DataAbortV
;
5024 /* S cycles from here on. */
5025 for (; temp
< 16; temp
++)
5028 /* Save this register. */
5031 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5033 if (state
->abortSig
&& !state
->Aborted
)
5035 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5036 state
->Aborted
= ARMul_DataAbortV
;
5040 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5041 /* Restore the correct bank. */
5042 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5044 if (BIT (21) && LHSReg
!= 15)
5051 /* This function does the work of adding two 32bit values
5052 together, and calculating if a carry has occurred. */
5055 Add32 (ARMword a1
, ARMword a2
, int *carry
)
5057 ARMword result
= (a1
+ a2
);
5058 unsigned int uresult
= (unsigned int) result
;
5059 unsigned int ua1
= (unsigned int) a1
;
5061 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5062 or (result > RdLo) then we have no carry. */
5063 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
5071 /* This function does the work of multiplying
5072 two 32bit values to give a 64bit result. */
5075 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5077 /* Operand register numbers. */
5078 int nRdHi
, nRdLo
, nRs
, nRm
;
5079 ARMword RdHi
= 0, RdLo
= 0, Rm
;
5083 nRdHi
= BITS (16, 19);
5084 nRdLo
= BITS (12, 15);
5088 /* Needed to calculate the cycle count. */
5089 Rm
= state
->Reg
[nRm
];
5091 /* Check for illegal operand combinations first. */
5100 /* Intermediate results. */
5101 ARMword lo
, mid1
, mid2
, hi
;
5103 ARMword Rs
= state
->Reg
[nRs
];
5108 /* Compute sign of result and adjust operands if necessary. */
5109 sign
= (Rm
^ Rs
) & 0x80000000;
5111 if (((ARMsword
) Rm
) < 0)
5114 if (((ARMsword
) Rs
) < 0)
5118 /* We can split the 32x32 into four 16x16 operations. This
5119 ensures that we do not lose precision on 32bit only hosts. */
5120 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
5121 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5122 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
5123 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5125 /* We now need to add all of these results together, taking
5126 care to propogate the carries from the additions. */
5127 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
5129 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
5131 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
5135 /* Negate result if necessary. */
5138 if (RdLo
== 0xFFFFFFFF)
5147 state
->Reg
[nRdLo
] = RdLo
;
5148 state
->Reg
[nRdHi
] = RdHi
;
5151 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
5154 /* Ensure that both RdHi and RdLo are used to compute Z,
5155 but don't let RdLo's sign bit make it to N. */
5156 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
5158 /* The cycle count depends on whether the instruction is a signed or
5159 unsigned multiply, and what bits are clear in the multiplier. */
5160 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
5161 /* Invert the bits to make the check against zero. */
5164 if ((Rm
& 0xFFFFFF00) == 0)
5166 else if ((Rm
& 0xFFFF0000) == 0)
5168 else if ((Rm
& 0xFF000000) == 0)
5176 /* This function does the work of multiplying two 32bit
5177 values and adding a 64bit value to give a 64bit result. */
5180 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5187 nRdHi
= BITS (16, 19);
5188 nRdLo
= BITS (12, 15);
5190 RdHi
= state
->Reg
[nRdHi
];
5191 RdLo
= state
->Reg
[nRdLo
];
5193 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
5195 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
5196 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
5198 state
->Reg
[nRdLo
] = RdLo
;
5199 state
->Reg
[nRdHi
] = RdHi
;
5202 /* Ensure that both RdHi and RdLo are used to compute Z,
5203 but don't let RdLo's sign bit make it to N. */
5204 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
5206 /* Extra cycle for addition. */