426617d6bb3ac725c846fc55043391829595d627
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 ARMword
GetLSRegRHS (ARMul_State
* state
, ARMword instr
);
28 static ARMword
GetLS7RHS (ARMul_State
* state
, ARMword instr
);
29 static unsigned LoadWord (ARMul_State
* state
, ARMword instr
,
31 static unsigned LoadHalfWord (ARMul_State
* state
, ARMword instr
,
32 ARMword address
, int signextend
);
33 static unsigned LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
,
35 static unsigned StoreWord (ARMul_State
* state
, ARMword instr
,
37 static unsigned StoreHalfWord (ARMul_State
* state
, ARMword instr
,
39 static unsigned StoreByte (ARMul_State
* state
, ARMword instr
,
41 static void LoadMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
43 static void StoreMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
45 static void LoadSMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
47 static void StoreSMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
49 static unsigned Multiply64 (ARMul_State
* state
, ARMword instr
,
50 int signextend
, int scc
);
51 static unsigned MultiplyAdd64 (ARMul_State
* state
, ARMword instr
,
52 int signextend
, int scc
);
54 #define LUNSIGNED (0) /* unsigned operation */
55 #define LSIGNED (1) /* signed operation */
56 #define LDEFAULT (0) /* default : do nothing */
57 #define LSCC (1) /* set condition codes on result */
59 #ifdef NEED_UI_LOOP_HOOK
60 /* How often to run the ui_loop update, when in use */
61 #define UI_LOOP_POLL_INTERVAL 0x32000
63 /* Counter for the ui_loop_hook update */
64 static long ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
66 /* Actual hook to call to run through gdb's gui event loop */
67 extern int (*ui_loop_hook
) (int);
68 #endif /* NEED_UI_LOOP_HOOK */
70 extern int stop_simulator
;
72 /***************************************************************************\
73 * short-hand macros for LDR/STR *
74 \***************************************************************************/
76 /* store post decrement writeback */
79 if (StoreHalfWord(state, instr, lhs)) \
80 LSBase = lhs - GetLS7RHS(state, instr) ;
82 /* store post increment writeback */
85 if (StoreHalfWord(state, instr, lhs)) \
86 LSBase = lhs + GetLS7RHS(state, instr) ;
88 /* store pre decrement */
90 (void)StoreHalfWord(state, instr, LHS - GetLS7RHS(state, instr)) ;
92 /* store pre decrement writeback */
93 #define SHPREDOWNWB() \
94 temp = LHS - GetLS7RHS(state, instr) ; \
95 if (StoreHalfWord(state, instr, temp)) \
98 /* store pre increment */
100 (void)StoreHalfWord(state, instr, LHS + GetLS7RHS(state, instr)) ;
102 /* store pre increment writeback */
103 #define SHPREUPWB() \
104 temp = LHS + GetLS7RHS(state, instr) ; \
105 if (StoreHalfWord(state, instr, temp)) \
108 /* load post decrement writeback */
109 #define LHPOSTDOWN() \
113 switch (BITS(5,6)) { \
115 if (LoadHalfWord(state,instr,lhs,LUNSIGNED)) \
116 LSBase = lhs - GetLS7RHS(state,instr) ; \
119 if (LoadByte(state,instr,lhs,LSIGNED)) \
120 LSBase = lhs - GetLS7RHS(state,instr) ; \
123 if (LoadHalfWord(state,instr,lhs,LSIGNED)) \
124 LSBase = lhs - GetLS7RHS(state,instr) ; \
126 case 0: /* SWP handled elsewhere */ \
135 /* load post increment writeback */
140 switch (BITS(5,6)) { \
142 if (LoadHalfWord(state,instr,lhs,LUNSIGNED)) \
143 LSBase = lhs + GetLS7RHS(state,instr) ; \
146 if (LoadByte(state,instr,lhs,LSIGNED)) \
147 LSBase = lhs + GetLS7RHS(state,instr) ; \
150 if (LoadHalfWord(state,instr,lhs,LSIGNED)) \
151 LSBase = lhs + GetLS7RHS(state,instr) ; \
153 case 0: /* SWP handled elsewhere */ \
162 /* load pre decrement */
163 #define LHPREDOWN() \
166 temp = LHS - GetLS7RHS(state,instr) ; \
167 switch (BITS(5,6)) { \
169 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
172 (void)LoadByte(state,instr,temp,LSIGNED) ; \
175 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
177 case 0: /* SWP handled elsewhere */ \
186 /* load pre decrement writeback */
187 #define LHPREDOWNWB() \
190 temp = LHS - GetLS7RHS(state, instr) ; \
191 switch (BITS(5,6)) { \
193 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
197 if (LoadByte(state,instr,temp,LSIGNED)) \
201 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
204 case 0: /* SWP handled elsewhere */ \
213 /* load pre increment */
217 temp = LHS + GetLS7RHS(state,instr) ; \
218 switch (BITS(5,6)) { \
220 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
223 (void)LoadByte(state,instr,temp,LSIGNED) ; \
226 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
228 case 0: /* SWP handled elsewhere */ \
237 /* load pre increment writeback */
238 #define LHPREUPWB() \
241 temp = LHS + GetLS7RHS(state, instr) ; \
242 switch (BITS(5,6)) { \
244 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
248 if (LoadByte(state,instr,temp,LSIGNED)) \
252 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
255 case 0: /* SWP handled elsewhere */ \
264 /***************************************************************************\
265 * EMULATION of ARM6 *
266 \***************************************************************************/
268 /* The PC pipeline value depends on whether ARM or Thumb instructions
269 are being executed: */
274 ARMul_Emulate32 (register ARMul_State
* state
)
278 ARMul_Emulate26 (register ARMul_State
* state
)
281 register ARMword instr
, /* the current instruction */
282 dest
= 0, /* almost the DestBus */
283 temp
, /* ubiquitous third hand */
284 pc
= 0; /* the address of the current instruction */
285 ARMword lhs
, rhs
; /* almost the ABus and BBus */
286 ARMword decoded
= 0, loaded
= 0; /* instruction pipeline */
288 /***************************************************************************\
289 * Execute the next instruction *
290 \***************************************************************************/
292 if (state
->NextInstr
< PRIMEPIPE
)
294 decoded
= state
->decoded
;
295 loaded
= state
->loaded
;
300 { /* just keep going */
309 switch (state
->NextInstr
)
312 state
->Reg
[15] += isize
; /* Advance the pipeline, and an S cycle */
316 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
320 state
->Reg
[15] += isize
; /* Advance the pipeline, and an N cycle */
324 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
329 pc
+= isize
; /* Program counter advanced, and an S cycle */
332 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
337 pc
+= isize
; /* Program counter advanced, and an N cycle */
340 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
344 case RESUME
: /* The program counter has been changed */
349 state
->Reg
[15] = pc
+ (isize
* 2);
351 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
352 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
353 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
357 default: /* The program counter has been changed */
362 state
->Reg
[15] = pc
+ (isize
* 2);
364 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
365 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
366 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
371 ARMul_EnvokeEvent (state
);
374 /* Enable this for a helpful bit of debugging when tracing is needed. */
375 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
380 if (state
->Exception
)
381 { /* Any exceptions */
382 if (state
->NresetSig
== LOW
)
384 ARMul_Abort (state
, ARMul_ResetV
);
387 else if (!state
->NfiqSig
&& !FFLAG
)
389 ARMul_Abort (state
, ARMul_FIQV
);
392 else if (!state
->NirqSig
&& !IFLAG
)
394 ARMul_Abort (state
, ARMul_IRQV
);
399 if (state
->CallDebug
> 0)
401 instr
= ARMul_Debug (state
, pc
, instr
);
402 if (state
->Emulate
< ONCE
)
404 state
->NextInstr
= RESUME
;
409 fprintf (stderr
, "At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
411 (void) fgetc (stdin
);
414 else if (state
->Emulate
< ONCE
)
416 state
->NextInstr
= RESUME
;
423 /* Provide Thumb instruction decoding. If the processor is in Thumb
424 mode, then we can simply decode the Thumb instruction, and map it
425 to the corresponding ARM instruction (by directly loading the
426 instr variable, and letting the normal ARM simulator
427 execute). There are some caveats to ensure that the correct
428 pipelined PC value is used when executing Thumb code, and also for
429 dealing with the BL instruction. */
431 { /* check if in Thumb mode */
433 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
436 ARMul_UndefInstr (state
, instr
); /* This is a Thumb instruction */
439 case t_branch
: /* already processed */
442 case t_decoded
: /* ARM instruction available */
443 instr
= new; /* so continue instruction decoding */
449 /***************************************************************************\
450 * Check the condition codes *
451 \***************************************************************************/
452 if ((temp
= TOPBITS (28)) == AL
)
453 goto mainswitch
; /* vile deed in the need for speed */
455 switch ((int) TOPBITS (28))
456 { /* check the condition code */
488 temp
= (CFLAG
&& !ZFLAG
);
491 temp
= (!CFLAG
|| ZFLAG
);
494 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
497 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
500 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
503 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
507 /***************************************************************************\
508 * Actual execution of instructions begins here *
509 \***************************************************************************/
512 { /* if the condition codes don't match, stop here */
516 switch ((int) BITS (20, 27))
519 /***************************************************************************\
520 * Data Processing Register RHS Instructions *
521 \***************************************************************************/
523 case 0x00: /* AND reg and MUL */
525 if (BITS (4, 11) == 0xB)
527 /* STRH register offset, no write-back, down, post indexed */
531 /* TODO: CHECK: should 0xD and 0xF generate undefined intruction aborts? */
533 if (BITS (4, 7) == 9)
535 rhs
= state
->Reg
[MULRHSReg
];
536 if (MULLHSReg
== MULDESTReg
)
539 state
->Reg
[MULDESTReg
] = 0;
541 else if (MULDESTReg
!= 15)
542 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
547 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
548 if (rhs
& (1L << dest
))
549 temp
= dest
; /* mult takes this many/2 I cycles */
550 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
560 case 0x01: /* ANDS reg and MULS */
562 if ((BITS (4, 11) & 0xF9) == 0x9)
564 /* LDR register offset, no write-back, down, post indexed */
566 /* fall through to rest of decoding */
569 if (BITS (4, 7) == 9)
571 rhs
= state
->Reg
[MULRHSReg
];
572 if (MULLHSReg
== MULDESTReg
)
575 state
->Reg
[MULDESTReg
] = 0;
579 else if (MULDESTReg
!= 15)
581 dest
= state
->Reg
[MULLHSReg
] * rhs
;
582 ARMul_NegZero (state
, dest
);
583 state
->Reg
[MULDESTReg
] = dest
;
589 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
590 if (rhs
& (1L << dest
))
591 temp
= dest
; /* mult takes this many/2 I cycles */
592 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
602 case 0x02: /* EOR reg and MLA */
604 if (BITS (4, 11) == 0xB)
606 /* STRH register offset, write-back, down, post indexed */
611 if (BITS (4, 7) == 9)
613 rhs
= state
->Reg
[MULRHSReg
];
614 if (MULLHSReg
== MULDESTReg
)
617 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
619 else if (MULDESTReg
!= 15)
620 state
->Reg
[MULDESTReg
] =
621 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
626 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
627 if (rhs
& (1L << dest
))
628 temp
= dest
; /* mult takes this many/2 I cycles */
629 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
639 case 0x03: /* EORS reg and MLAS */
641 if ((BITS (4, 11) & 0xF9) == 0x9)
643 /* LDR register offset, write-back, down, post-indexed */
645 /* fall through to rest of the decoding */
648 if (BITS (4, 7) == 9)
650 rhs
= state
->Reg
[MULRHSReg
];
651 if (MULLHSReg
== MULDESTReg
)
654 dest
= state
->Reg
[MULACCReg
];
655 ARMul_NegZero (state
, dest
);
656 state
->Reg
[MULDESTReg
] = dest
;
658 else if (MULDESTReg
!= 15)
661 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
662 ARMul_NegZero (state
, dest
);
663 state
->Reg
[MULDESTReg
] = dest
;
669 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
670 if (rhs
& (1L << dest
))
671 temp
= dest
; /* mult takes this many/2 I cycles */
672 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
682 case 0x04: /* SUB reg */
684 if (BITS (4, 7) == 0xB)
686 /* STRH immediate offset, no write-back, down, post indexed */
696 case 0x05: /* SUBS reg */
698 if ((BITS (4, 7) & 0x9) == 0x9)
700 /* LDR immediate offset, no write-back, down, post indexed */
702 /* fall through to the rest of the instruction decoding */
708 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
710 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
711 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
721 case 0x06: /* RSB reg */
723 if (BITS (4, 7) == 0xB)
725 /* STRH immediate offset, write-back, down, post indexed */
735 case 0x07: /* RSBS reg */
737 if ((BITS (4, 7) & 0x9) == 0x9)
739 /* LDR immediate offset, write-back, down, post indexed */
741 /* fall through to remainder of instruction decoding */
747 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
749 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
750 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
760 case 0x08: /* ADD reg */
762 if (BITS (4, 11) == 0xB)
764 /* STRH register offset, no write-back, up, post indexed */
770 if (BITS (4, 7) == 0x9)
773 ARMul_Icycles (state
,
774 Multiply64 (state
, instr
, LUNSIGNED
,
784 case 0x09: /* ADDS reg */
786 if ((BITS (4, 11) & 0xF9) == 0x9)
788 /* LDR register offset, no write-back, up, post indexed */
790 /* fall through to remaining instruction decoding */
794 if (BITS (4, 7) == 0x9)
797 ARMul_Icycles (state
,
798 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
807 if ((lhs
| rhs
) >> 30)
808 { /* possible C,V,N to set */
809 ASSIGNN (NEG (dest
));
810 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
811 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
822 case 0x0a: /* ADC reg */
824 if (BITS (4, 11) == 0xB)
826 /* STRH register offset, write-back, up, post-indexed */
832 if (BITS (4, 7) == 0x9)
835 ARMul_Icycles (state
,
836 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
842 dest
= LHS
+ rhs
+ CFLAG
;
846 case 0x0b: /* ADCS reg */
848 if ((BITS (4, 11) & 0xF9) == 0x9)
850 /* LDR register offset, write-back, up, post indexed */
852 /* fall through to remaining instruction decoding */
856 if (BITS (4, 7) == 0x9)
859 ARMul_Icycles (state
,
860 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
867 dest
= lhs
+ rhs
+ CFLAG
;
869 if ((lhs
| rhs
) >> 30)
870 { /* possible C,V,N to set */
871 ASSIGNN (NEG (dest
));
872 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
873 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
884 case 0x0c: /* SBC reg */
886 if (BITS (4, 7) == 0xB)
888 /* STRH immediate offset, no write-back, up post indexed */
894 if (BITS (4, 7) == 0x9)
897 ARMul_Icycles (state
,
898 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
904 dest
= LHS
- rhs
- !CFLAG
;
908 case 0x0d: /* SBCS reg */
910 if ((BITS (4, 7) & 0x9) == 0x9)
912 /* LDR immediate offset, no write-back, up, post indexed */
917 if (BITS (4, 7) == 0x9)
920 ARMul_Icycles (state
,
921 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
928 dest
= lhs
- rhs
- !CFLAG
;
929 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
931 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
932 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
942 case 0x0e: /* RSC reg */
944 if (BITS (4, 7) == 0xB)
946 /* STRH immediate offset, write-back, up, post indexed */
952 if (BITS (4, 7) == 0x9)
955 ARMul_Icycles (state
,
956 MultiplyAdd64 (state
, instr
, LSIGNED
,
962 dest
= rhs
- LHS
- !CFLAG
;
966 case 0x0f: /* RSCS reg */
968 if ((BITS (4, 7) & 0x9) == 0x9)
970 /* LDR immediate offset, write-back, up, post indexed */
972 /* fall through to remaining instruction decoding */
976 if (BITS (4, 7) == 0x9)
979 ARMul_Icycles (state
,
980 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
987 dest
= rhs
- lhs
- !CFLAG
;
988 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
990 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
991 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1001 case 0x10: /* TST reg and MRS CPSR and SWP word */
1003 if (BITS (4, 11) == 0xB)
1005 /* STRH register offset, no write-back, down, pre indexed */
1010 if (BITS (4, 11) == 9)
1016 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1018 INTERNALABORT (temp
);
1019 (void) ARMul_LoadWordN (state
, temp
);
1020 (void) ARMul_LoadWordN (state
, temp
);
1024 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1026 DEST
= ARMul_Align (state
, temp
, dest
);
1029 if (state
->abortSig
|| state
->Aborted
)
1034 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1037 DEST
= ECC
| EINT
| EMODE
;
1045 case 0x11: /* TSTP reg */
1047 if ((BITS (4, 11) & 0xF9) == 0x9)
1049 /* LDR register offset, no write-back, down, pre indexed */
1051 /* continue with remaining instruction decode */
1057 state
->Cpsr
= GETSPSR (state
->Bank
);
1058 ARMul_CPSRAltered (state
);
1069 ARMul_NegZero (state
, dest
);
1073 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6) */
1075 if (BITS (4, 11) == 0xB)
1077 /* STRH register offset, write-back, down, pre indexed */
1083 if (BITS (4, 27) == 0x12FFF1)
1085 /* Branch to the address in RHSReg. If bit0 of
1086 destination address is 1 then switch to Thumb mode: */
1087 ARMword addr
= state
->Reg
[RHSReg
];
1089 /* If we read the PC then the bottom bit is clear */
1093 /* Enable this for a helpful bit of debugging when
1094 GDB is not yet fully working...
1095 fprintf (stderr, "BX at %x to %x (go %s)\n",
1096 state->Reg[15], addr, (addr & 1) ? "thumb": "arm" ); */
1098 if (addr
& (1 << 0))
1101 state
->Reg
[15] = addr
& 0xfffffffe;
1102 /* NOTE: The other CPSR flag setting blocks do not
1103 seem to update the state->Cpsr state, but just do
1104 the explicit flag. The copy from the seperate
1105 flags to the register must happen later. */
1111 state
->Reg
[15] = addr
& 0xfffffffc;
1116 if (DESTReg
== 15 && BITS (17, 18) == 0)
1117 { /* MSR reg to CPSR */
1120 ARMul_FixCPSR (state
, instr
, temp
);
1128 case 0x13: /* TEQP reg */
1130 if ((BITS (4, 11) & 0xF9) == 0x9)
1132 /* LDR register offset, write-back, down, pre indexed */
1134 /* continue with remaining instruction decode */
1140 state
->Cpsr
= GETSPSR (state
->Bank
);
1141 ARMul_CPSRAltered (state
);
1152 ARMul_NegZero (state
, dest
);
1156 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1158 if (BITS (4, 7) == 0xB)
1160 /* STRH immediate offset, no write-back, down, pre indexed */
1165 if (BITS (4, 11) == 9)
1171 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1173 INTERNALABORT (temp
);
1174 (void) ARMul_LoadByte (state
, temp
);
1175 (void) ARMul_LoadByte (state
, temp
);
1179 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1180 if (state
->abortSig
|| state
->Aborted
)
1185 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1188 DEST
= GETSPSR (state
->Bank
);
1196 case 0x15: /* CMPP reg */
1198 if ((BITS (4, 7) & 0x9) == 0x9)
1200 /* LDR immediate offset, no write-back, down, pre indexed */
1202 /* continue with remaining instruction decode */
1208 state
->Cpsr
= GETSPSR (state
->Bank
);
1209 ARMul_CPSRAltered (state
);
1221 ARMul_NegZero (state
, dest
);
1222 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1224 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1225 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1235 case 0x16: /* CMN reg and MSR reg to SPSR */
1237 if (BITS (4, 7) == 0xB)
1239 /* STRH immediate offset, write-back, down, pre indexed */
1244 if (DESTReg
== 15 && BITS (17, 18) == 0)
1247 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1255 case 0x17: /* CMNP reg */
1257 if ((BITS (4, 7) & 0x9) == 0x9)
1259 /* LDR immediate offset, write-back, down, pre indexed */
1261 /* continue with remaining instruction decoding */
1267 state
->Cpsr
= GETSPSR (state
->Bank
);
1268 ARMul_CPSRAltered (state
);
1281 ASSIGNZ (dest
== 0);
1282 if ((lhs
| rhs
) >> 30)
1283 { /* possible C,V,N to set */
1284 ASSIGNN (NEG (dest
));
1285 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1286 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1297 case 0x18: /* ORR reg */
1299 if (BITS (4, 11) == 0xB)
1301 /* STRH register offset, no write-back, up, pre indexed */
1311 case 0x19: /* ORRS reg */
1313 if ((BITS (4, 11) & 0xF9) == 0x9)
1315 /* LDR register offset, no write-back, up, pre indexed */
1317 /* continue with remaining instruction decoding */
1325 case 0x1a: /* MOV reg */
1327 if (BITS (4, 11) == 0xB)
1329 /* STRH register offset, write-back, up, pre indexed */
1338 case 0x1b: /* MOVS reg */
1340 if ((BITS (4, 11) & 0xF9) == 0x9)
1342 /* LDR register offset, write-back, up, pre indexed */
1344 /* continue with remaining instruction decoding */
1351 case 0x1c: /* BIC reg */
1353 if (BITS (4, 7) == 0xB)
1355 /* STRH immediate offset, no write-back, up, pre indexed */
1365 case 0x1d: /* BICS reg */
1367 if ((BITS (4, 7) & 0x9) == 0x9)
1369 /* LDR immediate offset, no write-back, up, pre indexed */
1371 /* continue with instruction decoding */
1379 case 0x1e: /* MVN reg */
1381 if (BITS (4, 7) == 0xB)
1383 /* STRH immediate offset, write-back, up, pre indexed */
1392 case 0x1f: /* MVNS reg */
1394 if ((BITS (4, 7) & 0x9) == 0x9)
1396 /* LDR immediate offset, write-back, up, pre indexed */
1398 /* continue instruction decoding */
1405 /***************************************************************************\
1406 * Data Processing Immediate RHS Instructions *
1407 \***************************************************************************/
1409 case 0x20: /* AND immed */
1410 dest
= LHS
& DPImmRHS
;
1414 case 0x21: /* ANDS immed */
1420 case 0x22: /* EOR immed */
1421 dest
= LHS
^ DPImmRHS
;
1425 case 0x23: /* EORS immed */
1431 case 0x24: /* SUB immed */
1432 dest
= LHS
- DPImmRHS
;
1436 case 0x25: /* SUBS immed */
1440 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1442 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1443 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1453 case 0x26: /* RSB immed */
1454 dest
= DPImmRHS
- LHS
;
1458 case 0x27: /* RSBS immed */
1462 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1464 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1465 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1475 case 0x28: /* ADD immed */
1476 dest
= LHS
+ DPImmRHS
;
1480 case 0x29: /* ADDS immed */
1484 ASSIGNZ (dest
== 0);
1485 if ((lhs
| rhs
) >> 30)
1486 { /* possible C,V,N to set */
1487 ASSIGNN (NEG (dest
));
1488 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1489 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1500 case 0x2a: /* ADC immed */
1501 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1505 case 0x2b: /* ADCS immed */
1508 dest
= lhs
+ rhs
+ CFLAG
;
1509 ASSIGNZ (dest
== 0);
1510 if ((lhs
| rhs
) >> 30)
1511 { /* possible C,V,N to set */
1512 ASSIGNN (NEG (dest
));
1513 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1514 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1525 case 0x2c: /* SBC immed */
1526 dest
= LHS
- DPImmRHS
- !CFLAG
;
1530 case 0x2d: /* SBCS immed */
1533 dest
= lhs
- rhs
- !CFLAG
;
1534 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1536 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1537 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1547 case 0x2e: /* RSC immed */
1548 dest
= DPImmRHS
- LHS
- !CFLAG
;
1552 case 0x2f: /* RSCS immed */
1555 dest
= rhs
- lhs
- !CFLAG
;
1556 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1558 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1559 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1569 case 0x30: /* TST immed */
1573 case 0x31: /* TSTP immed */
1577 state
->Cpsr
= GETSPSR (state
->Bank
);
1578 ARMul_CPSRAltered (state
);
1580 temp
= LHS
& DPImmRHS
;
1586 DPSImmRHS
; /* TST immed */
1588 ARMul_NegZero (state
, dest
);
1592 case 0x32: /* TEQ immed and MSR immed to CPSR */
1593 if (DESTReg
== 15 && BITS (17, 18) == 0)
1594 { /* MSR immed to CPSR */
1595 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
1603 case 0x33: /* TEQP immed */
1607 state
->Cpsr
= GETSPSR (state
->Bank
);
1608 ARMul_CPSRAltered (state
);
1610 temp
= LHS
^ DPImmRHS
;
1616 DPSImmRHS
; /* TEQ immed */
1618 ARMul_NegZero (state
, dest
);
1622 case 0x34: /* CMP immed */
1626 case 0x35: /* CMPP immed */
1630 state
->Cpsr
= GETSPSR (state
->Bank
);
1631 ARMul_CPSRAltered (state
);
1633 temp
= LHS
- DPImmRHS
;
1640 lhs
= LHS
; /* CMP immed */
1643 ARMul_NegZero (state
, dest
);
1644 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1646 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1647 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1657 case 0x36: /* CMN immed and MSR immed to SPSR */
1658 if (DESTReg
== 15 && BITS (17, 18) == 0) /* MSR */
1659 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
1666 case 0x37: /* CMNP immed */
1670 state
->Cpsr
= GETSPSR (state
->Bank
);
1671 ARMul_CPSRAltered (state
);
1673 temp
= LHS
+ DPImmRHS
;
1680 lhs
= LHS
; /* CMN immed */
1683 ASSIGNZ (dest
== 0);
1684 if ((lhs
| rhs
) >> 30)
1685 { /* possible C,V,N to set */
1686 ASSIGNN (NEG (dest
));
1687 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1688 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1699 case 0x38: /* ORR immed */
1700 dest
= LHS
| DPImmRHS
;
1704 case 0x39: /* ORRS immed */
1710 case 0x3a: /* MOV immed */
1715 case 0x3b: /* MOVS immed */
1720 case 0x3c: /* BIC immed */
1721 dest
= LHS
& ~DPImmRHS
;
1725 case 0x3d: /* BICS immed */
1731 case 0x3e: /* MVN immed */
1736 case 0x3f: /* MVNS immed */
1741 /***************************************************************************\
1742 * Single Data Transfer Immediate RHS Instructions *
1743 \***************************************************************************/
1745 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
1747 if (StoreWord (state
, instr
, lhs
))
1748 LSBase
= lhs
- LSImmRHS
;
1751 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
1753 if (LoadWord (state
, instr
, lhs
))
1754 LSBase
= lhs
- LSImmRHS
;
1757 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
1758 UNDEF_LSRBaseEQDestWb
;
1761 temp
= lhs
- LSImmRHS
;
1762 state
->NtransSig
= LOW
;
1763 if (StoreWord (state
, instr
, lhs
))
1765 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1768 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
1769 UNDEF_LSRBaseEQDestWb
;
1772 state
->NtransSig
= LOW
;
1773 if (LoadWord (state
, instr
, lhs
))
1774 LSBase
= lhs
- LSImmRHS
;
1775 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1778 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
1780 if (StoreByte (state
, instr
, lhs
))
1781 LSBase
= lhs
- LSImmRHS
;
1784 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
1786 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1787 LSBase
= lhs
- LSImmRHS
;
1790 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
1791 UNDEF_LSRBaseEQDestWb
;
1794 state
->NtransSig
= LOW
;
1795 if (StoreByte (state
, instr
, lhs
))
1796 LSBase
= lhs
- LSImmRHS
;
1797 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1800 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
1801 UNDEF_LSRBaseEQDestWb
;
1804 state
->NtransSig
= LOW
;
1805 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1806 LSBase
= lhs
- LSImmRHS
;
1807 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1810 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
1812 if (StoreWord (state
, instr
, lhs
))
1813 LSBase
= lhs
+ LSImmRHS
;
1816 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
1818 if (LoadWord (state
, instr
, lhs
))
1819 LSBase
= lhs
+ LSImmRHS
;
1822 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
1823 UNDEF_LSRBaseEQDestWb
;
1826 state
->NtransSig
= LOW
;
1827 if (StoreWord (state
, instr
, lhs
))
1828 LSBase
= lhs
+ LSImmRHS
;
1829 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1832 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
1833 UNDEF_LSRBaseEQDestWb
;
1836 state
->NtransSig
= LOW
;
1837 if (LoadWord (state
, instr
, lhs
))
1838 LSBase
= lhs
+ LSImmRHS
;
1839 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1842 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
1844 if (StoreByte (state
, instr
, lhs
))
1845 LSBase
= lhs
+ LSImmRHS
;
1848 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
1850 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1851 LSBase
= lhs
+ LSImmRHS
;
1854 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
1855 UNDEF_LSRBaseEQDestWb
;
1858 state
->NtransSig
= LOW
;
1859 if (StoreByte (state
, instr
, lhs
))
1860 LSBase
= lhs
+ LSImmRHS
;
1861 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1864 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
1865 UNDEF_LSRBaseEQDestWb
;
1868 state
->NtransSig
= LOW
;
1869 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
1870 LSBase
= lhs
+ LSImmRHS
;
1871 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
1875 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
1876 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
1879 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
1880 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
1883 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
1884 UNDEF_LSRBaseEQDestWb
;
1886 temp
= LHS
- LSImmRHS
;
1887 if (StoreWord (state
, instr
, temp
))
1891 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
1892 UNDEF_LSRBaseEQDestWb
;
1894 temp
= LHS
- LSImmRHS
;
1895 if (LoadWord (state
, instr
, temp
))
1899 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
1900 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
1903 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
1904 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
1907 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
1908 UNDEF_LSRBaseEQDestWb
;
1910 temp
= LHS
- LSImmRHS
;
1911 if (StoreByte (state
, instr
, temp
))
1915 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
1916 UNDEF_LSRBaseEQDestWb
;
1918 temp
= LHS
- LSImmRHS
;
1919 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
1923 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
1924 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
1927 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
1928 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
1931 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
1932 UNDEF_LSRBaseEQDestWb
;
1934 temp
= LHS
+ LSImmRHS
;
1935 if (StoreWord (state
, instr
, temp
))
1939 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
1940 UNDEF_LSRBaseEQDestWb
;
1942 temp
= LHS
+ LSImmRHS
;
1943 if (LoadWord (state
, instr
, temp
))
1947 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
1948 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
1951 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
1952 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
1955 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
1956 UNDEF_LSRBaseEQDestWb
;
1958 temp
= LHS
+ LSImmRHS
;
1959 if (StoreByte (state
, instr
, temp
))
1963 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
1964 UNDEF_LSRBaseEQDestWb
;
1966 temp
= LHS
+ LSImmRHS
;
1967 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
1971 /***************************************************************************\
1972 * Single Data Transfer Register RHS Instructions *
1973 \***************************************************************************/
1975 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
1978 ARMul_UndefInstr (state
, instr
);
1981 UNDEF_LSRBaseEQOffWb
;
1982 UNDEF_LSRBaseEQDestWb
;
1986 if (StoreWord (state
, instr
, lhs
))
1987 LSBase
= lhs
- LSRegRHS
;
1990 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
1993 ARMul_UndefInstr (state
, instr
);
1996 UNDEF_LSRBaseEQOffWb
;
1997 UNDEF_LSRBaseEQDestWb
;
2001 if (LoadWord (state
, instr
, lhs
))
2002 LSBase
= lhs
- LSRegRHS
;
2005 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2008 ARMul_UndefInstr (state
, instr
);
2011 UNDEF_LSRBaseEQOffWb
;
2012 UNDEF_LSRBaseEQDestWb
;
2016 state
->NtransSig
= LOW
;
2017 if (StoreWord (state
, instr
, lhs
))
2018 LSBase
= lhs
- LSRegRHS
;
2019 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2022 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2025 ARMul_UndefInstr (state
, instr
);
2028 UNDEF_LSRBaseEQOffWb
;
2029 UNDEF_LSRBaseEQDestWb
;
2033 state
->NtransSig
= LOW
;
2034 if (LoadWord (state
, instr
, lhs
))
2035 LSBase
= lhs
- LSRegRHS
;
2036 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2039 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2042 ARMul_UndefInstr (state
, instr
);
2045 UNDEF_LSRBaseEQOffWb
;
2046 UNDEF_LSRBaseEQDestWb
;
2050 if (StoreByte (state
, instr
, lhs
))
2051 LSBase
= lhs
- LSRegRHS
;
2054 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2057 ARMul_UndefInstr (state
, instr
);
2060 UNDEF_LSRBaseEQOffWb
;
2061 UNDEF_LSRBaseEQDestWb
;
2065 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2066 LSBase
= lhs
- LSRegRHS
;
2069 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2072 ARMul_UndefInstr (state
, instr
);
2075 UNDEF_LSRBaseEQOffWb
;
2076 UNDEF_LSRBaseEQDestWb
;
2080 state
->NtransSig
= LOW
;
2081 if (StoreByte (state
, instr
, lhs
))
2082 LSBase
= lhs
- LSRegRHS
;
2083 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2086 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2089 ARMul_UndefInstr (state
, instr
);
2092 UNDEF_LSRBaseEQOffWb
;
2093 UNDEF_LSRBaseEQDestWb
;
2097 state
->NtransSig
= LOW
;
2098 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2099 LSBase
= lhs
- LSRegRHS
;
2100 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2103 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2106 ARMul_UndefInstr (state
, instr
);
2109 UNDEF_LSRBaseEQOffWb
;
2110 UNDEF_LSRBaseEQDestWb
;
2114 if (StoreWord (state
, instr
, lhs
))
2115 LSBase
= lhs
+ LSRegRHS
;
2118 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2121 ARMul_UndefInstr (state
, instr
);
2124 UNDEF_LSRBaseEQOffWb
;
2125 UNDEF_LSRBaseEQDestWb
;
2129 if (LoadWord (state
, instr
, lhs
))
2130 LSBase
= lhs
+ LSRegRHS
;
2133 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2136 ARMul_UndefInstr (state
, instr
);
2139 UNDEF_LSRBaseEQOffWb
;
2140 UNDEF_LSRBaseEQDestWb
;
2144 state
->NtransSig
= LOW
;
2145 if (StoreWord (state
, instr
, lhs
))
2146 LSBase
= lhs
+ LSRegRHS
;
2147 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2150 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2153 ARMul_UndefInstr (state
, instr
);
2156 UNDEF_LSRBaseEQOffWb
;
2157 UNDEF_LSRBaseEQDestWb
;
2161 state
->NtransSig
= LOW
;
2162 if (LoadWord (state
, instr
, lhs
))
2163 LSBase
= lhs
+ LSRegRHS
;
2164 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2167 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2170 ARMul_UndefInstr (state
, instr
);
2173 UNDEF_LSRBaseEQOffWb
;
2174 UNDEF_LSRBaseEQDestWb
;
2178 if (StoreByte (state
, instr
, lhs
))
2179 LSBase
= lhs
+ LSRegRHS
;
2182 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2185 ARMul_UndefInstr (state
, instr
);
2188 UNDEF_LSRBaseEQOffWb
;
2189 UNDEF_LSRBaseEQDestWb
;
2193 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2194 LSBase
= lhs
+ LSRegRHS
;
2197 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2200 ARMul_UndefInstr (state
, instr
);
2203 UNDEF_LSRBaseEQOffWb
;
2204 UNDEF_LSRBaseEQDestWb
;
2208 state
->NtransSig
= LOW
;
2209 if (StoreByte (state
, instr
, lhs
))
2210 LSBase
= lhs
+ LSRegRHS
;
2211 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2214 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2217 ARMul_UndefInstr (state
, instr
);
2220 UNDEF_LSRBaseEQOffWb
;
2221 UNDEF_LSRBaseEQDestWb
;
2225 state
->NtransSig
= LOW
;
2226 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2227 LSBase
= lhs
+ LSRegRHS
;
2228 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2232 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2235 ARMul_UndefInstr (state
, instr
);
2238 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2241 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2244 ARMul_UndefInstr (state
, instr
);
2247 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2250 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2253 ARMul_UndefInstr (state
, instr
);
2256 UNDEF_LSRBaseEQOffWb
;
2257 UNDEF_LSRBaseEQDestWb
;
2260 temp
= LHS
- LSRegRHS
;
2261 if (StoreWord (state
, instr
, temp
))
2265 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2268 ARMul_UndefInstr (state
, instr
);
2271 UNDEF_LSRBaseEQOffWb
;
2272 UNDEF_LSRBaseEQDestWb
;
2275 temp
= LHS
- LSRegRHS
;
2276 if (LoadWord (state
, instr
, temp
))
2280 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2283 ARMul_UndefInstr (state
, instr
);
2286 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2289 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2292 ARMul_UndefInstr (state
, instr
);
2295 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2298 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2301 ARMul_UndefInstr (state
, instr
);
2304 UNDEF_LSRBaseEQOffWb
;
2305 UNDEF_LSRBaseEQDestWb
;
2308 temp
= LHS
- LSRegRHS
;
2309 if (StoreByte (state
, instr
, temp
))
2313 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2316 ARMul_UndefInstr (state
, instr
);
2319 UNDEF_LSRBaseEQOffWb
;
2320 UNDEF_LSRBaseEQDestWb
;
2323 temp
= LHS
- LSRegRHS
;
2324 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2328 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2331 ARMul_UndefInstr (state
, instr
);
2334 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2337 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2340 ARMul_UndefInstr (state
, instr
);
2343 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2346 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2349 ARMul_UndefInstr (state
, instr
);
2352 UNDEF_LSRBaseEQOffWb
;
2353 UNDEF_LSRBaseEQDestWb
;
2356 temp
= LHS
+ LSRegRHS
;
2357 if (StoreWord (state
, instr
, temp
))
2361 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2364 ARMul_UndefInstr (state
, instr
);
2367 UNDEF_LSRBaseEQOffWb
;
2368 UNDEF_LSRBaseEQDestWb
;
2371 temp
= LHS
+ LSRegRHS
;
2372 if (LoadWord (state
, instr
, temp
))
2376 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2379 ARMul_UndefInstr (state
, instr
);
2382 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2385 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2388 ARMul_UndefInstr (state
, instr
);
2391 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2394 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2397 ARMul_UndefInstr (state
, instr
);
2400 UNDEF_LSRBaseEQOffWb
;
2401 UNDEF_LSRBaseEQDestWb
;
2404 temp
= LHS
+ LSRegRHS
;
2405 if (StoreByte (state
, instr
, temp
))
2409 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2412 /* Check for the special breakpoint opcode.
2413 This value should correspond to the value defined
2414 as ARM_BE_BREAKPOINT in gdb/arm-tdep.c. */
2415 if (BITS (0, 19) == 0xfdefe)
2417 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2418 ARMul_Abort (state
, ARMul_SWIV
);
2421 ARMul_UndefInstr (state
, instr
);
2424 UNDEF_LSRBaseEQOffWb
;
2425 UNDEF_LSRBaseEQDestWb
;
2428 temp
= LHS
+ LSRegRHS
;
2429 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2433 /***************************************************************************\
2434 * Multiple Data Transfer Instructions *
2435 \***************************************************************************/
2437 case 0x80: /* Store, No WriteBack, Post Dec */
2438 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2441 case 0x81: /* Load, No WriteBack, Post Dec */
2442 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2445 case 0x82: /* Store, WriteBack, Post Dec */
2446 temp
= LSBase
- LSMNumRegs
;
2447 STOREMULT (instr
, temp
+ 4L, temp
);
2450 case 0x83: /* Load, WriteBack, Post Dec */
2451 temp
= LSBase
- LSMNumRegs
;
2452 LOADMULT (instr
, temp
+ 4L, temp
);
2455 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2456 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2459 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2460 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2463 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2464 temp
= LSBase
- LSMNumRegs
;
2465 STORESMULT (instr
, temp
+ 4L, temp
);
2468 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2469 temp
= LSBase
- LSMNumRegs
;
2470 LOADSMULT (instr
, temp
+ 4L, temp
);
2474 case 0x88: /* Store, No WriteBack, Post Inc */
2475 STOREMULT (instr
, LSBase
, 0L);
2478 case 0x89: /* Load, No WriteBack, Post Inc */
2479 LOADMULT (instr
, LSBase
, 0L);
2482 case 0x8a: /* Store, WriteBack, Post Inc */
2484 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
2487 case 0x8b: /* Load, WriteBack, Post Inc */
2489 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
2492 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2493 STORESMULT (instr
, LSBase
, 0L);
2496 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2497 LOADSMULT (instr
, LSBase
, 0L);
2500 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2502 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
2505 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2507 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
2511 case 0x90: /* Store, No WriteBack, Pre Dec */
2512 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2515 case 0x91: /* Load, No WriteBack, Pre Dec */
2516 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2519 case 0x92: /* Store, WriteBack, Pre Dec */
2520 temp
= LSBase
- LSMNumRegs
;
2521 STOREMULT (instr
, temp
, temp
);
2524 case 0x93: /* Load, WriteBack, Pre Dec */
2525 temp
= LSBase
- LSMNumRegs
;
2526 LOADMULT (instr
, temp
, temp
);
2529 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2530 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2533 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2534 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2537 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
2538 temp
= LSBase
- LSMNumRegs
;
2539 STORESMULT (instr
, temp
, temp
);
2542 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
2543 temp
= LSBase
- LSMNumRegs
;
2544 LOADSMULT (instr
, temp
, temp
);
2548 case 0x98: /* Store, No WriteBack, Pre Inc */
2549 STOREMULT (instr
, LSBase
+ 4L, 0L);
2552 case 0x99: /* Load, No WriteBack, Pre Inc */
2553 LOADMULT (instr
, LSBase
+ 4L, 0L);
2556 case 0x9a: /* Store, WriteBack, Pre Inc */
2558 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2561 case 0x9b: /* Load, WriteBack, Pre Inc */
2563 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2566 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
2567 STORESMULT (instr
, LSBase
+ 4L, 0L);
2570 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
2571 LOADSMULT (instr
, LSBase
+ 4L, 0L);
2574 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
2576 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2579 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
2581 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2584 /***************************************************************************\
2586 \***************************************************************************/
2596 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2600 /***************************************************************************\
2602 \***************************************************************************/
2612 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2616 /***************************************************************************\
2617 * Branch and Link forward *
2618 \***************************************************************************/
2629 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
2631 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2633 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2637 /***************************************************************************\
2638 * Branch and Link backward *
2639 \***************************************************************************/
2650 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
2652 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2654 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2658 /***************************************************************************\
2659 * Co-Processor Data Transfers *
2660 \***************************************************************************/
2663 case 0xc0: /* Store , No WriteBack , Post Dec */
2664 ARMul_STC (state
, instr
, LHS
);
2668 case 0xc1: /* Load , No WriteBack , Post Dec */
2669 ARMul_LDC (state
, instr
, LHS
);
2673 case 0xc6: /* Store , WriteBack , Post Dec */
2675 state
->Base
= lhs
- LSCOff
;
2676 ARMul_STC (state
, instr
, lhs
);
2680 case 0xc7: /* Load , WriteBack , Post Dec */
2682 state
->Base
= lhs
- LSCOff
;
2683 ARMul_LDC (state
, instr
, lhs
);
2687 case 0xcc: /* Store , No WriteBack , Post Inc */
2688 ARMul_STC (state
, instr
, LHS
);
2692 case 0xcd: /* Load , No WriteBack , Post Inc */
2693 ARMul_LDC (state
, instr
, LHS
);
2697 case 0xce: /* Store , WriteBack , Post Inc */
2699 state
->Base
= lhs
+ LSCOff
;
2700 ARMul_STC (state
, instr
, LHS
);
2704 case 0xcf: /* Load , WriteBack , Post Inc */
2706 state
->Base
= lhs
+ LSCOff
;
2707 ARMul_LDC (state
, instr
, LHS
);
2712 case 0xd4: /* Store , No WriteBack , Pre Dec */
2713 ARMul_STC (state
, instr
, LHS
- LSCOff
);
2717 case 0xd5: /* Load , No WriteBack , Pre Dec */
2718 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
2722 case 0xd6: /* Store , WriteBack , Pre Dec */
2725 ARMul_STC (state
, instr
, lhs
);
2729 case 0xd7: /* Load , WriteBack , Pre Dec */
2732 ARMul_LDC (state
, instr
, lhs
);
2736 case 0xdc: /* Store , No WriteBack , Pre Inc */
2737 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
2741 case 0xdd: /* Load , No WriteBack , Pre Inc */
2742 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
2746 case 0xde: /* Store , WriteBack , Pre Inc */
2749 ARMul_STC (state
, instr
, lhs
);
2753 case 0xdf: /* Load , WriteBack , Pre Inc */
2756 ARMul_LDC (state
, instr
, lhs
);
2759 /***************************************************************************\
2760 * Co-Processor Register Transfers (MCR) and Data Ops *
2761 \***************************************************************************/
2777 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
2779 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
2780 ((state
->Reg
[15] + isize
) & R15PCBITS
));
2784 ARMul_MCR (state
, instr
, DEST
);
2786 else /* CDP Part 1 */
2787 ARMul_CDP (state
, instr
);
2790 /***************************************************************************\
2791 * Co-Processor Register Transfers (MRC) and Data Ops *
2792 \***************************************************************************/
2804 temp
= ARMul_MRC (state
, instr
);
2807 ASSIGNN ((temp
& NBIT
) != 0);
2808 ASSIGNZ ((temp
& ZBIT
) != 0);
2809 ASSIGNC ((temp
& CBIT
) != 0);
2810 ASSIGNV ((temp
& VBIT
) != 0);
2815 else /* CDP Part 2 */
2816 ARMul_CDP (state
, instr
);
2819 /***************************************************************************\
2821 \***************************************************************************/
2839 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
2840 { /* a prefetch abort */
2841 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
2845 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
2847 ARMul_Abort (state
, ARMul_SWIV
);
2850 } /* 256 way main switch */
2857 #ifdef NEED_UI_LOOP_HOOK
2858 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
2860 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
2863 #endif /* NEED_UI_LOOP_HOOK */
2865 if (state
->Emulate
== ONCE
)
2866 state
->Emulate
= STOP
;
2867 /* If we have changed mode, allow the PC to advance before stopping. */
2868 else if (state
->Emulate
== CHANGEMODE
)
2870 else if (state
->Emulate
!= RUN
)
2873 while (!stop_simulator
); /* do loop */
2875 state
->decoded
= decoded
;
2876 state
->loaded
= loaded
;
2880 } /* Emulate 26/32 in instruction based mode */
2883 /***************************************************************************\
2884 * This routine evaluates most Data Processing register RHS's with the S *
2885 * bit clear. It is intended to be called from the macro DPRegRHS, which *
2886 * filters the common case of an unshifted register with in line code *
2887 \***************************************************************************/
2890 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
2892 ARMword shamt
, base
;
2896 { /* shift amount in a register */
2901 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2904 base
= state
->Reg
[base
];
2905 ARMul_Icycles (state
, 1, 0L);
2906 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
2907 switch ((int) BITS (5, 6))
2912 else if (shamt
>= 32)
2915 return (base
<< shamt
);
2919 else if (shamt
>= 32)
2922 return (base
>> shamt
);
2926 else if (shamt
>= 32)
2927 return ((ARMword
) ((long int) base
>> 31L));
2929 return ((ARMword
) ((long int) base
>> (int) shamt
));
2935 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
2939 { /* shift amount is a constant */
2942 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2945 base
= state
->Reg
[base
];
2946 shamt
= BITS (7, 11);
2947 switch ((int) BITS (5, 6))
2950 return (base
<< shamt
);
2955 return (base
>> shamt
);
2958 return ((ARMword
) ((long int) base
>> 31L));
2960 return ((ARMword
) ((long int) base
>> (int) shamt
));
2962 if (shamt
== 0) /* its an RRX */
2963 return ((base
>> 1) | (CFLAG
<< 31));
2965 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
2968 return (0); /* just to shut up lint */
2971 /***************************************************************************\
2972 * This routine evaluates most Logical Data Processing register RHS's *
2973 * with the S bit set. It is intended to be called from the macro *
2974 * DPSRegRHS, which filters the common case of an unshifted register *
2975 * with in line code *
2976 \***************************************************************************/
2979 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
2981 ARMword shamt
, base
;
2985 { /* shift amount in a register */
2990 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2993 base
= state
->Reg
[base
];
2994 ARMul_Icycles (state
, 1, 0L);
2995 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
2996 switch ((int) BITS (5, 6))
3001 else if (shamt
== 32)
3006 else if (shamt
> 32)
3013 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3014 return (base
<< shamt
);
3019 else if (shamt
== 32)
3021 ASSIGNC (base
>> 31);
3024 else if (shamt
> 32)
3031 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3032 return (base
>> shamt
);
3037 else if (shamt
>= 32)
3039 ASSIGNC (base
>> 31L);
3040 return ((ARMword
) ((long int) base
>> 31L));
3044 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3045 return ((ARMword
) ((long int) base
>> (int) shamt
));
3053 ASSIGNC (base
>> 31);
3058 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3059 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3064 { /* shift amount is a constant */
3067 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3070 base
= state
->Reg
[base
];
3071 shamt
= BITS (7, 11);
3072 switch ((int) BITS (5, 6))
3075 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3076 return (base
<< shamt
);
3080 ASSIGNC (base
>> 31);
3085 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3086 return (base
>> shamt
);
3091 ASSIGNC (base
>> 31L);
3092 return ((ARMword
) ((long int) base
>> 31L));
3096 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3097 return ((ARMword
) ((long int) base
>> (int) shamt
));
3104 return ((base
>> 1) | (shamt
<< 31));
3108 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3109 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3113 return (0); /* just to shut up lint */
3116 /***************************************************************************\
3117 * This routine handles writes to register 15 when the S bit is not set. *
3118 \***************************************************************************/
3121 WriteR15 (ARMul_State
* state
, ARMword src
)
3123 /* The ARM documentation implies (but doe snot state) that the bottom bit of the PC is never set */
3125 state
->Reg
[15] = src
& PCBITS
& ~0x1;
3127 state
->Reg
[15] = (src
& R15PCBITS
& ~0x1) | ECC
| ER15INT
| EMODE
;
3128 ARMul_R15Altered (state
);
3133 /***************************************************************************\
3134 * This routine handles writes to register 15 when the S bit is set. *
3135 \***************************************************************************/
3138 WriteSR15 (ARMul_State
* state
, ARMword src
)
3141 state
->Reg
[15] = src
& PCBITS
;
3142 if (state
->Bank
> 0)
3144 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3145 ARMul_CPSRAltered (state
);
3148 if (state
->Bank
== USERBANK
)
3149 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3151 state
->Reg
[15] = src
;
3152 ARMul_R15Altered (state
);
3157 /***************************************************************************\
3158 * This routine evaluates most Load and Store register RHS's. It is *
3159 * intended to be called from the macro LSRegRHS, which filters the *
3160 * common case of an unshifted register with in line code *
3161 \***************************************************************************/
3164 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3166 ARMword shamt
, base
;
3171 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3174 base
= state
->Reg
[base
];
3176 shamt
= BITS (7, 11);
3177 switch ((int) BITS (5, 6))
3180 return (base
<< shamt
);
3185 return (base
>> shamt
);
3188 return ((ARMword
) ((long int) base
>> 31L));
3190 return ((ARMword
) ((long int) base
>> (int) shamt
));
3192 if (shamt
== 0) /* its an RRX */
3193 return ((base
>> 1) | (CFLAG
<< 31));
3195 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3197 return (0); /* just to shut up lint */
3200 /***************************************************************************\
3201 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3202 \***************************************************************************/
3205 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3211 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3213 return state
->Reg
[RHSReg
];
3216 /* else immediate */
3217 return BITS (0, 3) | (BITS (8, 11) << 4);
3220 /***************************************************************************\
3221 * This function does the work of loading a word for a LDR instruction. *
3222 \***************************************************************************/
3225 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3231 if (ADDREXCEPT (address
))
3233 INTERNALABORT (address
);
3236 dest
= ARMul_LoadWordN (state
, address
);
3240 return (state
->lateabtSig
);
3243 dest
= ARMul_Align (state
, address
, dest
);
3245 ARMul_Icycles (state
, 1, 0L);
3247 return (DESTReg
!= LHSReg
);
3251 /***************************************************************************\
3252 * This function does the work of loading a halfword. *
3253 \***************************************************************************/
3256 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3263 if (ADDREXCEPT (address
))
3265 INTERNALABORT (address
);
3268 dest
= ARMul_LoadHalfWord (state
, address
);
3272 return (state
->lateabtSig
);
3277 if (dest
& 1 << (16 - 1))
3278 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3281 ARMul_Icycles (state
, 1, 0L);
3282 return (DESTReg
!= LHSReg
);
3287 /***************************************************************************\
3288 * This function does the work of loading a byte for a LDRB instruction. *
3289 \***************************************************************************/
3292 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3298 if (ADDREXCEPT (address
))
3300 INTERNALABORT (address
);
3303 dest
= ARMul_LoadByte (state
, address
);
3307 return (state
->lateabtSig
);
3312 if (dest
& 1 << (8 - 1))
3313 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3316 ARMul_Icycles (state
, 1, 0L);
3317 return (DESTReg
!= LHSReg
);
3320 /***************************************************************************\
3321 * This function does the work of storing a word from a STR instruction. *
3322 \***************************************************************************/
3325 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3330 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3333 ARMul_StoreWordN (state
, address
, DEST
);
3335 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3337 INTERNALABORT (address
);
3338 (void) ARMul_LoadWordN (state
, address
);
3341 ARMul_StoreWordN (state
, address
, DEST
);
3346 return (state
->lateabtSig
);
3352 /***************************************************************************\
3353 * This function does the work of storing a byte for a STRH instruction. *
3354 \***************************************************************************/
3357 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3363 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3367 ARMul_StoreHalfWord (state
, address
, DEST
);
3369 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3371 INTERNALABORT (address
);
3372 (void) ARMul_LoadHalfWord (state
, address
);
3375 ARMul_StoreHalfWord (state
, address
, DEST
);
3381 return (state
->lateabtSig
);
3389 /***************************************************************************\
3390 * This function does the work of storing a byte for a STRB instruction. *
3391 \***************************************************************************/
3394 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
3399 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3402 ARMul_StoreByte (state
, address
, DEST
);
3404 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3406 INTERNALABORT (address
);
3407 (void) ARMul_LoadByte (state
, address
);
3410 ARMul_StoreByte (state
, address
, DEST
);
3415 return (state
->lateabtSig
);
3421 /***************************************************************************\
3422 * This function does the work of loading the registers listed in an LDM *
3423 * instruction, when the S bit is clear. The code here is always increment *
3424 * after, it's up to the caller to get the input address correct and to *
3425 * handle base register modification. *
3426 \***************************************************************************/
3429 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
3435 UNDEF_LSMBaseInListWb
;
3438 if (ADDREXCEPT (address
))
3440 INTERNALABORT (address
);
3443 if (BIT (21) && LHSReg
!= 15)
3446 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3447 dest
= ARMul_LoadWordN (state
, address
);
3448 if (!state
->abortSig
&& !state
->Aborted
)
3449 state
->Reg
[temp
++] = dest
;
3450 else if (!state
->Aborted
)
3451 state
->Aborted
= ARMul_DataAbortV
;
3453 for (; temp
< 16; temp
++) /* S cycles from here on */
3455 { /* load this register */
3457 dest
= ARMul_LoadWordS (state
, address
);
3458 if (!state
->abortSig
&& !state
->Aborted
)
3459 state
->Reg
[temp
] = dest
;
3460 else if (!state
->Aborted
)
3461 state
->Aborted
= ARMul_DataAbortV
;
3464 if (BIT (15) && !state
->Aborted
)
3465 { /* PC is in the reg list */
3467 state
->Reg
[15] = PC
;
3472 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3476 if (BIT (21) && LHSReg
!= 15)
3482 /***************************************************************************\
3483 * This function does the work of loading the registers listed in an LDM *
3484 * instruction, when the S bit is set. The code here is always increment *
3485 * after, it's up to the caller to get the input address correct and to *
3486 * handle base register modification. *
3487 \***************************************************************************/
3490 LoadSMult (ARMul_State
* state
, ARMword instr
,
3491 ARMword address
, ARMword WBBase
)
3497 UNDEF_LSMBaseInListWb
;
3500 if (ADDREXCEPT (address
))
3502 INTERNALABORT (address
);
3506 if (!BIT (15) && state
->Bank
!= USERBANK
)
3508 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* temporary reg bank switch */
3509 UNDEF_LSMUserBankWb
;
3512 if (BIT (21) && LHSReg
!= 15)
3515 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3516 dest
= ARMul_LoadWordN (state
, address
);
3517 if (!state
->abortSig
)
3518 state
->Reg
[temp
++] = dest
;
3519 else if (!state
->Aborted
)
3520 state
->Aborted
= ARMul_DataAbortV
;
3522 for (; temp
< 16; temp
++) /* S cycles from here on */
3524 { /* load this register */
3526 dest
= ARMul_LoadWordS (state
, address
);
3527 if (!state
->abortSig
&& !state
->Aborted
)
3528 state
->Reg
[temp
] = dest
;
3529 else if (!state
->Aborted
)
3530 state
->Aborted
= ARMul_DataAbortV
;
3533 if (BIT (15) && !state
->Aborted
)
3534 { /* PC is in the reg list */
3536 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3538 state
->Cpsr
= GETSPSR (state
->Bank
);
3539 ARMul_CPSRAltered (state
);
3541 state
->Reg
[15] = PC
;
3543 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
3544 { /* protect bits in user mode */
3545 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
3546 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
3547 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
3548 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
3551 ARMul_R15Altered (state
);
3556 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3557 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3559 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3563 if (BIT (21) && LHSReg
!= 15)
3570 /***************************************************************************\
3571 * This function does the work of storing the registers listed in an STM *
3572 * instruction, when the S bit is clear. The code here is always increment *
3573 * after, it's up to the caller to get the input address correct and to *
3574 * handle base register modification. *
3575 \***************************************************************************/
3578 StoreMult (ARMul_State
* state
, ARMword instr
,
3579 ARMword address
, ARMword WBBase
)
3585 UNDEF_LSMBaseInListWb
;
3588 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
3592 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3594 INTERNALABORT (address
);
3600 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3602 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3606 (void) ARMul_LoadWordN (state
, address
);
3607 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3609 { /* save this register */
3611 (void) ARMul_LoadWordS (state
, address
);
3613 if (BIT (21) && LHSReg
!= 15)
3619 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3621 if (state
->abortSig
&& !state
->Aborted
)
3622 state
->Aborted
= ARMul_DataAbortV
;
3624 if (BIT (21) && LHSReg
!= 15)
3627 for (; temp
< 16; temp
++) /* S cycles from here on */
3629 { /* save this register */
3631 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3632 if (state
->abortSig
&& !state
->Aborted
)
3633 state
->Aborted
= ARMul_DataAbortV
;
3641 /***************************************************************************\
3642 * This function does the work of storing the registers listed in an STM *
3643 * instruction when the S bit is set. The code here is always increment *
3644 * after, it's up to the caller to get the input address correct and to *
3645 * handle base register modification. *
3646 \***************************************************************************/
3649 StoreSMult (ARMul_State
* state
, ARMword instr
,
3650 ARMword address
, ARMword WBBase
)
3656 UNDEF_LSMBaseInListWb
;
3659 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3661 INTERNALABORT (address
);
3667 if (state
->Bank
!= USERBANK
)
3669 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* Force User Bank */
3670 UNDEF_LSMUserBankWb
;
3673 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3675 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3679 (void) ARMul_LoadWordN (state
, address
);
3680 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3682 { /* save this register */
3684 (void) ARMul_LoadWordS (state
, address
);
3686 if (BIT (21) && LHSReg
!= 15)
3692 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3694 if (state
->abortSig
&& !state
->Aborted
)
3695 state
->Aborted
= ARMul_DataAbortV
;
3697 if (BIT (21) && LHSReg
!= 15)
3700 for (; temp
< 16; temp
++) /* S cycles from here on */
3702 { /* save this register */
3704 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3705 if (state
->abortSig
&& !state
->Aborted
)
3706 state
->Aborted
= ARMul_DataAbortV
;
3709 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3710 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3718 /***************************************************************************\
3719 * This function does the work of adding two 32bit values together, and *
3720 * calculating if a carry has occurred. *
3721 \***************************************************************************/
3724 Add32 (ARMword a1
, ARMword a2
, int *carry
)
3726 ARMword result
= (a1
+ a2
);
3727 unsigned int uresult
= (unsigned int) result
;
3728 unsigned int ua1
= (unsigned int) a1
;
3730 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
3731 or (result > RdLo) then we have no carry: */
3732 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
3740 /***************************************************************************\
3741 * This function does the work of multiplying two 32bit values to give a *
3743 \***************************************************************************/
3746 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3748 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
3749 ARMword RdHi
= 0, RdLo
= 0, Rm
;
3750 int scount
; /* cycle count */
3752 nRdHi
= BITS (16, 19);
3753 nRdLo
= BITS (12, 15);
3757 /* Needed to calculate the cycle count: */
3758 Rm
= state
->Reg
[nRm
];
3760 /* Check for illegal operand combinations first: */
3764 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
3766 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
3768 ARMword Rs
= state
->Reg
[nRs
];
3773 /* Compute sign of result and adjust operands if necessary. */
3775 sign
= (Rm
^ Rs
) & 0x80000000;
3777 if (((signed long) Rm
) < 0)
3780 if (((signed long) Rs
) < 0)
3784 /* We can split the 32x32 into four 16x16 operations. This ensures
3785 that we do not lose precision on 32bit only hosts: */
3786 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
3787 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3788 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
3789 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3791 /* We now need to add all of these results together, taking care
3792 to propogate the carries from the additions: */
3793 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
3795 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
3797 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
3801 /* Negate result if necessary. */
3805 if (RdLo
== 0xFFFFFFFF)
3814 state
->Reg
[nRdLo
] = RdLo
;
3815 state
->Reg
[nRdHi
] = RdHi
;
3816 } /* else undefined result */
3818 fprintf (stderr
, "MULTIPLY64 - INVALID ARGUMENTS\n");
3822 if ((RdHi
== 0) && (RdLo
== 0))
3823 ARMul_NegZero (state
, RdHi
); /* zero value */
3825 ARMul_NegZero (state
, scc
); /* non-zero value */
3828 /* The cycle count depends on whether the instruction is a signed or
3829 unsigned multiply, and what bits are clear in the multiplier: */
3830 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
3831 Rm
= ~Rm
; /* invert the bits to make the check against zero */
3833 if ((Rm
& 0xFFFFFF00) == 0)
3835 else if ((Rm
& 0xFFFF0000) == 0)
3837 else if ((Rm
& 0xFF000000) == 0)
3845 /***************************************************************************\
3846 * This function does the work of multiplying two 32bit values and adding *
3847 * a 64bit value to give a 64bit result. *
3848 \***************************************************************************/
3851 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3858 nRdHi
= BITS (16, 19);
3859 nRdLo
= BITS (12, 15);
3861 RdHi
= state
->Reg
[nRdHi
];
3862 RdLo
= state
->Reg
[nRdLo
];
3864 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
3866 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
3867 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
3869 state
->Reg
[nRdLo
] = RdLo
;
3870 state
->Reg
[nRdHi
] = RdHi
;
3874 /* Ensure that both RdHi and RdLo are used to compute Z, but
3875 don't let RdLo's sign bit make it to N. */
3876 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
3879 return scount
+ 1; /* extra cycle for addition */
This page took 0.116836 seconds and 4 git commands to generate.