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
;
1345 /* Hardware is allowed to optionally override this
1346 instruction and treat it as a breakpoint. Since
1347 this is a simulator not hardware, we take the position
1348 that if a SWI vector was not installed, then an Abort
1349 vector was probably not installed either, and so
1350 normally this instruction would be ignored, even if an
1351 Abort is generated. This is a bad thing, since GDB
1352 uses this instruction for its breakpoints (at least in
1353 Thumb mode it does). So intercept the instruction here
1354 and generate a breakpoint SWI instead. */
1355 if (! SWI_vector_installed
)
1356 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1359 /* BKPT - normally this will cause an abort, but for the
1360 XScale if bit 31 in register 10 of coprocessor 14 is
1361 clear, then this is treated as a no-op. */
1362 if (state
->is_XScale
)
1364 if (read_cp14_reg (10) & (1UL << 31))
1368 value
= read_cp14_reg (10);
1372 write_cp14_reg (10, value
);
1373 write_cp15_reg (5, 0, 0, 0x200); /* Set FSR. */
1374 write_cp15_reg (6, 0, 0, pc
); /* Set FAR. */
1381 /* We must signal an abort to mark the next instruction as
1382 invalid and in need of refetching. This is because if this
1383 the instruction was a breakpoint inserted by the debugger,
1384 the instruction could be changed back to its original value.
1385 The abort however, will automatically reset the processor into
1386 ARM mode, so we have to preserve the mode flag and resort it
1387 after singalling the abort. */
1388 in_thumb_mode
= TFLAG
;
1389 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
1390 ASSIGNT (in_thumb_mode
);
1397 /* MSR reg to CPSR */
1401 /* Don't allow TBIT to be set by MSR. */
1404 ARMul_FixCPSR (state
, instr
, temp
);
1412 case 0x13: /* TEQP reg */
1414 if ((BITS (4, 11) & 0xF9) == 0x9)
1416 /* LDR register offset, write-back, down, pre indexed */
1418 /* continue with remaining instruction decode */
1424 state
->Cpsr
= GETSPSR (state
->Bank
);
1425 ARMul_CPSRAltered (state
);
1436 ARMul_NegZero (state
, dest
);
1440 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1443 if (BIT (4) == 0 && BIT (7) == 1)
1445 /* ElSegundo SMLALxy insn. */
1446 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1447 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1448 unsigned long long dest
;
1449 unsigned long long result
;
1462 dest
= (unsigned long long) state
->Reg
[BITS (16, 19)] << 32;
1463 dest
|= state
->Reg
[BITS (12, 15)];
1465 state
->Reg
[BITS (12, 15)] = dest
;
1466 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1470 if (BITS (4, 11) == 5)
1472 /* ElSegundo QDADD insn. */
1473 ARMword op1
= state
->Reg
[BITS (0, 3)];
1474 ARMword op2
= state
->Reg
[BITS (16, 19)];
1475 ARMword op2d
= op2
+ op2
;
1478 if (AddOverflow (op2
, op2
, op2d
))
1481 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1484 result
= op1
+ op2d
;
1485 if (AddOverflow (op1
, op2d
, result
))
1488 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1491 state
->Reg
[BITS (12, 15)] = result
;
1496 if (BITS (4, 7) == 0xB)
1498 /* STRH immediate offset, no write-back, down, pre indexed */
1502 if (BITS (4, 7) == 0xD)
1504 Handle_Load_Double (state
, instr
);
1507 if (BITS (4, 7) == 0xF)
1509 Handle_Store_Double (state
, instr
);
1513 if (BITS (4, 11) == 9)
1519 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1521 INTERNALABORT (temp
);
1522 (void) ARMul_LoadByte (state
, temp
);
1523 (void) ARMul_LoadByte (state
, temp
);
1527 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1528 if (state
->abortSig
|| state
->Aborted
)
1533 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1536 DEST
= GETSPSR (state
->Bank
);
1544 case 0x15: /* CMPP reg */
1546 if ((BITS (4, 7) & 0x9) == 0x9)
1548 /* LDR immediate offset, no write-back, down, pre indexed */
1550 /* continue with remaining instruction decode */
1556 state
->Cpsr
= GETSPSR (state
->Bank
);
1557 ARMul_CPSRAltered (state
);
1569 ARMul_NegZero (state
, dest
);
1570 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1572 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1573 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1583 case 0x16: /* CMN reg and MSR reg to SPSR */
1586 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1588 /* ElSegundo SMULxy insn. */
1589 ARMword op1
= state
->Reg
[BITS (0, 3)];
1590 ARMword op2
= state
->Reg
[BITS (8, 11)];
1591 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1604 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1608 if (BITS (4, 11) == 5)
1610 /* ElSegundo QDSUB insn. */
1611 ARMword op1
= state
->Reg
[BITS (0, 3)];
1612 ARMword op2
= state
->Reg
[BITS (16, 19)];
1613 ARMword op2d
= op2
+ op2
;
1616 if (AddOverflow (op2
, op2
, op2d
))
1619 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1622 result
= op1
- op2d
;
1623 if (SubOverflow (op1
, op2d
, result
))
1626 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1629 state
->Reg
[BITS (12, 15)] = result
;
1636 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1638 /* ARM5 CLZ insn. */
1639 ARMword op1
= state
->Reg
[BITS (0, 3)];
1643 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1646 state
->Reg
[BITS (12, 15)] = result
;
1651 if (BITS (4, 7) == 0xB)
1653 /* STRH immediate offset, write-back, down, pre indexed */
1657 if (BITS (4, 7) == 0xD)
1659 Handle_Load_Double (state
, instr
);
1662 if (BITS (4, 7) == 0xF)
1664 Handle_Store_Double (state
, instr
);
1671 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1679 case 0x17: /* CMNP reg */
1681 if ((BITS (4, 7) & 0x9) == 0x9)
1683 /* LDR immediate offset, write-back, down, pre indexed */
1685 /* continue with remaining instruction decoding */
1691 state
->Cpsr
= GETSPSR (state
->Bank
);
1692 ARMul_CPSRAltered (state
);
1705 ASSIGNZ (dest
== 0);
1706 if ((lhs
| rhs
) >> 30)
1707 { /* possible C,V,N to set */
1708 ASSIGNN (NEG (dest
));
1709 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1710 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1721 case 0x18: /* ORR reg */
1723 if (BITS (4, 11) == 0xB)
1725 /* STRH register offset, no write-back, up, pre indexed */
1729 if (BITS (4, 7) == 0xD)
1731 Handle_Load_Double (state
, instr
);
1734 if (BITS (4, 7) == 0xF)
1736 Handle_Store_Double (state
, instr
);
1745 case 0x19: /* ORRS reg */
1747 if ((BITS (4, 11) & 0xF9) == 0x9)
1749 /* LDR register offset, no write-back, up, pre indexed */
1751 /* continue with remaining instruction decoding */
1759 case 0x1a: /* MOV reg */
1761 if (BITS (4, 11) == 0xB)
1763 /* STRH register offset, write-back, up, pre indexed */
1767 if (BITS (4, 7) == 0xD)
1769 Handle_Load_Double (state
, instr
);
1772 if (BITS (4, 7) == 0xF)
1774 Handle_Store_Double (state
, instr
);
1782 case 0x1b: /* MOVS reg */
1784 if ((BITS (4, 11) & 0xF9) == 0x9)
1786 /* LDR register offset, write-back, up, pre indexed */
1788 /* continue with remaining instruction decoding */
1795 case 0x1c: /* BIC reg */
1797 if (BITS (4, 7) == 0xB)
1799 /* STRH immediate offset, no write-back, up, pre indexed */
1803 if (BITS (4, 7) == 0xD)
1805 Handle_Load_Double (state
, instr
);
1808 else if (BITS (4, 7) == 0xF)
1810 Handle_Store_Double (state
, instr
);
1819 case 0x1d: /* BICS reg */
1821 if ((BITS (4, 7) & 0x9) == 0x9)
1823 /* LDR immediate offset, no write-back, up, pre indexed */
1825 /* continue with instruction decoding */
1833 case 0x1e: /* MVN reg */
1835 if (BITS (4, 7) == 0xB)
1837 /* STRH immediate offset, write-back, up, pre indexed */
1841 if (BITS (4, 7) == 0xD)
1843 Handle_Load_Double (state
, instr
);
1846 if (BITS (4, 7) == 0xF)
1848 Handle_Store_Double (state
, instr
);
1856 case 0x1f: /* MVNS reg */
1858 if ((BITS (4, 7) & 0x9) == 0x9)
1860 /* LDR immediate offset, write-back, up, pre indexed */
1862 /* continue instruction decoding */
1869 /***************************************************************************\
1870 * Data Processing Immediate RHS Instructions *
1871 \***************************************************************************/
1873 case 0x20: /* AND immed */
1874 dest
= LHS
& DPImmRHS
;
1878 case 0x21: /* ANDS immed */
1884 case 0x22: /* EOR immed */
1885 dest
= LHS
^ DPImmRHS
;
1889 case 0x23: /* EORS immed */
1895 case 0x24: /* SUB immed */
1896 dest
= LHS
- DPImmRHS
;
1900 case 0x25: /* SUBS immed */
1904 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1906 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1907 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1917 case 0x26: /* RSB immed */
1918 dest
= DPImmRHS
- LHS
;
1922 case 0x27: /* RSBS immed */
1926 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1928 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1929 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1939 case 0x28: /* ADD immed */
1940 dest
= LHS
+ DPImmRHS
;
1944 case 0x29: /* ADDS immed */
1948 ASSIGNZ (dest
== 0);
1949 if ((lhs
| rhs
) >> 30)
1950 { /* possible C,V,N to set */
1951 ASSIGNN (NEG (dest
));
1952 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1953 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1964 case 0x2a: /* ADC immed */
1965 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1969 case 0x2b: /* ADCS immed */
1972 dest
= lhs
+ rhs
+ CFLAG
;
1973 ASSIGNZ (dest
== 0);
1974 if ((lhs
| rhs
) >> 30)
1975 { /* possible C,V,N to set */
1976 ASSIGNN (NEG (dest
));
1977 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1978 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1989 case 0x2c: /* SBC immed */
1990 dest
= LHS
- DPImmRHS
- !CFLAG
;
1994 case 0x2d: /* SBCS immed */
1997 dest
= lhs
- rhs
- !CFLAG
;
1998 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2000 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2001 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2011 case 0x2e: /* RSC immed */
2012 dest
= DPImmRHS
- LHS
- !CFLAG
;
2016 case 0x2f: /* RSCS immed */
2019 dest
= rhs
- lhs
- !CFLAG
;
2020 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2022 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2023 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2033 case 0x30: /* TST immed */
2037 case 0x31: /* TSTP immed */
2041 state
->Cpsr
= GETSPSR (state
->Bank
);
2042 ARMul_CPSRAltered (state
);
2044 temp
= LHS
& DPImmRHS
;
2050 DPSImmRHS
; /* TST immed */
2052 ARMul_NegZero (state
, dest
);
2056 case 0x32: /* TEQ immed and MSR immed to CPSR */
2058 { /* MSR immed to CPSR */
2059 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2067 case 0x33: /* TEQP immed */
2071 state
->Cpsr
= GETSPSR (state
->Bank
);
2072 ARMul_CPSRAltered (state
);
2074 temp
= LHS
^ DPImmRHS
;
2080 DPSImmRHS
; /* TEQ immed */
2082 ARMul_NegZero (state
, dest
);
2086 case 0x34: /* CMP immed */
2090 case 0x35: /* CMPP immed */
2094 state
->Cpsr
= GETSPSR (state
->Bank
);
2095 ARMul_CPSRAltered (state
);
2097 temp
= LHS
- DPImmRHS
;
2104 lhs
= LHS
; /* CMP immed */
2107 ARMul_NegZero (state
, dest
);
2108 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2110 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2111 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2121 case 0x36: /* CMN immed and MSR immed to SPSR */
2122 if (DESTReg
== 15) /* MSR */
2123 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2130 case 0x37: /* CMNP immed */
2134 state
->Cpsr
= GETSPSR (state
->Bank
);
2135 ARMul_CPSRAltered (state
);
2137 temp
= LHS
+ DPImmRHS
;
2144 lhs
= LHS
; /* CMN immed */
2147 ASSIGNZ (dest
== 0);
2148 if ((lhs
| rhs
) >> 30)
2149 { /* possible C,V,N to set */
2150 ASSIGNN (NEG (dest
));
2151 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2152 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2163 case 0x38: /* ORR immed */
2164 dest
= LHS
| DPImmRHS
;
2168 case 0x39: /* ORRS immed */
2174 case 0x3a: /* MOV immed */
2179 case 0x3b: /* MOVS immed */
2184 case 0x3c: /* BIC immed */
2185 dest
= LHS
& ~DPImmRHS
;
2189 case 0x3d: /* BICS immed */
2195 case 0x3e: /* MVN immed */
2200 case 0x3f: /* MVNS immed */
2205 /***************************************************************************\
2206 * Single Data Transfer Immediate RHS Instructions *
2207 \***************************************************************************/
2209 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
2211 if (StoreWord (state
, instr
, lhs
))
2212 LSBase
= lhs
- LSImmRHS
;
2215 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
2217 if (LoadWord (state
, instr
, lhs
))
2218 LSBase
= lhs
- LSImmRHS
;
2221 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
2222 UNDEF_LSRBaseEQDestWb
;
2225 temp
= lhs
- LSImmRHS
;
2226 state
->NtransSig
= LOW
;
2227 if (StoreWord (state
, instr
, lhs
))
2229 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2232 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
2233 UNDEF_LSRBaseEQDestWb
;
2236 state
->NtransSig
= LOW
;
2237 if (LoadWord (state
, instr
, lhs
))
2238 LSBase
= lhs
- LSImmRHS
;
2239 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2242 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
2244 if (StoreByte (state
, instr
, lhs
))
2245 LSBase
= lhs
- LSImmRHS
;
2248 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
2250 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2251 LSBase
= lhs
- LSImmRHS
;
2254 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
2255 UNDEF_LSRBaseEQDestWb
;
2258 state
->NtransSig
= LOW
;
2259 if (StoreByte (state
, instr
, lhs
))
2260 LSBase
= lhs
- LSImmRHS
;
2261 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2264 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
2265 UNDEF_LSRBaseEQDestWb
;
2268 state
->NtransSig
= LOW
;
2269 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2270 LSBase
= lhs
- LSImmRHS
;
2271 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2274 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
2276 if (StoreWord (state
, instr
, lhs
))
2277 LSBase
= lhs
+ LSImmRHS
;
2280 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
2282 if (LoadWord (state
, instr
, lhs
))
2283 LSBase
= lhs
+ LSImmRHS
;
2286 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
2287 UNDEF_LSRBaseEQDestWb
;
2290 state
->NtransSig
= LOW
;
2291 if (StoreWord (state
, instr
, lhs
))
2292 LSBase
= lhs
+ LSImmRHS
;
2293 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2296 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
2297 UNDEF_LSRBaseEQDestWb
;
2300 state
->NtransSig
= LOW
;
2301 if (LoadWord (state
, instr
, lhs
))
2302 LSBase
= lhs
+ LSImmRHS
;
2303 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2306 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
2308 if (StoreByte (state
, instr
, lhs
))
2309 LSBase
= lhs
+ LSImmRHS
;
2312 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
2314 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2315 LSBase
= lhs
+ LSImmRHS
;
2318 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
2319 UNDEF_LSRBaseEQDestWb
;
2322 state
->NtransSig
= LOW
;
2323 if (StoreByte (state
, instr
, lhs
))
2324 LSBase
= lhs
+ LSImmRHS
;
2325 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2328 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
2329 UNDEF_LSRBaseEQDestWb
;
2332 state
->NtransSig
= LOW
;
2333 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2334 LSBase
= lhs
+ LSImmRHS
;
2335 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2339 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
2340 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2343 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
2344 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2347 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
2348 UNDEF_LSRBaseEQDestWb
;
2350 temp
= LHS
- LSImmRHS
;
2351 if (StoreWord (state
, instr
, temp
))
2355 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
2356 UNDEF_LSRBaseEQDestWb
;
2358 temp
= LHS
- LSImmRHS
;
2359 if (LoadWord (state
, instr
, temp
))
2363 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
2364 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2367 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
2368 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2371 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
2372 UNDEF_LSRBaseEQDestWb
;
2374 temp
= LHS
- LSImmRHS
;
2375 if (StoreByte (state
, instr
, temp
))
2379 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
2380 UNDEF_LSRBaseEQDestWb
;
2382 temp
= LHS
- LSImmRHS
;
2383 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2387 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
2388 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2391 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
2392 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2395 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
2396 UNDEF_LSRBaseEQDestWb
;
2398 temp
= LHS
+ LSImmRHS
;
2399 if (StoreWord (state
, instr
, temp
))
2403 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
2404 UNDEF_LSRBaseEQDestWb
;
2406 temp
= LHS
+ LSImmRHS
;
2407 if (LoadWord (state
, instr
, temp
))
2411 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
2412 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2415 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
2416 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2419 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
2420 UNDEF_LSRBaseEQDestWb
;
2422 temp
= LHS
+ LSImmRHS
;
2423 if (StoreByte (state
, instr
, temp
))
2427 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
2428 UNDEF_LSRBaseEQDestWb
;
2430 temp
= LHS
+ LSImmRHS
;
2431 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2435 /***************************************************************************\
2436 * Single Data Transfer Register RHS Instructions *
2437 \***************************************************************************/
2439 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
2442 ARMul_UndefInstr (state
, instr
);
2445 UNDEF_LSRBaseEQOffWb
;
2446 UNDEF_LSRBaseEQDestWb
;
2450 if (StoreWord (state
, instr
, lhs
))
2451 LSBase
= lhs
- LSRegRHS
;
2454 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
2457 ARMul_UndefInstr (state
, instr
);
2460 UNDEF_LSRBaseEQOffWb
;
2461 UNDEF_LSRBaseEQDestWb
;
2465 temp
= lhs
- LSRegRHS
;
2466 if (LoadWord (state
, instr
, lhs
))
2470 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2473 ARMul_UndefInstr (state
, instr
);
2476 UNDEF_LSRBaseEQOffWb
;
2477 UNDEF_LSRBaseEQDestWb
;
2481 state
->NtransSig
= LOW
;
2482 if (StoreWord (state
, instr
, lhs
))
2483 LSBase
= lhs
- LSRegRHS
;
2484 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2487 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2490 ARMul_UndefInstr (state
, instr
);
2493 UNDEF_LSRBaseEQOffWb
;
2494 UNDEF_LSRBaseEQDestWb
;
2498 temp
= lhs
- LSRegRHS
;
2499 state
->NtransSig
= LOW
;
2500 if (LoadWord (state
, instr
, lhs
))
2502 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2505 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2508 ARMul_UndefInstr (state
, instr
);
2511 UNDEF_LSRBaseEQOffWb
;
2512 UNDEF_LSRBaseEQDestWb
;
2516 if (StoreByte (state
, instr
, lhs
))
2517 LSBase
= lhs
- LSRegRHS
;
2520 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2523 ARMul_UndefInstr (state
, instr
);
2526 UNDEF_LSRBaseEQOffWb
;
2527 UNDEF_LSRBaseEQDestWb
;
2531 temp
= lhs
- LSRegRHS
;
2532 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2536 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2539 ARMul_UndefInstr (state
, instr
);
2542 UNDEF_LSRBaseEQOffWb
;
2543 UNDEF_LSRBaseEQDestWb
;
2547 state
->NtransSig
= LOW
;
2548 if (StoreByte (state
, instr
, lhs
))
2549 LSBase
= lhs
- LSRegRHS
;
2550 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2553 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2556 ARMul_UndefInstr (state
, instr
);
2559 UNDEF_LSRBaseEQOffWb
;
2560 UNDEF_LSRBaseEQDestWb
;
2564 temp
= lhs
- LSRegRHS
;
2565 state
->NtransSig
= LOW
;
2566 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2568 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2571 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2574 ARMul_UndefInstr (state
, instr
);
2577 UNDEF_LSRBaseEQOffWb
;
2578 UNDEF_LSRBaseEQDestWb
;
2582 if (StoreWord (state
, instr
, lhs
))
2583 LSBase
= lhs
+ LSRegRHS
;
2586 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2589 ARMul_UndefInstr (state
, instr
);
2592 UNDEF_LSRBaseEQOffWb
;
2593 UNDEF_LSRBaseEQDestWb
;
2597 temp
= lhs
+ LSRegRHS
;
2598 if (LoadWord (state
, instr
, lhs
))
2602 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2605 ARMul_UndefInstr (state
, instr
);
2608 UNDEF_LSRBaseEQOffWb
;
2609 UNDEF_LSRBaseEQDestWb
;
2613 state
->NtransSig
= LOW
;
2614 if (StoreWord (state
, instr
, lhs
))
2615 LSBase
= lhs
+ LSRegRHS
;
2616 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2619 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2622 ARMul_UndefInstr (state
, instr
);
2625 UNDEF_LSRBaseEQOffWb
;
2626 UNDEF_LSRBaseEQDestWb
;
2630 temp
= lhs
+ LSRegRHS
;
2631 state
->NtransSig
= LOW
;
2632 if (LoadWord (state
, instr
, lhs
))
2634 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2637 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2640 ARMul_UndefInstr (state
, instr
);
2643 UNDEF_LSRBaseEQOffWb
;
2644 UNDEF_LSRBaseEQDestWb
;
2648 if (StoreByte (state
, instr
, lhs
))
2649 LSBase
= lhs
+ LSRegRHS
;
2652 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2655 ARMul_UndefInstr (state
, instr
);
2658 UNDEF_LSRBaseEQOffWb
;
2659 UNDEF_LSRBaseEQDestWb
;
2663 temp
= lhs
+ LSRegRHS
;
2664 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2668 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2671 ARMul_UndefInstr (state
, instr
);
2674 UNDEF_LSRBaseEQOffWb
;
2675 UNDEF_LSRBaseEQDestWb
;
2679 state
->NtransSig
= LOW
;
2680 if (StoreByte (state
, instr
, lhs
))
2681 LSBase
= lhs
+ LSRegRHS
;
2682 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2685 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2688 ARMul_UndefInstr (state
, instr
);
2691 UNDEF_LSRBaseEQOffWb
;
2692 UNDEF_LSRBaseEQDestWb
;
2696 temp
= lhs
+ LSRegRHS
;
2697 state
->NtransSig
= LOW
;
2698 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2700 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2704 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2707 ARMul_UndefInstr (state
, instr
);
2710 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2713 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2716 ARMul_UndefInstr (state
, instr
);
2719 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2722 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2725 ARMul_UndefInstr (state
, instr
);
2728 UNDEF_LSRBaseEQOffWb
;
2729 UNDEF_LSRBaseEQDestWb
;
2732 temp
= LHS
- LSRegRHS
;
2733 if (StoreWord (state
, instr
, temp
))
2737 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2740 ARMul_UndefInstr (state
, instr
);
2743 UNDEF_LSRBaseEQOffWb
;
2744 UNDEF_LSRBaseEQDestWb
;
2747 temp
= LHS
- LSRegRHS
;
2748 if (LoadWord (state
, instr
, temp
))
2752 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2755 ARMul_UndefInstr (state
, instr
);
2758 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2761 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2764 ARMul_UndefInstr (state
, instr
);
2767 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2770 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2773 ARMul_UndefInstr (state
, instr
);
2776 UNDEF_LSRBaseEQOffWb
;
2777 UNDEF_LSRBaseEQDestWb
;
2780 temp
= LHS
- LSRegRHS
;
2781 if (StoreByte (state
, instr
, temp
))
2785 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2788 ARMul_UndefInstr (state
, instr
);
2791 UNDEF_LSRBaseEQOffWb
;
2792 UNDEF_LSRBaseEQDestWb
;
2795 temp
= LHS
- LSRegRHS
;
2796 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2800 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2803 ARMul_UndefInstr (state
, instr
);
2806 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2809 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2812 ARMul_UndefInstr (state
, instr
);
2815 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2818 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2821 ARMul_UndefInstr (state
, instr
);
2824 UNDEF_LSRBaseEQOffWb
;
2825 UNDEF_LSRBaseEQDestWb
;
2828 temp
= LHS
+ LSRegRHS
;
2829 if (StoreWord (state
, instr
, temp
))
2833 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2836 ARMul_UndefInstr (state
, instr
);
2839 UNDEF_LSRBaseEQOffWb
;
2840 UNDEF_LSRBaseEQDestWb
;
2843 temp
= LHS
+ LSRegRHS
;
2844 if (LoadWord (state
, instr
, temp
))
2848 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2851 ARMul_UndefInstr (state
, instr
);
2854 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2857 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2860 ARMul_UndefInstr (state
, instr
);
2863 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2866 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2869 ARMul_UndefInstr (state
, instr
);
2872 UNDEF_LSRBaseEQOffWb
;
2873 UNDEF_LSRBaseEQDestWb
;
2876 temp
= LHS
+ LSRegRHS
;
2877 if (StoreByte (state
, instr
, temp
))
2881 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2884 /* Check for the special breakpoint opcode.
2885 This value should correspond to the value defined
2886 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2887 if (BITS (0, 19) == 0xfdefe)
2889 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2890 ARMul_Abort (state
, ARMul_SWIV
);
2893 ARMul_UndefInstr (state
, instr
);
2896 UNDEF_LSRBaseEQOffWb
;
2897 UNDEF_LSRBaseEQDestWb
;
2900 temp
= LHS
+ LSRegRHS
;
2901 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2905 /***************************************************************************\
2906 * Multiple Data Transfer Instructions *
2907 \***************************************************************************/
2909 case 0x80: /* Store, No WriteBack, Post Dec */
2910 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2913 case 0x81: /* Load, No WriteBack, Post Dec */
2914 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2917 case 0x82: /* Store, WriteBack, Post Dec */
2918 temp
= LSBase
- LSMNumRegs
;
2919 STOREMULT (instr
, temp
+ 4L, temp
);
2922 case 0x83: /* Load, WriteBack, Post Dec */
2923 temp
= LSBase
- LSMNumRegs
;
2924 LOADMULT (instr
, temp
+ 4L, temp
);
2927 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2928 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2931 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2932 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2935 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2936 temp
= LSBase
- LSMNumRegs
;
2937 STORESMULT (instr
, temp
+ 4L, temp
);
2940 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2941 temp
= LSBase
- LSMNumRegs
;
2942 LOADSMULT (instr
, temp
+ 4L, temp
);
2945 case 0x88: /* Store, No WriteBack, Post Inc */
2946 STOREMULT (instr
, LSBase
, 0L);
2949 case 0x89: /* Load, No WriteBack, Post Inc */
2950 LOADMULT (instr
, LSBase
, 0L);
2953 case 0x8a: /* Store, WriteBack, Post Inc */
2955 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
2958 case 0x8b: /* Load, WriteBack, Post Inc */
2960 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
2963 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2964 STORESMULT (instr
, LSBase
, 0L);
2967 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2968 LOADSMULT (instr
, LSBase
, 0L);
2971 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2973 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
2976 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2978 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
2981 case 0x90: /* Store, No WriteBack, Pre Dec */
2982 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2985 case 0x91: /* Load, No WriteBack, Pre Dec */
2986 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2989 case 0x92: /* Store, WriteBack, Pre Dec */
2990 temp
= LSBase
- LSMNumRegs
;
2991 STOREMULT (instr
, temp
, temp
);
2994 case 0x93: /* Load, WriteBack, Pre Dec */
2995 temp
= LSBase
- LSMNumRegs
;
2996 LOADMULT (instr
, temp
, temp
);
2999 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
3000 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3003 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
3004 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3007 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
3008 temp
= LSBase
- LSMNumRegs
;
3009 STORESMULT (instr
, temp
, temp
);
3012 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
3013 temp
= LSBase
- LSMNumRegs
;
3014 LOADSMULT (instr
, temp
, temp
);
3017 case 0x98: /* Store, No WriteBack, Pre Inc */
3018 STOREMULT (instr
, LSBase
+ 4L, 0L);
3021 case 0x99: /* Load, No WriteBack, Pre Inc */
3022 LOADMULT (instr
, LSBase
+ 4L, 0L);
3025 case 0x9a: /* Store, WriteBack, Pre Inc */
3027 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3030 case 0x9b: /* Load, WriteBack, Pre Inc */
3032 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3035 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
3036 STORESMULT (instr
, LSBase
+ 4L, 0L);
3039 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
3040 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3043 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
3045 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3048 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
3050 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3053 /***************************************************************************\
3055 \***************************************************************************/
3065 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3069 /***************************************************************************\
3071 \***************************************************************************/
3081 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3085 /***************************************************************************\
3086 * Branch and Link forward *
3087 \***************************************************************************/
3098 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3100 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3102 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3106 /***************************************************************************\
3107 * Branch and Link backward *
3108 \***************************************************************************/
3119 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3121 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3123 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3127 /***************************************************************************\
3128 * Co-Processor Data Transfers *
3129 \***************************************************************************/
3132 if (state
->is_XScale
)
3134 if (BITS (4, 7) != 0x00)
3135 ARMul_UndefInstr (state
, instr
);
3137 if (BITS (8, 11) != 0x00)
3138 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3140 /* XScale MAR insn. Move two registers into accumulator. */
3141 if (BITS (0, 3) == 0x00)
3143 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3144 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3147 /* Access to any other acc is unpredicatable. */
3152 case 0xc0: /* Store , No WriteBack , Post Dec */
3153 ARMul_STC (state
, instr
, LHS
);
3157 if (state
->is_XScale
)
3159 if (BITS (4, 7) != 0x00)
3160 ARMul_UndefInstr (state
, instr
);
3162 if (BITS (8, 11) != 0x00)
3163 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3165 /* XScale MRA insn. Move accumulator into two registers. */
3166 if (BITS (0, 3) == 0x00)
3168 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3173 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3174 state
->Reg
[BITS (16, 19)] = t1
;
3177 /* Access to any other acc is unpredicatable. */
3182 case 0xc1: /* Load , No WriteBack , Post Dec */
3183 ARMul_LDC (state
, instr
, LHS
);
3187 case 0xc6: /* Store , WriteBack , Post Dec */
3189 state
->Base
= lhs
- LSCOff
;
3190 ARMul_STC (state
, instr
, lhs
);
3194 case 0xc7: /* Load , WriteBack , Post Dec */
3196 state
->Base
= lhs
- LSCOff
;
3197 ARMul_LDC (state
, instr
, lhs
);
3201 case 0xcc: /* Store , No WriteBack , Post Inc */
3202 ARMul_STC (state
, instr
, LHS
);
3206 case 0xcd: /* Load , No WriteBack , Post Inc */
3207 ARMul_LDC (state
, instr
, LHS
);
3211 case 0xce: /* Store , WriteBack , Post Inc */
3213 state
->Base
= lhs
+ LSCOff
;
3214 ARMul_STC (state
, instr
, LHS
);
3218 case 0xcf: /* Load , WriteBack , Post Inc */
3220 state
->Base
= lhs
+ LSCOff
;
3221 ARMul_LDC (state
, instr
, LHS
);
3226 case 0xd4: /* Store , No WriteBack , Pre Dec */
3227 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3231 case 0xd5: /* Load , No WriteBack , Pre Dec */
3232 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3236 case 0xd6: /* Store , WriteBack , Pre Dec */
3239 ARMul_STC (state
, instr
, lhs
);
3243 case 0xd7: /* Load , WriteBack , Pre Dec */
3246 ARMul_LDC (state
, instr
, lhs
);
3250 case 0xdc: /* Store , No WriteBack , Pre Inc */
3251 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3255 case 0xdd: /* Load , No WriteBack , Pre Inc */
3256 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3260 case 0xde: /* Store , WriteBack , Pre Inc */
3263 ARMul_STC (state
, instr
, lhs
);
3267 case 0xdf: /* Load , WriteBack , Pre Inc */
3270 ARMul_LDC (state
, instr
, lhs
);
3273 /***************************************************************************\
3274 * Co-Processor Register Transfers (MCR) and Data Ops *
3275 \***************************************************************************/
3278 if (state
->is_XScale
)
3279 switch (BITS (18, 19))
3283 /* XScale MIA instruction. Signed multiplication of two 32 bit
3284 values and addition to 40 bit accumulator. */
3285 long long Rm
= state
->Reg
[MULLHSReg
];
3286 long long Rs
= state
->Reg
[MULACCReg
];
3292 state
->Accumulator
+= Rm
* Rs
;
3298 /* XScale MIAPH instruction. */
3299 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3300 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3301 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3302 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3317 state
->Accumulator
+= t5
;
3322 state
->Accumulator
+= t5
;
3328 /* XScale MIAxy instruction. */
3334 t1
= state
->Reg
[MULLHSReg
] >> 16;
3336 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3339 t2
= state
->Reg
[MULACCReg
] >> 16;
3341 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3351 state
->Accumulator
+= t5
;
3373 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3375 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3376 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3380 ARMul_MCR (state
, instr
, DEST
);
3382 else /* CDP Part 1 */
3383 ARMul_CDP (state
, instr
);
3386 /***************************************************************************\
3387 * Co-Processor Register Transfers (MRC) and Data Ops *
3388 \***************************************************************************/
3400 temp
= ARMul_MRC (state
, instr
);
3403 ASSIGNN ((temp
& NBIT
) != 0);
3404 ASSIGNZ ((temp
& ZBIT
) != 0);
3405 ASSIGNC ((temp
& CBIT
) != 0);
3406 ASSIGNV ((temp
& VBIT
) != 0);
3411 else /* CDP Part 2 */
3412 ARMul_CDP (state
, instr
);
3415 /***************************************************************************\
3417 \***************************************************************************/
3435 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3437 /* A prefetch abort. */
3438 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3442 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3444 ARMul_Abort (state
, ARMul_SWIV
);
3447 } /* 256 way main switch */
3454 #ifdef NEED_UI_LOOP_HOOK
3455 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3457 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3460 #endif /* NEED_UI_LOOP_HOOK */
3462 if (state
->Emulate
== ONCE
)
3463 state
->Emulate
= STOP
;
3464 /* If we have changed mode, allow the PC to advance before stopping. */
3465 else if (state
->Emulate
== CHANGEMODE
)
3467 else if (state
->Emulate
!= RUN
)
3470 while (!stop_simulator
); /* do loop */
3472 state
->decoded
= decoded
;
3473 state
->loaded
= loaded
;
3477 } /* Emulate 26/32 in instruction based mode */
3480 /***************************************************************************\
3481 * This routine evaluates most Data Processing register RHS's with the S *
3482 * bit clear. It is intended to be called from the macro DPRegRHS, which *
3483 * filters the common case of an unshifted register with in line code *
3484 \***************************************************************************/
3487 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3489 ARMword shamt
, base
;
3493 { /* shift amount in a register */
3498 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3501 base
= state
->Reg
[base
];
3502 ARMul_Icycles (state
, 1, 0L);
3503 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3504 switch ((int) BITS (5, 6))
3509 else if (shamt
>= 32)
3512 return (base
<< shamt
);
3516 else if (shamt
>= 32)
3519 return (base
>> shamt
);
3523 else if (shamt
>= 32)
3524 return ((ARMword
) ((long int) base
>> 31L));
3526 return ((ARMword
) ((long int) base
>> (int) shamt
));
3532 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3536 { /* shift amount is a constant */
3539 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3542 base
= state
->Reg
[base
];
3543 shamt
= BITS (7, 11);
3544 switch ((int) BITS (5, 6))
3547 return (base
<< shamt
);
3552 return (base
>> shamt
);
3555 return ((ARMword
) ((long int) base
>> 31L));
3557 return ((ARMword
) ((long int) base
>> (int) shamt
));
3559 if (shamt
== 0) /* its an RRX */
3560 return ((base
>> 1) | (CFLAG
<< 31));
3562 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3565 return (0); /* just to shut up lint */
3568 /***************************************************************************\
3569 * This routine evaluates most Logical Data Processing register RHS's *
3570 * with the S bit set. It is intended to be called from the macro *
3571 * DPSRegRHS, which filters the common case of an unshifted register *
3572 * with in line code *
3573 \***************************************************************************/
3576 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3578 ARMword shamt
, base
;
3582 { /* shift amount in a register */
3587 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3590 base
= state
->Reg
[base
];
3591 ARMul_Icycles (state
, 1, 0L);
3592 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3593 switch ((int) BITS (5, 6))
3598 else if (shamt
== 32)
3603 else if (shamt
> 32)
3610 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3611 return (base
<< shamt
);
3616 else if (shamt
== 32)
3618 ASSIGNC (base
>> 31);
3621 else if (shamt
> 32)
3628 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3629 return (base
>> shamt
);
3634 else if (shamt
>= 32)
3636 ASSIGNC (base
>> 31L);
3637 return ((ARMword
) ((long int) base
>> 31L));
3641 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3642 return ((ARMword
) ((long int) base
>> (int) shamt
));
3650 ASSIGNC (base
>> 31);
3655 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3656 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3661 { /* shift amount is a constant */
3664 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3667 base
= state
->Reg
[base
];
3668 shamt
= BITS (7, 11);
3669 switch ((int) BITS (5, 6))
3672 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3673 return (base
<< shamt
);
3677 ASSIGNC (base
>> 31);
3682 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3683 return (base
>> shamt
);
3688 ASSIGNC (base
>> 31L);
3689 return ((ARMword
) ((long int) base
>> 31L));
3693 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3694 return ((ARMword
) ((long int) base
>> (int) shamt
));
3701 return ((base
>> 1) | (shamt
<< 31));
3705 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3706 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3710 return (0); /* just to shut up lint */
3713 /***************************************************************************\
3714 * This routine handles writes to register 15 when the S bit is not set. *
3715 \***************************************************************************/
3718 WriteR15 (ARMul_State
* state
, ARMword src
)
3720 /* The ARM documentation states that the two least significant bits
3721 are discarded when setting PC, except in the cases handled by
3722 WriteR15Branch() below. It's probably an oversight: in THUMB
3723 mode, the second least significant bit should probably not be
3732 state
->Reg
[15] = src
& PCBITS
;
3734 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
3735 ARMul_R15Altered (state
);
3740 /***************************************************************************\
3741 * This routine handles writes to register 15 when the S bit is set. *
3742 \***************************************************************************/
3745 WriteSR15 (ARMul_State
* state
, ARMword src
)
3748 if (state
->Bank
> 0)
3750 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3751 ARMul_CPSRAltered (state
);
3759 state
->Reg
[15] = src
& PCBITS
;
3763 abort (); /* ARMul_R15Altered would have to support it. */
3767 if (state
->Bank
== USERBANK
)
3768 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3770 state
->Reg
[15] = src
;
3771 ARMul_R15Altered (state
);
3776 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3777 will switch to Thumb mode if the least significant bit is set. */
3780 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3786 state
->Reg
[15] = src
& 0xfffffffe;
3791 state
->Reg
[15] = src
& 0xfffffffc;
3795 WriteR15 (state
, src
);
3799 /***************************************************************************\
3800 * This routine evaluates most Load and Store register RHS's. It is *
3801 * intended to be called from the macro LSRegRHS, which filters the *
3802 * common case of an unshifted register with in line code *
3803 \***************************************************************************/
3806 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3808 ARMword shamt
, base
;
3813 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3816 base
= state
->Reg
[base
];
3818 shamt
= BITS (7, 11);
3819 switch ((int) BITS (5, 6))
3822 return (base
<< shamt
);
3827 return (base
>> shamt
);
3830 return ((ARMword
) ((long int) base
>> 31L));
3832 return ((ARMword
) ((long int) base
>> (int) shamt
));
3834 if (shamt
== 0) /* its an RRX */
3835 return ((base
>> 1) | (CFLAG
<< 31));
3837 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3839 return (0); /* just to shut up lint */
3842 /***************************************************************************\
3843 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3844 \***************************************************************************/
3847 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3853 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3855 return state
->Reg
[RHSReg
];
3858 /* else immediate */
3859 return BITS (0, 3) | (BITS (8, 11) << 4);
3862 /***************************************************************************\
3863 * This function does the work of loading a word for a LDR instruction. *
3864 \***************************************************************************/
3867 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3873 if (ADDREXCEPT (address
))
3875 INTERNALABORT (address
);
3878 dest
= ARMul_LoadWordN (state
, address
);
3882 return (state
->lateabtSig
);
3885 dest
= ARMul_Align (state
, address
, dest
);
3887 ARMul_Icycles (state
, 1, 0L);
3889 return (DESTReg
!= LHSReg
);
3893 /***************************************************************************\
3894 * This function does the work of loading a halfword. *
3895 \***************************************************************************/
3898 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3905 if (ADDREXCEPT (address
))
3907 INTERNALABORT (address
);
3910 dest
= ARMul_LoadHalfWord (state
, address
);
3914 return (state
->lateabtSig
);
3919 if (dest
& 1 << (16 - 1))
3920 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3923 ARMul_Icycles (state
, 1, 0L);
3924 return (DESTReg
!= LHSReg
);
3929 /***************************************************************************\
3930 * This function does the work of loading a byte for a LDRB instruction. *
3931 \***************************************************************************/
3934 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3940 if (ADDREXCEPT (address
))
3942 INTERNALABORT (address
);
3945 dest
= ARMul_LoadByte (state
, address
);
3949 return (state
->lateabtSig
);
3954 if (dest
& 1 << (8 - 1))
3955 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3958 ARMul_Icycles (state
, 1, 0L);
3959 return (DESTReg
!= LHSReg
);
3962 /***************************************************************************\
3963 * This function does the work of loading two words for a LDRD instruction. *
3964 \***************************************************************************/
3967 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
3971 ARMword write_back
= BIT (21);
3972 ARMword immediate
= BIT (22);
3973 ARMword add_to_base
= BIT (23);
3974 ARMword pre_indexed
= BIT (24);
3984 /* If the writeback bit is set, the pre-index bit must be clear. */
3985 if (write_back
&& ! pre_indexed
)
3987 ARMul_UndefInstr (state
, instr
);
3991 /* Extract the base address register. */
3994 /* Extract the destination register and check it. */
3997 /* Destination register must be even. */
3999 /* Destination register cannot be LR. */
4000 || (dest_reg
== 14))
4002 ARMul_UndefInstr (state
, instr
);
4006 /* Compute the base address. */
4007 base
= state
->Reg
[addr_reg
];
4009 /* Compute the offset. */
4010 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4012 /* Compute the sum of the two. */
4014 sum
= base
+ offset
;
4016 sum
= base
- offset
;
4018 /* If this is a pre-indexed mode use the sum. */
4024 /* The address must be aligned on a 8 byte boundary. */
4028 ARMul_DATAABORT (addr
);
4030 ARMul_UndefInstr (state
, instr
);
4035 /* For pre indexed or post indexed addressing modes,
4036 check that the destination registers do not overlap
4037 the address registers. */
4038 if ((! pre_indexed
|| write_back
)
4039 && ( addr_reg
== dest_reg
4040 || addr_reg
== dest_reg
+ 1))
4042 ARMul_UndefInstr (state
, instr
);
4046 /* Load the words. */
4047 value1
= ARMul_LoadWordN (state
, addr
);
4048 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4050 /* Check for data aborts. */
4057 ARMul_Icycles (state
, 2, 0L);
4059 /* Store the values. */
4060 state
->Reg
[dest_reg
] = value1
;
4061 state
->Reg
[dest_reg
+ 1] = value2
;
4063 /* Do the post addressing and writeback. */
4067 if (! pre_indexed
|| write_back
)
4068 state
->Reg
[addr_reg
] = addr
;
4071 /***************************************************************************\
4072 * This function does the work of storing two words for a STRD instruction. *
4073 \***************************************************************************/
4076 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4080 ARMword write_back
= BIT (21);
4081 ARMword immediate
= BIT (22);
4082 ARMword add_to_base
= BIT (23);
4083 ARMword pre_indexed
= BIT (24);
4091 /* If the writeback bit is set, the pre-index bit must be clear. */
4092 if (write_back
&& ! pre_indexed
)
4094 ARMul_UndefInstr (state
, instr
);
4098 /* Extract the base address register. */
4101 /* Base register cannot be PC. */
4104 ARMul_UndefInstr (state
, instr
);
4108 /* Extract the source register. */
4111 /* Source register must be even. */
4114 ARMul_UndefInstr (state
, instr
);
4118 /* Compute the base address. */
4119 base
= state
->Reg
[addr_reg
];
4121 /* Compute the offset. */
4122 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4124 /* Compute the sum of the two. */
4126 sum
= base
+ offset
;
4128 sum
= base
- offset
;
4130 /* If this is a pre-indexed mode use the sum. */
4136 /* The address must be aligned on a 8 byte boundary. */
4140 ARMul_DATAABORT (addr
);
4142 ARMul_UndefInstr (state
, instr
);
4147 /* For pre indexed or post indexed addressing modes,
4148 check that the destination registers do not overlap
4149 the address registers. */
4150 if ((! pre_indexed
|| write_back
)
4151 && ( addr_reg
== src_reg
4152 || addr_reg
== src_reg
+ 1))
4154 ARMul_UndefInstr (state
, instr
);
4158 /* Load the words. */
4159 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4160 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4168 /* Do the post addressing and writeback. */
4172 if (! pre_indexed
|| write_back
)
4173 state
->Reg
[addr_reg
] = addr
;
4176 /***************************************************************************\
4177 * This function does the work of storing a word from a STR instruction. *
4178 \***************************************************************************/
4181 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4186 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4189 ARMul_StoreWordN (state
, address
, DEST
);
4191 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4193 INTERNALABORT (address
);
4194 (void) ARMul_LoadWordN (state
, address
);
4197 ARMul_StoreWordN (state
, address
, DEST
);
4202 return (state
->lateabtSig
);
4208 /***************************************************************************\
4209 * This function does the work of storing a byte for a STRH instruction. *
4210 \***************************************************************************/
4213 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4219 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4223 ARMul_StoreHalfWord (state
, address
, DEST
);
4225 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4227 INTERNALABORT (address
);
4228 (void) ARMul_LoadHalfWord (state
, address
);
4231 ARMul_StoreHalfWord (state
, address
, DEST
);
4237 return (state
->lateabtSig
);
4245 /***************************************************************************\
4246 * This function does the work of storing a byte for a STRB instruction. *
4247 \***************************************************************************/
4250 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4255 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4258 ARMul_StoreByte (state
, address
, DEST
);
4260 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4262 INTERNALABORT (address
);
4263 (void) ARMul_LoadByte (state
, address
);
4266 ARMul_StoreByte (state
, address
, DEST
);
4271 return (state
->lateabtSig
);
4277 /***************************************************************************\
4278 * This function does the work of loading the registers listed in an LDM *
4279 * instruction, when the S bit is clear. The code here is always increment *
4280 * after, it's up to the caller to get the input address correct and to *
4281 * handle base register modification. *
4282 \***************************************************************************/
4285 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4291 UNDEF_LSMBaseInListWb
;
4294 if (ADDREXCEPT (address
))
4296 INTERNALABORT (address
);
4299 if (BIT (21) && LHSReg
!= 15)
4302 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4303 dest
= ARMul_LoadWordN (state
, address
);
4304 if (!state
->abortSig
&& !state
->Aborted
)
4305 state
->Reg
[temp
++] = dest
;
4306 else if (!state
->Aborted
)
4308 state
->Aborted
= ARMul_DataAbortV
;
4311 for (; temp
< 16; temp
++) /* S cycles from here on */
4313 { /* load this register */
4315 dest
= ARMul_LoadWordS (state
, address
);
4316 if (!state
->abortSig
&& !state
->Aborted
)
4317 state
->Reg
[temp
] = dest
;
4318 else if (!state
->Aborted
)
4320 state
->Aborted
= ARMul_DataAbortV
;
4324 if (BIT (15) && !state
->Aborted
)
4325 { /* PC is in the reg list */
4326 WriteR15Branch(state
, PC
);
4329 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
4333 if (BIT (21) && LHSReg
!= 15)
4339 /***************************************************************************\
4340 * This function does the work of loading the registers listed in an LDM *
4341 * instruction, when the S bit is set. The code here is always increment *
4342 * after, it's up to the caller to get the input address correct and to *
4343 * handle base register modification. *
4344 \***************************************************************************/
4347 LoadSMult (ARMul_State
* state
,
4356 UNDEF_LSMBaseInListWb
;
4361 if (ADDREXCEPT (address
))
4363 INTERNALABORT (address
);
4367 if (BIT (21) && LHSReg
!= 15)
4370 if (!BIT (15) && state
->Bank
!= USERBANK
)
4372 /* Temporary reg bank switch. */
4373 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4374 UNDEF_LSMUserBankWb
;
4377 for (temp
= 0; !BIT (temp
); temp
++)
4378 ; /* N cycle first. */
4380 dest
= ARMul_LoadWordN (state
, address
);
4382 if (!state
->abortSig
)
4383 state
->Reg
[temp
++] = dest
;
4384 else if (!state
->Aborted
)
4386 state
->Aborted
= ARMul_DataAbortV
;
4389 for (; temp
< 16; temp
++)
4390 /* S cycles from here on. */
4393 /* Load this register. */
4395 dest
= ARMul_LoadWordS (state
, address
);
4397 if (!state
->abortSig
&& !state
->Aborted
)
4398 state
->Reg
[temp
] = dest
;
4399 else if (!state
->Aborted
)
4401 state
->Aborted
= ARMul_DataAbortV
;
4405 if (BIT (15) && !state
->Aborted
)
4407 /* PC is in the reg list. */
4409 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4411 state
->Cpsr
= GETSPSR (state
->Bank
);
4412 ARMul_CPSRAltered (state
);
4415 WriteR15 (state
, PC
);
4417 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4419 /* Protect bits in user mode. */
4420 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4421 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4422 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4423 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4426 ARMul_R15Altered (state
);
4432 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4433 /* Restore the correct bank. */
4434 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4436 /* To write back the final register. */
4437 ARMul_Icycles (state
, 1, 0L);
4441 if (BIT (21) && LHSReg
!= 15)
4448 /***************************************************************************\
4449 * This function does the work of storing the registers listed in an STM *
4450 * instruction, when the S bit is clear. The code here is always increment *
4451 * after, it's up to the caller to get the input address correct and to *
4452 * handle base register modification. *
4453 \***************************************************************************/
4456 StoreMult (ARMul_State
* state
, ARMword instr
,
4457 ARMword address
, ARMword WBBase
)
4463 UNDEF_LSMBaseInListWb
;
4466 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
4470 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4472 INTERNALABORT (address
);
4478 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4480 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4484 (void) ARMul_LoadWordN (state
, address
);
4485 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
4487 { /* save this register */
4489 (void) ARMul_LoadWordS (state
, address
);
4491 if (BIT (21) && LHSReg
!= 15)
4497 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4500 if (state
->abortSig
&& !state
->Aborted
)
4502 state
->Aborted
= ARMul_DataAbortV
;
4505 if (BIT (21) && LHSReg
!= 15)
4508 for (; temp
< 16; temp
++) /* S cycles from here on */
4510 { /* save this register */
4513 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4515 if (state
->abortSig
&& !state
->Aborted
)
4517 state
->Aborted
= ARMul_DataAbortV
;
4527 /***************************************************************************\
4528 * This function does the work of storing the registers listed in an STM *
4529 * instruction when the S bit is set. The code here is always increment *
4530 * after, it's up to the caller to get the input address correct and to *
4531 * handle base register modification. *
4532 \***************************************************************************/
4535 StoreSMult (ARMul_State
* state
,
4544 UNDEF_LSMBaseInListWb
;
4549 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4551 INTERNALABORT (address
);
4558 if (state
->Bank
!= USERBANK
)
4560 /* Force User Bank. */
4561 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4562 UNDEF_LSMUserBankWb
;
4565 for (temp
= 0; !BIT (temp
); temp
++)
4566 ; /* N cycle first. */
4569 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4573 (void) ARMul_LoadWordN (state
, address
);
4575 for (; temp
< 16; temp
++)
4576 /* Fake the Stores as Loads. */
4579 /* Save this register. */
4582 (void) ARMul_LoadWordS (state
, address
);
4585 if (BIT (21) && LHSReg
!= 15)
4593 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4596 if (state
->abortSig
&& !state
->Aborted
)
4598 state
->Aborted
= ARMul_DataAbortV
;
4601 for (; temp
< 16; temp
++)
4602 /* S cycles from here on. */
4605 /* Save this register. */
4608 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4610 if (state
->abortSig
&& !state
->Aborted
)
4612 state
->Aborted
= ARMul_DataAbortV
;
4616 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4617 /* Restore the correct bank. */
4618 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4620 if (BIT (21) && LHSReg
!= 15)
4629 /***************************************************************************\
4630 * This function does the work of adding two 32bit values together, and *
4631 * calculating if a carry has occurred. *
4632 \***************************************************************************/
4635 Add32 (ARMword a1
, ARMword a2
, int *carry
)
4637 ARMword result
= (a1
+ a2
);
4638 unsigned int uresult
= (unsigned int) result
;
4639 unsigned int ua1
= (unsigned int) a1
;
4641 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4642 or (result > RdLo) then we have no carry: */
4643 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
4651 /***************************************************************************\
4652 * This function does the work of multiplying two 32bit values to give a *
4654 \***************************************************************************/
4657 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4659 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
4660 ARMword RdHi
= 0, RdLo
= 0, Rm
;
4661 int scount
; /* cycle count */
4663 nRdHi
= BITS (16, 19);
4664 nRdLo
= BITS (12, 15);
4668 /* Needed to calculate the cycle count: */
4669 Rm
= state
->Reg
[nRm
];
4671 /* Check for illegal operand combinations first: */
4675 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
4677 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
4679 ARMword Rs
= state
->Reg
[nRs
];
4684 /* Compute sign of result and adjust operands if necessary. */
4686 sign
= (Rm
^ Rs
) & 0x80000000;
4688 if (((signed long) Rm
) < 0)
4691 if (((signed long) Rs
) < 0)
4695 /* We can split the 32x32 into four 16x16 operations. This ensures
4696 that we do not lose precision on 32bit only hosts: */
4697 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
4698 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4699 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
4700 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4702 /* We now need to add all of these results together, taking care
4703 to propogate the carries from the additions: */
4704 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
4706 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
4708 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
4712 /* Negate result if necessary. */
4716 if (RdLo
== 0xFFFFFFFF)
4725 state
->Reg
[nRdLo
] = RdLo
;
4726 state
->Reg
[nRdHi
] = RdHi
;
4727 } /* else undefined result */
4729 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4733 /* Ensure that both RdHi and RdLo are used to compute Z, but
4734 don't let RdLo's sign bit make it to N. */
4735 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4738 /* The cycle count depends on whether the instruction is a signed or
4739 unsigned multiply, and what bits are clear in the multiplier: */
4740 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
4741 Rm
= ~Rm
; /* invert the bits to make the check against zero */
4743 if ((Rm
& 0xFFFFFF00) == 0)
4745 else if ((Rm
& 0xFFFF0000) == 0)
4747 else if ((Rm
& 0xFF000000) == 0)
4755 /***************************************************************************\
4756 * This function does the work of multiplying two 32bit values and adding *
4757 * a 64bit value to give a 64bit result. *
4758 \***************************************************************************/
4761 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4768 nRdHi
= BITS (16, 19);
4769 nRdLo
= BITS (12, 15);
4771 RdHi
= state
->Reg
[nRdHi
];
4772 RdLo
= state
->Reg
[nRdLo
];
4774 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
4776 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
4777 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
4779 state
->Reg
[nRdLo
] = RdLo
;
4780 state
->Reg
[nRdHi
] = RdHi
;
4784 /* Ensure that both RdHi and RdLo are used to compute Z, but
4785 don't let RdLo's sign bit make it to N. */
4786 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4789 return scount
+ 1; /* extra cycle for addition */