e0b2dd25a21c97fa8777d8ddb66857eeb37b9eff
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 unsigned StoreDoubleWord (ARMul_State
* state
, ARMword instr
,
44 static void LoadMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
46 static void StoreMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
48 static void LoadSMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
50 static void StoreSMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
52 static unsigned Multiply64 (ARMul_State
* state
, ARMword instr
,
53 int signextend
, int scc
);
54 static unsigned MultiplyAdd64 (ARMul_State
* state
, ARMword instr
,
55 int signextend
, int scc
);
56 static void Handle_Load_Double (ARMul_State
* state
, ARMword instr
);
57 static void Handle_Store_Double (ARMul_State
* state
, ARMword instr
);
59 #define LUNSIGNED (0) /* unsigned operation */
60 #define LSIGNED (1) /* signed operation */
61 #define LDEFAULT (0) /* default : do nothing */
62 #define LSCC (1) /* set condition codes on result */
64 #ifdef NEED_UI_LOOP_HOOK
65 /* How often to run the ui_loop update, when in use */
66 #define UI_LOOP_POLL_INTERVAL 0x32000
68 /* Counter for the ui_loop_hook update */
69 static long ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
71 /* Actual hook to call to run through gdb's gui event loop */
72 extern int (*ui_loop_hook
) (int);
73 #endif /* NEED_UI_LOOP_HOOK */
75 extern int stop_simulator
;
77 /***************************************************************************\
78 * short-hand macros for LDR/STR *
79 \***************************************************************************/
81 /* store post decrement writeback */
84 if (StoreHalfWord(state, instr, lhs)) \
85 LSBase = lhs - GetLS7RHS(state, instr) ;
87 /* store post increment writeback */
90 if (StoreHalfWord(state, instr, lhs)) \
91 LSBase = lhs + GetLS7RHS(state, instr) ;
93 /* store pre decrement */
95 (void)StoreHalfWord(state, instr, LHS - GetLS7RHS(state, instr)) ;
97 /* store pre decrement writeback */
98 #define SHPREDOWNWB() \
99 temp = LHS - GetLS7RHS(state, instr) ; \
100 if (StoreHalfWord(state, instr, temp)) \
103 /* store pre increment */
105 (void)StoreHalfWord(state, instr, LHS + GetLS7RHS(state, instr)) ;
107 /* store pre increment writeback */
108 #define SHPREUPWB() \
109 temp = LHS + GetLS7RHS(state, instr) ; \
110 if (StoreHalfWord(state, instr, temp)) \
113 /* Load post decrement writeback. */
114 #define LHPOSTDOWN() \
118 temp = lhs - GetLS7RHS (state, instr); \
120 switch (BITS (5, 6)) \
123 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
127 if (LoadByte (state, instr, lhs, LSIGNED)) \
131 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
134 case 0: /* SWP handled elsewhere. */ \
143 /* Load post increment writeback. */
148 temp = lhs + GetLS7RHS (state, instr); \
150 switch (BITS (5, 6)) \
153 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
157 if (LoadByte (state, instr, lhs, LSIGNED)) \
161 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
164 case 0: /* SWP handled elsewhere. */ \
174 /* load pre decrement */
175 #define LHPREDOWN() \
178 temp = LHS - GetLS7RHS(state,instr) ; \
179 switch (BITS(5,6)) { \
181 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
184 (void)LoadByte(state,instr,temp,LSIGNED) ; \
187 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
189 case 0: /* SWP handled elsewhere */ \
198 /* load pre decrement writeback */
199 #define LHPREDOWNWB() \
202 temp = LHS - GetLS7RHS(state, instr) ; \
203 switch (BITS(5,6)) { \
205 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
209 if (LoadByte(state,instr,temp,LSIGNED)) \
213 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
216 case 0: /* SWP handled elsewhere */ \
225 /* load pre increment */
229 temp = LHS + GetLS7RHS(state,instr) ; \
230 switch (BITS(5,6)) { \
232 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
235 (void)LoadByte(state,instr,temp,LSIGNED) ; \
238 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
240 case 0: /* SWP handled elsewhere */ \
249 /* load pre increment writeback */
250 #define LHPREUPWB() \
253 temp = LHS + GetLS7RHS(state, instr) ; \
254 switch (BITS(5,6)) { \
256 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
260 if (LoadByte(state,instr,temp,LSIGNED)) \
264 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
267 case 0: /* SWP handled elsewhere */ \
276 /***************************************************************************\
277 * EMULATION of ARM6 *
278 \***************************************************************************/
280 /* The PC pipeline value depends on whether ARM or Thumb instructions
281 are being executed: */
286 ARMul_Emulate32 (register ARMul_State
* state
)
290 ARMul_Emulate26 (register ARMul_State
* state
)
293 register ARMword instr
, /* the current instruction */
294 dest
= 0, /* almost the DestBus */
295 temp
, /* ubiquitous third hand */
296 pc
= 0; /* the address of the current instruction */
297 ARMword lhs
, rhs
; /* almost the ABus and BBus */
298 ARMword decoded
= 0, loaded
= 0; /* instruction pipeline */
300 /***************************************************************************\
301 * Execute the next instruction *
302 \***************************************************************************/
304 if (state
->NextInstr
< PRIMEPIPE
)
306 decoded
= state
->decoded
;
307 loaded
= state
->loaded
;
312 { /* just keep going */
314 switch (state
->NextInstr
)
317 state
->Reg
[15] += isize
; /* Advance the pipeline, and an S cycle */
321 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
325 state
->Reg
[15] += isize
; /* Advance the pipeline, and an N cycle */
329 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
334 pc
+= isize
; /* Program counter advanced, and an S cycle */
337 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
342 pc
+= isize
; /* Program counter advanced, and an N cycle */
345 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
349 case RESUME
: /* The program counter has been changed */
354 state
->Reg
[15] = pc
+ (isize
* 2);
356 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
357 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
358 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
362 default: /* The program counter has been changed */
367 state
->Reg
[15] = pc
+ (isize
* 2);
369 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
370 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
371 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
376 ARMul_EnvokeEvent (state
);
379 /* Enable this for a helpful bit of debugging when tracing is needed. */
380 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
385 if (state
->Exception
)
386 { /* Any exceptions */
387 if (state
->NresetSig
== LOW
)
389 ARMul_Abort (state
, ARMul_ResetV
);
392 else if (!state
->NfiqSig
&& !FFLAG
)
394 ARMul_Abort (state
, ARMul_FIQV
);
397 else if (!state
->NirqSig
&& !IFLAG
)
399 ARMul_Abort (state
, ARMul_IRQV
);
404 if (state
->CallDebug
> 0)
406 instr
= ARMul_Debug (state
, pc
, instr
);
407 if (state
->Emulate
< ONCE
)
409 state
->NextInstr
= RESUME
;
414 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
416 (void) fgetc (stdin
);
419 else if (state
->Emulate
< ONCE
)
421 state
->NextInstr
= RESUME
;
428 /* Provide Thumb instruction decoding. If the processor is in Thumb
429 mode, then we can simply decode the Thumb instruction, and map it
430 to the corresponding ARM instruction (by directly loading the
431 instr variable, and letting the normal ARM simulator
432 execute). There are some caveats to ensure that the correct
433 pipelined PC value is used when executing Thumb code, and also for
434 dealing with the BL instruction. */
436 { /* check if in Thumb mode */
438 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
441 ARMul_UndefInstr (state
, instr
); /* This is a Thumb instruction */
444 case t_branch
: /* already processed */
447 case t_decoded
: /* ARM instruction available */
448 instr
= new; /* so continue instruction decoding */
454 /***************************************************************************\
455 * Check the condition codes *
456 \***************************************************************************/
457 if ((temp
= TOPBITS (28)) == AL
)
458 goto mainswitch
; /* vile deed in the need for speed */
460 switch ((int) TOPBITS (28))
461 { /* check the condition code */
468 if (BITS (25, 27) == 5) /* BLX(1) */
472 state
->Reg
[14] = pc
+ 4;
474 dest
= pc
+ 8 + 1; /* Force entry into Thumb mode. */
476 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
478 dest
+= POSBRANCH
+ (BIT (24) << 1);
480 WriteR15Branch (state
, dest
);
483 else if ((instr
& 0xFC70F000) == 0xF450F000)
484 /* The PLD instruction. Ignored. */
487 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
488 ARMul_UndefInstr (state
, instr
);
517 temp
= (CFLAG
&& !ZFLAG
);
520 temp
= (!CFLAG
|| ZFLAG
);
523 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
526 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
529 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
532 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
536 /***************************************************************************\
537 * Actual execution of instructions begins here *
538 \***************************************************************************/
541 { /* if the condition codes don't match, stop here */
544 if (state
->is_XScale
)
546 if (BIT (20) == 0 && BITS (25, 27) == 0)
548 if (BITS (4, 7) == 0xD)
550 /* XScale Load Consecutive insn. */
551 ARMword temp
= GetLS7RHS (state
, instr
);
552 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
553 ARMword addr
= BIT (24) ? temp2
: temp
;
556 ARMul_UndefInstr (state
, instr
);
558 /* Alignment violation. */
559 ARMul_Abort (state
, ARMul_DataAbortV
);
562 int wb
= BIT (24) && BIT (21);
564 state
->Reg
[BITS (12, 15)] =
565 ARMul_LoadWordN (state
, addr
);
566 state
->Reg
[BITS (12, 15) + 1] =
567 ARMul_LoadWordN (state
, addr
+ 4);
574 else if (BITS (4, 7) == 0xF)
576 /* XScale Store Consecutive insn. */
577 ARMword temp
= GetLS7RHS (state
, instr
);
578 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
579 ARMword addr
= BIT (24) ? temp2
: temp
;
582 ARMul_UndefInstr (state
, instr
);
584 /* Alignment violation. */
585 ARMul_Abort (state
, ARMul_DataAbortV
);
588 ARMul_StoreWordN (state
, addr
,
589 state
->Reg
[BITS (12, 15)]);
590 ARMul_StoreWordN (state
, addr
+ 4,
591 state
->Reg
[BITS (12, 15) + 1]);
602 switch ((int) BITS (20, 27))
605 /***************************************************************************\
606 * Data Processing Register RHS Instructions *
607 \***************************************************************************/
609 case 0x00: /* AND reg and MUL */
611 if (BITS (4, 11) == 0xB)
613 /* STRH register offset, no write-back, down, post indexed */
617 if (BITS (4, 7) == 0xD)
619 Handle_Load_Double (state
, instr
);
622 if (BITS (4, 7) == 0xE)
624 Handle_Store_Double (state
, instr
);
628 if (BITS (4, 7) == 9)
630 rhs
= state
->Reg
[MULRHSReg
];
631 if (MULLHSReg
== MULDESTReg
)
634 state
->Reg
[MULDESTReg
] = 0;
636 else if (MULDESTReg
!= 15)
637 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
642 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
643 if (rhs
& (1L << dest
))
644 temp
= dest
; /* mult takes this many/2 I cycles */
645 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
655 case 0x01: /* ANDS reg and MULS */
657 if ((BITS (4, 11) & 0xF9) == 0x9)
659 /* LDR register offset, no write-back, down, post indexed */
661 /* fall through to rest of decoding */
664 if (BITS (4, 7) == 9)
666 rhs
= state
->Reg
[MULRHSReg
];
667 if (MULLHSReg
== MULDESTReg
)
670 state
->Reg
[MULDESTReg
] = 0;
674 else if (MULDESTReg
!= 15)
676 dest
= state
->Reg
[MULLHSReg
] * rhs
;
677 ARMul_NegZero (state
, dest
);
678 state
->Reg
[MULDESTReg
] = dest
;
684 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
685 if (rhs
& (1L << dest
))
686 temp
= dest
; /* mult takes this many/2 I cycles */
687 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
697 case 0x02: /* EOR reg and MLA */
699 if (BITS (4, 11) == 0xB)
701 /* STRH register offset, write-back, down, post indexed */
706 if (BITS (4, 7) == 9)
708 rhs
= state
->Reg
[MULRHSReg
];
709 if (MULLHSReg
== MULDESTReg
)
712 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
714 else if (MULDESTReg
!= 15)
715 state
->Reg
[MULDESTReg
] =
716 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
721 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
722 if (rhs
& (1L << dest
))
723 temp
= dest
; /* mult takes this many/2 I cycles */
724 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
734 case 0x03: /* EORS reg and MLAS */
736 if ((BITS (4, 11) & 0xF9) == 0x9)
738 /* LDR register offset, write-back, down, post-indexed */
740 /* fall through to rest of the decoding */
743 if (BITS (4, 7) == 9)
745 rhs
= state
->Reg
[MULRHSReg
];
746 if (MULLHSReg
== MULDESTReg
)
749 dest
= state
->Reg
[MULACCReg
];
750 ARMul_NegZero (state
, dest
);
751 state
->Reg
[MULDESTReg
] = dest
;
753 else if (MULDESTReg
!= 15)
756 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
757 ARMul_NegZero (state
, dest
);
758 state
->Reg
[MULDESTReg
] = dest
;
764 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
765 if (rhs
& (1L << dest
))
766 temp
= dest
; /* mult takes this many/2 I cycles */
767 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
777 case 0x04: /* SUB reg */
779 if (BITS (4, 7) == 0xB)
781 /* STRH immediate offset, no write-back, down, post indexed */
785 if (BITS (4, 7) == 0xD)
787 Handle_Load_Double (state
, instr
);
790 if (BITS (4, 7) == 0xE)
792 Handle_Store_Double (state
, instr
);
801 case 0x05: /* SUBS reg */
803 if ((BITS (4, 7) & 0x9) == 0x9)
805 /* LDR immediate offset, no write-back, down, post indexed */
807 /* fall through to the rest of the instruction decoding */
813 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
815 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
816 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
826 case 0x06: /* RSB reg */
828 if (BITS (4, 7) == 0xB)
830 /* STRH immediate offset, write-back, down, post indexed */
840 case 0x07: /* RSBS reg */
842 if ((BITS (4, 7) & 0x9) == 0x9)
844 /* LDR immediate offset, write-back, down, post indexed */
846 /* fall through to remainder of instruction decoding */
852 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
854 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
855 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
865 case 0x08: /* ADD reg */
867 if (BITS (4, 11) == 0xB)
869 /* STRH register offset, no write-back, up, post indexed */
873 if (BITS (4, 7) == 0xD)
875 Handle_Load_Double (state
, instr
);
878 if (BITS (4, 7) == 0xE)
880 Handle_Store_Double (state
, instr
);
885 if (BITS (4, 7) == 0x9)
888 ARMul_Icycles (state
,
889 Multiply64 (state
, instr
, LUNSIGNED
,
899 case 0x09: /* ADDS reg */
901 if ((BITS (4, 11) & 0xF9) == 0x9)
903 /* LDR register offset, no write-back, up, post indexed */
905 /* fall through to remaining instruction decoding */
909 if (BITS (4, 7) == 0x9)
912 ARMul_Icycles (state
,
913 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
922 if ((lhs
| rhs
) >> 30)
923 { /* possible C,V,N to set */
924 ASSIGNN (NEG (dest
));
925 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
926 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
937 case 0x0a: /* ADC reg */
939 if (BITS (4, 11) == 0xB)
941 /* STRH register offset, write-back, up, post-indexed */
947 if (BITS (4, 7) == 0x9)
950 ARMul_Icycles (state
,
951 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
957 dest
= LHS
+ rhs
+ CFLAG
;
961 case 0x0b: /* ADCS reg */
963 if ((BITS (4, 11) & 0xF9) == 0x9)
965 /* LDR register offset, write-back, up, post indexed */
967 /* fall through to remaining instruction decoding */
971 if (BITS (4, 7) == 0x9)
974 ARMul_Icycles (state
,
975 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
982 dest
= lhs
+ rhs
+ CFLAG
;
984 if ((lhs
| rhs
) >> 30)
985 { /* possible C,V,N to set */
986 ASSIGNN (NEG (dest
));
987 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
988 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
999 case 0x0c: /* SBC reg */
1001 if (BITS (4, 7) == 0xB)
1003 /* STRH immediate offset, no write-back, up post indexed */
1007 if (BITS (4, 7) == 0xD)
1009 Handle_Load_Double (state
, instr
);
1012 if (BITS (4, 7) == 0xE)
1014 Handle_Store_Double (state
, instr
);
1019 if (BITS (4, 7) == 0x9)
1022 ARMul_Icycles (state
,
1023 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
1029 dest
= LHS
- rhs
- !CFLAG
;
1033 case 0x0d: /* SBCS reg */
1035 if ((BITS (4, 7) & 0x9) == 0x9)
1037 /* LDR immediate offset, no write-back, up, post indexed */
1042 if (BITS (4, 7) == 0x9)
1045 ARMul_Icycles (state
,
1046 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
1053 dest
= lhs
- rhs
- !CFLAG
;
1054 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1056 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1057 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1067 case 0x0e: /* RSC reg */
1069 if (BITS (4, 7) == 0xB)
1071 /* STRH immediate offset, write-back, up, post indexed */
1077 if (BITS (4, 7) == 0x9)
1080 ARMul_Icycles (state
,
1081 MultiplyAdd64 (state
, instr
, LSIGNED
,
1087 dest
= rhs
- LHS
- !CFLAG
;
1091 case 0x0f: /* RSCS reg */
1093 if ((BITS (4, 7) & 0x9) == 0x9)
1095 /* LDR immediate offset, write-back, up, post indexed */
1097 /* fall through to remaining instruction decoding */
1101 if (BITS (4, 7) == 0x9)
1104 ARMul_Icycles (state
,
1105 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
1112 dest
= rhs
- lhs
- !CFLAG
;
1113 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1115 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1116 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1126 case 0x10: /* TST reg and MRS CPSR and SWP word */
1129 if (BIT (4) == 0 && BIT (7) == 1)
1131 /* ElSegundo SMLAxy insn. */
1132 ARMword op1
= state
->Reg
[BITS (0, 3)];
1133 ARMword op2
= state
->Reg
[BITS (8, 11)];
1134 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1148 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
1150 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
1154 if (BITS (4, 11) == 5)
1156 /* ElSegundo QADD insn. */
1157 ARMword op1
= state
->Reg
[BITS (0, 3)];
1158 ARMword op2
= state
->Reg
[BITS (16, 19)];
1159 ARMword result
= op1
+ op2
;
1160 if (AddOverflow (op1
, op2
, result
))
1162 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1165 state
->Reg
[BITS (12, 15)] = result
;
1170 if (BITS (4, 11) == 0xB)
1172 /* STRH register offset, no write-back, down, pre indexed */
1176 if (BITS (4, 7) == 0xD)
1178 Handle_Load_Double (state
, instr
);
1181 if (BITS (4, 7) == 0xE)
1183 Handle_Store_Double (state
, instr
);
1187 if (BITS (4, 11) == 9)
1193 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1195 INTERNALABORT (temp
);
1196 (void) ARMul_LoadWordN (state
, temp
);
1197 (void) ARMul_LoadWordN (state
, temp
);
1201 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1203 DEST
= ARMul_Align (state
, temp
, dest
);
1206 if (state
->abortSig
|| state
->Aborted
)
1211 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1214 DEST
= ECC
| EINT
| EMODE
;
1222 case 0x11: /* TSTP reg */
1224 if ((BITS (4, 11) & 0xF9) == 0x9)
1226 /* LDR register offset, no write-back, down, pre indexed */
1228 /* continue with remaining instruction decode */
1234 state
->Cpsr
= GETSPSR (state
->Bank
);
1235 ARMul_CPSRAltered (state
);
1246 ARMul_NegZero (state
, dest
);
1250 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6) */
1253 if (BITS (4, 7) == 3)
1259 temp
= (pc
+ 2) | 1;
1263 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1264 state
->Reg
[14] = temp
;
1271 if (BIT (4) == 0 && BIT (7) == 1
1272 && (BIT (5) == 0 || BITS (12, 15) == 0))
1274 /* ElSegundo SMLAWy/SMULWy insn. */
1275 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1276 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1277 unsigned long long result
;
1281 if (op1
& 0x80000000)
1286 result
= (op1
* op2
) >> 16;
1290 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1292 if (AddOverflow (result
, Rn
, result
+ Rn
))
1296 state
->Reg
[BITS (16, 19)] = result
;
1300 if (BITS (4, 11) == 5)
1302 /* ElSegundo QSUB insn. */
1303 ARMword op1
= state
->Reg
[BITS (0, 3)];
1304 ARMword op2
= state
->Reg
[BITS (16, 19)];
1305 ARMword result
= op1
- op2
;
1307 if (SubOverflow (op1
, op2
, result
))
1309 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1313 state
->Reg
[BITS (12, 15)] = result
;
1318 if (BITS (4, 11) == 0xB)
1320 /* STRH register offset, write-back, down, pre indexed */
1324 if (BITS (4, 27) == 0x12FFF1)
1327 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1330 if (BITS (4, 7) == 0xD)
1332 Handle_Load_Double (state
, instr
);
1335 if (BITS (4, 7) == 0xE)
1337 Handle_Store_Double (state
, instr
);
1343 if (BITS (4, 7) == 0x7)
1346 extern int SWI_vector_installed
;
1348 /* Hardware is allowed to optionally override this
1349 instruction and treat it as a breakpoint. Since
1350 this is a simulator not hardware, we take the position
1351 that if a SWI vector was not installed, then an Abort
1352 vector was probably not installed either, and so
1353 normally this instruction would be ignored, even if an
1354 Abort is generated. This is a bad thing, since GDB
1355 uses this instruction for its breakpoints (at least in
1356 Thumb mode it does). So intercept the instruction here
1357 and generate a breakpoint SWI instead. */
1358 if (! SWI_vector_installed
)
1359 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1362 /* BKPT - normally this will cause an abort, but for the
1363 XScale if bit 31 in register 10 of coprocessor 14 is
1364 clear, then this is treated as a no-op. */
1365 if (state
->is_XScale
)
1367 if (read_cp14_reg (10) & (1UL << 31))
1371 value
= read_cp14_reg (10);
1375 write_cp14_reg (10, value
);
1376 write_cp15_reg (5, 0, 0, 0x200); /* Set FSR. */
1377 write_cp15_reg (6, 0, 0, pc
); /* Set FAR. */
1383 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
1389 /* MSR reg to CPSR */
1393 /* Don't allow TBIT to be set by MSR. */
1396 ARMul_FixCPSR (state
, instr
, temp
);
1404 case 0x13: /* TEQP reg */
1406 if ((BITS (4, 11) & 0xF9) == 0x9)
1408 /* LDR register offset, write-back, down, pre indexed */
1410 /* continue with remaining instruction decode */
1416 state
->Cpsr
= GETSPSR (state
->Bank
);
1417 ARMul_CPSRAltered (state
);
1428 ARMul_NegZero (state
, dest
);
1432 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1435 if (BIT (4) == 0 && BIT (7) == 1)
1437 /* ElSegundo SMLALxy insn. */
1438 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1439 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1440 unsigned long long dest
;
1441 unsigned long long result
;
1454 dest
= (unsigned long long) state
->Reg
[BITS (16, 19)] << 32;
1455 dest
|= state
->Reg
[BITS (12, 15)];
1457 state
->Reg
[BITS (12, 15)] = dest
;
1458 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1462 if (BITS (4, 11) == 5)
1464 /* ElSegundo QDADD insn. */
1465 ARMword op1
= state
->Reg
[BITS (0, 3)];
1466 ARMword op2
= state
->Reg
[BITS (16, 19)];
1467 ARMword op2d
= op2
+ op2
;
1470 if (AddOverflow (op2
, op2
, op2d
))
1473 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1476 result
= op1
+ op2d
;
1477 if (AddOverflow (op1
, op2d
, result
))
1480 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1483 state
->Reg
[BITS (12, 15)] = result
;
1488 if (BITS (4, 7) == 0xB)
1490 /* STRH immediate offset, no write-back, down, pre indexed */
1494 if (BITS (4, 7) == 0xD)
1496 Handle_Load_Double (state
, instr
);
1499 if (BITS (4, 7) == 0xE)
1501 Handle_Store_Double (state
, instr
);
1505 if (BITS (4, 11) == 9)
1511 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1513 INTERNALABORT (temp
);
1514 (void) ARMul_LoadByte (state
, temp
);
1515 (void) ARMul_LoadByte (state
, temp
);
1519 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1520 if (state
->abortSig
|| state
->Aborted
)
1525 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1528 DEST
= GETSPSR (state
->Bank
);
1536 case 0x15: /* CMPP reg */
1538 if ((BITS (4, 7) & 0x9) == 0x9)
1540 /* LDR immediate offset, no write-back, down, pre indexed */
1542 /* continue with remaining instruction decode */
1548 state
->Cpsr
= GETSPSR (state
->Bank
);
1549 ARMul_CPSRAltered (state
);
1561 ARMul_NegZero (state
, dest
);
1562 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1564 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1565 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1575 case 0x16: /* CMN reg and MSR reg to SPSR */
1578 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1580 /* ElSegundo SMULxy insn. */
1581 ARMword op1
= state
->Reg
[BITS (0, 3)];
1582 ARMword op2
= state
->Reg
[BITS (8, 11)];
1583 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1596 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1600 if (BITS (4, 11) == 5)
1602 /* ElSegundo QDSUB insn. */
1603 ARMword op1
= state
->Reg
[BITS (0, 3)];
1604 ARMword op2
= state
->Reg
[BITS (16, 19)];
1605 ARMword op2d
= op2
+ op2
;
1608 if (AddOverflow (op2
, op2
, op2d
))
1611 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1614 result
= op1
- op2d
;
1615 if (SubOverflow (op1
, op2d
, result
))
1618 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1621 state
->Reg
[BITS (12, 15)] = result
;
1628 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1630 /* ARM5 CLZ insn. */
1631 ARMword op1
= state
->Reg
[BITS (0, 3)];
1635 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1638 state
->Reg
[BITS (12, 15)] = result
;
1643 if (BITS (4, 7) == 0xB)
1645 /* STRH immediate offset, write-back, down, pre indexed */
1649 if (BITS (4, 7) == 0xD)
1651 Handle_Load_Double (state
, instr
);
1654 if (BITS (4, 7) == 0xE)
1656 Handle_Store_Double (state
, instr
);
1663 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1671 case 0x17: /* CMNP reg */
1673 if ((BITS (4, 7) & 0x9) == 0x9)
1675 /* LDR immediate offset, write-back, down, pre indexed */
1677 /* continue with remaining instruction decoding */
1683 state
->Cpsr
= GETSPSR (state
->Bank
);
1684 ARMul_CPSRAltered (state
);
1697 ASSIGNZ (dest
== 0);
1698 if ((lhs
| rhs
) >> 30)
1699 { /* possible C,V,N to set */
1700 ASSIGNN (NEG (dest
));
1701 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1702 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1713 case 0x18: /* ORR reg */
1715 if (BITS (4, 11) == 0xB)
1717 /* STRH register offset, no write-back, up, pre indexed */
1721 if (BITS (4, 7) == 0xD)
1723 Handle_Load_Double (state
, instr
);
1726 if (BITS (4, 7) == 0xE)
1728 Handle_Store_Double (state
, instr
);
1737 case 0x19: /* ORRS reg */
1739 if ((BITS (4, 11) & 0xF9) == 0x9)
1741 /* LDR register offset, no write-back, up, pre indexed */
1743 /* continue with remaining instruction decoding */
1751 case 0x1a: /* MOV reg */
1753 if (BITS (4, 11) == 0xB)
1755 /* STRH register offset, write-back, up, pre indexed */
1759 if (BITS (4, 7) == 0xD)
1761 Handle_Load_Double (state
, instr
);
1764 if (BITS (4, 7) == 0xE)
1766 Handle_Store_Double (state
, instr
);
1774 case 0x1b: /* MOVS reg */
1776 if ((BITS (4, 11) & 0xF9) == 0x9)
1778 /* LDR register offset, write-back, up, pre indexed */
1780 /* continue with remaining instruction decoding */
1787 case 0x1c: /* BIC reg */
1789 if (BITS (4, 7) == 0xB)
1791 /* STRH immediate offset, no write-back, up, pre indexed */
1795 if (BITS (4, 7) == 0xD)
1797 Handle_Load_Double (state
, instr
);
1800 else if (BITS (4, 7) == 0xE)
1802 Handle_Store_Double (state
, instr
);
1811 case 0x1d: /* BICS reg */
1813 if ((BITS (4, 7) & 0x9) == 0x9)
1815 /* LDR immediate offset, no write-back, up, pre indexed */
1817 /* continue with instruction decoding */
1825 case 0x1e: /* MVN reg */
1827 if (BITS (4, 7) == 0xB)
1829 /* STRH immediate offset, write-back, up, pre indexed */
1833 if (BITS (4, 7) == 0xD)
1835 Handle_Load_Double (state
, instr
);
1838 if (BITS (4, 7) == 0xE)
1840 Handle_Store_Double (state
, instr
);
1848 case 0x1f: /* MVNS reg */
1850 if ((BITS (4, 7) & 0x9) == 0x9)
1852 /* LDR immediate offset, write-back, up, pre indexed */
1854 /* continue instruction decoding */
1861 /***************************************************************************\
1862 * Data Processing Immediate RHS Instructions *
1863 \***************************************************************************/
1865 case 0x20: /* AND immed */
1866 dest
= LHS
& DPImmRHS
;
1870 case 0x21: /* ANDS immed */
1876 case 0x22: /* EOR immed */
1877 dest
= LHS
^ DPImmRHS
;
1881 case 0x23: /* EORS immed */
1887 case 0x24: /* SUB immed */
1888 dest
= LHS
- DPImmRHS
;
1892 case 0x25: /* SUBS immed */
1896 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1898 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1899 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1909 case 0x26: /* RSB immed */
1910 dest
= DPImmRHS
- LHS
;
1914 case 0x27: /* RSBS immed */
1918 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1920 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1921 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1931 case 0x28: /* ADD immed */
1932 dest
= LHS
+ DPImmRHS
;
1936 case 0x29: /* ADDS immed */
1940 ASSIGNZ (dest
== 0);
1941 if ((lhs
| rhs
) >> 30)
1942 { /* possible C,V,N to set */
1943 ASSIGNN (NEG (dest
));
1944 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1945 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1956 case 0x2a: /* ADC immed */
1957 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1961 case 0x2b: /* ADCS immed */
1964 dest
= lhs
+ rhs
+ CFLAG
;
1965 ASSIGNZ (dest
== 0);
1966 if ((lhs
| rhs
) >> 30)
1967 { /* possible C,V,N to set */
1968 ASSIGNN (NEG (dest
));
1969 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1970 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1981 case 0x2c: /* SBC immed */
1982 dest
= LHS
- DPImmRHS
- !CFLAG
;
1986 case 0x2d: /* SBCS immed */
1989 dest
= lhs
- rhs
- !CFLAG
;
1990 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1992 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1993 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2003 case 0x2e: /* RSC immed */
2004 dest
= DPImmRHS
- LHS
- !CFLAG
;
2008 case 0x2f: /* RSCS immed */
2011 dest
= rhs
- lhs
- !CFLAG
;
2012 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2014 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2015 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2025 case 0x30: /* TST immed */
2029 case 0x31: /* TSTP immed */
2033 state
->Cpsr
= GETSPSR (state
->Bank
);
2034 ARMul_CPSRAltered (state
);
2036 temp
= LHS
& DPImmRHS
;
2042 DPSImmRHS
; /* TST immed */
2044 ARMul_NegZero (state
, dest
);
2048 case 0x32: /* TEQ immed and MSR immed to CPSR */
2050 { /* MSR immed to CPSR */
2051 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2059 case 0x33: /* TEQP immed */
2063 state
->Cpsr
= GETSPSR (state
->Bank
);
2064 ARMul_CPSRAltered (state
);
2066 temp
= LHS
^ DPImmRHS
;
2072 DPSImmRHS
; /* TEQ immed */
2074 ARMul_NegZero (state
, dest
);
2078 case 0x34: /* CMP immed */
2082 case 0x35: /* CMPP immed */
2086 state
->Cpsr
= GETSPSR (state
->Bank
);
2087 ARMul_CPSRAltered (state
);
2089 temp
= LHS
- DPImmRHS
;
2096 lhs
= LHS
; /* CMP immed */
2099 ARMul_NegZero (state
, dest
);
2100 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2102 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2103 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2113 case 0x36: /* CMN immed and MSR immed to SPSR */
2114 if (DESTReg
== 15) /* MSR */
2115 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2122 case 0x37: /* CMNP immed */
2126 state
->Cpsr
= GETSPSR (state
->Bank
);
2127 ARMul_CPSRAltered (state
);
2129 temp
= LHS
+ DPImmRHS
;
2136 lhs
= LHS
; /* CMN immed */
2139 ASSIGNZ (dest
== 0);
2140 if ((lhs
| rhs
) >> 30)
2141 { /* possible C,V,N to set */
2142 ASSIGNN (NEG (dest
));
2143 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2144 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2155 case 0x38: /* ORR immed */
2156 dest
= LHS
| DPImmRHS
;
2160 case 0x39: /* ORRS immed */
2166 case 0x3a: /* MOV immed */
2171 case 0x3b: /* MOVS immed */
2176 case 0x3c: /* BIC immed */
2177 dest
= LHS
& ~DPImmRHS
;
2181 case 0x3d: /* BICS immed */
2187 case 0x3e: /* MVN immed */
2192 case 0x3f: /* MVNS immed */
2197 /***************************************************************************\
2198 * Single Data Transfer Immediate RHS Instructions *
2199 \***************************************************************************/
2201 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
2203 if (StoreWord (state
, instr
, lhs
))
2204 LSBase
= lhs
- LSImmRHS
;
2207 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
2209 if (LoadWord (state
, instr
, lhs
))
2210 LSBase
= lhs
- LSImmRHS
;
2213 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
2214 UNDEF_LSRBaseEQDestWb
;
2217 temp
= lhs
- LSImmRHS
;
2218 state
->NtransSig
= LOW
;
2219 if (StoreWord (state
, instr
, lhs
))
2221 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2224 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
2225 UNDEF_LSRBaseEQDestWb
;
2228 state
->NtransSig
= LOW
;
2229 if (LoadWord (state
, instr
, lhs
))
2230 LSBase
= lhs
- LSImmRHS
;
2231 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2234 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
2236 if (StoreByte (state
, instr
, lhs
))
2237 LSBase
= lhs
- LSImmRHS
;
2240 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
2242 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2243 LSBase
= lhs
- LSImmRHS
;
2246 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
2247 UNDEF_LSRBaseEQDestWb
;
2250 state
->NtransSig
= LOW
;
2251 if (StoreByte (state
, instr
, lhs
))
2252 LSBase
= lhs
- LSImmRHS
;
2253 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2256 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
2257 UNDEF_LSRBaseEQDestWb
;
2260 state
->NtransSig
= LOW
;
2261 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2262 LSBase
= lhs
- LSImmRHS
;
2263 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2266 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
2268 if (StoreWord (state
, instr
, lhs
))
2269 LSBase
= lhs
+ LSImmRHS
;
2272 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
2274 if (LoadWord (state
, instr
, lhs
))
2275 LSBase
= lhs
+ LSImmRHS
;
2278 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
2279 UNDEF_LSRBaseEQDestWb
;
2282 state
->NtransSig
= LOW
;
2283 if (StoreWord (state
, instr
, lhs
))
2284 LSBase
= lhs
+ LSImmRHS
;
2285 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2288 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
2289 UNDEF_LSRBaseEQDestWb
;
2292 state
->NtransSig
= LOW
;
2293 if (LoadWord (state
, instr
, lhs
))
2294 LSBase
= lhs
+ LSImmRHS
;
2295 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2298 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
2300 if (StoreByte (state
, instr
, lhs
))
2301 LSBase
= lhs
+ LSImmRHS
;
2304 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
2306 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2307 LSBase
= lhs
+ LSImmRHS
;
2310 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
2311 UNDEF_LSRBaseEQDestWb
;
2314 state
->NtransSig
= LOW
;
2315 if (StoreByte (state
, instr
, lhs
))
2316 LSBase
= lhs
+ LSImmRHS
;
2317 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2320 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
2321 UNDEF_LSRBaseEQDestWb
;
2324 state
->NtransSig
= LOW
;
2325 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2326 LSBase
= lhs
+ LSImmRHS
;
2327 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2331 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
2332 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2335 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
2336 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2339 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
2340 UNDEF_LSRBaseEQDestWb
;
2342 temp
= LHS
- LSImmRHS
;
2343 if (StoreWord (state
, instr
, temp
))
2347 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
2348 UNDEF_LSRBaseEQDestWb
;
2350 temp
= LHS
- LSImmRHS
;
2351 if (LoadWord (state
, instr
, temp
))
2355 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
2356 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2359 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
2360 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2363 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
2364 UNDEF_LSRBaseEQDestWb
;
2366 temp
= LHS
- LSImmRHS
;
2367 if (StoreByte (state
, instr
, temp
))
2371 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
2372 UNDEF_LSRBaseEQDestWb
;
2374 temp
= LHS
- LSImmRHS
;
2375 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2379 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
2380 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2383 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
2384 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2387 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
2388 UNDEF_LSRBaseEQDestWb
;
2390 temp
= LHS
+ LSImmRHS
;
2391 if (StoreWord (state
, instr
, temp
))
2395 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
2396 UNDEF_LSRBaseEQDestWb
;
2398 temp
= LHS
+ LSImmRHS
;
2399 if (LoadWord (state
, instr
, temp
))
2403 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
2404 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2407 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
2408 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2411 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
2412 UNDEF_LSRBaseEQDestWb
;
2414 temp
= LHS
+ LSImmRHS
;
2415 if (StoreByte (state
, instr
, temp
))
2419 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
2420 UNDEF_LSRBaseEQDestWb
;
2422 temp
= LHS
+ LSImmRHS
;
2423 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2427 /***************************************************************************\
2428 * Single Data Transfer Register RHS Instructions *
2429 \***************************************************************************/
2431 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
2434 ARMul_UndefInstr (state
, instr
);
2437 UNDEF_LSRBaseEQOffWb
;
2438 UNDEF_LSRBaseEQDestWb
;
2442 if (StoreWord (state
, instr
, lhs
))
2443 LSBase
= lhs
- LSRegRHS
;
2446 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
2449 ARMul_UndefInstr (state
, instr
);
2452 UNDEF_LSRBaseEQOffWb
;
2453 UNDEF_LSRBaseEQDestWb
;
2457 temp
= lhs
- LSRegRHS
;
2458 if (LoadWord (state
, instr
, lhs
))
2462 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2465 ARMul_UndefInstr (state
, instr
);
2468 UNDEF_LSRBaseEQOffWb
;
2469 UNDEF_LSRBaseEQDestWb
;
2473 state
->NtransSig
= LOW
;
2474 if (StoreWord (state
, instr
, lhs
))
2475 LSBase
= lhs
- LSRegRHS
;
2476 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2479 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2482 ARMul_UndefInstr (state
, instr
);
2485 UNDEF_LSRBaseEQOffWb
;
2486 UNDEF_LSRBaseEQDestWb
;
2490 temp
= lhs
- LSRegRHS
;
2491 state
->NtransSig
= LOW
;
2492 if (LoadWord (state
, instr
, lhs
))
2494 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2497 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2500 ARMul_UndefInstr (state
, instr
);
2503 UNDEF_LSRBaseEQOffWb
;
2504 UNDEF_LSRBaseEQDestWb
;
2508 if (StoreByte (state
, instr
, lhs
))
2509 LSBase
= lhs
- LSRegRHS
;
2512 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2515 ARMul_UndefInstr (state
, instr
);
2518 UNDEF_LSRBaseEQOffWb
;
2519 UNDEF_LSRBaseEQDestWb
;
2523 temp
= lhs
- LSRegRHS
;
2524 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2528 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2531 ARMul_UndefInstr (state
, instr
);
2534 UNDEF_LSRBaseEQOffWb
;
2535 UNDEF_LSRBaseEQDestWb
;
2539 state
->NtransSig
= LOW
;
2540 if (StoreByte (state
, instr
, lhs
))
2541 LSBase
= lhs
- LSRegRHS
;
2542 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2545 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2548 ARMul_UndefInstr (state
, instr
);
2551 UNDEF_LSRBaseEQOffWb
;
2552 UNDEF_LSRBaseEQDestWb
;
2556 temp
= lhs
- LSRegRHS
;
2557 state
->NtransSig
= LOW
;
2558 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2560 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2563 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2566 ARMul_UndefInstr (state
, instr
);
2569 UNDEF_LSRBaseEQOffWb
;
2570 UNDEF_LSRBaseEQDestWb
;
2574 if (StoreWord (state
, instr
, lhs
))
2575 LSBase
= lhs
+ LSRegRHS
;
2578 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2581 ARMul_UndefInstr (state
, instr
);
2584 UNDEF_LSRBaseEQOffWb
;
2585 UNDEF_LSRBaseEQDestWb
;
2589 temp
= lhs
+ LSRegRHS
;
2590 if (LoadWord (state
, instr
, lhs
))
2594 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2597 ARMul_UndefInstr (state
, instr
);
2600 UNDEF_LSRBaseEQOffWb
;
2601 UNDEF_LSRBaseEQDestWb
;
2605 state
->NtransSig
= LOW
;
2606 if (StoreWord (state
, instr
, lhs
))
2607 LSBase
= lhs
+ LSRegRHS
;
2608 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2611 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2614 ARMul_UndefInstr (state
, instr
);
2617 UNDEF_LSRBaseEQOffWb
;
2618 UNDEF_LSRBaseEQDestWb
;
2622 temp
= lhs
+ LSRegRHS
;
2623 state
->NtransSig
= LOW
;
2624 if (LoadWord (state
, instr
, lhs
))
2626 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2629 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2632 ARMul_UndefInstr (state
, instr
);
2635 UNDEF_LSRBaseEQOffWb
;
2636 UNDEF_LSRBaseEQDestWb
;
2640 if (StoreByte (state
, instr
, lhs
))
2641 LSBase
= lhs
+ LSRegRHS
;
2644 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2647 ARMul_UndefInstr (state
, instr
);
2650 UNDEF_LSRBaseEQOffWb
;
2651 UNDEF_LSRBaseEQDestWb
;
2655 temp
= lhs
+ LSRegRHS
;
2656 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2660 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2663 ARMul_UndefInstr (state
, instr
);
2666 UNDEF_LSRBaseEQOffWb
;
2667 UNDEF_LSRBaseEQDestWb
;
2671 state
->NtransSig
= LOW
;
2672 if (StoreByte (state
, instr
, lhs
))
2673 LSBase
= lhs
+ LSRegRHS
;
2674 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2677 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2680 ARMul_UndefInstr (state
, instr
);
2683 UNDEF_LSRBaseEQOffWb
;
2684 UNDEF_LSRBaseEQDestWb
;
2688 temp
= lhs
+ LSRegRHS
;
2689 state
->NtransSig
= LOW
;
2690 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2692 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2696 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2699 ARMul_UndefInstr (state
, instr
);
2702 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2705 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2708 ARMul_UndefInstr (state
, instr
);
2711 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2714 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2717 ARMul_UndefInstr (state
, instr
);
2720 UNDEF_LSRBaseEQOffWb
;
2721 UNDEF_LSRBaseEQDestWb
;
2724 temp
= LHS
- LSRegRHS
;
2725 if (StoreWord (state
, instr
, temp
))
2729 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2732 ARMul_UndefInstr (state
, instr
);
2735 UNDEF_LSRBaseEQOffWb
;
2736 UNDEF_LSRBaseEQDestWb
;
2739 temp
= LHS
- LSRegRHS
;
2740 if (LoadWord (state
, instr
, temp
))
2744 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2747 ARMul_UndefInstr (state
, instr
);
2750 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2753 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2756 ARMul_UndefInstr (state
, instr
);
2759 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2762 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2765 ARMul_UndefInstr (state
, instr
);
2768 UNDEF_LSRBaseEQOffWb
;
2769 UNDEF_LSRBaseEQDestWb
;
2772 temp
= LHS
- LSRegRHS
;
2773 if (StoreByte (state
, instr
, temp
))
2777 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2780 ARMul_UndefInstr (state
, instr
);
2783 UNDEF_LSRBaseEQOffWb
;
2784 UNDEF_LSRBaseEQDestWb
;
2787 temp
= LHS
- LSRegRHS
;
2788 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2792 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2795 ARMul_UndefInstr (state
, instr
);
2798 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2801 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2804 ARMul_UndefInstr (state
, instr
);
2807 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2810 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2813 ARMul_UndefInstr (state
, instr
);
2816 UNDEF_LSRBaseEQOffWb
;
2817 UNDEF_LSRBaseEQDestWb
;
2820 temp
= LHS
+ LSRegRHS
;
2821 if (StoreWord (state
, instr
, temp
))
2825 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2828 ARMul_UndefInstr (state
, instr
);
2831 UNDEF_LSRBaseEQOffWb
;
2832 UNDEF_LSRBaseEQDestWb
;
2835 temp
= LHS
+ LSRegRHS
;
2836 if (LoadWord (state
, instr
, temp
))
2840 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2843 ARMul_UndefInstr (state
, instr
);
2846 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2849 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2852 ARMul_UndefInstr (state
, instr
);
2855 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2858 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2861 ARMul_UndefInstr (state
, instr
);
2864 UNDEF_LSRBaseEQOffWb
;
2865 UNDEF_LSRBaseEQDestWb
;
2868 temp
= LHS
+ LSRegRHS
;
2869 if (StoreByte (state
, instr
, temp
))
2873 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2876 /* Check for the special breakpoint opcode.
2877 This value should correspond to the value defined
2878 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2879 if (BITS (0, 19) == 0xfdefe)
2881 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2882 ARMul_Abort (state
, ARMul_SWIV
);
2885 ARMul_UndefInstr (state
, instr
);
2888 UNDEF_LSRBaseEQOffWb
;
2889 UNDEF_LSRBaseEQDestWb
;
2892 temp
= LHS
+ LSRegRHS
;
2893 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2897 /***************************************************************************\
2898 * Multiple Data Transfer Instructions *
2899 \***************************************************************************/
2901 case 0x80: /* Store, No WriteBack, Post Dec */
2902 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2905 case 0x81: /* Load, No WriteBack, Post Dec */
2906 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2909 case 0x82: /* Store, WriteBack, Post Dec */
2910 temp
= LSBase
- LSMNumRegs
;
2911 STOREMULT (instr
, temp
+ 4L, temp
);
2914 case 0x83: /* Load, WriteBack, Post Dec */
2915 temp
= LSBase
- LSMNumRegs
;
2916 LOADMULT (instr
, temp
+ 4L, temp
);
2919 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2920 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2923 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2924 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2927 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2928 temp
= LSBase
- LSMNumRegs
;
2929 STORESMULT (instr
, temp
+ 4L, temp
);
2932 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2933 temp
= LSBase
- LSMNumRegs
;
2934 LOADSMULT (instr
, temp
+ 4L, temp
);
2938 case 0x88: /* Store, No WriteBack, Post Inc */
2939 STOREMULT (instr
, LSBase
, 0L);
2942 case 0x89: /* Load, No WriteBack, Post Inc */
2943 LOADMULT (instr
, LSBase
, 0L);
2946 case 0x8a: /* Store, WriteBack, Post Inc */
2948 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
2951 case 0x8b: /* Load, WriteBack, Post Inc */
2953 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
2956 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2957 STORESMULT (instr
, LSBase
, 0L);
2960 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2961 LOADSMULT (instr
, LSBase
, 0L);
2964 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2966 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
2969 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2971 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
2975 case 0x90: /* Store, No WriteBack, Pre Dec */
2976 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2979 case 0x91: /* Load, No WriteBack, Pre Dec */
2980 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2983 case 0x92: /* Store, WriteBack, Pre Dec */
2984 temp
= LSBase
- LSMNumRegs
;
2985 STOREMULT (instr
, temp
, temp
);
2988 case 0x93: /* Load, WriteBack, Pre Dec */
2989 temp
= LSBase
- LSMNumRegs
;
2990 LOADMULT (instr
, temp
, temp
);
2993 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2994 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2997 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2998 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3001 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
3002 temp
= LSBase
- LSMNumRegs
;
3003 STORESMULT (instr
, temp
, temp
);
3006 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
3007 temp
= LSBase
- LSMNumRegs
;
3008 LOADSMULT (instr
, temp
, temp
);
3012 case 0x98: /* Store, No WriteBack, Pre Inc */
3013 STOREMULT (instr
, LSBase
+ 4L, 0L);
3016 case 0x99: /* Load, No WriteBack, Pre Inc */
3017 LOADMULT (instr
, LSBase
+ 4L, 0L);
3020 case 0x9a: /* Store, WriteBack, Pre Inc */
3022 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3025 case 0x9b: /* Load, WriteBack, Pre Inc */
3027 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3030 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
3031 STORESMULT (instr
, LSBase
+ 4L, 0L);
3034 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
3035 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3038 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
3040 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3043 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
3045 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3048 /***************************************************************************\
3050 \***************************************************************************/
3060 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3064 /***************************************************************************\
3066 \***************************************************************************/
3076 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3080 /***************************************************************************\
3081 * Branch and Link forward *
3082 \***************************************************************************/
3093 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3095 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3097 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3101 /***************************************************************************\
3102 * Branch and Link backward *
3103 \***************************************************************************/
3114 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3116 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3118 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3122 /***************************************************************************\
3123 * Co-Processor Data Transfers *
3124 \***************************************************************************/
3127 if (state
->is_XScale
)
3129 if (BITS (4, 7) != 0x00)
3130 ARMul_UndefInstr (state
, instr
);
3132 if (BITS (8, 11) != 0x00)
3133 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3135 /* XScale MAR insn. Move two registers into accumulator. */
3136 if (BITS (0, 3) == 0x00)
3138 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3139 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3142 /* Access to any other acc is unpredicatable. */
3147 case 0xc0: /* Store , No WriteBack , Post Dec */
3148 ARMul_STC (state
, instr
, LHS
);
3152 if (state
->is_XScale
)
3154 if (BITS (4, 7) != 0x00)
3155 ARMul_UndefInstr (state
, instr
);
3157 if (BITS (8, 11) != 0x00)
3158 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3160 /* XScale MRA insn. Move accumulator into two registers. */
3161 if (BITS (0, 3) == 0x00)
3163 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3168 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3169 state
->Reg
[BITS (16, 19)] = t1
;
3172 /* Access to any other acc is unpredicatable. */
3177 case 0xc1: /* Load , No WriteBack , Post Dec */
3178 ARMul_LDC (state
, instr
, LHS
);
3182 case 0xc6: /* Store , WriteBack , Post Dec */
3184 state
->Base
= lhs
- LSCOff
;
3185 ARMul_STC (state
, instr
, lhs
);
3189 case 0xc7: /* Load , WriteBack , Post Dec */
3191 state
->Base
= lhs
- LSCOff
;
3192 ARMul_LDC (state
, instr
, lhs
);
3196 case 0xcc: /* Store , No WriteBack , Post Inc */
3197 ARMul_STC (state
, instr
, LHS
);
3201 case 0xcd: /* Load , No WriteBack , Post Inc */
3202 ARMul_LDC (state
, instr
, LHS
);
3206 case 0xce: /* Store , WriteBack , Post Inc */
3208 state
->Base
= lhs
+ LSCOff
;
3209 ARMul_STC (state
, instr
, LHS
);
3213 case 0xcf: /* Load , WriteBack , Post Inc */
3215 state
->Base
= lhs
+ LSCOff
;
3216 ARMul_LDC (state
, instr
, LHS
);
3221 case 0xd4: /* Store , No WriteBack , Pre Dec */
3222 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3226 case 0xd5: /* Load , No WriteBack , Pre Dec */
3227 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3231 case 0xd6: /* Store , WriteBack , Pre Dec */
3234 ARMul_STC (state
, instr
, lhs
);
3238 case 0xd7: /* Load , WriteBack , Pre Dec */
3241 ARMul_LDC (state
, instr
, lhs
);
3245 case 0xdc: /* Store , No WriteBack , Pre Inc */
3246 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3250 case 0xdd: /* Load , No WriteBack , Pre Inc */
3251 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3255 case 0xde: /* Store , WriteBack , Pre Inc */
3258 ARMul_STC (state
, instr
, lhs
);
3262 case 0xdf: /* Load , WriteBack , Pre Inc */
3265 ARMul_LDC (state
, instr
, lhs
);
3268 /***************************************************************************\
3269 * Co-Processor Register Transfers (MCR) and Data Ops *
3270 \***************************************************************************/
3273 if (state
->is_XScale
)
3274 switch (BITS (18, 19))
3278 /* XScale MIA instruction. Signed multiplication of two 32 bit
3279 values and addition to 40 bit accumulator. */
3280 long long Rm
= state
->Reg
[MULLHSReg
];
3281 long long Rs
= state
->Reg
[MULACCReg
];
3287 state
->Accumulator
+= Rm
* Rs
;
3293 /* XScale MIAPH instruction. */
3294 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3295 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3296 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3297 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3312 state
->Accumulator
+= t5
;
3317 state
->Accumulator
+= t5
;
3323 /* XScale MIAxy instruction. */
3329 t1
= state
->Reg
[MULLHSReg
] >> 16;
3331 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3334 t2
= state
->Reg
[MULACCReg
] >> 16;
3336 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3346 state
->Accumulator
+= t5
;
3368 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3370 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3371 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3375 ARMul_MCR (state
, instr
, DEST
);
3377 else /* CDP Part 1 */
3378 ARMul_CDP (state
, instr
);
3381 /***************************************************************************\
3382 * Co-Processor Register Transfers (MRC) and Data Ops *
3383 \***************************************************************************/
3395 temp
= ARMul_MRC (state
, instr
);
3398 ASSIGNN ((temp
& NBIT
) != 0);
3399 ASSIGNZ ((temp
& ZBIT
) != 0);
3400 ASSIGNC ((temp
& CBIT
) != 0);
3401 ASSIGNV ((temp
& VBIT
) != 0);
3406 else /* CDP Part 2 */
3407 ARMul_CDP (state
, instr
);
3410 /***************************************************************************\
3412 \***************************************************************************/
3430 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3431 { /* a prefetch abort */
3432 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3436 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3438 ARMul_Abort (state
, ARMul_SWIV
);
3441 } /* 256 way main switch */
3448 #ifdef NEED_UI_LOOP_HOOK
3449 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3451 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3454 #endif /* NEED_UI_LOOP_HOOK */
3456 if (state
->Emulate
== ONCE
)
3457 state
->Emulate
= STOP
;
3458 /* If we have changed mode, allow the PC to advance before stopping. */
3459 else if (state
->Emulate
== CHANGEMODE
)
3461 else if (state
->Emulate
!= RUN
)
3464 while (!stop_simulator
); /* do loop */
3466 state
->decoded
= decoded
;
3467 state
->loaded
= loaded
;
3471 } /* Emulate 26/32 in instruction based mode */
3474 /***************************************************************************\
3475 * This routine evaluates most Data Processing register RHS's with the S *
3476 * bit clear. It is intended to be called from the macro DPRegRHS, which *
3477 * filters the common case of an unshifted register with in line code *
3478 \***************************************************************************/
3481 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3483 ARMword shamt
, base
;
3487 { /* shift amount in a register */
3492 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3495 base
= state
->Reg
[base
];
3496 ARMul_Icycles (state
, 1, 0L);
3497 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3498 switch ((int) BITS (5, 6))
3503 else if (shamt
>= 32)
3506 return (base
<< shamt
);
3510 else if (shamt
>= 32)
3513 return (base
>> shamt
);
3517 else if (shamt
>= 32)
3518 return ((ARMword
) ((long int) base
>> 31L));
3520 return ((ARMword
) ((long int) base
>> (int) shamt
));
3526 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3530 { /* shift amount is a constant */
3533 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3536 base
= state
->Reg
[base
];
3537 shamt
= BITS (7, 11);
3538 switch ((int) BITS (5, 6))
3541 return (base
<< shamt
);
3546 return (base
>> shamt
);
3549 return ((ARMword
) ((long int) base
>> 31L));
3551 return ((ARMword
) ((long int) base
>> (int) shamt
));
3553 if (shamt
== 0) /* its an RRX */
3554 return ((base
>> 1) | (CFLAG
<< 31));
3556 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3559 return (0); /* just to shut up lint */
3562 /***************************************************************************\
3563 * This routine evaluates most Logical Data Processing register RHS's *
3564 * with the S bit set. It is intended to be called from the macro *
3565 * DPSRegRHS, which filters the common case of an unshifted register *
3566 * with in line code *
3567 \***************************************************************************/
3570 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3572 ARMword shamt
, base
;
3576 { /* shift amount in a register */
3581 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3584 base
= state
->Reg
[base
];
3585 ARMul_Icycles (state
, 1, 0L);
3586 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3587 switch ((int) BITS (5, 6))
3592 else if (shamt
== 32)
3597 else if (shamt
> 32)
3604 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3605 return (base
<< shamt
);
3610 else if (shamt
== 32)
3612 ASSIGNC (base
>> 31);
3615 else if (shamt
> 32)
3622 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3623 return (base
>> shamt
);
3628 else if (shamt
>= 32)
3630 ASSIGNC (base
>> 31L);
3631 return ((ARMword
) ((long int) base
>> 31L));
3635 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3636 return ((ARMword
) ((long int) base
>> (int) shamt
));
3644 ASSIGNC (base
>> 31);
3649 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3650 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3655 { /* shift amount is a constant */
3658 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3661 base
= state
->Reg
[base
];
3662 shamt
= BITS (7, 11);
3663 switch ((int) BITS (5, 6))
3666 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3667 return (base
<< shamt
);
3671 ASSIGNC (base
>> 31);
3676 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3677 return (base
>> shamt
);
3682 ASSIGNC (base
>> 31L);
3683 return ((ARMword
) ((long int) base
>> 31L));
3687 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3688 return ((ARMword
) ((long int) base
>> (int) shamt
));
3695 return ((base
>> 1) | (shamt
<< 31));
3699 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3700 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3704 return (0); /* just to shut up lint */
3707 /***************************************************************************\
3708 * This routine handles writes to register 15 when the S bit is not set. *
3709 \***************************************************************************/
3712 WriteR15 (ARMul_State
* state
, ARMword src
)
3714 /* The ARM documentation states that the two least significant bits
3715 are discarded when setting PC, except in the cases handled by
3716 WriteR15Branch() below. It's probably an oversight: in THUMB
3717 mode, the second least significant bit should probably not be
3726 state
->Reg
[15] = src
& PCBITS
;
3728 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
3729 ARMul_R15Altered (state
);
3734 /***************************************************************************\
3735 * This routine handles writes to register 15 when the S bit is set. *
3736 \***************************************************************************/
3739 WriteSR15 (ARMul_State
* state
, ARMword src
)
3742 if (state
->Bank
> 0)
3744 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3745 ARMul_CPSRAltered (state
);
3753 state
->Reg
[15] = src
& PCBITS
;
3757 abort (); /* ARMul_R15Altered would have to support it. */
3761 if (state
->Bank
== USERBANK
)
3762 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3764 state
->Reg
[15] = src
;
3765 ARMul_R15Altered (state
);
3770 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3771 will switch to Thumb mode if the least significant bit is set. */
3774 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3780 state
->Reg
[15] = src
& 0xfffffffe;
3785 state
->Reg
[15] = src
& 0xfffffffc;
3789 WriteR15 (state
, src
);
3793 /***************************************************************************\
3794 * This routine evaluates most Load and Store register RHS's. It is *
3795 * intended to be called from the macro LSRegRHS, which filters the *
3796 * common case of an unshifted register with in line code *
3797 \***************************************************************************/
3800 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3802 ARMword shamt
, base
;
3807 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3810 base
= state
->Reg
[base
];
3812 shamt
= BITS (7, 11);
3813 switch ((int) BITS (5, 6))
3816 return (base
<< shamt
);
3821 return (base
>> shamt
);
3824 return ((ARMword
) ((long int) base
>> 31L));
3826 return ((ARMword
) ((long int) base
>> (int) shamt
));
3828 if (shamt
== 0) /* its an RRX */
3829 return ((base
>> 1) | (CFLAG
<< 31));
3831 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3833 return (0); /* just to shut up lint */
3836 /***************************************************************************\
3837 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3838 \***************************************************************************/
3841 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3847 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3849 return state
->Reg
[RHSReg
];
3852 /* else immediate */
3853 return BITS (0, 3) | (BITS (8, 11) << 4);
3856 /***************************************************************************\
3857 * This function does the work of loading a word for a LDR instruction. *
3858 \***************************************************************************/
3861 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3867 if (ADDREXCEPT (address
))
3869 INTERNALABORT (address
);
3872 dest
= ARMul_LoadWordN (state
, address
);
3876 return (state
->lateabtSig
);
3879 dest
= ARMul_Align (state
, address
, dest
);
3881 ARMul_Icycles (state
, 1, 0L);
3883 return (DESTReg
!= LHSReg
);
3887 /***************************************************************************\
3888 * This function does the work of loading a halfword. *
3889 \***************************************************************************/
3892 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3899 if (ADDREXCEPT (address
))
3901 INTERNALABORT (address
);
3904 dest
= ARMul_LoadHalfWord (state
, address
);
3908 return (state
->lateabtSig
);
3913 if (dest
& 1 << (16 - 1))
3914 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3917 ARMul_Icycles (state
, 1, 0L);
3918 return (DESTReg
!= LHSReg
);
3923 /***************************************************************************\
3924 * This function does the work of loading a byte for a LDRB instruction. *
3925 \***************************************************************************/
3928 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3934 if (ADDREXCEPT (address
))
3936 INTERNALABORT (address
);
3939 dest
= ARMul_LoadByte (state
, address
);
3943 return (state
->lateabtSig
);
3948 if (dest
& 1 << (8 - 1))
3949 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3952 ARMul_Icycles (state
, 1, 0L);
3953 return (DESTReg
!= LHSReg
);
3956 /***************************************************************************\
3957 * This function does the work of loading two words for a LDRD instruction. *
3958 \***************************************************************************/
3961 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
3965 ARMword write_back
= BIT (21);
3966 ARMword immediate
= BIT (22);
3967 ARMword add_to_base
= BIT (23);
3968 ARMword pre_indexed
= BIT (24);
3978 /* If the writeback bit is set, the pre-index bit must be clear. */
3979 if (write_back
&& ! pre_indexed
)
3981 ARMul_UndefInstr (state
, instr
);
3985 /* Extract the base address register. */
3988 /* Extract the destination register and check it. */
3991 /* Destination register must be even. */
3993 /* Destination register cannot be LR. */
3994 || (dest_reg
== 14))
3996 ARMul_UndefInstr (state
, instr
);
4000 /* Compute the base address. */
4001 base
= state
->Reg
[addr_reg
];
4003 /* Compute the offset. */
4004 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4006 /* Compute the sum of the two. */
4008 sum
= base
+ offset
;
4010 sum
= base
- offset
;
4012 /* If this is a pre-indexed mode use the sum. */
4018 /* The address must be aligned on a 8 byte boundary. */
4022 ARMul_DATAABORT (addr
);
4024 ARMul_UndefInstr (state
, instr
);
4029 /* For pre indexed or post indexed addressing modes,
4030 check that the destination registers do not overlap
4031 the address registers. */
4032 if ((! pre_indexed
|| write_back
)
4033 && ( addr_reg
== dest_reg
4034 || addr_reg
== dest_reg
+ 1))
4036 ARMul_UndefInstr (state
, instr
);
4040 /* Load the words. */
4041 value1
= ARMul_LoadWordN (state
, addr
);
4042 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4044 /* Check for data aborts. */
4051 ARMul_Icycles (state
, 2, 0L);
4053 /* Store the values. */
4054 state
->Reg
[dest_reg
] = value1
;
4055 state
->Reg
[dest_reg
+ 1] = value2
;
4057 /* Do the post addressing and writeback. */
4061 if (! pre_indexed
|| write_back
)
4062 state
->Reg
[addr_reg
] = addr
;
4065 /***************************************************************************\
4066 * This function does the work of storing two words for a STRD instruction. *
4067 \***************************************************************************/
4070 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4074 ARMword write_back
= BIT (21);
4075 ARMword immediate
= BIT (22);
4076 ARMword add_to_base
= BIT (23);
4077 ARMword pre_indexed
= BIT (24);
4085 /* If the writeback bit is set, the pre-index bit must be clear. */
4086 if (write_back
&& ! pre_indexed
)
4088 ARMul_UndefInstr (state
, instr
);
4092 /* Extract the base address register. */
4095 /* Base register cannot be PC. */
4098 ARMul_UndefInstr (state
, instr
);
4102 /* Extract the source register. */
4105 /* Source register must be even. */
4108 ARMul_UndefInstr (state
, instr
);
4112 /* Compute the base address. */
4113 base
= state
->Reg
[addr_reg
];
4115 /* Compute the offset. */
4116 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4118 /* Compute the sum of the two. */
4120 sum
= base
+ offset
;
4122 sum
= base
- offset
;
4124 /* If this is a pre-indexed mode use the sum. */
4130 /* The address must be aligned on a 8 byte boundary. */
4134 ARMul_DATAABORT (addr
);
4136 ARMul_UndefInstr (state
, instr
);
4141 /* For pre indexed or post indexed addressing modes,
4142 check that the destination registers do not overlap
4143 the address registers. */
4144 if ((! pre_indexed
|| write_back
)
4145 && ( addr_reg
== src_reg
4146 || addr_reg
== src_reg
+ 1))
4148 ARMul_UndefInstr (state
, instr
);
4152 /* Load the words. */
4153 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4154 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4162 /* Do the post addressing and writeback. */
4166 if (! pre_indexed
|| write_back
)
4167 state
->Reg
[addr_reg
] = addr
;
4170 /***************************************************************************\
4171 * This function does the work of storing a word from a STR instruction. *
4172 \***************************************************************************/
4175 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4180 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4183 ARMul_StoreWordN (state
, address
, DEST
);
4185 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4187 INTERNALABORT (address
);
4188 (void) ARMul_LoadWordN (state
, address
);
4191 ARMul_StoreWordN (state
, address
, DEST
);
4196 return (state
->lateabtSig
);
4202 /***************************************************************************\
4203 * This function does the work of storing a byte for a STRH instruction. *
4204 \***************************************************************************/
4207 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4213 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4217 ARMul_StoreHalfWord (state
, address
, DEST
);
4219 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4221 INTERNALABORT (address
);
4222 (void) ARMul_LoadHalfWord (state
, address
);
4225 ARMul_StoreHalfWord (state
, address
, DEST
);
4231 return (state
->lateabtSig
);
4239 /***************************************************************************\
4240 * This function does the work of storing a byte for a STRB instruction. *
4241 \***************************************************************************/
4244 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4249 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4252 ARMul_StoreByte (state
, address
, DEST
);
4254 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4256 INTERNALABORT (address
);
4257 (void) ARMul_LoadByte (state
, address
);
4260 ARMul_StoreByte (state
, address
, DEST
);
4265 return (state
->lateabtSig
);
4271 /***************************************************************************\
4272 * This function does the work of loading the registers listed in an LDM *
4273 * instruction, when the S bit is clear. The code here is always increment *
4274 * after, it's up to the caller to get the input address correct and to *
4275 * handle base register modification. *
4276 \***************************************************************************/
4279 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4285 UNDEF_LSMBaseInListWb
;
4288 if (ADDREXCEPT (address
))
4290 INTERNALABORT (address
);
4293 if (BIT (21) && LHSReg
!= 15)
4296 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4297 dest
= ARMul_LoadWordN (state
, address
);
4298 if (!state
->abortSig
&& !state
->Aborted
)
4299 state
->Reg
[temp
++] = dest
;
4300 else if (!state
->Aborted
)
4301 state
->Aborted
= ARMul_DataAbortV
;
4303 for (; temp
< 16; temp
++) /* S cycles from here on */
4305 { /* load this register */
4307 dest
= ARMul_LoadWordS (state
, address
);
4308 if (!state
->abortSig
&& !state
->Aborted
)
4309 state
->Reg
[temp
] = dest
;
4310 else if (!state
->Aborted
)
4311 state
->Aborted
= ARMul_DataAbortV
;
4314 if (BIT (15) && !state
->Aborted
)
4315 { /* PC is in the reg list */
4316 WriteR15Branch(state
, PC
);
4319 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
4323 if (BIT (21) && LHSReg
!= 15)
4329 /***************************************************************************\
4330 * This function does the work of loading the registers listed in an LDM *
4331 * instruction, when the S bit is set. The code here is always increment *
4332 * after, it's up to the caller to get the input address correct and to *
4333 * handle base register modification. *
4334 \***************************************************************************/
4337 LoadSMult (ARMul_State
* state
, ARMword instr
,
4338 ARMword address
, ARMword WBBase
)
4344 UNDEF_LSMBaseInListWb
;
4347 if (ADDREXCEPT (address
))
4349 INTERNALABORT (address
);
4353 if (!BIT (15) && state
->Bank
!= USERBANK
)
4355 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* temporary reg bank switch */
4356 UNDEF_LSMUserBankWb
;
4359 if (BIT (21) && LHSReg
!= 15)
4362 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4363 dest
= ARMul_LoadWordN (state
, address
);
4364 if (!state
->abortSig
)
4365 state
->Reg
[temp
++] = dest
;
4366 else if (!state
->Aborted
)
4367 state
->Aborted
= ARMul_DataAbortV
;
4369 for (; temp
< 16; temp
++) /* S cycles from here on */
4371 { /* load this register */
4373 dest
= ARMul_LoadWordS (state
, address
);
4374 if (!state
->abortSig
&& !state
->Aborted
)
4375 state
->Reg
[temp
] = dest
;
4376 else if (!state
->Aborted
)
4377 state
->Aborted
= ARMul_DataAbortV
;
4380 if (BIT (15) && !state
->Aborted
)
4381 { /* PC is in the reg list */
4383 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4385 state
->Cpsr
= GETSPSR (state
->Bank
);
4386 ARMul_CPSRAltered (state
);
4388 WriteR15 (state
, PC
);
4390 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4391 { /* protect bits in user mode */
4392 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4393 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4394 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4395 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4398 ARMul_R15Altered (state
);
4403 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4404 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
4406 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
4410 if (BIT (21) && LHSReg
!= 15)
4417 /***************************************************************************\
4418 * This function does the work of storing the registers listed in an STM *
4419 * instruction, when the S bit is clear. The code here is always increment *
4420 * after, it's up to the caller to get the input address correct and to *
4421 * handle base register modification. *
4422 \***************************************************************************/
4425 StoreMult (ARMul_State
* state
, ARMword instr
,
4426 ARMword address
, ARMword WBBase
)
4432 UNDEF_LSMBaseInListWb
;
4435 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
4439 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4441 INTERNALABORT (address
);
4447 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4449 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4453 (void) ARMul_LoadWordN (state
, address
);
4454 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
4456 { /* save this register */
4458 (void) ARMul_LoadWordS (state
, address
);
4460 if (BIT (21) && LHSReg
!= 15)
4466 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4468 if (state
->abortSig
&& !state
->Aborted
)
4469 state
->Aborted
= ARMul_DataAbortV
;
4471 if (BIT (21) && LHSReg
!= 15)
4474 for (; temp
< 16; temp
++) /* S cycles from here on */
4476 { /* save this register */
4478 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4479 if (state
->abortSig
&& !state
->Aborted
)
4480 state
->Aborted
= ARMul_DataAbortV
;
4488 /***************************************************************************\
4489 * This function does the work of storing the registers listed in an STM *
4490 * instruction when the S bit is set. The code here is always increment *
4491 * after, it's up to the caller to get the input address correct and to *
4492 * handle base register modification. *
4493 \***************************************************************************/
4496 StoreSMult (ARMul_State
* state
, ARMword instr
,
4497 ARMword address
, ARMword WBBase
)
4503 UNDEF_LSMBaseInListWb
;
4506 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4508 INTERNALABORT (address
);
4514 if (state
->Bank
!= USERBANK
)
4516 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* Force User Bank */
4517 UNDEF_LSMUserBankWb
;
4520 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4522 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4526 (void) ARMul_LoadWordN (state
, address
);
4527 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
4529 { /* save this register */
4531 (void) ARMul_LoadWordS (state
, address
);
4533 if (BIT (21) && LHSReg
!= 15)
4539 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4541 if (state
->abortSig
&& !state
->Aborted
)
4542 state
->Aborted
= ARMul_DataAbortV
;
4544 if (BIT (21) && LHSReg
!= 15)
4547 for (; temp
< 16; temp
++) /* S cycles from here on */
4549 { /* save this register */
4551 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4552 if (state
->abortSig
&& !state
->Aborted
)
4553 state
->Aborted
= ARMul_DataAbortV
;
4556 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4557 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
4565 /***************************************************************************\
4566 * This function does the work of adding two 32bit values together, and *
4567 * calculating if a carry has occurred. *
4568 \***************************************************************************/
4571 Add32 (ARMword a1
, ARMword a2
, int *carry
)
4573 ARMword result
= (a1
+ a2
);
4574 unsigned int uresult
= (unsigned int) result
;
4575 unsigned int ua1
= (unsigned int) a1
;
4577 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4578 or (result > RdLo) then we have no carry: */
4579 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
4587 /***************************************************************************\
4588 * This function does the work of multiplying two 32bit values to give a *
4590 \***************************************************************************/
4593 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4595 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
4596 ARMword RdHi
= 0, RdLo
= 0, Rm
;
4597 int scount
; /* cycle count */
4599 nRdHi
= BITS (16, 19);
4600 nRdLo
= BITS (12, 15);
4604 /* Needed to calculate the cycle count: */
4605 Rm
= state
->Reg
[nRm
];
4607 /* Check for illegal operand combinations first: */
4611 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
4613 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
4615 ARMword Rs
= state
->Reg
[nRs
];
4620 /* Compute sign of result and adjust operands if necessary. */
4622 sign
= (Rm
^ Rs
) & 0x80000000;
4624 if (((signed long) Rm
) < 0)
4627 if (((signed long) Rs
) < 0)
4631 /* We can split the 32x32 into four 16x16 operations. This ensures
4632 that we do not lose precision on 32bit only hosts: */
4633 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
4634 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4635 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
4636 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4638 /* We now need to add all of these results together, taking care
4639 to propogate the carries from the additions: */
4640 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
4642 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
4644 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
4648 /* Negate result if necessary. */
4652 if (RdLo
== 0xFFFFFFFF)
4661 state
->Reg
[nRdLo
] = RdLo
;
4662 state
->Reg
[nRdHi
] = RdHi
;
4663 } /* else undefined result */
4665 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4669 /* Ensure that both RdHi and RdLo are used to compute Z, but
4670 don't let RdLo's sign bit make it to N. */
4671 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4674 /* The cycle count depends on whether the instruction is a signed or
4675 unsigned multiply, and what bits are clear in the multiplier: */
4676 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
4677 Rm
= ~Rm
; /* invert the bits to make the check against zero */
4679 if ((Rm
& 0xFFFFFF00) == 0)
4681 else if ((Rm
& 0xFFFF0000) == 0)
4683 else if ((Rm
& 0xFF000000) == 0)
4691 /***************************************************************************\
4692 * This function does the work of multiplying two 32bit values and adding *
4693 * a 64bit value to give a 64bit result. *
4694 \***************************************************************************/
4697 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4704 nRdHi
= BITS (16, 19);
4705 nRdLo
= BITS (12, 15);
4707 RdHi
= state
->Reg
[nRdHi
];
4708 RdLo
= state
->Reg
[nRdLo
];
4710 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
4712 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
4713 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
4715 state
->Reg
[nRdLo
] = RdLo
;
4716 state
->Reg
[nRdHi
] = RdHi
;
4720 /* Ensure that both RdHi and RdLo are used to compute Z, but
4721 don't let RdLo's sign bit make it to N. */
4722 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4725 return scount
+ 1; /* extra cycle for addition */
This page took 0.207322 seconds and 4 git commands to generate.