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 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
1386 /* MSR reg to CPSR */
1390 /* Don't allow TBIT to be set by MSR. */
1393 ARMul_FixCPSR (state
, instr
, temp
);
1401 case 0x13: /* TEQP reg */
1403 if ((BITS (4, 11) & 0xF9) == 0x9)
1405 /* LDR register offset, write-back, down, pre indexed */
1407 /* continue with remaining instruction decode */
1413 state
->Cpsr
= GETSPSR (state
->Bank
);
1414 ARMul_CPSRAltered (state
);
1425 ARMul_NegZero (state
, dest
);
1429 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1432 if (BIT (4) == 0 && BIT (7) == 1)
1434 /* ElSegundo SMLALxy insn. */
1435 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1436 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1437 unsigned long long dest
;
1438 unsigned long long result
;
1451 dest
= (unsigned long long) state
->Reg
[BITS (16, 19)] << 32;
1452 dest
|= state
->Reg
[BITS (12, 15)];
1454 state
->Reg
[BITS (12, 15)] = dest
;
1455 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1459 if (BITS (4, 11) == 5)
1461 /* ElSegundo QDADD insn. */
1462 ARMword op1
= state
->Reg
[BITS (0, 3)];
1463 ARMword op2
= state
->Reg
[BITS (16, 19)];
1464 ARMword op2d
= op2
+ op2
;
1467 if (AddOverflow (op2
, op2
, op2d
))
1470 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1473 result
= op1
+ op2d
;
1474 if (AddOverflow (op1
, op2d
, result
))
1477 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1480 state
->Reg
[BITS (12, 15)] = result
;
1485 if (BITS (4, 7) == 0xB)
1487 /* STRH immediate offset, no write-back, down, pre indexed */
1491 if (BITS (4, 7) == 0xD)
1493 Handle_Load_Double (state
, instr
);
1496 if (BITS (4, 7) == 0xF)
1498 Handle_Store_Double (state
, instr
);
1502 if (BITS (4, 11) == 9)
1508 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1510 INTERNALABORT (temp
);
1511 (void) ARMul_LoadByte (state
, temp
);
1512 (void) ARMul_LoadByte (state
, temp
);
1516 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1517 if (state
->abortSig
|| state
->Aborted
)
1522 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1525 DEST
= GETSPSR (state
->Bank
);
1533 case 0x15: /* CMPP reg */
1535 if ((BITS (4, 7) & 0x9) == 0x9)
1537 /* LDR immediate offset, no write-back, down, pre indexed */
1539 /* continue with remaining instruction decode */
1545 state
->Cpsr
= GETSPSR (state
->Bank
);
1546 ARMul_CPSRAltered (state
);
1558 ARMul_NegZero (state
, dest
);
1559 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1561 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1562 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1572 case 0x16: /* CMN reg and MSR reg to SPSR */
1575 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1577 /* ElSegundo SMULxy insn. */
1578 ARMword op1
= state
->Reg
[BITS (0, 3)];
1579 ARMword op2
= state
->Reg
[BITS (8, 11)];
1580 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1593 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1597 if (BITS (4, 11) == 5)
1599 /* ElSegundo QDSUB insn. */
1600 ARMword op1
= state
->Reg
[BITS (0, 3)];
1601 ARMword op2
= state
->Reg
[BITS (16, 19)];
1602 ARMword op2d
= op2
+ op2
;
1605 if (AddOverflow (op2
, op2
, op2d
))
1608 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1611 result
= op1
- op2d
;
1612 if (SubOverflow (op1
, op2d
, result
))
1615 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1618 state
->Reg
[BITS (12, 15)] = result
;
1625 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1627 /* ARM5 CLZ insn. */
1628 ARMword op1
= state
->Reg
[BITS (0, 3)];
1632 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1635 state
->Reg
[BITS (12, 15)] = result
;
1640 if (BITS (4, 7) == 0xB)
1642 /* STRH immediate offset, write-back, down, pre indexed */
1646 if (BITS (4, 7) == 0xD)
1648 Handle_Load_Double (state
, instr
);
1651 if (BITS (4, 7) == 0xF)
1653 Handle_Store_Double (state
, instr
);
1660 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1668 case 0x17: /* CMNP reg */
1670 if ((BITS (4, 7) & 0x9) == 0x9)
1672 /* LDR immediate offset, write-back, down, pre indexed */
1674 /* continue with remaining instruction decoding */
1680 state
->Cpsr
= GETSPSR (state
->Bank
);
1681 ARMul_CPSRAltered (state
);
1694 ASSIGNZ (dest
== 0);
1695 if ((lhs
| rhs
) >> 30)
1696 { /* possible C,V,N to set */
1697 ASSIGNN (NEG (dest
));
1698 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1699 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1710 case 0x18: /* ORR reg */
1712 if (BITS (4, 11) == 0xB)
1714 /* STRH register offset, no write-back, up, pre indexed */
1718 if (BITS (4, 7) == 0xD)
1720 Handle_Load_Double (state
, instr
);
1723 if (BITS (4, 7) == 0xF)
1725 Handle_Store_Double (state
, instr
);
1734 case 0x19: /* ORRS reg */
1736 if ((BITS (4, 11) & 0xF9) == 0x9)
1738 /* LDR register offset, no write-back, up, pre indexed */
1740 /* continue with remaining instruction decoding */
1748 case 0x1a: /* MOV reg */
1750 if (BITS (4, 11) == 0xB)
1752 /* STRH register offset, write-back, up, pre indexed */
1756 if (BITS (4, 7) == 0xD)
1758 Handle_Load_Double (state
, instr
);
1761 if (BITS (4, 7) == 0xF)
1763 Handle_Store_Double (state
, instr
);
1771 case 0x1b: /* MOVS reg */
1773 if ((BITS (4, 11) & 0xF9) == 0x9)
1775 /* LDR register offset, write-back, up, pre indexed */
1777 /* continue with remaining instruction decoding */
1784 case 0x1c: /* BIC reg */
1786 if (BITS (4, 7) == 0xB)
1788 /* STRH immediate offset, no write-back, up, pre indexed */
1792 if (BITS (4, 7) == 0xD)
1794 Handle_Load_Double (state
, instr
);
1797 else if (BITS (4, 7) == 0xF)
1799 Handle_Store_Double (state
, instr
);
1808 case 0x1d: /* BICS reg */
1810 if ((BITS (4, 7) & 0x9) == 0x9)
1812 /* LDR immediate offset, no write-back, up, pre indexed */
1814 /* continue with instruction decoding */
1822 case 0x1e: /* MVN reg */
1824 if (BITS (4, 7) == 0xB)
1826 /* STRH immediate offset, write-back, up, pre indexed */
1830 if (BITS (4, 7) == 0xD)
1832 Handle_Load_Double (state
, instr
);
1835 if (BITS (4, 7) == 0xF)
1837 Handle_Store_Double (state
, instr
);
1845 case 0x1f: /* MVNS reg */
1847 if ((BITS (4, 7) & 0x9) == 0x9)
1849 /* LDR immediate offset, write-back, up, pre indexed */
1851 /* continue instruction decoding */
1858 /***************************************************************************\
1859 * Data Processing Immediate RHS Instructions *
1860 \***************************************************************************/
1862 case 0x20: /* AND immed */
1863 dest
= LHS
& DPImmRHS
;
1867 case 0x21: /* ANDS immed */
1873 case 0x22: /* EOR immed */
1874 dest
= LHS
^ DPImmRHS
;
1878 case 0x23: /* EORS immed */
1884 case 0x24: /* SUB immed */
1885 dest
= LHS
- DPImmRHS
;
1889 case 0x25: /* SUBS immed */
1893 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1895 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1896 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1906 case 0x26: /* RSB immed */
1907 dest
= DPImmRHS
- LHS
;
1911 case 0x27: /* RSBS immed */
1915 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1917 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1918 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1928 case 0x28: /* ADD immed */
1929 dest
= LHS
+ DPImmRHS
;
1933 case 0x29: /* ADDS immed */
1937 ASSIGNZ (dest
== 0);
1938 if ((lhs
| rhs
) >> 30)
1939 { /* possible C,V,N to set */
1940 ASSIGNN (NEG (dest
));
1941 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1942 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1953 case 0x2a: /* ADC immed */
1954 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1958 case 0x2b: /* ADCS immed */
1961 dest
= lhs
+ rhs
+ CFLAG
;
1962 ASSIGNZ (dest
== 0);
1963 if ((lhs
| rhs
) >> 30)
1964 { /* possible C,V,N to set */
1965 ASSIGNN (NEG (dest
));
1966 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1967 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1978 case 0x2c: /* SBC immed */
1979 dest
= LHS
- DPImmRHS
- !CFLAG
;
1983 case 0x2d: /* SBCS immed */
1986 dest
= lhs
- rhs
- !CFLAG
;
1987 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1989 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1990 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2000 case 0x2e: /* RSC immed */
2001 dest
= DPImmRHS
- LHS
- !CFLAG
;
2005 case 0x2f: /* RSCS immed */
2008 dest
= rhs
- lhs
- !CFLAG
;
2009 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2011 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2012 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2022 case 0x30: /* TST immed */
2026 case 0x31: /* TSTP immed */
2030 state
->Cpsr
= GETSPSR (state
->Bank
);
2031 ARMul_CPSRAltered (state
);
2033 temp
= LHS
& DPImmRHS
;
2039 DPSImmRHS
; /* TST immed */
2041 ARMul_NegZero (state
, dest
);
2045 case 0x32: /* TEQ immed and MSR immed to CPSR */
2047 { /* MSR immed to CPSR */
2048 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2056 case 0x33: /* TEQP immed */
2060 state
->Cpsr
= GETSPSR (state
->Bank
);
2061 ARMul_CPSRAltered (state
);
2063 temp
= LHS
^ DPImmRHS
;
2069 DPSImmRHS
; /* TEQ immed */
2071 ARMul_NegZero (state
, dest
);
2075 case 0x34: /* CMP immed */
2079 case 0x35: /* CMPP immed */
2083 state
->Cpsr
= GETSPSR (state
->Bank
);
2084 ARMul_CPSRAltered (state
);
2086 temp
= LHS
- DPImmRHS
;
2093 lhs
= LHS
; /* CMP immed */
2096 ARMul_NegZero (state
, dest
);
2097 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2099 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2100 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2110 case 0x36: /* CMN immed and MSR immed to SPSR */
2111 if (DESTReg
== 15) /* MSR */
2112 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2119 case 0x37: /* CMNP immed */
2123 state
->Cpsr
= GETSPSR (state
->Bank
);
2124 ARMul_CPSRAltered (state
);
2126 temp
= LHS
+ DPImmRHS
;
2133 lhs
= LHS
; /* CMN immed */
2136 ASSIGNZ (dest
== 0);
2137 if ((lhs
| rhs
) >> 30)
2138 { /* possible C,V,N to set */
2139 ASSIGNN (NEG (dest
));
2140 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2141 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2152 case 0x38: /* ORR immed */
2153 dest
= LHS
| DPImmRHS
;
2157 case 0x39: /* ORRS immed */
2163 case 0x3a: /* MOV immed */
2168 case 0x3b: /* MOVS immed */
2173 case 0x3c: /* BIC immed */
2174 dest
= LHS
& ~DPImmRHS
;
2178 case 0x3d: /* BICS immed */
2184 case 0x3e: /* MVN immed */
2189 case 0x3f: /* MVNS immed */
2194 /***************************************************************************\
2195 * Single Data Transfer Immediate RHS Instructions *
2196 \***************************************************************************/
2198 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
2200 if (StoreWord (state
, instr
, lhs
))
2201 LSBase
= lhs
- LSImmRHS
;
2204 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
2206 if (LoadWord (state
, instr
, lhs
))
2207 LSBase
= lhs
- LSImmRHS
;
2210 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
2211 UNDEF_LSRBaseEQDestWb
;
2214 temp
= lhs
- LSImmRHS
;
2215 state
->NtransSig
= LOW
;
2216 if (StoreWord (state
, instr
, lhs
))
2218 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2221 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
2222 UNDEF_LSRBaseEQDestWb
;
2225 state
->NtransSig
= LOW
;
2226 if (LoadWord (state
, instr
, lhs
))
2227 LSBase
= lhs
- LSImmRHS
;
2228 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2231 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
2233 if (StoreByte (state
, instr
, lhs
))
2234 LSBase
= lhs
- LSImmRHS
;
2237 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
2239 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2240 LSBase
= lhs
- LSImmRHS
;
2243 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
2244 UNDEF_LSRBaseEQDestWb
;
2247 state
->NtransSig
= LOW
;
2248 if (StoreByte (state
, instr
, lhs
))
2249 LSBase
= lhs
- LSImmRHS
;
2250 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2253 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
2254 UNDEF_LSRBaseEQDestWb
;
2257 state
->NtransSig
= LOW
;
2258 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2259 LSBase
= lhs
- LSImmRHS
;
2260 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2263 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
2265 if (StoreWord (state
, instr
, lhs
))
2266 LSBase
= lhs
+ LSImmRHS
;
2269 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
2271 if (LoadWord (state
, instr
, lhs
))
2272 LSBase
= lhs
+ LSImmRHS
;
2275 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
2276 UNDEF_LSRBaseEQDestWb
;
2279 state
->NtransSig
= LOW
;
2280 if (StoreWord (state
, instr
, lhs
))
2281 LSBase
= lhs
+ LSImmRHS
;
2282 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2285 case 0x4b: /* Load Word, WriteBack, Post Inc, 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 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
2297 if (StoreByte (state
, instr
, lhs
))
2298 LSBase
= lhs
+ LSImmRHS
;
2301 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
2303 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2304 LSBase
= lhs
+ LSImmRHS
;
2307 case 0x4e: /* Store Byte, WriteBack, Post Inc, 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 0x4f: /* Load Byte, WriteBack, Post Inc, 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
;
2328 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
2329 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2332 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
2333 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2336 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
2337 UNDEF_LSRBaseEQDestWb
;
2339 temp
= LHS
- LSImmRHS
;
2340 if (StoreWord (state
, instr
, temp
))
2344 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
2345 UNDEF_LSRBaseEQDestWb
;
2347 temp
= LHS
- LSImmRHS
;
2348 if (LoadWord (state
, instr
, temp
))
2352 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
2353 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2356 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
2357 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2360 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
2361 UNDEF_LSRBaseEQDestWb
;
2363 temp
= LHS
- LSImmRHS
;
2364 if (StoreByte (state
, instr
, temp
))
2368 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
2369 UNDEF_LSRBaseEQDestWb
;
2371 temp
= LHS
- LSImmRHS
;
2372 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2376 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
2377 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2380 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
2381 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2384 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
2385 UNDEF_LSRBaseEQDestWb
;
2387 temp
= LHS
+ LSImmRHS
;
2388 if (StoreWord (state
, instr
, temp
))
2392 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
2393 UNDEF_LSRBaseEQDestWb
;
2395 temp
= LHS
+ LSImmRHS
;
2396 if (LoadWord (state
, instr
, temp
))
2400 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
2401 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2404 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
2405 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2408 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
2409 UNDEF_LSRBaseEQDestWb
;
2411 temp
= LHS
+ LSImmRHS
;
2412 if (StoreByte (state
, instr
, temp
))
2416 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
2417 UNDEF_LSRBaseEQDestWb
;
2419 temp
= LHS
+ LSImmRHS
;
2420 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2424 /***************************************************************************\
2425 * Single Data Transfer Register RHS Instructions *
2426 \***************************************************************************/
2428 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
2431 ARMul_UndefInstr (state
, instr
);
2434 UNDEF_LSRBaseEQOffWb
;
2435 UNDEF_LSRBaseEQDestWb
;
2439 if (StoreWord (state
, instr
, lhs
))
2440 LSBase
= lhs
- LSRegRHS
;
2443 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
2446 ARMul_UndefInstr (state
, instr
);
2449 UNDEF_LSRBaseEQOffWb
;
2450 UNDEF_LSRBaseEQDestWb
;
2454 temp
= lhs
- LSRegRHS
;
2455 if (LoadWord (state
, instr
, lhs
))
2459 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2462 ARMul_UndefInstr (state
, instr
);
2465 UNDEF_LSRBaseEQOffWb
;
2466 UNDEF_LSRBaseEQDestWb
;
2470 state
->NtransSig
= LOW
;
2471 if (StoreWord (state
, instr
, lhs
))
2472 LSBase
= lhs
- LSRegRHS
;
2473 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2476 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2479 ARMul_UndefInstr (state
, instr
);
2482 UNDEF_LSRBaseEQOffWb
;
2483 UNDEF_LSRBaseEQDestWb
;
2487 temp
= lhs
- LSRegRHS
;
2488 state
->NtransSig
= LOW
;
2489 if (LoadWord (state
, instr
, lhs
))
2491 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2494 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2497 ARMul_UndefInstr (state
, instr
);
2500 UNDEF_LSRBaseEQOffWb
;
2501 UNDEF_LSRBaseEQDestWb
;
2505 if (StoreByte (state
, instr
, lhs
))
2506 LSBase
= lhs
- LSRegRHS
;
2509 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2512 ARMul_UndefInstr (state
, instr
);
2515 UNDEF_LSRBaseEQOffWb
;
2516 UNDEF_LSRBaseEQDestWb
;
2520 temp
= lhs
- LSRegRHS
;
2521 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2525 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2528 ARMul_UndefInstr (state
, instr
);
2531 UNDEF_LSRBaseEQOffWb
;
2532 UNDEF_LSRBaseEQDestWb
;
2536 state
->NtransSig
= LOW
;
2537 if (StoreByte (state
, instr
, lhs
))
2538 LSBase
= lhs
- LSRegRHS
;
2539 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2542 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2545 ARMul_UndefInstr (state
, instr
);
2548 UNDEF_LSRBaseEQOffWb
;
2549 UNDEF_LSRBaseEQDestWb
;
2553 temp
= lhs
- LSRegRHS
;
2554 state
->NtransSig
= LOW
;
2555 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2557 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2560 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2563 ARMul_UndefInstr (state
, instr
);
2566 UNDEF_LSRBaseEQOffWb
;
2567 UNDEF_LSRBaseEQDestWb
;
2571 if (StoreWord (state
, instr
, lhs
))
2572 LSBase
= lhs
+ LSRegRHS
;
2575 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2578 ARMul_UndefInstr (state
, instr
);
2581 UNDEF_LSRBaseEQOffWb
;
2582 UNDEF_LSRBaseEQDestWb
;
2586 temp
= lhs
+ LSRegRHS
;
2587 if (LoadWord (state
, instr
, lhs
))
2591 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2594 ARMul_UndefInstr (state
, instr
);
2597 UNDEF_LSRBaseEQOffWb
;
2598 UNDEF_LSRBaseEQDestWb
;
2602 state
->NtransSig
= LOW
;
2603 if (StoreWord (state
, instr
, lhs
))
2604 LSBase
= lhs
+ LSRegRHS
;
2605 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2608 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2611 ARMul_UndefInstr (state
, instr
);
2614 UNDEF_LSRBaseEQOffWb
;
2615 UNDEF_LSRBaseEQDestWb
;
2619 temp
= lhs
+ LSRegRHS
;
2620 state
->NtransSig
= LOW
;
2621 if (LoadWord (state
, instr
, lhs
))
2623 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2626 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2629 ARMul_UndefInstr (state
, instr
);
2632 UNDEF_LSRBaseEQOffWb
;
2633 UNDEF_LSRBaseEQDestWb
;
2637 if (StoreByte (state
, instr
, lhs
))
2638 LSBase
= lhs
+ LSRegRHS
;
2641 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2644 ARMul_UndefInstr (state
, instr
);
2647 UNDEF_LSRBaseEQOffWb
;
2648 UNDEF_LSRBaseEQDestWb
;
2652 temp
= lhs
+ LSRegRHS
;
2653 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2657 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2660 ARMul_UndefInstr (state
, instr
);
2663 UNDEF_LSRBaseEQOffWb
;
2664 UNDEF_LSRBaseEQDestWb
;
2668 state
->NtransSig
= LOW
;
2669 if (StoreByte (state
, instr
, lhs
))
2670 LSBase
= lhs
+ LSRegRHS
;
2671 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2674 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2677 ARMul_UndefInstr (state
, instr
);
2680 UNDEF_LSRBaseEQOffWb
;
2681 UNDEF_LSRBaseEQDestWb
;
2685 temp
= lhs
+ LSRegRHS
;
2686 state
->NtransSig
= LOW
;
2687 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2689 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2693 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2696 ARMul_UndefInstr (state
, instr
);
2699 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2702 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2705 ARMul_UndefInstr (state
, instr
);
2708 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2711 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2714 ARMul_UndefInstr (state
, instr
);
2717 UNDEF_LSRBaseEQOffWb
;
2718 UNDEF_LSRBaseEQDestWb
;
2721 temp
= LHS
- LSRegRHS
;
2722 if (StoreWord (state
, instr
, temp
))
2726 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2729 ARMul_UndefInstr (state
, instr
);
2732 UNDEF_LSRBaseEQOffWb
;
2733 UNDEF_LSRBaseEQDestWb
;
2736 temp
= LHS
- LSRegRHS
;
2737 if (LoadWord (state
, instr
, temp
))
2741 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2744 ARMul_UndefInstr (state
, instr
);
2747 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2750 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2753 ARMul_UndefInstr (state
, instr
);
2756 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2759 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2762 ARMul_UndefInstr (state
, instr
);
2765 UNDEF_LSRBaseEQOffWb
;
2766 UNDEF_LSRBaseEQDestWb
;
2769 temp
= LHS
- LSRegRHS
;
2770 if (StoreByte (state
, instr
, temp
))
2774 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2777 ARMul_UndefInstr (state
, instr
);
2780 UNDEF_LSRBaseEQOffWb
;
2781 UNDEF_LSRBaseEQDestWb
;
2784 temp
= LHS
- LSRegRHS
;
2785 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2789 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2792 ARMul_UndefInstr (state
, instr
);
2795 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2798 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2801 ARMul_UndefInstr (state
, instr
);
2804 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2807 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2810 ARMul_UndefInstr (state
, instr
);
2813 UNDEF_LSRBaseEQOffWb
;
2814 UNDEF_LSRBaseEQDestWb
;
2817 temp
= LHS
+ LSRegRHS
;
2818 if (StoreWord (state
, instr
, temp
))
2822 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2825 ARMul_UndefInstr (state
, instr
);
2828 UNDEF_LSRBaseEQOffWb
;
2829 UNDEF_LSRBaseEQDestWb
;
2832 temp
= LHS
+ LSRegRHS
;
2833 if (LoadWord (state
, instr
, temp
))
2837 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2840 ARMul_UndefInstr (state
, instr
);
2843 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2846 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2849 ARMul_UndefInstr (state
, instr
);
2852 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2855 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2858 ARMul_UndefInstr (state
, instr
);
2861 UNDEF_LSRBaseEQOffWb
;
2862 UNDEF_LSRBaseEQDestWb
;
2865 temp
= LHS
+ LSRegRHS
;
2866 if (StoreByte (state
, instr
, temp
))
2870 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2873 /* Check for the special breakpoint opcode.
2874 This value should correspond to the value defined
2875 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2876 if (BITS (0, 19) == 0xfdefe)
2878 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2879 ARMul_Abort (state
, ARMul_SWIV
);
2882 ARMul_UndefInstr (state
, instr
);
2885 UNDEF_LSRBaseEQOffWb
;
2886 UNDEF_LSRBaseEQDestWb
;
2889 temp
= LHS
+ LSRegRHS
;
2890 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2894 /***************************************************************************\
2895 * Multiple Data Transfer Instructions *
2896 \***************************************************************************/
2898 case 0x80: /* Store, No WriteBack, Post Dec */
2899 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2902 case 0x81: /* Load, No WriteBack, Post Dec */
2903 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2906 case 0x82: /* Store, WriteBack, Post Dec */
2907 temp
= LSBase
- LSMNumRegs
;
2908 STOREMULT (instr
, temp
+ 4L, temp
);
2911 case 0x83: /* Load, WriteBack, Post Dec */
2912 temp
= LSBase
- LSMNumRegs
;
2913 LOADMULT (instr
, temp
+ 4L, temp
);
2916 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2917 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2920 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2921 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2924 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2925 temp
= LSBase
- LSMNumRegs
;
2926 STORESMULT (instr
, temp
+ 4L, temp
);
2929 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2930 temp
= LSBase
- LSMNumRegs
;
2931 LOADSMULT (instr
, temp
+ 4L, temp
);
2934 case 0x88: /* Store, No WriteBack, Post Inc */
2935 STOREMULT (instr
, LSBase
, 0L);
2938 case 0x89: /* Load, No WriteBack, Post Inc */
2939 LOADMULT (instr
, LSBase
, 0L);
2942 case 0x8a: /* Store, WriteBack, Post Inc */
2944 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
2947 case 0x8b: /* Load, WriteBack, Post Inc */
2949 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
2952 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2953 STORESMULT (instr
, LSBase
, 0L);
2956 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2957 LOADSMULT (instr
, LSBase
, 0L);
2960 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2962 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
2965 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2967 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
2970 case 0x90: /* Store, No WriteBack, Pre Dec */
2971 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2974 case 0x91: /* Load, No WriteBack, Pre Dec */
2975 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2978 case 0x92: /* Store, WriteBack, Pre Dec */
2979 temp
= LSBase
- LSMNumRegs
;
2980 STOREMULT (instr
, temp
, temp
);
2983 case 0x93: /* Load, WriteBack, Pre Dec */
2984 temp
= LSBase
- LSMNumRegs
;
2985 LOADMULT (instr
, temp
, temp
);
2988 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2989 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2992 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2993 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2996 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
2997 temp
= LSBase
- LSMNumRegs
;
2998 STORESMULT (instr
, temp
, temp
);
3001 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
3002 temp
= LSBase
- LSMNumRegs
;
3003 LOADSMULT (instr
, temp
, temp
);
3006 case 0x98: /* Store, No WriteBack, Pre Inc */
3007 STOREMULT (instr
, LSBase
+ 4L, 0L);
3010 case 0x99: /* Load, No WriteBack, Pre Inc */
3011 LOADMULT (instr
, LSBase
+ 4L, 0L);
3014 case 0x9a: /* Store, WriteBack, Pre Inc */
3016 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3019 case 0x9b: /* Load, WriteBack, Pre Inc */
3021 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3024 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
3025 STORESMULT (instr
, LSBase
+ 4L, 0L);
3028 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
3029 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3032 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
3034 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3037 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
3039 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3042 /***************************************************************************\
3044 \***************************************************************************/
3054 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3058 /***************************************************************************\
3060 \***************************************************************************/
3070 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3074 /***************************************************************************\
3075 * Branch and Link forward *
3076 \***************************************************************************/
3087 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3089 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3091 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3095 /***************************************************************************\
3096 * Branch and Link backward *
3097 \***************************************************************************/
3108 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3110 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3112 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3116 /***************************************************************************\
3117 * Co-Processor Data Transfers *
3118 \***************************************************************************/
3121 if (state
->is_XScale
)
3123 if (BITS (4, 7) != 0x00)
3124 ARMul_UndefInstr (state
, instr
);
3126 if (BITS (8, 11) != 0x00)
3127 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3129 /* XScale MAR insn. Move two registers into accumulator. */
3130 if (BITS (0, 3) == 0x00)
3132 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3133 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3136 /* Access to any other acc is unpredicatable. */
3141 case 0xc0: /* Store , No WriteBack , Post Dec */
3142 ARMul_STC (state
, instr
, LHS
);
3146 if (state
->is_XScale
)
3148 if (BITS (4, 7) != 0x00)
3149 ARMul_UndefInstr (state
, instr
);
3151 if (BITS (8, 11) != 0x00)
3152 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3154 /* XScale MRA insn. Move accumulator into two registers. */
3155 if (BITS (0, 3) == 0x00)
3157 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3162 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3163 state
->Reg
[BITS (16, 19)] = t1
;
3166 /* Access to any other acc is unpredicatable. */
3171 case 0xc1: /* Load , No WriteBack , Post Dec */
3172 ARMul_LDC (state
, instr
, LHS
);
3176 case 0xc6: /* Store , WriteBack , Post Dec */
3178 state
->Base
= lhs
- LSCOff
;
3179 ARMul_STC (state
, instr
, lhs
);
3183 case 0xc7: /* Load , WriteBack , Post Dec */
3185 state
->Base
= lhs
- LSCOff
;
3186 ARMul_LDC (state
, instr
, lhs
);
3190 case 0xcc: /* Store , No WriteBack , Post Inc */
3191 ARMul_STC (state
, instr
, LHS
);
3195 case 0xcd: /* Load , No WriteBack , Post Inc */
3196 ARMul_LDC (state
, instr
, LHS
);
3200 case 0xce: /* Store , WriteBack , Post Inc */
3202 state
->Base
= lhs
+ LSCOff
;
3203 ARMul_STC (state
, instr
, LHS
);
3207 case 0xcf: /* Load , WriteBack , Post Inc */
3209 state
->Base
= lhs
+ LSCOff
;
3210 ARMul_LDC (state
, instr
, LHS
);
3215 case 0xd4: /* Store , No WriteBack , Pre Dec */
3216 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3220 case 0xd5: /* Load , No WriteBack , Pre Dec */
3221 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3225 case 0xd6: /* Store , WriteBack , Pre Dec */
3228 ARMul_STC (state
, instr
, lhs
);
3232 case 0xd7: /* Load , WriteBack , Pre Dec */
3235 ARMul_LDC (state
, instr
, lhs
);
3239 case 0xdc: /* Store , No WriteBack , Pre Inc */
3240 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3244 case 0xdd: /* Load , No WriteBack , Pre Inc */
3245 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3249 case 0xde: /* Store , WriteBack , Pre Inc */
3252 ARMul_STC (state
, instr
, lhs
);
3256 case 0xdf: /* Load , WriteBack , Pre Inc */
3259 ARMul_LDC (state
, instr
, lhs
);
3262 /***************************************************************************\
3263 * Co-Processor Register Transfers (MCR) and Data Ops *
3264 \***************************************************************************/
3267 if (state
->is_XScale
)
3268 switch (BITS (18, 19))
3272 /* XScale MIA instruction. Signed multiplication of two 32 bit
3273 values and addition to 40 bit accumulator. */
3274 long long Rm
= state
->Reg
[MULLHSReg
];
3275 long long Rs
= state
->Reg
[MULACCReg
];
3281 state
->Accumulator
+= Rm
* Rs
;
3287 /* XScale MIAPH instruction. */
3288 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3289 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3290 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3291 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3306 state
->Accumulator
+= t5
;
3311 state
->Accumulator
+= t5
;
3317 /* XScale MIAxy instruction. */
3323 t1
= state
->Reg
[MULLHSReg
] >> 16;
3325 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3328 t2
= state
->Reg
[MULACCReg
] >> 16;
3330 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3340 state
->Accumulator
+= t5
;
3362 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3364 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3365 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3369 ARMul_MCR (state
, instr
, DEST
);
3371 else /* CDP Part 1 */
3372 ARMul_CDP (state
, instr
);
3375 /***************************************************************************\
3376 * Co-Processor Register Transfers (MRC) and Data Ops *
3377 \***************************************************************************/
3389 temp
= ARMul_MRC (state
, instr
);
3392 ASSIGNN ((temp
& NBIT
) != 0);
3393 ASSIGNZ ((temp
& ZBIT
) != 0);
3394 ASSIGNC ((temp
& CBIT
) != 0);
3395 ASSIGNV ((temp
& VBIT
) != 0);
3400 else /* CDP Part 2 */
3401 ARMul_CDP (state
, instr
);
3404 /***************************************************************************\
3406 \***************************************************************************/
3424 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3426 /* A prefetch abort. */
3427 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3431 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3433 ARMul_Abort (state
, ARMul_SWIV
);
3436 } /* 256 way main switch */
3443 #ifdef NEED_UI_LOOP_HOOK
3444 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3446 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3449 #endif /* NEED_UI_LOOP_HOOK */
3451 if (state
->Emulate
== ONCE
)
3452 state
->Emulate
= STOP
;
3453 /* If we have changed mode, allow the PC to advance before stopping. */
3454 else if (state
->Emulate
== CHANGEMODE
)
3456 else if (state
->Emulate
!= RUN
)
3459 while (!stop_simulator
); /* do loop */
3461 state
->decoded
= decoded
;
3462 state
->loaded
= loaded
;
3466 } /* Emulate 26/32 in instruction based mode */
3469 /***************************************************************************\
3470 * This routine evaluates most Data Processing register RHS's with the S *
3471 * bit clear. It is intended to be called from the macro DPRegRHS, which *
3472 * filters the common case of an unshifted register with in line code *
3473 \***************************************************************************/
3476 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3478 ARMword shamt
, base
;
3482 { /* shift amount in a register */
3487 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3490 base
= state
->Reg
[base
];
3491 ARMul_Icycles (state
, 1, 0L);
3492 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3493 switch ((int) BITS (5, 6))
3498 else if (shamt
>= 32)
3501 return (base
<< shamt
);
3505 else if (shamt
>= 32)
3508 return (base
>> shamt
);
3512 else if (shamt
>= 32)
3513 return ((ARMword
) ((long int) base
>> 31L));
3515 return ((ARMword
) ((long int) base
>> (int) shamt
));
3521 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3525 { /* shift amount is a constant */
3528 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3531 base
= state
->Reg
[base
];
3532 shamt
= BITS (7, 11);
3533 switch ((int) BITS (5, 6))
3536 return (base
<< shamt
);
3541 return (base
>> shamt
);
3544 return ((ARMword
) ((long int) base
>> 31L));
3546 return ((ARMword
) ((long int) base
>> (int) shamt
));
3548 if (shamt
== 0) /* its an RRX */
3549 return ((base
>> 1) | (CFLAG
<< 31));
3551 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3554 return (0); /* just to shut up lint */
3557 /***************************************************************************\
3558 * This routine evaluates most Logical Data Processing register RHS's *
3559 * with the S bit set. It is intended to be called from the macro *
3560 * DPSRegRHS, which filters the common case of an unshifted register *
3561 * with in line code *
3562 \***************************************************************************/
3565 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3567 ARMword shamt
, base
;
3571 { /* shift amount in a register */
3576 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3579 base
= state
->Reg
[base
];
3580 ARMul_Icycles (state
, 1, 0L);
3581 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3582 switch ((int) BITS (5, 6))
3587 else if (shamt
== 32)
3592 else if (shamt
> 32)
3599 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3600 return (base
<< shamt
);
3605 else if (shamt
== 32)
3607 ASSIGNC (base
>> 31);
3610 else if (shamt
> 32)
3617 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3618 return (base
>> shamt
);
3623 else if (shamt
>= 32)
3625 ASSIGNC (base
>> 31L);
3626 return ((ARMword
) ((long int) base
>> 31L));
3630 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3631 return ((ARMword
) ((long int) base
>> (int) shamt
));
3639 ASSIGNC (base
>> 31);
3644 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3645 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3650 { /* shift amount is a constant */
3653 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3656 base
= state
->Reg
[base
];
3657 shamt
= BITS (7, 11);
3658 switch ((int) BITS (5, 6))
3661 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3662 return (base
<< shamt
);
3666 ASSIGNC (base
>> 31);
3671 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3672 return (base
>> shamt
);
3677 ASSIGNC (base
>> 31L);
3678 return ((ARMword
) ((long int) base
>> 31L));
3682 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3683 return ((ARMword
) ((long int) base
>> (int) shamt
));
3690 return ((base
>> 1) | (shamt
<< 31));
3694 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3695 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3699 return (0); /* just to shut up lint */
3702 /***************************************************************************\
3703 * This routine handles writes to register 15 when the S bit is not set. *
3704 \***************************************************************************/
3707 WriteR15 (ARMul_State
* state
, ARMword src
)
3709 /* The ARM documentation states that the two least significant bits
3710 are discarded when setting PC, except in the cases handled by
3711 WriteR15Branch() below. It's probably an oversight: in THUMB
3712 mode, the second least significant bit should probably not be
3721 state
->Reg
[15] = src
& PCBITS
;
3723 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
3724 ARMul_R15Altered (state
);
3729 /***************************************************************************\
3730 * This routine handles writes to register 15 when the S bit is set. *
3731 \***************************************************************************/
3734 WriteSR15 (ARMul_State
* state
, ARMword src
)
3737 if (state
->Bank
> 0)
3739 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3740 ARMul_CPSRAltered (state
);
3748 state
->Reg
[15] = src
& PCBITS
;
3752 abort (); /* ARMul_R15Altered would have to support it. */
3756 if (state
->Bank
== USERBANK
)
3757 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3759 state
->Reg
[15] = src
;
3760 ARMul_R15Altered (state
);
3765 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3766 will switch to Thumb mode if the least significant bit is set. */
3769 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3775 state
->Reg
[15] = src
& 0xfffffffe;
3780 state
->Reg
[15] = src
& 0xfffffffc;
3784 WriteR15 (state
, src
);
3788 /***************************************************************************\
3789 * This routine evaluates most Load and Store register RHS's. It is *
3790 * intended to be called from the macro LSRegRHS, which filters the *
3791 * common case of an unshifted register with in line code *
3792 \***************************************************************************/
3795 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3797 ARMword shamt
, base
;
3802 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3805 base
= state
->Reg
[base
];
3807 shamt
= BITS (7, 11);
3808 switch ((int) BITS (5, 6))
3811 return (base
<< shamt
);
3816 return (base
>> shamt
);
3819 return ((ARMword
) ((long int) base
>> 31L));
3821 return ((ARMword
) ((long int) base
>> (int) shamt
));
3823 if (shamt
== 0) /* its an RRX */
3824 return ((base
>> 1) | (CFLAG
<< 31));
3826 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3828 return (0); /* just to shut up lint */
3831 /***************************************************************************\
3832 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3833 \***************************************************************************/
3836 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3842 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3844 return state
->Reg
[RHSReg
];
3847 /* else immediate */
3848 return BITS (0, 3) | (BITS (8, 11) << 4);
3851 /***************************************************************************\
3852 * This function does the work of loading a word for a LDR instruction. *
3853 \***************************************************************************/
3856 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3862 if (ADDREXCEPT (address
))
3864 INTERNALABORT (address
);
3867 dest
= ARMul_LoadWordN (state
, address
);
3871 return (state
->lateabtSig
);
3874 dest
= ARMul_Align (state
, address
, dest
);
3876 ARMul_Icycles (state
, 1, 0L);
3878 return (DESTReg
!= LHSReg
);
3882 /***************************************************************************\
3883 * This function does the work of loading a halfword. *
3884 \***************************************************************************/
3887 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3894 if (ADDREXCEPT (address
))
3896 INTERNALABORT (address
);
3899 dest
= ARMul_LoadHalfWord (state
, address
);
3903 return (state
->lateabtSig
);
3908 if (dest
& 1 << (16 - 1))
3909 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3912 ARMul_Icycles (state
, 1, 0L);
3913 return (DESTReg
!= LHSReg
);
3918 /***************************************************************************\
3919 * This function does the work of loading a byte for a LDRB instruction. *
3920 \***************************************************************************/
3923 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3929 if (ADDREXCEPT (address
))
3931 INTERNALABORT (address
);
3934 dest
= ARMul_LoadByte (state
, address
);
3938 return (state
->lateabtSig
);
3943 if (dest
& 1 << (8 - 1))
3944 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3947 ARMul_Icycles (state
, 1, 0L);
3948 return (DESTReg
!= LHSReg
);
3951 /***************************************************************************\
3952 * This function does the work of loading two words for a LDRD instruction. *
3953 \***************************************************************************/
3956 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
3960 ARMword write_back
= BIT (21);
3961 ARMword immediate
= BIT (22);
3962 ARMword add_to_base
= BIT (23);
3963 ARMword pre_indexed
= BIT (24);
3973 /* If the writeback bit is set, the pre-index bit must be clear. */
3974 if (write_back
&& ! pre_indexed
)
3976 ARMul_UndefInstr (state
, instr
);
3980 /* Extract the base address register. */
3983 /* Extract the destination register and check it. */
3986 /* Destination register must be even. */
3988 /* Destination register cannot be LR. */
3989 || (dest_reg
== 14))
3991 ARMul_UndefInstr (state
, instr
);
3995 /* Compute the base address. */
3996 base
= state
->Reg
[addr_reg
];
3998 /* Compute the offset. */
3999 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4001 /* Compute the sum of the two. */
4003 sum
= base
+ offset
;
4005 sum
= base
- offset
;
4007 /* If this is a pre-indexed mode use the sum. */
4013 /* The address must be aligned on a 8 byte boundary. */
4017 ARMul_DATAABORT (addr
);
4019 ARMul_UndefInstr (state
, instr
);
4024 /* For pre indexed or post indexed addressing modes,
4025 check that the destination registers do not overlap
4026 the address registers. */
4027 if ((! pre_indexed
|| write_back
)
4028 && ( addr_reg
== dest_reg
4029 || addr_reg
== dest_reg
+ 1))
4031 ARMul_UndefInstr (state
, instr
);
4035 /* Load the words. */
4036 value1
= ARMul_LoadWordN (state
, addr
);
4037 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4039 /* Check for data aborts. */
4046 ARMul_Icycles (state
, 2, 0L);
4048 /* Store the values. */
4049 state
->Reg
[dest_reg
] = value1
;
4050 state
->Reg
[dest_reg
+ 1] = value2
;
4052 /* Do the post addressing and writeback. */
4056 if (! pre_indexed
|| write_back
)
4057 state
->Reg
[addr_reg
] = addr
;
4060 /***************************************************************************\
4061 * This function does the work of storing two words for a STRD instruction. *
4062 \***************************************************************************/
4065 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4069 ARMword write_back
= BIT (21);
4070 ARMword immediate
= BIT (22);
4071 ARMword add_to_base
= BIT (23);
4072 ARMword pre_indexed
= BIT (24);
4080 /* If the writeback bit is set, the pre-index bit must be clear. */
4081 if (write_back
&& ! pre_indexed
)
4083 ARMul_UndefInstr (state
, instr
);
4087 /* Extract the base address register. */
4090 /* Base register cannot be PC. */
4093 ARMul_UndefInstr (state
, instr
);
4097 /* Extract the source register. */
4100 /* Source register must be even. */
4103 ARMul_UndefInstr (state
, instr
);
4107 /* Compute the base address. */
4108 base
= state
->Reg
[addr_reg
];
4110 /* Compute the offset. */
4111 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4113 /* Compute the sum of the two. */
4115 sum
= base
+ offset
;
4117 sum
= base
- offset
;
4119 /* If this is a pre-indexed mode use the sum. */
4125 /* The address must be aligned on a 8 byte boundary. */
4129 ARMul_DATAABORT (addr
);
4131 ARMul_UndefInstr (state
, instr
);
4136 /* For pre indexed or post indexed addressing modes,
4137 check that the destination registers do not overlap
4138 the address registers. */
4139 if ((! pre_indexed
|| write_back
)
4140 && ( addr_reg
== src_reg
4141 || addr_reg
== src_reg
+ 1))
4143 ARMul_UndefInstr (state
, instr
);
4147 /* Load the words. */
4148 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4149 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4157 /* Do the post addressing and writeback. */
4161 if (! pre_indexed
|| write_back
)
4162 state
->Reg
[addr_reg
] = addr
;
4165 /***************************************************************************\
4166 * This function does the work of storing a word from a STR instruction. *
4167 \***************************************************************************/
4170 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4175 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4178 ARMul_StoreWordN (state
, address
, DEST
);
4180 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4182 INTERNALABORT (address
);
4183 (void) ARMul_LoadWordN (state
, address
);
4186 ARMul_StoreWordN (state
, address
, DEST
);
4191 return (state
->lateabtSig
);
4197 /***************************************************************************\
4198 * This function does the work of storing a byte for a STRH instruction. *
4199 \***************************************************************************/
4202 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4208 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4212 ARMul_StoreHalfWord (state
, address
, DEST
);
4214 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4216 INTERNALABORT (address
);
4217 (void) ARMul_LoadHalfWord (state
, address
);
4220 ARMul_StoreHalfWord (state
, address
, DEST
);
4226 return (state
->lateabtSig
);
4234 /***************************************************************************\
4235 * This function does the work of storing a byte for a STRB instruction. *
4236 \***************************************************************************/
4239 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4244 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4247 ARMul_StoreByte (state
, address
, DEST
);
4249 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4251 INTERNALABORT (address
);
4252 (void) ARMul_LoadByte (state
, address
);
4255 ARMul_StoreByte (state
, address
, DEST
);
4260 return (state
->lateabtSig
);
4266 /***************************************************************************\
4267 * This function does the work of loading the registers listed in an LDM *
4268 * instruction, when the S bit is clear. The code here is always increment *
4269 * after, it's up to the caller to get the input address correct and to *
4270 * handle base register modification. *
4271 \***************************************************************************/
4274 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4280 UNDEF_LSMBaseInListWb
;
4283 if (ADDREXCEPT (address
))
4285 INTERNALABORT (address
);
4288 if (BIT (21) && LHSReg
!= 15)
4291 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4292 dest
= ARMul_LoadWordN (state
, address
);
4293 if (!state
->abortSig
&& !state
->Aborted
)
4294 state
->Reg
[temp
++] = dest
;
4295 else if (!state
->Aborted
)
4297 state
->Aborted
= ARMul_DataAbortV
;
4300 for (; temp
< 16; temp
++) /* S cycles from here on */
4302 { /* load this register */
4304 dest
= ARMul_LoadWordS (state
, address
);
4305 if (!state
->abortSig
&& !state
->Aborted
)
4306 state
->Reg
[temp
] = dest
;
4307 else if (!state
->Aborted
)
4309 state
->Aborted
= ARMul_DataAbortV
;
4313 if (BIT (15) && !state
->Aborted
)
4314 { /* PC is in the reg list */
4315 WriteR15Branch(state
, PC
);
4318 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
4322 if (BIT (21) && LHSReg
!= 15)
4328 /***************************************************************************\
4329 * This function does the work of loading the registers listed in an LDM *
4330 * instruction, when the S bit is set. The code here is always increment *
4331 * after, it's up to the caller to get the input address correct and to *
4332 * handle base register modification. *
4333 \***************************************************************************/
4336 LoadSMult (ARMul_State
* state
,
4345 UNDEF_LSMBaseInListWb
;
4350 if (ADDREXCEPT (address
))
4352 INTERNALABORT (address
);
4356 if (BIT (21) && LHSReg
!= 15)
4359 if (!BIT (15) && state
->Bank
!= USERBANK
)
4361 /* Temporary reg bank switch. */
4362 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4363 UNDEF_LSMUserBankWb
;
4366 for (temp
= 0; !BIT (temp
); temp
++)
4367 ; /* N cycle first. */
4369 dest
= ARMul_LoadWordN (state
, address
);
4371 if (!state
->abortSig
)
4372 state
->Reg
[temp
++] = dest
;
4373 else if (!state
->Aborted
)
4375 state
->Aborted
= ARMul_DataAbortV
;
4378 for (; temp
< 16; temp
++)
4379 /* S cycles from here on. */
4382 /* Load this register. */
4384 dest
= ARMul_LoadWordS (state
, address
);
4386 if (!state
->abortSig
&& !state
->Aborted
)
4387 state
->Reg
[temp
] = dest
;
4388 else if (!state
->Aborted
)
4390 state
->Aborted
= ARMul_DataAbortV
;
4394 if (BIT (15) && !state
->Aborted
)
4396 /* PC is in the reg list. */
4398 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4400 state
->Cpsr
= GETSPSR (state
->Bank
);
4401 ARMul_CPSRAltered (state
);
4404 WriteR15 (state
, PC
);
4406 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4408 /* Protect bits in user mode. */
4409 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4410 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4411 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4412 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4415 ARMul_R15Altered (state
);
4421 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4422 /* Restore the correct bank. */
4423 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4425 /* To write back the final register. */
4426 ARMul_Icycles (state
, 1, 0L);
4430 if (BIT (21) && LHSReg
!= 15)
4437 /***************************************************************************\
4438 * This function does the work of storing the registers listed in an STM *
4439 * instruction, when the S bit is clear. The code here is always increment *
4440 * after, it's up to the caller to get the input address correct and to *
4441 * handle base register modification. *
4442 \***************************************************************************/
4445 StoreMult (ARMul_State
* state
, ARMword instr
,
4446 ARMword address
, ARMword WBBase
)
4452 UNDEF_LSMBaseInListWb
;
4455 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
4459 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4461 INTERNALABORT (address
);
4467 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4469 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4473 (void) ARMul_LoadWordN (state
, address
);
4474 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
4476 { /* save this register */
4478 (void) ARMul_LoadWordS (state
, address
);
4480 if (BIT (21) && LHSReg
!= 15)
4486 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4489 if (state
->abortSig
&& !state
->Aborted
)
4491 state
->Aborted
= ARMul_DataAbortV
;
4494 if (BIT (21) && LHSReg
!= 15)
4497 for (; temp
< 16; temp
++) /* S cycles from here on */
4499 { /* save this register */
4502 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4504 if (state
->abortSig
&& !state
->Aborted
)
4506 state
->Aborted
= ARMul_DataAbortV
;
4516 /***************************************************************************\
4517 * This function does the work of storing the registers listed in an STM *
4518 * instruction when the S bit is set. The code here is always increment *
4519 * after, it's up to the caller to get the input address correct and to *
4520 * handle base register modification. *
4521 \***************************************************************************/
4524 StoreSMult (ARMul_State
* state
,
4533 UNDEF_LSMBaseInListWb
;
4538 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4540 INTERNALABORT (address
);
4547 if (state
->Bank
!= USERBANK
)
4549 /* Force User Bank. */
4550 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4551 UNDEF_LSMUserBankWb
;
4554 for (temp
= 0; !BIT (temp
); temp
++)
4555 ; /* N cycle first. */
4558 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4562 (void) ARMul_LoadWordN (state
, address
);
4564 for (; temp
< 16; temp
++)
4565 /* Fake the Stores as Loads. */
4568 /* Save this register. */
4571 (void) ARMul_LoadWordS (state
, address
);
4574 if (BIT (21) && LHSReg
!= 15)
4582 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4585 if (state
->abortSig
&& !state
->Aborted
)
4587 state
->Aborted
= ARMul_DataAbortV
;
4590 for (; temp
< 16; temp
++)
4591 /* S cycles from here on. */
4594 /* Save this register. */
4597 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4599 if (state
->abortSig
&& !state
->Aborted
)
4601 state
->Aborted
= ARMul_DataAbortV
;
4605 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4606 /* Restore the correct bank. */
4607 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4609 if (BIT (21) && LHSReg
!= 15)
4618 /***************************************************************************\
4619 * This function does the work of adding two 32bit values together, and *
4620 * calculating if a carry has occurred. *
4621 \***************************************************************************/
4624 Add32 (ARMword a1
, ARMword a2
, int *carry
)
4626 ARMword result
= (a1
+ a2
);
4627 unsigned int uresult
= (unsigned int) result
;
4628 unsigned int ua1
= (unsigned int) a1
;
4630 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4631 or (result > RdLo) then we have no carry: */
4632 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
4640 /***************************************************************************\
4641 * This function does the work of multiplying two 32bit values to give a *
4643 \***************************************************************************/
4646 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4648 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
4649 ARMword RdHi
= 0, RdLo
= 0, Rm
;
4650 int scount
; /* cycle count */
4652 nRdHi
= BITS (16, 19);
4653 nRdLo
= BITS (12, 15);
4657 /* Needed to calculate the cycle count: */
4658 Rm
= state
->Reg
[nRm
];
4660 /* Check for illegal operand combinations first: */
4664 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
4666 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
4668 ARMword Rs
= state
->Reg
[nRs
];
4673 /* Compute sign of result and adjust operands if necessary. */
4675 sign
= (Rm
^ Rs
) & 0x80000000;
4677 if (((signed long) Rm
) < 0)
4680 if (((signed long) Rs
) < 0)
4684 /* We can split the 32x32 into four 16x16 operations. This ensures
4685 that we do not lose precision on 32bit only hosts: */
4686 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
4687 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4688 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
4689 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4691 /* We now need to add all of these results together, taking care
4692 to propogate the carries from the additions: */
4693 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
4695 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
4697 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
4701 /* Negate result if necessary. */
4705 if (RdLo
== 0xFFFFFFFF)
4714 state
->Reg
[nRdLo
] = RdLo
;
4715 state
->Reg
[nRdHi
] = RdHi
;
4716 } /* else undefined result */
4718 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4722 /* Ensure that both RdHi and RdLo are used to compute Z, but
4723 don't let RdLo's sign bit make it to N. */
4724 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4727 /* The cycle count depends on whether the instruction is a signed or
4728 unsigned multiply, and what bits are clear in the multiplier: */
4729 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
4730 Rm
= ~Rm
; /* invert the bits to make the check against zero */
4732 if ((Rm
& 0xFFFFFF00) == 0)
4734 else if ((Rm
& 0xFFFF0000) == 0)
4736 else if ((Rm
& 0xFF000000) == 0)
4744 /***************************************************************************\
4745 * This function does the work of multiplying two 32bit values and adding *
4746 * a 64bit value to give a 64bit result. *
4747 \***************************************************************************/
4750 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4757 nRdHi
= BITS (16, 19);
4758 nRdLo
= BITS (12, 15);
4760 RdHi
= state
->Reg
[nRdHi
];
4761 RdLo
= state
->Reg
[nRdLo
];
4763 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
4765 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
4766 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
4768 state
->Reg
[nRdLo
] = RdLo
;
4769 state
->Reg
[nRdHi
] = RdHi
;
4773 /* Ensure that both RdHi and RdLo are used to compute Z, but
4774 don't let RdLo's sign bit make it to N. */
4775 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4778 return scount
+ 1; /* extra cycle for addition */