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. */
23 static ARMword
GetDPRegRHS (ARMul_State
*, ARMword
);
24 static ARMword
GetDPSRegRHS (ARMul_State
*, ARMword
);
25 static void WriteR15 (ARMul_State
*, ARMword
);
26 static void WriteSR15 (ARMul_State
*, ARMword
);
27 static void WriteR15Branch (ARMul_State
*, ARMword
);
28 static ARMword
GetLSRegRHS (ARMul_State
*, ARMword
);
29 static ARMword
GetLS7RHS (ARMul_State
*, ARMword
);
30 static unsigned LoadWord (ARMul_State
*, ARMword
, ARMword
);
31 static unsigned LoadHalfWord (ARMul_State
*, ARMword
, ARMword
, int);
32 static unsigned LoadByte (ARMul_State
*, ARMword
, ARMword
, int);
33 static unsigned StoreWord (ARMul_State
*, ARMword
, ARMword
);
34 static unsigned StoreHalfWord (ARMul_State
*, ARMword
, ARMword
);
35 static unsigned StoreByte (ARMul_State
*, ARMword
, ARMword
);
36 static void LoadMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
37 static void StoreMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
38 static void LoadSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
39 static void StoreSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
40 static unsigned Multiply64 (ARMul_State
*, ARMword
, int, int);
41 static unsigned MultiplyAdd64 (ARMul_State
*, ARMword
, int, int);
42 static void Handle_Load_Double (ARMul_State
*, ARMword
);
43 static void Handle_Store_Double (ARMul_State
*, ARMword
);
45 #define LUNSIGNED (0) /* unsigned operation */
46 #define LSIGNED (1) /* signed operation */
47 #define LDEFAULT (0) /* default : do nothing */
48 #define LSCC (1) /* set condition codes on result */
50 #ifdef NEED_UI_LOOP_HOOK
51 /* How often to run the ui_loop update, when in use. */
52 #define UI_LOOP_POLL_INTERVAL 0x32000
54 /* Counter for the ui_loop_hook update. */
55 static long ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
57 /* Actual hook to call to run through gdb's gui event loop. */
58 extern int (*ui_loop_hook
) (int);
59 #endif /* NEED_UI_LOOP_HOOK */
61 extern int stop_simulator
;
63 /* Short-hand macros for LDR/STR. */
65 /* Store post decrement writeback. */
68 if (StoreHalfWord (state, instr, lhs)) \
69 LSBase = lhs - GetLS7RHS (state, instr);
71 /* Store post increment writeback. */
74 if (StoreHalfWord (state, instr, lhs)) \
75 LSBase = lhs + GetLS7RHS (state, instr);
77 /* Store pre decrement. */
79 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
81 /* Store pre decrement writeback. */
82 #define SHPREDOWNWB() \
83 temp = LHS - GetLS7RHS (state, instr); \
84 if (StoreHalfWord (state, instr, temp)) \
87 /* Store pre increment. */
89 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
91 /* Store pre increment writeback. */
93 temp = LHS + GetLS7RHS (state, instr); \
94 if (StoreHalfWord (state, instr, temp)) \
97 /* Load post decrement writeback. */
98 #define LHPOSTDOWN() \
102 temp = lhs - GetLS7RHS (state, instr); \
104 switch (BITS (5, 6)) \
107 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
111 if (LoadByte (state, instr, lhs, LSIGNED)) \
115 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
118 case 0: /* SWP handled elsewhere. */ \
127 /* Load post increment writeback. */
132 temp = lhs + GetLS7RHS (state, instr); \
134 switch (BITS (5, 6)) \
137 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
141 if (LoadByte (state, instr, lhs, LSIGNED)) \
145 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
148 case 0: /* SWP handled elsewhere. */ \
157 /* Load pre decrement. */
158 #define LHPREDOWN() \
162 temp = LHS - GetLS7RHS (state, instr); \
163 switch (BITS (5, 6)) \
166 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
169 (void) LoadByte (state, instr, temp, LSIGNED); \
172 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
175 /* SWP handled elsewhere. */ \
184 /* Load pre decrement writeback. */
185 #define LHPREDOWNWB() \
189 temp = LHS - GetLS7RHS (state, instr); \
190 switch (BITS (5, 6)) \
193 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
197 if (LoadByte (state, instr, temp, LSIGNED)) \
201 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
205 /* SWP handled elsewhere. */ \
214 /* Load pre increment. */
219 temp = LHS + GetLS7RHS (state, instr); \
220 switch (BITS (5, 6)) \
223 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
226 (void) LoadByte (state, instr, temp, LSIGNED); \
229 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
232 /* SWP handled elsewhere. */ \
241 /* Load pre increment writeback. */
242 #define LHPREUPWB() \
246 temp = LHS + GetLS7RHS (state, instr); \
247 switch (BITS (5, 6)) \
250 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
254 if (LoadByte (state, instr, temp, LSIGNED)) \
258 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
262 /* SWP handled elsewhere. */ \
271 /* EMULATION of ARM6. */
273 /* The PC pipeline value depends on whether ARM
274 or Thumb instructions are being executed. */
279 ARMul_Emulate32 (ARMul_State
* state
)
281 ARMul_Emulate26 (ARMul_State
* state
)
284 ARMword instr
; /* The current instruction. */
285 ARMword dest
= 0; /* Almost the DestBus. */
286 ARMword temp
; /* Ubiquitous third hand. */
287 ARMword pc
= 0; /* The address of the current instruction. */
288 ARMword lhs
; /* Almost the ABus and BBus. */
290 ARMword decoded
= 0; /* Instruction pipeline. */
293 /* Execute the next instruction. */
295 if (state
->NextInstr
< PRIMEPIPE
)
297 decoded
= state
->decoded
;
298 loaded
= state
->loaded
;
304 /* Just keep going. */
307 switch (state
->NextInstr
)
310 /* Advance the pipeline, and an S cycle. */
311 state
->Reg
[15] += isize
;
315 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
319 /* Advance the pipeline, and an N cycle. */
320 state
->Reg
[15] += isize
;
324 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
329 /* Program counter advanced, and an S cycle. */
333 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
338 /* Program counter advanced, and an N cycle. */
342 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
347 /* The program counter has been changed. */
352 state
->Reg
[15] = pc
+ (isize
* 2);
354 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
355 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
356 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
361 /* The program counter has been changed. */
366 state
->Reg
[15] = pc
+ (isize
* 2);
368 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
369 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
370 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
376 ARMul_EnvokeEvent (state
);
378 /* Enable this for a helpful bit of debugging when tracing is needed. */
379 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
384 if (state
->Exception
)
386 /* Any exceptions ? */
387 if (state
->NresetSig
== LOW
)
389 ARMul_Abort (state
, ARMul_ResetV
);
392 else if (!state
->NfiqSig
&& !FFLAG
)
394 ARMul_Abort (state
, ARMul_FIQV
);
397 else if (!state
->NirqSig
&& !IFLAG
)
399 ARMul_Abort (state
, ARMul_IRQV
);
404 if (state
->CallDebug
> 0)
406 instr
= ARMul_Debug (state
, pc
, instr
);
407 if (state
->Emulate
< ONCE
)
409 state
->NextInstr
= RESUME
;
414 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
416 (void) fgetc (stdin
);
419 else if (state
->Emulate
< ONCE
)
421 state
->NextInstr
= RESUME
;
428 /* Provide Thumb instruction decoding. If the processor is in Thumb
429 mode, then we can simply decode the Thumb instruction, and map it
430 to the corresponding ARM instruction (by directly loading the
431 instr variable, and letting the normal ARM simulator
432 execute). There are some caveats to ensure that the correct
433 pipelined PC value is used when executing Thumb code, and also for
434 dealing with the BL instruction. */
439 /* Check if in Thumb mode. */
440 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
443 /* This is a Thumb instruction. */
444 ARMul_UndefInstr (state
, instr
);
448 /* Already processed. */
452 /* ARM instruction available. */
454 /* So continue instruction decoding. */
462 /* Check the condition codes. */
463 if ((temp
= TOPBITS (28)) == AL
)
464 /* Vile deed in the need for speed. */
467 /* Check the condition code. */
468 switch ((int) TOPBITS (28))
476 if (BITS (25, 27) == 5) /* BLX(1) */
480 state
->Reg
[14] = pc
+ 4;
482 dest
= pc
+ 8 + 1; /* Force entry into Thumb mode. */
484 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
486 dest
+= POSBRANCH
+ (BIT (24) << 1);
488 WriteR15Branch (state
, dest
);
491 else if ((instr
& 0xFC70F000) == 0xF450F000)
492 /* The PLD instruction. Ignored. */
495 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
496 ARMul_UndefInstr (state
, instr
);
525 temp
= (CFLAG
&& !ZFLAG
);
528 temp
= (!CFLAG
|| ZFLAG
);
531 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
534 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
537 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
540 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
544 /* Handle the Clock counter here. */
545 if (state
->is_XScale
)
547 ARMword cp14r0
= state
->CPRead
[14] (state
, 0, 0);
549 if (cp14r0
&& ARMul_CP14_R0_ENABLE
)
551 unsigned long newcycles
, nowtime
= ARMul_Time(state
);
553 newcycles
= nowtime
- state
->LastTime
;
554 state
->LastTime
= nowtime
;
555 if (cp14r0
&& ARMul_CP14_R0_CCD
)
557 if (state
->CP14R0_CCD
== -1)
558 state
->CP14R0_CCD
= newcycles
;
560 state
->CP14R0_CCD
+= newcycles
;
561 if (state
->CP14R0_CCD
>= 64)
564 while (state
->CP14R0_CCD
>= 64)
565 state
->CP14R0_CCD
-= 64, newcycles
++;
574 state
->CP14R0_CCD
= -1;
576 cp14r0
|= ARMul_CP14_R0_FLAG2
;
577 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
579 cp14r1
= state
->CPRead
[14] (state
, 1, 0);
581 /* Coded like this for portability. */
584 if (cp14r1
== 0xffffffff)
593 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
594 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
596 if (state
->CPRead
[13] (state
, 8, 0)
597 && ARMul_CP13_R8_PMUS
)
598 ARMul_Abort (state
, ARMul_FIQV
);
600 ARMul_Abort (state
, ARMul_IRQV
);
606 /* Handle hardware instructions breakpoints here. */
607 if (state
->is_XScale
)
609 if ((pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
610 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
612 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
613 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
617 /* Actual execution of instructions begins here. */
621 /* If the condition codes don't match, stop here. */
624 if (state
->is_XScale
)
626 if (BIT (20) == 0 && BITS (25, 27) == 0)
628 if (BITS (4, 7) == 0xD)
630 /* XScale Load Consecutive insn. */
631 ARMword temp
= GetLS7RHS (state
, instr
);
632 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
633 ARMword addr
= BIT (24) ? temp2
: LHS
;
636 ARMul_UndefInstr (state
, instr
);
638 /* Alignment violation. */
639 ARMul_Abort (state
, ARMul_DataAbortV
);
642 int wb
= BIT (21) || (! BIT (24));
644 state
->Reg
[BITS (12, 15)] =
645 ARMul_LoadWordN (state
, addr
);
646 state
->Reg
[BITS (12, 15) + 1] =
647 ARMul_LoadWordN (state
, addr
+ 4);
654 else if (BITS (4, 7) == 0xF)
656 /* XScale Store Consecutive insn. */
657 ARMword temp
= GetLS7RHS (state
, instr
);
658 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
659 ARMword addr
= BIT (24) ? temp2
: LHS
;
662 ARMul_UndefInstr (state
, instr
);
664 /* Alignment violation. */
665 ARMul_Abort (state
, ARMul_DataAbortV
);
668 ARMul_StoreWordN (state
, addr
,
669 state
->Reg
[BITS (12, 15)]);
670 ARMul_StoreWordN (state
, addr
+ 4,
671 state
->Reg
[BITS (12, 15) + 1]);
673 if (BIT (21)|| ! BIT (24))
682 switch ((int) BITS (20, 27))
684 /* Data Processing Register RHS Instructions. */
686 case 0x00: /* AND reg and MUL */
688 if (BITS (4, 11) == 0xB)
690 /* STRH register offset, no write-back, down, post indexed. */
694 if (BITS (4, 7) == 0xD)
696 Handle_Load_Double (state
, instr
);
699 if (BITS (4, 7) == 0xF)
701 Handle_Store_Double (state
, instr
);
705 if (BITS (4, 7) == 9)
707 rhs
= state
->Reg
[MULRHSReg
];
708 if (MULLHSReg
== MULDESTReg
)
711 state
->Reg
[MULDESTReg
] = 0;
713 else if (MULDESTReg
!= 15)
714 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
719 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
720 if (rhs
& (1L << dest
))
721 temp
= dest
; /* mult takes this many/2 I cycles */
722 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
732 case 0x01: /* ANDS reg and MULS */
734 if ((BITS (4, 11) & 0xF9) == 0x9)
736 /* LDR register offset, no write-back, down, post indexed */
738 /* fall through to rest of decoding */
741 if (BITS (4, 7) == 9)
743 rhs
= state
->Reg
[MULRHSReg
];
744 if (MULLHSReg
== MULDESTReg
)
747 state
->Reg
[MULDESTReg
] = 0;
751 else if (MULDESTReg
!= 15)
753 dest
= state
->Reg
[MULLHSReg
] * rhs
;
754 ARMul_NegZero (state
, dest
);
755 state
->Reg
[MULDESTReg
] = dest
;
761 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
762 if (rhs
& (1L << dest
))
763 temp
= dest
; /* mult takes this many/2 I cycles */
764 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
774 case 0x02: /* EOR reg and MLA */
776 if (BITS (4, 11) == 0xB)
778 /* STRH register offset, write-back, down, post indexed */
783 if (BITS (4, 7) == 9)
785 rhs
= state
->Reg
[MULRHSReg
];
786 if (MULLHSReg
== MULDESTReg
)
789 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
791 else if (MULDESTReg
!= 15)
792 state
->Reg
[MULDESTReg
] =
793 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
798 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
799 if (rhs
& (1L << dest
))
800 temp
= dest
; /* mult takes this many/2 I cycles */
801 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
811 case 0x03: /* EORS reg and MLAS */
813 if ((BITS (4, 11) & 0xF9) == 0x9)
815 /* LDR register offset, write-back, down, post-indexed */
817 /* fall through to rest of the decoding */
820 if (BITS (4, 7) == 9)
822 rhs
= state
->Reg
[MULRHSReg
];
823 if (MULLHSReg
== MULDESTReg
)
826 dest
= state
->Reg
[MULACCReg
];
827 ARMul_NegZero (state
, dest
);
828 state
->Reg
[MULDESTReg
] = dest
;
830 else if (MULDESTReg
!= 15)
833 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
834 ARMul_NegZero (state
, dest
);
835 state
->Reg
[MULDESTReg
] = dest
;
841 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
842 if (rhs
& (1L << dest
))
843 temp
= dest
; /* mult takes this many/2 I cycles */
844 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
854 case 0x04: /* SUB reg */
856 if (BITS (4, 7) == 0xB)
858 /* STRH immediate offset, no write-back, down, post indexed */
862 if (BITS (4, 7) == 0xD)
864 Handle_Load_Double (state
, instr
);
867 if (BITS (4, 7) == 0xF)
869 Handle_Store_Double (state
, instr
);
878 case 0x05: /* SUBS reg */
880 if ((BITS (4, 7) & 0x9) == 0x9)
882 /* LDR immediate offset, no write-back, down, post indexed */
884 /* fall through to the rest of the instruction decoding */
890 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
892 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
893 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
903 case 0x06: /* RSB reg */
905 if (BITS (4, 7) == 0xB)
907 /* STRH immediate offset, write-back, down, post indexed */
917 case 0x07: /* RSBS reg */
919 if ((BITS (4, 7) & 0x9) == 0x9)
921 /* LDR immediate offset, write-back, down, post indexed */
923 /* fall through to remainder of instruction decoding */
929 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
931 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
932 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
942 case 0x08: /* ADD reg */
944 if (BITS (4, 11) == 0xB)
946 /* STRH register offset, no write-back, up, post indexed */
950 if (BITS (4, 7) == 0xD)
952 Handle_Load_Double (state
, instr
);
955 if (BITS (4, 7) == 0xF)
957 Handle_Store_Double (state
, instr
);
962 if (BITS (4, 7) == 0x9)
965 ARMul_Icycles (state
,
966 Multiply64 (state
, instr
, LUNSIGNED
,
976 case 0x09: /* ADDS reg */
978 if ((BITS (4, 11) & 0xF9) == 0x9)
980 /* LDR register offset, no write-back, up, post indexed */
982 /* fall through to remaining instruction decoding */
986 if (BITS (4, 7) == 0x9)
989 ARMul_Icycles (state
,
990 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
999 if ((lhs
| rhs
) >> 30)
1000 { /* possible C,V,N to set */
1001 ASSIGNN (NEG (dest
));
1002 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1003 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1014 case 0x0a: /* ADC reg */
1016 if (BITS (4, 11) == 0xB)
1018 /* STRH register offset, write-back, up, post-indexed */
1024 if (BITS (4, 7) == 0x9)
1027 ARMul_Icycles (state
,
1028 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1034 dest
= LHS
+ rhs
+ CFLAG
;
1038 case 0x0b: /* ADCS reg */
1040 if ((BITS (4, 11) & 0xF9) == 0x9)
1042 /* LDR register offset, write-back, up, post indexed */
1044 /* fall through to remaining instruction decoding */
1048 if (BITS (4, 7) == 0x9)
1051 ARMul_Icycles (state
,
1052 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1059 dest
= lhs
+ rhs
+ CFLAG
;
1060 ASSIGNZ (dest
== 0);
1061 if ((lhs
| rhs
) >> 30)
1062 { /* possible C,V,N to set */
1063 ASSIGNN (NEG (dest
));
1064 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1065 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1076 case 0x0c: /* SBC reg */
1078 if (BITS (4, 7) == 0xB)
1080 /* STRH immediate offset, no write-back, up post indexed */
1084 if (BITS (4, 7) == 0xD)
1086 Handle_Load_Double (state
, instr
);
1089 if (BITS (4, 7) == 0xF)
1091 Handle_Store_Double (state
, instr
);
1096 if (BITS (4, 7) == 0x9)
1099 ARMul_Icycles (state
,
1100 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
1106 dest
= LHS
- rhs
- !CFLAG
;
1110 case 0x0d: /* SBCS reg */
1112 if ((BITS (4, 7) & 0x9) == 0x9)
1114 /* LDR immediate offset, no write-back, up, post indexed */
1119 if (BITS (4, 7) == 0x9)
1122 ARMul_Icycles (state
,
1123 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
1130 dest
= lhs
- rhs
- !CFLAG
;
1131 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1133 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1134 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1144 case 0x0e: /* RSC reg */
1146 if (BITS (4, 7) == 0xB)
1148 /* STRH immediate offset, write-back, up, post indexed */
1154 if (BITS (4, 7) == 0x9)
1157 ARMul_Icycles (state
,
1158 MultiplyAdd64 (state
, instr
, LSIGNED
,
1164 dest
= rhs
- LHS
- !CFLAG
;
1168 case 0x0f: /* RSCS reg */
1170 if ((BITS (4, 7) & 0x9) == 0x9)
1172 /* LDR immediate offset, write-back, up, post indexed */
1174 /* fall through to remaining instruction decoding */
1178 if (BITS (4, 7) == 0x9)
1181 ARMul_Icycles (state
,
1182 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
1189 dest
= rhs
- lhs
- !CFLAG
;
1190 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1192 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1193 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1203 case 0x10: /* TST reg and MRS CPSR and SWP word */
1206 if (BIT (4) == 0 && BIT (7) == 1)
1208 /* ElSegundo SMLAxy insn. */
1209 ARMword op1
= state
->Reg
[BITS (0, 3)];
1210 ARMword op2
= state
->Reg
[BITS (8, 11)];
1211 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1225 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
1227 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
1231 if (BITS (4, 11) == 5)
1233 /* ElSegundo QADD insn. */
1234 ARMword op1
= state
->Reg
[BITS (0, 3)];
1235 ARMword op2
= state
->Reg
[BITS (16, 19)];
1236 ARMword result
= op1
+ op2
;
1237 if (AddOverflow (op1
, op2
, result
))
1239 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1242 state
->Reg
[BITS (12, 15)] = result
;
1247 if (BITS (4, 11) == 0xB)
1249 /* STRH register offset, no write-back, down, pre indexed */
1253 if (BITS (4, 7) == 0xD)
1255 Handle_Load_Double (state
, instr
);
1258 if (BITS (4, 7) == 0xF)
1260 Handle_Store_Double (state
, instr
);
1264 if (BITS (4, 11) == 9)
1270 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1272 INTERNALABORT (temp
);
1273 (void) ARMul_LoadWordN (state
, temp
);
1274 (void) ARMul_LoadWordN (state
, temp
);
1278 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1280 DEST
= ARMul_Align (state
, temp
, dest
);
1283 if (state
->abortSig
|| state
->Aborted
)
1288 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1291 DEST
= ECC
| EINT
| EMODE
;
1299 case 0x11: /* TSTP reg */
1301 if ((BITS (4, 11) & 0xF9) == 0x9)
1303 /* LDR register offset, no write-back, down, pre indexed */
1305 /* continue with remaining instruction decode */
1311 state
->Cpsr
= GETSPSR (state
->Bank
);
1312 ARMul_CPSRAltered (state
);
1323 ARMul_NegZero (state
, dest
);
1327 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6) */
1330 if (BITS (4, 7) == 3)
1336 temp
= (pc
+ 2) | 1;
1340 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1341 state
->Reg
[14] = temp
;
1348 if (BIT (4) == 0 && BIT (7) == 1
1349 && (BIT (5) == 0 || BITS (12, 15) == 0))
1351 /* ElSegundo SMLAWy/SMULWy insn. */
1352 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1353 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1354 unsigned long long result
;
1358 if (op1
& 0x80000000)
1363 result
= (op1
* op2
) >> 16;
1367 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1369 if (AddOverflow (result
, Rn
, result
+ Rn
))
1373 state
->Reg
[BITS (16, 19)] = result
;
1377 if (BITS (4, 11) == 5)
1379 /* ElSegundo QSUB insn. */
1380 ARMword op1
= state
->Reg
[BITS (0, 3)];
1381 ARMword op2
= state
->Reg
[BITS (16, 19)];
1382 ARMword result
= op1
- op2
;
1384 if (SubOverflow (op1
, op2
, result
))
1386 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1390 state
->Reg
[BITS (12, 15)] = result
;
1395 if (BITS (4, 11) == 0xB)
1397 /* STRH register offset, write-back, down, pre indexed */
1401 if (BITS (4, 27) == 0x12FFF1)
1404 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1407 if (BITS (4, 7) == 0xD)
1409 Handle_Load_Double (state
, instr
);
1412 if (BITS (4, 7) == 0xF)
1414 Handle_Store_Double (state
, instr
);
1420 if (BITS (4, 7) == 0x7)
1423 extern int SWI_vector_installed
;
1425 /* Hardware is allowed to optionally override this
1426 instruction and treat it as a breakpoint. Since
1427 this is a simulator not hardware, we take the position
1428 that if a SWI vector was not installed, then an Abort
1429 vector was probably not installed either, and so
1430 normally this instruction would be ignored, even if an
1431 Abort is generated. This is a bad thing, since GDB
1432 uses this instruction for its breakpoints (at least in
1433 Thumb mode it does). So intercept the instruction here
1434 and generate a breakpoint SWI instead. */
1435 if (! SWI_vector_installed
)
1436 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1439 /* BKPT - normally this will cause an abort, but on the
1440 XScale we must check the DCSR. */
1441 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
1442 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
1446 /* Force the next instruction to be refetched. */
1447 state
->NextInstr
= RESUME
;
1453 /* MSR reg to CPSR */
1457 /* Don't allow TBIT to be set by MSR. */
1460 ARMul_FixCPSR (state
, instr
, temp
);
1468 case 0x13: /* TEQP reg */
1470 if ((BITS (4, 11) & 0xF9) == 0x9)
1472 /* LDR register offset, write-back, down, pre indexed. */
1474 /* Continue with remaining instruction decode. */
1480 state
->Cpsr
= GETSPSR (state
->Bank
);
1481 ARMul_CPSRAltered (state
);
1492 ARMul_NegZero (state
, dest
);
1496 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1499 if (BIT (4) == 0 && BIT (7) == 1)
1501 /* ElSegundo SMLALxy insn. */
1502 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1503 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1504 unsigned long long dest
;
1505 unsigned long long result
;
1518 dest
= (unsigned long long) state
->Reg
[BITS (16, 19)] << 32;
1519 dest
|= state
->Reg
[BITS (12, 15)];
1521 state
->Reg
[BITS (12, 15)] = dest
;
1522 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1526 if (BITS (4, 11) == 5)
1528 /* ElSegundo QDADD insn. */
1529 ARMword op1
= state
->Reg
[BITS (0, 3)];
1530 ARMword op2
= state
->Reg
[BITS (16, 19)];
1531 ARMword op2d
= op2
+ op2
;
1534 if (AddOverflow (op2
, op2
, op2d
))
1537 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1540 result
= op1
+ op2d
;
1541 if (AddOverflow (op1
, op2d
, result
))
1544 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1547 state
->Reg
[BITS (12, 15)] = result
;
1552 if (BITS (4, 7) == 0xB)
1554 /* STRH immediate offset, no write-back, down, pre indexed. */
1558 if (BITS (4, 7) == 0xD)
1560 Handle_Load_Double (state
, instr
);
1563 if (BITS (4, 7) == 0xF)
1565 Handle_Store_Double (state
, instr
);
1569 if (BITS (4, 11) == 9)
1575 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1577 INTERNALABORT (temp
);
1578 (void) ARMul_LoadByte (state
, temp
);
1579 (void) ARMul_LoadByte (state
, temp
);
1583 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1584 if (state
->abortSig
|| state
->Aborted
)
1589 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1592 DEST
= GETSPSR (state
->Bank
);
1600 case 0x15: /* CMPP reg */
1602 if ((BITS (4, 7) & 0x9) == 0x9)
1604 /* LDR immediate offset, no write-back, down, pre indexed */
1606 /* continue with remaining instruction decode */
1612 state
->Cpsr
= GETSPSR (state
->Bank
);
1613 ARMul_CPSRAltered (state
);
1625 ARMul_NegZero (state
, dest
);
1626 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1628 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1629 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1639 case 0x16: /* CMN reg and MSR reg to SPSR */
1642 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1644 /* ElSegundo SMULxy insn. */
1645 ARMword op1
= state
->Reg
[BITS (0, 3)];
1646 ARMword op2
= state
->Reg
[BITS (8, 11)];
1647 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1660 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1664 if (BITS (4, 11) == 5)
1666 /* ElSegundo QDSUB insn. */
1667 ARMword op1
= state
->Reg
[BITS (0, 3)];
1668 ARMword op2
= state
->Reg
[BITS (16, 19)];
1669 ARMword op2d
= op2
+ op2
;
1672 if (AddOverflow (op2
, op2
, op2d
))
1675 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1678 result
= op1
- op2d
;
1679 if (SubOverflow (op1
, op2d
, result
))
1682 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1685 state
->Reg
[BITS (12, 15)] = result
;
1692 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1694 /* ARM5 CLZ insn. */
1695 ARMword op1
= state
->Reg
[BITS (0, 3)];
1699 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1702 state
->Reg
[BITS (12, 15)] = result
;
1707 if (BITS (4, 7) == 0xB)
1709 /* STRH immediate offset, write-back, down, pre indexed */
1713 if (BITS (4, 7) == 0xD)
1715 Handle_Load_Double (state
, instr
);
1718 if (BITS (4, 7) == 0xF)
1720 Handle_Store_Double (state
, instr
);
1727 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1735 case 0x17: /* CMNP reg */
1737 if ((BITS (4, 7) & 0x9) == 0x9)
1739 /* LDR immediate offset, write-back, down, pre indexed */
1741 /* continue with remaining instruction decoding */
1747 state
->Cpsr
= GETSPSR (state
->Bank
);
1748 ARMul_CPSRAltered (state
);
1761 ASSIGNZ (dest
== 0);
1762 if ((lhs
| rhs
) >> 30)
1763 { /* possible C,V,N to set */
1764 ASSIGNN (NEG (dest
));
1765 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1766 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1777 case 0x18: /* ORR reg */
1779 if (BITS (4, 11) == 0xB)
1781 /* STRH register offset, no write-back, up, pre indexed */
1785 if (BITS (4, 7) == 0xD)
1787 Handle_Load_Double (state
, instr
);
1790 if (BITS (4, 7) == 0xF)
1792 Handle_Store_Double (state
, instr
);
1801 case 0x19: /* ORRS reg */
1803 if ((BITS (4, 11) & 0xF9) == 0x9)
1805 /* LDR register offset, no write-back, up, pre indexed */
1807 /* continue with remaining instruction decoding */
1815 case 0x1a: /* MOV reg */
1817 if (BITS (4, 11) == 0xB)
1819 /* STRH register offset, write-back, up, pre indexed */
1823 if (BITS (4, 7) == 0xD)
1825 Handle_Load_Double (state
, instr
);
1828 if (BITS (4, 7) == 0xF)
1830 Handle_Store_Double (state
, instr
);
1838 case 0x1b: /* MOVS reg */
1840 if ((BITS (4, 11) & 0xF9) == 0x9)
1842 /* LDR register offset, write-back, up, pre indexed */
1844 /* continue with remaining instruction decoding */
1851 case 0x1c: /* BIC reg */
1853 if (BITS (4, 7) == 0xB)
1855 /* STRH immediate offset, no write-back, up, pre indexed */
1859 if (BITS (4, 7) == 0xD)
1861 Handle_Load_Double (state
, instr
);
1864 else if (BITS (4, 7) == 0xF)
1866 Handle_Store_Double (state
, instr
);
1875 case 0x1d: /* BICS reg */
1877 if ((BITS (4, 7) & 0x9) == 0x9)
1879 /* LDR immediate offset, no write-back, up, pre indexed */
1881 /* continue with instruction decoding */
1889 case 0x1e: /* MVN reg */
1891 if (BITS (4, 7) == 0xB)
1893 /* STRH immediate offset, write-back, up, pre indexed */
1897 if (BITS (4, 7) == 0xD)
1899 Handle_Load_Double (state
, instr
);
1902 if (BITS (4, 7) == 0xF)
1904 Handle_Store_Double (state
, instr
);
1912 case 0x1f: /* MVNS reg */
1914 if ((BITS (4, 7) & 0x9) == 0x9)
1916 /* LDR immediate offset, write-back, up, pre indexed */
1918 /* continue instruction decoding */
1926 /* Data Processing Immediate RHS Instructions. */
1928 case 0x20: /* AND immed */
1929 dest
= LHS
& DPImmRHS
;
1933 case 0x21: /* ANDS immed */
1939 case 0x22: /* EOR immed */
1940 dest
= LHS
^ DPImmRHS
;
1944 case 0x23: /* EORS immed */
1950 case 0x24: /* SUB immed */
1951 dest
= LHS
- DPImmRHS
;
1955 case 0x25: /* SUBS immed */
1959 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1961 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1962 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1972 case 0x26: /* RSB immed */
1973 dest
= DPImmRHS
- LHS
;
1977 case 0x27: /* RSBS immed */
1981 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1983 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1984 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1994 case 0x28: /* ADD immed */
1995 dest
= LHS
+ DPImmRHS
;
1999 case 0x29: /* ADDS immed */
2003 ASSIGNZ (dest
== 0);
2004 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 0x2a: /* ADC immed */
2020 dest
= LHS
+ DPImmRHS
+ CFLAG
;
2024 case 0x2b: /* ADCS immed */
2027 dest
= lhs
+ rhs
+ CFLAG
;
2028 ASSIGNZ (dest
== 0);
2029 if ((lhs
| rhs
) >> 30)
2030 { /* possible C,V,N to set */
2031 ASSIGNN (NEG (dest
));
2032 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2033 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2044 case 0x2c: /* SBC immed */
2045 dest
= LHS
- DPImmRHS
- !CFLAG
;
2049 case 0x2d: /* SBCS immed */
2052 dest
= lhs
- rhs
- !CFLAG
;
2053 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2055 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2056 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2066 case 0x2e: /* RSC immed */
2067 dest
= DPImmRHS
- LHS
- !CFLAG
;
2071 case 0x2f: /* RSCS immed */
2074 dest
= rhs
- lhs
- !CFLAG
;
2075 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2077 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2078 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2088 case 0x30: /* TST immed */
2092 case 0x31: /* TSTP immed */
2096 state
->Cpsr
= GETSPSR (state
->Bank
);
2097 ARMul_CPSRAltered (state
);
2099 temp
= LHS
& DPImmRHS
;
2105 DPSImmRHS
; /* TST immed */
2107 ARMul_NegZero (state
, dest
);
2111 case 0x32: /* TEQ immed and MSR immed to CPSR */
2113 { /* MSR immed to CPSR */
2114 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2122 case 0x33: /* TEQP immed */
2126 state
->Cpsr
= GETSPSR (state
->Bank
);
2127 ARMul_CPSRAltered (state
);
2129 temp
= LHS
^ DPImmRHS
;
2135 DPSImmRHS
; /* TEQ immed */
2137 ARMul_NegZero (state
, dest
);
2141 case 0x34: /* CMP immed */
2145 case 0x35: /* CMPP immed */
2149 state
->Cpsr
= GETSPSR (state
->Bank
);
2150 ARMul_CPSRAltered (state
);
2152 temp
= LHS
- DPImmRHS
;
2159 lhs
= LHS
; /* CMP immed */
2162 ARMul_NegZero (state
, dest
);
2163 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2165 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2166 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2176 case 0x36: /* CMN immed and MSR immed to SPSR */
2177 if (DESTReg
== 15) /* MSR */
2178 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2185 case 0x37: /* CMNP immed */
2189 state
->Cpsr
= GETSPSR (state
->Bank
);
2190 ARMul_CPSRAltered (state
);
2192 temp
= LHS
+ DPImmRHS
;
2199 lhs
= LHS
; /* CMN immed */
2202 ASSIGNZ (dest
== 0);
2203 if ((lhs
| rhs
) >> 30)
2204 { /* possible C,V,N to set */
2205 ASSIGNN (NEG (dest
));
2206 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2207 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2218 case 0x38: /* ORR immed */
2219 dest
= LHS
| DPImmRHS
;
2223 case 0x39: /* ORRS immed */
2229 case 0x3a: /* MOV immed */
2234 case 0x3b: /* MOVS immed */
2239 case 0x3c: /* BIC immed */
2240 dest
= LHS
& ~DPImmRHS
;
2244 case 0x3d: /* BICS immed */
2250 case 0x3e: /* MVN immed */
2255 case 0x3f: /* MVNS immed */
2260 /* Single Data Transfer Immediate RHS Instructions. */
2262 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
2264 if (StoreWord (state
, instr
, lhs
))
2265 LSBase
= lhs
- LSImmRHS
;
2268 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
2270 if (LoadWord (state
, instr
, lhs
))
2271 LSBase
= lhs
- LSImmRHS
;
2274 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
2275 UNDEF_LSRBaseEQDestWb
;
2278 temp
= lhs
- LSImmRHS
;
2279 state
->NtransSig
= LOW
;
2280 if (StoreWord (state
, instr
, lhs
))
2282 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2285 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
2286 UNDEF_LSRBaseEQDestWb
;
2289 state
->NtransSig
= LOW
;
2290 if (LoadWord (state
, instr
, lhs
))
2291 LSBase
= lhs
- LSImmRHS
;
2292 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2295 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
2297 if (StoreByte (state
, instr
, lhs
))
2298 LSBase
= lhs
- LSImmRHS
;
2301 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
2303 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2304 LSBase
= lhs
- LSImmRHS
;
2307 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
2308 UNDEF_LSRBaseEQDestWb
;
2311 state
->NtransSig
= LOW
;
2312 if (StoreByte (state
, instr
, lhs
))
2313 LSBase
= lhs
- LSImmRHS
;
2314 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2317 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
2318 UNDEF_LSRBaseEQDestWb
;
2321 state
->NtransSig
= LOW
;
2322 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2323 LSBase
= lhs
- LSImmRHS
;
2324 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2327 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
2329 if (StoreWord (state
, instr
, lhs
))
2330 LSBase
= lhs
+ LSImmRHS
;
2333 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
2335 if (LoadWord (state
, instr
, lhs
))
2336 LSBase
= lhs
+ LSImmRHS
;
2339 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
2340 UNDEF_LSRBaseEQDestWb
;
2343 state
->NtransSig
= LOW
;
2344 if (StoreWord (state
, instr
, lhs
))
2345 LSBase
= lhs
+ LSImmRHS
;
2346 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2349 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
2350 UNDEF_LSRBaseEQDestWb
;
2353 state
->NtransSig
= LOW
;
2354 if (LoadWord (state
, instr
, lhs
))
2355 LSBase
= lhs
+ LSImmRHS
;
2356 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2359 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
2361 if (StoreByte (state
, instr
, lhs
))
2362 LSBase
= lhs
+ LSImmRHS
;
2365 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
2367 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2368 LSBase
= lhs
+ LSImmRHS
;
2371 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
2372 UNDEF_LSRBaseEQDestWb
;
2375 state
->NtransSig
= LOW
;
2376 if (StoreByte (state
, instr
, lhs
))
2377 LSBase
= lhs
+ LSImmRHS
;
2378 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2381 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
2382 UNDEF_LSRBaseEQDestWb
;
2385 state
->NtransSig
= LOW
;
2386 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2387 LSBase
= lhs
+ LSImmRHS
;
2388 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2392 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
2393 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2396 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
2397 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2400 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
2401 UNDEF_LSRBaseEQDestWb
;
2403 temp
= LHS
- LSImmRHS
;
2404 if (StoreWord (state
, instr
, temp
))
2408 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
2409 UNDEF_LSRBaseEQDestWb
;
2411 temp
= LHS
- LSImmRHS
;
2412 if (LoadWord (state
, instr
, temp
))
2416 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
2417 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2420 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
2421 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2424 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
2425 UNDEF_LSRBaseEQDestWb
;
2427 temp
= LHS
- LSImmRHS
;
2428 if (StoreByte (state
, instr
, temp
))
2432 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
2433 UNDEF_LSRBaseEQDestWb
;
2435 temp
= LHS
- LSImmRHS
;
2436 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2440 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
2441 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2444 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
2445 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2448 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
2449 UNDEF_LSRBaseEQDestWb
;
2451 temp
= LHS
+ LSImmRHS
;
2452 if (StoreWord (state
, instr
, temp
))
2456 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
2457 UNDEF_LSRBaseEQDestWb
;
2459 temp
= LHS
+ LSImmRHS
;
2460 if (LoadWord (state
, instr
, temp
))
2464 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
2465 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2468 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
2469 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2472 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
2473 UNDEF_LSRBaseEQDestWb
;
2475 temp
= LHS
+ LSImmRHS
;
2476 if (StoreByte (state
, instr
, temp
))
2480 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
2481 UNDEF_LSRBaseEQDestWb
;
2483 temp
= LHS
+ LSImmRHS
;
2484 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2489 /* Single Data Transfer Register RHS Instructions. */
2491 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
2494 ARMul_UndefInstr (state
, instr
);
2497 UNDEF_LSRBaseEQOffWb
;
2498 UNDEF_LSRBaseEQDestWb
;
2502 if (StoreWord (state
, instr
, lhs
))
2503 LSBase
= lhs
- LSRegRHS
;
2506 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
2509 ARMul_UndefInstr (state
, instr
);
2512 UNDEF_LSRBaseEQOffWb
;
2513 UNDEF_LSRBaseEQDestWb
;
2517 temp
= lhs
- LSRegRHS
;
2518 if (LoadWord (state
, instr
, lhs
))
2522 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2525 ARMul_UndefInstr (state
, instr
);
2528 UNDEF_LSRBaseEQOffWb
;
2529 UNDEF_LSRBaseEQDestWb
;
2533 state
->NtransSig
= LOW
;
2534 if (StoreWord (state
, instr
, lhs
))
2535 LSBase
= lhs
- LSRegRHS
;
2536 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2539 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2542 ARMul_UndefInstr (state
, instr
);
2545 UNDEF_LSRBaseEQOffWb
;
2546 UNDEF_LSRBaseEQDestWb
;
2550 temp
= lhs
- LSRegRHS
;
2551 state
->NtransSig
= LOW
;
2552 if (LoadWord (state
, instr
, lhs
))
2554 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2557 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2560 ARMul_UndefInstr (state
, instr
);
2563 UNDEF_LSRBaseEQOffWb
;
2564 UNDEF_LSRBaseEQDestWb
;
2568 if (StoreByte (state
, instr
, lhs
))
2569 LSBase
= lhs
- LSRegRHS
;
2572 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2575 ARMul_UndefInstr (state
, instr
);
2578 UNDEF_LSRBaseEQOffWb
;
2579 UNDEF_LSRBaseEQDestWb
;
2583 temp
= lhs
- LSRegRHS
;
2584 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2588 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2591 ARMul_UndefInstr (state
, instr
);
2594 UNDEF_LSRBaseEQOffWb
;
2595 UNDEF_LSRBaseEQDestWb
;
2599 state
->NtransSig
= LOW
;
2600 if (StoreByte (state
, instr
, lhs
))
2601 LSBase
= lhs
- LSRegRHS
;
2602 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2605 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2608 ARMul_UndefInstr (state
, instr
);
2611 UNDEF_LSRBaseEQOffWb
;
2612 UNDEF_LSRBaseEQDestWb
;
2616 temp
= lhs
- LSRegRHS
;
2617 state
->NtransSig
= LOW
;
2618 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2620 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2623 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2626 ARMul_UndefInstr (state
, instr
);
2629 UNDEF_LSRBaseEQOffWb
;
2630 UNDEF_LSRBaseEQDestWb
;
2634 if (StoreWord (state
, instr
, lhs
))
2635 LSBase
= lhs
+ LSRegRHS
;
2638 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2641 ARMul_UndefInstr (state
, instr
);
2644 UNDEF_LSRBaseEQOffWb
;
2645 UNDEF_LSRBaseEQDestWb
;
2649 temp
= lhs
+ LSRegRHS
;
2650 if (LoadWord (state
, instr
, lhs
))
2654 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2657 ARMul_UndefInstr (state
, instr
);
2660 UNDEF_LSRBaseEQOffWb
;
2661 UNDEF_LSRBaseEQDestWb
;
2665 state
->NtransSig
= LOW
;
2666 if (StoreWord (state
, instr
, lhs
))
2667 LSBase
= lhs
+ LSRegRHS
;
2668 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2671 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2674 ARMul_UndefInstr (state
, instr
);
2677 UNDEF_LSRBaseEQOffWb
;
2678 UNDEF_LSRBaseEQDestWb
;
2682 temp
= lhs
+ LSRegRHS
;
2683 state
->NtransSig
= LOW
;
2684 if (LoadWord (state
, instr
, lhs
))
2686 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2689 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2692 ARMul_UndefInstr (state
, instr
);
2695 UNDEF_LSRBaseEQOffWb
;
2696 UNDEF_LSRBaseEQDestWb
;
2700 if (StoreByte (state
, instr
, lhs
))
2701 LSBase
= lhs
+ LSRegRHS
;
2704 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2707 ARMul_UndefInstr (state
, instr
);
2710 UNDEF_LSRBaseEQOffWb
;
2711 UNDEF_LSRBaseEQDestWb
;
2715 temp
= lhs
+ LSRegRHS
;
2716 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2720 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2723 ARMul_UndefInstr (state
, instr
);
2726 UNDEF_LSRBaseEQOffWb
;
2727 UNDEF_LSRBaseEQDestWb
;
2731 state
->NtransSig
= LOW
;
2732 if (StoreByte (state
, instr
, lhs
))
2733 LSBase
= lhs
+ LSRegRHS
;
2734 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2737 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2740 ARMul_UndefInstr (state
, instr
);
2743 UNDEF_LSRBaseEQOffWb
;
2744 UNDEF_LSRBaseEQDestWb
;
2748 temp
= lhs
+ LSRegRHS
;
2749 state
->NtransSig
= LOW
;
2750 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2752 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2756 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2759 ARMul_UndefInstr (state
, instr
);
2762 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2765 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2768 ARMul_UndefInstr (state
, instr
);
2771 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2774 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2777 ARMul_UndefInstr (state
, instr
);
2780 UNDEF_LSRBaseEQOffWb
;
2781 UNDEF_LSRBaseEQDestWb
;
2784 temp
= LHS
- LSRegRHS
;
2785 if (StoreWord (state
, instr
, temp
))
2789 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2792 ARMul_UndefInstr (state
, instr
);
2795 UNDEF_LSRBaseEQOffWb
;
2796 UNDEF_LSRBaseEQDestWb
;
2799 temp
= LHS
- LSRegRHS
;
2800 if (LoadWord (state
, instr
, temp
))
2804 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2807 ARMul_UndefInstr (state
, instr
);
2810 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2813 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2816 ARMul_UndefInstr (state
, instr
);
2819 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2822 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2825 ARMul_UndefInstr (state
, instr
);
2828 UNDEF_LSRBaseEQOffWb
;
2829 UNDEF_LSRBaseEQDestWb
;
2832 temp
= LHS
- LSRegRHS
;
2833 if (StoreByte (state
, instr
, temp
))
2837 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2840 ARMul_UndefInstr (state
, instr
);
2843 UNDEF_LSRBaseEQOffWb
;
2844 UNDEF_LSRBaseEQDestWb
;
2847 temp
= LHS
- LSRegRHS
;
2848 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2852 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2855 ARMul_UndefInstr (state
, instr
);
2858 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2861 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2864 ARMul_UndefInstr (state
, instr
);
2867 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2870 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2873 ARMul_UndefInstr (state
, instr
);
2876 UNDEF_LSRBaseEQOffWb
;
2877 UNDEF_LSRBaseEQDestWb
;
2880 temp
= LHS
+ LSRegRHS
;
2881 if (StoreWord (state
, instr
, temp
))
2885 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2888 ARMul_UndefInstr (state
, instr
);
2891 UNDEF_LSRBaseEQOffWb
;
2892 UNDEF_LSRBaseEQDestWb
;
2895 temp
= LHS
+ LSRegRHS
;
2896 if (LoadWord (state
, instr
, temp
))
2900 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2903 ARMul_UndefInstr (state
, instr
);
2906 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2909 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2912 ARMul_UndefInstr (state
, instr
);
2915 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2918 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2921 ARMul_UndefInstr (state
, instr
);
2924 UNDEF_LSRBaseEQOffWb
;
2925 UNDEF_LSRBaseEQDestWb
;
2928 temp
= LHS
+ LSRegRHS
;
2929 if (StoreByte (state
, instr
, temp
))
2933 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2936 /* Check for the special breakpoint opcode.
2937 This value should correspond to the value defined
2938 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2939 if (BITS (0, 19) == 0xfdefe)
2941 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2942 ARMul_Abort (state
, ARMul_SWIV
);
2945 ARMul_UndefInstr (state
, instr
);
2948 UNDEF_LSRBaseEQOffWb
;
2949 UNDEF_LSRBaseEQDestWb
;
2952 temp
= LHS
+ LSRegRHS
;
2953 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2958 /* Multiple Data Transfer Instructions. */
2960 case 0x80: /* Store, No WriteBack, Post Dec */
2961 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2964 case 0x81: /* Load, No WriteBack, Post Dec */
2965 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2968 case 0x82: /* Store, WriteBack, Post Dec */
2969 temp
= LSBase
- LSMNumRegs
;
2970 STOREMULT (instr
, temp
+ 4L, temp
);
2973 case 0x83: /* Load, WriteBack, Post Dec */
2974 temp
= LSBase
- LSMNumRegs
;
2975 LOADMULT (instr
, temp
+ 4L, temp
);
2978 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2979 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2982 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2983 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2986 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2987 temp
= LSBase
- LSMNumRegs
;
2988 STORESMULT (instr
, temp
+ 4L, temp
);
2991 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2992 temp
= LSBase
- LSMNumRegs
;
2993 LOADSMULT (instr
, temp
+ 4L, temp
);
2996 case 0x88: /* Store, No WriteBack, Post Inc */
2997 STOREMULT (instr
, LSBase
, 0L);
3000 case 0x89: /* Load, No WriteBack, Post Inc */
3001 LOADMULT (instr
, LSBase
, 0L);
3004 case 0x8a: /* Store, WriteBack, Post Inc */
3006 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
3009 case 0x8b: /* Load, WriteBack, Post Inc */
3011 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
3014 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
3015 STORESMULT (instr
, LSBase
, 0L);
3018 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
3019 LOADSMULT (instr
, LSBase
, 0L);
3022 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
3024 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
3027 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
3029 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
3032 case 0x90: /* Store, No WriteBack, Pre Dec */
3033 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3036 case 0x91: /* Load, No WriteBack, Pre Dec */
3037 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3040 case 0x92: /* Store, WriteBack, Pre Dec */
3041 temp
= LSBase
- LSMNumRegs
;
3042 STOREMULT (instr
, temp
, temp
);
3045 case 0x93: /* Load, WriteBack, Pre Dec */
3046 temp
= LSBase
- LSMNumRegs
;
3047 LOADMULT (instr
, temp
, temp
);
3050 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
3051 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3054 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
3055 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3058 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
3059 temp
= LSBase
- LSMNumRegs
;
3060 STORESMULT (instr
, temp
, temp
);
3063 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
3064 temp
= LSBase
- LSMNumRegs
;
3065 LOADSMULT (instr
, temp
, temp
);
3068 case 0x98: /* Store, No WriteBack, Pre Inc */
3069 STOREMULT (instr
, LSBase
+ 4L, 0L);
3072 case 0x99: /* Load, No WriteBack, Pre Inc */
3073 LOADMULT (instr
, LSBase
+ 4L, 0L);
3076 case 0x9a: /* Store, WriteBack, Pre Inc */
3078 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3081 case 0x9b: /* Load, WriteBack, Pre Inc */
3083 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3086 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
3087 STORESMULT (instr
, LSBase
+ 4L, 0L);
3090 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
3091 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3094 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
3096 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3099 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
3101 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3105 /* Branch forward. */
3114 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3119 /* Branch backward. */
3128 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3133 /* Branch and Link forward. */
3142 /* Put PC into Link. */
3144 state
->Reg
[14] = pc
+ 4;
3146 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3148 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3153 /* Branch and Link backward. */
3162 /* Put PC into Link. */
3164 state
->Reg
[14] = pc
+ 4;
3166 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3168 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3172 /* Co-Processor Data Transfers. */
3176 /* Reading from R15 is UNPREDICTABLE. */
3177 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3178 ARMul_UndefInstr (state
, instr
);
3179 /* Is access to coprocessor 0 allowed ? */
3180 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3181 ARMul_UndefInstr (state
, instr
);
3182 /* Special treatment for XScale coprocessors. */
3183 else if (state
->is_XScale
)
3185 /* Only opcode 0 is supported. */
3186 if (BITS (4, 7) != 0x00)
3187 ARMul_UndefInstr (state
, instr
);
3188 /* Only coporcessor 0 is supported. */
3189 else if (CPNum
!= 0x00)
3190 ARMul_UndefInstr (state
, instr
);
3191 /* Only accumulator 0 is supported. */
3192 else if (BITS (0, 3) != 0x00)
3193 ARMul_UndefInstr (state
, instr
);
3196 /* XScale MAR insn. Move two registers into accumulator. */
3197 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3198 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3202 /* FIXME: Not sure what to do for other v5 processors. */
3203 ARMul_UndefInstr (state
, instr
);
3208 case 0xc0: /* Store , No WriteBack , Post Dec */
3209 ARMul_STC (state
, instr
, LHS
);
3215 /* Writes to R15 are UNPREDICATABLE. */
3216 if (DESTReg
== 15 || LHSReg
== 15)
3217 ARMul_UndefInstr (state
, instr
);
3218 /* Is access to the coprocessor allowed ? */
3219 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3220 ARMul_UndefInstr (state
, instr
);
3221 /* Special handling for XScale coprcoessors. */
3222 else if (state
->is_XScale
)
3224 /* Only opcode 0 is supported. */
3225 if (BITS (4, 7) != 0x00)
3226 ARMul_UndefInstr (state
, instr
);
3227 /* Only coprocessor 0 is supported. */
3228 else if (CPNum
!= 0x00)
3229 ARMul_UndefInstr (state
, instr
);
3230 /* Only accumulator 0 is supported. */
3231 else if (BITS (0, 3) != 0x00)
3232 ARMul_UndefInstr (state
, instr
);
3235 /* XScale MRA insn. Move accumulator into two registers. */
3236 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3241 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3242 state
->Reg
[BITS (16, 19)] = t1
;
3247 /* FIXME: Not sure what to do for other v5 processors. */
3248 ARMul_UndefInstr (state
, instr
);
3253 case 0xc1: /* Load , No WriteBack , Post Dec */
3254 ARMul_LDC (state
, instr
, LHS
);
3258 case 0xc6: /* Store , WriteBack , Post Dec */
3260 state
->Base
= lhs
- LSCOff
;
3261 ARMul_STC (state
, instr
, lhs
);
3265 case 0xc7: /* Load , WriteBack , Post Dec */
3267 state
->Base
= lhs
- LSCOff
;
3268 ARMul_LDC (state
, instr
, lhs
);
3272 case 0xcc: /* Store , No WriteBack , Post Inc */
3273 ARMul_STC (state
, instr
, LHS
);
3277 case 0xcd: /* Load , No WriteBack , Post Inc */
3278 ARMul_LDC (state
, instr
, LHS
);
3282 case 0xce: /* Store , WriteBack , Post Inc */
3284 state
->Base
= lhs
+ LSCOff
;
3285 ARMul_STC (state
, instr
, LHS
);
3289 case 0xcf: /* Load , WriteBack , Post Inc */
3291 state
->Base
= lhs
+ LSCOff
;
3292 ARMul_LDC (state
, instr
, LHS
);
3296 case 0xd4: /* Store , No WriteBack , Pre Dec */
3297 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3301 case 0xd5: /* Load , No WriteBack , Pre Dec */
3302 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3306 case 0xd6: /* Store , WriteBack , Pre Dec */
3309 ARMul_STC (state
, instr
, lhs
);
3313 case 0xd7: /* Load , WriteBack , Pre Dec */
3316 ARMul_LDC (state
, instr
, lhs
);
3320 case 0xdc: /* Store , No WriteBack , Pre Inc */
3321 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3325 case 0xdd: /* Load , No WriteBack , Pre Inc */
3326 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3330 case 0xde: /* Store , WriteBack , Pre Inc */
3333 ARMul_STC (state
, instr
, lhs
);
3337 case 0xdf: /* Load , WriteBack , Pre Inc */
3340 ARMul_LDC (state
, instr
, lhs
);
3344 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3346 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3348 ARMul_UndefInstr (state
, instr
);
3351 if (state
->is_XScale
)
3352 switch (BITS (18, 19))
3356 /* XScale MIA instruction. Signed multiplication of two 32 bit
3357 values and addition to 40 bit accumulator. */
3358 long long Rm
= state
->Reg
[MULLHSReg
];
3359 long long Rs
= state
->Reg
[MULACCReg
];
3365 state
->Accumulator
+= Rm
* Rs
;
3371 /* XScale MIAPH instruction. */
3372 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3373 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3374 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3375 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3390 state
->Accumulator
+= t5
;
3395 state
->Accumulator
+= t5
;
3401 /* XScale MIAxy instruction. */
3407 t1
= state
->Reg
[MULLHSReg
] >> 16;
3409 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3412 t2
= state
->Reg
[MULACCReg
] >> 16;
3414 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3424 state
->Accumulator
+= t5
;
3446 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3448 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3449 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3453 ARMul_MCR (state
, instr
, DEST
);
3455 else /* CDP Part 1 */
3456 ARMul_CDP (state
, instr
);
3460 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3471 temp
= ARMul_MRC (state
, instr
);
3474 ASSIGNN ((temp
& NBIT
) != 0);
3475 ASSIGNZ ((temp
& ZBIT
) != 0);
3476 ASSIGNC ((temp
& CBIT
) != 0);
3477 ASSIGNV ((temp
& VBIT
) != 0);
3482 else /* CDP Part 2 */
3483 ARMul_CDP (state
, instr
);
3487 /* SWI instruction. */
3504 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3506 /* A prefetch abort. */
3507 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
3508 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3512 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3513 ARMul_Abort (state
, ARMul_SWIV
);
3523 #ifdef NEED_UI_LOOP_HOOK
3524 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3526 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3529 #endif /* NEED_UI_LOOP_HOOK */
3531 if (state
->Emulate
== ONCE
)
3532 state
->Emulate
= STOP
;
3533 /* If we have changed mode, allow the PC to advance before stopping. */
3534 else if (state
->Emulate
== CHANGEMODE
)
3536 else if (state
->Emulate
!= RUN
)
3539 while (!stop_simulator
);
3541 state
->decoded
= decoded
;
3542 state
->loaded
= loaded
;
3548 /* This routine evaluates most Data Processing register RHS's with the S
3549 bit clear. It is intended to be called from the macro DPRegRHS, which
3550 filters the common case of an unshifted register with in line code. */
3553 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3555 ARMword shamt
, base
;
3560 /* Shift amount in a register. */
3565 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3568 base
= state
->Reg
[base
];
3569 ARMul_Icycles (state
, 1, 0L);
3570 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3571 switch ((int) BITS (5, 6))
3576 else if (shamt
>= 32)
3579 return (base
<< shamt
);
3583 else if (shamt
>= 32)
3586 return (base
>> shamt
);
3590 else if (shamt
>= 32)
3591 return ((ARMword
) ((long int) base
>> 31L));
3593 return ((ARMword
) ((long int) base
>> (int) shamt
));
3599 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3604 /* Shift amount is a constant. */
3607 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3610 base
= state
->Reg
[base
];
3611 shamt
= BITS (7, 11);
3612 switch ((int) BITS (5, 6))
3615 return (base
<< shamt
);
3620 return (base
>> shamt
);
3623 return ((ARMword
) ((long int) base
>> 31L));
3625 return ((ARMword
) ((long int) base
>> (int) shamt
));
3627 if (shamt
== 0) /* its an RRX */
3628 return ((base
>> 1) | (CFLAG
<< 31));
3630 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3637 /* This routine evaluates most Logical Data Processing register RHS's
3638 with the S bit set. It is intended to be called from the macro
3639 DPSRegRHS, which filters the common case of an unshifted register
3640 with in line code. */
3643 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3645 ARMword shamt
, base
;
3650 /* Shift amount in a register. */
3655 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3658 base
= state
->Reg
[base
];
3659 ARMul_Icycles (state
, 1, 0L);
3660 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3661 switch ((int) BITS (5, 6))
3666 else if (shamt
== 32)
3671 else if (shamt
> 32)
3678 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3679 return (base
<< shamt
);
3684 else if (shamt
== 32)
3686 ASSIGNC (base
>> 31);
3689 else if (shamt
> 32)
3696 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3697 return (base
>> shamt
);
3702 else if (shamt
>= 32)
3704 ASSIGNC (base
>> 31L);
3705 return ((ARMword
) ((long int) base
>> 31L));
3709 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3710 return ((ARMword
) ((long int) base
>> (int) shamt
));
3718 ASSIGNC (base
>> 31);
3723 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3724 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3730 /* Shift amount is a constant. */
3733 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3736 base
= state
->Reg
[base
];
3737 shamt
= BITS (7, 11);
3738 switch ((int) BITS (5, 6))
3741 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3742 return (base
<< shamt
);
3746 ASSIGNC (base
>> 31);
3751 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3752 return (base
>> shamt
);
3757 ASSIGNC (base
>> 31L);
3758 return ((ARMword
) ((long int) base
>> 31L));
3762 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3763 return ((ARMword
) ((long int) base
>> (int) shamt
));
3770 return ((base
>> 1) | (shamt
<< 31));
3774 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3775 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3783 /* This routine handles writes to register 15 when the S bit is not set. */
3786 WriteR15 (ARMul_State
* state
, ARMword src
)
3788 /* The ARM documentation states that the two least significant bits
3789 are discarded when setting PC, except in the cases handled by
3790 WriteR15Branch() below. It's probably an oversight: in THUMB
3791 mode, the second least significant bit should probably not be
3800 state
->Reg
[15] = src
& PCBITS
;
3802 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
3803 ARMul_R15Altered (state
);
3808 /* This routine handles writes to register 15 when the S bit is set. */
3811 WriteSR15 (ARMul_State
* state
, ARMword src
)
3814 if (state
->Bank
> 0)
3816 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3817 ARMul_CPSRAltered (state
);
3825 state
->Reg
[15] = src
& PCBITS
;
3829 abort (); /* ARMul_R15Altered would have to support it. */
3833 if (state
->Bank
== USERBANK
)
3834 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3836 state
->Reg
[15] = src
;
3837 ARMul_R15Altered (state
);
3842 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3843 will switch to Thumb mode if the least significant bit is set. */
3846 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3853 state
->Reg
[15] = src
& 0xfffffffe;
3858 state
->Reg
[15] = src
& 0xfffffffc;
3862 WriteR15 (state
, src
);
3866 /* This routine evaluates most Load and Store register RHS's. It is
3867 intended to be called from the macro LSRegRHS, which filters the
3868 common case of an unshifted register with in line code. */
3871 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3873 ARMword shamt
, base
;
3878 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3881 base
= state
->Reg
[base
];
3883 shamt
= BITS (7, 11);
3884 switch ((int) BITS (5, 6))
3887 return (base
<< shamt
);
3892 return (base
>> shamt
);
3895 return ((ARMword
) ((long int) base
>> 31L));
3897 return ((ARMword
) ((long int) base
>> (int) shamt
));
3899 if (shamt
== 0) /* its an RRX */
3900 return ((base
>> 1) | (CFLAG
<< 31));
3902 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3909 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
3912 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3919 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3921 return state
->Reg
[RHSReg
];
3924 /* Otherwise an immediate. */
3925 return BITS (0, 3) | (BITS (8, 11) << 4);
3928 /* This function does the work of loading a word for a LDR instruction. */
3931 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3937 if (ADDREXCEPT (address
))
3938 INTERNALABORT (address
);
3941 dest
= ARMul_LoadWordN (state
, address
);
3946 return (state
->lateabtSig
);
3949 dest
= ARMul_Align (state
, address
, dest
);
3951 ARMul_Icycles (state
, 1, 0L);
3953 return (DESTReg
!= LHSReg
);
3957 /* This function does the work of loading a halfword. */
3960 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3967 if (ADDREXCEPT (address
))
3969 INTERNALABORT (address
);
3972 dest
= ARMul_LoadHalfWord (state
, address
);
3976 return (state
->lateabtSig
);
3981 if (dest
& 1 << (16 - 1))
3982 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3985 ARMul_Icycles (state
, 1, 0L);
3986 return (DESTReg
!= LHSReg
);
3991 /* This function does the work of loading a byte for a LDRB instruction. */
3994 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
4000 if (ADDREXCEPT (address
))
4002 INTERNALABORT (address
);
4005 dest
= ARMul_LoadByte (state
, address
);
4009 return (state
->lateabtSig
);
4014 if (dest
& 1 << (8 - 1))
4015 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
4018 ARMul_Icycles (state
, 1, 0L);
4019 return (DESTReg
!= LHSReg
);
4022 /* This function does the work of loading two words for a LDRD instruction. */
4025 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
4029 ARMword write_back
= BIT (21);
4030 ARMword immediate
= BIT (22);
4031 ARMword add_to_base
= BIT (23);
4032 ARMword pre_indexed
= BIT (24);
4042 /* If the writeback bit is set, the pre-index bit must be clear. */
4043 if (write_back
&& ! pre_indexed
)
4045 ARMul_UndefInstr (state
, instr
);
4049 /* Extract the base address register. */
4052 /* Extract the destination register and check it. */
4055 /* Destination register must be even. */
4057 /* Destination register cannot be LR. */
4058 || (dest_reg
== 14))
4060 ARMul_UndefInstr (state
, instr
);
4064 /* Compute the base address. */
4065 base
= state
->Reg
[addr_reg
];
4067 /* Compute the offset. */
4068 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4070 /* Compute the sum of the two. */
4072 sum
= base
+ offset
;
4074 sum
= base
- offset
;
4076 /* If this is a pre-indexed mode use the sum. */
4082 /* The address must be aligned on a 8 byte boundary. */
4086 ARMul_DATAABORT (addr
);
4088 ARMul_UndefInstr (state
, instr
);
4093 /* For pre indexed or post indexed addressing modes,
4094 check that the destination registers do not overlap
4095 the address registers. */
4096 if ((! pre_indexed
|| write_back
)
4097 && ( addr_reg
== dest_reg
4098 || addr_reg
== dest_reg
+ 1))
4100 ARMul_UndefInstr (state
, instr
);
4104 /* Load the words. */
4105 value1
= ARMul_LoadWordN (state
, addr
);
4106 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4108 /* Check for data aborts. */
4115 ARMul_Icycles (state
, 2, 0L);
4117 /* Store the values. */
4118 state
->Reg
[dest_reg
] = value1
;
4119 state
->Reg
[dest_reg
+ 1] = value2
;
4121 /* Do the post addressing and writeback. */
4125 if (! pre_indexed
|| write_back
)
4126 state
->Reg
[addr_reg
] = addr
;
4129 /* This function does the work of storing two words for a STRD instruction. */
4132 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4136 ARMword write_back
= BIT (21);
4137 ARMword immediate
= BIT (22);
4138 ARMword add_to_base
= BIT (23);
4139 ARMword pre_indexed
= BIT (24);
4147 /* If the writeback bit is set, the pre-index bit must be clear. */
4148 if (write_back
&& ! pre_indexed
)
4150 ARMul_UndefInstr (state
, instr
);
4154 /* Extract the base address register. */
4157 /* Base register cannot be PC. */
4160 ARMul_UndefInstr (state
, instr
);
4164 /* Extract the source register. */
4167 /* Source register must be even. */
4170 ARMul_UndefInstr (state
, instr
);
4174 /* Compute the base address. */
4175 base
= state
->Reg
[addr_reg
];
4177 /* Compute the offset. */
4178 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4180 /* Compute the sum of the two. */
4182 sum
= base
+ offset
;
4184 sum
= base
- offset
;
4186 /* If this is a pre-indexed mode use the sum. */
4192 /* The address must be aligned on a 8 byte boundary. */
4196 ARMul_DATAABORT (addr
);
4198 ARMul_UndefInstr (state
, instr
);
4203 /* For pre indexed or post indexed addressing modes,
4204 check that the destination registers do not overlap
4205 the address registers. */
4206 if ((! pre_indexed
|| write_back
)
4207 && ( addr_reg
== src_reg
4208 || addr_reg
== src_reg
+ 1))
4210 ARMul_UndefInstr (state
, instr
);
4214 /* Load the words. */
4215 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4216 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4224 /* Do the post addressing and writeback. */
4228 if (! pre_indexed
|| write_back
)
4229 state
->Reg
[addr_reg
] = addr
;
4232 /* This function does the work of storing a word from a STR instruction. */
4235 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4240 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4243 ARMul_StoreWordN (state
, address
, DEST
);
4245 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4247 INTERNALABORT (address
);
4248 (void) ARMul_LoadWordN (state
, address
);
4251 ARMul_StoreWordN (state
, address
, DEST
);
4256 return state
->lateabtSig
;
4262 /* This function does the work of storing a byte for a STRH instruction. */
4265 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4271 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4275 ARMul_StoreHalfWord (state
, address
, DEST
);
4277 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4279 INTERNALABORT (address
);
4280 (void) ARMul_LoadHalfWord (state
, address
);
4283 ARMul_StoreHalfWord (state
, address
, DEST
);
4289 return state
->lateabtSig
;
4297 /* This function does the work of storing a byte for a STRB instruction. */
4300 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4305 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4308 ARMul_StoreByte (state
, address
, DEST
);
4310 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4312 INTERNALABORT (address
);
4313 (void) ARMul_LoadByte (state
, address
);
4316 ARMul_StoreByte (state
, address
, DEST
);
4321 return (state
->lateabtSig
);
4327 /* This function does the work of loading the registers listed in an LDM
4328 instruction, when the S bit is clear. The code here is always increment
4329 after, it's up to the caller to get the input address correct and to
4330 handle base register modification.a */
4333 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4339 UNDEF_LSMBaseInListWb
;
4342 if (ADDREXCEPT (address
))
4343 INTERNALABORT (address
);
4345 if (BIT (21) && LHSReg
!= 15)
4348 for (temp
= 0; !BIT (temp
); temp
++)
4349 ; /* N cycle first */
4351 dest
= ARMul_LoadWordN (state
, address
);
4353 if (!state
->abortSig
&& !state
->Aborted
)
4354 state
->Reg
[temp
++] = dest
;
4355 else if (!state
->Aborted
)
4357 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4358 state
->Aborted
= ARMul_DataAbortV
;
4361 for (; temp
< 16; temp
++) /* S cycles from here on */
4363 { /* load this register */
4365 dest
= ARMul_LoadWordS (state
, address
);
4367 if (!state
->abortSig
&& !state
->Aborted
)
4368 state
->Reg
[temp
] = dest
;
4369 else if (!state
->Aborted
)
4371 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4372 state
->Aborted
= ARMul_DataAbortV
;
4376 if (BIT (15) && !state
->Aborted
)
4377 /* PC is in the reg list. */
4378 WriteR15Branch (state
, PC
);
4380 /* To write back the final register. */
4381 ARMul_Icycles (state
, 1, 0L);
4385 if (BIT (21) && LHSReg
!= 15)
4391 /* This function does the work of loading the registers listed in an LDM
4392 instruction, when the S bit is set. The code here is always increment
4393 after, it's up to the caller to get the input address correct and to
4394 handle base register modification. */
4397 LoadSMult (ARMul_State
* state
,
4406 UNDEF_LSMBaseInListWb
;
4411 if (ADDREXCEPT (address
))
4412 INTERNALABORT (address
);
4415 if (BIT (21) && LHSReg
!= 15)
4418 if (!BIT (15) && state
->Bank
!= USERBANK
)
4420 /* Temporary reg bank switch. */
4421 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4422 UNDEF_LSMUserBankWb
;
4425 for (temp
= 0; !BIT (temp
); temp
++)
4426 ; /* N cycle first. */
4428 dest
= ARMul_LoadWordN (state
, address
);
4430 if (!state
->abortSig
)
4431 state
->Reg
[temp
++] = dest
;
4432 else if (!state
->Aborted
)
4434 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4435 state
->Aborted
= ARMul_DataAbortV
;
4438 for (; temp
< 16; temp
++)
4439 /* S cycles from here on. */
4442 /* Load this register. */
4444 dest
= ARMul_LoadWordS (state
, address
);
4446 if (!state
->abortSig
&& !state
->Aborted
)
4447 state
->Reg
[temp
] = dest
;
4448 else if (!state
->Aborted
)
4450 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4451 state
->Aborted
= ARMul_DataAbortV
;
4455 if (BIT (15) && !state
->Aborted
)
4457 /* PC is in the reg list. */
4459 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4461 state
->Cpsr
= GETSPSR (state
->Bank
);
4462 ARMul_CPSRAltered (state
);
4465 WriteR15 (state
, PC
);
4467 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4469 /* Protect bits in user mode. */
4470 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4471 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4472 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4473 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4476 ARMul_R15Altered (state
);
4482 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4483 /* Restore the correct bank. */
4484 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4486 /* To write back the final register. */
4487 ARMul_Icycles (state
, 1, 0L);
4491 if (BIT (21) && LHSReg
!= 15)
4498 /* This function does the work of storing the registers listed in an STM
4499 instruction, when the S bit is clear. The code here is always increment
4500 after, it's up to the caller to get the input address correct and to
4501 handle base register modification. */
4504 StoreMult (ARMul_State
* state
, ARMword instr
,
4505 ARMword address
, ARMword WBBase
)
4511 UNDEF_LSMBaseInListWb
;
4514 /* N-cycle, increment the PC and update the NextInstr state. */
4518 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4519 INTERNALABORT (address
);
4525 for (temp
= 0; !BIT (temp
); temp
++)
4526 ; /* N cycle first. */
4529 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4533 (void) ARMul_LoadWordN (state
, address
);
4535 /* Fake the Stores as Loads. */
4536 for (; temp
< 16; temp
++)
4539 /* Save this register. */
4541 (void) ARMul_LoadWordS (state
, address
);
4543 if (BIT (21) && LHSReg
!= 15)
4549 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4552 if (state
->abortSig
&& !state
->Aborted
)
4554 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4555 state
->Aborted
= ARMul_DataAbortV
;
4558 if (BIT (21) && LHSReg
!= 15)
4561 for (; temp
< 16; temp
++) /* S cycles from here on */
4564 /* Save this register. */
4567 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4569 if (state
->abortSig
&& !state
->Aborted
)
4571 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4572 state
->Aborted
= ARMul_DataAbortV
;
4580 /* This function does the work of storing the registers listed in an STM
4581 instruction when the S bit is set. The code here is always increment
4582 after, it's up to the caller to get the input address correct and to
4583 handle base register modification. */
4586 StoreSMult (ARMul_State
* state
,
4595 UNDEF_LSMBaseInListWb
;
4600 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4601 INTERNALABORT (address
);
4607 if (state
->Bank
!= USERBANK
)
4609 /* Force User Bank. */
4610 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4611 UNDEF_LSMUserBankWb
;
4614 for (temp
= 0; !BIT (temp
); temp
++)
4615 ; /* N cycle first. */
4618 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4622 (void) ARMul_LoadWordN (state
, address
);
4624 for (; temp
< 16; temp
++)
4625 /* Fake the Stores as Loads. */
4628 /* Save this register. */
4631 (void) ARMul_LoadWordS (state
, address
);
4634 if (BIT (21) && LHSReg
!= 15)
4642 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4645 if (state
->abortSig
&& !state
->Aborted
)
4647 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4648 state
->Aborted
= ARMul_DataAbortV
;
4651 for (; temp
< 16; temp
++)
4652 /* S cycles from here on. */
4655 /* Save this register. */
4658 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4660 if (state
->abortSig
&& !state
->Aborted
)
4662 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4663 state
->Aborted
= ARMul_DataAbortV
;
4667 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4668 /* Restore the correct bank. */
4669 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4671 if (BIT (21) && LHSReg
!= 15)
4678 /* This function does the work of adding two 32bit values
4679 together, and calculating if a carry has occurred. */
4682 Add32 (ARMword a1
, ARMword a2
, int *carry
)
4684 ARMword result
= (a1
+ a2
);
4685 unsigned int uresult
= (unsigned int) result
;
4686 unsigned int ua1
= (unsigned int) a1
;
4688 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4689 or (result > RdLo) then we have no carry: */
4690 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
4698 /* This function does the work of multiplying
4699 two 32bit values to give a 64bit result. */
4702 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4704 /* Operand register numbers. */
4705 int nRdHi
, nRdLo
, nRs
, nRm
;
4706 ARMword RdHi
= 0, RdLo
= 0, Rm
;
4710 nRdHi
= BITS (16, 19);
4711 nRdLo
= BITS (12, 15);
4715 /* Needed to calculate the cycle count. */
4716 Rm
= state
->Reg
[nRm
];
4718 /* Check for illegal operand combinations first. */
4727 /* Intermediate results. */
4728 ARMword lo
, mid1
, mid2
, hi
;
4730 ARMword Rs
= state
->Reg
[nRs
];
4735 /* Compute sign of result and adjust operands if necessary. */
4737 sign
= (Rm
^ Rs
) & 0x80000000;
4739 if (((signed long) Rm
) < 0)
4742 if (((signed long) Rs
) < 0)
4746 /* We can split the 32x32 into four 16x16 operations. This
4747 ensures that we do not lose precision on 32bit only hosts. */
4748 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
4749 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4750 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
4751 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4753 /* We now need to add all of these results together, taking
4754 care to propogate the carries from the additions. */
4755 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
4757 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
4759 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
4763 /* Negate result if necessary. */
4767 if (RdLo
== 0xFFFFFFFF)
4775 /* Else undefined result. */
4777 state
->Reg
[nRdLo
] = RdLo
;
4778 state
->Reg
[nRdHi
] = RdHi
;
4781 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4785 /* Ensure that both RdHi and RdLo are used to compute Z,
4786 but don't let RdLo's sign bit make it to N. */
4787 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4790 /* The cycle count depends on whether the instruction is a signed or
4791 unsigned multiply, and what bits are clear in the multiplier. */
4792 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
4793 /* Invert the bits to make the check against zero. */
4796 if ((Rm
& 0xFFFFFF00) == 0)
4798 else if ((Rm
& 0xFFFF0000) == 0)
4800 else if ((Rm
& 0xFF000000) == 0)
4808 /* This function does the work of multiplying two 32bit
4809 values and adding a 64bit value to give a 64bit result. */
4812 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4819 nRdHi
= BITS (16, 19);
4820 nRdLo
= BITS (12, 15);
4822 RdHi
= state
->Reg
[nRdHi
];
4823 RdLo
= state
->Reg
[nRdLo
];
4825 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
4827 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
4828 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
4830 state
->Reg
[nRdLo
] = RdLo
;
4831 state
->Reg
[nRdHi
] = RdHi
;
4834 /* Ensure that both RdHi and RdLo are used to compute Z,
4835 but don't let RdLo's sign bit make it to N. */
4836 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4838 /* Extra cycle for addition. */