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 else if (state
->Emulate
!= RUN
)
2870 while (!stop_simulator
); /* do loop */
2872 state
->decoded
= decoded
;
2873 state
->loaded
= loaded
;
2876 } /* Emulate 26/32 in instruction based mode */
2879 /***************************************************************************\
2880 * This routine evaluates most Data Processing register RHS's with the S *
2881 * bit clear. It is intended to be called from the macro DPRegRHS, which *
2882 * filters the common case of an unshifted register with in line code *
2883 \***************************************************************************/
2886 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
2888 ARMword shamt
, base
;
2892 { /* shift amount in a register */
2897 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2900 base
= state
->Reg
[base
];
2901 ARMul_Icycles (state
, 1, 0L);
2902 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
2903 switch ((int) BITS (5, 6))
2908 else if (shamt
>= 32)
2911 return (base
<< shamt
);
2915 else if (shamt
>= 32)
2918 return (base
>> shamt
);
2922 else if (shamt
>= 32)
2923 return ((ARMword
) ((long int) base
>> 31L));
2925 return ((ARMword
) ((long int) base
>> (int) shamt
));
2931 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
2935 { /* shift amount is a constant */
2938 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2941 base
= state
->Reg
[base
];
2942 shamt
= BITS (7, 11);
2943 switch ((int) BITS (5, 6))
2946 return (base
<< shamt
);
2951 return (base
>> shamt
);
2954 return ((ARMword
) ((long int) base
>> 31L));
2956 return ((ARMword
) ((long int) base
>> (int) shamt
));
2958 if (shamt
== 0) /* its an RRX */
2959 return ((base
>> 1) | (CFLAG
<< 31));
2961 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
2964 return (0); /* just to shut up lint */
2967 /***************************************************************************\
2968 * This routine evaluates most Logical Data Processing register RHS's *
2969 * with the S bit set. It is intended to be called from the macro *
2970 * DPSRegRHS, which filters the common case of an unshifted register *
2971 * with in line code *
2972 \***************************************************************************/
2975 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
2977 ARMword shamt
, base
;
2981 { /* shift amount in a register */
2986 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2989 base
= state
->Reg
[base
];
2990 ARMul_Icycles (state
, 1, 0L);
2991 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
2992 switch ((int) BITS (5, 6))
2997 else if (shamt
== 32)
3002 else if (shamt
> 32)
3009 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3010 return (base
<< shamt
);
3015 else if (shamt
== 32)
3017 ASSIGNC (base
>> 31);
3020 else if (shamt
> 32)
3027 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3028 return (base
>> shamt
);
3033 else if (shamt
>= 32)
3035 ASSIGNC (base
>> 31L);
3036 return ((ARMword
) ((long int) base
>> 31L));
3040 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3041 return ((ARMword
) ((long int) base
>> (int) shamt
));
3049 ASSIGNC (base
>> 31);
3054 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3055 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3060 { /* shift amount is a constant */
3063 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3066 base
= state
->Reg
[base
];
3067 shamt
= BITS (7, 11);
3068 switch ((int) BITS (5, 6))
3071 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3072 return (base
<< shamt
);
3076 ASSIGNC (base
>> 31);
3081 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3082 return (base
>> shamt
);
3087 ASSIGNC (base
>> 31L);
3088 return ((ARMword
) ((long int) base
>> 31L));
3092 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3093 return ((ARMword
) ((long int) base
>> (int) shamt
));
3100 return ((base
>> 1) | (shamt
<< 31));
3104 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3105 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3109 return (0); /* just to shut up lint */
3112 /***************************************************************************\
3113 * This routine handles writes to register 15 when the S bit is not set. *
3114 \***************************************************************************/
3117 WriteR15 (ARMul_State
* state
, ARMword src
)
3119 /* The ARM documentation implies (but doe snot state) that the bottom bit of the PC is never set */
3121 state
->Reg
[15] = src
& PCBITS
& ~0x1;
3123 state
->Reg
[15] = (src
& R15PCBITS
& ~0x1) | ECC
| ER15INT
| EMODE
;
3124 ARMul_R15Altered (state
);
3129 /***************************************************************************\
3130 * This routine handles writes to register 15 when the S bit is set. *
3131 \***************************************************************************/
3134 WriteSR15 (ARMul_State
* state
, ARMword src
)
3137 state
->Reg
[15] = src
& PCBITS
;
3138 if (state
->Bank
> 0)
3140 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3141 ARMul_CPSRAltered (state
);
3144 if (state
->Bank
== USERBANK
)
3145 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3147 state
->Reg
[15] = src
;
3148 ARMul_R15Altered (state
);
3153 /***************************************************************************\
3154 * This routine evaluates most Load and Store register RHS's. It is *
3155 * intended to be called from the macro LSRegRHS, which filters the *
3156 * common case of an unshifted register with in line code *
3157 \***************************************************************************/
3160 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3162 ARMword shamt
, base
;
3167 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3170 base
= state
->Reg
[base
];
3172 shamt
= BITS (7, 11);
3173 switch ((int) BITS (5, 6))
3176 return (base
<< shamt
);
3181 return (base
>> shamt
);
3184 return ((ARMword
) ((long int) base
>> 31L));
3186 return ((ARMword
) ((long int) base
>> (int) shamt
));
3188 if (shamt
== 0) /* its an RRX */
3189 return ((base
>> 1) | (CFLAG
<< 31));
3191 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3193 return (0); /* just to shut up lint */
3196 /***************************************************************************\
3197 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3198 \***************************************************************************/
3201 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3207 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3209 return state
->Reg
[RHSReg
];
3212 /* else immediate */
3213 return BITS (0, 3) | (BITS (8, 11) << 4);
3216 /***************************************************************************\
3217 * This function does the work of loading a word for a LDR instruction. *
3218 \***************************************************************************/
3221 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3227 if (ADDREXCEPT (address
))
3229 INTERNALABORT (address
);
3232 dest
= ARMul_LoadWordN (state
, address
);
3236 return (state
->lateabtSig
);
3239 dest
= ARMul_Align (state
, address
, dest
);
3241 ARMul_Icycles (state
, 1, 0L);
3243 return (DESTReg
!= LHSReg
);
3247 /***************************************************************************\
3248 * This function does the work of loading a halfword. *
3249 \***************************************************************************/
3252 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3259 if (ADDREXCEPT (address
))
3261 INTERNALABORT (address
);
3264 dest
= ARMul_LoadHalfWord (state
, address
);
3268 return (state
->lateabtSig
);
3273 if (dest
& 1 << (16 - 1))
3274 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3277 ARMul_Icycles (state
, 1, 0L);
3278 return (DESTReg
!= LHSReg
);
3283 /***************************************************************************\
3284 * This function does the work of loading a byte for a LDRB instruction. *
3285 \***************************************************************************/
3288 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3294 if (ADDREXCEPT (address
))
3296 INTERNALABORT (address
);
3299 dest
= ARMul_LoadByte (state
, address
);
3303 return (state
->lateabtSig
);
3308 if (dest
& 1 << (8 - 1))
3309 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3312 ARMul_Icycles (state
, 1, 0L);
3313 return (DESTReg
!= LHSReg
);
3316 /***************************************************************************\
3317 * This function does the work of storing a word from a STR instruction. *
3318 \***************************************************************************/
3321 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3326 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3329 ARMul_StoreWordN (state
, address
, DEST
);
3331 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3333 INTERNALABORT (address
);
3334 (void) ARMul_LoadWordN (state
, address
);
3337 ARMul_StoreWordN (state
, address
, DEST
);
3342 return (state
->lateabtSig
);
3348 /***************************************************************************\
3349 * This function does the work of storing a byte for a STRH instruction. *
3350 \***************************************************************************/
3353 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3359 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3363 ARMul_StoreHalfWord (state
, address
, DEST
);
3365 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3367 INTERNALABORT (address
);
3368 (void) ARMul_LoadHalfWord (state
, address
);
3371 ARMul_StoreHalfWord (state
, address
, DEST
);
3377 return (state
->lateabtSig
);
3385 /***************************************************************************\
3386 * This function does the work of storing a byte for a STRB instruction. *
3387 \***************************************************************************/
3390 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
3395 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3398 ARMul_StoreByte (state
, address
, DEST
);
3400 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3402 INTERNALABORT (address
);
3403 (void) ARMul_LoadByte (state
, address
);
3406 ARMul_StoreByte (state
, address
, DEST
);
3411 return (state
->lateabtSig
);
3417 /***************************************************************************\
3418 * This function does the work of loading the registers listed in an LDM *
3419 * instruction, when the S bit is clear. The code here is always increment *
3420 * after, it's up to the caller to get the input address correct and to *
3421 * handle base register modification. *
3422 \***************************************************************************/
3425 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
3431 UNDEF_LSMBaseInListWb
;
3434 if (ADDREXCEPT (address
))
3436 INTERNALABORT (address
);
3439 if (BIT (21) && LHSReg
!= 15)
3442 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3443 dest
= ARMul_LoadWordN (state
, address
);
3444 if (!state
->abortSig
&& !state
->Aborted
)
3445 state
->Reg
[temp
++] = dest
;
3446 else if (!state
->Aborted
)
3447 state
->Aborted
= ARMul_DataAbortV
;
3449 for (; temp
< 16; temp
++) /* S cycles from here on */
3451 { /* load this register */
3453 dest
= ARMul_LoadWordS (state
, address
);
3454 if (!state
->abortSig
&& !state
->Aborted
)
3455 state
->Reg
[temp
] = dest
;
3456 else if (!state
->Aborted
)
3457 state
->Aborted
= ARMul_DataAbortV
;
3461 { /* PC is in the reg list */
3463 state
->Reg
[15] = PC
;
3468 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3472 if (BIT (21) && LHSReg
!= 15)
3478 /***************************************************************************\
3479 * This function does the work of loading the registers listed in an LDM *
3480 * instruction, when the S bit is set. The code here is always increment *
3481 * after, it's up to the caller to get the input address correct and to *
3482 * handle base register modification. *
3483 \***************************************************************************/
3486 LoadSMult (ARMul_State
* state
, ARMword instr
,
3487 ARMword address
, ARMword WBBase
)
3493 UNDEF_LSMBaseInListWb
;
3496 if (ADDREXCEPT (address
))
3498 INTERNALABORT (address
);
3502 if (!BIT (15) && state
->Bank
!= USERBANK
)
3504 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* temporary reg bank switch */
3505 UNDEF_LSMUserBankWb
;
3508 if (BIT (21) && LHSReg
!= 15)
3511 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3512 dest
= ARMul_LoadWordN (state
, address
);
3513 if (!state
->abortSig
)
3514 state
->Reg
[temp
++] = dest
;
3515 else if (!state
->Aborted
)
3516 state
->Aborted
= ARMul_DataAbortV
;
3518 for (; temp
< 16; temp
++) /* S cycles from here on */
3520 { /* load this register */
3522 dest
= ARMul_LoadWordS (state
, address
);
3523 if (!state
->abortSig
|| state
->Aborted
)
3524 state
->Reg
[temp
] = dest
;
3525 else if (!state
->Aborted
)
3526 state
->Aborted
= ARMul_DataAbortV
;
3530 { /* PC is in the reg list */
3532 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3534 state
->Cpsr
= GETSPSR (state
->Bank
);
3535 ARMul_CPSRAltered (state
);
3537 state
->Reg
[15] = PC
;
3539 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
3540 { /* protect bits in user mode */
3541 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
3542 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
3543 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
3544 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
3547 ARMul_R15Altered (state
);
3552 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3553 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3555 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3559 if (BIT (21) && LHSReg
!= 15)
3566 /***************************************************************************\
3567 * This function does the work of storing the registers listed in an STM *
3568 * instruction, when the S bit is clear. The code here is always increment *
3569 * after, it's up to the caller to get the input address correct and to *
3570 * handle base register modification. *
3571 \***************************************************************************/
3574 StoreMult (ARMul_State
* state
, ARMword instr
,
3575 ARMword address
, ARMword WBBase
)
3581 UNDEF_LSMBaseInListWb
;
3584 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
3588 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3590 INTERNALABORT (address
);
3596 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3598 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3602 (void) ARMul_LoadWordN (state
, address
);
3603 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3605 { /* save this register */
3607 (void) ARMul_LoadWordS (state
, address
);
3609 if (BIT (21) && LHSReg
!= 15)
3615 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3617 if (state
->abortSig
&& !state
->Aborted
)
3618 state
->Aborted
= ARMul_DataAbortV
;
3620 if (BIT (21) && LHSReg
!= 15)
3623 for (; temp
< 16; temp
++) /* S cycles from here on */
3625 { /* save this register */
3627 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3628 if (state
->abortSig
&& !state
->Aborted
)
3629 state
->Aborted
= ARMul_DataAbortV
;
3637 /***************************************************************************\
3638 * This function does the work of storing the registers listed in an STM *
3639 * instruction when the S bit is set. The code here is always increment *
3640 * after, it's up to the caller to get the input address correct and to *
3641 * handle base register modification. *
3642 \***************************************************************************/
3645 StoreSMult (ARMul_State
* state
, ARMword instr
,
3646 ARMword address
, ARMword WBBase
)
3652 UNDEF_LSMBaseInListWb
;
3655 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3657 INTERNALABORT (address
);
3663 if (state
->Bank
!= USERBANK
)
3665 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* Force User Bank */
3666 UNDEF_LSMUserBankWb
;
3669 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3671 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3675 (void) ARMul_LoadWordN (state
, address
);
3676 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3678 { /* save this register */
3680 (void) ARMul_LoadWordS (state
, address
);
3682 if (BIT (21) && LHSReg
!= 15)
3688 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3690 if (state
->abortSig
&& !state
->Aborted
)
3691 state
->Aborted
= ARMul_DataAbortV
;
3693 if (BIT (21) && LHSReg
!= 15)
3696 for (; temp
< 16; temp
++) /* S cycles from here on */
3698 { /* save this register */
3700 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3701 if (state
->abortSig
&& !state
->Aborted
)
3702 state
->Aborted
= ARMul_DataAbortV
;
3705 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3706 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3714 /***************************************************************************\
3715 * This function does the work of adding two 32bit values together, and *
3716 * calculating if a carry has occurred. *
3717 \***************************************************************************/
3720 Add32 (ARMword a1
, ARMword a2
, int *carry
)
3722 ARMword result
= (a1
+ a2
);
3723 unsigned int uresult
= (unsigned int) result
;
3724 unsigned int ua1
= (unsigned int) a1
;
3726 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
3727 or (result > RdLo) then we have no carry: */
3728 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
3736 /***************************************************************************\
3737 * This function does the work of multiplying two 32bit values to give a *
3739 \***************************************************************************/
3742 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3744 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
3745 ARMword RdHi
= 0, RdLo
= 0, Rm
;
3746 int scount
; /* cycle count */
3748 nRdHi
= BITS (16, 19);
3749 nRdLo
= BITS (12, 15);
3753 /* Needed to calculate the cycle count: */
3754 Rm
= state
->Reg
[nRm
];
3756 /* Check for illegal operand combinations first: */
3760 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
3762 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
3764 ARMword Rs
= state
->Reg
[nRs
];
3769 /* Compute sign of result and adjust operands if necessary. */
3771 sign
= (Rm
^ Rs
) & 0x80000000;
3773 if (((signed long) Rm
) < 0)
3776 if (((signed long) Rs
) < 0)
3780 /* We can split the 32x32 into four 16x16 operations. This ensures
3781 that we do not lose precision on 32bit only hosts: */
3782 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
3783 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3784 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
3785 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3787 /* We now need to add all of these results together, taking care
3788 to propogate the carries from the additions: */
3789 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
3791 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
3793 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
3797 /* Negate result if necessary. */
3801 if (RdLo
== 0xFFFFFFFF)
3810 state
->Reg
[nRdLo
] = RdLo
;
3811 state
->Reg
[nRdHi
] = RdHi
;
3812 } /* else undefined result */
3814 fprintf (stderr
, "MULTIPLY64 - INVALID ARGUMENTS\n");
3818 if ((RdHi
== 0) && (RdLo
== 0))
3819 ARMul_NegZero (state
, RdHi
); /* zero value */
3821 ARMul_NegZero (state
, scc
); /* non-zero value */
3824 /* The cycle count depends on whether the instruction is a signed or
3825 unsigned multiply, and what bits are clear in the multiplier: */
3826 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
3827 Rm
= ~Rm
; /* invert the bits to make the check against zero */
3829 if ((Rm
& 0xFFFFFF00) == 0)
3831 else if ((Rm
& 0xFFFF0000) == 0)
3833 else if ((Rm
& 0xFF000000) == 0)
3841 /***************************************************************************\
3842 * This function does the work of multiplying two 32bit values and adding *
3843 * a 64bit value to give a 64bit result. *
3844 \***************************************************************************/
3847 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3854 nRdHi
= BITS (16, 19);
3855 nRdLo
= BITS (12, 15);
3857 RdHi
= state
->Reg
[nRdHi
];
3858 RdLo
= state
->Reg
[nRdLo
];
3860 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
3862 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
3863 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
3865 state
->Reg
[nRdLo
] = RdLo
;
3866 state
->Reg
[nRdHi
] = RdHi
;
3870 if ((RdHi
== 0) && (RdLo
== 0))
3871 ARMul_NegZero (state
, RdHi
); /* zero value */
3873 ARMul_NegZero (state
, scc
); /* non-zero value */
3876 return scount
+ 1; /* extra cycle for addition */
This page took 0.124273 seconds and 4 git commands to generate.