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
* state
, ARMword instr
);
24 static ARMword
GetDPSRegRHS (ARMul_State
* state
, ARMword instr
);
25 static void WriteR15 (ARMul_State
* state
, ARMword src
);
26 static void WriteSR15 (ARMul_State
* state
, ARMword src
);
27 static void WriteR15Branch (ARMul_State
* state
, ARMword src
);
28 static ARMword
GetLSRegRHS (ARMul_State
* state
, ARMword instr
);
29 static ARMword
GetLS7RHS (ARMul_State
* state
, ARMword instr
);
30 static unsigned LoadWord (ARMul_State
* state
, ARMword instr
,
32 static unsigned LoadHalfWord (ARMul_State
* state
, ARMword instr
,
33 ARMword address
, int signextend
);
34 static unsigned LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
,
36 static unsigned StoreWord (ARMul_State
* state
, ARMword instr
,
38 static unsigned StoreHalfWord (ARMul_State
* state
, ARMword instr
,
40 static unsigned StoreByte (ARMul_State
* state
, ARMword instr
,
42 static void LoadMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
44 static void StoreMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
46 static void LoadSMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
48 static void StoreSMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
50 static unsigned Multiply64 (ARMul_State
* state
, ARMword instr
,
51 int signextend
, int scc
);
52 static unsigned MultiplyAdd64 (ARMul_State
* state
, ARMword instr
,
53 int signextend
, int scc
);
54 static void Handle_Load_Double (ARMul_State
* state
, ARMword instr
);
55 static void Handle_Store_Double (ARMul_State
* state
, ARMword instr
);
57 #define LUNSIGNED (0) /* unsigned operation */
58 #define LSIGNED (1) /* signed operation */
59 #define LDEFAULT (0) /* default : do nothing */
60 #define LSCC (1) /* set condition codes on result */
62 #ifdef NEED_UI_LOOP_HOOK
63 /* How often to run the ui_loop update, when in use */
64 #define UI_LOOP_POLL_INTERVAL 0x32000
66 /* Counter for the ui_loop_hook update */
67 static long ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
69 /* Actual hook to call to run through gdb's gui event loop */
70 extern int (*ui_loop_hook
) (int);
71 #endif /* NEED_UI_LOOP_HOOK */
73 extern int stop_simulator
;
75 /***************************************************************************\
76 * short-hand macros for LDR/STR *
77 \***************************************************************************/
79 /* store post decrement writeback */
82 if (StoreHalfWord(state, instr, lhs)) \
83 LSBase = lhs - GetLS7RHS(state, instr) ;
85 /* store post increment writeback */
88 if (StoreHalfWord(state, instr, lhs)) \
89 LSBase = lhs + GetLS7RHS(state, instr) ;
91 /* store pre decrement */
93 (void)StoreHalfWord(state, instr, LHS - GetLS7RHS(state, instr)) ;
95 /* store pre decrement writeback */
96 #define SHPREDOWNWB() \
97 temp = LHS - GetLS7RHS(state, instr) ; \
98 if (StoreHalfWord(state, instr, temp)) \
101 /* store pre increment */
103 (void)StoreHalfWord(state, instr, LHS + GetLS7RHS(state, instr)) ;
105 /* store pre increment writeback */
106 #define SHPREUPWB() \
107 temp = LHS + GetLS7RHS(state, instr) ; \
108 if (StoreHalfWord(state, instr, temp)) \
111 /* Load post decrement writeback. */
112 #define LHPOSTDOWN() \
116 temp = lhs - GetLS7RHS (state, instr); \
118 switch (BITS (5, 6)) \
121 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
125 if (LoadByte (state, instr, lhs, LSIGNED)) \
129 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
132 case 0: /* SWP handled elsewhere. */ \
141 /* Load post increment writeback. */
146 temp = lhs + GetLS7RHS (state, instr); \
148 switch (BITS (5, 6)) \
151 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
155 if (LoadByte (state, instr, lhs, LSIGNED)) \
159 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
162 case 0: /* SWP handled elsewhere. */ \
172 /* load pre decrement */
173 #define LHPREDOWN() \
176 temp = LHS - GetLS7RHS(state,instr) ; \
177 switch (BITS(5,6)) { \
179 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
182 (void)LoadByte(state,instr,temp,LSIGNED) ; \
185 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
187 case 0: /* SWP handled elsewhere */ \
196 /* load pre decrement writeback */
197 #define LHPREDOWNWB() \
200 temp = LHS - GetLS7RHS(state, instr) ; \
201 switch (BITS(5,6)) { \
203 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
207 if (LoadByte(state,instr,temp,LSIGNED)) \
211 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
214 case 0: /* SWP handled elsewhere */ \
223 /* load pre increment */
227 temp = LHS + GetLS7RHS(state,instr) ; \
228 switch (BITS(5,6)) { \
230 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
233 (void)LoadByte(state,instr,temp,LSIGNED) ; \
236 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
238 case 0: /* SWP handled elsewhere */ \
247 /* load pre increment writeback */
248 #define LHPREUPWB() \
251 temp = LHS + GetLS7RHS(state, instr) ; \
252 switch (BITS(5,6)) { \
254 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
258 if (LoadByte(state,instr,temp,LSIGNED)) \
262 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
265 case 0: /* SWP handled elsewhere */ \
274 /***************************************************************************\
275 * EMULATION of ARM6 *
276 \***************************************************************************/
278 /* The PC pipeline value depends on whether ARM or Thumb instructions
279 are being executed: */
284 ARMul_Emulate32 (register ARMul_State
* state
)
286 ARMul_Emulate26 (register ARMul_State
* state
)
289 register ARMword instr
, /* the current instruction */
290 dest
= 0, /* almost the DestBus */
291 temp
, /* ubiquitous third hand */
292 pc
= 0; /* the address of the current instruction */
293 ARMword lhs
, rhs
; /* almost the ABus and BBus */
294 ARMword decoded
= 0, loaded
= 0; /* instruction pipeline */
296 /***************************************************************************\
297 * Execute the next instruction *
298 \***************************************************************************/
300 if (state
->NextInstr
< PRIMEPIPE
)
302 decoded
= state
->decoded
;
303 loaded
= state
->loaded
;
308 { /* just keep going */
310 switch (state
->NextInstr
)
313 state
->Reg
[15] += isize
; /* Advance the pipeline, and an S cycle */
317 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
321 state
->Reg
[15] += isize
; /* Advance the pipeline, and an N cycle */
325 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
330 pc
+= isize
; /* Program counter advanced, and an S cycle */
333 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
338 pc
+= isize
; /* Program counter advanced, and an N cycle */
341 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
345 case RESUME
: /* The program counter has been changed */
350 state
->Reg
[15] = pc
+ (isize
* 2);
352 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
353 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
354 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
358 default: /* The program counter has been changed */
363 state
->Reg
[15] = pc
+ (isize
* 2);
365 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
366 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
367 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
372 ARMul_EnvokeEvent (state
);
375 /* Enable this for a helpful bit of debugging when tracing is needed. */
376 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
381 if (state
->Exception
)
382 { /* Any exceptions */
383 if (state
->NresetSig
== LOW
)
385 ARMul_Abort (state
, ARMul_ResetV
);
388 else if (!state
->NfiqSig
&& !FFLAG
)
390 ARMul_Abort (state
, ARMul_FIQV
);
393 else if (!state
->NirqSig
&& !IFLAG
)
395 ARMul_Abort (state
, ARMul_IRQV
);
400 if (state
->CallDebug
> 0)
402 instr
= ARMul_Debug (state
, pc
, instr
);
403 if (state
->Emulate
< ONCE
)
405 state
->NextInstr
= RESUME
;
410 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
412 (void) fgetc (stdin
);
415 else if (state
->Emulate
< ONCE
)
417 state
->NextInstr
= RESUME
;
424 /* Provide Thumb instruction decoding. If the processor is in Thumb
425 mode, then we can simply decode the Thumb instruction, and map it
426 to the corresponding ARM instruction (by directly loading the
427 instr variable, and letting the normal ARM simulator
428 execute). There are some caveats to ensure that the correct
429 pipelined PC value is used when executing Thumb code, and also for
430 dealing with the BL instruction. */
432 { /* check if in Thumb mode */
434 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
437 ARMul_UndefInstr (state
, instr
); /* This is a Thumb instruction */
440 case t_branch
: /* already processed */
443 case t_decoded
: /* ARM instruction available */
444 instr
= new; /* so continue instruction decoding */
450 /***************************************************************************\
451 * Check the condition codes *
452 \***************************************************************************/
453 if ((temp
= TOPBITS (28)) == AL
)
454 goto mainswitch
; /* vile deed in the need for speed */
456 switch ((int) TOPBITS (28))
457 { /* check the condition code */
464 if (BITS (25, 27) == 5) /* BLX(1) */
468 state
->Reg
[14] = pc
+ 4;
470 dest
= pc
+ 8 + 1; /* Force entry into Thumb mode. */
472 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
474 dest
+= POSBRANCH
+ (BIT (24) << 1);
476 WriteR15Branch (state
, dest
);
479 else if ((instr
& 0xFC70F000) == 0xF450F000)
480 /* The PLD instruction. Ignored. */
483 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
484 ARMul_UndefInstr (state
, instr
);
513 temp
= (CFLAG
&& !ZFLAG
);
516 temp
= (!CFLAG
|| ZFLAG
);
519 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
522 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
525 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
528 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
532 /***************************************************************************\
533 * Actual execution of instructions begins here *
534 \***************************************************************************/
537 { /* if the condition codes don't match, stop here */
540 if (state
->is_XScale
)
542 if (BIT (20) == 0 && BITS (25, 27) == 0)
544 if (BITS (4, 7) == 0xD)
546 /* XScale Load Consecutive insn. */
547 ARMword temp
= GetLS7RHS (state
, instr
);
548 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
549 ARMword addr
= BIT (24) ? temp2
: temp
;
552 ARMul_UndefInstr (state
, instr
);
554 /* Alignment violation. */
555 ARMul_Abort (state
, ARMul_DataAbortV
);
558 int wb
= BIT (24) && BIT (21);
560 state
->Reg
[BITS (12, 15)] =
561 ARMul_LoadWordN (state
, addr
);
562 state
->Reg
[BITS (12, 15) + 1] =
563 ARMul_LoadWordN (state
, addr
+ 4);
570 else if (BITS (4, 7) == 0xF)
572 /* XScale Store Consecutive insn. */
573 ARMword temp
= GetLS7RHS (state
, instr
);
574 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
575 ARMword addr
= BIT (24) ? temp2
: temp
;
578 ARMul_UndefInstr (state
, instr
);
580 /* Alignment violation. */
581 ARMul_Abort (state
, ARMul_DataAbortV
);
584 ARMul_StoreWordN (state
, addr
,
585 state
->Reg
[BITS (12, 15)]);
586 ARMul_StoreWordN (state
, addr
+ 4,
587 state
->Reg
[BITS (12, 15) + 1]);
598 switch ((int) BITS (20, 27))
601 /***************************************************************************\
602 * Data Processing Register RHS Instructions *
603 \***************************************************************************/
605 case 0x00: /* AND reg and MUL */
607 if (BITS (4, 11) == 0xB)
609 /* STRH register offset, no write-back, down, post indexed */
613 if (BITS (4, 7) == 0xD)
615 Handle_Load_Double (state
, instr
);
618 if (BITS (4, 7) == 0xF)
620 Handle_Store_Double (state
, instr
);
624 if (BITS (4, 7) == 9)
626 rhs
= state
->Reg
[MULRHSReg
];
627 if (MULLHSReg
== MULDESTReg
)
630 state
->Reg
[MULDESTReg
] = 0;
632 else if (MULDESTReg
!= 15)
633 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
638 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
639 if (rhs
& (1L << dest
))
640 temp
= dest
; /* mult takes this many/2 I cycles */
641 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
651 case 0x01: /* ANDS reg and MULS */
653 if ((BITS (4, 11) & 0xF9) == 0x9)
655 /* LDR register offset, no write-back, down, post indexed */
657 /* fall through to rest of decoding */
660 if (BITS (4, 7) == 9)
662 rhs
= state
->Reg
[MULRHSReg
];
663 if (MULLHSReg
== MULDESTReg
)
666 state
->Reg
[MULDESTReg
] = 0;
670 else if (MULDESTReg
!= 15)
672 dest
= state
->Reg
[MULLHSReg
] * rhs
;
673 ARMul_NegZero (state
, dest
);
674 state
->Reg
[MULDESTReg
] = dest
;
680 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
681 if (rhs
& (1L << dest
))
682 temp
= dest
; /* mult takes this many/2 I cycles */
683 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
693 case 0x02: /* EOR reg and MLA */
695 if (BITS (4, 11) == 0xB)
697 /* STRH register offset, write-back, down, post indexed */
702 if (BITS (4, 7) == 9)
704 rhs
= state
->Reg
[MULRHSReg
];
705 if (MULLHSReg
== MULDESTReg
)
708 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
710 else if (MULDESTReg
!= 15)
711 state
->Reg
[MULDESTReg
] =
712 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
717 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
718 if (rhs
& (1L << dest
))
719 temp
= dest
; /* mult takes this many/2 I cycles */
720 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
730 case 0x03: /* EORS reg and MLAS */
732 if ((BITS (4, 11) & 0xF9) == 0x9)
734 /* LDR register offset, write-back, down, post-indexed */
736 /* fall through to rest of the decoding */
739 if (BITS (4, 7) == 9)
741 rhs
= state
->Reg
[MULRHSReg
];
742 if (MULLHSReg
== MULDESTReg
)
745 dest
= state
->Reg
[MULACCReg
];
746 ARMul_NegZero (state
, dest
);
747 state
->Reg
[MULDESTReg
] = dest
;
749 else if (MULDESTReg
!= 15)
752 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
753 ARMul_NegZero (state
, dest
);
754 state
->Reg
[MULDESTReg
] = dest
;
760 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
761 if (rhs
& (1L << dest
))
762 temp
= dest
; /* mult takes this many/2 I cycles */
763 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
773 case 0x04: /* SUB reg */
775 if (BITS (4, 7) == 0xB)
777 /* STRH immediate offset, no write-back, down, post indexed */
781 if (BITS (4, 7) == 0xD)
783 Handle_Load_Double (state
, instr
);
786 if (BITS (4, 7) == 0xF)
788 Handle_Store_Double (state
, instr
);
797 case 0x05: /* SUBS reg */
799 if ((BITS (4, 7) & 0x9) == 0x9)
801 /* LDR immediate offset, no write-back, down, post indexed */
803 /* fall through to the rest of the instruction decoding */
809 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
811 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
812 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
822 case 0x06: /* RSB reg */
824 if (BITS (4, 7) == 0xB)
826 /* STRH immediate offset, write-back, down, post indexed */
836 case 0x07: /* RSBS reg */
838 if ((BITS (4, 7) & 0x9) == 0x9)
840 /* LDR immediate offset, write-back, down, post indexed */
842 /* fall through to remainder of instruction decoding */
848 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
850 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
851 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
861 case 0x08: /* ADD reg */
863 if (BITS (4, 11) == 0xB)
865 /* STRH register offset, no write-back, up, post indexed */
869 if (BITS (4, 7) == 0xD)
871 Handle_Load_Double (state
, instr
);
874 if (BITS (4, 7) == 0xF)
876 Handle_Store_Double (state
, instr
);
881 if (BITS (4, 7) == 0x9)
884 ARMul_Icycles (state
,
885 Multiply64 (state
, instr
, LUNSIGNED
,
895 case 0x09: /* ADDS reg */
897 if ((BITS (4, 11) & 0xF9) == 0x9)
899 /* LDR register offset, no write-back, up, post indexed */
901 /* fall through to remaining instruction decoding */
905 if (BITS (4, 7) == 0x9)
908 ARMul_Icycles (state
,
909 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
918 if ((lhs
| rhs
) >> 30)
919 { /* possible C,V,N to set */
920 ASSIGNN (NEG (dest
));
921 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
922 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
933 case 0x0a: /* ADC reg */
935 if (BITS (4, 11) == 0xB)
937 /* STRH register offset, write-back, up, post-indexed */
943 if (BITS (4, 7) == 0x9)
946 ARMul_Icycles (state
,
947 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
953 dest
= LHS
+ rhs
+ CFLAG
;
957 case 0x0b: /* ADCS reg */
959 if ((BITS (4, 11) & 0xF9) == 0x9)
961 /* LDR register offset, write-back, up, post indexed */
963 /* fall through to remaining instruction decoding */
967 if (BITS (4, 7) == 0x9)
970 ARMul_Icycles (state
,
971 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
978 dest
= lhs
+ rhs
+ CFLAG
;
980 if ((lhs
| rhs
) >> 30)
981 { /* possible C,V,N to set */
982 ASSIGNN (NEG (dest
));
983 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
984 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
995 case 0x0c: /* SBC reg */
997 if (BITS (4, 7) == 0xB)
999 /* STRH immediate offset, no write-back, up post indexed */
1003 if (BITS (4, 7) == 0xD)
1005 Handle_Load_Double (state
, instr
);
1008 if (BITS (4, 7) == 0xF)
1010 Handle_Store_Double (state
, instr
);
1015 if (BITS (4, 7) == 0x9)
1018 ARMul_Icycles (state
,
1019 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
1025 dest
= LHS
- rhs
- !CFLAG
;
1029 case 0x0d: /* SBCS reg */
1031 if ((BITS (4, 7) & 0x9) == 0x9)
1033 /* LDR immediate offset, no write-back, up, post indexed */
1038 if (BITS (4, 7) == 0x9)
1041 ARMul_Icycles (state
,
1042 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
1049 dest
= lhs
- rhs
- !CFLAG
;
1050 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1052 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1053 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1063 case 0x0e: /* RSC reg */
1065 if (BITS (4, 7) == 0xB)
1067 /* STRH immediate offset, write-back, up, post indexed */
1073 if (BITS (4, 7) == 0x9)
1076 ARMul_Icycles (state
,
1077 MultiplyAdd64 (state
, instr
, LSIGNED
,
1083 dest
= rhs
- LHS
- !CFLAG
;
1087 case 0x0f: /* RSCS reg */
1089 if ((BITS (4, 7) & 0x9) == 0x9)
1091 /* LDR immediate offset, write-back, up, post indexed */
1093 /* fall through to remaining instruction decoding */
1097 if (BITS (4, 7) == 0x9)
1100 ARMul_Icycles (state
,
1101 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
1108 dest
= rhs
- lhs
- !CFLAG
;
1109 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1111 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1112 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1122 case 0x10: /* TST reg and MRS CPSR and SWP word */
1125 if (BIT (4) == 0 && BIT (7) == 1)
1127 /* ElSegundo SMLAxy insn. */
1128 ARMword op1
= state
->Reg
[BITS (0, 3)];
1129 ARMword op2
= state
->Reg
[BITS (8, 11)];
1130 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1144 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
1146 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
1150 if (BITS (4, 11) == 5)
1152 /* ElSegundo QADD insn. */
1153 ARMword op1
= state
->Reg
[BITS (0, 3)];
1154 ARMword op2
= state
->Reg
[BITS (16, 19)];
1155 ARMword result
= op1
+ op2
;
1156 if (AddOverflow (op1
, op2
, result
))
1158 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1161 state
->Reg
[BITS (12, 15)] = result
;
1166 if (BITS (4, 11) == 0xB)
1168 /* STRH register offset, no write-back, down, pre indexed */
1172 if (BITS (4, 7) == 0xD)
1174 Handle_Load_Double (state
, instr
);
1177 if (BITS (4, 7) == 0xF)
1179 Handle_Store_Double (state
, instr
);
1183 if (BITS (4, 11) == 9)
1189 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1191 INTERNALABORT (temp
);
1192 (void) ARMul_LoadWordN (state
, temp
);
1193 (void) ARMul_LoadWordN (state
, temp
);
1197 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1199 DEST
= ARMul_Align (state
, temp
, dest
);
1202 if (state
->abortSig
|| state
->Aborted
)
1207 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1210 DEST
= ECC
| EINT
| EMODE
;
1218 case 0x11: /* TSTP reg */
1220 if ((BITS (4, 11) & 0xF9) == 0x9)
1222 /* LDR register offset, no write-back, down, pre indexed */
1224 /* continue with remaining instruction decode */
1230 state
->Cpsr
= GETSPSR (state
->Bank
);
1231 ARMul_CPSRAltered (state
);
1242 ARMul_NegZero (state
, dest
);
1246 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6) */
1249 if (BITS (4, 7) == 3)
1255 temp
= (pc
+ 2) | 1;
1259 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1260 state
->Reg
[14] = temp
;
1267 if (BIT (4) == 0 && BIT (7) == 1
1268 && (BIT (5) == 0 || BITS (12, 15) == 0))
1270 /* ElSegundo SMLAWy/SMULWy insn. */
1271 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1272 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1273 unsigned long long result
;
1277 if (op1
& 0x80000000)
1282 result
= (op1
* op2
) >> 16;
1286 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1288 if (AddOverflow (result
, Rn
, result
+ Rn
))
1292 state
->Reg
[BITS (16, 19)] = result
;
1296 if (BITS (4, 11) == 5)
1298 /* ElSegundo QSUB insn. */
1299 ARMword op1
= state
->Reg
[BITS (0, 3)];
1300 ARMword op2
= state
->Reg
[BITS (16, 19)];
1301 ARMword result
= op1
- op2
;
1303 if (SubOverflow (op1
, op2
, result
))
1305 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1309 state
->Reg
[BITS (12, 15)] = result
;
1314 if (BITS (4, 11) == 0xB)
1316 /* STRH register offset, write-back, down, pre indexed */
1320 if (BITS (4, 27) == 0x12FFF1)
1323 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1326 if (BITS (4, 7) == 0xD)
1328 Handle_Load_Double (state
, instr
);
1331 if (BITS (4, 7) == 0xF)
1333 Handle_Store_Double (state
, instr
);
1339 if (BITS (4, 7) == 0x7)
1342 extern int SWI_vector_installed
;
1344 /* Hardware is allowed to optionally override this
1345 instruction and treat it as a breakpoint. Since
1346 this is a simulator not hardware, we take the position
1347 that if a SWI vector was not installed, then an Abort
1348 vector was probably not installed either, and so
1349 normally this instruction would be ignored, even if an
1350 Abort is generated. This is a bad thing, since GDB
1351 uses this instruction for its breakpoints (at least in
1352 Thumb mode it does). So intercept the instruction here
1353 and generate a breakpoint SWI instead. */
1354 if (! SWI_vector_installed
)
1355 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1358 /* BKPT - normally this will cause an abort, but for the
1359 XScale if bit 31 in register 10 of coprocessor 14 is
1360 clear, then this is treated as a no-op. */
1361 if (state
->is_XScale
)
1363 if (read_cp14_reg (10) & (1UL << 31))
1367 value
= read_cp14_reg (10);
1371 write_cp14_reg (10, value
);
1372 write_cp15_reg (5, 0, 0, 0x200); /* Set FSR. */
1373 write_cp15_reg (6, 0, 0, pc
); /* Set FAR. */
1380 /* Force the next instruction to be refetched. */
1381 state
->NextInstr
= RESUME
;
1387 /* MSR reg to CPSR */
1391 /* Don't allow TBIT to be set by MSR. */
1394 ARMul_FixCPSR (state
, instr
, temp
);
1402 case 0x13: /* TEQP reg */
1404 if ((BITS (4, 11) & 0xF9) == 0x9)
1406 /* LDR register offset, write-back, down, pre indexed */
1408 /* continue with remaining instruction decode */
1414 state
->Cpsr
= GETSPSR (state
->Bank
);
1415 ARMul_CPSRAltered (state
);
1426 ARMul_NegZero (state
, dest
);
1430 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1433 if (BIT (4) == 0 && BIT (7) == 1)
1435 /* ElSegundo SMLALxy insn. */
1436 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1437 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1438 unsigned long long dest
;
1439 unsigned long long result
;
1452 dest
= (unsigned long long) state
->Reg
[BITS (16, 19)] << 32;
1453 dest
|= state
->Reg
[BITS (12, 15)];
1455 state
->Reg
[BITS (12, 15)] = dest
;
1456 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1460 if (BITS (4, 11) == 5)
1462 /* ElSegundo QDADD insn. */
1463 ARMword op1
= state
->Reg
[BITS (0, 3)];
1464 ARMword op2
= state
->Reg
[BITS (16, 19)];
1465 ARMword op2d
= op2
+ op2
;
1468 if (AddOverflow (op2
, op2
, op2d
))
1471 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1474 result
= op1
+ op2d
;
1475 if (AddOverflow (op1
, op2d
, result
))
1478 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1481 state
->Reg
[BITS (12, 15)] = result
;
1486 if (BITS (4, 7) == 0xB)
1488 /* STRH immediate offset, no write-back, down, pre indexed */
1492 if (BITS (4, 7) == 0xD)
1494 Handle_Load_Double (state
, instr
);
1497 if (BITS (4, 7) == 0xF)
1499 Handle_Store_Double (state
, instr
);
1503 if (BITS (4, 11) == 9)
1509 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1511 INTERNALABORT (temp
);
1512 (void) ARMul_LoadByte (state
, temp
);
1513 (void) ARMul_LoadByte (state
, temp
);
1517 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1518 if (state
->abortSig
|| state
->Aborted
)
1523 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1526 DEST
= GETSPSR (state
->Bank
);
1534 case 0x15: /* CMPP reg */
1536 if ((BITS (4, 7) & 0x9) == 0x9)
1538 /* LDR immediate offset, no write-back, down, pre indexed */
1540 /* continue with remaining instruction decode */
1546 state
->Cpsr
= GETSPSR (state
->Bank
);
1547 ARMul_CPSRAltered (state
);
1559 ARMul_NegZero (state
, dest
);
1560 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1562 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1563 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1573 case 0x16: /* CMN reg and MSR reg to SPSR */
1576 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1578 /* ElSegundo SMULxy insn. */
1579 ARMword op1
= state
->Reg
[BITS (0, 3)];
1580 ARMword op2
= state
->Reg
[BITS (8, 11)];
1581 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1594 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1598 if (BITS (4, 11) == 5)
1600 /* ElSegundo QDSUB insn. */
1601 ARMword op1
= state
->Reg
[BITS (0, 3)];
1602 ARMword op2
= state
->Reg
[BITS (16, 19)];
1603 ARMword op2d
= op2
+ op2
;
1606 if (AddOverflow (op2
, op2
, op2d
))
1609 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1612 result
= op1
- op2d
;
1613 if (SubOverflow (op1
, op2d
, result
))
1616 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1619 state
->Reg
[BITS (12, 15)] = result
;
1626 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1628 /* ARM5 CLZ insn. */
1629 ARMword op1
= state
->Reg
[BITS (0, 3)];
1633 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1636 state
->Reg
[BITS (12, 15)] = result
;
1641 if (BITS (4, 7) == 0xB)
1643 /* STRH immediate offset, write-back, down, pre indexed */
1647 if (BITS (4, 7) == 0xD)
1649 Handle_Load_Double (state
, instr
);
1652 if (BITS (4, 7) == 0xF)
1654 Handle_Store_Double (state
, instr
);
1661 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1669 case 0x17: /* CMNP reg */
1671 if ((BITS (4, 7) & 0x9) == 0x9)
1673 /* LDR immediate offset, write-back, down, pre indexed */
1675 /* continue with remaining instruction decoding */
1681 state
->Cpsr
= GETSPSR (state
->Bank
);
1682 ARMul_CPSRAltered (state
);
1695 ASSIGNZ (dest
== 0);
1696 if ((lhs
| rhs
) >> 30)
1697 { /* possible C,V,N to set */
1698 ASSIGNN (NEG (dest
));
1699 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1700 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1711 case 0x18: /* ORR reg */
1713 if (BITS (4, 11) == 0xB)
1715 /* STRH register offset, no write-back, up, pre indexed */
1719 if (BITS (4, 7) == 0xD)
1721 Handle_Load_Double (state
, instr
);
1724 if (BITS (4, 7) == 0xF)
1726 Handle_Store_Double (state
, instr
);
1735 case 0x19: /* ORRS reg */
1737 if ((BITS (4, 11) & 0xF9) == 0x9)
1739 /* LDR register offset, no write-back, up, pre indexed */
1741 /* continue with remaining instruction decoding */
1749 case 0x1a: /* MOV reg */
1751 if (BITS (4, 11) == 0xB)
1753 /* STRH register offset, write-back, up, pre indexed */
1757 if (BITS (4, 7) == 0xD)
1759 Handle_Load_Double (state
, instr
);
1762 if (BITS (4, 7) == 0xF)
1764 Handle_Store_Double (state
, instr
);
1772 case 0x1b: /* MOVS reg */
1774 if ((BITS (4, 11) & 0xF9) == 0x9)
1776 /* LDR register offset, write-back, up, pre indexed */
1778 /* continue with remaining instruction decoding */
1785 case 0x1c: /* BIC reg */
1787 if (BITS (4, 7) == 0xB)
1789 /* STRH immediate offset, no write-back, up, pre indexed */
1793 if (BITS (4, 7) == 0xD)
1795 Handle_Load_Double (state
, instr
);
1798 else if (BITS (4, 7) == 0xF)
1800 Handle_Store_Double (state
, instr
);
1809 case 0x1d: /* BICS reg */
1811 if ((BITS (4, 7) & 0x9) == 0x9)
1813 /* LDR immediate offset, no write-back, up, pre indexed */
1815 /* continue with instruction decoding */
1823 case 0x1e: /* MVN reg */
1825 if (BITS (4, 7) == 0xB)
1827 /* STRH immediate offset, write-back, up, pre indexed */
1831 if (BITS (4, 7) == 0xD)
1833 Handle_Load_Double (state
, instr
);
1836 if (BITS (4, 7) == 0xF)
1838 Handle_Store_Double (state
, instr
);
1846 case 0x1f: /* MVNS reg */
1848 if ((BITS (4, 7) & 0x9) == 0x9)
1850 /* LDR immediate offset, write-back, up, pre indexed */
1852 /* continue instruction decoding */
1859 /***************************************************************************\
1860 * Data Processing Immediate RHS Instructions *
1861 \***************************************************************************/
1863 case 0x20: /* AND immed */
1864 dest
= LHS
& DPImmRHS
;
1868 case 0x21: /* ANDS immed */
1874 case 0x22: /* EOR immed */
1875 dest
= LHS
^ DPImmRHS
;
1879 case 0x23: /* EORS immed */
1885 case 0x24: /* SUB immed */
1886 dest
= LHS
- DPImmRHS
;
1890 case 0x25: /* SUBS immed */
1894 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1896 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1897 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1907 case 0x26: /* RSB immed */
1908 dest
= DPImmRHS
- LHS
;
1912 case 0x27: /* RSBS immed */
1916 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1918 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1919 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1929 case 0x28: /* ADD immed */
1930 dest
= LHS
+ DPImmRHS
;
1934 case 0x29: /* ADDS immed */
1938 ASSIGNZ (dest
== 0);
1939 if ((lhs
| rhs
) >> 30)
1940 { /* possible C,V,N to set */
1941 ASSIGNN (NEG (dest
));
1942 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1943 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1954 case 0x2a: /* ADC immed */
1955 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1959 case 0x2b: /* ADCS immed */
1962 dest
= lhs
+ rhs
+ CFLAG
;
1963 ASSIGNZ (dest
== 0);
1964 if ((lhs
| rhs
) >> 30)
1965 { /* possible C,V,N to set */
1966 ASSIGNN (NEG (dest
));
1967 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1968 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1979 case 0x2c: /* SBC immed */
1980 dest
= LHS
- DPImmRHS
- !CFLAG
;
1984 case 0x2d: /* SBCS immed */
1987 dest
= lhs
- rhs
- !CFLAG
;
1988 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1990 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1991 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2001 case 0x2e: /* RSC immed */
2002 dest
= DPImmRHS
- LHS
- !CFLAG
;
2006 case 0x2f: /* RSCS immed */
2009 dest
= rhs
- lhs
- !CFLAG
;
2010 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2012 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2013 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2023 case 0x30: /* TST immed */
2027 case 0x31: /* TSTP immed */
2031 state
->Cpsr
= GETSPSR (state
->Bank
);
2032 ARMul_CPSRAltered (state
);
2034 temp
= LHS
& DPImmRHS
;
2040 DPSImmRHS
; /* TST immed */
2042 ARMul_NegZero (state
, dest
);
2046 case 0x32: /* TEQ immed and MSR immed to CPSR */
2048 { /* MSR immed to CPSR */
2049 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2057 case 0x33: /* TEQP immed */
2061 state
->Cpsr
= GETSPSR (state
->Bank
);
2062 ARMul_CPSRAltered (state
);
2064 temp
= LHS
^ DPImmRHS
;
2070 DPSImmRHS
; /* TEQ immed */
2072 ARMul_NegZero (state
, dest
);
2076 case 0x34: /* CMP immed */
2080 case 0x35: /* CMPP immed */
2084 state
->Cpsr
= GETSPSR (state
->Bank
);
2085 ARMul_CPSRAltered (state
);
2087 temp
= LHS
- DPImmRHS
;
2094 lhs
= LHS
; /* CMP immed */
2097 ARMul_NegZero (state
, dest
);
2098 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2100 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2101 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2111 case 0x36: /* CMN immed and MSR immed to SPSR */
2112 if (DESTReg
== 15) /* MSR */
2113 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2120 case 0x37: /* CMNP immed */
2124 state
->Cpsr
= GETSPSR (state
->Bank
);
2125 ARMul_CPSRAltered (state
);
2127 temp
= LHS
+ DPImmRHS
;
2134 lhs
= LHS
; /* CMN immed */
2137 ASSIGNZ (dest
== 0);
2138 if ((lhs
| rhs
) >> 30)
2139 { /* possible C,V,N to set */
2140 ASSIGNN (NEG (dest
));
2141 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2142 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2153 case 0x38: /* ORR immed */
2154 dest
= LHS
| DPImmRHS
;
2158 case 0x39: /* ORRS immed */
2164 case 0x3a: /* MOV immed */
2169 case 0x3b: /* MOVS immed */
2174 case 0x3c: /* BIC immed */
2175 dest
= LHS
& ~DPImmRHS
;
2179 case 0x3d: /* BICS immed */
2185 case 0x3e: /* MVN immed */
2190 case 0x3f: /* MVNS immed */
2195 /***************************************************************************\
2196 * Single Data Transfer Immediate RHS Instructions *
2197 \***************************************************************************/
2199 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
2201 if (StoreWord (state
, instr
, lhs
))
2202 LSBase
= lhs
- LSImmRHS
;
2205 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
2207 if (LoadWord (state
, instr
, lhs
))
2208 LSBase
= lhs
- LSImmRHS
;
2211 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
2212 UNDEF_LSRBaseEQDestWb
;
2215 temp
= lhs
- LSImmRHS
;
2216 state
->NtransSig
= LOW
;
2217 if (StoreWord (state
, instr
, lhs
))
2219 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2222 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
2223 UNDEF_LSRBaseEQDestWb
;
2226 state
->NtransSig
= LOW
;
2227 if (LoadWord (state
, instr
, lhs
))
2228 LSBase
= lhs
- LSImmRHS
;
2229 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2232 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
2234 if (StoreByte (state
, instr
, lhs
))
2235 LSBase
= lhs
- LSImmRHS
;
2238 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
2240 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2241 LSBase
= lhs
- LSImmRHS
;
2244 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
2245 UNDEF_LSRBaseEQDestWb
;
2248 state
->NtransSig
= LOW
;
2249 if (StoreByte (state
, instr
, lhs
))
2250 LSBase
= lhs
- LSImmRHS
;
2251 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2254 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
2255 UNDEF_LSRBaseEQDestWb
;
2258 state
->NtransSig
= LOW
;
2259 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2260 LSBase
= lhs
- LSImmRHS
;
2261 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2264 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
2266 if (StoreWord (state
, instr
, lhs
))
2267 LSBase
= lhs
+ LSImmRHS
;
2270 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
2272 if (LoadWord (state
, instr
, lhs
))
2273 LSBase
= lhs
+ LSImmRHS
;
2276 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
2277 UNDEF_LSRBaseEQDestWb
;
2280 state
->NtransSig
= LOW
;
2281 if (StoreWord (state
, instr
, lhs
))
2282 LSBase
= lhs
+ LSImmRHS
;
2283 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2286 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
2287 UNDEF_LSRBaseEQDestWb
;
2290 state
->NtransSig
= LOW
;
2291 if (LoadWord (state
, instr
, lhs
))
2292 LSBase
= lhs
+ LSImmRHS
;
2293 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2296 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
2298 if (StoreByte (state
, instr
, lhs
))
2299 LSBase
= lhs
+ LSImmRHS
;
2302 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
2304 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2305 LSBase
= lhs
+ LSImmRHS
;
2308 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
2309 UNDEF_LSRBaseEQDestWb
;
2312 state
->NtransSig
= LOW
;
2313 if (StoreByte (state
, instr
, lhs
))
2314 LSBase
= lhs
+ LSImmRHS
;
2315 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2318 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
2319 UNDEF_LSRBaseEQDestWb
;
2322 state
->NtransSig
= LOW
;
2323 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2324 LSBase
= lhs
+ LSImmRHS
;
2325 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2329 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
2330 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2333 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
2334 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2337 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
2338 UNDEF_LSRBaseEQDestWb
;
2340 temp
= LHS
- LSImmRHS
;
2341 if (StoreWord (state
, instr
, temp
))
2345 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
2346 UNDEF_LSRBaseEQDestWb
;
2348 temp
= LHS
- LSImmRHS
;
2349 if (LoadWord (state
, instr
, temp
))
2353 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
2354 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2357 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
2358 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2361 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
2362 UNDEF_LSRBaseEQDestWb
;
2364 temp
= LHS
- LSImmRHS
;
2365 if (StoreByte (state
, instr
, temp
))
2369 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
2370 UNDEF_LSRBaseEQDestWb
;
2372 temp
= LHS
- LSImmRHS
;
2373 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2377 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
2378 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2381 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
2382 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2385 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
2386 UNDEF_LSRBaseEQDestWb
;
2388 temp
= LHS
+ LSImmRHS
;
2389 if (StoreWord (state
, instr
, temp
))
2393 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
2394 UNDEF_LSRBaseEQDestWb
;
2396 temp
= LHS
+ LSImmRHS
;
2397 if (LoadWord (state
, instr
, temp
))
2401 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
2402 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2405 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
2406 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2409 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
2410 UNDEF_LSRBaseEQDestWb
;
2412 temp
= LHS
+ LSImmRHS
;
2413 if (StoreByte (state
, instr
, temp
))
2417 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
2418 UNDEF_LSRBaseEQDestWb
;
2420 temp
= LHS
+ LSImmRHS
;
2421 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2425 /***************************************************************************\
2426 * Single Data Transfer Register RHS Instructions *
2427 \***************************************************************************/
2429 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
2432 ARMul_UndefInstr (state
, instr
);
2435 UNDEF_LSRBaseEQOffWb
;
2436 UNDEF_LSRBaseEQDestWb
;
2440 if (StoreWord (state
, instr
, lhs
))
2441 LSBase
= lhs
- LSRegRHS
;
2444 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
2447 ARMul_UndefInstr (state
, instr
);
2450 UNDEF_LSRBaseEQOffWb
;
2451 UNDEF_LSRBaseEQDestWb
;
2455 temp
= lhs
- LSRegRHS
;
2456 if (LoadWord (state
, instr
, lhs
))
2460 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2463 ARMul_UndefInstr (state
, instr
);
2466 UNDEF_LSRBaseEQOffWb
;
2467 UNDEF_LSRBaseEQDestWb
;
2471 state
->NtransSig
= LOW
;
2472 if (StoreWord (state
, instr
, lhs
))
2473 LSBase
= lhs
- LSRegRHS
;
2474 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2477 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2480 ARMul_UndefInstr (state
, instr
);
2483 UNDEF_LSRBaseEQOffWb
;
2484 UNDEF_LSRBaseEQDestWb
;
2488 temp
= lhs
- LSRegRHS
;
2489 state
->NtransSig
= LOW
;
2490 if (LoadWord (state
, instr
, lhs
))
2492 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2495 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2498 ARMul_UndefInstr (state
, instr
);
2501 UNDEF_LSRBaseEQOffWb
;
2502 UNDEF_LSRBaseEQDestWb
;
2506 if (StoreByte (state
, instr
, lhs
))
2507 LSBase
= lhs
- LSRegRHS
;
2510 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2513 ARMul_UndefInstr (state
, instr
);
2516 UNDEF_LSRBaseEQOffWb
;
2517 UNDEF_LSRBaseEQDestWb
;
2521 temp
= lhs
- LSRegRHS
;
2522 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2526 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2529 ARMul_UndefInstr (state
, instr
);
2532 UNDEF_LSRBaseEQOffWb
;
2533 UNDEF_LSRBaseEQDestWb
;
2537 state
->NtransSig
= LOW
;
2538 if (StoreByte (state
, instr
, lhs
))
2539 LSBase
= lhs
- LSRegRHS
;
2540 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2543 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2546 ARMul_UndefInstr (state
, instr
);
2549 UNDEF_LSRBaseEQOffWb
;
2550 UNDEF_LSRBaseEQDestWb
;
2554 temp
= lhs
- LSRegRHS
;
2555 state
->NtransSig
= LOW
;
2556 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2558 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2561 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2564 ARMul_UndefInstr (state
, instr
);
2567 UNDEF_LSRBaseEQOffWb
;
2568 UNDEF_LSRBaseEQDestWb
;
2572 if (StoreWord (state
, instr
, lhs
))
2573 LSBase
= lhs
+ LSRegRHS
;
2576 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2579 ARMul_UndefInstr (state
, instr
);
2582 UNDEF_LSRBaseEQOffWb
;
2583 UNDEF_LSRBaseEQDestWb
;
2587 temp
= lhs
+ LSRegRHS
;
2588 if (LoadWord (state
, instr
, lhs
))
2592 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2595 ARMul_UndefInstr (state
, instr
);
2598 UNDEF_LSRBaseEQOffWb
;
2599 UNDEF_LSRBaseEQDestWb
;
2603 state
->NtransSig
= LOW
;
2604 if (StoreWord (state
, instr
, lhs
))
2605 LSBase
= lhs
+ LSRegRHS
;
2606 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2609 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2612 ARMul_UndefInstr (state
, instr
);
2615 UNDEF_LSRBaseEQOffWb
;
2616 UNDEF_LSRBaseEQDestWb
;
2620 temp
= lhs
+ LSRegRHS
;
2621 state
->NtransSig
= LOW
;
2622 if (LoadWord (state
, instr
, lhs
))
2624 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2627 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2630 ARMul_UndefInstr (state
, instr
);
2633 UNDEF_LSRBaseEQOffWb
;
2634 UNDEF_LSRBaseEQDestWb
;
2638 if (StoreByte (state
, instr
, lhs
))
2639 LSBase
= lhs
+ LSRegRHS
;
2642 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2645 ARMul_UndefInstr (state
, instr
);
2648 UNDEF_LSRBaseEQOffWb
;
2649 UNDEF_LSRBaseEQDestWb
;
2653 temp
= lhs
+ LSRegRHS
;
2654 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2658 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2661 ARMul_UndefInstr (state
, instr
);
2664 UNDEF_LSRBaseEQOffWb
;
2665 UNDEF_LSRBaseEQDestWb
;
2669 state
->NtransSig
= LOW
;
2670 if (StoreByte (state
, instr
, lhs
))
2671 LSBase
= lhs
+ LSRegRHS
;
2672 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2675 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2678 ARMul_UndefInstr (state
, instr
);
2681 UNDEF_LSRBaseEQOffWb
;
2682 UNDEF_LSRBaseEQDestWb
;
2686 temp
= lhs
+ LSRegRHS
;
2687 state
->NtransSig
= LOW
;
2688 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2690 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2694 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2697 ARMul_UndefInstr (state
, instr
);
2700 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2703 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2706 ARMul_UndefInstr (state
, instr
);
2709 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2712 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2715 ARMul_UndefInstr (state
, instr
);
2718 UNDEF_LSRBaseEQOffWb
;
2719 UNDEF_LSRBaseEQDestWb
;
2722 temp
= LHS
- LSRegRHS
;
2723 if (StoreWord (state
, instr
, temp
))
2727 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2730 ARMul_UndefInstr (state
, instr
);
2733 UNDEF_LSRBaseEQOffWb
;
2734 UNDEF_LSRBaseEQDestWb
;
2737 temp
= LHS
- LSRegRHS
;
2738 if (LoadWord (state
, instr
, temp
))
2742 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2745 ARMul_UndefInstr (state
, instr
);
2748 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2751 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2754 ARMul_UndefInstr (state
, instr
);
2757 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2760 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2763 ARMul_UndefInstr (state
, instr
);
2766 UNDEF_LSRBaseEQOffWb
;
2767 UNDEF_LSRBaseEQDestWb
;
2770 temp
= LHS
- LSRegRHS
;
2771 if (StoreByte (state
, instr
, temp
))
2775 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2778 ARMul_UndefInstr (state
, instr
);
2781 UNDEF_LSRBaseEQOffWb
;
2782 UNDEF_LSRBaseEQDestWb
;
2785 temp
= LHS
- LSRegRHS
;
2786 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2790 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2793 ARMul_UndefInstr (state
, instr
);
2796 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2799 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2802 ARMul_UndefInstr (state
, instr
);
2805 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2808 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2811 ARMul_UndefInstr (state
, instr
);
2814 UNDEF_LSRBaseEQOffWb
;
2815 UNDEF_LSRBaseEQDestWb
;
2818 temp
= LHS
+ LSRegRHS
;
2819 if (StoreWord (state
, instr
, temp
))
2823 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2826 ARMul_UndefInstr (state
, instr
);
2829 UNDEF_LSRBaseEQOffWb
;
2830 UNDEF_LSRBaseEQDestWb
;
2833 temp
= LHS
+ LSRegRHS
;
2834 if (LoadWord (state
, instr
, temp
))
2838 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2841 ARMul_UndefInstr (state
, instr
);
2844 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2847 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2850 ARMul_UndefInstr (state
, instr
);
2853 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2856 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2859 ARMul_UndefInstr (state
, instr
);
2862 UNDEF_LSRBaseEQOffWb
;
2863 UNDEF_LSRBaseEQDestWb
;
2866 temp
= LHS
+ LSRegRHS
;
2867 if (StoreByte (state
, instr
, temp
))
2871 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2874 /* Check for the special breakpoint opcode.
2875 This value should correspond to the value defined
2876 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2877 if (BITS (0, 19) == 0xfdefe)
2879 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2880 ARMul_Abort (state
, ARMul_SWIV
);
2883 ARMul_UndefInstr (state
, instr
);
2886 UNDEF_LSRBaseEQOffWb
;
2887 UNDEF_LSRBaseEQDestWb
;
2890 temp
= LHS
+ LSRegRHS
;
2891 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2895 /***************************************************************************\
2896 * Multiple Data Transfer Instructions *
2897 \***************************************************************************/
2899 case 0x80: /* Store, No WriteBack, Post Dec */
2900 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2903 case 0x81: /* Load, No WriteBack, Post Dec */
2904 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2907 case 0x82: /* Store, WriteBack, Post Dec */
2908 temp
= LSBase
- LSMNumRegs
;
2909 STOREMULT (instr
, temp
+ 4L, temp
);
2912 case 0x83: /* Load, WriteBack, Post Dec */
2913 temp
= LSBase
- LSMNumRegs
;
2914 LOADMULT (instr
, temp
+ 4L, temp
);
2917 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2918 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2921 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2922 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2925 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2926 temp
= LSBase
- LSMNumRegs
;
2927 STORESMULT (instr
, temp
+ 4L, temp
);
2930 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2931 temp
= LSBase
- LSMNumRegs
;
2932 LOADSMULT (instr
, temp
+ 4L, temp
);
2935 case 0x88: /* Store, No WriteBack, Post Inc */
2936 STOREMULT (instr
, LSBase
, 0L);
2939 case 0x89: /* Load, No WriteBack, Post Inc */
2940 LOADMULT (instr
, LSBase
, 0L);
2943 case 0x8a: /* Store, WriteBack, Post Inc */
2945 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
2948 case 0x8b: /* Load, WriteBack, Post Inc */
2950 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
2953 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2954 STORESMULT (instr
, LSBase
, 0L);
2957 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2958 LOADSMULT (instr
, LSBase
, 0L);
2961 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2963 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
2966 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2968 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
2971 case 0x90: /* Store, No WriteBack, Pre Dec */
2972 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2975 case 0x91: /* Load, No WriteBack, Pre Dec */
2976 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2979 case 0x92: /* Store, WriteBack, Pre Dec */
2980 temp
= LSBase
- LSMNumRegs
;
2981 STOREMULT (instr
, temp
, temp
);
2984 case 0x93: /* Load, WriteBack, Pre Dec */
2985 temp
= LSBase
- LSMNumRegs
;
2986 LOADMULT (instr
, temp
, temp
);
2989 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2990 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2993 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2994 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2997 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
2998 temp
= LSBase
- LSMNumRegs
;
2999 STORESMULT (instr
, temp
, temp
);
3002 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
3003 temp
= LSBase
- LSMNumRegs
;
3004 LOADSMULT (instr
, temp
, temp
);
3007 case 0x98: /* Store, No WriteBack, Pre Inc */
3008 STOREMULT (instr
, LSBase
+ 4L, 0L);
3011 case 0x99: /* Load, No WriteBack, Pre Inc */
3012 LOADMULT (instr
, LSBase
+ 4L, 0L);
3015 case 0x9a: /* Store, WriteBack, Pre Inc */
3017 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3020 case 0x9b: /* Load, WriteBack, Pre Inc */
3022 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3025 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
3026 STORESMULT (instr
, LSBase
+ 4L, 0L);
3029 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
3030 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3033 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
3035 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3038 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
3040 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3043 /***************************************************************************\
3045 \***************************************************************************/
3055 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3059 /***************************************************************************\
3061 \***************************************************************************/
3071 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3075 /***************************************************************************\
3076 * Branch and Link forward *
3077 \***************************************************************************/
3088 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3090 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3092 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3096 /***************************************************************************\
3097 * Branch and Link backward *
3098 \***************************************************************************/
3109 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3111 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3113 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3117 /***************************************************************************\
3118 * Co-Processor Data Transfers *
3119 \***************************************************************************/
3122 if (state
->is_XScale
)
3124 if (BITS (4, 7) != 0x00)
3125 ARMul_UndefInstr (state
, instr
);
3127 if (BITS (8, 11) != 0x00)
3128 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3130 /* XScale MAR insn. Move two registers into accumulator. */
3131 if (BITS (0, 3) == 0x00)
3133 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3134 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3137 /* Access to any other acc is unpredicatable. */
3142 case 0xc0: /* Store , No WriteBack , Post Dec */
3143 ARMul_STC (state
, instr
, LHS
);
3147 if (state
->is_XScale
)
3149 if (BITS (4, 7) != 0x00)
3150 ARMul_UndefInstr (state
, instr
);
3152 if (BITS (8, 11) != 0x00)
3153 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3155 /* XScale MRA insn. Move accumulator into two registers. */
3156 if (BITS (0, 3) == 0x00)
3158 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3163 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3164 state
->Reg
[BITS (16, 19)] = t1
;
3167 /* Access to any other acc is unpredicatable. */
3172 case 0xc1: /* Load , No WriteBack , Post Dec */
3173 ARMul_LDC (state
, instr
, LHS
);
3177 case 0xc6: /* Store , WriteBack , Post Dec */
3179 state
->Base
= lhs
- LSCOff
;
3180 ARMul_STC (state
, instr
, lhs
);
3184 case 0xc7: /* Load , WriteBack , Post Dec */
3186 state
->Base
= lhs
- LSCOff
;
3187 ARMul_LDC (state
, instr
, lhs
);
3191 case 0xcc: /* Store , No WriteBack , Post Inc */
3192 ARMul_STC (state
, instr
, LHS
);
3196 case 0xcd: /* Load , No WriteBack , Post Inc */
3197 ARMul_LDC (state
, instr
, LHS
);
3201 case 0xce: /* Store , WriteBack , Post Inc */
3203 state
->Base
= lhs
+ LSCOff
;
3204 ARMul_STC (state
, instr
, LHS
);
3208 case 0xcf: /* Load , WriteBack , Post Inc */
3210 state
->Base
= lhs
+ LSCOff
;
3211 ARMul_LDC (state
, instr
, LHS
);
3216 case 0xd4: /* Store , No WriteBack , Pre Dec */
3217 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3221 case 0xd5: /* Load , No WriteBack , Pre Dec */
3222 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3226 case 0xd6: /* Store , WriteBack , Pre Dec */
3229 ARMul_STC (state
, instr
, lhs
);
3233 case 0xd7: /* Load , WriteBack , Pre Dec */
3236 ARMul_LDC (state
, instr
, lhs
);
3240 case 0xdc: /* Store , No WriteBack , Pre Inc */
3241 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3245 case 0xdd: /* Load , No WriteBack , Pre Inc */
3246 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3250 case 0xde: /* Store , WriteBack , Pre Inc */
3253 ARMul_STC (state
, instr
, lhs
);
3257 case 0xdf: /* Load , WriteBack , Pre Inc */
3260 ARMul_LDC (state
, instr
, lhs
);
3263 /***************************************************************************\
3264 * Co-Processor Register Transfers (MCR) and Data Ops *
3265 \***************************************************************************/
3268 if (state
->is_XScale
)
3269 switch (BITS (18, 19))
3273 /* XScale MIA instruction. Signed multiplication of two 32 bit
3274 values and addition to 40 bit accumulator. */
3275 long long Rm
= state
->Reg
[MULLHSReg
];
3276 long long Rs
= state
->Reg
[MULACCReg
];
3282 state
->Accumulator
+= Rm
* Rs
;
3288 /* XScale MIAPH instruction. */
3289 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3290 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3291 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3292 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3307 state
->Accumulator
+= t5
;
3312 state
->Accumulator
+= t5
;
3318 /* XScale MIAxy instruction. */
3324 t1
= state
->Reg
[MULLHSReg
] >> 16;
3326 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3329 t2
= state
->Reg
[MULACCReg
] >> 16;
3331 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3341 state
->Accumulator
+= t5
;
3363 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3365 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3366 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3370 ARMul_MCR (state
, instr
, DEST
);
3372 else /* CDP Part 1 */
3373 ARMul_CDP (state
, instr
);
3376 /***************************************************************************\
3377 * Co-Processor Register Transfers (MRC) and Data Ops *
3378 \***************************************************************************/
3390 temp
= ARMul_MRC (state
, instr
);
3393 ASSIGNN ((temp
& NBIT
) != 0);
3394 ASSIGNZ ((temp
& ZBIT
) != 0);
3395 ASSIGNC ((temp
& CBIT
) != 0);
3396 ASSIGNV ((temp
& VBIT
) != 0);
3401 else /* CDP Part 2 */
3402 ARMul_CDP (state
, instr
);
3405 /***************************************************************************\
3407 \***************************************************************************/
3425 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3427 /* A prefetch abort. */
3428 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3432 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3434 ARMul_Abort (state
, ARMul_SWIV
);
3437 } /* 256 way main switch */
3444 #ifdef NEED_UI_LOOP_HOOK
3445 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3447 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3450 #endif /* NEED_UI_LOOP_HOOK */
3452 if (state
->Emulate
== ONCE
)
3453 state
->Emulate
= STOP
;
3454 /* If we have changed mode, allow the PC to advance before stopping. */
3455 else if (state
->Emulate
== CHANGEMODE
)
3457 else if (state
->Emulate
!= RUN
)
3460 while (!stop_simulator
); /* do loop */
3462 state
->decoded
= decoded
;
3463 state
->loaded
= loaded
;
3467 } /* Emulate 26/32 in instruction based mode */
3470 /***************************************************************************\
3471 * This routine evaluates most Data Processing register RHS's with the S *
3472 * bit clear. It is intended to be called from the macro DPRegRHS, which *
3473 * filters the common case of an unshifted register with in line code *
3474 \***************************************************************************/
3477 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3479 ARMword shamt
, base
;
3483 { /* shift amount in a register */
3488 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3491 base
= state
->Reg
[base
];
3492 ARMul_Icycles (state
, 1, 0L);
3493 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3494 switch ((int) BITS (5, 6))
3499 else if (shamt
>= 32)
3502 return (base
<< shamt
);
3506 else if (shamt
>= 32)
3509 return (base
>> shamt
);
3513 else if (shamt
>= 32)
3514 return ((ARMword
) ((long int) base
>> 31L));
3516 return ((ARMword
) ((long int) base
>> (int) shamt
));
3522 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3526 { /* shift amount is a constant */
3529 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3532 base
= state
->Reg
[base
];
3533 shamt
= BITS (7, 11);
3534 switch ((int) BITS (5, 6))
3537 return (base
<< shamt
);
3542 return (base
>> shamt
);
3545 return ((ARMword
) ((long int) base
>> 31L));
3547 return ((ARMword
) ((long int) base
>> (int) shamt
));
3549 if (shamt
== 0) /* its an RRX */
3550 return ((base
>> 1) | (CFLAG
<< 31));
3552 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3555 return (0); /* just to shut up lint */
3558 /***************************************************************************\
3559 * This routine evaluates most Logical Data Processing register RHS's *
3560 * with the S bit set. It is intended to be called from the macro *
3561 * DPSRegRHS, which filters the common case of an unshifted register *
3562 * with in line code *
3563 \***************************************************************************/
3566 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3568 ARMword shamt
, base
;
3572 { /* shift amount in a register */
3577 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3580 base
= state
->Reg
[base
];
3581 ARMul_Icycles (state
, 1, 0L);
3582 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3583 switch ((int) BITS (5, 6))
3588 else if (shamt
== 32)
3593 else if (shamt
> 32)
3600 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3601 return (base
<< shamt
);
3606 else if (shamt
== 32)
3608 ASSIGNC (base
>> 31);
3611 else if (shamt
> 32)
3618 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3619 return (base
>> shamt
);
3624 else if (shamt
>= 32)
3626 ASSIGNC (base
>> 31L);
3627 return ((ARMword
) ((long int) base
>> 31L));
3631 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3632 return ((ARMword
) ((long int) base
>> (int) shamt
));
3640 ASSIGNC (base
>> 31);
3645 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3646 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3651 { /* shift amount is a constant */
3654 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3657 base
= state
->Reg
[base
];
3658 shamt
= BITS (7, 11);
3659 switch ((int) BITS (5, 6))
3662 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3663 return (base
<< shamt
);
3667 ASSIGNC (base
>> 31);
3672 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3673 return (base
>> shamt
);
3678 ASSIGNC (base
>> 31L);
3679 return ((ARMword
) ((long int) base
>> 31L));
3683 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3684 return ((ARMword
) ((long int) base
>> (int) shamt
));
3691 return ((base
>> 1) | (shamt
<< 31));
3695 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3696 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3700 return (0); /* just to shut up lint */
3703 /***************************************************************************\
3704 * This routine handles writes to register 15 when the S bit is not set. *
3705 \***************************************************************************/
3708 WriteR15 (ARMul_State
* state
, ARMword src
)
3710 /* The ARM documentation states that the two least significant bits
3711 are discarded when setting PC, except in the cases handled by
3712 WriteR15Branch() below. It's probably an oversight: in THUMB
3713 mode, the second least significant bit should probably not be
3722 state
->Reg
[15] = src
& PCBITS
;
3724 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
3725 ARMul_R15Altered (state
);
3730 /***************************************************************************\
3731 * This routine handles writes to register 15 when the S bit is set. *
3732 \***************************************************************************/
3735 WriteSR15 (ARMul_State
* state
, ARMword src
)
3738 if (state
->Bank
> 0)
3740 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3741 ARMul_CPSRAltered (state
);
3749 state
->Reg
[15] = src
& PCBITS
;
3753 abort (); /* ARMul_R15Altered would have to support it. */
3757 if (state
->Bank
== USERBANK
)
3758 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3760 state
->Reg
[15] = src
;
3761 ARMul_R15Altered (state
);
3766 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3767 will switch to Thumb mode if the least significant bit is set. */
3770 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3776 state
->Reg
[15] = src
& 0xfffffffe;
3781 state
->Reg
[15] = src
& 0xfffffffc;
3785 WriteR15 (state
, src
);
3789 /***************************************************************************\
3790 * This routine evaluates most Load and Store register RHS's. It is *
3791 * intended to be called from the macro LSRegRHS, which filters the *
3792 * common case of an unshifted register with in line code *
3793 \***************************************************************************/
3796 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3798 ARMword shamt
, base
;
3803 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3806 base
= state
->Reg
[base
];
3808 shamt
= BITS (7, 11);
3809 switch ((int) BITS (5, 6))
3812 return (base
<< shamt
);
3817 return (base
>> shamt
);
3820 return ((ARMword
) ((long int) base
>> 31L));
3822 return ((ARMword
) ((long int) base
>> (int) shamt
));
3824 if (shamt
== 0) /* its an RRX */
3825 return ((base
>> 1) | (CFLAG
<< 31));
3827 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3829 return (0); /* just to shut up lint */
3832 /***************************************************************************\
3833 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3834 \***************************************************************************/
3837 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3843 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3845 return state
->Reg
[RHSReg
];
3848 /* else immediate */
3849 return BITS (0, 3) | (BITS (8, 11) << 4);
3852 /***************************************************************************\
3853 * This function does the work of loading a word for a LDR instruction. *
3854 \***************************************************************************/
3857 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3863 if (ADDREXCEPT (address
))
3865 INTERNALABORT (address
);
3868 dest
= ARMul_LoadWordN (state
, address
);
3872 return (state
->lateabtSig
);
3875 dest
= ARMul_Align (state
, address
, dest
);
3877 ARMul_Icycles (state
, 1, 0L);
3879 return (DESTReg
!= LHSReg
);
3883 /***************************************************************************\
3884 * This function does the work of loading a halfword. *
3885 \***************************************************************************/
3888 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3895 if (ADDREXCEPT (address
))
3897 INTERNALABORT (address
);
3900 dest
= ARMul_LoadHalfWord (state
, address
);
3904 return (state
->lateabtSig
);
3909 if (dest
& 1 << (16 - 1))
3910 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3913 ARMul_Icycles (state
, 1, 0L);
3914 return (DESTReg
!= LHSReg
);
3919 /***************************************************************************\
3920 * This function does the work of loading a byte for a LDRB instruction. *
3921 \***************************************************************************/
3924 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3930 if (ADDREXCEPT (address
))
3932 INTERNALABORT (address
);
3935 dest
= ARMul_LoadByte (state
, address
);
3939 return (state
->lateabtSig
);
3944 if (dest
& 1 << (8 - 1))
3945 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3948 ARMul_Icycles (state
, 1, 0L);
3949 return (DESTReg
!= LHSReg
);
3952 /***************************************************************************\
3953 * This function does the work of loading two words for a LDRD instruction. *
3954 \***************************************************************************/
3957 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
3961 ARMword write_back
= BIT (21);
3962 ARMword immediate
= BIT (22);
3963 ARMword add_to_base
= BIT (23);
3964 ARMword pre_indexed
= BIT (24);
3974 /* If the writeback bit is set, the pre-index bit must be clear. */
3975 if (write_back
&& ! pre_indexed
)
3977 ARMul_UndefInstr (state
, instr
);
3981 /* Extract the base address register. */
3984 /* Extract the destination register and check it. */
3987 /* Destination register must be even. */
3989 /* Destination register cannot be LR. */
3990 || (dest_reg
== 14))
3992 ARMul_UndefInstr (state
, instr
);
3996 /* Compute the base address. */
3997 base
= state
->Reg
[addr_reg
];
3999 /* Compute the offset. */
4000 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4002 /* Compute the sum of the two. */
4004 sum
= base
+ offset
;
4006 sum
= base
- offset
;
4008 /* If this is a pre-indexed mode use the sum. */
4014 /* The address must be aligned on a 8 byte boundary. */
4018 ARMul_DATAABORT (addr
);
4020 ARMul_UndefInstr (state
, instr
);
4025 /* For pre indexed or post indexed addressing modes,
4026 check that the destination registers do not overlap
4027 the address registers. */
4028 if ((! pre_indexed
|| write_back
)
4029 && ( addr_reg
== dest_reg
4030 || addr_reg
== dest_reg
+ 1))
4032 ARMul_UndefInstr (state
, instr
);
4036 /* Load the words. */
4037 value1
= ARMul_LoadWordN (state
, addr
);
4038 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4040 /* Check for data aborts. */
4047 ARMul_Icycles (state
, 2, 0L);
4049 /* Store the values. */
4050 state
->Reg
[dest_reg
] = value1
;
4051 state
->Reg
[dest_reg
+ 1] = value2
;
4053 /* Do the post addressing and writeback. */
4057 if (! pre_indexed
|| write_back
)
4058 state
->Reg
[addr_reg
] = addr
;
4061 /***************************************************************************\
4062 * This function does the work of storing two words for a STRD instruction. *
4063 \***************************************************************************/
4066 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4070 ARMword write_back
= BIT (21);
4071 ARMword immediate
= BIT (22);
4072 ARMword add_to_base
= BIT (23);
4073 ARMword pre_indexed
= BIT (24);
4081 /* If the writeback bit is set, the pre-index bit must be clear. */
4082 if (write_back
&& ! pre_indexed
)
4084 ARMul_UndefInstr (state
, instr
);
4088 /* Extract the base address register. */
4091 /* Base register cannot be PC. */
4094 ARMul_UndefInstr (state
, instr
);
4098 /* Extract the source register. */
4101 /* Source register must be even. */
4104 ARMul_UndefInstr (state
, instr
);
4108 /* Compute the base address. */
4109 base
= state
->Reg
[addr_reg
];
4111 /* Compute the offset. */
4112 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4114 /* Compute the sum of the two. */
4116 sum
= base
+ offset
;
4118 sum
= base
- offset
;
4120 /* If this is a pre-indexed mode use the sum. */
4126 /* The address must be aligned on a 8 byte boundary. */
4130 ARMul_DATAABORT (addr
);
4132 ARMul_UndefInstr (state
, instr
);
4137 /* For pre indexed or post indexed addressing modes,
4138 check that the destination registers do not overlap
4139 the address registers. */
4140 if ((! pre_indexed
|| write_back
)
4141 && ( addr_reg
== src_reg
4142 || addr_reg
== src_reg
+ 1))
4144 ARMul_UndefInstr (state
, instr
);
4148 /* Load the words. */
4149 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4150 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4158 /* Do the post addressing and writeback. */
4162 if (! pre_indexed
|| write_back
)
4163 state
->Reg
[addr_reg
] = addr
;
4166 /***************************************************************************\
4167 * This function does the work of storing a word from a STR instruction. *
4168 \***************************************************************************/
4171 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4176 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4179 ARMul_StoreWordN (state
, address
, DEST
);
4181 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4183 INTERNALABORT (address
);
4184 (void) ARMul_LoadWordN (state
, address
);
4187 ARMul_StoreWordN (state
, address
, DEST
);
4192 return (state
->lateabtSig
);
4198 /***************************************************************************\
4199 * This function does the work of storing a byte for a STRH instruction. *
4200 \***************************************************************************/
4203 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4209 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4213 ARMul_StoreHalfWord (state
, address
, DEST
);
4215 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4217 INTERNALABORT (address
);
4218 (void) ARMul_LoadHalfWord (state
, address
);
4221 ARMul_StoreHalfWord (state
, address
, DEST
);
4227 return (state
->lateabtSig
);
4235 /***************************************************************************\
4236 * This function does the work of storing a byte for a STRB instruction. *
4237 \***************************************************************************/
4240 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4245 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4248 ARMul_StoreByte (state
, address
, DEST
);
4250 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4252 INTERNALABORT (address
);
4253 (void) ARMul_LoadByte (state
, address
);
4256 ARMul_StoreByte (state
, address
, DEST
);
4261 return (state
->lateabtSig
);
4267 /***************************************************************************\
4268 * This function does the work of loading the registers listed in an LDM *
4269 * instruction, when the S bit is clear. The code here is always increment *
4270 * after, it's up to the caller to get the input address correct and to *
4271 * handle base register modification. *
4272 \***************************************************************************/
4275 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4281 UNDEF_LSMBaseInListWb
;
4284 if (ADDREXCEPT (address
))
4286 INTERNALABORT (address
);
4289 if (BIT (21) && LHSReg
!= 15)
4292 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4293 dest
= ARMul_LoadWordN (state
, address
);
4294 if (!state
->abortSig
&& !state
->Aborted
)
4295 state
->Reg
[temp
++] = dest
;
4296 else if (!state
->Aborted
)
4298 state
->Aborted
= ARMul_DataAbortV
;
4301 for (; temp
< 16; temp
++) /* S cycles from here on */
4303 { /* load this register */
4305 dest
= ARMul_LoadWordS (state
, address
);
4306 if (!state
->abortSig
&& !state
->Aborted
)
4307 state
->Reg
[temp
] = dest
;
4308 else if (!state
->Aborted
)
4310 state
->Aborted
= ARMul_DataAbortV
;
4314 if (BIT (15) && !state
->Aborted
)
4315 { /* PC is in the reg list */
4316 WriteR15Branch(state
, PC
);
4319 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
4323 if (BIT (21) && LHSReg
!= 15)
4329 /***************************************************************************\
4330 * This function does the work of loading the registers listed in an LDM *
4331 * instruction, when the S bit is set. The code here is always increment *
4332 * after, it's up to the caller to get the input address correct and to *
4333 * handle base register modification. *
4334 \***************************************************************************/
4337 LoadSMult (ARMul_State
* state
,
4346 UNDEF_LSMBaseInListWb
;
4351 if (ADDREXCEPT (address
))
4353 INTERNALABORT (address
);
4357 if (BIT (21) && LHSReg
!= 15)
4360 if (!BIT (15) && state
->Bank
!= USERBANK
)
4362 /* Temporary reg bank switch. */
4363 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4364 UNDEF_LSMUserBankWb
;
4367 for (temp
= 0; !BIT (temp
); temp
++)
4368 ; /* N cycle first. */
4370 dest
= ARMul_LoadWordN (state
, address
);
4372 if (!state
->abortSig
)
4373 state
->Reg
[temp
++] = dest
;
4374 else if (!state
->Aborted
)
4376 state
->Aborted
= ARMul_DataAbortV
;
4379 for (; temp
< 16; temp
++)
4380 /* S cycles from here on. */
4383 /* Load this register. */
4385 dest
= ARMul_LoadWordS (state
, address
);
4387 if (!state
->abortSig
&& !state
->Aborted
)
4388 state
->Reg
[temp
] = dest
;
4389 else if (!state
->Aborted
)
4391 state
->Aborted
= ARMul_DataAbortV
;
4395 if (BIT (15) && !state
->Aborted
)
4397 /* PC is in the reg list. */
4399 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4401 state
->Cpsr
= GETSPSR (state
->Bank
);
4402 ARMul_CPSRAltered (state
);
4405 WriteR15 (state
, PC
);
4407 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4409 /* Protect bits in user mode. */
4410 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4411 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4412 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4413 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4416 ARMul_R15Altered (state
);
4422 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4423 /* Restore the correct bank. */
4424 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4426 /* To write back the final register. */
4427 ARMul_Icycles (state
, 1, 0L);
4431 if (BIT (21) && LHSReg
!= 15)
4438 /***************************************************************************\
4439 * This function does the work of storing the registers listed in an STM *
4440 * instruction, when the S bit is clear. The code here is always increment *
4441 * after, it's up to the caller to get the input address correct and to *
4442 * handle base register modification. *
4443 \***************************************************************************/
4446 StoreMult (ARMul_State
* state
, ARMword instr
,
4447 ARMword address
, ARMword WBBase
)
4453 UNDEF_LSMBaseInListWb
;
4456 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
4460 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4462 INTERNALABORT (address
);
4468 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4470 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4474 (void) ARMul_LoadWordN (state
, address
);
4475 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
4477 { /* save this register */
4479 (void) ARMul_LoadWordS (state
, address
);
4481 if (BIT (21) && LHSReg
!= 15)
4487 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4490 if (state
->abortSig
&& !state
->Aborted
)
4492 state
->Aborted
= ARMul_DataAbortV
;
4495 if (BIT (21) && LHSReg
!= 15)
4498 for (; temp
< 16; temp
++) /* S cycles from here on */
4500 { /* save this register */
4503 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4505 if (state
->abortSig
&& !state
->Aborted
)
4507 state
->Aborted
= ARMul_DataAbortV
;
4517 /***************************************************************************\
4518 * This function does the work of storing the registers listed in an STM *
4519 * instruction when the S bit is set. The code here is always increment *
4520 * after, it's up to the caller to get the input address correct and to *
4521 * handle base register modification. *
4522 \***************************************************************************/
4525 StoreSMult (ARMul_State
* state
,
4534 UNDEF_LSMBaseInListWb
;
4539 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4541 INTERNALABORT (address
);
4548 if (state
->Bank
!= USERBANK
)
4550 /* Force User Bank. */
4551 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4552 UNDEF_LSMUserBankWb
;
4555 for (temp
= 0; !BIT (temp
); temp
++)
4556 ; /* N cycle first. */
4559 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4563 (void) ARMul_LoadWordN (state
, address
);
4565 for (; temp
< 16; temp
++)
4566 /* Fake the Stores as Loads. */
4569 /* Save this register. */
4572 (void) ARMul_LoadWordS (state
, address
);
4575 if (BIT (21) && LHSReg
!= 15)
4583 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4586 if (state
->abortSig
&& !state
->Aborted
)
4588 state
->Aborted
= ARMul_DataAbortV
;
4591 for (; temp
< 16; temp
++)
4592 /* S cycles from here on. */
4595 /* Save this register. */
4598 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4600 if (state
->abortSig
&& !state
->Aborted
)
4602 state
->Aborted
= ARMul_DataAbortV
;
4606 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4607 /* Restore the correct bank. */
4608 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4610 if (BIT (21) && LHSReg
!= 15)
4619 /***************************************************************************\
4620 * This function does the work of adding two 32bit values together, and *
4621 * calculating if a carry has occurred. *
4622 \***************************************************************************/
4625 Add32 (ARMword a1
, ARMword a2
, int *carry
)
4627 ARMword result
= (a1
+ a2
);
4628 unsigned int uresult
= (unsigned int) result
;
4629 unsigned int ua1
= (unsigned int) a1
;
4631 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4632 or (result > RdLo) then we have no carry: */
4633 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
4641 /***************************************************************************\
4642 * This function does the work of multiplying two 32bit values to give a *
4644 \***************************************************************************/
4647 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4649 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
4650 ARMword RdHi
= 0, RdLo
= 0, Rm
;
4651 int scount
; /* cycle count */
4653 nRdHi
= BITS (16, 19);
4654 nRdLo
= BITS (12, 15);
4658 /* Needed to calculate the cycle count: */
4659 Rm
= state
->Reg
[nRm
];
4661 /* Check for illegal operand combinations first: */
4665 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
4667 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
4669 ARMword Rs
= state
->Reg
[nRs
];
4674 /* Compute sign of result and adjust operands if necessary. */
4676 sign
= (Rm
^ Rs
) & 0x80000000;
4678 if (((signed long) Rm
) < 0)
4681 if (((signed long) Rs
) < 0)
4685 /* We can split the 32x32 into four 16x16 operations. This ensures
4686 that we do not lose precision on 32bit only hosts: */
4687 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
4688 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4689 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
4690 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4692 /* We now need to add all of these results together, taking care
4693 to propogate the carries from the additions: */
4694 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
4696 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
4698 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
4702 /* Negate result if necessary. */
4706 if (RdLo
== 0xFFFFFFFF)
4715 state
->Reg
[nRdLo
] = RdLo
;
4716 state
->Reg
[nRdHi
] = RdHi
;
4717 } /* else undefined result */
4719 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4723 /* Ensure that both RdHi and RdLo are used to compute Z, but
4724 don't let RdLo's sign bit make it to N. */
4725 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4728 /* The cycle count depends on whether the instruction is a signed or
4729 unsigned multiply, and what bits are clear in the multiplier: */
4730 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
4731 Rm
= ~Rm
; /* invert the bits to make the check against zero */
4733 if ((Rm
& 0xFFFFFF00) == 0)
4735 else if ((Rm
& 0xFFFF0000) == 0)
4737 else if ((Rm
& 0xFF000000) == 0)
4745 /***************************************************************************\
4746 * This function does the work of multiplying two 32bit values and adding *
4747 * a 64bit value to give a 64bit result. *
4748 \***************************************************************************/
4751 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4758 nRdHi
= BITS (16, 19);
4759 nRdLo
= BITS (12, 15);
4761 RdHi
= state
->Reg
[nRdHi
];
4762 RdLo
= state
->Reg
[nRdLo
];
4764 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
4766 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
4767 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
4769 state
->Reg
[nRdLo
] = RdLo
;
4770 state
->Reg
[nRdHi
] = RdHi
;
4774 /* Ensure that both RdHi and RdLo are used to compute Z, but
4775 don't let RdLo's sign bit make it to N. */
4776 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4779 return scount
+ 1; /* extra cycle for addition */