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 */
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. */
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
)
3127 state
->Reg
[15] = src
& PCBITS
;
3128 if (state
->Bank
> 0)
3130 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3131 ARMul_CPSRAltered (state
);
3134 if (state
->Bank
== USERBANK
)
3135 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3137 state
->Reg
[15] = src
;
3138 ARMul_R15Altered (state
);
3143 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3144 will switch to Thumb mode if the least significant bit is set. */
3147 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3153 state
->Reg
[15] = src
& 0xfffffffe;
3158 state
->Reg
[15] = src
& 0xfffffffc;
3162 WriteR15 (state
, src
);
3166 /***************************************************************************\
3167 * This routine evaluates most Load and Store register RHS's. It is *
3168 * intended to be called from the macro LSRegRHS, which filters the *
3169 * common case of an unshifted register with in line code *
3170 \***************************************************************************/
3173 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3175 ARMword shamt
, base
;
3180 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3183 base
= state
->Reg
[base
];
3185 shamt
= BITS (7, 11);
3186 switch ((int) BITS (5, 6))
3189 return (base
<< shamt
);
3194 return (base
>> shamt
);
3197 return ((ARMword
) ((long int) base
>> 31L));
3199 return ((ARMword
) ((long int) base
>> (int) shamt
));
3201 if (shamt
== 0) /* its an RRX */
3202 return ((base
>> 1) | (CFLAG
<< 31));
3204 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3206 return (0); /* just to shut up lint */
3209 /***************************************************************************\
3210 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3211 \***************************************************************************/
3214 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3220 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3222 return state
->Reg
[RHSReg
];
3225 /* else immediate */
3226 return BITS (0, 3) | (BITS (8, 11) << 4);
3229 /***************************************************************************\
3230 * This function does the work of loading a word for a LDR instruction. *
3231 \***************************************************************************/
3234 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3240 if (ADDREXCEPT (address
))
3242 INTERNALABORT (address
);
3245 dest
= ARMul_LoadWordN (state
, address
);
3249 return (state
->lateabtSig
);
3252 dest
= ARMul_Align (state
, address
, dest
);
3254 ARMul_Icycles (state
, 1, 0L);
3256 return (DESTReg
!= LHSReg
);
3260 /***************************************************************************\
3261 * This function does the work of loading a halfword. *
3262 \***************************************************************************/
3265 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3272 if (ADDREXCEPT (address
))
3274 INTERNALABORT (address
);
3277 dest
= ARMul_LoadHalfWord (state
, address
);
3281 return (state
->lateabtSig
);
3286 if (dest
& 1 << (16 - 1))
3287 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3290 ARMul_Icycles (state
, 1, 0L);
3291 return (DESTReg
!= LHSReg
);
3296 /***************************************************************************\
3297 * This function does the work of loading a byte for a LDRB instruction. *
3298 \***************************************************************************/
3301 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3307 if (ADDREXCEPT (address
))
3309 INTERNALABORT (address
);
3312 dest
= ARMul_LoadByte (state
, address
);
3316 return (state
->lateabtSig
);
3321 if (dest
& 1 << (8 - 1))
3322 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3325 ARMul_Icycles (state
, 1, 0L);
3326 return (DESTReg
!= LHSReg
);
3329 /***************************************************************************\
3330 * This function does the work of storing a word from a STR instruction. *
3331 \***************************************************************************/
3334 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3339 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3342 ARMul_StoreWordN (state
, address
, DEST
);
3344 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3346 INTERNALABORT (address
);
3347 (void) ARMul_LoadWordN (state
, address
);
3350 ARMul_StoreWordN (state
, address
, DEST
);
3355 return (state
->lateabtSig
);
3361 /***************************************************************************\
3362 * This function does the work of storing a byte for a STRH instruction. *
3363 \***************************************************************************/
3366 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3372 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3376 ARMul_StoreHalfWord (state
, address
, DEST
);
3378 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3380 INTERNALABORT (address
);
3381 (void) ARMul_LoadHalfWord (state
, address
);
3384 ARMul_StoreHalfWord (state
, address
, DEST
);
3390 return (state
->lateabtSig
);
3398 /***************************************************************************\
3399 * This function does the work of storing a byte for a STRB instruction. *
3400 \***************************************************************************/
3403 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
3408 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3411 ARMul_StoreByte (state
, address
, DEST
);
3413 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3415 INTERNALABORT (address
);
3416 (void) ARMul_LoadByte (state
, address
);
3419 ARMul_StoreByte (state
, address
, DEST
);
3424 return (state
->lateabtSig
);
3430 /***************************************************************************\
3431 * This function does the work of loading the registers listed in an LDM *
3432 * instruction, when the S bit is clear. The code here is always increment *
3433 * after, it's up to the caller to get the input address correct and to *
3434 * handle base register modification. *
3435 \***************************************************************************/
3438 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
3444 UNDEF_LSMBaseInListWb
;
3447 if (ADDREXCEPT (address
))
3449 INTERNALABORT (address
);
3452 if (BIT (21) && LHSReg
!= 15)
3455 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3456 dest
= ARMul_LoadWordN (state
, address
);
3457 if (!state
->abortSig
&& !state
->Aborted
)
3458 state
->Reg
[temp
++] = dest
;
3459 else if (!state
->Aborted
)
3460 state
->Aborted
= ARMul_DataAbortV
;
3462 for (; temp
< 16; temp
++) /* S cycles from here on */
3464 { /* load this register */
3466 dest
= ARMul_LoadWordS (state
, address
);
3467 if (!state
->abortSig
&& !state
->Aborted
)
3468 state
->Reg
[temp
] = dest
;
3469 else if (!state
->Aborted
)
3470 state
->Aborted
= ARMul_DataAbortV
;
3473 if (BIT (15) && !state
->Aborted
)
3474 { /* PC is in the reg list */
3475 WriteR15Branch(state
, PC
);
3478 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3482 if (BIT (21) && LHSReg
!= 15)
3488 /***************************************************************************\
3489 * This function does the work of loading the registers listed in an LDM *
3490 * instruction, when the S bit is set. The code here is always increment *
3491 * after, it's up to the caller to get the input address correct and to *
3492 * handle base register modification. *
3493 \***************************************************************************/
3496 LoadSMult (ARMul_State
* state
, ARMword instr
,
3497 ARMword address
, ARMword WBBase
)
3503 UNDEF_LSMBaseInListWb
;
3506 if (ADDREXCEPT (address
))
3508 INTERNALABORT (address
);
3512 if (!BIT (15) && state
->Bank
!= USERBANK
)
3514 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* temporary reg bank switch */
3515 UNDEF_LSMUserBankWb
;
3518 if (BIT (21) && LHSReg
!= 15)
3521 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3522 dest
= ARMul_LoadWordN (state
, address
);
3523 if (!state
->abortSig
)
3524 state
->Reg
[temp
++] = dest
;
3525 else if (!state
->Aborted
)
3526 state
->Aborted
= ARMul_DataAbortV
;
3528 for (; temp
< 16; temp
++) /* S cycles from here on */
3530 { /* load this register */
3532 dest
= ARMul_LoadWordS (state
, address
);
3533 if (!state
->abortSig
&& !state
->Aborted
)
3534 state
->Reg
[temp
] = dest
;
3535 else if (!state
->Aborted
)
3536 state
->Aborted
= ARMul_DataAbortV
;
3539 if (BIT (15) && !state
->Aborted
)
3540 { /* PC is in the reg list */
3542 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3544 state
->Cpsr
= GETSPSR (state
->Bank
);
3545 ARMul_CPSRAltered (state
);
3547 WriteR15 (state
, PC
);
3549 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
3550 { /* protect bits in user mode */
3551 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
3552 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
3553 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
3554 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
3557 ARMul_R15Altered (state
);
3562 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3563 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3565 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3569 if (BIT (21) && LHSReg
!= 15)
3576 /***************************************************************************\
3577 * This function does the work of storing the registers listed in an STM *
3578 * instruction, when the S bit is clear. The code here is always increment *
3579 * after, it's up to the caller to get the input address correct and to *
3580 * handle base register modification. *
3581 \***************************************************************************/
3584 StoreMult (ARMul_State
* state
, ARMword instr
,
3585 ARMword address
, ARMword WBBase
)
3591 UNDEF_LSMBaseInListWb
;
3594 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
3598 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3600 INTERNALABORT (address
);
3606 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3608 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3612 (void) ARMul_LoadWordN (state
, address
);
3613 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3615 { /* save this register */
3617 (void) ARMul_LoadWordS (state
, address
);
3619 if (BIT (21) && LHSReg
!= 15)
3625 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3627 if (state
->abortSig
&& !state
->Aborted
)
3628 state
->Aborted
= ARMul_DataAbortV
;
3630 if (BIT (21) && LHSReg
!= 15)
3633 for (; temp
< 16; temp
++) /* S cycles from here on */
3635 { /* save this register */
3637 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3638 if (state
->abortSig
&& !state
->Aborted
)
3639 state
->Aborted
= ARMul_DataAbortV
;
3647 /***************************************************************************\
3648 * This function does the work of storing the registers listed in an STM *
3649 * instruction when the S bit is set. The code here is always increment *
3650 * after, it's up to the caller to get the input address correct and to *
3651 * handle base register modification. *
3652 \***************************************************************************/
3655 StoreSMult (ARMul_State
* state
, ARMword instr
,
3656 ARMword address
, ARMword WBBase
)
3662 UNDEF_LSMBaseInListWb
;
3665 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3667 INTERNALABORT (address
);
3673 if (state
->Bank
!= USERBANK
)
3675 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* Force User Bank */
3676 UNDEF_LSMUserBankWb
;
3679 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3681 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3685 (void) ARMul_LoadWordN (state
, address
);
3686 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3688 { /* save this register */
3690 (void) ARMul_LoadWordS (state
, address
);
3692 if (BIT (21) && LHSReg
!= 15)
3698 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3700 if (state
->abortSig
&& !state
->Aborted
)
3701 state
->Aborted
= ARMul_DataAbortV
;
3703 if (BIT (21) && LHSReg
!= 15)
3706 for (; temp
< 16; temp
++) /* S cycles from here on */
3708 { /* save this register */
3710 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3711 if (state
->abortSig
&& !state
->Aborted
)
3712 state
->Aborted
= ARMul_DataAbortV
;
3715 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3716 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3724 /***************************************************************************\
3725 * This function does the work of adding two 32bit values together, and *
3726 * calculating if a carry has occurred. *
3727 \***************************************************************************/
3730 Add32 (ARMword a1
, ARMword a2
, int *carry
)
3732 ARMword result
= (a1
+ a2
);
3733 unsigned int uresult
= (unsigned int) result
;
3734 unsigned int ua1
= (unsigned int) a1
;
3736 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
3737 or (result > RdLo) then we have no carry: */
3738 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
3746 /***************************************************************************\
3747 * This function does the work of multiplying two 32bit values to give a *
3749 \***************************************************************************/
3752 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3754 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
3755 ARMword RdHi
= 0, RdLo
= 0, Rm
;
3756 int scount
; /* cycle count */
3758 nRdHi
= BITS (16, 19);
3759 nRdLo
= BITS (12, 15);
3763 /* Needed to calculate the cycle count: */
3764 Rm
= state
->Reg
[nRm
];
3766 /* Check for illegal operand combinations first: */
3770 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
3772 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
3774 ARMword Rs
= state
->Reg
[nRs
];
3779 /* Compute sign of result and adjust operands if necessary. */
3781 sign
= (Rm
^ Rs
) & 0x80000000;
3783 if (((signed long) Rm
) < 0)
3786 if (((signed long) Rs
) < 0)
3790 /* We can split the 32x32 into four 16x16 operations. This ensures
3791 that we do not lose precision on 32bit only hosts: */
3792 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
3793 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3794 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
3795 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3797 /* We now need to add all of these results together, taking care
3798 to propogate the carries from the additions: */
3799 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
3801 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
3803 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
3807 /* Negate result if necessary. */
3811 if (RdLo
== 0xFFFFFFFF)
3820 state
->Reg
[nRdLo
] = RdLo
;
3821 state
->Reg
[nRdHi
] = RdHi
;
3822 } /* else undefined result */
3824 fprintf (stderr
, "MULTIPLY64 - INVALID ARGUMENTS\n");
3828 /* Ensure that both RdHi and RdLo are used to compute Z, but
3829 don't let RdLo's sign bit make it to N. */
3830 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
3833 /* The cycle count depends on whether the instruction is a signed or
3834 unsigned multiply, and what bits are clear in the multiplier: */
3835 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
3836 Rm
= ~Rm
; /* invert the bits to make the check against zero */
3838 if ((Rm
& 0xFFFFFF00) == 0)
3840 else if ((Rm
& 0xFFFF0000) == 0)
3842 else if ((Rm
& 0xFF000000) == 0)
3850 /***************************************************************************\
3851 * This function does the work of multiplying two 32bit values and adding *
3852 * a 64bit value to give a 64bit result. *
3853 \***************************************************************************/
3856 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3863 nRdHi
= BITS (16, 19);
3864 nRdLo
= BITS (12, 15);
3866 RdHi
= state
->Reg
[nRdHi
];
3867 RdLo
= state
->Reg
[nRdLo
];
3869 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
3871 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
3872 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
3874 state
->Reg
[nRdLo
] = RdLo
;
3875 state
->Reg
[nRdHi
] = RdHi
;
3879 /* Ensure that both RdHi and RdLo are used to compute Z, but
3880 don't let RdLo's sign bit make it to N. */
3881 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
3884 return scount
+ 1; /* extra cycle for addition */
This page took 0.171771 seconds and 4 git commands to generate.