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
)
288 ARMul_Emulate26 (register ARMul_State
* state
)
291 register ARMword instr
, /* the current instruction */
292 dest
= 0, /* almost the DestBus */
293 temp
, /* ubiquitous third hand */
294 pc
= 0; /* the address of the current instruction */
295 ARMword lhs
, rhs
; /* almost the ABus and BBus */
296 ARMword decoded
= 0, loaded
= 0; /* instruction pipeline */
298 /***************************************************************************\
299 * Execute the next instruction *
300 \***************************************************************************/
302 if (state
->NextInstr
< PRIMEPIPE
)
304 decoded
= state
->decoded
;
305 loaded
= state
->loaded
;
310 { /* just keep going */
312 switch (state
->NextInstr
)
315 state
->Reg
[15] += isize
; /* Advance the pipeline, and an S cycle */
319 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
323 state
->Reg
[15] += isize
; /* Advance the pipeline, and an N cycle */
327 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
332 pc
+= isize
; /* Program counter advanced, and an S cycle */
335 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
340 pc
+= isize
; /* Program counter advanced, and an N cycle */
343 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
347 case RESUME
: /* The program counter has been changed */
352 state
->Reg
[15] = pc
+ (isize
* 2);
354 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
355 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
356 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
360 default: /* The program counter has been changed */
365 state
->Reg
[15] = pc
+ (isize
* 2);
367 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
368 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
369 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
374 ARMul_EnvokeEvent (state
);
377 /* Enable this for a helpful bit of debugging when tracing is needed. */
378 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
383 if (state
->Exception
)
384 { /* Any exceptions */
385 if (state
->NresetSig
== LOW
)
387 ARMul_Abort (state
, ARMul_ResetV
);
390 else if (!state
->NfiqSig
&& !FFLAG
)
392 ARMul_Abort (state
, ARMul_FIQV
);
395 else if (!state
->NirqSig
&& !IFLAG
)
397 ARMul_Abort (state
, ARMul_IRQV
);
402 if (state
->CallDebug
> 0)
404 instr
= ARMul_Debug (state
, pc
, instr
);
405 if (state
->Emulate
< ONCE
)
407 state
->NextInstr
= RESUME
;
412 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
414 (void) fgetc (stdin
);
417 else if (state
->Emulate
< ONCE
)
419 state
->NextInstr
= RESUME
;
426 /* Provide Thumb instruction decoding. If the processor is in Thumb
427 mode, then we can simply decode the Thumb instruction, and map it
428 to the corresponding ARM instruction (by directly loading the
429 instr variable, and letting the normal ARM simulator
430 execute). There are some caveats to ensure that the correct
431 pipelined PC value is used when executing Thumb code, and also for
432 dealing with the BL instruction. */
434 { /* check if in Thumb mode */
436 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
439 ARMul_UndefInstr (state
, instr
); /* This is a Thumb instruction */
442 case t_branch
: /* already processed */
445 case t_decoded
: /* ARM instruction available */
446 instr
= new; /* so continue instruction decoding */
452 /***************************************************************************\
453 * Check the condition codes *
454 \***************************************************************************/
455 if ((temp
= TOPBITS (28)) == AL
)
456 goto mainswitch
; /* vile deed in the need for speed */
458 switch ((int) TOPBITS (28))
459 { /* check the condition code */
466 if (BITS (25, 27) == 5) /* BLX(1) */
470 state
->Reg
[14] = pc
+ 4;
472 dest
= pc
+ 8 + 1; /* Force entry into Thumb mode. */
474 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
476 dest
+= POSBRANCH
+ (BIT (24) << 1);
478 WriteR15Branch (state
, dest
);
481 else if ((instr
& 0xFC70F000) == 0xF450F000)
482 /* The PLD instruction. Ignored. */
485 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
486 ARMul_UndefInstr (state
, instr
);
515 temp
= (CFLAG
&& !ZFLAG
);
518 temp
= (!CFLAG
|| ZFLAG
);
521 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
524 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
527 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
530 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
534 /***************************************************************************\
535 * Actual execution of instructions begins here *
536 \***************************************************************************/
539 { /* if the condition codes don't match, stop here */
542 if (state
->is_XScale
)
544 if (BIT (20) == 0 && BITS (25, 27) == 0)
546 if (BITS (4, 7) == 0xD)
548 /* XScale Load Consecutive insn. */
549 ARMword temp
= GetLS7RHS (state
, instr
);
550 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
551 ARMword addr
= BIT (24) ? temp2
: temp
;
554 ARMul_UndefInstr (state
, instr
);
556 /* Alignment violation. */
557 ARMul_Abort (state
, ARMul_DataAbortV
);
560 int wb
= BIT (24) && BIT (21);
562 state
->Reg
[BITS (12, 15)] =
563 ARMul_LoadWordN (state
, addr
);
564 state
->Reg
[BITS (12, 15) + 1] =
565 ARMul_LoadWordN (state
, addr
+ 4);
572 else if (BITS (4, 7) == 0xF)
574 /* XScale Store Consecutive insn. */
575 ARMword temp
= GetLS7RHS (state
, instr
);
576 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
577 ARMword addr
= BIT (24) ? temp2
: temp
;
580 ARMul_UndefInstr (state
, instr
);
582 /* Alignment violation. */
583 ARMul_Abort (state
, ARMul_DataAbortV
);
586 ARMul_StoreWordN (state
, addr
,
587 state
->Reg
[BITS (12, 15)]);
588 ARMul_StoreWordN (state
, addr
+ 4,
589 state
->Reg
[BITS (12, 15) + 1]);
600 switch ((int) BITS (20, 27))
603 /***************************************************************************\
604 * Data Processing Register RHS Instructions *
605 \***************************************************************************/
607 case 0x00: /* AND reg and MUL */
609 if (BITS (4, 11) == 0xB)
611 /* STRH register offset, no write-back, down, post indexed */
615 if (BITS (4, 7) == 0xD)
617 Handle_Load_Double (state
, instr
);
620 if (BITS (4, 7) == 0xE)
622 Handle_Store_Double (state
, instr
);
626 if (BITS (4, 7) == 9)
628 rhs
= state
->Reg
[MULRHSReg
];
629 if (MULLHSReg
== MULDESTReg
)
632 state
->Reg
[MULDESTReg
] = 0;
634 else if (MULDESTReg
!= 15)
635 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
640 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
641 if (rhs
& (1L << dest
))
642 temp
= dest
; /* mult takes this many/2 I cycles */
643 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
653 case 0x01: /* ANDS reg and MULS */
655 if ((BITS (4, 11) & 0xF9) == 0x9)
657 /* LDR register offset, no write-back, down, post indexed */
659 /* fall through to rest of decoding */
662 if (BITS (4, 7) == 9)
664 rhs
= state
->Reg
[MULRHSReg
];
665 if (MULLHSReg
== MULDESTReg
)
668 state
->Reg
[MULDESTReg
] = 0;
672 else if (MULDESTReg
!= 15)
674 dest
= state
->Reg
[MULLHSReg
] * rhs
;
675 ARMul_NegZero (state
, dest
);
676 state
->Reg
[MULDESTReg
] = dest
;
682 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
683 if (rhs
& (1L << dest
))
684 temp
= dest
; /* mult takes this many/2 I cycles */
685 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
695 case 0x02: /* EOR reg and MLA */
697 if (BITS (4, 11) == 0xB)
699 /* STRH register offset, write-back, down, post indexed */
704 if (BITS (4, 7) == 9)
706 rhs
= state
->Reg
[MULRHSReg
];
707 if (MULLHSReg
== MULDESTReg
)
710 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
712 else if (MULDESTReg
!= 15)
713 state
->Reg
[MULDESTReg
] =
714 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
719 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
720 if (rhs
& (1L << dest
))
721 temp
= dest
; /* mult takes this many/2 I cycles */
722 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
732 case 0x03: /* EORS reg and MLAS */
734 if ((BITS (4, 11) & 0xF9) == 0x9)
736 /* LDR register offset, write-back, down, post-indexed */
738 /* fall through to rest of the decoding */
741 if (BITS (4, 7) == 9)
743 rhs
= state
->Reg
[MULRHSReg
];
744 if (MULLHSReg
== MULDESTReg
)
747 dest
= state
->Reg
[MULACCReg
];
748 ARMul_NegZero (state
, dest
);
749 state
->Reg
[MULDESTReg
] = dest
;
751 else if (MULDESTReg
!= 15)
754 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
755 ARMul_NegZero (state
, dest
);
756 state
->Reg
[MULDESTReg
] = dest
;
762 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
763 if (rhs
& (1L << dest
))
764 temp
= dest
; /* mult takes this many/2 I cycles */
765 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
775 case 0x04: /* SUB reg */
777 if (BITS (4, 7) == 0xB)
779 /* STRH immediate offset, no write-back, down, post indexed */
783 if (BITS (4, 7) == 0xD)
785 Handle_Load_Double (state
, instr
);
788 if (BITS (4, 7) == 0xE)
790 Handle_Store_Double (state
, instr
);
799 case 0x05: /* SUBS reg */
801 if ((BITS (4, 7) & 0x9) == 0x9)
803 /* LDR immediate offset, no write-back, down, post indexed */
805 /* fall through to the rest of the instruction decoding */
811 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
813 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
814 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
824 case 0x06: /* RSB reg */
826 if (BITS (4, 7) == 0xB)
828 /* STRH immediate offset, write-back, down, post indexed */
838 case 0x07: /* RSBS reg */
840 if ((BITS (4, 7) & 0x9) == 0x9)
842 /* LDR immediate offset, write-back, down, post indexed */
844 /* fall through to remainder of instruction decoding */
850 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
852 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
853 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
863 case 0x08: /* ADD reg */
865 if (BITS (4, 11) == 0xB)
867 /* STRH register offset, no write-back, up, post indexed */
871 if (BITS (4, 7) == 0xD)
873 Handle_Load_Double (state
, instr
);
876 if (BITS (4, 7) == 0xE)
878 Handle_Store_Double (state
, instr
);
883 if (BITS (4, 7) == 0x9)
886 ARMul_Icycles (state
,
887 Multiply64 (state
, instr
, LUNSIGNED
,
897 case 0x09: /* ADDS reg */
899 if ((BITS (4, 11) & 0xF9) == 0x9)
901 /* LDR register offset, no write-back, up, post indexed */
903 /* fall through to remaining instruction decoding */
907 if (BITS (4, 7) == 0x9)
910 ARMul_Icycles (state
,
911 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
920 if ((lhs
| rhs
) >> 30)
921 { /* possible C,V,N to set */
922 ASSIGNN (NEG (dest
));
923 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
924 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
935 case 0x0a: /* ADC reg */
937 if (BITS (4, 11) == 0xB)
939 /* STRH register offset, write-back, up, post-indexed */
945 if (BITS (4, 7) == 0x9)
948 ARMul_Icycles (state
,
949 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
955 dest
= LHS
+ rhs
+ CFLAG
;
959 case 0x0b: /* ADCS reg */
961 if ((BITS (4, 11) & 0xF9) == 0x9)
963 /* LDR register offset, write-back, up, post indexed */
965 /* fall through to remaining instruction decoding */
969 if (BITS (4, 7) == 0x9)
972 ARMul_Icycles (state
,
973 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
980 dest
= lhs
+ rhs
+ CFLAG
;
982 if ((lhs
| rhs
) >> 30)
983 { /* possible C,V,N to set */
984 ASSIGNN (NEG (dest
));
985 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
986 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
997 case 0x0c: /* SBC reg */
999 if (BITS (4, 7) == 0xB)
1001 /* STRH immediate offset, no write-back, up post indexed */
1005 if (BITS (4, 7) == 0xD)
1007 Handle_Load_Double (state
, instr
);
1010 if (BITS (4, 7) == 0xE)
1012 Handle_Store_Double (state
, instr
);
1017 if (BITS (4, 7) == 0x9)
1020 ARMul_Icycles (state
,
1021 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
1027 dest
= LHS
- rhs
- !CFLAG
;
1031 case 0x0d: /* SBCS reg */
1033 if ((BITS (4, 7) & 0x9) == 0x9)
1035 /* LDR immediate offset, no write-back, up, post indexed */
1040 if (BITS (4, 7) == 0x9)
1043 ARMul_Icycles (state
,
1044 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
1051 dest
= lhs
- rhs
- !CFLAG
;
1052 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1054 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1055 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1065 case 0x0e: /* RSC reg */
1067 if (BITS (4, 7) == 0xB)
1069 /* STRH immediate offset, write-back, up, post indexed */
1075 if (BITS (4, 7) == 0x9)
1078 ARMul_Icycles (state
,
1079 MultiplyAdd64 (state
, instr
, LSIGNED
,
1085 dest
= rhs
- LHS
- !CFLAG
;
1089 case 0x0f: /* RSCS reg */
1091 if ((BITS (4, 7) & 0x9) == 0x9)
1093 /* LDR immediate offset, write-back, up, post indexed */
1095 /* fall through to remaining instruction decoding */
1099 if (BITS (4, 7) == 0x9)
1102 ARMul_Icycles (state
,
1103 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
1110 dest
= rhs
- lhs
- !CFLAG
;
1111 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1113 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1114 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1124 case 0x10: /* TST reg and MRS CPSR and SWP word */
1127 if (BIT (4) == 0 && BIT (7) == 1)
1129 /* ElSegundo SMLAxy insn. */
1130 ARMword op1
= state
->Reg
[BITS (0, 3)];
1131 ARMword op2
= state
->Reg
[BITS (8, 11)];
1132 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1146 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
1148 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
1152 if (BITS (4, 11) == 5)
1154 /* ElSegundo QADD insn. */
1155 ARMword op1
= state
->Reg
[BITS (0, 3)];
1156 ARMword op2
= state
->Reg
[BITS (16, 19)];
1157 ARMword result
= op1
+ op2
;
1158 if (AddOverflow (op1
, op2
, result
))
1160 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1163 state
->Reg
[BITS (12, 15)] = result
;
1168 if (BITS (4, 11) == 0xB)
1170 /* STRH register offset, no write-back, down, pre indexed */
1174 if (BITS (4, 7) == 0xD)
1176 Handle_Load_Double (state
, instr
);
1179 if (BITS (4, 7) == 0xE)
1181 Handle_Store_Double (state
, instr
);
1185 if (BITS (4, 11) == 9)
1191 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1193 INTERNALABORT (temp
);
1194 (void) ARMul_LoadWordN (state
, temp
);
1195 (void) ARMul_LoadWordN (state
, temp
);
1199 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1201 DEST
= ARMul_Align (state
, temp
, dest
);
1204 if (state
->abortSig
|| state
->Aborted
)
1209 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1212 DEST
= ECC
| EINT
| EMODE
;
1220 case 0x11: /* TSTP reg */
1222 if ((BITS (4, 11) & 0xF9) == 0x9)
1224 /* LDR register offset, no write-back, down, pre indexed */
1226 /* continue with remaining instruction decode */
1232 state
->Cpsr
= GETSPSR (state
->Bank
);
1233 ARMul_CPSRAltered (state
);
1244 ARMul_NegZero (state
, dest
);
1248 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6) */
1251 if (BITS (4, 7) == 3)
1257 temp
= (pc
+ 2) | 1;
1261 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1262 state
->Reg
[14] = temp
;
1269 if (BIT (4) == 0 && BIT (7) == 1
1270 && (BIT (5) == 0 || BITS (12, 15) == 0))
1272 /* ElSegundo SMLAWy/SMULWy insn. */
1273 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1274 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1275 unsigned long long result
;
1279 if (op1
& 0x80000000)
1284 result
= (op1
* op2
) >> 16;
1288 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1290 if (AddOverflow (result
, Rn
, result
+ Rn
))
1294 state
->Reg
[BITS (16, 19)] = result
;
1298 if (BITS (4, 11) == 5)
1300 /* ElSegundo QSUB insn. */
1301 ARMword op1
= state
->Reg
[BITS (0, 3)];
1302 ARMword op2
= state
->Reg
[BITS (16, 19)];
1303 ARMword result
= op1
- op2
;
1305 if (SubOverflow (op1
, op2
, result
))
1307 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1311 state
->Reg
[BITS (12, 15)] = result
;
1316 if (BITS (4, 11) == 0xB)
1318 /* STRH register offset, write-back, down, pre indexed */
1322 if (BITS (4, 27) == 0x12FFF1)
1325 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1328 if (BITS (4, 7) == 0xD)
1330 Handle_Load_Double (state
, instr
);
1333 if (BITS (4, 7) == 0xE)
1335 Handle_Store_Double (state
, instr
);
1341 if (BITS (4, 7) == 0x7)
1344 extern int SWI_vector_installed
;
1346 /* Hardware is allowed to optionally override this
1347 instruction and treat it as a breakpoint. Since
1348 this is a simulator not hardware, we take the position
1349 that if a SWI vector was not installed, then an Abort
1350 vector was probably not installed either, and so
1351 normally this instruction would be ignored, even if an
1352 Abort is generated. This is a bad thing, since GDB
1353 uses this instruction for its breakpoints (at least in
1354 Thumb mode it does). So intercept the instruction here
1355 and generate a breakpoint SWI instead. */
1356 if (! SWI_vector_installed
)
1357 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1360 /* BKPT - normally this will cause an abort, but for the
1361 XScale if bit 31 in register 10 of coprocessor 14 is
1362 clear, then this is treated as a no-op. */
1363 if (state
->is_XScale
)
1365 if (read_cp14_reg (10) & (1UL << 31))
1369 value
= read_cp14_reg (10);
1373 write_cp14_reg (10, value
);
1374 write_cp15_reg (5, 0, 0, 0x200); /* Set FSR. */
1375 write_cp15_reg (6, 0, 0, pc
); /* Set FAR. */
1381 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
1387 /* MSR reg to CPSR */
1391 /* Don't allow TBIT to be set by MSR. */
1394 ARMul_FixCPSR (state
, instr
, temp
);
1402 case 0x13: /* TEQP reg */
1404 if ((BITS (4, 11) & 0xF9) == 0x9)
1406 /* LDR register offset, write-back, down, pre indexed */
1408 /* continue with remaining instruction decode */
1414 state
->Cpsr
= GETSPSR (state
->Bank
);
1415 ARMul_CPSRAltered (state
);
1426 ARMul_NegZero (state
, dest
);
1430 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1433 if (BIT (4) == 0 && BIT (7) == 1)
1435 /* ElSegundo SMLALxy insn. */
1436 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1437 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1438 unsigned long long dest
;
1439 unsigned long long result
;
1452 dest
= (unsigned long long) state
->Reg
[BITS (16, 19)] << 32;
1453 dest
|= state
->Reg
[BITS (12, 15)];
1455 state
->Reg
[BITS (12, 15)] = dest
;
1456 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1460 if (BITS (4, 11) == 5)
1462 /* ElSegundo QDADD insn. */
1463 ARMword op1
= state
->Reg
[BITS (0, 3)];
1464 ARMword op2
= state
->Reg
[BITS (16, 19)];
1465 ARMword op2d
= op2
+ op2
;
1468 if (AddOverflow (op2
, op2
, op2d
))
1471 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1474 result
= op1
+ op2d
;
1475 if (AddOverflow (op1
, op2d
, result
))
1478 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1481 state
->Reg
[BITS (12, 15)] = result
;
1486 if (BITS (4, 7) == 0xB)
1488 /* STRH immediate offset, no write-back, down, pre indexed */
1492 if (BITS (4, 7) == 0xD)
1494 Handle_Load_Double (state
, instr
);
1497 if (BITS (4, 7) == 0xE)
1499 Handle_Store_Double (state
, instr
);
1503 if (BITS (4, 11) == 9)
1509 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1511 INTERNALABORT (temp
);
1512 (void) ARMul_LoadByte (state
, temp
);
1513 (void) ARMul_LoadByte (state
, temp
);
1517 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1518 if (state
->abortSig
|| state
->Aborted
)
1523 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1526 DEST
= GETSPSR (state
->Bank
);
1534 case 0x15: /* CMPP reg */
1536 if ((BITS (4, 7) & 0x9) == 0x9)
1538 /* LDR immediate offset, no write-back, down, pre indexed */
1540 /* continue with remaining instruction decode */
1546 state
->Cpsr
= GETSPSR (state
->Bank
);
1547 ARMul_CPSRAltered (state
);
1559 ARMul_NegZero (state
, dest
);
1560 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1562 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1563 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1573 case 0x16: /* CMN reg and MSR reg to SPSR */
1576 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1578 /* ElSegundo SMULxy insn. */
1579 ARMword op1
= state
->Reg
[BITS (0, 3)];
1580 ARMword op2
= state
->Reg
[BITS (8, 11)];
1581 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1594 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1598 if (BITS (4, 11) == 5)
1600 /* ElSegundo QDSUB insn. */
1601 ARMword op1
= state
->Reg
[BITS (0, 3)];
1602 ARMword op2
= state
->Reg
[BITS (16, 19)];
1603 ARMword op2d
= op2
+ op2
;
1606 if (AddOverflow (op2
, op2
, op2d
))
1609 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1612 result
= op1
- op2d
;
1613 if (SubOverflow (op1
, op2d
, result
))
1616 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1619 state
->Reg
[BITS (12, 15)] = result
;
1626 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1628 /* ARM5 CLZ insn. */
1629 ARMword op1
= state
->Reg
[BITS (0, 3)];
1633 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1636 state
->Reg
[BITS (12, 15)] = result
;
1641 if (BITS (4, 7) == 0xB)
1643 /* STRH immediate offset, write-back, down, pre indexed */
1647 if (BITS (4, 7) == 0xD)
1649 Handle_Load_Double (state
, instr
);
1652 if (BITS (4, 7) == 0xE)
1654 Handle_Store_Double (state
, instr
);
1661 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1669 case 0x17: /* CMNP reg */
1671 if ((BITS (4, 7) & 0x9) == 0x9)
1673 /* LDR immediate offset, write-back, down, pre indexed */
1675 /* continue with remaining instruction decoding */
1681 state
->Cpsr
= GETSPSR (state
->Bank
);
1682 ARMul_CPSRAltered (state
);
1695 ASSIGNZ (dest
== 0);
1696 if ((lhs
| rhs
) >> 30)
1697 { /* possible C,V,N to set */
1698 ASSIGNN (NEG (dest
));
1699 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1700 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1711 case 0x18: /* ORR reg */
1713 if (BITS (4, 11) == 0xB)
1715 /* STRH register offset, no write-back, up, pre indexed */
1719 if (BITS (4, 7) == 0xD)
1721 Handle_Load_Double (state
, instr
);
1724 if (BITS (4, 7) == 0xE)
1726 Handle_Store_Double (state
, instr
);
1735 case 0x19: /* ORRS reg */
1737 if ((BITS (4, 11) & 0xF9) == 0x9)
1739 /* LDR register offset, no write-back, up, pre indexed */
1741 /* continue with remaining instruction decoding */
1749 case 0x1a: /* MOV reg */
1751 if (BITS (4, 11) == 0xB)
1753 /* STRH register offset, write-back, up, pre indexed */
1757 if (BITS (4, 7) == 0xD)
1759 Handle_Load_Double (state
, instr
);
1762 if (BITS (4, 7) == 0xE)
1764 Handle_Store_Double (state
, instr
);
1772 case 0x1b: /* MOVS reg */
1774 if ((BITS (4, 11) & 0xF9) == 0x9)
1776 /* LDR register offset, write-back, up, pre indexed */
1778 /* continue with remaining instruction decoding */
1785 case 0x1c: /* BIC reg */
1787 if (BITS (4, 7) == 0xB)
1789 /* STRH immediate offset, no write-back, up, pre indexed */
1793 if (BITS (4, 7) == 0xD)
1795 Handle_Load_Double (state
, instr
);
1798 else if (BITS (4, 7) == 0xE)
1800 Handle_Store_Double (state
, instr
);
1809 case 0x1d: /* BICS reg */
1811 if ((BITS (4, 7) & 0x9) == 0x9)
1813 /* LDR immediate offset, no write-back, up, pre indexed */
1815 /* continue with instruction decoding */
1823 case 0x1e: /* MVN reg */
1825 if (BITS (4, 7) == 0xB)
1827 /* STRH immediate offset, write-back, up, pre indexed */
1831 if (BITS (4, 7) == 0xD)
1833 Handle_Load_Double (state
, instr
);
1836 if (BITS (4, 7) == 0xE)
1838 Handle_Store_Double (state
, instr
);
1846 case 0x1f: /* MVNS reg */
1848 if ((BITS (4, 7) & 0x9) == 0x9)
1850 /* LDR immediate offset, write-back, up, pre indexed */
1852 /* continue instruction decoding */
1859 /***************************************************************************\
1860 * Data Processing Immediate RHS Instructions *
1861 \***************************************************************************/
1863 case 0x20: /* AND immed */
1864 dest
= LHS
& DPImmRHS
;
1868 case 0x21: /* ANDS immed */
1874 case 0x22: /* EOR immed */
1875 dest
= LHS
^ DPImmRHS
;
1879 case 0x23: /* EORS immed */
1885 case 0x24: /* SUB immed */
1886 dest
= LHS
- DPImmRHS
;
1890 case 0x25: /* SUBS immed */
1894 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1896 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1897 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1907 case 0x26: /* RSB immed */
1908 dest
= DPImmRHS
- LHS
;
1912 case 0x27: /* RSBS immed */
1916 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1918 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1919 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1929 case 0x28: /* ADD immed */
1930 dest
= LHS
+ DPImmRHS
;
1934 case 0x29: /* ADDS immed */
1938 ASSIGNZ (dest
== 0);
1939 if ((lhs
| rhs
) >> 30)
1940 { /* possible C,V,N to set */
1941 ASSIGNN (NEG (dest
));
1942 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1943 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1954 case 0x2a: /* ADC immed */
1955 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1959 case 0x2b: /* ADCS immed */
1962 dest
= lhs
+ rhs
+ CFLAG
;
1963 ASSIGNZ (dest
== 0);
1964 if ((lhs
| rhs
) >> 30)
1965 { /* possible C,V,N to set */
1966 ASSIGNN (NEG (dest
));
1967 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1968 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1979 case 0x2c: /* SBC immed */
1980 dest
= LHS
- DPImmRHS
- !CFLAG
;
1984 case 0x2d: /* SBCS immed */
1987 dest
= lhs
- rhs
- !CFLAG
;
1988 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1990 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1991 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2001 case 0x2e: /* RSC immed */
2002 dest
= DPImmRHS
- LHS
- !CFLAG
;
2006 case 0x2f: /* RSCS immed */
2009 dest
= rhs
- lhs
- !CFLAG
;
2010 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2012 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2013 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2023 case 0x30: /* TST immed */
2027 case 0x31: /* TSTP immed */
2031 state
->Cpsr
= GETSPSR (state
->Bank
);
2032 ARMul_CPSRAltered (state
);
2034 temp
= LHS
& DPImmRHS
;
2040 DPSImmRHS
; /* TST immed */
2042 ARMul_NegZero (state
, dest
);
2046 case 0x32: /* TEQ immed and MSR immed to CPSR */
2048 { /* MSR immed to CPSR */
2049 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2057 case 0x33: /* TEQP immed */
2061 state
->Cpsr
= GETSPSR (state
->Bank
);
2062 ARMul_CPSRAltered (state
);
2064 temp
= LHS
^ DPImmRHS
;
2070 DPSImmRHS
; /* TEQ immed */
2072 ARMul_NegZero (state
, dest
);
2076 case 0x34: /* CMP immed */
2080 case 0x35: /* CMPP immed */
2084 state
->Cpsr
= GETSPSR (state
->Bank
);
2085 ARMul_CPSRAltered (state
);
2087 temp
= LHS
- DPImmRHS
;
2094 lhs
= LHS
; /* CMP immed */
2097 ARMul_NegZero (state
, dest
);
2098 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2100 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2101 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2111 case 0x36: /* CMN immed and MSR immed to SPSR */
2112 if (DESTReg
== 15) /* MSR */
2113 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2120 case 0x37: /* CMNP immed */
2124 state
->Cpsr
= GETSPSR (state
->Bank
);
2125 ARMul_CPSRAltered (state
);
2127 temp
= LHS
+ DPImmRHS
;
2134 lhs
= LHS
; /* CMN immed */
2137 ASSIGNZ (dest
== 0);
2138 if ((lhs
| rhs
) >> 30)
2139 { /* possible C,V,N to set */
2140 ASSIGNN (NEG (dest
));
2141 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2142 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2153 case 0x38: /* ORR immed */
2154 dest
= LHS
| DPImmRHS
;
2158 case 0x39: /* ORRS immed */
2164 case 0x3a: /* MOV immed */
2169 case 0x3b: /* MOVS immed */
2174 case 0x3c: /* BIC immed */
2175 dest
= LHS
& ~DPImmRHS
;
2179 case 0x3d: /* BICS immed */
2185 case 0x3e: /* MVN immed */
2190 case 0x3f: /* MVNS immed */
2195 /***************************************************************************\
2196 * Single Data Transfer Immediate RHS Instructions *
2197 \***************************************************************************/
2199 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
2201 if (StoreWord (state
, instr
, lhs
))
2202 LSBase
= lhs
- LSImmRHS
;
2205 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
2207 if (LoadWord (state
, instr
, lhs
))
2208 LSBase
= lhs
- LSImmRHS
;
2211 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
2212 UNDEF_LSRBaseEQDestWb
;
2215 temp
= lhs
- LSImmRHS
;
2216 state
->NtransSig
= LOW
;
2217 if (StoreWord (state
, instr
, lhs
))
2219 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2222 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
2223 UNDEF_LSRBaseEQDestWb
;
2226 state
->NtransSig
= LOW
;
2227 if (LoadWord (state
, instr
, lhs
))
2228 LSBase
= lhs
- LSImmRHS
;
2229 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2232 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
2234 if (StoreByte (state
, instr
, lhs
))
2235 LSBase
= lhs
- LSImmRHS
;
2238 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
2240 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2241 LSBase
= lhs
- LSImmRHS
;
2244 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
2245 UNDEF_LSRBaseEQDestWb
;
2248 state
->NtransSig
= LOW
;
2249 if (StoreByte (state
, instr
, lhs
))
2250 LSBase
= lhs
- LSImmRHS
;
2251 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2254 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
2255 UNDEF_LSRBaseEQDestWb
;
2258 state
->NtransSig
= LOW
;
2259 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2260 LSBase
= lhs
- LSImmRHS
;
2261 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2264 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
2266 if (StoreWord (state
, instr
, lhs
))
2267 LSBase
= lhs
+ LSImmRHS
;
2270 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
2272 if (LoadWord (state
, instr
, lhs
))
2273 LSBase
= lhs
+ LSImmRHS
;
2276 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
2277 UNDEF_LSRBaseEQDestWb
;
2280 state
->NtransSig
= LOW
;
2281 if (StoreWord (state
, instr
, lhs
))
2282 LSBase
= lhs
+ LSImmRHS
;
2283 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2286 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
2287 UNDEF_LSRBaseEQDestWb
;
2290 state
->NtransSig
= LOW
;
2291 if (LoadWord (state
, instr
, lhs
))
2292 LSBase
= lhs
+ LSImmRHS
;
2293 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2296 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
2298 if (StoreByte (state
, instr
, lhs
))
2299 LSBase
= lhs
+ LSImmRHS
;
2302 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
2304 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2305 LSBase
= lhs
+ LSImmRHS
;
2308 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
2309 UNDEF_LSRBaseEQDestWb
;
2312 state
->NtransSig
= LOW
;
2313 if (StoreByte (state
, instr
, lhs
))
2314 LSBase
= lhs
+ LSImmRHS
;
2315 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2318 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
2319 UNDEF_LSRBaseEQDestWb
;
2322 state
->NtransSig
= LOW
;
2323 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2324 LSBase
= lhs
+ LSImmRHS
;
2325 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2329 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
2330 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2333 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
2334 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2337 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
2338 UNDEF_LSRBaseEQDestWb
;
2340 temp
= LHS
- LSImmRHS
;
2341 if (StoreWord (state
, instr
, temp
))
2345 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
2346 UNDEF_LSRBaseEQDestWb
;
2348 temp
= LHS
- LSImmRHS
;
2349 if (LoadWord (state
, instr
, temp
))
2353 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
2354 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2357 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
2358 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2361 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
2362 UNDEF_LSRBaseEQDestWb
;
2364 temp
= LHS
- LSImmRHS
;
2365 if (StoreByte (state
, instr
, temp
))
2369 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
2370 UNDEF_LSRBaseEQDestWb
;
2372 temp
= LHS
- LSImmRHS
;
2373 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2377 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
2378 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2381 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
2382 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2385 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
2386 UNDEF_LSRBaseEQDestWb
;
2388 temp
= LHS
+ LSImmRHS
;
2389 if (StoreWord (state
, instr
, temp
))
2393 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
2394 UNDEF_LSRBaseEQDestWb
;
2396 temp
= LHS
+ LSImmRHS
;
2397 if (LoadWord (state
, instr
, temp
))
2401 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
2402 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2405 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
2406 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2409 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
2410 UNDEF_LSRBaseEQDestWb
;
2412 temp
= LHS
+ LSImmRHS
;
2413 if (StoreByte (state
, instr
, temp
))
2417 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
2418 UNDEF_LSRBaseEQDestWb
;
2420 temp
= LHS
+ LSImmRHS
;
2421 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2425 /***************************************************************************\
2426 * Single Data Transfer Register RHS Instructions *
2427 \***************************************************************************/
2429 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
2432 ARMul_UndefInstr (state
, instr
);
2435 UNDEF_LSRBaseEQOffWb
;
2436 UNDEF_LSRBaseEQDestWb
;
2440 if (StoreWord (state
, instr
, lhs
))
2441 LSBase
= lhs
- LSRegRHS
;
2444 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
2447 ARMul_UndefInstr (state
, instr
);
2450 UNDEF_LSRBaseEQOffWb
;
2451 UNDEF_LSRBaseEQDestWb
;
2455 temp
= lhs
- LSRegRHS
;
2456 if (LoadWord (state
, instr
, lhs
))
2460 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2463 ARMul_UndefInstr (state
, instr
);
2466 UNDEF_LSRBaseEQOffWb
;
2467 UNDEF_LSRBaseEQDestWb
;
2471 state
->NtransSig
= LOW
;
2472 if (StoreWord (state
, instr
, lhs
))
2473 LSBase
= lhs
- LSRegRHS
;
2474 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2477 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2480 ARMul_UndefInstr (state
, instr
);
2483 UNDEF_LSRBaseEQOffWb
;
2484 UNDEF_LSRBaseEQDestWb
;
2488 temp
= lhs
- LSRegRHS
;
2489 state
->NtransSig
= LOW
;
2490 if (LoadWord (state
, instr
, lhs
))
2492 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2495 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2498 ARMul_UndefInstr (state
, instr
);
2501 UNDEF_LSRBaseEQOffWb
;
2502 UNDEF_LSRBaseEQDestWb
;
2506 if (StoreByte (state
, instr
, lhs
))
2507 LSBase
= lhs
- LSRegRHS
;
2510 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2513 ARMul_UndefInstr (state
, instr
);
2516 UNDEF_LSRBaseEQOffWb
;
2517 UNDEF_LSRBaseEQDestWb
;
2521 temp
= lhs
- LSRegRHS
;
2522 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2526 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2529 ARMul_UndefInstr (state
, instr
);
2532 UNDEF_LSRBaseEQOffWb
;
2533 UNDEF_LSRBaseEQDestWb
;
2537 state
->NtransSig
= LOW
;
2538 if (StoreByte (state
, instr
, lhs
))
2539 LSBase
= lhs
- LSRegRHS
;
2540 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2543 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2546 ARMul_UndefInstr (state
, instr
);
2549 UNDEF_LSRBaseEQOffWb
;
2550 UNDEF_LSRBaseEQDestWb
;
2554 temp
= lhs
- LSRegRHS
;
2555 state
->NtransSig
= LOW
;
2556 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2558 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2561 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2564 ARMul_UndefInstr (state
, instr
);
2567 UNDEF_LSRBaseEQOffWb
;
2568 UNDEF_LSRBaseEQDestWb
;
2572 if (StoreWord (state
, instr
, lhs
))
2573 LSBase
= lhs
+ LSRegRHS
;
2576 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2579 ARMul_UndefInstr (state
, instr
);
2582 UNDEF_LSRBaseEQOffWb
;
2583 UNDEF_LSRBaseEQDestWb
;
2587 temp
= lhs
+ LSRegRHS
;
2588 if (LoadWord (state
, instr
, lhs
))
2592 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2595 ARMul_UndefInstr (state
, instr
);
2598 UNDEF_LSRBaseEQOffWb
;
2599 UNDEF_LSRBaseEQDestWb
;
2603 state
->NtransSig
= LOW
;
2604 if (StoreWord (state
, instr
, lhs
))
2605 LSBase
= lhs
+ LSRegRHS
;
2606 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2609 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2612 ARMul_UndefInstr (state
, instr
);
2615 UNDEF_LSRBaseEQOffWb
;
2616 UNDEF_LSRBaseEQDestWb
;
2620 temp
= lhs
+ LSRegRHS
;
2621 state
->NtransSig
= LOW
;
2622 if (LoadWord (state
, instr
, lhs
))
2624 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2627 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2630 ARMul_UndefInstr (state
, instr
);
2633 UNDEF_LSRBaseEQOffWb
;
2634 UNDEF_LSRBaseEQDestWb
;
2638 if (StoreByte (state
, instr
, lhs
))
2639 LSBase
= lhs
+ LSRegRHS
;
2642 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2645 ARMul_UndefInstr (state
, instr
);
2648 UNDEF_LSRBaseEQOffWb
;
2649 UNDEF_LSRBaseEQDestWb
;
2653 temp
= lhs
+ LSRegRHS
;
2654 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2658 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2661 ARMul_UndefInstr (state
, instr
);
2664 UNDEF_LSRBaseEQOffWb
;
2665 UNDEF_LSRBaseEQDestWb
;
2669 state
->NtransSig
= LOW
;
2670 if (StoreByte (state
, instr
, lhs
))
2671 LSBase
= lhs
+ LSRegRHS
;
2672 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2675 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2678 ARMul_UndefInstr (state
, instr
);
2681 UNDEF_LSRBaseEQOffWb
;
2682 UNDEF_LSRBaseEQDestWb
;
2686 temp
= lhs
+ LSRegRHS
;
2687 state
->NtransSig
= LOW
;
2688 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2690 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2694 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2697 ARMul_UndefInstr (state
, instr
);
2700 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2703 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2706 ARMul_UndefInstr (state
, instr
);
2709 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2712 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2715 ARMul_UndefInstr (state
, instr
);
2718 UNDEF_LSRBaseEQOffWb
;
2719 UNDEF_LSRBaseEQDestWb
;
2722 temp
= LHS
- LSRegRHS
;
2723 if (StoreWord (state
, instr
, temp
))
2727 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2730 ARMul_UndefInstr (state
, instr
);
2733 UNDEF_LSRBaseEQOffWb
;
2734 UNDEF_LSRBaseEQDestWb
;
2737 temp
= LHS
- LSRegRHS
;
2738 if (LoadWord (state
, instr
, temp
))
2742 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2745 ARMul_UndefInstr (state
, instr
);
2748 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2751 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2754 ARMul_UndefInstr (state
, instr
);
2757 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2760 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2763 ARMul_UndefInstr (state
, instr
);
2766 UNDEF_LSRBaseEQOffWb
;
2767 UNDEF_LSRBaseEQDestWb
;
2770 temp
= LHS
- LSRegRHS
;
2771 if (StoreByte (state
, instr
, temp
))
2775 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2778 ARMul_UndefInstr (state
, instr
);
2781 UNDEF_LSRBaseEQOffWb
;
2782 UNDEF_LSRBaseEQDestWb
;
2785 temp
= LHS
- LSRegRHS
;
2786 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2790 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2793 ARMul_UndefInstr (state
, instr
);
2796 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2799 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2802 ARMul_UndefInstr (state
, instr
);
2805 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2808 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2811 ARMul_UndefInstr (state
, instr
);
2814 UNDEF_LSRBaseEQOffWb
;
2815 UNDEF_LSRBaseEQDestWb
;
2818 temp
= LHS
+ LSRegRHS
;
2819 if (StoreWord (state
, instr
, temp
))
2823 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2826 ARMul_UndefInstr (state
, instr
);
2829 UNDEF_LSRBaseEQOffWb
;
2830 UNDEF_LSRBaseEQDestWb
;
2833 temp
= LHS
+ LSRegRHS
;
2834 if (LoadWord (state
, instr
, temp
))
2838 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2841 ARMul_UndefInstr (state
, instr
);
2844 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2847 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2850 ARMul_UndefInstr (state
, instr
);
2853 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2856 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2859 ARMul_UndefInstr (state
, instr
);
2862 UNDEF_LSRBaseEQOffWb
;
2863 UNDEF_LSRBaseEQDestWb
;
2866 temp
= LHS
+ LSRegRHS
;
2867 if (StoreByte (state
, instr
, temp
))
2871 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2874 /* Check for the special breakpoint opcode.
2875 This value should correspond to the value defined
2876 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2877 if (BITS (0, 19) == 0xfdefe)
2879 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2880 ARMul_Abort (state
, ARMul_SWIV
);
2883 ARMul_UndefInstr (state
, instr
);
2886 UNDEF_LSRBaseEQOffWb
;
2887 UNDEF_LSRBaseEQDestWb
;
2890 temp
= LHS
+ LSRegRHS
;
2891 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2895 /***************************************************************************\
2896 * Multiple Data Transfer Instructions *
2897 \***************************************************************************/
2899 case 0x80: /* Store, No WriteBack, Post Dec */
2900 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2903 case 0x81: /* Load, No WriteBack, Post Dec */
2904 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2907 case 0x82: /* Store, WriteBack, Post Dec */
2908 temp
= LSBase
- LSMNumRegs
;
2909 STOREMULT (instr
, temp
+ 4L, temp
);
2912 case 0x83: /* Load, WriteBack, Post Dec */
2913 temp
= LSBase
- LSMNumRegs
;
2914 LOADMULT (instr
, temp
+ 4L, temp
);
2917 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2918 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2921 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2922 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2925 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2926 temp
= LSBase
- LSMNumRegs
;
2927 STORESMULT (instr
, temp
+ 4L, temp
);
2930 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2931 temp
= LSBase
- LSMNumRegs
;
2932 LOADSMULT (instr
, temp
+ 4L, temp
);
2936 case 0x88: /* Store, No WriteBack, Post Inc */
2937 STOREMULT (instr
, LSBase
, 0L);
2940 case 0x89: /* Load, No WriteBack, Post Inc */
2941 LOADMULT (instr
, LSBase
, 0L);
2944 case 0x8a: /* Store, WriteBack, Post Inc */
2946 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
2949 case 0x8b: /* Load, WriteBack, Post Inc */
2951 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
2954 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2955 STORESMULT (instr
, LSBase
, 0L);
2958 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2959 LOADSMULT (instr
, LSBase
, 0L);
2962 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2964 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
2967 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2969 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
2973 case 0x90: /* Store, No WriteBack, Pre Dec */
2974 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2977 case 0x91: /* Load, No WriteBack, Pre Dec */
2978 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2981 case 0x92: /* Store, WriteBack, Pre Dec */
2982 temp
= LSBase
- LSMNumRegs
;
2983 STOREMULT (instr
, temp
, temp
);
2986 case 0x93: /* Load, WriteBack, Pre Dec */
2987 temp
= LSBase
- LSMNumRegs
;
2988 LOADMULT (instr
, temp
, temp
);
2991 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2992 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2995 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2996 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2999 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
3000 temp
= LSBase
- LSMNumRegs
;
3001 STORESMULT (instr
, temp
, temp
);
3004 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
3005 temp
= LSBase
- LSMNumRegs
;
3006 LOADSMULT (instr
, temp
, temp
);
3010 case 0x98: /* Store, No WriteBack, Pre Inc */
3011 STOREMULT (instr
, LSBase
+ 4L, 0L);
3014 case 0x99: /* Load, No WriteBack, Pre Inc */
3015 LOADMULT (instr
, LSBase
+ 4L, 0L);
3018 case 0x9a: /* Store, WriteBack, Pre Inc */
3020 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3023 case 0x9b: /* Load, WriteBack, Pre Inc */
3025 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3028 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
3029 STORESMULT (instr
, LSBase
+ 4L, 0L);
3032 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
3033 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3036 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
3038 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3041 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
3043 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3046 /***************************************************************************\
3048 \***************************************************************************/
3058 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3062 /***************************************************************************\
3064 \***************************************************************************/
3074 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3078 /***************************************************************************\
3079 * Branch and Link forward *
3080 \***************************************************************************/
3091 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3093 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3095 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3099 /***************************************************************************\
3100 * Branch and Link backward *
3101 \***************************************************************************/
3112 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3114 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3116 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3120 /***************************************************************************\
3121 * Co-Processor Data Transfers *
3122 \***************************************************************************/
3125 if (state
->is_XScale
)
3127 if (BITS (4, 7) != 0x00)
3128 ARMul_UndefInstr (state
, instr
);
3130 if (BITS (8, 11) != 0x00)
3131 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3133 /* XScale MAR insn. Move two registers into accumulator. */
3134 if (BITS (0, 3) == 0x00)
3136 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3137 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3140 /* Access to any other acc is unpredicatable. */
3145 case 0xc0: /* Store , No WriteBack , Post Dec */
3146 ARMul_STC (state
, instr
, LHS
);
3150 if (state
->is_XScale
)
3152 if (BITS (4, 7) != 0x00)
3153 ARMul_UndefInstr (state
, instr
);
3155 if (BITS (8, 11) != 0x00)
3156 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3158 /* XScale MRA insn. Move accumulator into two registers. */
3159 if (BITS (0, 3) == 0x00)
3161 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3166 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3167 state
->Reg
[BITS (16, 19)] = t1
;
3170 /* Access to any other acc is unpredicatable. */
3175 case 0xc1: /* Load , No WriteBack , Post Dec */
3176 ARMul_LDC (state
, instr
, LHS
);
3180 case 0xc6: /* Store , WriteBack , Post Dec */
3182 state
->Base
= lhs
- LSCOff
;
3183 ARMul_STC (state
, instr
, lhs
);
3187 case 0xc7: /* Load , WriteBack , Post Dec */
3189 state
->Base
= lhs
- LSCOff
;
3190 ARMul_LDC (state
, instr
, lhs
);
3194 case 0xcc: /* Store , No WriteBack , Post Inc */
3195 ARMul_STC (state
, instr
, LHS
);
3199 case 0xcd: /* Load , No WriteBack , Post Inc */
3200 ARMul_LDC (state
, instr
, LHS
);
3204 case 0xce: /* Store , WriteBack , Post Inc */
3206 state
->Base
= lhs
+ LSCOff
;
3207 ARMul_STC (state
, instr
, LHS
);
3211 case 0xcf: /* Load , WriteBack , Post Inc */
3213 state
->Base
= lhs
+ LSCOff
;
3214 ARMul_LDC (state
, instr
, LHS
);
3219 case 0xd4: /* Store , No WriteBack , Pre Dec */
3220 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3224 case 0xd5: /* Load , No WriteBack , Pre Dec */
3225 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3229 case 0xd6: /* Store , WriteBack , Pre Dec */
3232 ARMul_STC (state
, instr
, lhs
);
3236 case 0xd7: /* Load , WriteBack , Pre Dec */
3239 ARMul_LDC (state
, instr
, lhs
);
3243 case 0xdc: /* Store , No WriteBack , Pre Inc */
3244 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3248 case 0xdd: /* Load , No WriteBack , Pre Inc */
3249 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3253 case 0xde: /* Store , WriteBack , Pre Inc */
3256 ARMul_STC (state
, instr
, lhs
);
3260 case 0xdf: /* Load , WriteBack , Pre Inc */
3263 ARMul_LDC (state
, instr
, lhs
);
3266 /***************************************************************************\
3267 * Co-Processor Register Transfers (MCR) and Data Ops *
3268 \***************************************************************************/
3271 if (state
->is_XScale
)
3272 switch (BITS (18, 19))
3276 /* XScale MIA instruction. Signed multiplication of two 32 bit
3277 values and addition to 40 bit accumulator. */
3278 long long Rm
= state
->Reg
[MULLHSReg
];
3279 long long Rs
= state
->Reg
[MULACCReg
];
3285 state
->Accumulator
+= Rm
* Rs
;
3291 /* XScale MIAPH instruction. */
3292 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3293 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3294 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3295 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3310 state
->Accumulator
+= t5
;
3315 state
->Accumulator
+= t5
;
3321 /* XScale MIAxy instruction. */
3327 t1
= state
->Reg
[MULLHSReg
] >> 16;
3329 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3332 t2
= state
->Reg
[MULACCReg
] >> 16;
3334 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3344 state
->Accumulator
+= t5
;
3366 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3368 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3369 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3373 ARMul_MCR (state
, instr
, DEST
);
3375 else /* CDP Part 1 */
3376 ARMul_CDP (state
, instr
);
3379 /***************************************************************************\
3380 * Co-Processor Register Transfers (MRC) and Data Ops *
3381 \***************************************************************************/
3393 temp
= ARMul_MRC (state
, instr
);
3396 ASSIGNN ((temp
& NBIT
) != 0);
3397 ASSIGNZ ((temp
& ZBIT
) != 0);
3398 ASSIGNC ((temp
& CBIT
) != 0);
3399 ASSIGNV ((temp
& VBIT
) != 0);
3404 else /* CDP Part 2 */
3405 ARMul_CDP (state
, instr
);
3408 /***************************************************************************\
3410 \***************************************************************************/
3428 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3429 { /* a prefetch abort */
3430 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3434 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3436 ARMul_Abort (state
, ARMul_SWIV
);
3439 } /* 256 way main switch */
3446 #ifdef NEED_UI_LOOP_HOOK
3447 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3449 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3452 #endif /* NEED_UI_LOOP_HOOK */
3454 if (state
->Emulate
== ONCE
)
3455 state
->Emulate
= STOP
;
3456 /* If we have changed mode, allow the PC to advance before stopping. */
3457 else if (state
->Emulate
== CHANGEMODE
)
3459 else if (state
->Emulate
!= RUN
)
3462 while (!stop_simulator
); /* do loop */
3464 state
->decoded
= decoded
;
3465 state
->loaded
= loaded
;
3469 } /* Emulate 26/32 in instruction based mode */
3472 /***************************************************************************\
3473 * This routine evaluates most Data Processing register RHS's with the S *
3474 * bit clear. It is intended to be called from the macro DPRegRHS, which *
3475 * filters the common case of an unshifted register with in line code *
3476 \***************************************************************************/
3479 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3481 ARMword shamt
, base
;
3485 { /* shift amount in a register */
3490 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3493 base
= state
->Reg
[base
];
3494 ARMul_Icycles (state
, 1, 0L);
3495 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3496 switch ((int) BITS (5, 6))
3501 else if (shamt
>= 32)
3504 return (base
<< shamt
);
3508 else if (shamt
>= 32)
3511 return (base
>> shamt
);
3515 else if (shamt
>= 32)
3516 return ((ARMword
) ((long int) base
>> 31L));
3518 return ((ARMword
) ((long int) base
>> (int) shamt
));
3524 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3528 { /* shift amount is a constant */
3531 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3534 base
= state
->Reg
[base
];
3535 shamt
= BITS (7, 11);
3536 switch ((int) BITS (5, 6))
3539 return (base
<< shamt
);
3544 return (base
>> shamt
);
3547 return ((ARMword
) ((long int) base
>> 31L));
3549 return ((ARMword
) ((long int) base
>> (int) shamt
));
3551 if (shamt
== 0) /* its an RRX */
3552 return ((base
>> 1) | (CFLAG
<< 31));
3554 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3557 return (0); /* just to shut up lint */
3560 /***************************************************************************\
3561 * This routine evaluates most Logical Data Processing register RHS's *
3562 * with the S bit set. It is intended to be called from the macro *
3563 * DPSRegRHS, which filters the common case of an unshifted register *
3564 * with in line code *
3565 \***************************************************************************/
3568 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3570 ARMword shamt
, base
;
3574 { /* shift amount in a register */
3579 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3582 base
= state
->Reg
[base
];
3583 ARMul_Icycles (state
, 1, 0L);
3584 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3585 switch ((int) BITS (5, 6))
3590 else if (shamt
== 32)
3595 else if (shamt
> 32)
3602 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3603 return (base
<< shamt
);
3608 else if (shamt
== 32)
3610 ASSIGNC (base
>> 31);
3613 else if (shamt
> 32)
3620 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3621 return (base
>> shamt
);
3626 else if (shamt
>= 32)
3628 ASSIGNC (base
>> 31L);
3629 return ((ARMword
) ((long int) base
>> 31L));
3633 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3634 return ((ARMword
) ((long int) base
>> (int) shamt
));
3642 ASSIGNC (base
>> 31);
3647 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3648 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3653 { /* shift amount is a constant */
3656 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3659 base
= state
->Reg
[base
];
3660 shamt
= BITS (7, 11);
3661 switch ((int) BITS (5, 6))
3664 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3665 return (base
<< shamt
);
3669 ASSIGNC (base
>> 31);
3674 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3675 return (base
>> shamt
);
3680 ASSIGNC (base
>> 31L);
3681 return ((ARMword
) ((long int) base
>> 31L));
3685 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3686 return ((ARMword
) ((long int) base
>> (int) shamt
));
3693 return ((base
>> 1) | (shamt
<< 31));
3697 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3698 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3702 return (0); /* just to shut up lint */
3705 /***************************************************************************\
3706 * This routine handles writes to register 15 when the S bit is not set. *
3707 \***************************************************************************/
3710 WriteR15 (ARMul_State
* state
, ARMword src
)
3712 /* The ARM documentation states that the two least significant bits
3713 are discarded when setting PC, except in the cases handled by
3714 WriteR15Branch() below. It's probably an oversight: in THUMB
3715 mode, the second least significant bit should probably not be
3724 state
->Reg
[15] = src
& PCBITS
;
3726 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
3727 ARMul_R15Altered (state
);
3732 /***************************************************************************\
3733 * This routine handles writes to register 15 when the S bit is set. *
3734 \***************************************************************************/
3737 WriteSR15 (ARMul_State
* state
, ARMword src
)
3740 if (state
->Bank
> 0)
3742 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3743 ARMul_CPSRAltered (state
);
3751 state
->Reg
[15] = src
& PCBITS
;
3755 abort (); /* ARMul_R15Altered would have to support it. */
3759 if (state
->Bank
== USERBANK
)
3760 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3762 state
->Reg
[15] = src
;
3763 ARMul_R15Altered (state
);
3768 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3769 will switch to Thumb mode if the least significant bit is set. */
3772 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3778 state
->Reg
[15] = src
& 0xfffffffe;
3783 state
->Reg
[15] = src
& 0xfffffffc;
3787 WriteR15 (state
, src
);
3791 /***************************************************************************\
3792 * This routine evaluates most Load and Store register RHS's. It is *
3793 * intended to be called from the macro LSRegRHS, which filters the *
3794 * common case of an unshifted register with in line code *
3795 \***************************************************************************/
3798 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3800 ARMword shamt
, base
;
3805 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3808 base
= state
->Reg
[base
];
3810 shamt
= BITS (7, 11);
3811 switch ((int) BITS (5, 6))
3814 return (base
<< shamt
);
3819 return (base
>> shamt
);
3822 return ((ARMword
) ((long int) base
>> 31L));
3824 return ((ARMword
) ((long int) base
>> (int) shamt
));
3826 if (shamt
== 0) /* its an RRX */
3827 return ((base
>> 1) | (CFLAG
<< 31));
3829 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3831 return (0); /* just to shut up lint */
3834 /***************************************************************************\
3835 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3836 \***************************************************************************/
3839 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3845 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3847 return state
->Reg
[RHSReg
];
3850 /* else immediate */
3851 return BITS (0, 3) | (BITS (8, 11) << 4);
3854 /***************************************************************************\
3855 * This function does the work of loading a word for a LDR instruction. *
3856 \***************************************************************************/
3859 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3865 if (ADDREXCEPT (address
))
3867 INTERNALABORT (address
);
3870 dest
= ARMul_LoadWordN (state
, address
);
3874 return (state
->lateabtSig
);
3877 dest
= ARMul_Align (state
, address
, dest
);
3879 ARMul_Icycles (state
, 1, 0L);
3881 return (DESTReg
!= LHSReg
);
3885 /***************************************************************************\
3886 * This function does the work of loading a halfword. *
3887 \***************************************************************************/
3890 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3897 if (ADDREXCEPT (address
))
3899 INTERNALABORT (address
);
3902 dest
= ARMul_LoadHalfWord (state
, address
);
3906 return (state
->lateabtSig
);
3911 if (dest
& 1 << (16 - 1))
3912 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3915 ARMul_Icycles (state
, 1, 0L);
3916 return (DESTReg
!= LHSReg
);
3921 /***************************************************************************\
3922 * This function does the work of loading a byte for a LDRB instruction. *
3923 \***************************************************************************/
3926 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3932 if (ADDREXCEPT (address
))
3934 INTERNALABORT (address
);
3937 dest
= ARMul_LoadByte (state
, address
);
3941 return (state
->lateabtSig
);
3946 if (dest
& 1 << (8 - 1))
3947 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3950 ARMul_Icycles (state
, 1, 0L);
3951 return (DESTReg
!= LHSReg
);
3954 /***************************************************************************\
3955 * This function does the work of loading two words for a LDRD instruction. *
3956 \***************************************************************************/
3959 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
3963 ARMword write_back
= BIT (21);
3964 ARMword immediate
= BIT (22);
3965 ARMword add_to_base
= BIT (23);
3966 ARMword pre_indexed
= BIT (24);
3976 /* If the writeback bit is set, the pre-index bit must be clear. */
3977 if (write_back
&& ! pre_indexed
)
3979 ARMul_UndefInstr (state
, instr
);
3983 /* Extract the base address register. */
3986 /* Extract the destination register and check it. */
3989 /* Destination register must be even. */
3991 /* Destination register cannot be LR. */
3992 || (dest_reg
== 14))
3994 ARMul_UndefInstr (state
, instr
);
3998 /* Compute the base address. */
3999 base
= state
->Reg
[addr_reg
];
4001 /* Compute the offset. */
4002 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4004 /* Compute the sum of the two. */
4006 sum
= base
+ offset
;
4008 sum
= base
- offset
;
4010 /* If this is a pre-indexed mode use the sum. */
4016 /* The address must be aligned on a 8 byte boundary. */
4020 ARMul_DATAABORT (addr
);
4022 ARMul_UndefInstr (state
, instr
);
4027 /* For pre indexed or post indexed addressing modes,
4028 check that the destination registers do not overlap
4029 the address registers. */
4030 if ((! pre_indexed
|| write_back
)
4031 && ( addr_reg
== dest_reg
4032 || addr_reg
== dest_reg
+ 1))
4034 ARMul_UndefInstr (state
, instr
);
4038 /* Load the words. */
4039 value1
= ARMul_LoadWordN (state
, addr
);
4040 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4042 /* Check for data aborts. */
4049 ARMul_Icycles (state
, 2, 0L);
4051 /* Store the values. */
4052 state
->Reg
[dest_reg
] = value1
;
4053 state
->Reg
[dest_reg
+ 1] = value2
;
4055 /* Do the post addressing and writeback. */
4059 if (! pre_indexed
|| write_back
)
4060 state
->Reg
[addr_reg
] = addr
;
4063 /***************************************************************************\
4064 * This function does the work of storing two words for a STRD instruction. *
4065 \***************************************************************************/
4068 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4072 ARMword write_back
= BIT (21);
4073 ARMword immediate
= BIT (22);
4074 ARMword add_to_base
= BIT (23);
4075 ARMword pre_indexed
= BIT (24);
4083 /* If the writeback bit is set, the pre-index bit must be clear. */
4084 if (write_back
&& ! pre_indexed
)
4086 ARMul_UndefInstr (state
, instr
);
4090 /* Extract the base address register. */
4093 /* Base register cannot be PC. */
4096 ARMul_UndefInstr (state
, instr
);
4100 /* Extract the source register. */
4103 /* Source register must be even. */
4106 ARMul_UndefInstr (state
, instr
);
4110 /* Compute the base address. */
4111 base
= state
->Reg
[addr_reg
];
4113 /* Compute the offset. */
4114 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4116 /* Compute the sum of the two. */
4118 sum
= base
+ offset
;
4120 sum
= base
- offset
;
4122 /* If this is a pre-indexed mode use the sum. */
4128 /* The address must be aligned on a 8 byte boundary. */
4132 ARMul_DATAABORT (addr
);
4134 ARMul_UndefInstr (state
, instr
);
4139 /* For pre indexed or post indexed addressing modes,
4140 check that the destination registers do not overlap
4141 the address registers. */
4142 if ((! pre_indexed
|| write_back
)
4143 && ( addr_reg
== src_reg
4144 || addr_reg
== src_reg
+ 1))
4146 ARMul_UndefInstr (state
, instr
);
4150 /* Load the words. */
4151 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4152 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4160 /* Do the post addressing and writeback. */
4164 if (! pre_indexed
|| write_back
)
4165 state
->Reg
[addr_reg
] = addr
;
4168 /***************************************************************************\
4169 * This function does the work of storing a word from a STR instruction. *
4170 \***************************************************************************/
4173 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4178 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4181 ARMul_StoreWordN (state
, address
, DEST
);
4183 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4185 INTERNALABORT (address
);
4186 (void) ARMul_LoadWordN (state
, address
);
4189 ARMul_StoreWordN (state
, address
, DEST
);
4194 return (state
->lateabtSig
);
4200 /***************************************************************************\
4201 * This function does the work of storing a byte for a STRH instruction. *
4202 \***************************************************************************/
4205 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4211 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4215 ARMul_StoreHalfWord (state
, address
, DEST
);
4217 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4219 INTERNALABORT (address
);
4220 (void) ARMul_LoadHalfWord (state
, address
);
4223 ARMul_StoreHalfWord (state
, address
, DEST
);
4229 return (state
->lateabtSig
);
4237 /***************************************************************************\
4238 * This function does the work of storing a byte for a STRB instruction. *
4239 \***************************************************************************/
4242 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4247 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4250 ARMul_StoreByte (state
, address
, DEST
);
4252 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4254 INTERNALABORT (address
);
4255 (void) ARMul_LoadByte (state
, address
);
4258 ARMul_StoreByte (state
, address
, DEST
);
4263 return (state
->lateabtSig
);
4269 /***************************************************************************\
4270 * This function does the work of loading the registers listed in an LDM *
4271 * instruction, when the S bit is clear. The code here is always increment *
4272 * after, it's up to the caller to get the input address correct and to *
4273 * handle base register modification. *
4274 \***************************************************************************/
4277 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4283 UNDEF_LSMBaseInListWb
;
4286 if (ADDREXCEPT (address
))
4288 INTERNALABORT (address
);
4291 if (BIT (21) && LHSReg
!= 15)
4294 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4295 dest
= ARMul_LoadWordN (state
, address
);
4296 if (!state
->abortSig
&& !state
->Aborted
)
4297 state
->Reg
[temp
++] = dest
;
4298 else if (!state
->Aborted
)
4299 state
->Aborted
= ARMul_DataAbortV
;
4301 for (; temp
< 16; temp
++) /* S cycles from here on */
4303 { /* load this register */
4305 dest
= ARMul_LoadWordS (state
, address
);
4306 if (!state
->abortSig
&& !state
->Aborted
)
4307 state
->Reg
[temp
] = dest
;
4308 else if (!state
->Aborted
)
4309 state
->Aborted
= ARMul_DataAbortV
;
4312 if (BIT (15) && !state
->Aborted
)
4313 { /* PC is in the reg list */
4314 WriteR15Branch(state
, PC
);
4317 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
4321 if (BIT (21) && LHSReg
!= 15)
4327 /***************************************************************************\
4328 * This function does the work of loading the registers listed in an LDM *
4329 * instruction, when the S bit is set. The code here is always increment *
4330 * after, it's up to the caller to get the input address correct and to *
4331 * handle base register modification. *
4332 \***************************************************************************/
4335 LoadSMult (ARMul_State
* state
, ARMword instr
,
4336 ARMword address
, ARMword WBBase
)
4342 UNDEF_LSMBaseInListWb
;
4345 if (ADDREXCEPT (address
))
4347 INTERNALABORT (address
);
4351 if (!BIT (15) && state
->Bank
!= USERBANK
)
4353 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* temporary reg bank switch */
4354 UNDEF_LSMUserBankWb
;
4357 if (BIT (21) && LHSReg
!= 15)
4360 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4361 dest
= ARMul_LoadWordN (state
, address
);
4362 if (!state
->abortSig
)
4363 state
->Reg
[temp
++] = dest
;
4364 else if (!state
->Aborted
)
4365 state
->Aborted
= ARMul_DataAbortV
;
4367 for (; temp
< 16; temp
++) /* S cycles from here on */
4369 { /* load this register */
4371 dest
= ARMul_LoadWordS (state
, address
);
4372 if (!state
->abortSig
&& !state
->Aborted
)
4373 state
->Reg
[temp
] = dest
;
4374 else if (!state
->Aborted
)
4375 state
->Aborted
= ARMul_DataAbortV
;
4378 if (BIT (15) && !state
->Aborted
)
4379 { /* PC is in the reg list */
4381 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4383 state
->Cpsr
= GETSPSR (state
->Bank
);
4384 ARMul_CPSRAltered (state
);
4386 WriteR15 (state
, PC
);
4388 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4389 { /* protect bits in user mode */
4390 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4391 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4392 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4393 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4396 ARMul_R15Altered (state
);
4401 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4402 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
4404 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
4408 if (BIT (21) && LHSReg
!= 15)
4415 /***************************************************************************\
4416 * This function does the work of storing the registers listed in an STM *
4417 * instruction, when the S bit is clear. The code here is always increment *
4418 * after, it's up to the caller to get the input address correct and to *
4419 * handle base register modification. *
4420 \***************************************************************************/
4423 StoreMult (ARMul_State
* state
, ARMword instr
,
4424 ARMword address
, ARMword WBBase
)
4430 UNDEF_LSMBaseInListWb
;
4433 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
4437 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4439 INTERNALABORT (address
);
4445 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4447 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4451 (void) ARMul_LoadWordN (state
, address
);
4452 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
4454 { /* save this register */
4456 (void) ARMul_LoadWordS (state
, address
);
4458 if (BIT (21) && LHSReg
!= 15)
4464 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4466 if (state
->abortSig
&& !state
->Aborted
)
4467 state
->Aborted
= ARMul_DataAbortV
;
4469 if (BIT (21) && LHSReg
!= 15)
4472 for (; temp
< 16; temp
++) /* S cycles from here on */
4474 { /* save this register */
4476 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4477 if (state
->abortSig
&& !state
->Aborted
)
4478 state
->Aborted
= ARMul_DataAbortV
;
4486 /***************************************************************************\
4487 * This function does the work of storing the registers listed in an STM *
4488 * instruction when the S bit is set. The code here is always increment *
4489 * after, it's up to the caller to get the input address correct and to *
4490 * handle base register modification. *
4491 \***************************************************************************/
4494 StoreSMult (ARMul_State
* state
, ARMword instr
,
4495 ARMword address
, ARMword WBBase
)
4501 UNDEF_LSMBaseInListWb
;
4504 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4506 INTERNALABORT (address
);
4512 if (state
->Bank
!= USERBANK
)
4514 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* Force User Bank */
4515 UNDEF_LSMUserBankWb
;
4518 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4520 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4524 (void) ARMul_LoadWordN (state
, address
);
4525 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
4527 { /* save this register */
4529 (void) ARMul_LoadWordS (state
, address
);
4531 if (BIT (21) && LHSReg
!= 15)
4537 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4539 if (state
->abortSig
&& !state
->Aborted
)
4540 state
->Aborted
= ARMul_DataAbortV
;
4542 if (BIT (21) && LHSReg
!= 15)
4545 for (; temp
< 16; temp
++) /* S cycles from here on */
4547 { /* save this register */
4549 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4550 if (state
->abortSig
&& !state
->Aborted
)
4551 state
->Aborted
= ARMul_DataAbortV
;
4554 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4555 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
4563 /***************************************************************************\
4564 * This function does the work of adding two 32bit values together, and *
4565 * calculating if a carry has occurred. *
4566 \***************************************************************************/
4569 Add32 (ARMword a1
, ARMword a2
, int *carry
)
4571 ARMword result
= (a1
+ a2
);
4572 unsigned int uresult
= (unsigned int) result
;
4573 unsigned int ua1
= (unsigned int) a1
;
4575 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4576 or (result > RdLo) then we have no carry: */
4577 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
4585 /***************************************************************************\
4586 * This function does the work of multiplying two 32bit values to give a *
4588 \***************************************************************************/
4591 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4593 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
4594 ARMword RdHi
= 0, RdLo
= 0, Rm
;
4595 int scount
; /* cycle count */
4597 nRdHi
= BITS (16, 19);
4598 nRdLo
= BITS (12, 15);
4602 /* Needed to calculate the cycle count: */
4603 Rm
= state
->Reg
[nRm
];
4605 /* Check for illegal operand combinations first: */
4609 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
4611 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
4613 ARMword Rs
= state
->Reg
[nRs
];
4618 /* Compute sign of result and adjust operands if necessary. */
4620 sign
= (Rm
^ Rs
) & 0x80000000;
4622 if (((signed long) Rm
) < 0)
4625 if (((signed long) Rs
) < 0)
4629 /* We can split the 32x32 into four 16x16 operations. This ensures
4630 that we do not lose precision on 32bit only hosts: */
4631 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
4632 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4633 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
4634 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4636 /* We now need to add all of these results together, taking care
4637 to propogate the carries from the additions: */
4638 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
4640 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
4642 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
4646 /* Negate result if necessary. */
4650 if (RdLo
== 0xFFFFFFFF)
4659 state
->Reg
[nRdLo
] = RdLo
;
4660 state
->Reg
[nRdHi
] = RdHi
;
4661 } /* else undefined result */
4663 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4667 /* Ensure that both RdHi and RdLo are used to compute Z, but
4668 don't let RdLo's sign bit make it to N. */
4669 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4672 /* The cycle count depends on whether the instruction is a signed or
4673 unsigned multiply, and what bits are clear in the multiplier: */
4674 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
4675 Rm
= ~Rm
; /* invert the bits to make the check against zero */
4677 if ((Rm
& 0xFFFFFF00) == 0)
4679 else if ((Rm
& 0xFFFF0000) == 0)
4681 else if ((Rm
& 0xFF000000) == 0)
4689 /***************************************************************************\
4690 * This function does the work of multiplying two 32bit values and adding *
4691 * a 64bit value to give a 64bit result. *
4692 \***************************************************************************/
4695 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4702 nRdHi
= BITS (16, 19);
4703 nRdLo
= BITS (12, 15);
4705 RdHi
= state
->Reg
[nRdHi
];
4706 RdLo
= state
->Reg
[nRdLo
];
4708 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
4710 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
4711 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
4713 state
->Reg
[nRdLo
] = RdLo
;
4714 state
->Reg
[nRdHi
] = RdHi
;
4718 /* Ensure that both RdHi and RdLo are used to compute Z, but
4719 don't let RdLo's sign bit make it to N. */
4720 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4723 return scount
+ 1; /* extra cycle for addition */