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
);
55 #define LUNSIGNED (0) /* unsigned operation */
56 #define LSIGNED (1) /* signed operation */
57 #define LDEFAULT (0) /* default : do nothing */
58 #define LSCC (1) /* set condition codes on result */
60 #ifdef NEED_UI_LOOP_HOOK
61 /* How often to run the ui_loop update, when in use */
62 #define UI_LOOP_POLL_INTERVAL 0x32000
64 /* Counter for the ui_loop_hook update */
65 static long ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
67 /* Actual hook to call to run through gdb's gui event loop */
68 extern int (*ui_loop_hook
) (int);
69 #endif /* NEED_UI_LOOP_HOOK */
71 extern int stop_simulator
;
73 /***************************************************************************\
74 * short-hand macros for LDR/STR *
75 \***************************************************************************/
77 /* store post decrement writeback */
80 if (StoreHalfWord(state, instr, lhs)) \
81 LSBase = lhs - GetLS7RHS(state, instr) ;
83 /* store post increment writeback */
86 if (StoreHalfWord(state, instr, lhs)) \
87 LSBase = lhs + GetLS7RHS(state, instr) ;
89 /* store pre decrement */
91 (void)StoreHalfWord(state, instr, LHS - GetLS7RHS(state, instr)) ;
93 /* store pre decrement writeback */
94 #define SHPREDOWNWB() \
95 temp = LHS - GetLS7RHS(state, instr) ; \
96 if (StoreHalfWord(state, instr, temp)) \
99 /* store pre increment */
101 (void)StoreHalfWord(state, instr, LHS + GetLS7RHS(state, instr)) ;
103 /* store pre increment writeback */
104 #define SHPREUPWB() \
105 temp = LHS + GetLS7RHS(state, instr) ; \
106 if (StoreHalfWord(state, instr, temp)) \
109 /* load post decrement writeback */
110 #define LHPOSTDOWN() \
114 switch (BITS(5,6)) { \
116 if (LoadHalfWord(state,instr,lhs,LUNSIGNED)) \
117 LSBase = lhs - GetLS7RHS(state,instr) ; \
120 if (LoadByte(state,instr,lhs,LSIGNED)) \
121 LSBase = lhs - GetLS7RHS(state,instr) ; \
124 if (LoadHalfWord(state,instr,lhs,LSIGNED)) \
125 LSBase = lhs - GetLS7RHS(state,instr) ; \
127 case 0: /* SWP handled elsewhere */ \
136 /* load post increment writeback */
141 switch (BITS(5,6)) { \
143 if (LoadHalfWord(state,instr,lhs,LUNSIGNED)) \
144 LSBase = lhs + GetLS7RHS(state,instr) ; \
147 if (LoadByte(state,instr,lhs,LSIGNED)) \
148 LSBase = lhs + GetLS7RHS(state,instr) ; \
151 if (LoadHalfWord(state,instr,lhs,LSIGNED)) \
152 LSBase = lhs + GetLS7RHS(state,instr) ; \
154 case 0: /* SWP handled elsewhere */ \
163 /* load pre decrement */
164 #define LHPREDOWN() \
167 temp = LHS - GetLS7RHS(state,instr) ; \
168 switch (BITS(5,6)) { \
170 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
173 (void)LoadByte(state,instr,temp,LSIGNED) ; \
176 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
178 case 0: /* SWP handled elsewhere */ \
187 /* load pre decrement writeback */
188 #define LHPREDOWNWB() \
191 temp = LHS - GetLS7RHS(state, instr) ; \
192 switch (BITS(5,6)) { \
194 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
198 if (LoadByte(state,instr,temp,LSIGNED)) \
202 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
205 case 0: /* SWP handled elsewhere */ \
214 /* load pre increment */
218 temp = LHS + GetLS7RHS(state,instr) ; \
219 switch (BITS(5,6)) { \
221 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
224 (void)LoadByte(state,instr,temp,LSIGNED) ; \
227 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
229 case 0: /* SWP handled elsewhere */ \
238 /* load pre increment writeback */
239 #define LHPREUPWB() \
242 temp = LHS + GetLS7RHS(state, instr) ; \
243 switch (BITS(5,6)) { \
245 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
249 if (LoadByte(state,instr,temp,LSIGNED)) \
253 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
256 case 0: /* SWP handled elsewhere */ \
265 /***************************************************************************\
266 * EMULATION of ARM6 *
267 \***************************************************************************/
269 /* The PC pipeline value depends on whether ARM or Thumb instructions
270 are being executed: */
275 ARMul_Emulate32 (register ARMul_State
* state
)
279 ARMul_Emulate26 (register ARMul_State
* state
)
282 register ARMword instr
, /* the current instruction */
283 dest
= 0, /* almost the DestBus */
284 temp
, /* ubiquitous third hand */
285 pc
= 0; /* the address of the current instruction */
286 ARMword lhs
, rhs
; /* almost the ABus and BBus */
287 ARMword decoded
= 0, loaded
= 0; /* instruction pipeline */
289 /***************************************************************************\
290 * Execute the next instruction *
291 \***************************************************************************/
293 if (state
->NextInstr
< PRIMEPIPE
)
295 decoded
= state
->decoded
;
296 loaded
= state
->loaded
;
301 { /* just keep going */
303 switch (state
->NextInstr
)
306 state
->Reg
[15] += isize
; /* Advance the pipeline, and an S cycle */
310 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
314 state
->Reg
[15] += isize
; /* Advance the pipeline, and an N cycle */
318 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
323 pc
+= isize
; /* Program counter advanced, and an S cycle */
326 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
331 pc
+= isize
; /* Program counter advanced, and an N cycle */
334 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
338 case RESUME
: /* The program counter has been changed */
343 state
->Reg
[15] = pc
+ (isize
* 2);
345 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
346 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
347 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
351 default: /* The program counter has been changed */
356 state
->Reg
[15] = pc
+ (isize
* 2);
358 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
359 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
360 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
365 ARMul_EnvokeEvent (state
);
368 /* Enable this for a helpful bit of debugging when tracing is needed. */
369 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
374 if (state
->Exception
)
375 { /* Any exceptions */
376 if (state
->NresetSig
== LOW
)
378 ARMul_Abort (state
, ARMul_ResetV
);
381 else if (!state
->NfiqSig
&& !FFLAG
)
383 ARMul_Abort (state
, ARMul_FIQV
);
386 else if (!state
->NirqSig
&& !IFLAG
)
388 ARMul_Abort (state
, ARMul_IRQV
);
393 if (state
->CallDebug
> 0)
395 instr
= ARMul_Debug (state
, pc
, instr
);
396 if (state
->Emulate
< ONCE
)
398 state
->NextInstr
= RESUME
;
403 fprintf (stderr
, "At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
405 (void) fgetc (stdin
);
408 else if (state
->Emulate
< ONCE
)
410 state
->NextInstr
= RESUME
;
417 /* Provide Thumb instruction decoding. If the processor is in Thumb
418 mode, then we can simply decode the Thumb instruction, and map it
419 to the corresponding ARM instruction (by directly loading the
420 instr variable, and letting the normal ARM simulator
421 execute). There are some caveats to ensure that the correct
422 pipelined PC value is used when executing Thumb code, and also for
423 dealing with the BL instruction. */
425 { /* check if in Thumb mode */
427 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
430 ARMul_UndefInstr (state
, instr
); /* This is a Thumb instruction */
433 case t_branch
: /* already processed */
436 case t_decoded
: /* ARM instruction available */
437 instr
= new; /* so continue instruction decoding */
443 /***************************************************************************\
444 * Check the condition codes *
445 \***************************************************************************/
446 if ((temp
= TOPBITS (28)) == AL
)
447 goto mainswitch
; /* vile deed in the need for speed */
449 switch ((int) TOPBITS (28))
450 { /* check the condition code */
482 temp
= (CFLAG
&& !ZFLAG
);
485 temp
= (!CFLAG
|| ZFLAG
);
488 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
491 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
494 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
497 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
501 /***************************************************************************\
502 * Actual execution of instructions begins here *
503 \***************************************************************************/
506 { /* if the condition codes don't match, stop here */
510 switch ((int) BITS (20, 27))
513 /***************************************************************************\
514 * Data Processing Register RHS Instructions *
515 \***************************************************************************/
517 case 0x00: /* AND reg and MUL */
519 if (BITS (4, 11) == 0xB)
521 /* STRH register offset, no write-back, down, post indexed */
525 /* TODO: CHECK: should 0xD and 0xF generate undefined intruction aborts? */
527 if (BITS (4, 7) == 9)
529 rhs
= state
->Reg
[MULRHSReg
];
530 if (MULLHSReg
== MULDESTReg
)
533 state
->Reg
[MULDESTReg
] = 0;
535 else if (MULDESTReg
!= 15)
536 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
541 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
542 if (rhs
& (1L << dest
))
543 temp
= dest
; /* mult takes this many/2 I cycles */
544 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
554 case 0x01: /* ANDS reg and MULS */
556 if ((BITS (4, 11) & 0xF9) == 0x9)
558 /* LDR register offset, no write-back, down, post indexed */
560 /* fall through to rest of decoding */
563 if (BITS (4, 7) == 9)
565 rhs
= state
->Reg
[MULRHSReg
];
566 if (MULLHSReg
== MULDESTReg
)
569 state
->Reg
[MULDESTReg
] = 0;
573 else if (MULDESTReg
!= 15)
575 dest
= state
->Reg
[MULLHSReg
] * rhs
;
576 ARMul_NegZero (state
, dest
);
577 state
->Reg
[MULDESTReg
] = dest
;
583 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
584 if (rhs
& (1L << dest
))
585 temp
= dest
; /* mult takes this many/2 I cycles */
586 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
596 case 0x02: /* EOR reg and MLA */
598 if (BITS (4, 11) == 0xB)
600 /* STRH register offset, write-back, down, post indexed */
605 if (BITS (4, 7) == 9)
607 rhs
= state
->Reg
[MULRHSReg
];
608 if (MULLHSReg
== MULDESTReg
)
611 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
613 else if (MULDESTReg
!= 15)
614 state
->Reg
[MULDESTReg
] =
615 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
620 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
621 if (rhs
& (1L << dest
))
622 temp
= dest
; /* mult takes this many/2 I cycles */
623 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
633 case 0x03: /* EORS reg and MLAS */
635 if ((BITS (4, 11) & 0xF9) == 0x9)
637 /* LDR register offset, write-back, down, post-indexed */
639 /* fall through to rest of the decoding */
642 if (BITS (4, 7) == 9)
644 rhs
= state
->Reg
[MULRHSReg
];
645 if (MULLHSReg
== MULDESTReg
)
648 dest
= state
->Reg
[MULACCReg
];
649 ARMul_NegZero (state
, dest
);
650 state
->Reg
[MULDESTReg
] = dest
;
652 else if (MULDESTReg
!= 15)
655 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
656 ARMul_NegZero (state
, dest
);
657 state
->Reg
[MULDESTReg
] = dest
;
663 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
664 if (rhs
& (1L << dest
))
665 temp
= dest
; /* mult takes this many/2 I cycles */
666 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
676 case 0x04: /* SUB reg */
678 if (BITS (4, 7) == 0xB)
680 /* STRH immediate offset, no write-back, down, post indexed */
690 case 0x05: /* SUBS reg */
692 if ((BITS (4, 7) & 0x9) == 0x9)
694 /* LDR immediate offset, no write-back, down, post indexed */
696 /* fall through to the rest of the instruction decoding */
702 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
704 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
705 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
715 case 0x06: /* RSB reg */
717 if (BITS (4, 7) == 0xB)
719 /* STRH immediate offset, write-back, down, post indexed */
729 case 0x07: /* RSBS reg */
731 if ((BITS (4, 7) & 0x9) == 0x9)
733 /* LDR immediate offset, write-back, down, post indexed */
735 /* fall through to remainder of instruction decoding */
741 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
743 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
744 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
754 case 0x08: /* ADD reg */
756 if (BITS (4, 11) == 0xB)
758 /* STRH register offset, no write-back, up, post indexed */
764 if (BITS (4, 7) == 0x9)
767 ARMul_Icycles (state
,
768 Multiply64 (state
, instr
, LUNSIGNED
,
778 case 0x09: /* ADDS reg */
780 if ((BITS (4, 11) & 0xF9) == 0x9)
782 /* LDR register offset, no write-back, up, post indexed */
784 /* fall through to remaining instruction decoding */
788 if (BITS (4, 7) == 0x9)
791 ARMul_Icycles (state
,
792 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
801 if ((lhs
| rhs
) >> 30)
802 { /* possible C,V,N to set */
803 ASSIGNN (NEG (dest
));
804 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
805 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
816 case 0x0a: /* ADC reg */
818 if (BITS (4, 11) == 0xB)
820 /* STRH register offset, write-back, up, post-indexed */
826 if (BITS (4, 7) == 0x9)
829 ARMul_Icycles (state
,
830 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
836 dest
= LHS
+ rhs
+ CFLAG
;
840 case 0x0b: /* ADCS reg */
842 if ((BITS (4, 11) & 0xF9) == 0x9)
844 /* LDR register offset, write-back, up, post indexed */
846 /* fall through to remaining instruction decoding */
850 if (BITS (4, 7) == 0x9)
853 ARMul_Icycles (state
,
854 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
861 dest
= lhs
+ rhs
+ CFLAG
;
863 if ((lhs
| rhs
) >> 30)
864 { /* possible C,V,N to set */
865 ASSIGNN (NEG (dest
));
866 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
867 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
878 case 0x0c: /* SBC reg */
880 if (BITS (4, 7) == 0xB)
882 /* STRH immediate offset, no write-back, up post indexed */
888 if (BITS (4, 7) == 0x9)
891 ARMul_Icycles (state
,
892 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
898 dest
= LHS
- rhs
- !CFLAG
;
902 case 0x0d: /* SBCS reg */
904 if ((BITS (4, 7) & 0x9) == 0x9)
906 /* LDR immediate offset, no write-back, up, post indexed */
911 if (BITS (4, 7) == 0x9)
914 ARMul_Icycles (state
,
915 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
922 dest
= lhs
- rhs
- !CFLAG
;
923 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
925 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
926 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
936 case 0x0e: /* RSC reg */
938 if (BITS (4, 7) == 0xB)
940 /* STRH immediate offset, write-back, up, post indexed */
946 if (BITS (4, 7) == 0x9)
949 ARMul_Icycles (state
,
950 MultiplyAdd64 (state
, instr
, LSIGNED
,
956 dest
= rhs
- LHS
- !CFLAG
;
960 case 0x0f: /* RSCS reg */
962 if ((BITS (4, 7) & 0x9) == 0x9)
964 /* LDR immediate offset, write-back, up, post indexed */
966 /* fall through to remaining instruction decoding */
970 if (BITS (4, 7) == 0x9)
973 ARMul_Icycles (state
,
974 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
981 dest
= rhs
- lhs
- !CFLAG
;
982 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
984 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
985 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
995 case 0x10: /* TST reg and MRS CPSR and SWP word */
997 if (BITS (4, 11) == 0xB)
999 /* STRH register offset, no write-back, down, pre indexed */
1004 if (BITS (4, 11) == 9)
1010 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1012 INTERNALABORT (temp
);
1013 (void) ARMul_LoadWordN (state
, temp
);
1014 (void) ARMul_LoadWordN (state
, temp
);
1018 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1020 DEST
= ARMul_Align (state
, temp
, dest
);
1023 if (state
->abortSig
|| state
->Aborted
)
1028 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1031 DEST
= ECC
| EINT
| EMODE
;
1039 case 0x11: /* TSTP reg */
1041 if ((BITS (4, 11) & 0xF9) == 0x9)
1043 /* LDR register offset, no write-back, down, pre indexed */
1045 /* continue with remaining instruction decode */
1051 state
->Cpsr
= GETSPSR (state
->Bank
);
1052 ARMul_CPSRAltered (state
);
1063 ARMul_NegZero (state
, dest
);
1067 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6) */
1069 if (BITS (4, 11) == 0xB)
1071 /* STRH register offset, write-back, down, pre indexed */
1077 if (BITS (4, 27) == 0x12FFF1)
1079 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1084 { /* MSR reg to CPSR */
1087 ARMul_FixCPSR (state
, instr
, temp
);
1095 case 0x13: /* TEQP reg */
1097 if ((BITS (4, 11) & 0xF9) == 0x9)
1099 /* LDR register offset, write-back, down, pre indexed */
1101 /* continue with remaining instruction decode */
1107 state
->Cpsr
= GETSPSR (state
->Bank
);
1108 ARMul_CPSRAltered (state
);
1119 ARMul_NegZero (state
, dest
);
1123 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1125 if (BITS (4, 7) == 0xB)
1127 /* STRH immediate offset, no write-back, down, pre indexed */
1132 if (BITS (4, 11) == 9)
1138 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1140 INTERNALABORT (temp
);
1141 (void) ARMul_LoadByte (state
, temp
);
1142 (void) ARMul_LoadByte (state
, temp
);
1146 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1147 if (state
->abortSig
|| state
->Aborted
)
1152 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1155 DEST
= GETSPSR (state
->Bank
);
1163 case 0x15: /* CMPP reg */
1165 if ((BITS (4, 7) & 0x9) == 0x9)
1167 /* LDR immediate offset, no write-back, down, pre indexed */
1169 /* continue with remaining instruction decode */
1175 state
->Cpsr
= GETSPSR (state
->Bank
);
1176 ARMul_CPSRAltered (state
);
1188 ARMul_NegZero (state
, dest
);
1189 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1191 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1192 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1202 case 0x16: /* CMN reg and MSR reg to SPSR */
1204 if (BITS (4, 7) == 0xB)
1206 /* STRH immediate offset, write-back, down, pre indexed */
1214 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1222 case 0x17: /* CMNP reg */
1224 if ((BITS (4, 7) & 0x9) == 0x9)
1226 /* LDR immediate offset, write-back, down, pre indexed */
1228 /* continue with remaining instruction decoding */
1234 state
->Cpsr
= GETSPSR (state
->Bank
);
1235 ARMul_CPSRAltered (state
);
1248 ASSIGNZ (dest
== 0);
1249 if ((lhs
| rhs
) >> 30)
1250 { /* possible C,V,N to set */
1251 ASSIGNN (NEG (dest
));
1252 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1253 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1264 case 0x18: /* ORR reg */
1266 if (BITS (4, 11) == 0xB)
1268 /* STRH register offset, no write-back, up, pre indexed */
1278 case 0x19: /* ORRS reg */
1280 if ((BITS (4, 11) & 0xF9) == 0x9)
1282 /* LDR register offset, no write-back, up, pre indexed */
1284 /* continue with remaining instruction decoding */
1292 case 0x1a: /* MOV reg */
1294 if (BITS (4, 11) == 0xB)
1296 /* STRH register offset, write-back, up, pre indexed */
1305 case 0x1b: /* MOVS reg */
1307 if ((BITS (4, 11) & 0xF9) == 0x9)
1309 /* LDR register offset, write-back, up, pre indexed */
1311 /* continue with remaining instruction decoding */
1318 case 0x1c: /* BIC reg */
1320 if (BITS (4, 7) == 0xB)
1322 /* STRH immediate offset, no write-back, up, pre indexed */
1332 case 0x1d: /* BICS reg */
1334 if ((BITS (4, 7) & 0x9) == 0x9)
1336 /* LDR immediate offset, no write-back, up, pre indexed */
1338 /* continue with instruction decoding */
1346 case 0x1e: /* MVN reg */
1348 if (BITS (4, 7) == 0xB)
1350 /* STRH immediate offset, write-back, up, pre indexed */
1359 case 0x1f: /* MVNS reg */
1361 if ((BITS (4, 7) & 0x9) == 0x9)
1363 /* LDR immediate offset, write-back, up, pre indexed */
1365 /* continue instruction decoding */
1372 /***************************************************************************\
1373 * Data Processing Immediate RHS Instructions *
1374 \***************************************************************************/
1376 case 0x20: /* AND immed */
1377 dest
= LHS
& DPImmRHS
;
1381 case 0x21: /* ANDS immed */
1387 case 0x22: /* EOR immed */
1388 dest
= LHS
^ DPImmRHS
;
1392 case 0x23: /* EORS immed */
1398 case 0x24: /* SUB immed */
1399 dest
= LHS
- DPImmRHS
;
1403 case 0x25: /* SUBS immed */
1407 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1409 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1410 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1420 case 0x26: /* RSB immed */
1421 dest
= DPImmRHS
- LHS
;
1425 case 0x27: /* RSBS immed */
1429 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1431 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1432 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1442 case 0x28: /* ADD immed */
1443 dest
= LHS
+ DPImmRHS
;
1447 case 0x29: /* ADDS immed */
1451 ASSIGNZ (dest
== 0);
1452 if ((lhs
| rhs
) >> 30)
1453 { /* possible C,V,N to set */
1454 ASSIGNN (NEG (dest
));
1455 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1456 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1467 case 0x2a: /* ADC immed */
1468 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1472 case 0x2b: /* ADCS immed */
1475 dest
= lhs
+ rhs
+ CFLAG
;
1476 ASSIGNZ (dest
== 0);
1477 if ((lhs
| rhs
) >> 30)
1478 { /* possible C,V,N to set */
1479 ASSIGNN (NEG (dest
));
1480 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1481 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1492 case 0x2c: /* SBC immed */
1493 dest
= LHS
- DPImmRHS
- !CFLAG
;
1497 case 0x2d: /* SBCS immed */
1500 dest
= lhs
- rhs
- !CFLAG
;
1501 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1503 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1504 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1514 case 0x2e: /* RSC immed */
1515 dest
= DPImmRHS
- LHS
- !CFLAG
;
1519 case 0x2f: /* RSCS immed */
1522 dest
= rhs
- lhs
- !CFLAG
;
1523 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1525 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1526 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1536 case 0x30: /* TST immed */
1540 case 0x31: /* TSTP immed */
1544 state
->Cpsr
= GETSPSR (state
->Bank
);
1545 ARMul_CPSRAltered (state
);
1547 temp
= LHS
& DPImmRHS
;
1553 DPSImmRHS
; /* TST immed */
1555 ARMul_NegZero (state
, dest
);
1559 case 0x32: /* TEQ immed and MSR immed to CPSR */
1561 { /* MSR immed to CPSR */
1562 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
1570 case 0x33: /* TEQP immed */
1574 state
->Cpsr
= GETSPSR (state
->Bank
);
1575 ARMul_CPSRAltered (state
);
1577 temp
= LHS
^ DPImmRHS
;
1583 DPSImmRHS
; /* TEQ immed */
1585 ARMul_NegZero (state
, dest
);
1589 case 0x34: /* CMP immed */
1593 case 0x35: /* CMPP immed */
1597 state
->Cpsr
= GETSPSR (state
->Bank
);
1598 ARMul_CPSRAltered (state
);
1600 temp
= LHS
- DPImmRHS
;
1607 lhs
= LHS
; /* CMP immed */
1610 ARMul_NegZero (state
, dest
);
1611 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1613 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1614 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1624 case 0x36: /* CMN immed and MSR immed to SPSR */
1625 if (DESTReg
== 15) /* MSR */
1626 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
1633 case 0x37: /* CMNP immed */
1637 state
->Cpsr
= GETSPSR (state
->Bank
);
1638 ARMul_CPSRAltered (state
);
1640 temp
= LHS
+ DPImmRHS
;
1647 lhs
= LHS
; /* CMN immed */
1650 ASSIGNZ (dest
== 0);
1651 if ((lhs
| rhs
) >> 30)
1652 { /* possible C,V,N to set */
1653 ASSIGNN (NEG (dest
));
1654 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1655 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1666 case 0x38: /* ORR immed */
1667 dest
= LHS
| DPImmRHS
;
1671 case 0x39: /* ORRS immed */
1677 case 0x3a: /* MOV immed */
1682 case 0x3b: /* MOVS immed */
1687 case 0x3c: /* BIC immed */
1688 dest
= LHS
& ~DPImmRHS
;
1692 case 0x3d: /* BICS immed */
1698 case 0x3e: /* MVN immed */
1703 case 0x3f: /* MVNS immed */
1708 /***************************************************************************\
1709 * Single Data Transfer Immediate RHS Instructions *
1710 \***************************************************************************/
1712 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
1714 if (StoreWord (state
, instr
, lhs
))
1715 LSBase
= lhs
- LSImmRHS
;
1718 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
1720 if (LoadWord (state
, instr
, lhs
))
1721 LSBase
= lhs
- LSImmRHS
;
1724 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
1725 UNDEF_LSRBaseEQDestWb
;
1728 temp
= lhs
- LSImmRHS
;
1729 state
->NtransSig
= LOW
;
1730 if (StoreWord (state
, instr
, lhs
))
1732 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1735 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
1736 UNDEF_LSRBaseEQDestWb
;
1739 state
->NtransSig
= LOW
;
1740 if (LoadWord (state
, instr
, lhs
))
1741 LSBase
= lhs
- LSImmRHS
;
1742 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1745 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
1747 if (StoreByte (state
, instr
, lhs
))
1748 LSBase
= lhs
- LSImmRHS
;
1751 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
1753 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1754 LSBase
= lhs
- LSImmRHS
;
1757 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
1758 UNDEF_LSRBaseEQDestWb
;
1761 state
->NtransSig
= LOW
;
1762 if (StoreByte (state
, instr
, lhs
))
1763 LSBase
= lhs
- LSImmRHS
;
1764 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1767 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
1768 UNDEF_LSRBaseEQDestWb
;
1771 state
->NtransSig
= LOW
;
1772 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1773 LSBase
= lhs
- LSImmRHS
;
1774 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1777 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
1779 if (StoreWord (state
, instr
, lhs
))
1780 LSBase
= lhs
+ LSImmRHS
;
1783 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
1785 if (LoadWord (state
, instr
, lhs
))
1786 LSBase
= lhs
+ LSImmRHS
;
1789 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
1790 UNDEF_LSRBaseEQDestWb
;
1793 state
->NtransSig
= LOW
;
1794 if (StoreWord (state
, instr
, lhs
))
1795 LSBase
= lhs
+ LSImmRHS
;
1796 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1799 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
1800 UNDEF_LSRBaseEQDestWb
;
1803 state
->NtransSig
= LOW
;
1804 if (LoadWord (state
, instr
, lhs
))
1805 LSBase
= lhs
+ LSImmRHS
;
1806 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1809 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
1811 if (StoreByte (state
, instr
, lhs
))
1812 LSBase
= lhs
+ LSImmRHS
;
1815 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
1817 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1818 LSBase
= lhs
+ LSImmRHS
;
1821 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
1822 UNDEF_LSRBaseEQDestWb
;
1825 state
->NtransSig
= LOW
;
1826 if (StoreByte (state
, instr
, lhs
))
1827 LSBase
= lhs
+ LSImmRHS
;
1828 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1831 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
1832 UNDEF_LSRBaseEQDestWb
;
1835 state
->NtransSig
= LOW
;
1836 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1837 LSBase
= lhs
+ LSImmRHS
;
1838 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1842 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
1843 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
1846 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
1847 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
1850 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
1851 UNDEF_LSRBaseEQDestWb
;
1853 temp
= LHS
- LSImmRHS
;
1854 if (StoreWord (state
, instr
, temp
))
1858 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
1859 UNDEF_LSRBaseEQDestWb
;
1861 temp
= LHS
- LSImmRHS
;
1862 if (LoadWord (state
, instr
, temp
))
1866 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
1867 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
1870 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
1871 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
1874 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
1875 UNDEF_LSRBaseEQDestWb
;
1877 temp
= LHS
- LSImmRHS
;
1878 if (StoreByte (state
, instr
, temp
))
1882 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
1883 UNDEF_LSRBaseEQDestWb
;
1885 temp
= LHS
- LSImmRHS
;
1886 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
1890 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
1891 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
1894 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
1895 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
1898 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
1899 UNDEF_LSRBaseEQDestWb
;
1901 temp
= LHS
+ LSImmRHS
;
1902 if (StoreWord (state
, instr
, temp
))
1906 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
1907 UNDEF_LSRBaseEQDestWb
;
1909 temp
= LHS
+ LSImmRHS
;
1910 if (LoadWord (state
, instr
, temp
))
1914 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
1915 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
1918 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
1919 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
1922 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
1923 UNDEF_LSRBaseEQDestWb
;
1925 temp
= LHS
+ LSImmRHS
;
1926 if (StoreByte (state
, instr
, temp
))
1930 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
1931 UNDEF_LSRBaseEQDestWb
;
1933 temp
= LHS
+ LSImmRHS
;
1934 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
1938 /***************************************************************************\
1939 * Single Data Transfer Register RHS Instructions *
1940 \***************************************************************************/
1942 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
1945 ARMul_UndefInstr (state
, instr
);
1948 UNDEF_LSRBaseEQOffWb
;
1949 UNDEF_LSRBaseEQDestWb
;
1953 if (StoreWord (state
, instr
, lhs
))
1954 LSBase
= lhs
- LSRegRHS
;
1957 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
1960 ARMul_UndefInstr (state
, instr
);
1963 UNDEF_LSRBaseEQOffWb
;
1964 UNDEF_LSRBaseEQDestWb
;
1968 temp
= lhs
- LSRegRHS
;
1969 if (LoadWord (state
, instr
, lhs
))
1973 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
1976 ARMul_UndefInstr (state
, instr
);
1979 UNDEF_LSRBaseEQOffWb
;
1980 UNDEF_LSRBaseEQDestWb
;
1984 state
->NtransSig
= LOW
;
1985 if (StoreWord (state
, instr
, lhs
))
1986 LSBase
= lhs
- LSRegRHS
;
1987 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1990 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
1993 ARMul_UndefInstr (state
, instr
);
1996 UNDEF_LSRBaseEQOffWb
;
1997 UNDEF_LSRBaseEQDestWb
;
2001 temp
= lhs
- LSRegRHS
;
2002 state
->NtransSig
= LOW
;
2003 if (LoadWord (state
, instr
, lhs
))
2005 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2008 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2011 ARMul_UndefInstr (state
, instr
);
2014 UNDEF_LSRBaseEQOffWb
;
2015 UNDEF_LSRBaseEQDestWb
;
2019 if (StoreByte (state
, instr
, lhs
))
2020 LSBase
= lhs
- LSRegRHS
;
2023 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2026 ARMul_UndefInstr (state
, instr
);
2029 UNDEF_LSRBaseEQOffWb
;
2030 UNDEF_LSRBaseEQDestWb
;
2034 temp
= lhs
- LSRegRHS
;
2035 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2039 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2042 ARMul_UndefInstr (state
, instr
);
2045 UNDEF_LSRBaseEQOffWb
;
2046 UNDEF_LSRBaseEQDestWb
;
2050 state
->NtransSig
= LOW
;
2051 if (StoreByte (state
, instr
, lhs
))
2052 LSBase
= lhs
- LSRegRHS
;
2053 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2056 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2059 ARMul_UndefInstr (state
, instr
);
2062 UNDEF_LSRBaseEQOffWb
;
2063 UNDEF_LSRBaseEQDestWb
;
2067 temp
= lhs
- LSRegRHS
;
2068 state
->NtransSig
= LOW
;
2069 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2071 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2074 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2077 ARMul_UndefInstr (state
, instr
);
2080 UNDEF_LSRBaseEQOffWb
;
2081 UNDEF_LSRBaseEQDestWb
;
2085 if (StoreWord (state
, instr
, lhs
))
2086 LSBase
= lhs
+ LSRegRHS
;
2089 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2092 ARMul_UndefInstr (state
, instr
);
2095 UNDEF_LSRBaseEQOffWb
;
2096 UNDEF_LSRBaseEQDestWb
;
2100 temp
= lhs
+ LSRegRHS
;
2101 if (LoadWord (state
, instr
, lhs
))
2105 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2108 ARMul_UndefInstr (state
, instr
);
2111 UNDEF_LSRBaseEQOffWb
;
2112 UNDEF_LSRBaseEQDestWb
;
2116 state
->NtransSig
= LOW
;
2117 if (StoreWord (state
, instr
, lhs
))
2118 LSBase
= lhs
+ LSRegRHS
;
2119 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2122 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2125 ARMul_UndefInstr (state
, instr
);
2128 UNDEF_LSRBaseEQOffWb
;
2129 UNDEF_LSRBaseEQDestWb
;
2133 temp
= lhs
+ LSRegRHS
;
2134 state
->NtransSig
= LOW
;
2135 if (LoadWord (state
, instr
, lhs
))
2137 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2140 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2143 ARMul_UndefInstr (state
, instr
);
2146 UNDEF_LSRBaseEQOffWb
;
2147 UNDEF_LSRBaseEQDestWb
;
2151 if (StoreByte (state
, instr
, lhs
))
2152 LSBase
= lhs
+ LSRegRHS
;
2155 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2158 ARMul_UndefInstr (state
, instr
);
2161 UNDEF_LSRBaseEQOffWb
;
2162 UNDEF_LSRBaseEQDestWb
;
2166 temp
= lhs
+ LSRegRHS
;
2167 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2171 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2174 ARMul_UndefInstr (state
, instr
);
2177 UNDEF_LSRBaseEQOffWb
;
2178 UNDEF_LSRBaseEQDestWb
;
2182 state
->NtransSig
= LOW
;
2183 if (StoreByte (state
, instr
, lhs
))
2184 LSBase
= lhs
+ LSRegRHS
;
2185 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2188 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2191 ARMul_UndefInstr (state
, instr
);
2194 UNDEF_LSRBaseEQOffWb
;
2195 UNDEF_LSRBaseEQDestWb
;
2199 temp
= lhs
+ LSRegRHS
;
2200 state
->NtransSig
= LOW
;
2201 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2203 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2207 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2210 ARMul_UndefInstr (state
, instr
);
2213 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2216 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2219 ARMul_UndefInstr (state
, instr
);
2222 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2225 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2228 ARMul_UndefInstr (state
, instr
);
2231 UNDEF_LSRBaseEQOffWb
;
2232 UNDEF_LSRBaseEQDestWb
;
2235 temp
= LHS
- LSRegRHS
;
2236 if (StoreWord (state
, instr
, temp
))
2240 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2243 ARMul_UndefInstr (state
, instr
);
2246 UNDEF_LSRBaseEQOffWb
;
2247 UNDEF_LSRBaseEQDestWb
;
2250 temp
= LHS
- LSRegRHS
;
2251 if (LoadWord (state
, instr
, temp
))
2255 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2258 ARMul_UndefInstr (state
, instr
);
2261 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2264 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2267 ARMul_UndefInstr (state
, instr
);
2270 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2273 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2276 ARMul_UndefInstr (state
, instr
);
2279 UNDEF_LSRBaseEQOffWb
;
2280 UNDEF_LSRBaseEQDestWb
;
2283 temp
= LHS
- LSRegRHS
;
2284 if (StoreByte (state
, instr
, temp
))
2288 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2291 ARMul_UndefInstr (state
, instr
);
2294 UNDEF_LSRBaseEQOffWb
;
2295 UNDEF_LSRBaseEQDestWb
;
2298 temp
= LHS
- LSRegRHS
;
2299 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2303 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2306 ARMul_UndefInstr (state
, instr
);
2309 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2312 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2315 ARMul_UndefInstr (state
, instr
);
2318 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2321 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2324 ARMul_UndefInstr (state
, instr
);
2327 UNDEF_LSRBaseEQOffWb
;
2328 UNDEF_LSRBaseEQDestWb
;
2331 temp
= LHS
+ LSRegRHS
;
2332 if (StoreWord (state
, instr
, temp
))
2336 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2339 ARMul_UndefInstr (state
, instr
);
2342 UNDEF_LSRBaseEQOffWb
;
2343 UNDEF_LSRBaseEQDestWb
;
2346 temp
= LHS
+ LSRegRHS
;
2347 if (LoadWord (state
, instr
, temp
))
2351 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2354 ARMul_UndefInstr (state
, instr
);
2357 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2360 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2363 ARMul_UndefInstr (state
, instr
);
2366 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2369 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2372 ARMul_UndefInstr (state
, instr
);
2375 UNDEF_LSRBaseEQOffWb
;
2376 UNDEF_LSRBaseEQDestWb
;
2379 temp
= LHS
+ LSRegRHS
;
2380 if (StoreByte (state
, instr
, temp
))
2384 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2387 /* Check for the special breakpoint opcode.
2388 This value should correspond to the value defined
2389 as ARM_BE_BREAKPOINT in gdb/arm-tdep.c. */
2390 if (BITS (0, 19) == 0xfdefe)
2392 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2393 ARMul_Abort (state
, ARMul_SWIV
);
2396 ARMul_UndefInstr (state
, instr
);
2399 UNDEF_LSRBaseEQOffWb
;
2400 UNDEF_LSRBaseEQDestWb
;
2403 temp
= LHS
+ LSRegRHS
;
2404 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2408 /***************************************************************************\
2409 * Multiple Data Transfer Instructions *
2410 \***************************************************************************/
2412 case 0x80: /* Store, No WriteBack, Post Dec */
2413 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2416 case 0x81: /* Load, No WriteBack, Post Dec */
2417 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2420 case 0x82: /* Store, WriteBack, Post Dec */
2421 temp
= LSBase
- LSMNumRegs
;
2422 STOREMULT (instr
, temp
+ 4L, temp
);
2425 case 0x83: /* Load, WriteBack, Post Dec */
2426 temp
= LSBase
- LSMNumRegs
;
2427 LOADMULT (instr
, temp
+ 4L, temp
);
2430 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2431 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2434 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2435 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2438 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2439 temp
= LSBase
- LSMNumRegs
;
2440 STORESMULT (instr
, temp
+ 4L, temp
);
2443 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2444 temp
= LSBase
- LSMNumRegs
;
2445 LOADSMULT (instr
, temp
+ 4L, temp
);
2449 case 0x88: /* Store, No WriteBack, Post Inc */
2450 STOREMULT (instr
, LSBase
, 0L);
2453 case 0x89: /* Load, No WriteBack, Post Inc */
2454 LOADMULT (instr
, LSBase
, 0L);
2457 case 0x8a: /* Store, WriteBack, Post Inc */
2459 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
2462 case 0x8b: /* Load, WriteBack, Post Inc */
2464 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
2467 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2468 STORESMULT (instr
, LSBase
, 0L);
2471 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2472 LOADSMULT (instr
, LSBase
, 0L);
2475 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2477 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
2480 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2482 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
2486 case 0x90: /* Store, No WriteBack, Pre Dec */
2487 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2490 case 0x91: /* Load, No WriteBack, Pre Dec */
2491 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2494 case 0x92: /* Store, WriteBack, Pre Dec */
2495 temp
= LSBase
- LSMNumRegs
;
2496 STOREMULT (instr
, temp
, temp
);
2499 case 0x93: /* Load, WriteBack, Pre Dec */
2500 temp
= LSBase
- LSMNumRegs
;
2501 LOADMULT (instr
, temp
, temp
);
2504 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2505 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2508 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2509 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2512 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
2513 temp
= LSBase
- LSMNumRegs
;
2514 STORESMULT (instr
, temp
, temp
);
2517 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
2518 temp
= LSBase
- LSMNumRegs
;
2519 LOADSMULT (instr
, temp
, temp
);
2523 case 0x98: /* Store, No WriteBack, Pre Inc */
2524 STOREMULT (instr
, LSBase
+ 4L, 0L);
2527 case 0x99: /* Load, No WriteBack, Pre Inc */
2528 LOADMULT (instr
, LSBase
+ 4L, 0L);
2531 case 0x9a: /* Store, WriteBack, Pre Inc */
2533 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2536 case 0x9b: /* Load, WriteBack, Pre Inc */
2538 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2541 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
2542 STORESMULT (instr
, LSBase
+ 4L, 0L);
2545 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
2546 LOADSMULT (instr
, LSBase
+ 4L, 0L);
2549 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
2551 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2554 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
2556 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2559 /***************************************************************************\
2561 \***************************************************************************/
2571 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2575 /***************************************************************************\
2577 \***************************************************************************/
2587 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2591 /***************************************************************************\
2592 * Branch and Link forward *
2593 \***************************************************************************/
2604 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
2606 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2608 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2612 /***************************************************************************\
2613 * Branch and Link backward *
2614 \***************************************************************************/
2625 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
2627 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2629 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2633 /***************************************************************************\
2634 * Co-Processor Data Transfers *
2635 \***************************************************************************/
2638 case 0xc0: /* Store , No WriteBack , Post Dec */
2639 ARMul_STC (state
, instr
, LHS
);
2643 case 0xc1: /* Load , No WriteBack , Post Dec */
2644 ARMul_LDC (state
, instr
, LHS
);
2648 case 0xc6: /* Store , WriteBack , Post Dec */
2650 state
->Base
= lhs
- LSCOff
;
2651 ARMul_STC (state
, instr
, lhs
);
2655 case 0xc7: /* Load , WriteBack , Post Dec */
2657 state
->Base
= lhs
- LSCOff
;
2658 ARMul_LDC (state
, instr
, lhs
);
2662 case 0xcc: /* Store , No WriteBack , Post Inc */
2663 ARMul_STC (state
, instr
, LHS
);
2667 case 0xcd: /* Load , No WriteBack , Post Inc */
2668 ARMul_LDC (state
, instr
, LHS
);
2672 case 0xce: /* Store , WriteBack , Post Inc */
2674 state
->Base
= lhs
+ LSCOff
;
2675 ARMul_STC (state
, instr
, LHS
);
2679 case 0xcf: /* Load , WriteBack , Post Inc */
2681 state
->Base
= lhs
+ LSCOff
;
2682 ARMul_LDC (state
, instr
, LHS
);
2687 case 0xd4: /* Store , No WriteBack , Pre Dec */
2688 ARMul_STC (state
, instr
, LHS
- LSCOff
);
2692 case 0xd5: /* Load , No WriteBack , Pre Dec */
2693 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
2697 case 0xd6: /* Store , WriteBack , Pre Dec */
2700 ARMul_STC (state
, instr
, lhs
);
2704 case 0xd7: /* Load , WriteBack , Pre Dec */
2707 ARMul_LDC (state
, instr
, lhs
);
2711 case 0xdc: /* Store , No WriteBack , Pre Inc */
2712 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
2716 case 0xdd: /* Load , No WriteBack , Pre Inc */
2717 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
2721 case 0xde: /* Store , WriteBack , Pre Inc */
2724 ARMul_STC (state
, instr
, lhs
);
2728 case 0xdf: /* Load , WriteBack , Pre Inc */
2731 ARMul_LDC (state
, instr
, lhs
);
2734 /***************************************************************************\
2735 * Co-Processor Register Transfers (MCR) and Data Ops *
2736 \***************************************************************************/
2752 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
2754 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
2755 ((state
->Reg
[15] + isize
) & R15PCBITS
));
2759 ARMul_MCR (state
, instr
, DEST
);
2761 else /* CDP Part 1 */
2762 ARMul_CDP (state
, instr
);
2765 /***************************************************************************\
2766 * Co-Processor Register Transfers (MRC) and Data Ops *
2767 \***************************************************************************/
2779 temp
= ARMul_MRC (state
, instr
);
2782 ASSIGNN ((temp
& NBIT
) != 0);
2783 ASSIGNZ ((temp
& ZBIT
) != 0);
2784 ASSIGNC ((temp
& CBIT
) != 0);
2785 ASSIGNV ((temp
& VBIT
) != 0);
2790 else /* CDP Part 2 */
2791 ARMul_CDP (state
, instr
);
2794 /***************************************************************************\
2796 \***************************************************************************/
2814 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
2815 { /* a prefetch abort */
2816 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
2820 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
2822 ARMul_Abort (state
, ARMul_SWIV
);
2825 } /* 256 way main switch */
2832 #ifdef NEED_UI_LOOP_HOOK
2833 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
2835 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
2838 #endif /* NEED_UI_LOOP_HOOK */
2840 if (state
->Emulate
== ONCE
)
2841 state
->Emulate
= STOP
;
2842 /* If we have changed mode, allow the PC to advance before stopping. */
2843 else if (state
->Emulate
== CHANGEMODE
)
2845 else if (state
->Emulate
!= RUN
)
2848 while (!stop_simulator
); /* do loop */
2850 state
->decoded
= decoded
;
2851 state
->loaded
= loaded
;
2855 } /* Emulate 26/32 in instruction based mode */
2858 /***************************************************************************\
2859 * This routine evaluates most Data Processing register RHS's with the S *
2860 * bit clear. It is intended to be called from the macro DPRegRHS, which *
2861 * filters the common case of an unshifted register with in line code *
2862 \***************************************************************************/
2865 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
2867 ARMword shamt
, base
;
2871 { /* shift amount in a register */
2876 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2879 base
= state
->Reg
[base
];
2880 ARMul_Icycles (state
, 1, 0L);
2881 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
2882 switch ((int) BITS (5, 6))
2887 else if (shamt
>= 32)
2890 return (base
<< shamt
);
2894 else if (shamt
>= 32)
2897 return (base
>> shamt
);
2901 else if (shamt
>= 32)
2902 return ((ARMword
) ((long int) base
>> 31L));
2904 return ((ARMword
) ((long int) base
>> (int) shamt
));
2910 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
2914 { /* shift amount is a constant */
2917 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2920 base
= state
->Reg
[base
];
2921 shamt
= BITS (7, 11);
2922 switch ((int) BITS (5, 6))
2925 return (base
<< shamt
);
2930 return (base
>> shamt
);
2933 return ((ARMword
) ((long int) base
>> 31L));
2935 return ((ARMword
) ((long int) base
>> (int) shamt
));
2937 if (shamt
== 0) /* its an RRX */
2938 return ((base
>> 1) | (CFLAG
<< 31));
2940 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
2943 return (0); /* just to shut up lint */
2946 /***************************************************************************\
2947 * This routine evaluates most Logical Data Processing register RHS's *
2948 * with the S bit set. It is intended to be called from the macro *
2949 * DPSRegRHS, which filters the common case of an unshifted register *
2950 * with in line code *
2951 \***************************************************************************/
2954 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
2956 ARMword shamt
, base
;
2960 { /* shift amount in a register */
2965 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2968 base
= state
->Reg
[base
];
2969 ARMul_Icycles (state
, 1, 0L);
2970 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
2971 switch ((int) BITS (5, 6))
2976 else if (shamt
== 32)
2981 else if (shamt
> 32)
2988 ASSIGNC ((base
>> (32 - shamt
)) & 1);
2989 return (base
<< shamt
);
2994 else if (shamt
== 32)
2996 ASSIGNC (base
>> 31);
2999 else if (shamt
> 32)
3006 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3007 return (base
>> shamt
);
3012 else if (shamt
>= 32)
3014 ASSIGNC (base
>> 31L);
3015 return ((ARMword
) ((long int) base
>> 31L));
3019 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3020 return ((ARMword
) ((long int) base
>> (int) shamt
));
3028 ASSIGNC (base
>> 31);
3033 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3034 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3039 { /* shift amount is a constant */
3042 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3045 base
= state
->Reg
[base
];
3046 shamt
= BITS (7, 11);
3047 switch ((int) BITS (5, 6))
3050 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3051 return (base
<< shamt
);
3055 ASSIGNC (base
>> 31);
3060 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3061 return (base
>> shamt
);
3066 ASSIGNC (base
>> 31L);
3067 return ((ARMword
) ((long int) base
>> 31L));
3071 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3072 return ((ARMword
) ((long int) base
>> (int) shamt
));
3079 return ((base
>> 1) | (shamt
<< 31));
3083 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3084 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3088 return (0); /* just to shut up lint */
3091 /***************************************************************************\
3092 * This routine handles writes to register 15 when the S bit is not set. *
3093 \***************************************************************************/
3096 WriteR15 (ARMul_State
* state
, ARMword src
)
3098 /* The ARM documentation states that the two least significant bits
3099 are discarded when setting PC, except in the cases handled by
3100 WriteR15Branch() below. It's probably an oversight: in THUMB
3101 mode, the second least significant bit should probably not be
3110 state
->Reg
[15] = src
& PCBITS
;
3112 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
3113 ARMul_R15Altered (state
);
3118 /***************************************************************************\
3119 * This routine handles writes to register 15 when the S bit is set. *
3120 \***************************************************************************/
3123 WriteSR15 (ARMul_State
* state
, ARMword src
)
3126 if (state
->Bank
> 0)
3128 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3129 ARMul_CPSRAltered (state
);
3137 state
->Reg
[15] = src
& PCBITS
;
3141 abort (); /* ARMul_R15Altered would have to support it. */
3145 if (state
->Bank
== USERBANK
)
3146 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3148 state
->Reg
[15] = src
;
3149 ARMul_R15Altered (state
);
3154 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3155 will switch to Thumb mode if the least significant bit is set. */
3158 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3164 state
->Reg
[15] = src
& 0xfffffffe;
3169 state
->Reg
[15] = src
& 0xfffffffc;
3173 WriteR15 (state
, src
);
3177 /***************************************************************************\
3178 * This routine evaluates most Load and Store register RHS's. It is *
3179 * intended to be called from the macro LSRegRHS, which filters the *
3180 * common case of an unshifted register with in line code *
3181 \***************************************************************************/
3184 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3186 ARMword shamt
, base
;
3191 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3194 base
= state
->Reg
[base
];
3196 shamt
= BITS (7, 11);
3197 switch ((int) BITS (5, 6))
3200 return (base
<< shamt
);
3205 return (base
>> shamt
);
3208 return ((ARMword
) ((long int) base
>> 31L));
3210 return ((ARMword
) ((long int) base
>> (int) shamt
));
3212 if (shamt
== 0) /* its an RRX */
3213 return ((base
>> 1) | (CFLAG
<< 31));
3215 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3217 return (0); /* just to shut up lint */
3220 /***************************************************************************\
3221 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3222 \***************************************************************************/
3225 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3231 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3233 return state
->Reg
[RHSReg
];
3236 /* else immediate */
3237 return BITS (0, 3) | (BITS (8, 11) << 4);
3240 /***************************************************************************\
3241 * This function does the work of loading a word for a LDR instruction. *
3242 \***************************************************************************/
3245 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3251 if (ADDREXCEPT (address
))
3253 INTERNALABORT (address
);
3256 dest
= ARMul_LoadWordN (state
, address
);
3260 return (state
->lateabtSig
);
3263 dest
= ARMul_Align (state
, address
, dest
);
3265 ARMul_Icycles (state
, 1, 0L);
3267 return (DESTReg
!= LHSReg
);
3271 /***************************************************************************\
3272 * This function does the work of loading a halfword. *
3273 \***************************************************************************/
3276 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3283 if (ADDREXCEPT (address
))
3285 INTERNALABORT (address
);
3288 dest
= ARMul_LoadHalfWord (state
, address
);
3292 return (state
->lateabtSig
);
3297 if (dest
& 1 << (16 - 1))
3298 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3301 ARMul_Icycles (state
, 1, 0L);
3302 return (DESTReg
!= LHSReg
);
3307 /***************************************************************************\
3308 * This function does the work of loading a byte for a LDRB instruction. *
3309 \***************************************************************************/
3312 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3318 if (ADDREXCEPT (address
))
3320 INTERNALABORT (address
);
3323 dest
= ARMul_LoadByte (state
, address
);
3327 return (state
->lateabtSig
);
3332 if (dest
& 1 << (8 - 1))
3333 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3336 ARMul_Icycles (state
, 1, 0L);
3337 return (DESTReg
!= LHSReg
);
3340 /***************************************************************************\
3341 * This function does the work of storing a word from a STR instruction. *
3342 \***************************************************************************/
3345 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3350 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3353 ARMul_StoreWordN (state
, address
, DEST
);
3355 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3357 INTERNALABORT (address
);
3358 (void) ARMul_LoadWordN (state
, address
);
3361 ARMul_StoreWordN (state
, address
, DEST
);
3366 return (state
->lateabtSig
);
3372 /***************************************************************************\
3373 * This function does the work of storing a byte for a STRH instruction. *
3374 \***************************************************************************/
3377 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3383 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3387 ARMul_StoreHalfWord (state
, address
, DEST
);
3389 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3391 INTERNALABORT (address
);
3392 (void) ARMul_LoadHalfWord (state
, address
);
3395 ARMul_StoreHalfWord (state
, address
, DEST
);
3401 return (state
->lateabtSig
);
3409 /***************************************************************************\
3410 * This function does the work of storing a byte for a STRB instruction. *
3411 \***************************************************************************/
3414 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
3419 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3422 ARMul_StoreByte (state
, address
, DEST
);
3424 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3426 INTERNALABORT (address
);
3427 (void) ARMul_LoadByte (state
, address
);
3430 ARMul_StoreByte (state
, address
, DEST
);
3435 return (state
->lateabtSig
);
3441 /***************************************************************************\
3442 * This function does the work of loading the registers listed in an LDM *
3443 * instruction, when the S bit is clear. The code here is always increment *
3444 * after, it's up to the caller to get the input address correct and to *
3445 * handle base register modification. *
3446 \***************************************************************************/
3449 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
3455 UNDEF_LSMBaseInListWb
;
3458 if (ADDREXCEPT (address
))
3460 INTERNALABORT (address
);
3463 if (BIT (21) && LHSReg
!= 15)
3466 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3467 dest
= ARMul_LoadWordN (state
, address
);
3468 if (!state
->abortSig
&& !state
->Aborted
)
3469 state
->Reg
[temp
++] = dest
;
3470 else if (!state
->Aborted
)
3471 state
->Aborted
= ARMul_DataAbortV
;
3473 for (; temp
< 16; temp
++) /* S cycles from here on */
3475 { /* load this register */
3477 dest
= ARMul_LoadWordS (state
, address
);
3478 if (!state
->abortSig
&& !state
->Aborted
)
3479 state
->Reg
[temp
] = dest
;
3480 else if (!state
->Aborted
)
3481 state
->Aborted
= ARMul_DataAbortV
;
3484 if (BIT (15) && !state
->Aborted
)
3485 { /* PC is in the reg list */
3486 WriteR15Branch(state
, PC
);
3489 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3493 if (BIT (21) && LHSReg
!= 15)
3499 /***************************************************************************\
3500 * This function does the work of loading the registers listed in an LDM *
3501 * instruction, when the S bit is set. The code here is always increment *
3502 * after, it's up to the caller to get the input address correct and to *
3503 * handle base register modification. *
3504 \***************************************************************************/
3507 LoadSMult (ARMul_State
* state
, ARMword instr
,
3508 ARMword address
, ARMword WBBase
)
3514 UNDEF_LSMBaseInListWb
;
3517 if (ADDREXCEPT (address
))
3519 INTERNALABORT (address
);
3523 if (!BIT (15) && state
->Bank
!= USERBANK
)
3525 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* temporary reg bank switch */
3526 UNDEF_LSMUserBankWb
;
3529 if (BIT (21) && LHSReg
!= 15)
3532 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3533 dest
= ARMul_LoadWordN (state
, address
);
3534 if (!state
->abortSig
)
3535 state
->Reg
[temp
++] = dest
;
3536 else if (!state
->Aborted
)
3537 state
->Aborted
= ARMul_DataAbortV
;
3539 for (; temp
< 16; temp
++) /* S cycles from here on */
3541 { /* load this register */
3543 dest
= ARMul_LoadWordS (state
, address
);
3544 if (!state
->abortSig
&& !state
->Aborted
)
3545 state
->Reg
[temp
] = dest
;
3546 else if (!state
->Aborted
)
3547 state
->Aborted
= ARMul_DataAbortV
;
3550 if (BIT (15) && !state
->Aborted
)
3551 { /* PC is in the reg list */
3553 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3555 state
->Cpsr
= GETSPSR (state
->Bank
);
3556 ARMul_CPSRAltered (state
);
3558 WriteR15 (state
, PC
);
3560 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
3561 { /* protect bits in user mode */
3562 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
3563 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
3564 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
3565 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
3568 ARMul_R15Altered (state
);
3573 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3574 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3576 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3580 if (BIT (21) && LHSReg
!= 15)
3587 /***************************************************************************\
3588 * This function does the work of storing the registers listed in an STM *
3589 * instruction, when the S bit is clear. The code here is always increment *
3590 * after, it's up to the caller to get the input address correct and to *
3591 * handle base register modification. *
3592 \***************************************************************************/
3595 StoreMult (ARMul_State
* state
, ARMword instr
,
3596 ARMword address
, ARMword WBBase
)
3602 UNDEF_LSMBaseInListWb
;
3605 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
3609 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3611 INTERNALABORT (address
);
3617 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3619 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3623 (void) ARMul_LoadWordN (state
, address
);
3624 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3626 { /* save this register */
3628 (void) ARMul_LoadWordS (state
, address
);
3630 if (BIT (21) && LHSReg
!= 15)
3636 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3638 if (state
->abortSig
&& !state
->Aborted
)
3639 state
->Aborted
= ARMul_DataAbortV
;
3641 if (BIT (21) && LHSReg
!= 15)
3644 for (; temp
< 16; temp
++) /* S cycles from here on */
3646 { /* save this register */
3648 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3649 if (state
->abortSig
&& !state
->Aborted
)
3650 state
->Aborted
= ARMul_DataAbortV
;
3658 /***************************************************************************\
3659 * This function does the work of storing the registers listed in an STM *
3660 * instruction when the S bit is set. The code here is always increment *
3661 * after, it's up to the caller to get the input address correct and to *
3662 * handle base register modification. *
3663 \***************************************************************************/
3666 StoreSMult (ARMul_State
* state
, ARMword instr
,
3667 ARMword address
, ARMword WBBase
)
3673 UNDEF_LSMBaseInListWb
;
3676 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3678 INTERNALABORT (address
);
3684 if (state
->Bank
!= USERBANK
)
3686 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* Force User Bank */
3687 UNDEF_LSMUserBankWb
;
3690 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3692 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3696 (void) ARMul_LoadWordN (state
, address
);
3697 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3699 { /* save this register */
3701 (void) ARMul_LoadWordS (state
, address
);
3703 if (BIT (21) && LHSReg
!= 15)
3709 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3711 if (state
->abortSig
&& !state
->Aborted
)
3712 state
->Aborted
= ARMul_DataAbortV
;
3714 if (BIT (21) && LHSReg
!= 15)
3717 for (; temp
< 16; temp
++) /* S cycles from here on */
3719 { /* save this register */
3721 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3722 if (state
->abortSig
&& !state
->Aborted
)
3723 state
->Aborted
= ARMul_DataAbortV
;
3726 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3727 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3735 /***************************************************************************\
3736 * This function does the work of adding two 32bit values together, and *
3737 * calculating if a carry has occurred. *
3738 \***************************************************************************/
3741 Add32 (ARMword a1
, ARMword a2
, int *carry
)
3743 ARMword result
= (a1
+ a2
);
3744 unsigned int uresult
= (unsigned int) result
;
3745 unsigned int ua1
= (unsigned int) a1
;
3747 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
3748 or (result > RdLo) then we have no carry: */
3749 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
3757 /***************************************************************************\
3758 * This function does the work of multiplying two 32bit values to give a *
3760 \***************************************************************************/
3763 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3765 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
3766 ARMword RdHi
= 0, RdLo
= 0, Rm
;
3767 int scount
; /* cycle count */
3769 nRdHi
= BITS (16, 19);
3770 nRdLo
= BITS (12, 15);
3774 /* Needed to calculate the cycle count: */
3775 Rm
= state
->Reg
[nRm
];
3777 /* Check for illegal operand combinations first: */
3781 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
3783 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
3785 ARMword Rs
= state
->Reg
[nRs
];
3790 /* Compute sign of result and adjust operands if necessary. */
3792 sign
= (Rm
^ Rs
) & 0x80000000;
3794 if (((signed long) Rm
) < 0)
3797 if (((signed long) Rs
) < 0)
3801 /* We can split the 32x32 into four 16x16 operations. This ensures
3802 that we do not lose precision on 32bit only hosts: */
3803 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
3804 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3805 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
3806 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3808 /* We now need to add all of these results together, taking care
3809 to propogate the carries from the additions: */
3810 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
3812 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
3814 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
3818 /* Negate result if necessary. */
3822 if (RdLo
== 0xFFFFFFFF)
3831 state
->Reg
[nRdLo
] = RdLo
;
3832 state
->Reg
[nRdHi
] = RdHi
;
3833 } /* else undefined result */
3835 fprintf (stderr
, "MULTIPLY64 - INVALID ARGUMENTS\n");
3839 /* Ensure that both RdHi and RdLo are used to compute Z, but
3840 don't let RdLo's sign bit make it to N. */
3841 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
3844 /* The cycle count depends on whether the instruction is a signed or
3845 unsigned multiply, and what bits are clear in the multiplier: */
3846 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
3847 Rm
= ~Rm
; /* invert the bits to make the check against zero */
3849 if ((Rm
& 0xFFFFFF00) == 0)
3851 else if ((Rm
& 0xFFFF0000) == 0)
3853 else if ((Rm
& 0xFF000000) == 0)
3861 /***************************************************************************\
3862 * This function does the work of multiplying two 32bit values and adding *
3863 * a 64bit value to give a 64bit result. *
3864 \***************************************************************************/
3867 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3874 nRdHi
= BITS (16, 19);
3875 nRdLo
= BITS (12, 15);
3877 RdHi
= state
->Reg
[nRdHi
];
3878 RdLo
= state
->Reg
[nRdLo
];
3880 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
3882 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
3883 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
3885 state
->Reg
[nRdLo
] = RdLo
;
3886 state
->Reg
[nRdHi
] = RdHi
;
3890 /* Ensure that both RdHi and RdLo are used to compute Z, but
3891 don't let RdLo's sign bit make it to N. */
3892 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
3895 return scount
+ 1; /* extra cycle for addition */
This page took 0.11243 seconds and 4 git commands to generate.