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 temp = lhs - GetLS7RHS (state, instr); \
116 switch (BITS (5, 6)) \
119 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
123 if (LoadByte (state, instr, lhs, LSIGNED)) \
127 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
130 case 0: /* SWP handled elsewhere. */ \
139 /* Load post increment writeback. */
144 temp = lhs + GetLS7RHS (state, instr); \
146 switch (BITS (5, 6)) \
149 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
153 if (LoadByte (state, instr, lhs, LSIGNED)) \
157 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
160 case 0: /* SWP handled elsewhere. */ \
170 /* load pre decrement */
171 #define LHPREDOWN() \
174 temp = LHS - GetLS7RHS(state,instr) ; \
175 switch (BITS(5,6)) { \
177 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
180 (void)LoadByte(state,instr,temp,LSIGNED) ; \
183 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
185 case 0: /* SWP handled elsewhere */ \
194 /* load pre decrement writeback */
195 #define LHPREDOWNWB() \
198 temp = LHS - GetLS7RHS(state, instr) ; \
199 switch (BITS(5,6)) { \
201 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
205 if (LoadByte(state,instr,temp,LSIGNED)) \
209 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
212 case 0: /* SWP handled elsewhere */ \
221 /* load pre increment */
225 temp = LHS + GetLS7RHS(state,instr) ; \
226 switch (BITS(5,6)) { \
228 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
231 (void)LoadByte(state,instr,temp,LSIGNED) ; \
234 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
236 case 0: /* SWP handled elsewhere */ \
245 /* load pre increment writeback */
246 #define LHPREUPWB() \
249 temp = LHS + GetLS7RHS(state, instr) ; \
250 switch (BITS(5,6)) { \
252 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
256 if (LoadByte(state,instr,temp,LSIGNED)) \
260 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
263 case 0: /* SWP handled elsewhere */ \
272 /***************************************************************************\
273 * EMULATION of ARM6 *
274 \***************************************************************************/
276 /* The PC pipeline value depends on whether ARM or Thumb instructions
277 are being executed: */
282 ARMul_Emulate32 (register ARMul_State
* state
)
286 ARMul_Emulate26 (register ARMul_State
* state
)
289 register ARMword instr
, /* the current instruction */
290 dest
= 0, /* almost the DestBus */
291 temp
, /* ubiquitous third hand */
292 pc
= 0; /* the address of the current instruction */
293 ARMword lhs
, rhs
; /* almost the ABus and BBus */
294 ARMword decoded
= 0, loaded
= 0; /* instruction pipeline */
296 /***************************************************************************\
297 * Execute the next instruction *
298 \***************************************************************************/
300 if (state
->NextInstr
< PRIMEPIPE
)
302 decoded
= state
->decoded
;
303 loaded
= state
->loaded
;
308 { /* just keep going */
310 switch (state
->NextInstr
)
313 state
->Reg
[15] += isize
; /* Advance the pipeline, and an S cycle */
317 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
321 state
->Reg
[15] += isize
; /* Advance the pipeline, and an N cycle */
325 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
330 pc
+= isize
; /* Program counter advanced, and an S cycle */
333 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
338 pc
+= isize
; /* Program counter advanced, and an N cycle */
341 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
345 case RESUME
: /* The program counter has been changed */
350 state
->Reg
[15] = pc
+ (isize
* 2);
352 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
353 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
354 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
358 default: /* The program counter has been changed */
363 state
->Reg
[15] = pc
+ (isize
* 2);
365 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
366 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
367 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
372 ARMul_EnvokeEvent (state
);
375 /* Enable this for a helpful bit of debugging when tracing is needed. */
376 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
381 if (state
->Exception
)
382 { /* Any exceptions */
383 if (state
->NresetSig
== LOW
)
385 ARMul_Abort (state
, ARMul_ResetV
);
388 else if (!state
->NfiqSig
&& !FFLAG
)
390 ARMul_Abort (state
, ARMul_FIQV
);
393 else if (!state
->NirqSig
&& !IFLAG
)
395 ARMul_Abort (state
, ARMul_IRQV
);
400 if (state
->CallDebug
> 0)
402 instr
= ARMul_Debug (state
, pc
, instr
);
403 if (state
->Emulate
< ONCE
)
405 state
->NextInstr
= RESUME
;
410 fprintf (stderr
, "At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
412 (void) fgetc (stdin
);
415 else if (state
->Emulate
< ONCE
)
417 state
->NextInstr
= RESUME
;
424 /* Provide Thumb instruction decoding. If the processor is in Thumb
425 mode, then we can simply decode the Thumb instruction, and map it
426 to the corresponding ARM instruction (by directly loading the
427 instr variable, and letting the normal ARM simulator
428 execute). There are some caveats to ensure that the correct
429 pipelined PC value is used when executing Thumb code, and also for
430 dealing with the BL instruction. */
432 { /* check if in Thumb mode */
434 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
437 ARMul_UndefInstr (state
, instr
); /* This is a Thumb instruction */
440 case t_branch
: /* already processed */
443 case t_decoded
: /* ARM instruction available */
444 instr
= new; /* so continue instruction decoding */
450 /***************************************************************************\
451 * Check the condition codes *
452 \***************************************************************************/
453 if ((temp
= TOPBITS (28)) == AL
)
454 goto mainswitch
; /* vile deed in the need for speed */
456 switch ((int) TOPBITS (28))
457 { /* check the condition code */
489 temp
= (CFLAG
&& !ZFLAG
);
492 temp
= (!CFLAG
|| ZFLAG
);
495 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
498 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
501 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
504 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
508 /***************************************************************************\
509 * Actual execution of instructions begins here *
510 \***************************************************************************/
513 { /* if the condition codes don't match, stop here */
517 switch ((int) BITS (20, 27))
520 /***************************************************************************\
521 * Data Processing Register RHS Instructions *
522 \***************************************************************************/
524 case 0x00: /* AND reg and MUL */
526 if (BITS (4, 11) == 0xB)
528 /* STRH register offset, no write-back, down, post indexed */
532 /* TODO: CHECK: should 0xD and 0xF generate undefined intruction aborts? */
534 if (BITS (4, 7) == 9)
536 rhs
= state
->Reg
[MULRHSReg
];
537 if (MULLHSReg
== MULDESTReg
)
540 state
->Reg
[MULDESTReg
] = 0;
542 else if (MULDESTReg
!= 15)
543 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
548 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
549 if (rhs
& (1L << dest
))
550 temp
= dest
; /* mult takes this many/2 I cycles */
551 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
561 case 0x01: /* ANDS reg and MULS */
563 if ((BITS (4, 11) & 0xF9) == 0x9)
565 /* LDR register offset, no write-back, down, post indexed */
567 /* fall through to rest of decoding */
570 if (BITS (4, 7) == 9)
572 rhs
= state
->Reg
[MULRHSReg
];
573 if (MULLHSReg
== MULDESTReg
)
576 state
->Reg
[MULDESTReg
] = 0;
580 else if (MULDESTReg
!= 15)
582 dest
= state
->Reg
[MULLHSReg
] * rhs
;
583 ARMul_NegZero (state
, dest
);
584 state
->Reg
[MULDESTReg
] = dest
;
590 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
591 if (rhs
& (1L << dest
))
592 temp
= dest
; /* mult takes this many/2 I cycles */
593 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
603 case 0x02: /* EOR reg and MLA */
605 if (BITS (4, 11) == 0xB)
607 /* STRH register offset, write-back, down, post indexed */
612 if (BITS (4, 7) == 9)
614 rhs
= state
->Reg
[MULRHSReg
];
615 if (MULLHSReg
== MULDESTReg
)
618 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
620 else if (MULDESTReg
!= 15)
621 state
->Reg
[MULDESTReg
] =
622 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
627 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
628 if (rhs
& (1L << dest
))
629 temp
= dest
; /* mult takes this many/2 I cycles */
630 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
640 case 0x03: /* EORS reg and MLAS */
642 if ((BITS (4, 11) & 0xF9) == 0x9)
644 /* LDR register offset, write-back, down, post-indexed */
646 /* fall through to rest of the decoding */
649 if (BITS (4, 7) == 9)
651 rhs
= state
->Reg
[MULRHSReg
];
652 if (MULLHSReg
== MULDESTReg
)
655 dest
= state
->Reg
[MULACCReg
];
656 ARMul_NegZero (state
, dest
);
657 state
->Reg
[MULDESTReg
] = dest
;
659 else if (MULDESTReg
!= 15)
662 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
663 ARMul_NegZero (state
, dest
);
664 state
->Reg
[MULDESTReg
] = dest
;
670 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
671 if (rhs
& (1L << dest
))
672 temp
= dest
; /* mult takes this many/2 I cycles */
673 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
683 case 0x04: /* SUB reg */
685 if (BITS (4, 7) == 0xB)
687 /* STRH immediate offset, no write-back, down, post indexed */
697 case 0x05: /* SUBS reg */
699 if ((BITS (4, 7) & 0x9) == 0x9)
701 /* LDR immediate offset, no write-back, down, post indexed */
703 /* fall through to the rest of the instruction decoding */
709 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
711 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
712 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
722 case 0x06: /* RSB reg */
724 if (BITS (4, 7) == 0xB)
726 /* STRH immediate offset, write-back, down, post indexed */
736 case 0x07: /* RSBS reg */
738 if ((BITS (4, 7) & 0x9) == 0x9)
740 /* LDR immediate offset, write-back, down, post indexed */
742 /* fall through to remainder of instruction decoding */
748 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
750 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
751 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
761 case 0x08: /* ADD reg */
763 if (BITS (4, 11) == 0xB)
765 /* STRH register offset, no write-back, up, post indexed */
771 if (BITS (4, 7) == 0x9)
774 ARMul_Icycles (state
,
775 Multiply64 (state
, instr
, LUNSIGNED
,
785 case 0x09: /* ADDS reg */
787 if ((BITS (4, 11) & 0xF9) == 0x9)
789 /* LDR register offset, no write-back, up, post indexed */
791 /* fall through to remaining instruction decoding */
795 if (BITS (4, 7) == 0x9)
798 ARMul_Icycles (state
,
799 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
808 if ((lhs
| rhs
) >> 30)
809 { /* possible C,V,N to set */
810 ASSIGNN (NEG (dest
));
811 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
812 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
823 case 0x0a: /* ADC reg */
825 if (BITS (4, 11) == 0xB)
827 /* STRH register offset, write-back, up, post-indexed */
833 if (BITS (4, 7) == 0x9)
836 ARMul_Icycles (state
,
837 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
843 dest
= LHS
+ rhs
+ CFLAG
;
847 case 0x0b: /* ADCS reg */
849 if ((BITS (4, 11) & 0xF9) == 0x9)
851 /* LDR register offset, write-back, up, post indexed */
853 /* fall through to remaining instruction decoding */
857 if (BITS (4, 7) == 0x9)
860 ARMul_Icycles (state
,
861 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
868 dest
= lhs
+ rhs
+ CFLAG
;
870 if ((lhs
| rhs
) >> 30)
871 { /* possible C,V,N to set */
872 ASSIGNN (NEG (dest
));
873 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
874 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
885 case 0x0c: /* SBC reg */
887 if (BITS (4, 7) == 0xB)
889 /* STRH immediate offset, no write-back, up post indexed */
895 if (BITS (4, 7) == 0x9)
898 ARMul_Icycles (state
,
899 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
905 dest
= LHS
- rhs
- !CFLAG
;
909 case 0x0d: /* SBCS reg */
911 if ((BITS (4, 7) & 0x9) == 0x9)
913 /* LDR immediate offset, no write-back, up, post indexed */
918 if (BITS (4, 7) == 0x9)
921 ARMul_Icycles (state
,
922 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
929 dest
= lhs
- rhs
- !CFLAG
;
930 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
932 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
933 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
943 case 0x0e: /* RSC reg */
945 if (BITS (4, 7) == 0xB)
947 /* STRH immediate offset, write-back, up, post indexed */
953 if (BITS (4, 7) == 0x9)
956 ARMul_Icycles (state
,
957 MultiplyAdd64 (state
, instr
, LSIGNED
,
963 dest
= rhs
- LHS
- !CFLAG
;
967 case 0x0f: /* RSCS reg */
969 if ((BITS (4, 7) & 0x9) == 0x9)
971 /* LDR immediate offset, write-back, up, post indexed */
973 /* fall through to remaining instruction decoding */
977 if (BITS (4, 7) == 0x9)
980 ARMul_Icycles (state
,
981 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
988 dest
= rhs
- lhs
- !CFLAG
;
989 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
991 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
992 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1002 case 0x10: /* TST reg and MRS CPSR and SWP word */
1004 if (BITS (4, 11) == 0xB)
1006 /* STRH register offset, no write-back, down, pre indexed */
1011 if (BITS (4, 11) == 9)
1017 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1019 INTERNALABORT (temp
);
1020 (void) ARMul_LoadWordN (state
, temp
);
1021 (void) ARMul_LoadWordN (state
, temp
);
1025 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1027 DEST
= ARMul_Align (state
, temp
, dest
);
1030 if (state
->abortSig
|| state
->Aborted
)
1035 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1038 DEST
= ECC
| EINT
| EMODE
;
1046 case 0x11: /* TSTP reg */
1048 if ((BITS (4, 11) & 0xF9) == 0x9)
1050 /* LDR register offset, no write-back, down, pre indexed */
1052 /* continue with remaining instruction decode */
1058 state
->Cpsr
= GETSPSR (state
->Bank
);
1059 ARMul_CPSRAltered (state
);
1070 ARMul_NegZero (state
, dest
);
1074 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6) */
1076 if (BITS (4, 11) == 0xB)
1078 /* STRH register offset, write-back, down, pre indexed */
1084 if (BITS (4, 27) == 0x12FFF1)
1086 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1091 { /* MSR reg to CPSR */
1094 ARMul_FixCPSR (state
, instr
, temp
);
1102 case 0x13: /* TEQP reg */
1104 if ((BITS (4, 11) & 0xF9) == 0x9)
1106 /* LDR register offset, write-back, down, pre indexed */
1108 /* continue with remaining instruction decode */
1114 state
->Cpsr
= GETSPSR (state
->Bank
);
1115 ARMul_CPSRAltered (state
);
1126 ARMul_NegZero (state
, dest
);
1130 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1132 if (BITS (4, 7) == 0xB)
1134 /* STRH immediate offset, no write-back, down, pre indexed */
1139 if (BITS (4, 11) == 9)
1145 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1147 INTERNALABORT (temp
);
1148 (void) ARMul_LoadByte (state
, temp
);
1149 (void) ARMul_LoadByte (state
, temp
);
1153 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1154 if (state
->abortSig
|| state
->Aborted
)
1159 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1162 DEST
= GETSPSR (state
->Bank
);
1170 case 0x15: /* CMPP reg */
1172 if ((BITS (4, 7) & 0x9) == 0x9)
1174 /* LDR immediate offset, no write-back, down, pre indexed */
1176 /* continue with remaining instruction decode */
1182 state
->Cpsr
= GETSPSR (state
->Bank
);
1183 ARMul_CPSRAltered (state
);
1195 ARMul_NegZero (state
, dest
);
1196 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1198 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1199 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1209 case 0x16: /* CMN reg and MSR reg to SPSR */
1211 if (BITS (4, 7) == 0xB)
1213 /* STRH immediate offset, write-back, down, pre indexed */
1221 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1229 case 0x17: /* CMNP reg */
1231 if ((BITS (4, 7) & 0x9) == 0x9)
1233 /* LDR immediate offset, write-back, down, pre indexed */
1235 /* continue with remaining instruction decoding */
1241 state
->Cpsr
= GETSPSR (state
->Bank
);
1242 ARMul_CPSRAltered (state
);
1255 ASSIGNZ (dest
== 0);
1256 if ((lhs
| rhs
) >> 30)
1257 { /* possible C,V,N to set */
1258 ASSIGNN (NEG (dest
));
1259 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1260 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1271 case 0x18: /* ORR reg */
1273 if (BITS (4, 11) == 0xB)
1275 /* STRH register offset, no write-back, up, pre indexed */
1285 case 0x19: /* ORRS reg */
1287 if ((BITS (4, 11) & 0xF9) == 0x9)
1289 /* LDR register offset, no write-back, up, pre indexed */
1291 /* continue with remaining instruction decoding */
1299 case 0x1a: /* MOV reg */
1301 if (BITS (4, 11) == 0xB)
1303 /* STRH register offset, write-back, up, pre indexed */
1312 case 0x1b: /* MOVS reg */
1314 if ((BITS (4, 11) & 0xF9) == 0x9)
1316 /* LDR register offset, write-back, up, pre indexed */
1318 /* continue with remaining instruction decoding */
1325 case 0x1c: /* BIC reg */
1327 if (BITS (4, 7) == 0xB)
1329 /* STRH immediate offset, no write-back, up, pre indexed */
1339 case 0x1d: /* BICS reg */
1341 if ((BITS (4, 7) & 0x9) == 0x9)
1343 /* LDR immediate offset, no write-back, up, pre indexed */
1345 /* continue with instruction decoding */
1353 case 0x1e: /* MVN reg */
1355 if (BITS (4, 7) == 0xB)
1357 /* STRH immediate offset, write-back, up, pre indexed */
1366 case 0x1f: /* MVNS reg */
1368 if ((BITS (4, 7) & 0x9) == 0x9)
1370 /* LDR immediate offset, write-back, up, pre indexed */
1372 /* continue instruction decoding */
1379 /***************************************************************************\
1380 * Data Processing Immediate RHS Instructions *
1381 \***************************************************************************/
1383 case 0x20: /* AND immed */
1384 dest
= LHS
& DPImmRHS
;
1388 case 0x21: /* ANDS immed */
1394 case 0x22: /* EOR immed */
1395 dest
= LHS
^ DPImmRHS
;
1399 case 0x23: /* EORS immed */
1405 case 0x24: /* SUB immed */
1406 dest
= LHS
- DPImmRHS
;
1410 case 0x25: /* SUBS immed */
1414 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1416 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1417 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1427 case 0x26: /* RSB immed */
1428 dest
= DPImmRHS
- LHS
;
1432 case 0x27: /* RSBS immed */
1436 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1438 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1439 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1449 case 0x28: /* ADD immed */
1450 dest
= LHS
+ DPImmRHS
;
1454 case 0x29: /* ADDS immed */
1458 ASSIGNZ (dest
== 0);
1459 if ((lhs
| rhs
) >> 30)
1460 { /* possible C,V,N to set */
1461 ASSIGNN (NEG (dest
));
1462 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1463 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1474 case 0x2a: /* ADC immed */
1475 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1479 case 0x2b: /* ADCS immed */
1482 dest
= lhs
+ rhs
+ CFLAG
;
1483 ASSIGNZ (dest
== 0);
1484 if ((lhs
| rhs
) >> 30)
1485 { /* possible C,V,N to set */
1486 ASSIGNN (NEG (dest
));
1487 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1488 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1499 case 0x2c: /* SBC immed */
1500 dest
= LHS
- DPImmRHS
- !CFLAG
;
1504 case 0x2d: /* SBCS immed */
1507 dest
= lhs
- rhs
- !CFLAG
;
1508 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1510 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1511 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1521 case 0x2e: /* RSC immed */
1522 dest
= DPImmRHS
- LHS
- !CFLAG
;
1526 case 0x2f: /* RSCS immed */
1529 dest
= rhs
- lhs
- !CFLAG
;
1530 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1532 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1533 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1543 case 0x30: /* TST immed */
1547 case 0x31: /* TSTP immed */
1551 state
->Cpsr
= GETSPSR (state
->Bank
);
1552 ARMul_CPSRAltered (state
);
1554 temp
= LHS
& DPImmRHS
;
1560 DPSImmRHS
; /* TST immed */
1562 ARMul_NegZero (state
, dest
);
1566 case 0x32: /* TEQ immed and MSR immed to CPSR */
1568 { /* MSR immed to CPSR */
1569 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
1577 case 0x33: /* TEQP immed */
1581 state
->Cpsr
= GETSPSR (state
->Bank
);
1582 ARMul_CPSRAltered (state
);
1584 temp
= LHS
^ DPImmRHS
;
1590 DPSImmRHS
; /* TEQ immed */
1592 ARMul_NegZero (state
, dest
);
1596 case 0x34: /* CMP immed */
1600 case 0x35: /* CMPP immed */
1604 state
->Cpsr
= GETSPSR (state
->Bank
);
1605 ARMul_CPSRAltered (state
);
1607 temp
= LHS
- DPImmRHS
;
1614 lhs
= LHS
; /* CMP immed */
1617 ARMul_NegZero (state
, dest
);
1618 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1620 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1621 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1631 case 0x36: /* CMN immed and MSR immed to SPSR */
1632 if (DESTReg
== 15) /* MSR */
1633 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
1640 case 0x37: /* CMNP immed */
1644 state
->Cpsr
= GETSPSR (state
->Bank
);
1645 ARMul_CPSRAltered (state
);
1647 temp
= LHS
+ DPImmRHS
;
1654 lhs
= LHS
; /* CMN immed */
1657 ASSIGNZ (dest
== 0);
1658 if ((lhs
| rhs
) >> 30)
1659 { /* possible C,V,N to set */
1660 ASSIGNN (NEG (dest
));
1661 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1662 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1673 case 0x38: /* ORR immed */
1674 dest
= LHS
| DPImmRHS
;
1678 case 0x39: /* ORRS immed */
1684 case 0x3a: /* MOV immed */
1689 case 0x3b: /* MOVS immed */
1694 case 0x3c: /* BIC immed */
1695 dest
= LHS
& ~DPImmRHS
;
1699 case 0x3d: /* BICS immed */
1705 case 0x3e: /* MVN immed */
1710 case 0x3f: /* MVNS immed */
1715 /***************************************************************************\
1716 * Single Data Transfer Immediate RHS Instructions *
1717 \***************************************************************************/
1719 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
1721 if (StoreWord (state
, instr
, lhs
))
1722 LSBase
= lhs
- LSImmRHS
;
1725 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
1727 if (LoadWord (state
, instr
, lhs
))
1728 LSBase
= lhs
- LSImmRHS
;
1731 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
1732 UNDEF_LSRBaseEQDestWb
;
1735 temp
= lhs
- LSImmRHS
;
1736 state
->NtransSig
= LOW
;
1737 if (StoreWord (state
, instr
, lhs
))
1739 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1742 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
1743 UNDEF_LSRBaseEQDestWb
;
1746 state
->NtransSig
= LOW
;
1747 if (LoadWord (state
, instr
, lhs
))
1748 LSBase
= lhs
- LSImmRHS
;
1749 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1752 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
1754 if (StoreByte (state
, instr
, lhs
))
1755 LSBase
= lhs
- LSImmRHS
;
1758 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
1760 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1761 LSBase
= lhs
- LSImmRHS
;
1764 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
1765 UNDEF_LSRBaseEQDestWb
;
1768 state
->NtransSig
= LOW
;
1769 if (StoreByte (state
, instr
, lhs
))
1770 LSBase
= lhs
- LSImmRHS
;
1771 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1774 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
1775 UNDEF_LSRBaseEQDestWb
;
1778 state
->NtransSig
= LOW
;
1779 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1780 LSBase
= lhs
- LSImmRHS
;
1781 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1784 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
1786 if (StoreWord (state
, instr
, lhs
))
1787 LSBase
= lhs
+ LSImmRHS
;
1790 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
1792 if (LoadWord (state
, instr
, lhs
))
1793 LSBase
= lhs
+ LSImmRHS
;
1796 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
1797 UNDEF_LSRBaseEQDestWb
;
1800 state
->NtransSig
= LOW
;
1801 if (StoreWord (state
, instr
, lhs
))
1802 LSBase
= lhs
+ LSImmRHS
;
1803 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1806 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
1807 UNDEF_LSRBaseEQDestWb
;
1810 state
->NtransSig
= LOW
;
1811 if (LoadWord (state
, instr
, lhs
))
1812 LSBase
= lhs
+ LSImmRHS
;
1813 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1816 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
1818 if (StoreByte (state
, instr
, lhs
))
1819 LSBase
= lhs
+ LSImmRHS
;
1822 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
1824 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1825 LSBase
= lhs
+ LSImmRHS
;
1828 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
1829 UNDEF_LSRBaseEQDestWb
;
1832 state
->NtransSig
= LOW
;
1833 if (StoreByte (state
, instr
, lhs
))
1834 LSBase
= lhs
+ LSImmRHS
;
1835 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1838 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
1839 UNDEF_LSRBaseEQDestWb
;
1842 state
->NtransSig
= LOW
;
1843 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1844 LSBase
= lhs
+ LSImmRHS
;
1845 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1849 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
1850 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
1853 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
1854 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
1857 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
1858 UNDEF_LSRBaseEQDestWb
;
1860 temp
= LHS
- LSImmRHS
;
1861 if (StoreWord (state
, instr
, temp
))
1865 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
1866 UNDEF_LSRBaseEQDestWb
;
1868 temp
= LHS
- LSImmRHS
;
1869 if (LoadWord (state
, instr
, temp
))
1873 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
1874 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
1877 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
1878 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
1881 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
1882 UNDEF_LSRBaseEQDestWb
;
1884 temp
= LHS
- LSImmRHS
;
1885 if (StoreByte (state
, instr
, temp
))
1889 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
1890 UNDEF_LSRBaseEQDestWb
;
1892 temp
= LHS
- LSImmRHS
;
1893 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
1897 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
1898 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
1901 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
1902 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
1905 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
1906 UNDEF_LSRBaseEQDestWb
;
1908 temp
= LHS
+ LSImmRHS
;
1909 if (StoreWord (state
, instr
, temp
))
1913 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
1914 UNDEF_LSRBaseEQDestWb
;
1916 temp
= LHS
+ LSImmRHS
;
1917 if (LoadWord (state
, instr
, temp
))
1921 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
1922 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
1925 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
1926 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
1929 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
1930 UNDEF_LSRBaseEQDestWb
;
1932 temp
= LHS
+ LSImmRHS
;
1933 if (StoreByte (state
, instr
, temp
))
1937 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
1938 UNDEF_LSRBaseEQDestWb
;
1940 temp
= LHS
+ LSImmRHS
;
1941 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
1945 /***************************************************************************\
1946 * Single Data Transfer Register RHS Instructions *
1947 \***************************************************************************/
1949 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
1952 ARMul_UndefInstr (state
, instr
);
1955 UNDEF_LSRBaseEQOffWb
;
1956 UNDEF_LSRBaseEQDestWb
;
1960 if (StoreWord (state
, instr
, lhs
))
1961 LSBase
= lhs
- LSRegRHS
;
1964 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
1967 ARMul_UndefInstr (state
, instr
);
1970 UNDEF_LSRBaseEQOffWb
;
1971 UNDEF_LSRBaseEQDestWb
;
1975 temp
= lhs
- LSRegRHS
;
1976 if (LoadWord (state
, instr
, lhs
))
1980 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
1983 ARMul_UndefInstr (state
, instr
);
1986 UNDEF_LSRBaseEQOffWb
;
1987 UNDEF_LSRBaseEQDestWb
;
1991 state
->NtransSig
= LOW
;
1992 if (StoreWord (state
, instr
, lhs
))
1993 LSBase
= lhs
- LSRegRHS
;
1994 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1997 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2000 ARMul_UndefInstr (state
, instr
);
2003 UNDEF_LSRBaseEQOffWb
;
2004 UNDEF_LSRBaseEQDestWb
;
2008 temp
= lhs
- LSRegRHS
;
2009 state
->NtransSig
= LOW
;
2010 if (LoadWord (state
, instr
, lhs
))
2012 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2015 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2018 ARMul_UndefInstr (state
, instr
);
2021 UNDEF_LSRBaseEQOffWb
;
2022 UNDEF_LSRBaseEQDestWb
;
2026 if (StoreByte (state
, instr
, lhs
))
2027 LSBase
= lhs
- LSRegRHS
;
2030 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2033 ARMul_UndefInstr (state
, instr
);
2036 UNDEF_LSRBaseEQOffWb
;
2037 UNDEF_LSRBaseEQDestWb
;
2041 temp
= lhs
- LSRegRHS
;
2042 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2046 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2049 ARMul_UndefInstr (state
, instr
);
2052 UNDEF_LSRBaseEQOffWb
;
2053 UNDEF_LSRBaseEQDestWb
;
2057 state
->NtransSig
= LOW
;
2058 if (StoreByte (state
, instr
, lhs
))
2059 LSBase
= lhs
- LSRegRHS
;
2060 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2063 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2066 ARMul_UndefInstr (state
, instr
);
2069 UNDEF_LSRBaseEQOffWb
;
2070 UNDEF_LSRBaseEQDestWb
;
2074 temp
= lhs
- LSRegRHS
;
2075 state
->NtransSig
= LOW
;
2076 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2078 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2081 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2084 ARMul_UndefInstr (state
, instr
);
2087 UNDEF_LSRBaseEQOffWb
;
2088 UNDEF_LSRBaseEQDestWb
;
2092 if (StoreWord (state
, instr
, lhs
))
2093 LSBase
= lhs
+ LSRegRHS
;
2096 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2099 ARMul_UndefInstr (state
, instr
);
2102 UNDEF_LSRBaseEQOffWb
;
2103 UNDEF_LSRBaseEQDestWb
;
2107 temp
= lhs
+ LSRegRHS
;
2108 if (LoadWord (state
, instr
, lhs
))
2112 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2115 ARMul_UndefInstr (state
, instr
);
2118 UNDEF_LSRBaseEQOffWb
;
2119 UNDEF_LSRBaseEQDestWb
;
2123 state
->NtransSig
= LOW
;
2124 if (StoreWord (state
, instr
, lhs
))
2125 LSBase
= lhs
+ LSRegRHS
;
2126 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2129 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2132 ARMul_UndefInstr (state
, instr
);
2135 UNDEF_LSRBaseEQOffWb
;
2136 UNDEF_LSRBaseEQDestWb
;
2140 temp
= lhs
+ LSRegRHS
;
2141 state
->NtransSig
= LOW
;
2142 if (LoadWord (state
, instr
, lhs
))
2144 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2147 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2150 ARMul_UndefInstr (state
, instr
);
2153 UNDEF_LSRBaseEQOffWb
;
2154 UNDEF_LSRBaseEQDestWb
;
2158 if (StoreByte (state
, instr
, lhs
))
2159 LSBase
= lhs
+ LSRegRHS
;
2162 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2165 ARMul_UndefInstr (state
, instr
);
2168 UNDEF_LSRBaseEQOffWb
;
2169 UNDEF_LSRBaseEQDestWb
;
2173 temp
= lhs
+ LSRegRHS
;
2174 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2178 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2181 ARMul_UndefInstr (state
, instr
);
2184 UNDEF_LSRBaseEQOffWb
;
2185 UNDEF_LSRBaseEQDestWb
;
2189 state
->NtransSig
= LOW
;
2190 if (StoreByte (state
, instr
, lhs
))
2191 LSBase
= lhs
+ LSRegRHS
;
2192 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2195 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2198 ARMul_UndefInstr (state
, instr
);
2201 UNDEF_LSRBaseEQOffWb
;
2202 UNDEF_LSRBaseEQDestWb
;
2206 temp
= lhs
+ LSRegRHS
;
2207 state
->NtransSig
= LOW
;
2208 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2210 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2214 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2217 ARMul_UndefInstr (state
, instr
);
2220 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2223 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2226 ARMul_UndefInstr (state
, instr
);
2229 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2232 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2235 ARMul_UndefInstr (state
, instr
);
2238 UNDEF_LSRBaseEQOffWb
;
2239 UNDEF_LSRBaseEQDestWb
;
2242 temp
= LHS
- LSRegRHS
;
2243 if (StoreWord (state
, instr
, temp
))
2247 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2250 ARMul_UndefInstr (state
, instr
);
2253 UNDEF_LSRBaseEQOffWb
;
2254 UNDEF_LSRBaseEQDestWb
;
2257 temp
= LHS
- LSRegRHS
;
2258 if (LoadWord (state
, instr
, temp
))
2262 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2265 ARMul_UndefInstr (state
, instr
);
2268 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2271 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2274 ARMul_UndefInstr (state
, instr
);
2277 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2280 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2283 ARMul_UndefInstr (state
, instr
);
2286 UNDEF_LSRBaseEQOffWb
;
2287 UNDEF_LSRBaseEQDestWb
;
2290 temp
= LHS
- LSRegRHS
;
2291 if (StoreByte (state
, instr
, temp
))
2295 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2298 ARMul_UndefInstr (state
, instr
);
2301 UNDEF_LSRBaseEQOffWb
;
2302 UNDEF_LSRBaseEQDestWb
;
2305 temp
= LHS
- LSRegRHS
;
2306 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2310 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2313 ARMul_UndefInstr (state
, instr
);
2316 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2319 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2322 ARMul_UndefInstr (state
, instr
);
2325 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2328 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2331 ARMul_UndefInstr (state
, instr
);
2334 UNDEF_LSRBaseEQOffWb
;
2335 UNDEF_LSRBaseEQDestWb
;
2338 temp
= LHS
+ LSRegRHS
;
2339 if (StoreWord (state
, instr
, temp
))
2343 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2346 ARMul_UndefInstr (state
, instr
);
2349 UNDEF_LSRBaseEQOffWb
;
2350 UNDEF_LSRBaseEQDestWb
;
2353 temp
= LHS
+ LSRegRHS
;
2354 if (LoadWord (state
, instr
, temp
))
2358 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2361 ARMul_UndefInstr (state
, instr
);
2364 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2367 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2370 ARMul_UndefInstr (state
, instr
);
2373 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2376 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2379 ARMul_UndefInstr (state
, instr
);
2382 UNDEF_LSRBaseEQOffWb
;
2383 UNDEF_LSRBaseEQDestWb
;
2386 temp
= LHS
+ LSRegRHS
;
2387 if (StoreByte (state
, instr
, temp
))
2391 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2394 /* Check for the special breakpoint opcode.
2395 This value should correspond to the value defined
2396 as ARM_BE_BREAKPOINT in gdb/arm-tdep.c. */
2397 if (BITS (0, 19) == 0xfdefe)
2399 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2400 ARMul_Abort (state
, ARMul_SWIV
);
2403 ARMul_UndefInstr (state
, instr
);
2406 UNDEF_LSRBaseEQOffWb
;
2407 UNDEF_LSRBaseEQDestWb
;
2410 temp
= LHS
+ LSRegRHS
;
2411 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2415 /***************************************************************************\
2416 * Multiple Data Transfer Instructions *
2417 \***************************************************************************/
2419 case 0x80: /* Store, No WriteBack, Post Dec */
2420 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2423 case 0x81: /* Load, No WriteBack, Post Dec */
2424 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2427 case 0x82: /* Store, WriteBack, Post Dec */
2428 temp
= LSBase
- LSMNumRegs
;
2429 STOREMULT (instr
, temp
+ 4L, temp
);
2432 case 0x83: /* Load, WriteBack, Post Dec */
2433 temp
= LSBase
- LSMNumRegs
;
2434 LOADMULT (instr
, temp
+ 4L, temp
);
2437 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2438 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2441 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2442 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2445 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2446 temp
= LSBase
- LSMNumRegs
;
2447 STORESMULT (instr
, temp
+ 4L, temp
);
2450 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2451 temp
= LSBase
- LSMNumRegs
;
2452 LOADSMULT (instr
, temp
+ 4L, temp
);
2456 case 0x88: /* Store, No WriteBack, Post Inc */
2457 STOREMULT (instr
, LSBase
, 0L);
2460 case 0x89: /* Load, No WriteBack, Post Inc */
2461 LOADMULT (instr
, LSBase
, 0L);
2464 case 0x8a: /* Store, WriteBack, Post Inc */
2466 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
2469 case 0x8b: /* Load, WriteBack, Post Inc */
2471 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
2474 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2475 STORESMULT (instr
, LSBase
, 0L);
2478 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2479 LOADSMULT (instr
, LSBase
, 0L);
2482 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2484 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
2487 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2489 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
2493 case 0x90: /* Store, No WriteBack, Pre Dec */
2494 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2497 case 0x91: /* Load, No WriteBack, Pre Dec */
2498 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2501 case 0x92: /* Store, WriteBack, Pre Dec */
2502 temp
= LSBase
- LSMNumRegs
;
2503 STOREMULT (instr
, temp
, temp
);
2506 case 0x93: /* Load, WriteBack, Pre Dec */
2507 temp
= LSBase
- LSMNumRegs
;
2508 LOADMULT (instr
, temp
, temp
);
2511 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2512 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2515 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2516 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2519 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
2520 temp
= LSBase
- LSMNumRegs
;
2521 STORESMULT (instr
, temp
, temp
);
2524 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
2525 temp
= LSBase
- LSMNumRegs
;
2526 LOADSMULT (instr
, temp
, temp
);
2530 case 0x98: /* Store, No WriteBack, Pre Inc */
2531 STOREMULT (instr
, LSBase
+ 4L, 0L);
2534 case 0x99: /* Load, No WriteBack, Pre Inc */
2535 LOADMULT (instr
, LSBase
+ 4L, 0L);
2538 case 0x9a: /* Store, WriteBack, Pre Inc */
2540 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2543 case 0x9b: /* Load, WriteBack, Pre Inc */
2545 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2548 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
2549 STORESMULT (instr
, LSBase
+ 4L, 0L);
2552 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
2553 LOADSMULT (instr
, LSBase
+ 4L, 0L);
2556 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
2558 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2561 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
2563 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2566 /***************************************************************************\
2568 \***************************************************************************/
2578 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2582 /***************************************************************************\
2584 \***************************************************************************/
2594 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2598 /***************************************************************************\
2599 * Branch and Link forward *
2600 \***************************************************************************/
2611 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
2613 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2615 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2619 /***************************************************************************\
2620 * Branch and Link backward *
2621 \***************************************************************************/
2632 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
2634 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2636 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2640 /***************************************************************************\
2641 * Co-Processor Data Transfers *
2642 \***************************************************************************/
2645 case 0xc0: /* Store , No WriteBack , Post Dec */
2646 ARMul_STC (state
, instr
, LHS
);
2650 case 0xc1: /* Load , No WriteBack , Post Dec */
2651 ARMul_LDC (state
, instr
, LHS
);
2655 case 0xc6: /* Store , WriteBack , Post Dec */
2657 state
->Base
= lhs
- LSCOff
;
2658 ARMul_STC (state
, instr
, lhs
);
2662 case 0xc7: /* Load , WriteBack , Post Dec */
2664 state
->Base
= lhs
- LSCOff
;
2665 ARMul_LDC (state
, instr
, lhs
);
2669 case 0xcc: /* Store , No WriteBack , Post Inc */
2670 ARMul_STC (state
, instr
, LHS
);
2674 case 0xcd: /* Load , No WriteBack , Post Inc */
2675 ARMul_LDC (state
, instr
, LHS
);
2679 case 0xce: /* Store , WriteBack , Post Inc */
2681 state
->Base
= lhs
+ LSCOff
;
2682 ARMul_STC (state
, instr
, LHS
);
2686 case 0xcf: /* Load , WriteBack , Post Inc */
2688 state
->Base
= lhs
+ LSCOff
;
2689 ARMul_LDC (state
, instr
, LHS
);
2694 case 0xd4: /* Store , No WriteBack , Pre Dec */
2695 ARMul_STC (state
, instr
, LHS
- LSCOff
);
2699 case 0xd5: /* Load , No WriteBack , Pre Dec */
2700 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
2704 case 0xd6: /* Store , WriteBack , Pre Dec */
2707 ARMul_STC (state
, instr
, lhs
);
2711 case 0xd7: /* Load , WriteBack , Pre Dec */
2714 ARMul_LDC (state
, instr
, lhs
);
2718 case 0xdc: /* Store , No WriteBack , Pre Inc */
2719 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
2723 case 0xdd: /* Load , No WriteBack , Pre Inc */
2724 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
2728 case 0xde: /* Store , WriteBack , Pre Inc */
2731 ARMul_STC (state
, instr
, lhs
);
2735 case 0xdf: /* Load , WriteBack , Pre Inc */
2738 ARMul_LDC (state
, instr
, lhs
);
2741 /***************************************************************************\
2742 * Co-Processor Register Transfers (MCR) and Data Ops *
2743 \***************************************************************************/
2759 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
2761 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
2762 ((state
->Reg
[15] + isize
) & R15PCBITS
));
2766 ARMul_MCR (state
, instr
, DEST
);
2768 else /* CDP Part 1 */
2769 ARMul_CDP (state
, instr
);
2772 /***************************************************************************\
2773 * Co-Processor Register Transfers (MRC) and Data Ops *
2774 \***************************************************************************/
2786 temp
= ARMul_MRC (state
, instr
);
2789 ASSIGNN ((temp
& NBIT
) != 0);
2790 ASSIGNZ ((temp
& ZBIT
) != 0);
2791 ASSIGNC ((temp
& CBIT
) != 0);
2792 ASSIGNV ((temp
& VBIT
) != 0);
2797 else /* CDP Part 2 */
2798 ARMul_CDP (state
, instr
);
2801 /***************************************************************************\
2803 \***************************************************************************/
2821 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
2822 { /* a prefetch abort */
2823 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
2827 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
2829 ARMul_Abort (state
, ARMul_SWIV
);
2832 } /* 256 way main switch */
2839 #ifdef NEED_UI_LOOP_HOOK
2840 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
2842 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
2845 #endif /* NEED_UI_LOOP_HOOK */
2847 if (state
->Emulate
== ONCE
)
2848 state
->Emulate
= STOP
;
2849 /* If we have changed mode, allow the PC to advance before stopping. */
2850 else if (state
->Emulate
== CHANGEMODE
)
2852 else if (state
->Emulate
!= RUN
)
2855 while (!stop_simulator
); /* do loop */
2857 state
->decoded
= decoded
;
2858 state
->loaded
= loaded
;
2862 } /* Emulate 26/32 in instruction based mode */
2865 /***************************************************************************\
2866 * This routine evaluates most Data Processing register RHS's with the S *
2867 * bit clear. It is intended to be called from the macro DPRegRHS, which *
2868 * filters the common case of an unshifted register with in line code *
2869 \***************************************************************************/
2872 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
2874 ARMword shamt
, base
;
2878 { /* shift amount in a register */
2883 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2886 base
= state
->Reg
[base
];
2887 ARMul_Icycles (state
, 1, 0L);
2888 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
2889 switch ((int) BITS (5, 6))
2894 else if (shamt
>= 32)
2897 return (base
<< shamt
);
2901 else if (shamt
>= 32)
2904 return (base
>> shamt
);
2908 else if (shamt
>= 32)
2909 return ((ARMword
) ((long int) base
>> 31L));
2911 return ((ARMword
) ((long int) base
>> (int) shamt
));
2917 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
2921 { /* shift amount is a constant */
2924 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2927 base
= state
->Reg
[base
];
2928 shamt
= BITS (7, 11);
2929 switch ((int) BITS (5, 6))
2932 return (base
<< shamt
);
2937 return (base
>> shamt
);
2940 return ((ARMword
) ((long int) base
>> 31L));
2942 return ((ARMword
) ((long int) base
>> (int) shamt
));
2944 if (shamt
== 0) /* its an RRX */
2945 return ((base
>> 1) | (CFLAG
<< 31));
2947 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
2950 return (0); /* just to shut up lint */
2953 /***************************************************************************\
2954 * This routine evaluates most Logical Data Processing register RHS's *
2955 * with the S bit set. It is intended to be called from the macro *
2956 * DPSRegRHS, which filters the common case of an unshifted register *
2957 * with in line code *
2958 \***************************************************************************/
2961 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
2963 ARMword shamt
, base
;
2967 { /* shift amount in a register */
2972 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2975 base
= state
->Reg
[base
];
2976 ARMul_Icycles (state
, 1, 0L);
2977 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
2978 switch ((int) BITS (5, 6))
2983 else if (shamt
== 32)
2988 else if (shamt
> 32)
2995 ASSIGNC ((base
>> (32 - shamt
)) & 1);
2996 return (base
<< shamt
);
3001 else if (shamt
== 32)
3003 ASSIGNC (base
>> 31);
3006 else if (shamt
> 32)
3013 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3014 return (base
>> shamt
);
3019 else if (shamt
>= 32)
3021 ASSIGNC (base
>> 31L);
3022 return ((ARMword
) ((long int) base
>> 31L));
3026 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3027 return ((ARMword
) ((long int) base
>> (int) shamt
));
3035 ASSIGNC (base
>> 31);
3040 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3041 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3046 { /* shift amount is a constant */
3049 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3052 base
= state
->Reg
[base
];
3053 shamt
= BITS (7, 11);
3054 switch ((int) BITS (5, 6))
3057 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3058 return (base
<< shamt
);
3062 ASSIGNC (base
>> 31);
3067 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3068 return (base
>> shamt
);
3073 ASSIGNC (base
>> 31L);
3074 return ((ARMword
) ((long int) base
>> 31L));
3078 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3079 return ((ARMword
) ((long int) base
>> (int) shamt
));
3086 return ((base
>> 1) | (shamt
<< 31));
3090 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3091 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3095 return (0); /* just to shut up lint */
3098 /***************************************************************************\
3099 * This routine handles writes to register 15 when the S bit is not set. *
3100 \***************************************************************************/
3103 WriteR15 (ARMul_State
* state
, ARMword src
)
3105 /* The ARM documentation states that the two least significant bits
3106 are discarded when setting PC, except in the cases handled by
3107 WriteR15Branch() below. It's probably an oversight: in THUMB
3108 mode, the second least significant bit should probably not be
3117 state
->Reg
[15] = src
& PCBITS
;
3119 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
3120 ARMul_R15Altered (state
);
3125 /***************************************************************************\
3126 * This routine handles writes to register 15 when the S bit is set. *
3127 \***************************************************************************/
3130 WriteSR15 (ARMul_State
* state
, ARMword src
)
3133 if (state
->Bank
> 0)
3135 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3136 ARMul_CPSRAltered (state
);
3144 state
->Reg
[15] = src
& PCBITS
;
3148 abort (); /* ARMul_R15Altered would have to support it. */
3152 if (state
->Bank
== USERBANK
)
3153 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3155 state
->Reg
[15] = src
;
3156 ARMul_R15Altered (state
);
3161 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3162 will switch to Thumb mode if the least significant bit is set. */
3165 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3171 state
->Reg
[15] = src
& 0xfffffffe;
3176 state
->Reg
[15] = src
& 0xfffffffc;
3180 WriteR15 (state
, src
);
3184 /***************************************************************************\
3185 * This routine evaluates most Load and Store register RHS's. It is *
3186 * intended to be called from the macro LSRegRHS, which filters the *
3187 * common case of an unshifted register with in line code *
3188 \***************************************************************************/
3191 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3193 ARMword shamt
, base
;
3198 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3201 base
= state
->Reg
[base
];
3203 shamt
= BITS (7, 11);
3204 switch ((int) BITS (5, 6))
3207 return (base
<< shamt
);
3212 return (base
>> shamt
);
3215 return ((ARMword
) ((long int) base
>> 31L));
3217 return ((ARMword
) ((long int) base
>> (int) shamt
));
3219 if (shamt
== 0) /* its an RRX */
3220 return ((base
>> 1) | (CFLAG
<< 31));
3222 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3224 return (0); /* just to shut up lint */
3227 /***************************************************************************\
3228 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3229 \***************************************************************************/
3232 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3238 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3240 return state
->Reg
[RHSReg
];
3243 /* else immediate */
3244 return BITS (0, 3) | (BITS (8, 11) << 4);
3247 /***************************************************************************\
3248 * This function does the work of loading a word for a LDR instruction. *
3249 \***************************************************************************/
3252 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3258 if (ADDREXCEPT (address
))
3260 INTERNALABORT (address
);
3263 dest
= ARMul_LoadWordN (state
, address
);
3267 return (state
->lateabtSig
);
3270 dest
= ARMul_Align (state
, address
, dest
);
3272 ARMul_Icycles (state
, 1, 0L);
3274 return (DESTReg
!= LHSReg
);
3278 /***************************************************************************\
3279 * This function does the work of loading a halfword. *
3280 \***************************************************************************/
3283 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3290 if (ADDREXCEPT (address
))
3292 INTERNALABORT (address
);
3295 dest
= ARMul_LoadHalfWord (state
, address
);
3299 return (state
->lateabtSig
);
3304 if (dest
& 1 << (16 - 1))
3305 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3308 ARMul_Icycles (state
, 1, 0L);
3309 return (DESTReg
!= LHSReg
);
3314 /***************************************************************************\
3315 * This function does the work of loading a byte for a LDRB instruction. *
3316 \***************************************************************************/
3319 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3325 if (ADDREXCEPT (address
))
3327 INTERNALABORT (address
);
3330 dest
= ARMul_LoadByte (state
, address
);
3334 return (state
->lateabtSig
);
3339 if (dest
& 1 << (8 - 1))
3340 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3343 ARMul_Icycles (state
, 1, 0L);
3344 return (DESTReg
!= LHSReg
);
3347 /***************************************************************************\
3348 * This function does the work of storing a word from a STR instruction. *
3349 \***************************************************************************/
3352 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3357 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3360 ARMul_StoreWordN (state
, address
, DEST
);
3362 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3364 INTERNALABORT (address
);
3365 (void) ARMul_LoadWordN (state
, address
);
3368 ARMul_StoreWordN (state
, address
, DEST
);
3373 return (state
->lateabtSig
);
3379 /***************************************************************************\
3380 * This function does the work of storing a byte for a STRH instruction. *
3381 \***************************************************************************/
3384 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3390 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3394 ARMul_StoreHalfWord (state
, address
, DEST
);
3396 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3398 INTERNALABORT (address
);
3399 (void) ARMul_LoadHalfWord (state
, address
);
3402 ARMul_StoreHalfWord (state
, address
, DEST
);
3408 return (state
->lateabtSig
);
3416 /***************************************************************************\
3417 * This function does the work of storing a byte for a STRB instruction. *
3418 \***************************************************************************/
3421 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
3426 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3429 ARMul_StoreByte (state
, address
, DEST
);
3431 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3433 INTERNALABORT (address
);
3434 (void) ARMul_LoadByte (state
, address
);
3437 ARMul_StoreByte (state
, address
, DEST
);
3442 return (state
->lateabtSig
);
3448 /***************************************************************************\
3449 * This function does the work of loading the registers listed in an LDM *
3450 * instruction, when the S bit is clear. The code here is always increment *
3451 * after, it's up to the caller to get the input address correct and to *
3452 * handle base register modification. *
3453 \***************************************************************************/
3456 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
3462 UNDEF_LSMBaseInListWb
;
3465 if (ADDREXCEPT (address
))
3467 INTERNALABORT (address
);
3470 if (BIT (21) && LHSReg
!= 15)
3473 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3474 dest
= ARMul_LoadWordN (state
, address
);
3475 if (!state
->abortSig
&& !state
->Aborted
)
3476 state
->Reg
[temp
++] = dest
;
3477 else if (!state
->Aborted
)
3478 state
->Aborted
= ARMul_DataAbortV
;
3480 for (; temp
< 16; temp
++) /* S cycles from here on */
3482 { /* load this register */
3484 dest
= ARMul_LoadWordS (state
, address
);
3485 if (!state
->abortSig
&& !state
->Aborted
)
3486 state
->Reg
[temp
] = dest
;
3487 else if (!state
->Aborted
)
3488 state
->Aborted
= ARMul_DataAbortV
;
3491 if (BIT (15) && !state
->Aborted
)
3492 { /* PC is in the reg list */
3493 WriteR15Branch(state
, PC
);
3496 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3500 if (BIT (21) && LHSReg
!= 15)
3506 /***************************************************************************\
3507 * This function does the work of loading the registers listed in an LDM *
3508 * instruction, when the S bit is set. The code here is always increment *
3509 * after, it's up to the caller to get the input address correct and to *
3510 * handle base register modification. *
3511 \***************************************************************************/
3514 LoadSMult (ARMul_State
* state
, ARMword instr
,
3515 ARMword address
, ARMword WBBase
)
3521 UNDEF_LSMBaseInListWb
;
3524 if (ADDREXCEPT (address
))
3526 INTERNALABORT (address
);
3530 if (!BIT (15) && state
->Bank
!= USERBANK
)
3532 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* temporary reg bank switch */
3533 UNDEF_LSMUserBankWb
;
3536 if (BIT (21) && LHSReg
!= 15)
3539 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3540 dest
= ARMul_LoadWordN (state
, address
);
3541 if (!state
->abortSig
)
3542 state
->Reg
[temp
++] = dest
;
3543 else if (!state
->Aborted
)
3544 state
->Aborted
= ARMul_DataAbortV
;
3546 for (; temp
< 16; temp
++) /* S cycles from here on */
3548 { /* load this register */
3550 dest
= ARMul_LoadWordS (state
, address
);
3551 if (!state
->abortSig
&& !state
->Aborted
)
3552 state
->Reg
[temp
] = dest
;
3553 else if (!state
->Aborted
)
3554 state
->Aborted
= ARMul_DataAbortV
;
3557 if (BIT (15) && !state
->Aborted
)
3558 { /* PC is in the reg list */
3560 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3562 state
->Cpsr
= GETSPSR (state
->Bank
);
3563 ARMul_CPSRAltered (state
);
3565 WriteR15 (state
, PC
);
3567 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
3568 { /* protect bits in user mode */
3569 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
3570 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
3571 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
3572 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
3575 ARMul_R15Altered (state
);
3580 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3581 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3583 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3587 if (BIT (21) && LHSReg
!= 15)
3594 /***************************************************************************\
3595 * This function does the work of storing the registers listed in an STM *
3596 * instruction, when the S bit is clear. The code here is always increment *
3597 * after, it's up to the caller to get the input address correct and to *
3598 * handle base register modification. *
3599 \***************************************************************************/
3602 StoreMult (ARMul_State
* state
, ARMword instr
,
3603 ARMword address
, ARMword WBBase
)
3609 UNDEF_LSMBaseInListWb
;
3612 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
3616 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3618 INTERNALABORT (address
);
3624 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3626 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3630 (void) ARMul_LoadWordN (state
, address
);
3631 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3633 { /* save this register */
3635 (void) ARMul_LoadWordS (state
, address
);
3637 if (BIT (21) && LHSReg
!= 15)
3643 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3645 if (state
->abortSig
&& !state
->Aborted
)
3646 state
->Aborted
= ARMul_DataAbortV
;
3648 if (BIT (21) && LHSReg
!= 15)
3651 for (; temp
< 16; temp
++) /* S cycles from here on */
3653 { /* save this register */
3655 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3656 if (state
->abortSig
&& !state
->Aborted
)
3657 state
->Aborted
= ARMul_DataAbortV
;
3665 /***************************************************************************\
3666 * This function does the work of storing the registers listed in an STM *
3667 * instruction when the S bit is set. The code here is always increment *
3668 * after, it's up to the caller to get the input address correct and to *
3669 * handle base register modification. *
3670 \***************************************************************************/
3673 StoreSMult (ARMul_State
* state
, ARMword instr
,
3674 ARMword address
, ARMword WBBase
)
3680 UNDEF_LSMBaseInListWb
;
3683 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3685 INTERNALABORT (address
);
3691 if (state
->Bank
!= USERBANK
)
3693 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* Force User Bank */
3694 UNDEF_LSMUserBankWb
;
3697 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3699 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3703 (void) ARMul_LoadWordN (state
, address
);
3704 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3706 { /* save this register */
3708 (void) ARMul_LoadWordS (state
, address
);
3710 if (BIT (21) && LHSReg
!= 15)
3716 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3718 if (state
->abortSig
&& !state
->Aborted
)
3719 state
->Aborted
= ARMul_DataAbortV
;
3721 if (BIT (21) && LHSReg
!= 15)
3724 for (; temp
< 16; temp
++) /* S cycles from here on */
3726 { /* save this register */
3728 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3729 if (state
->abortSig
&& !state
->Aborted
)
3730 state
->Aborted
= ARMul_DataAbortV
;
3733 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3734 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3742 /***************************************************************************\
3743 * This function does the work of adding two 32bit values together, and *
3744 * calculating if a carry has occurred. *
3745 \***************************************************************************/
3748 Add32 (ARMword a1
, ARMword a2
, int *carry
)
3750 ARMword result
= (a1
+ a2
);
3751 unsigned int uresult
= (unsigned int) result
;
3752 unsigned int ua1
= (unsigned int) a1
;
3754 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
3755 or (result > RdLo) then we have no carry: */
3756 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
3764 /***************************************************************************\
3765 * This function does the work of multiplying two 32bit values to give a *
3767 \***************************************************************************/
3770 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3772 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
3773 ARMword RdHi
= 0, RdLo
= 0, Rm
;
3774 int scount
; /* cycle count */
3776 nRdHi
= BITS (16, 19);
3777 nRdLo
= BITS (12, 15);
3781 /* Needed to calculate the cycle count: */
3782 Rm
= state
->Reg
[nRm
];
3784 /* Check for illegal operand combinations first: */
3788 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
3790 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
3792 ARMword Rs
= state
->Reg
[nRs
];
3797 /* Compute sign of result and adjust operands if necessary. */
3799 sign
= (Rm
^ Rs
) & 0x80000000;
3801 if (((signed long) Rm
) < 0)
3804 if (((signed long) Rs
) < 0)
3808 /* We can split the 32x32 into four 16x16 operations. This ensures
3809 that we do not lose precision on 32bit only hosts: */
3810 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
3811 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3812 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
3813 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3815 /* We now need to add all of these results together, taking care
3816 to propogate the carries from the additions: */
3817 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
3819 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
3821 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
3825 /* Negate result if necessary. */
3829 if (RdLo
== 0xFFFFFFFF)
3838 state
->Reg
[nRdLo
] = RdLo
;
3839 state
->Reg
[nRdHi
] = RdHi
;
3840 } /* else undefined result */
3842 fprintf (stderr
, "MULTIPLY64 - INVALID ARGUMENTS\n");
3846 /* Ensure that both RdHi and RdLo are used to compute Z, but
3847 don't let RdLo's sign bit make it to N. */
3848 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
3851 /* The cycle count depends on whether the instruction is a signed or
3852 unsigned multiply, and what bits are clear in the multiplier: */
3853 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
3854 Rm
= ~Rm
; /* invert the bits to make the check against zero */
3856 if ((Rm
& 0xFFFFFF00) == 0)
3858 else if ((Rm
& 0xFFFF0000) == 0)
3860 else if ((Rm
& 0xFF000000) == 0)
3868 /***************************************************************************\
3869 * This function does the work of multiplying two 32bit values and adding *
3870 * a 64bit value to give a 64bit result. *
3871 \***************************************************************************/
3874 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3881 nRdHi
= BITS (16, 19);
3882 nRdLo
= BITS (12, 15);
3884 RdHi
= state
->Reg
[nRdHi
];
3885 RdLo
= state
->Reg
[nRdLo
];
3887 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
3889 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
3890 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
3892 state
->Reg
[nRdLo
] = RdLo
;
3893 state
->Reg
[nRdHi
] = RdHi
;
3897 /* Ensure that both RdHi and RdLo are used to compute Z, but
3898 don't let RdLo's sign bit make it to N. */
3899 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
3902 return scount
+ 1; /* extra cycle for addition */