]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/arm/armemu.c
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;
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 */
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 */
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) /* 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 temp
= lhs
- LSRegRHS
;
2002 if (LoadWord (state
, instr
, lhs
))
2006 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2009 ARMul_UndefInstr (state
, instr
);
2012 UNDEF_LSRBaseEQOffWb
;
2013 UNDEF_LSRBaseEQDestWb
;
2017 state
->NtransSig
= LOW
;
2018 if (StoreWord (state
, instr
, lhs
))
2019 LSBase
= lhs
- LSRegRHS
;
2020 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2023 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2026 ARMul_UndefInstr (state
, instr
);
2029 UNDEF_LSRBaseEQOffWb
;
2030 UNDEF_LSRBaseEQDestWb
;
2034 temp
= lhs
- LSRegRHS
;
2035 state
->NtransSig
= LOW
;
2036 if (LoadWord (state
, instr
, lhs
))
2038 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2041 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2044 ARMul_UndefInstr (state
, instr
);
2047 UNDEF_LSRBaseEQOffWb
;
2048 UNDEF_LSRBaseEQDestWb
;
2052 if (StoreByte (state
, instr
, lhs
))
2053 LSBase
= lhs
- LSRegRHS
;
2056 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2059 ARMul_UndefInstr (state
, instr
);
2062 UNDEF_LSRBaseEQOffWb
;
2063 UNDEF_LSRBaseEQDestWb
;
2067 temp
= lhs
- LSRegRHS
;
2068 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2072 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2075 ARMul_UndefInstr (state
, instr
);
2078 UNDEF_LSRBaseEQOffWb
;
2079 UNDEF_LSRBaseEQDestWb
;
2083 state
->NtransSig
= LOW
;
2084 if (StoreByte (state
, instr
, lhs
))
2085 LSBase
= lhs
- LSRegRHS
;
2086 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2089 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2092 ARMul_UndefInstr (state
, instr
);
2095 UNDEF_LSRBaseEQOffWb
;
2096 UNDEF_LSRBaseEQDestWb
;
2100 temp
= lhs
- LSRegRHS
;
2101 state
->NtransSig
= LOW
;
2102 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2104 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2107 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2110 ARMul_UndefInstr (state
, instr
);
2113 UNDEF_LSRBaseEQOffWb
;
2114 UNDEF_LSRBaseEQDestWb
;
2118 if (StoreWord (state
, instr
, lhs
))
2119 LSBase
= lhs
+ LSRegRHS
;
2122 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2125 ARMul_UndefInstr (state
, instr
);
2128 UNDEF_LSRBaseEQOffWb
;
2129 UNDEF_LSRBaseEQDestWb
;
2133 temp
= lhs
+ LSRegRHS
;
2134 if (LoadWord (state
, instr
, lhs
))
2138 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2141 ARMul_UndefInstr (state
, instr
);
2144 UNDEF_LSRBaseEQOffWb
;
2145 UNDEF_LSRBaseEQDestWb
;
2149 state
->NtransSig
= LOW
;
2150 if (StoreWord (state
, instr
, lhs
))
2151 LSBase
= lhs
+ LSRegRHS
;
2152 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2155 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2158 ARMul_UndefInstr (state
, instr
);
2161 UNDEF_LSRBaseEQOffWb
;
2162 UNDEF_LSRBaseEQDestWb
;
2166 temp
= lhs
+ LSRegRHS
;
2167 state
->NtransSig
= LOW
;
2168 if (LoadWord (state
, instr
, lhs
))
2170 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2173 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2176 ARMul_UndefInstr (state
, instr
);
2179 UNDEF_LSRBaseEQOffWb
;
2180 UNDEF_LSRBaseEQDestWb
;
2184 if (StoreByte (state
, instr
, lhs
))
2185 LSBase
= lhs
+ LSRegRHS
;
2188 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2191 ARMul_UndefInstr (state
, instr
);
2194 UNDEF_LSRBaseEQOffWb
;
2195 UNDEF_LSRBaseEQDestWb
;
2199 temp
= lhs
+ LSRegRHS
;
2200 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2204 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2207 ARMul_UndefInstr (state
, instr
);
2210 UNDEF_LSRBaseEQOffWb
;
2211 UNDEF_LSRBaseEQDestWb
;
2215 state
->NtransSig
= LOW
;
2216 if (StoreByte (state
, instr
, lhs
))
2217 LSBase
= lhs
+ LSRegRHS
;
2218 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2221 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2224 ARMul_UndefInstr (state
, instr
);
2227 UNDEF_LSRBaseEQOffWb
;
2228 UNDEF_LSRBaseEQDestWb
;
2232 temp
= lhs
+ LSRegRHS
;
2233 state
->NtransSig
= LOW
;
2234 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2236 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2240 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2243 ARMul_UndefInstr (state
, instr
);
2246 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2249 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2252 ARMul_UndefInstr (state
, instr
);
2255 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2258 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2261 ARMul_UndefInstr (state
, instr
);
2264 UNDEF_LSRBaseEQOffWb
;
2265 UNDEF_LSRBaseEQDestWb
;
2268 temp
= LHS
- LSRegRHS
;
2269 if (StoreWord (state
, instr
, temp
))
2273 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2276 ARMul_UndefInstr (state
, instr
);
2279 UNDEF_LSRBaseEQOffWb
;
2280 UNDEF_LSRBaseEQDestWb
;
2283 temp
= LHS
- LSRegRHS
;
2284 if (LoadWord (state
, instr
, temp
))
2288 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2291 ARMul_UndefInstr (state
, instr
);
2294 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2297 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2300 ARMul_UndefInstr (state
, instr
);
2303 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2306 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2309 ARMul_UndefInstr (state
, instr
);
2312 UNDEF_LSRBaseEQOffWb
;
2313 UNDEF_LSRBaseEQDestWb
;
2316 temp
= LHS
- LSRegRHS
;
2317 if (StoreByte (state
, instr
, temp
))
2321 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2324 ARMul_UndefInstr (state
, instr
);
2327 UNDEF_LSRBaseEQOffWb
;
2328 UNDEF_LSRBaseEQDestWb
;
2331 temp
= LHS
- LSRegRHS
;
2332 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2336 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2339 ARMul_UndefInstr (state
, instr
);
2342 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2345 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2348 ARMul_UndefInstr (state
, instr
);
2351 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2354 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2357 ARMul_UndefInstr (state
, instr
);
2360 UNDEF_LSRBaseEQOffWb
;
2361 UNDEF_LSRBaseEQDestWb
;
2364 temp
= LHS
+ LSRegRHS
;
2365 if (StoreWord (state
, instr
, temp
))
2369 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2372 ARMul_UndefInstr (state
, instr
);
2375 UNDEF_LSRBaseEQOffWb
;
2376 UNDEF_LSRBaseEQDestWb
;
2379 temp
= LHS
+ LSRegRHS
;
2380 if (LoadWord (state
, instr
, temp
))
2384 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2387 ARMul_UndefInstr (state
, instr
);
2390 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2393 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2396 ARMul_UndefInstr (state
, instr
);
2399 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2402 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2405 ARMul_UndefInstr (state
, instr
);
2408 UNDEF_LSRBaseEQOffWb
;
2409 UNDEF_LSRBaseEQDestWb
;
2412 temp
= LHS
+ LSRegRHS
;
2413 if (StoreByte (state
, instr
, temp
))
2417 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2420 /* Check for the special breakpoint opcode.
2421 This value should correspond to the value defined
2422 as ARM_BE_BREAKPOINT in gdb/arm-tdep.c. */
2423 if (BITS (0, 19) == 0xfdefe)
2425 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2426 ARMul_Abort (state
, ARMul_SWIV
);
2429 ARMul_UndefInstr (state
, instr
);
2432 UNDEF_LSRBaseEQOffWb
;
2433 UNDEF_LSRBaseEQDestWb
;
2436 temp
= LHS
+ LSRegRHS
;
2437 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2441 /***************************************************************************\
2442 * Multiple Data Transfer Instructions *
2443 \***************************************************************************/
2445 case 0x80: /* Store, No WriteBack, Post Dec */
2446 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2449 case 0x81: /* Load, No WriteBack, Post Dec */
2450 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2453 case 0x82: /* Store, WriteBack, Post Dec */
2454 temp
= LSBase
- LSMNumRegs
;
2455 STOREMULT (instr
, temp
+ 4L, temp
);
2458 case 0x83: /* Load, WriteBack, Post Dec */
2459 temp
= LSBase
- LSMNumRegs
;
2460 LOADMULT (instr
, temp
+ 4L, temp
);
2463 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2464 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2467 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2468 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2471 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2472 temp
= LSBase
- LSMNumRegs
;
2473 STORESMULT (instr
, temp
+ 4L, temp
);
2476 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2477 temp
= LSBase
- LSMNumRegs
;
2478 LOADSMULT (instr
, temp
+ 4L, temp
);
2482 case 0x88: /* Store, No WriteBack, Post Inc */
2483 STOREMULT (instr
, LSBase
, 0L);
2486 case 0x89: /* Load, No WriteBack, Post Inc */
2487 LOADMULT (instr
, LSBase
, 0L);
2490 case 0x8a: /* Store, WriteBack, Post Inc */
2492 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
2495 case 0x8b: /* Load, WriteBack, Post Inc */
2497 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
2500 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2501 STORESMULT (instr
, LSBase
, 0L);
2504 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2505 LOADSMULT (instr
, LSBase
, 0L);
2508 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2510 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
2513 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2515 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
2519 case 0x90: /* Store, No WriteBack, Pre Dec */
2520 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2523 case 0x91: /* Load, No WriteBack, Pre Dec */
2524 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2527 case 0x92: /* Store, WriteBack, Pre Dec */
2528 temp
= LSBase
- LSMNumRegs
;
2529 STOREMULT (instr
, temp
, temp
);
2532 case 0x93: /* Load, WriteBack, Pre Dec */
2533 temp
= LSBase
- LSMNumRegs
;
2534 LOADMULT (instr
, temp
, temp
);
2537 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2538 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2541 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2542 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2545 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
2546 temp
= LSBase
- LSMNumRegs
;
2547 STORESMULT (instr
, temp
, temp
);
2550 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
2551 temp
= LSBase
- LSMNumRegs
;
2552 LOADSMULT (instr
, temp
, temp
);
2556 case 0x98: /* Store, No WriteBack, Pre Inc */
2557 STOREMULT (instr
, LSBase
+ 4L, 0L);
2560 case 0x99: /* Load, No WriteBack, Pre Inc */
2561 LOADMULT (instr
, LSBase
+ 4L, 0L);
2564 case 0x9a: /* Store, WriteBack, Pre Inc */
2566 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2569 case 0x9b: /* Load, WriteBack, Pre Inc */
2571 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2574 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
2575 STORESMULT (instr
, LSBase
+ 4L, 0L);
2578 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
2579 LOADSMULT (instr
, LSBase
+ 4L, 0L);
2582 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
2584 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2587 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
2589 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2592 /***************************************************************************\
2594 \***************************************************************************/
2604 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2608 /***************************************************************************\
2610 \***************************************************************************/
2620 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2624 /***************************************************************************\
2625 * Branch and Link forward *
2626 \***************************************************************************/
2637 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
2639 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2641 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2645 /***************************************************************************\
2646 * Branch and Link backward *
2647 \***************************************************************************/
2658 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
2660 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2662 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2666 /***************************************************************************\
2667 * Co-Processor Data Transfers *
2668 \***************************************************************************/
2671 case 0xc0: /* Store , No WriteBack , Post Dec */
2672 ARMul_STC (state
, instr
, LHS
);
2676 case 0xc1: /* Load , No WriteBack , Post Dec */
2677 ARMul_LDC (state
, instr
, LHS
);
2681 case 0xc6: /* Store , WriteBack , Post Dec */
2683 state
->Base
= lhs
- LSCOff
;
2684 ARMul_STC (state
, instr
, lhs
);
2688 case 0xc7: /* Load , WriteBack , Post Dec */
2690 state
->Base
= lhs
- LSCOff
;
2691 ARMul_LDC (state
, instr
, lhs
);
2695 case 0xcc: /* Store , No WriteBack , Post Inc */
2696 ARMul_STC (state
, instr
, LHS
);
2700 case 0xcd: /* Load , No WriteBack , Post Inc */
2701 ARMul_LDC (state
, instr
, LHS
);
2705 case 0xce: /* Store , WriteBack , Post Inc */
2707 state
->Base
= lhs
+ LSCOff
;
2708 ARMul_STC (state
, instr
, LHS
);
2712 case 0xcf: /* Load , WriteBack , Post Inc */
2714 state
->Base
= lhs
+ LSCOff
;
2715 ARMul_LDC (state
, instr
, LHS
);
2720 case 0xd4: /* Store , No WriteBack , Pre Dec */
2721 ARMul_STC (state
, instr
, LHS
- LSCOff
);
2725 case 0xd5: /* Load , No WriteBack , Pre Dec */
2726 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
2730 case 0xd6: /* Store , WriteBack , Pre Dec */
2733 ARMul_STC (state
, instr
, lhs
);
2737 case 0xd7: /* Load , WriteBack , Pre Dec */
2740 ARMul_LDC (state
, instr
, lhs
);
2744 case 0xdc: /* Store , No WriteBack , Pre Inc */
2745 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
2749 case 0xdd: /* Load , No WriteBack , Pre Inc */
2750 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
2754 case 0xde: /* Store , WriteBack , Pre Inc */
2757 ARMul_STC (state
, instr
, lhs
);
2761 case 0xdf: /* Load , WriteBack , Pre Inc */
2764 ARMul_LDC (state
, instr
, lhs
);
2767 /***************************************************************************\
2768 * Co-Processor Register Transfers (MCR) and Data Ops *
2769 \***************************************************************************/
2785 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
2787 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
2788 ((state
->Reg
[15] + isize
) & R15PCBITS
));
2792 ARMul_MCR (state
, instr
, DEST
);
2794 else /* CDP Part 1 */
2795 ARMul_CDP (state
, instr
);
2798 /***************************************************************************\
2799 * Co-Processor Register Transfers (MRC) and Data Ops *
2800 \***************************************************************************/
2812 temp
= ARMul_MRC (state
, instr
);
2815 ASSIGNN ((temp
& NBIT
) != 0);
2816 ASSIGNZ ((temp
& ZBIT
) != 0);
2817 ASSIGNC ((temp
& CBIT
) != 0);
2818 ASSIGNV ((temp
& VBIT
) != 0);
2823 else /* CDP Part 2 */
2824 ARMul_CDP (state
, instr
);
2827 /***************************************************************************\
2829 \***************************************************************************/
2847 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
2848 { /* a prefetch abort */
2849 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
2853 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
2855 ARMul_Abort (state
, ARMul_SWIV
);
2858 } /* 256 way main switch */
2865 #ifdef NEED_UI_LOOP_HOOK
2866 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
2868 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
2871 #endif /* NEED_UI_LOOP_HOOK */
2873 if (state
->Emulate
== ONCE
)
2874 state
->Emulate
= STOP
;
2875 /* If we have changed mode, allow the PC to advance before stopping. */
2876 else if (state
->Emulate
== CHANGEMODE
)
2878 else if (state
->Emulate
!= RUN
)
2881 while (!stop_simulator
); /* do loop */
2883 state
->decoded
= decoded
;
2884 state
->loaded
= loaded
;
2888 } /* Emulate 26/32 in instruction based mode */
2891 /***************************************************************************\
2892 * This routine evaluates most Data Processing register RHS's with the S *
2893 * bit clear. It is intended to be called from the macro DPRegRHS, which *
2894 * filters the common case of an unshifted register with in line code *
2895 \***************************************************************************/
2898 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
2900 ARMword shamt
, base
;
2904 { /* shift amount in a register */
2909 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2912 base
= state
->Reg
[base
];
2913 ARMul_Icycles (state
, 1, 0L);
2914 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
2915 switch ((int) BITS (5, 6))
2920 else if (shamt
>= 32)
2923 return (base
<< shamt
);
2927 else if (shamt
>= 32)
2930 return (base
>> shamt
);
2934 else if (shamt
>= 32)
2935 return ((ARMword
) ((long int) base
>> 31L));
2937 return ((ARMword
) ((long int) base
>> (int) shamt
));
2943 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
2947 { /* shift amount is a constant */
2950 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2953 base
= state
->Reg
[base
];
2954 shamt
= BITS (7, 11);
2955 switch ((int) BITS (5, 6))
2958 return (base
<< shamt
);
2963 return (base
>> shamt
);
2966 return ((ARMword
) ((long int) base
>> 31L));
2968 return ((ARMword
) ((long int) base
>> (int) shamt
));
2970 if (shamt
== 0) /* its an RRX */
2971 return ((base
>> 1) | (CFLAG
<< 31));
2973 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
2976 return (0); /* just to shut up lint */
2979 /***************************************************************************\
2980 * This routine evaluates most Logical Data Processing register RHS's *
2981 * with the S bit set. It is intended to be called from the macro *
2982 * DPSRegRHS, which filters the common case of an unshifted register *
2983 * with in line code *
2984 \***************************************************************************/
2987 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
2989 ARMword shamt
, base
;
2993 { /* shift amount in a register */
2998 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3001 base
= state
->Reg
[base
];
3002 ARMul_Icycles (state
, 1, 0L);
3003 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3004 switch ((int) BITS (5, 6))
3009 else if (shamt
== 32)
3014 else if (shamt
> 32)
3021 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3022 return (base
<< shamt
);
3027 else if (shamt
== 32)
3029 ASSIGNC (base
>> 31);
3032 else if (shamt
> 32)
3039 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3040 return (base
>> shamt
);
3045 else if (shamt
>= 32)
3047 ASSIGNC (base
>> 31L);
3048 return ((ARMword
) ((long int) base
>> 31L));
3052 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3053 return ((ARMword
) ((long int) base
>> (int) shamt
));
3061 ASSIGNC (base
>> 31);
3066 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3067 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3072 { /* shift amount is a constant */
3075 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3078 base
= state
->Reg
[base
];
3079 shamt
= BITS (7, 11);
3080 switch ((int) BITS (5, 6))
3083 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3084 return (base
<< shamt
);
3088 ASSIGNC (base
>> 31);
3093 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3094 return (base
>> shamt
);
3099 ASSIGNC (base
>> 31L);
3100 return ((ARMword
) ((long int) base
>> 31L));
3104 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3105 return ((ARMword
) ((long int) base
>> (int) shamt
));
3112 return ((base
>> 1) | (shamt
<< 31));
3116 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3117 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3121 return (0); /* just to shut up lint */
3124 /***************************************************************************\
3125 * This routine handles writes to register 15 when the S bit is not set. *
3126 \***************************************************************************/
3129 WriteR15 (ARMul_State
* state
, ARMword src
)
3131 /* The ARM documentation implies (but doe snot state) that the bottom bit of the PC is never set */
3133 state
->Reg
[15] = src
& PCBITS
& ~0x1;
3135 state
->Reg
[15] = (src
& R15PCBITS
& ~0x1) | ECC
| ER15INT
| EMODE
;
3136 ARMul_R15Altered (state
);
3141 /***************************************************************************\
3142 * This routine handles writes to register 15 when the S bit is set. *
3143 \***************************************************************************/
3146 WriteSR15 (ARMul_State
* state
, ARMword src
)
3149 state
->Reg
[15] = src
& PCBITS
;
3150 if (state
->Bank
> 0)
3152 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3153 ARMul_CPSRAltered (state
);
3156 if (state
->Bank
== USERBANK
)
3157 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3159 state
->Reg
[15] = src
;
3160 ARMul_R15Altered (state
);
3165 /***************************************************************************\
3166 * This routine evaluates most Load and Store register RHS's. It is *
3167 * intended to be called from the macro LSRegRHS, which filters the *
3168 * common case of an unshifted register with in line code *
3169 \***************************************************************************/
3172 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3174 ARMword shamt
, base
;
3179 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3182 base
= state
->Reg
[base
];
3184 shamt
= BITS (7, 11);
3185 switch ((int) BITS (5, 6))
3188 return (base
<< shamt
);
3193 return (base
>> shamt
);
3196 return ((ARMword
) ((long int) base
>> 31L));
3198 return ((ARMword
) ((long int) base
>> (int) shamt
));
3200 if (shamt
== 0) /* its an RRX */
3201 return ((base
>> 1) | (CFLAG
<< 31));
3203 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3205 return (0); /* just to shut up lint */
3208 /***************************************************************************\
3209 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3210 \***************************************************************************/
3213 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3219 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3221 return state
->Reg
[RHSReg
];
3224 /* else immediate */
3225 return BITS (0, 3) | (BITS (8, 11) << 4);
3228 /***************************************************************************\
3229 * This function does the work of loading a word for a LDR instruction. *
3230 \***************************************************************************/
3233 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3239 if (ADDREXCEPT (address
))
3241 INTERNALABORT (address
);
3244 dest
= ARMul_LoadWordN (state
, address
);
3248 return (state
->lateabtSig
);
3251 dest
= ARMul_Align (state
, address
, dest
);
3253 ARMul_Icycles (state
, 1, 0L);
3255 return (DESTReg
!= LHSReg
);
3259 /***************************************************************************\
3260 * This function does the work of loading a halfword. *
3261 \***************************************************************************/
3264 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3271 if (ADDREXCEPT (address
))
3273 INTERNALABORT (address
);
3276 dest
= ARMul_LoadHalfWord (state
, address
);
3280 return (state
->lateabtSig
);
3285 if (dest
& 1 << (16 - 1))
3286 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3289 ARMul_Icycles (state
, 1, 0L);
3290 return (DESTReg
!= LHSReg
);
3295 /***************************************************************************\
3296 * This function does the work of loading a byte for a LDRB instruction. *
3297 \***************************************************************************/
3300 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3306 if (ADDREXCEPT (address
))
3308 INTERNALABORT (address
);
3311 dest
= ARMul_LoadByte (state
, address
);
3315 return (state
->lateabtSig
);
3320 if (dest
& 1 << (8 - 1))
3321 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3324 ARMul_Icycles (state
, 1, 0L);
3325 return (DESTReg
!= LHSReg
);
3328 /***************************************************************************\
3329 * This function does the work of storing a word from a STR instruction. *
3330 \***************************************************************************/
3333 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3338 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3341 ARMul_StoreWordN (state
, address
, DEST
);
3343 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3345 INTERNALABORT (address
);
3346 (void) ARMul_LoadWordN (state
, address
);
3349 ARMul_StoreWordN (state
, address
, DEST
);
3354 return (state
->lateabtSig
);
3360 /***************************************************************************\
3361 * This function does the work of storing a byte for a STRH instruction. *
3362 \***************************************************************************/
3365 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3371 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3375 ARMul_StoreHalfWord (state
, address
, DEST
);
3377 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3379 INTERNALABORT (address
);
3380 (void) ARMul_LoadHalfWord (state
, address
);
3383 ARMul_StoreHalfWord (state
, address
, DEST
);
3389 return (state
->lateabtSig
);
3397 /***************************************************************************\
3398 * This function does the work of storing a byte for a STRB instruction. *
3399 \***************************************************************************/
3402 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
3407 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3410 ARMul_StoreByte (state
, address
, DEST
);
3412 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3414 INTERNALABORT (address
);
3415 (void) ARMul_LoadByte (state
, address
);
3418 ARMul_StoreByte (state
, address
, DEST
);
3423 return (state
->lateabtSig
);
3429 /***************************************************************************\
3430 * This function does the work of loading the registers listed in an LDM *
3431 * instruction, when the S bit is clear. The code here is always increment *
3432 * after, it's up to the caller to get the input address correct and to *
3433 * handle base register modification. *
3434 \***************************************************************************/
3437 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
3443 UNDEF_LSMBaseInListWb
;
3446 if (ADDREXCEPT (address
))
3448 INTERNALABORT (address
);
3451 if (BIT (21) && LHSReg
!= 15)
3454 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3455 dest
= ARMul_LoadWordN (state
, address
);
3456 if (!state
->abortSig
&& !state
->Aborted
)
3457 state
->Reg
[temp
++] = dest
;
3458 else if (!state
->Aborted
)
3459 state
->Aborted
= ARMul_DataAbortV
;
3461 for (; temp
< 16; temp
++) /* S cycles from here on */
3463 { /* load this register */
3465 dest
= ARMul_LoadWordS (state
, address
);
3466 if (!state
->abortSig
&& !state
->Aborted
)
3467 state
->Reg
[temp
] = dest
;
3468 else if (!state
->Aborted
)
3469 state
->Aborted
= ARMul_DataAbortV
;
3472 if (BIT (15) && !state
->Aborted
)
3473 { /* PC is in the reg list */
3475 state
->Reg
[15] = PC
;
3480 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3484 if (BIT (21) && LHSReg
!= 15)
3490 /***************************************************************************\
3491 * This function does the work of loading the registers listed in an LDM *
3492 * instruction, when the S bit is set. The code here is always increment *
3493 * after, it's up to the caller to get the input address correct and to *
3494 * handle base register modification. *
3495 \***************************************************************************/
3498 LoadSMult (ARMul_State
* state
, ARMword instr
,
3499 ARMword address
, ARMword WBBase
)
3505 UNDEF_LSMBaseInListWb
;
3508 if (ADDREXCEPT (address
))
3510 INTERNALABORT (address
);
3514 if (!BIT (15) && state
->Bank
!= USERBANK
)
3516 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* temporary reg bank switch */
3517 UNDEF_LSMUserBankWb
;
3520 if (BIT (21) && LHSReg
!= 15)
3523 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3524 dest
= ARMul_LoadWordN (state
, address
);
3525 if (!state
->abortSig
)
3526 state
->Reg
[temp
++] = dest
;
3527 else if (!state
->Aborted
)
3528 state
->Aborted
= ARMul_DataAbortV
;
3530 for (; temp
< 16; temp
++) /* S cycles from here on */
3532 { /* load this register */
3534 dest
= ARMul_LoadWordS (state
, address
);
3535 if (!state
->abortSig
&& !state
->Aborted
)
3536 state
->Reg
[temp
] = dest
;
3537 else if (!state
->Aborted
)
3538 state
->Aborted
= ARMul_DataAbortV
;
3541 if (BIT (15) && !state
->Aborted
)
3542 { /* PC is in the reg list */
3544 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3546 state
->Cpsr
= GETSPSR (state
->Bank
);
3547 ARMul_CPSRAltered (state
);
3549 state
->Reg
[15] = PC
;
3551 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
3552 { /* protect bits in user mode */
3553 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
3554 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
3555 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
3556 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
3559 ARMul_R15Altered (state
);
3564 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3565 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3567 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3571 if (BIT (21) && LHSReg
!= 15)
3578 /***************************************************************************\
3579 * This function does the work of storing the registers listed in an STM *
3580 * instruction, when the S bit is clear. The code here is always increment *
3581 * after, it's up to the caller to get the input address correct and to *
3582 * handle base register modification. *
3583 \***************************************************************************/
3586 StoreMult (ARMul_State
* state
, ARMword instr
,
3587 ARMword address
, ARMword WBBase
)
3593 UNDEF_LSMBaseInListWb
;
3596 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
3600 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3602 INTERNALABORT (address
);
3608 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3610 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3614 (void) ARMul_LoadWordN (state
, address
);
3615 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3617 { /* save this register */
3619 (void) ARMul_LoadWordS (state
, address
);
3621 if (BIT (21) && LHSReg
!= 15)
3627 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3629 if (state
->abortSig
&& !state
->Aborted
)
3630 state
->Aborted
= ARMul_DataAbortV
;
3632 if (BIT (21) && LHSReg
!= 15)
3635 for (; temp
< 16; temp
++) /* S cycles from here on */
3637 { /* save this register */
3639 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3640 if (state
->abortSig
&& !state
->Aborted
)
3641 state
->Aborted
= ARMul_DataAbortV
;
3649 /***************************************************************************\
3650 * This function does the work of storing the registers listed in an STM *
3651 * instruction when the S bit is set. The code here is always increment *
3652 * after, it's up to the caller to get the input address correct and to *
3653 * handle base register modification. *
3654 \***************************************************************************/
3657 StoreSMult (ARMul_State
* state
, ARMword instr
,
3658 ARMword address
, ARMword WBBase
)
3664 UNDEF_LSMBaseInListWb
;
3667 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3669 INTERNALABORT (address
);
3675 if (state
->Bank
!= USERBANK
)
3677 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* Force User Bank */
3678 UNDEF_LSMUserBankWb
;
3681 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3683 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3687 (void) ARMul_LoadWordN (state
, address
);
3688 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
3690 { /* save this register */
3692 (void) ARMul_LoadWordS (state
, address
);
3694 if (BIT (21) && LHSReg
!= 15)
3700 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
3702 if (state
->abortSig
&& !state
->Aborted
)
3703 state
->Aborted
= ARMul_DataAbortV
;
3705 if (BIT (21) && LHSReg
!= 15)
3708 for (; temp
< 16; temp
++) /* S cycles from here on */
3710 { /* save this register */
3712 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
3713 if (state
->abortSig
&& !state
->Aborted
)
3714 state
->Aborted
= ARMul_DataAbortV
;
3717 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3718 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
3726 /***************************************************************************\
3727 * This function does the work of adding two 32bit values together, and *
3728 * calculating if a carry has occurred. *
3729 \***************************************************************************/
3732 Add32 (ARMword a1
, ARMword a2
, int *carry
)
3734 ARMword result
= (a1
+ a2
);
3735 unsigned int uresult
= (unsigned int) result
;
3736 unsigned int ua1
= (unsigned int) a1
;
3738 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
3739 or (result > RdLo) then we have no carry: */
3740 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
3748 /***************************************************************************\
3749 * This function does the work of multiplying two 32bit values to give a *
3751 \***************************************************************************/
3754 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3756 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
3757 ARMword RdHi
= 0, RdLo
= 0, Rm
;
3758 int scount
; /* cycle count */
3760 nRdHi
= BITS (16, 19);
3761 nRdLo
= BITS (12, 15);
3765 /* Needed to calculate the cycle count: */
3766 Rm
= state
->Reg
[nRm
];
3768 /* Check for illegal operand combinations first: */
3772 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
3774 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
3776 ARMword Rs
= state
->Reg
[nRs
];
3781 /* Compute sign of result and adjust operands if necessary. */
3783 sign
= (Rm
^ Rs
) & 0x80000000;
3785 if (((signed long) Rm
) < 0)
3788 if (((signed long) Rs
) < 0)
3792 /* We can split the 32x32 into four 16x16 operations. This ensures
3793 that we do not lose precision on 32bit only hosts: */
3794 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
3795 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3796 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
3797 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3799 /* We now need to add all of these results together, taking care
3800 to propogate the carries from the additions: */
3801 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
3803 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
3805 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
3809 /* Negate result if necessary. */
3813 if (RdLo
== 0xFFFFFFFF)
3822 state
->Reg
[nRdLo
] = RdLo
;
3823 state
->Reg
[nRdHi
] = RdHi
;
3824 } /* else undefined result */
3826 fprintf (stderr
, "MULTIPLY64 - INVALID ARGUMENTS\n");
3830 /* Ensure that both RdHi and RdLo are used to compute Z, but
3831 don't let RdLo's sign bit make it to N. */
3832 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
3835 /* The cycle count depends on whether the instruction is a signed or
3836 unsigned multiply, and what bits are clear in the multiplier: */
3837 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
3838 Rm
= ~Rm
; /* invert the bits to make the check against zero */
3840 if ((Rm
& 0xFFFFFF00) == 0)
3842 else if ((Rm
& 0xFFFF0000) == 0)
3844 else if ((Rm
& 0xFF000000) == 0)
3852 /***************************************************************************\
3853 * This function does the work of multiplying two 32bit values and adding *
3854 * a 64bit value to give a 64bit result. *
3855 \***************************************************************************/
3858 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
3865 nRdHi
= BITS (16, 19);
3866 nRdLo
= BITS (12, 15);
3868 RdHi
= state
->Reg
[nRdHi
];
3869 RdLo
= state
->Reg
[nRdLo
];
3871 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
3873 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
3874 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
3876 state
->Reg
[nRdLo
] = RdLo
;
3877 state
->Reg
[nRdHi
] = RdHi
;
3881 /* Ensure that both RdHi and RdLo are used to compute Z, but
3882 don't let RdLo's sign bit make it to N. */
3883 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
3886 return scount
+ 1; /* extra cycle for addition */