]>
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
, ARMword address
) ;
30 static unsigned LoadHalfWord(ARMul_State
*state
, ARMword instr
, ARMword address
,int signextend
) ;
31 static unsigned LoadByte(ARMul_State
*state
, ARMword instr
, ARMword address
,int signextend
) ;
32 static unsigned StoreWord(ARMul_State
*state
, ARMword instr
, ARMword address
) ;
33 static unsigned StoreHalfWord(ARMul_State
*state
, ARMword instr
, ARMword address
) ;
34 static unsigned StoreByte(ARMul_State
*state
, ARMword instr
, ARMword address
) ;
35 static void LoadMult(ARMul_State
*state
, ARMword address
, ARMword instr
, ARMword WBBase
) ;
36 static void StoreMult(ARMul_State
*state
, ARMword address
, ARMword instr
, ARMword WBBase
) ;
37 static void LoadSMult(ARMul_State
*state
, ARMword address
, ARMword instr
, ARMword WBBase
) ;
38 static void StoreSMult(ARMul_State
*state
, ARMword address
, ARMword instr
, ARMword WBBase
) ;
39 static unsigned Multiply64(ARMul_State
*state
, ARMword instr
,int signextend
,int scc
) ;
40 static unsigned MultiplyAdd64(ARMul_State
*state
, ARMword instr
,int signextend
,int scc
) ;
42 #define LUNSIGNED (0) /* unsigned operation */
43 #define LSIGNED (1) /* signed operation */
44 #define LDEFAULT (0) /* default : do nothing */
45 #define LSCC (1) /* set condition codes on result */
47 #ifdef NEED_UI_LOOP_HOOK
48 /* How often to run the ui_loop update, when in use */
49 #define UI_LOOP_POLL_INTERVAL 0x32000
51 /* Counter for the ui_loop_hook update */
52 static long ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
54 /* Actual hook to call to run through gdb's gui event loop */
55 extern int (*ui_loop_hook
) (int);
56 #endif /* NEED_UI_LOOP_HOOK */
58 extern int stop_simulator
;
60 /***************************************************************************\
61 * short-hand macros for LDR/STR *
62 \***************************************************************************/
64 /* store post decrement writeback */
67 if (StoreHalfWord(state, instr, lhs)) \
68 LSBase = lhs - GetLS7RHS(state, instr) ;
70 /* store post increment writeback */
73 if (StoreHalfWord(state, instr, lhs)) \
74 LSBase = lhs + GetLS7RHS(state, instr) ;
76 /* store pre decrement */
78 (void)StoreHalfWord(state, instr, LHS - GetLS7RHS(state, instr)) ;
80 /* store pre decrement writeback */
81 #define SHPREDOWNWB() \
82 temp = LHS - GetLS7RHS(state, instr) ; \
83 if (StoreHalfWord(state, instr, temp)) \
86 /* store pre increment */
88 (void)StoreHalfWord(state, instr, LHS + GetLS7RHS(state, instr)) ;
90 /* store pre increment writeback */
92 temp = LHS + GetLS7RHS(state, instr) ; \
93 if (StoreHalfWord(state, instr, temp)) \
96 /* load post decrement writeback */
97 #define LHPOSTDOWN() \
101 switch (BITS(5,6)) { \
103 if (LoadHalfWord(state,instr,lhs,LUNSIGNED)) \
104 LSBase = lhs - GetLS7RHS(state,instr) ; \
107 if (LoadByte(state,instr,lhs,LSIGNED)) \
108 LSBase = lhs - GetLS7RHS(state,instr) ; \
111 if (LoadHalfWord(state,instr,lhs,LSIGNED)) \
112 LSBase = lhs - GetLS7RHS(state,instr) ; \
114 case 0: /* SWP handled elsewhere */ \
123 /* load post increment writeback */
128 switch (BITS(5,6)) { \
130 if (LoadHalfWord(state,instr,lhs,LUNSIGNED)) \
131 LSBase = lhs + GetLS7RHS(state,instr) ; \
134 if (LoadByte(state,instr,lhs,LSIGNED)) \
135 LSBase = lhs + GetLS7RHS(state,instr) ; \
138 if (LoadHalfWord(state,instr,lhs,LSIGNED)) \
139 LSBase = lhs + GetLS7RHS(state,instr) ; \
141 case 0: /* SWP handled elsewhere */ \
150 /* load pre decrement */
151 #define LHPREDOWN() \
154 temp = LHS - GetLS7RHS(state,instr) ; \
155 switch (BITS(5,6)) { \
157 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
160 (void)LoadByte(state,instr,temp,LSIGNED) ; \
163 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
165 case 0: /* SWP handled elsewhere */ \
174 /* load pre decrement writeback */
175 #define LHPREDOWNWB() \
178 temp = LHS - GetLS7RHS(state, instr) ; \
179 switch (BITS(5,6)) { \
181 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
185 if (LoadByte(state,instr,temp,LSIGNED)) \
189 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
192 case 0: /* SWP handled elsewhere */ \
201 /* load pre increment */
205 temp = LHS + GetLS7RHS(state,instr) ; \
206 switch (BITS(5,6)) { \
208 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
211 (void)LoadByte(state,instr,temp,LSIGNED) ; \
214 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
216 case 0: /* SWP handled elsewhere */ \
225 /* load pre increment writeback */
226 #define LHPREUPWB() \
229 temp = LHS + GetLS7RHS(state, instr) ; \
230 switch (BITS(5,6)) { \
232 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
236 if (LoadByte(state,instr,temp,LSIGNED)) \
240 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
243 case 0: /* SWP handled elsewhere */ \
252 /***************************************************************************\
253 * EMULATION of ARM6 *
254 \***************************************************************************/
256 /* The PC pipeline value depends on whether ARM or Thumb instructions
257 are being executed: */
261 ARMword
ARMul_Emulate32(register ARMul_State
*state
)
264 ARMword
ARMul_Emulate26(register ARMul_State
*state
)
267 register ARMword instr
, /* the current instruction */
268 dest
, /* almost the DestBus */
269 temp
, /* ubiquitous third hand */
270 pc
; /* the address of the current instruction */
271 ARMword lhs
, rhs
; /* almost the ABus and BBus */
272 ARMword decoded
, loaded
; /* instruction pipeline */
274 /***************************************************************************\
275 * Execute the next instruction *
276 \***************************************************************************/
278 if (state
->NextInstr
< PRIMEPIPE
) {
279 decoded
= state
->decoded
;
280 loaded
= state
->loaded
;
284 do { /* just keep going */
291 switch (state
->NextInstr
) {
293 state
->Reg
[15] += isize
; /* Advance the pipeline, and an S cycle */
297 loaded
= ARMul_LoadInstrS(state
,pc
+(isize
* 2),isize
) ;
301 state
->Reg
[15] += isize
; /* Advance the pipeline, and an N cycle */
305 loaded
= ARMul_LoadInstrN(state
,pc
+(isize
* 2),isize
) ;
310 pc
+= isize
; /* Program counter advanced, and an S cycle */
313 loaded
= ARMul_LoadInstrS(state
,pc
+(isize
* 2),isize
) ;
318 pc
+= isize
; /* Program counter advanced, and an N cycle */
321 loaded
= ARMul_LoadInstrN(state
,pc
+(isize
* 2),isize
) ;
325 case RESUME
: /* The program counter has been changed */
326 pc
= state
->Reg
[15] ;
328 pc
= pc
& R15PCBITS
;
330 state
->Reg
[15] = pc
+ (isize
* 2) ;
332 instr
= ARMul_ReLoadInstr(state
,pc
,isize
) ;
333 decoded
= ARMul_ReLoadInstr(state
,pc
+ isize
,isize
) ;
334 loaded
= ARMul_ReLoadInstr(state
,pc
+ isize
* 2,isize
) ;
338 default : /* The program counter has been changed */
339 pc
= state
->Reg
[15] ;
341 pc
= pc
& R15PCBITS
;
343 state
->Reg
[15] = pc
+ (isize
* 2) ;
345 instr
= ARMul_LoadInstrN(state
,pc
,isize
) ;
346 decoded
= ARMul_LoadInstrS(state
,pc
+ (isize
),isize
) ;
347 loaded
= ARMul_LoadInstrS(state
,pc
+ (isize
* 2),isize
) ;
352 ARMul_EnvokeEvent(state
) ;
355 /* Enable this for a helpful bit of debugging when tracing is needed. */
356 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
357 if (instr
== 0) abort ();
360 if (state
->Exception
) { /* Any exceptions */
361 if (state
->NresetSig
== LOW
) {
362 ARMul_Abort(state
,ARMul_ResetV
) ;
365 else if (!state
->NfiqSig
&& !FFLAG
) {
366 ARMul_Abort(state
,ARMul_FIQV
) ;
369 else if (!state
->NirqSig
&& !IFLAG
) {
370 ARMul_Abort(state
,ARMul_IRQV
) ;
375 if (state
->CallDebug
> 0) {
376 instr
= ARMul_Debug(state
,pc
,instr
) ;
377 if (state
->Emulate
< ONCE
) {
378 state
->NextInstr
= RESUME
;
382 fprintf(stderr
,"At %08lx Instr %08lx Mode %02lx\n",pc
,instr
,state
->Mode
) ;
387 if (state
->Emulate
< ONCE
) {
388 state
->NextInstr
= RESUME
;
395 /* Provide Thumb instruction decoding. If the processor is in Thumb
396 mode, then we can simply decode the Thumb instruction, and map it
397 to the corresponding ARM instruction (by directly loading the
398 instr variable, and letting the normal ARM simulator
399 execute). There are some caveats to ensure that the correct
400 pipelined PC value is used when executing Thumb code, and also for
401 dealing with the BL instruction. */
402 if (TFLAG
) { /* check if in Thumb mode */
404 switch (ARMul_ThumbDecode(state
,pc
,instr
,&new)) {
406 ARMul_UndefInstr(state
,instr
); /* This is a Thumb instruction */
409 case t_branch
: /* already processed */
412 case t_decoded
: /* ARM instruction available */
413 instr
= new; /* so continue instruction decoding */
419 /***************************************************************************\
420 * Check the condition codes *
421 \***************************************************************************/
422 if ((temp
= TOPBITS(28)) == AL
)
423 goto mainswitch
; /* vile deed in the need for speed */
425 switch ((int)TOPBITS(28)) { /* check the condition code */
426 case AL
: temp
=TRUE
;
428 case NV
: temp
=FALSE
;
430 case EQ
: temp
=ZFLAG
;
432 case NE
: temp
=!ZFLAG
;
434 case VS
: temp
=VFLAG
;
436 case VC
: temp
=!VFLAG
;
438 case MI
: temp
=NFLAG
;
440 case PL
: temp
=!NFLAG
;
442 case CS
: temp
=CFLAG
;
444 case CC
: temp
=!CFLAG
;
446 case HI
: temp
=(CFLAG
&& !ZFLAG
) ;
448 case LS
: temp
=(!CFLAG
|| ZFLAG
) ;
450 case GE
: temp
=((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
)) ;
452 case LT
: temp
=((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) ;
454 case GT
: temp
=((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
)) ;
456 case LE
: temp
=((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
460 /***************************************************************************\
461 * Actual execution of instructions begins here *
462 \***************************************************************************/
464 if (temp
) { /* if the condition codes don't match, stop here */
468 switch ((int)BITS(20,27)) {
470 /***************************************************************************\
471 * Data Processing Register RHS Instructions *
472 \***************************************************************************/
474 case 0x00 : /* AND reg and MUL */
476 if (BITS(4,11) == 0xB) {
477 /* STRH register offset, no write-back, down, post indexed */
481 /* TODO: CHECK: should 0xD and 0xF generate undefined intruction aborts? */
483 if (BITS(4,7) == 9) { /* MUL */
484 rhs
= state
->Reg
[MULRHSReg
] ;
485 if (MULLHSReg
== MULDESTReg
) {
487 state
->Reg
[MULDESTReg
] = 0 ;
489 else if (MULDESTReg
!= 15)
490 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
494 for (dest
= 0, temp
= 0 ; dest
< 32 ; dest
++)
495 if (rhs
& (1L << dest
))
496 temp
= dest
; /* mult takes this many/2 I cycles */
497 ARMul_Icycles(state
,ARMul_MultTable
[temp
],0L) ;
506 case 0x01 : /* ANDS reg and MULS */
508 if ((BITS(4,11) & 0xF9) == 0x9) {
509 /* LDR register offset, no write-back, down, post indexed */
511 /* fall through to rest of decoding */
514 if (BITS(4,7) == 9) { /* MULS */
515 rhs
= state
->Reg
[MULRHSReg
] ;
516 if (MULLHSReg
== MULDESTReg
) {
518 state
->Reg
[MULDESTReg
] = 0 ;
522 else if (MULDESTReg
!= 15) {
523 dest
= state
->Reg
[MULLHSReg
] * rhs
;
524 ARMul_NegZero(state
,dest
) ;
525 state
->Reg
[MULDESTReg
] = dest
;
530 for (dest
= 0, temp
= 0 ; dest
< 32 ; dest
++)
531 if (rhs
& (1L << dest
))
532 temp
= dest
; /* mult takes this many/2 I cycles */
533 ARMul_Icycles(state
,ARMul_MultTable
[temp
],0L) ;
535 else { /* ANDS reg */
542 case 0x02 : /* EOR reg and MLA */
544 if (BITS(4,11) == 0xB) {
545 /* STRH register offset, write-back, down, post indexed */
550 if (BITS(4,7) == 9) { /* MLA */
551 rhs
= state
->Reg
[MULRHSReg
] ;
552 if (MULLHSReg
== MULDESTReg
) {
554 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
] ;
556 else if (MULDESTReg
!= 15)
557 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
] ;
561 for (dest
= 0, temp
= 0 ; dest
< 32 ; dest
++)
562 if (rhs
& (1L << dest
))
563 temp
= dest
; /* mult takes this many/2 I cycles */
564 ARMul_Icycles(state
,ARMul_MultTable
[temp
],0L) ;
573 case 0x03 : /* EORS reg and MLAS */
575 if ((BITS(4,11) & 0xF9) == 0x9) {
576 /* LDR register offset, write-back, down, post-indexed */
578 /* fall through to rest of the decoding */
581 if (BITS(4,7) == 9) { /* MLAS */
582 rhs
= state
->Reg
[MULRHSReg
] ;
583 if (MULLHSReg
== MULDESTReg
) {
585 dest
= state
->Reg
[MULACCReg
] ;
586 ARMul_NegZero(state
,dest
) ;
587 state
->Reg
[MULDESTReg
] = dest
;
589 else if (MULDESTReg
!= 15) {
590 dest
= state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
] ;
591 ARMul_NegZero(state
,dest
) ;
592 state
->Reg
[MULDESTReg
] = dest
;
597 for (dest
= 0, temp
= 0 ; dest
< 32 ; dest
++)
598 if (rhs
& (1L << dest
))
599 temp
= dest
; /* mult takes this many/2 I cycles */
600 ARMul_Icycles(state
,ARMul_MultTable
[temp
],0L) ;
602 else { /* EORS Reg */
609 case 0x04 : /* SUB reg */
611 if (BITS(4,7) == 0xB) {
612 /* STRH immediate offset, no write-back, down, post indexed */
622 case 0x05 : /* SUBS reg */
624 if ((BITS(4,7) & 0x9) == 0x9) {
625 /* LDR immediate offset, no write-back, down, post indexed */
627 /* fall through to the rest of the instruction decoding */
633 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
634 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
635 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
644 case 0x06 : /* RSB reg */
646 if (BITS(4,7) == 0xB) {
647 /* STRH immediate offset, write-back, down, post indexed */
657 case 0x07 : /* RSBS reg */
659 if ((BITS(4,7) & 0x9) == 0x9) {
660 /* LDR immediate offset, write-back, down, post indexed */
662 /* fall through to remainder of instruction decoding */
668 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31)) {
669 ARMul_SubCarry(state
,rhs
,lhs
,dest
) ;
670 ARMul_SubOverflow(state
,rhs
,lhs
,dest
) ;
679 case 0x08 : /* ADD reg */
681 if (BITS(4,11) == 0xB) {
682 /* STRH register offset, no write-back, up, post indexed */
688 if (BITS(4,7) == 0x9) { /* MULL */
690 ARMul_Icycles(state
,Multiply64(state
,instr
,LUNSIGNED
,LDEFAULT
),0L) ;
699 case 0x09 : /* ADDS reg */
701 if ((BITS(4,11) & 0xF9) == 0x9) {
702 /* LDR register offset, no write-back, up, post indexed */
704 /* fall through to remaining instruction decoding */
708 if (BITS(4,7) == 0x9) { /* MULL */
710 ARMul_Icycles(state
,Multiply64(state
,instr
,LUNSIGNED
,LSCC
),0L) ;
718 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
720 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
721 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
731 case 0x0a : /* ADC reg */
733 if (BITS(4,11) == 0xB) {
734 /* STRH register offset, write-back, up, post-indexed */
740 if (BITS(4,7) == 0x9) { /* MULL */
742 ARMul_Icycles(state
,MultiplyAdd64(state
,instr
,LUNSIGNED
,LDEFAULT
),0L) ;
747 dest
= LHS
+ rhs
+ CFLAG
;
751 case 0x0b : /* ADCS reg */
753 if ((BITS(4,11) & 0xF9) == 0x9) {
754 /* LDR register offset, write-back, up, post indexed */
756 /* fall through to remaining instruction decoding */
760 if (BITS(4,7) == 0x9) { /* MULL */
762 ARMul_Icycles(state
,MultiplyAdd64(state
,instr
,LUNSIGNED
,LSCC
),0L) ;
768 dest
= lhs
+ rhs
+ CFLAG
;
770 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
772 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
773 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
783 case 0x0c : /* SBC reg */
785 if (BITS(4,7) == 0xB) {
786 /* STRH immediate offset, no write-back, up post indexed */
792 if (BITS(4,7) == 0x9) { /* MULL */
794 ARMul_Icycles(state
,Multiply64(state
,instr
,LSIGNED
,LDEFAULT
),0L) ;
799 dest
= LHS
- rhs
- !CFLAG
;
803 case 0x0d : /* SBCS reg */
805 if ((BITS(4,7) & 0x9) == 0x9) {
806 /* LDR immediate offset, no write-back, up, post indexed */
811 if (BITS(4,7) == 0x9) { /* MULL */
813 ARMul_Icycles(state
,Multiply64(state
,instr
,LSIGNED
,LSCC
),0L) ;
819 dest
= lhs
- rhs
- !CFLAG
;
820 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
821 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
822 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
831 case 0x0e : /* RSC reg */
833 if (BITS(4,7) == 0xB) {
834 /* STRH immediate offset, write-back, up, post indexed */
840 if (BITS(4,7) == 0x9) { /* MULL */
842 ARMul_Icycles(state
,MultiplyAdd64(state
,instr
,LSIGNED
,LDEFAULT
),0L) ;
847 dest
= rhs
- LHS
- !CFLAG
;
851 case 0x0f : /* RSCS reg */
853 if ((BITS(4,7) & 0x9) == 0x9) {
854 /* LDR immediate offset, write-back, up, post indexed */
856 /* fall through to remaining instruction decoding */
860 if (BITS(4,7) == 0x9) { /* MULL */
862 ARMul_Icycles(state
,MultiplyAdd64(state
,instr
,LSIGNED
,LSCC
),0L) ;
868 dest
= rhs
- lhs
- !CFLAG
;
869 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31)) {
870 ARMul_SubCarry(state
,rhs
,lhs
,dest
) ;
871 ARMul_SubOverflow(state
,rhs
,lhs
,dest
) ;
880 case 0x10 : /* TST reg and MRS CPSR and SWP word */
883 if (BITS(4,11) == 0xB) {
884 /* STRH register offset, no write-back, down, pre indexed */
889 if (BITS(4,11) == 9) { /* SWP */
894 if (VECTORACCESS(temp
) || ADDREXCEPT(temp
)) {
895 INTERNALABORT(temp
) ;
896 (void)ARMul_LoadWordN(state
,temp
) ;
897 (void)ARMul_LoadWordN(state
,temp
) ;
901 dest
= ARMul_SwapWord(state
,temp
,state
->Reg
[RHSReg
]) ;
903 DEST
= ARMul_Align(state
,temp
,dest
) ;
906 if (state
->abortSig
|| state
->Aborted
) {
910 else if ((BITS(0,11)==0) && (LHSReg
==15)) { /* MRS CPSR */
912 DEST
= ECC
| EINT
| EMODE
;
919 case 0x11 : /* TSTP reg */
921 if ((BITS(4,11) & 0xF9) == 0x9) {
922 /* LDR register offset, no write-back, down, pre indexed */
924 /* continue with remaining instruction decode */
927 if (DESTReg
== 15) { /* TSTP reg */
929 state
->Cpsr
= GETSPSR(state
->Bank
) ;
930 ARMul_CPSRAltered(state
) ;
940 ARMul_NegZero(state
,dest
) ;
944 case 0x12 : /* TEQ reg and MSR reg to CPSR (ARM6) */
946 if (BITS(4,11) == 0xB) {
947 /* STRH register offset, write-back, down, pre indexed */
953 if (BITS(4,27)==0x12FFF1) { /* BX */
954 /* Branch to the address in RHSReg. If bit0 of
955 destination address is 1 then switch to Thumb mode: */
956 ARMword addr
= state
->Reg
[RHSReg
];
958 /* If we read the PC then the bottom bit is clear */
959 if (RHSReg
== 15) addr
&= ~1;
961 /* Enable this for a helpful bit of debugging when
962 GDB is not yet fully working...
963 fprintf (stderr, "BX at %x to %x (go %s)\n",
964 state->Reg[15], addr, (addr & 1) ? "thumb": "arm" ); */
966 if (addr
& (1 << 0)) { /* Thumb bit */
968 state
->Reg
[15] = addr
& 0xfffffffe;
969 /* NOTE: The other CPSR flag setting blocks do not
970 seem to update the state->Cpsr state, but just do
971 the explicit flag. The copy from the seperate
972 flags to the register must happen later. */
976 state
->Reg
[15] = addr
& 0xfffffffc;
981 if (DESTReg
==15 && BITS(17,18)==0) { /* MSR reg to CPSR */
984 ARMul_FixCPSR(state
,instr
,temp
) ;
991 case 0x13 : /* TEQP reg */
993 if ((BITS(4,11) & 0xF9) == 0x9) {
994 /* LDR register offset, write-back, down, pre indexed */
996 /* continue with remaining instruction decode */
999 if (DESTReg
== 15) { /* TEQP reg */
1001 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1002 ARMul_CPSRAltered(state
) ;
1009 else { /* TEQ Reg */
1012 ARMul_NegZero(state
,dest
) ;
1016 case 0x14 : /* CMP reg and MRS SPSR and SWP byte */
1018 if (BITS(4,7) == 0xB) {
1019 /* STRH immediate offset, no write-back, down, pre indexed */
1024 if (BITS(4,11) == 9) { /* SWP */
1029 if (VECTORACCESS(temp
) || ADDREXCEPT(temp
)) {
1030 INTERNALABORT(temp
) ;
1031 (void)ARMul_LoadByte(state
,temp
) ;
1032 (void)ARMul_LoadByte(state
,temp
) ;
1036 DEST
= ARMul_SwapByte(state
,temp
,state
->Reg
[RHSReg
]) ;
1037 if (state
->abortSig
|| state
->Aborted
) {
1041 else if ((BITS(0,11)==0) && (LHSReg
==15)) { /* MRS SPSR */
1043 DEST
= GETSPSR(state
->Bank
) ;
1050 case 0x15 : /* CMPP reg */
1052 if ((BITS(4,7) & 0x9) == 0x9) {
1053 /* LDR immediate offset, no write-back, down, pre indexed */
1055 /* continue with remaining instruction decode */
1058 if (DESTReg
== 15) { /* CMPP reg */
1060 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1061 ARMul_CPSRAltered(state
) ;
1068 else { /* CMP reg */
1072 ARMul_NegZero(state
,dest
) ;
1073 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1074 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1075 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1084 case 0x16 : /* CMN reg and MSR reg to SPSR */
1086 if (BITS(4,7) == 0xB) {
1087 /* STRH immediate offset, write-back, down, pre indexed */
1092 if (DESTReg
==15 && BITS(17,18)==0) { /* MSR */
1094 ARMul_FixSPSR(state
,instr
,DPRegRHS
);
1101 case 0x17 : /* CMNP reg */
1103 if ((BITS(4,7) & 0x9) == 0x9) {
1104 /* LDR immediate offset, write-back, down, pre indexed */
1106 /* continue with remaining instruction decoding */
1109 if (DESTReg
== 15) {
1111 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1112 ARMul_CPSRAltered(state
) ;
1120 else { /* CMN reg */
1125 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1126 ASSIGNN(NEG(dest
)) ;
1127 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1128 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1138 case 0x18 : /* ORR reg */
1140 if (BITS(4,11) == 0xB) {
1141 /* STRH register offset, no write-back, up, pre indexed */
1151 case 0x19 : /* ORRS reg */
1153 if ((BITS(4,11) & 0xF9) == 0x9) {
1154 /* LDR register offset, no write-back, up, pre indexed */
1156 /* continue with remaining instruction decoding */
1164 case 0x1a : /* MOV reg */
1166 if (BITS(4,11) == 0xB) {
1167 /* STRH register offset, write-back, up, pre indexed */
1176 case 0x1b : /* MOVS reg */
1178 if ((BITS(4,11) & 0xF9) == 0x9) {
1179 /* LDR register offset, write-back, up, pre indexed */
1181 /* continue with remaining instruction decoding */
1188 case 0x1c : /* BIC reg */
1190 if (BITS(4,7) == 0xB) {
1191 /* STRH immediate offset, no write-back, up, pre indexed */
1201 case 0x1d : /* BICS reg */
1203 if ((BITS(4,7) & 0x9) == 0x9) {
1204 /* LDR immediate offset, no write-back, up, pre indexed */
1206 /* continue with instruction decoding */
1214 case 0x1e : /* MVN reg */
1216 if (BITS(4,7) == 0xB) {
1217 /* STRH immediate offset, write-back, up, pre indexed */
1226 case 0x1f : /* MVNS reg */
1228 if ((BITS(4,7) & 0x9) == 0x9) {
1229 /* LDR immediate offset, write-back, up, pre indexed */
1231 /* continue instruction decoding */
1238 /***************************************************************************\
1239 * Data Processing Immediate RHS Instructions *
1240 \***************************************************************************/
1242 case 0x20 : /* AND immed */
1243 dest
= LHS
& DPImmRHS
;
1247 case 0x21 : /* ANDS immed */
1253 case 0x22 : /* EOR immed */
1254 dest
= LHS
^ DPImmRHS
;
1258 case 0x23 : /* EORS immed */
1264 case 0x24 : /* SUB immed */
1265 dest
= LHS
- DPImmRHS
;
1269 case 0x25 : /* SUBS immed */
1273 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1274 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1275 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1284 case 0x26 : /* RSB immed */
1285 dest
= DPImmRHS
- LHS
;
1289 case 0x27 : /* RSBS immed */
1293 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31)) {
1294 ARMul_SubCarry(state
,rhs
,lhs
,dest
) ;
1295 ARMul_SubOverflow(state
,rhs
,lhs
,dest
) ;
1304 case 0x28 : /* ADD immed */
1305 dest
= LHS
+ DPImmRHS
;
1309 case 0x29 : /* ADDS immed */
1314 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1315 ASSIGNN(NEG(dest
)) ;
1316 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1317 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1327 case 0x2a : /* ADC immed */
1328 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1332 case 0x2b : /* ADCS immed */
1335 dest
= lhs
+ rhs
+ CFLAG
;
1337 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1338 ASSIGNN(NEG(dest
)) ;
1339 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1340 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1350 case 0x2c : /* SBC immed */
1351 dest
= LHS
- DPImmRHS
- !CFLAG
;
1355 case 0x2d : /* SBCS immed */
1358 dest
= lhs
- rhs
- !CFLAG
;
1359 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1360 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1361 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1370 case 0x2e : /* RSC immed */
1371 dest
= DPImmRHS
- LHS
- !CFLAG
;
1375 case 0x2f : /* RSCS immed */
1378 dest
= rhs
- lhs
- !CFLAG
;
1379 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31)) {
1380 ARMul_SubCarry(state
,rhs
,lhs
,dest
) ;
1381 ARMul_SubOverflow(state
,rhs
,lhs
,dest
) ;
1390 case 0x30 : /* TST immed */
1394 case 0x31 : /* TSTP immed */
1395 if (DESTReg
== 15) { /* TSTP immed */
1397 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1398 ARMul_CPSRAltered(state
) ;
1400 temp
= LHS
& DPImmRHS
;
1405 DPSImmRHS
; /* TST immed */
1407 ARMul_NegZero(state
,dest
) ;
1411 case 0x32 : /* TEQ immed and MSR immed to CPSR */
1412 if (DESTReg
==15 && BITS(17,18)==0) { /* MSR immed to CPSR */
1413 ARMul_FixCPSR(state
,instr
,DPImmRHS
) ;
1420 case 0x33 : /* TEQP immed */
1421 if (DESTReg
== 15) { /* TEQP immed */
1423 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1424 ARMul_CPSRAltered(state
) ;
1426 temp
= LHS
^ DPImmRHS
;
1431 DPSImmRHS
; /* TEQ immed */
1433 ARMul_NegZero(state
,dest
) ;
1437 case 0x34 : /* CMP immed */
1441 case 0x35 : /* CMPP immed */
1442 if (DESTReg
== 15) { /* CMPP immed */
1444 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1445 ARMul_CPSRAltered(state
) ;
1447 temp
= LHS
- DPImmRHS
;
1453 lhs
= LHS
; /* CMP immed */
1456 ARMul_NegZero(state
,dest
) ;
1457 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1458 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1459 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1468 case 0x36 : /* CMN immed and MSR immed to SPSR */
1469 if (DESTReg
==15 && BITS(17,18)==0) /* MSR */
1470 ARMul_FixSPSR(state
, instr
, DPImmRHS
) ;
1476 case 0x37 : /* CMNP immed */
1477 if (DESTReg
== 15) { /* CMNP immed */
1479 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1480 ARMul_CPSRAltered(state
) ;
1482 temp
= LHS
+ DPImmRHS
;
1488 lhs
= LHS
; /* CMN immed */
1492 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1493 ASSIGNN(NEG(dest
)) ;
1494 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1495 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1505 case 0x38 : /* ORR immed */
1506 dest
= LHS
| DPImmRHS
;
1510 case 0x39 : /* ORRS immed */
1516 case 0x3a : /* MOV immed */
1521 case 0x3b : /* MOVS immed */
1526 case 0x3c : /* BIC immed */
1527 dest
= LHS
& ~DPImmRHS
;
1531 case 0x3d : /* BICS immed */
1537 case 0x3e : /* MVN immed */
1542 case 0x3f : /* MVNS immed */
1547 /***************************************************************************\
1548 * Single Data Transfer Immediate RHS Instructions *
1549 \***************************************************************************/
1551 case 0x40 : /* Store Word, No WriteBack, Post Dec, Immed */
1553 if (StoreWord(state
,instr
,lhs
))
1554 LSBase
= lhs
- LSImmRHS
;
1557 case 0x41 : /* Load Word, No WriteBack, Post Dec, Immed */
1559 if (LoadWord(state
,instr
,lhs
))
1560 LSBase
= lhs
- LSImmRHS
;
1563 case 0x42 : /* Store Word, WriteBack, Post Dec, Immed */
1564 UNDEF_LSRBaseEQDestWb
;
1567 temp
= lhs
- LSImmRHS
;
1568 state
->NtransSig
= LOW
;
1569 if (StoreWord(state
,instr
,lhs
))
1571 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1574 case 0x43 : /* Load Word, WriteBack, Post Dec, Immed */
1575 UNDEF_LSRBaseEQDestWb
;
1578 state
->NtransSig
= LOW
;
1579 if (LoadWord(state
,instr
,lhs
))
1580 LSBase
= lhs
- LSImmRHS
;
1581 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1584 case 0x44 : /* Store Byte, No WriteBack, Post Dec, Immed */
1586 if (StoreByte(state
,instr
,lhs
))
1587 LSBase
= lhs
- LSImmRHS
;
1590 case 0x45 : /* Load Byte, No WriteBack, Post Dec, Immed */
1592 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1593 LSBase
= lhs
- LSImmRHS
;
1596 case 0x46 : /* Store Byte, WriteBack, Post Dec, Immed */
1597 UNDEF_LSRBaseEQDestWb
;
1600 state
->NtransSig
= LOW
;
1601 if (StoreByte(state
,instr
,lhs
))
1602 LSBase
= lhs
- LSImmRHS
;
1603 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1606 case 0x47 : /* Load Byte, WriteBack, Post Dec, Immed */
1607 UNDEF_LSRBaseEQDestWb
;
1610 state
->NtransSig
= LOW
;
1611 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1612 LSBase
= lhs
- LSImmRHS
;
1613 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1616 case 0x48 : /* Store Word, No WriteBack, Post Inc, Immed */
1618 if (StoreWord(state
,instr
,lhs
))
1619 LSBase
= lhs
+ LSImmRHS
;
1622 case 0x49 : /* Load Word, No WriteBack, Post Inc, Immed */
1624 if (LoadWord(state
,instr
,lhs
))
1625 LSBase
= lhs
+ LSImmRHS
;
1628 case 0x4a : /* Store Word, WriteBack, Post Inc, Immed */
1629 UNDEF_LSRBaseEQDestWb
;
1632 state
->NtransSig
= LOW
;
1633 if (StoreWord(state
,instr
,lhs
))
1634 LSBase
= lhs
+ LSImmRHS
;
1635 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1638 case 0x4b : /* Load Word, WriteBack, Post Inc, Immed */
1639 UNDEF_LSRBaseEQDestWb
;
1642 state
->NtransSig
= LOW
;
1643 if (LoadWord(state
,instr
,lhs
))
1644 LSBase
= lhs
+ LSImmRHS
;
1645 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1648 case 0x4c : /* Store Byte, No WriteBack, Post Inc, Immed */
1650 if (StoreByte(state
,instr
,lhs
))
1651 LSBase
= lhs
+ LSImmRHS
;
1654 case 0x4d : /* Load Byte, No WriteBack, Post Inc, Immed */
1656 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1657 LSBase
= lhs
+ LSImmRHS
;
1660 case 0x4e : /* Store Byte, WriteBack, Post Inc, Immed */
1661 UNDEF_LSRBaseEQDestWb
;
1664 state
->NtransSig
= LOW
;
1665 if (StoreByte(state
,instr
,lhs
))
1666 LSBase
= lhs
+ LSImmRHS
;
1667 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1670 case 0x4f : /* Load Byte, WriteBack, Post Inc, Immed */
1671 UNDEF_LSRBaseEQDestWb
;
1674 state
->NtransSig
= LOW
;
1675 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1676 LSBase
= lhs
+ LSImmRHS
;
1677 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1681 case 0x50 : /* Store Word, No WriteBack, Pre Dec, Immed */
1682 (void)StoreWord(state
,instr
,LHS
- LSImmRHS
) ;
1685 case 0x51 : /* Load Word, No WriteBack, Pre Dec, Immed */
1686 (void)LoadWord(state
,instr
,LHS
- LSImmRHS
) ;
1689 case 0x52 : /* Store Word, WriteBack, Pre Dec, Immed */
1690 UNDEF_LSRBaseEQDestWb
;
1692 temp
= LHS
- LSImmRHS
;
1693 if (StoreWord(state
,instr
,temp
))
1697 case 0x53 : /* Load Word, WriteBack, Pre Dec, Immed */
1698 UNDEF_LSRBaseEQDestWb
;
1700 temp
= LHS
- LSImmRHS
;
1701 if (LoadWord(state
,instr
,temp
))
1705 case 0x54 : /* Store Byte, No WriteBack, Pre Dec, Immed */
1706 (void)StoreByte(state
,instr
,LHS
- LSImmRHS
) ;
1709 case 0x55 : /* Load Byte, No WriteBack, Pre Dec, Immed */
1710 (void)LoadByte(state
,instr
,LHS
- LSImmRHS
,LUNSIGNED
) ;
1713 case 0x56 : /* Store Byte, WriteBack, Pre Dec, Immed */
1714 UNDEF_LSRBaseEQDestWb
;
1716 temp
= LHS
- LSImmRHS
;
1717 if (StoreByte(state
,instr
,temp
))
1721 case 0x57 : /* Load Byte, WriteBack, Pre Dec, Immed */
1722 UNDEF_LSRBaseEQDestWb
;
1724 temp
= LHS
- LSImmRHS
;
1725 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
1729 case 0x58 : /* Store Word, No WriteBack, Pre Inc, Immed */
1730 (void)StoreWord(state
,instr
,LHS
+ LSImmRHS
) ;
1733 case 0x59 : /* Load Word, No WriteBack, Pre Inc, Immed */
1734 (void)LoadWord(state
,instr
,LHS
+ LSImmRHS
) ;
1737 case 0x5a : /* Store Word, WriteBack, Pre Inc, Immed */
1738 UNDEF_LSRBaseEQDestWb
;
1740 temp
= LHS
+ LSImmRHS
;
1741 if (StoreWord(state
,instr
,temp
))
1745 case 0x5b : /* Load Word, WriteBack, Pre Inc, Immed */
1746 UNDEF_LSRBaseEQDestWb
;
1748 temp
= LHS
+ LSImmRHS
;
1749 if (LoadWord(state
,instr
,temp
))
1753 case 0x5c : /* Store Byte, No WriteBack, Pre Inc, Immed */
1754 (void)StoreByte(state
,instr
,LHS
+ LSImmRHS
) ;
1757 case 0x5d : /* Load Byte, No WriteBack, Pre Inc, Immed */
1758 (void)LoadByte(state
,instr
,LHS
+ LSImmRHS
,LUNSIGNED
) ;
1761 case 0x5e : /* Store Byte, WriteBack, Pre Inc, Immed */
1762 UNDEF_LSRBaseEQDestWb
;
1764 temp
= LHS
+ LSImmRHS
;
1765 if (StoreByte(state
,instr
,temp
))
1769 case 0x5f : /* Load Byte, WriteBack, Pre Inc, Immed */
1770 UNDEF_LSRBaseEQDestWb
;
1772 temp
= LHS
+ LSImmRHS
;
1773 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
1777 /***************************************************************************\
1778 * Single Data Transfer Register RHS Instructions *
1779 \***************************************************************************/
1781 case 0x60 : /* Store Word, No WriteBack, Post Dec, Reg */
1783 ARMul_UndefInstr(state
,instr
) ;
1786 UNDEF_LSRBaseEQOffWb
;
1787 UNDEF_LSRBaseEQDestWb
;
1791 if (StoreWord(state
,instr
,lhs
))
1792 LSBase
= lhs
- LSRegRHS
;
1795 case 0x61 : /* Load Word, No WriteBack, Post Dec, Reg */
1797 ARMul_UndefInstr(state
,instr
) ;
1800 UNDEF_LSRBaseEQOffWb
;
1801 UNDEF_LSRBaseEQDestWb
;
1805 if (LoadWord(state
,instr
,lhs
))
1806 LSBase
= lhs
- LSRegRHS
;
1809 case 0x62 : /* Store Word, WriteBack, Post Dec, Reg */
1811 ARMul_UndefInstr(state
,instr
) ;
1814 UNDEF_LSRBaseEQOffWb
;
1815 UNDEF_LSRBaseEQDestWb
;
1819 state
->NtransSig
= LOW
;
1820 if (StoreWord(state
,instr
,lhs
))
1821 LSBase
= lhs
- LSRegRHS
;
1822 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1825 case 0x63 : /* Load Word, WriteBack, Post Dec, Reg */
1827 ARMul_UndefInstr(state
,instr
) ;
1830 UNDEF_LSRBaseEQOffWb
;
1831 UNDEF_LSRBaseEQDestWb
;
1835 state
->NtransSig
= LOW
;
1836 if (LoadWord(state
,instr
,lhs
))
1837 LSBase
= lhs
- LSRegRHS
;
1838 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1841 case 0x64 : /* Store Byte, No WriteBack, Post Dec, Reg */
1843 ARMul_UndefInstr(state
,instr
) ;
1846 UNDEF_LSRBaseEQOffWb
;
1847 UNDEF_LSRBaseEQDestWb
;
1851 if (StoreByte(state
,instr
,lhs
))
1852 LSBase
= lhs
- LSRegRHS
;
1855 case 0x65 : /* Load Byte, No WriteBack, Post Dec, Reg */
1857 ARMul_UndefInstr(state
,instr
) ;
1860 UNDEF_LSRBaseEQOffWb
;
1861 UNDEF_LSRBaseEQDestWb
;
1865 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1866 LSBase
= lhs
- LSRegRHS
;
1869 case 0x66 : /* Store Byte, WriteBack, Post Dec, Reg */
1871 ARMul_UndefInstr(state
,instr
) ;
1874 UNDEF_LSRBaseEQOffWb
;
1875 UNDEF_LSRBaseEQDestWb
;
1879 state
->NtransSig
= LOW
;
1880 if (StoreByte(state
,instr
,lhs
))
1881 LSBase
= lhs
- LSRegRHS
;
1882 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1885 case 0x67 : /* Load Byte, WriteBack, Post Dec, Reg */
1887 ARMul_UndefInstr(state
,instr
) ;
1890 UNDEF_LSRBaseEQOffWb
;
1891 UNDEF_LSRBaseEQDestWb
;
1895 state
->NtransSig
= LOW
;
1896 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1897 LSBase
= lhs
- LSRegRHS
;
1898 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1901 case 0x68 : /* Store Word, No WriteBack, Post Inc, Reg */
1903 ARMul_UndefInstr(state
,instr
) ;
1906 UNDEF_LSRBaseEQOffWb
;
1907 UNDEF_LSRBaseEQDestWb
;
1911 if (StoreWord(state
,instr
,lhs
))
1912 LSBase
= lhs
+ LSRegRHS
;
1915 case 0x69 : /* Load Word, No WriteBack, Post Inc, Reg */
1917 ARMul_UndefInstr(state
,instr
) ;
1920 UNDEF_LSRBaseEQOffWb
;
1921 UNDEF_LSRBaseEQDestWb
;
1925 if (LoadWord(state
,instr
,lhs
))
1926 LSBase
= lhs
+ LSRegRHS
;
1929 case 0x6a : /* Store Word, WriteBack, Post Inc, Reg */
1931 ARMul_UndefInstr(state
,instr
) ;
1934 UNDEF_LSRBaseEQOffWb
;
1935 UNDEF_LSRBaseEQDestWb
;
1939 state
->NtransSig
= LOW
;
1940 if (StoreWord(state
,instr
,lhs
))
1941 LSBase
= lhs
+ LSRegRHS
;
1942 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1945 case 0x6b : /* Load Word, WriteBack, Post Inc, Reg */
1947 ARMul_UndefInstr(state
,instr
) ;
1950 UNDEF_LSRBaseEQOffWb
;
1951 UNDEF_LSRBaseEQDestWb
;
1955 state
->NtransSig
= LOW
;
1956 if (LoadWord(state
,instr
,lhs
))
1957 LSBase
= lhs
+ LSRegRHS
;
1958 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1961 case 0x6c : /* Store Byte, No WriteBack, Post Inc, Reg */
1963 ARMul_UndefInstr(state
,instr
) ;
1966 UNDEF_LSRBaseEQOffWb
;
1967 UNDEF_LSRBaseEQDestWb
;
1971 if (StoreByte(state
,instr
,lhs
))
1972 LSBase
= lhs
+ LSRegRHS
;
1975 case 0x6d : /* Load Byte, No WriteBack, Post Inc, Reg */
1977 ARMul_UndefInstr(state
,instr
) ;
1980 UNDEF_LSRBaseEQOffWb
;
1981 UNDEF_LSRBaseEQDestWb
;
1985 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1986 LSBase
= lhs
+ LSRegRHS
;
1989 case 0x6e : /* Store Byte, WriteBack, Post Inc, Reg */
1991 ARMul_UndefInstr(state
,instr
) ;
1994 UNDEF_LSRBaseEQOffWb
;
1995 UNDEF_LSRBaseEQDestWb
;
1999 state
->NtransSig
= LOW
;
2000 if (StoreByte(state
,instr
,lhs
))
2001 LSBase
= lhs
+ LSRegRHS
;
2002 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
2005 case 0x6f : /* Load Byte, WriteBack, Post Inc, Reg */
2007 ARMul_UndefInstr(state
,instr
) ;
2010 UNDEF_LSRBaseEQOffWb
;
2011 UNDEF_LSRBaseEQDestWb
;
2015 state
->NtransSig
= LOW
;
2016 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
2017 LSBase
= lhs
+ LSRegRHS
;
2018 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
2022 case 0x70 : /* Store Word, No WriteBack, Pre Dec, Reg */
2024 ARMul_UndefInstr(state
,instr
) ;
2027 (void)StoreWord(state
,instr
,LHS
- LSRegRHS
) ;
2030 case 0x71 : /* Load Word, No WriteBack, Pre Dec, Reg */
2032 ARMul_UndefInstr(state
,instr
) ;
2035 (void)LoadWord(state
,instr
,LHS
- LSRegRHS
) ;
2038 case 0x72 : /* Store Word, WriteBack, Pre Dec, Reg */
2040 ARMul_UndefInstr(state
,instr
) ;
2043 UNDEF_LSRBaseEQOffWb
;
2044 UNDEF_LSRBaseEQDestWb
;
2047 temp
= LHS
- LSRegRHS
;
2048 if (StoreWord(state
,instr
,temp
))
2052 case 0x73 : /* Load Word, WriteBack, Pre Dec, Reg */
2054 ARMul_UndefInstr(state
,instr
) ;
2057 UNDEF_LSRBaseEQOffWb
;
2058 UNDEF_LSRBaseEQDestWb
;
2061 temp
= LHS
- LSRegRHS
;
2062 if (LoadWord(state
,instr
,temp
))
2066 case 0x74 : /* Store Byte, No WriteBack, Pre Dec, Reg */
2068 ARMul_UndefInstr(state
,instr
) ;
2071 (void)StoreByte(state
,instr
,LHS
- LSRegRHS
) ;
2074 case 0x75 : /* Load Byte, No WriteBack, Pre Dec, Reg */
2076 ARMul_UndefInstr(state
,instr
) ;
2079 (void)LoadByte(state
,instr
,LHS
- LSRegRHS
,LUNSIGNED
) ;
2082 case 0x76 : /* Store Byte, WriteBack, Pre Dec, Reg */
2084 ARMul_UndefInstr(state
,instr
) ;
2087 UNDEF_LSRBaseEQOffWb
;
2088 UNDEF_LSRBaseEQDestWb
;
2091 temp
= LHS
- LSRegRHS
;
2092 if (StoreByte(state
,instr
,temp
))
2096 case 0x77 : /* Load Byte, WriteBack, Pre Dec, Reg */
2098 ARMul_UndefInstr(state
,instr
) ;
2101 UNDEF_LSRBaseEQOffWb
;
2102 UNDEF_LSRBaseEQDestWb
;
2105 temp
= LHS
- LSRegRHS
;
2106 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
2110 case 0x78 : /* Store Word, No WriteBack, Pre Inc, Reg */
2112 ARMul_UndefInstr(state
,instr
) ;
2115 (void)StoreWord(state
,instr
,LHS
+ LSRegRHS
) ;
2118 case 0x79 : /* Load Word, No WriteBack, Pre Inc, Reg */
2120 ARMul_UndefInstr(state
,instr
) ;
2123 (void)LoadWord(state
,instr
,LHS
+ LSRegRHS
) ;
2126 case 0x7a : /* Store Word, WriteBack, Pre Inc, Reg */
2128 ARMul_UndefInstr(state
,instr
) ;
2131 UNDEF_LSRBaseEQOffWb
;
2132 UNDEF_LSRBaseEQDestWb
;
2135 temp
= LHS
+ LSRegRHS
;
2136 if (StoreWord(state
,instr
,temp
))
2140 case 0x7b : /* Load Word, WriteBack, Pre Inc, Reg */
2142 ARMul_UndefInstr(state
,instr
) ;
2145 UNDEF_LSRBaseEQOffWb
;
2146 UNDEF_LSRBaseEQDestWb
;
2149 temp
= LHS
+ LSRegRHS
;
2150 if (LoadWord(state
,instr
,temp
))
2154 case 0x7c : /* Store Byte, No WriteBack, Pre Inc, Reg */
2156 ARMul_UndefInstr(state
,instr
) ;
2159 (void)StoreByte(state
,instr
,LHS
+ LSRegRHS
) ;
2162 case 0x7d : /* Load Byte, No WriteBack, Pre Inc, Reg */
2164 ARMul_UndefInstr(state
,instr
) ;
2167 (void)LoadByte(state
,instr
,LHS
+ LSRegRHS
,LUNSIGNED
) ;
2170 case 0x7e : /* Store Byte, WriteBack, Pre Inc, Reg */
2172 ARMul_UndefInstr(state
,instr
) ;
2175 UNDEF_LSRBaseEQOffWb
;
2176 UNDEF_LSRBaseEQDestWb
;
2179 temp
= LHS
+ LSRegRHS
;
2180 if (StoreByte(state
,instr
,temp
))
2184 case 0x7f : /* Load Byte, WriteBack, Pre Inc, Reg */
2187 /* Check for the special breakpoint opcode.
2188 This value should correspond to the value defined
2189 as ARM_BE_BREAKPOINT in gdb/arm-tdep.c. */
2190 if (BITS (0,19) == 0xfdefe)
2192 if (! ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2193 ARMul_Abort (state
, ARMul_SWIV
);
2196 ARMul_UndefInstr(state
,instr
) ;
2199 UNDEF_LSRBaseEQOffWb
;
2200 UNDEF_LSRBaseEQDestWb
;
2203 temp
= LHS
+ LSRegRHS
;
2204 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
2208 /***************************************************************************\
2209 * Multiple Data Transfer Instructions *
2210 \***************************************************************************/
2212 case 0x80 : /* Store, No WriteBack, Post Dec */
2213 STOREMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2216 case 0x81 : /* Load, No WriteBack, Post Dec */
2217 LOADMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2220 case 0x82 : /* Store, WriteBack, Post Dec */
2221 temp
= LSBase
- LSMNumRegs
;
2222 STOREMULT(instr
,temp
+ 4L,temp
) ;
2225 case 0x83 : /* Load, WriteBack, Post Dec */
2226 temp
= LSBase
- LSMNumRegs
;
2227 LOADMULT(instr
,temp
+ 4L,temp
) ;
2230 case 0x84 : /* Store, Flags, No WriteBack, Post Dec */
2231 STORESMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2234 case 0x85 : /* Load, Flags, No WriteBack, Post Dec */
2235 LOADSMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2238 case 0x86 : /* Store, Flags, WriteBack, Post Dec */
2239 temp
= LSBase
- LSMNumRegs
;
2240 STORESMULT(instr
,temp
+ 4L,temp
) ;
2243 case 0x87 : /* Load, Flags, WriteBack, Post Dec */
2244 temp
= LSBase
- LSMNumRegs
;
2245 LOADSMULT(instr
,temp
+ 4L,temp
) ;
2249 case 0x88 : /* Store, No WriteBack, Post Inc */
2250 STOREMULT(instr
,LSBase
,0L) ;
2253 case 0x89 : /* Load, No WriteBack, Post Inc */
2254 LOADMULT(instr
,LSBase
,0L) ;
2257 case 0x8a : /* Store, WriteBack, Post Inc */
2259 STOREMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2262 case 0x8b : /* Load, WriteBack, Post Inc */
2264 LOADMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2267 case 0x8c : /* Store, Flags, No WriteBack, Post Inc */
2268 STORESMULT(instr
,LSBase
,0L) ;
2271 case 0x8d : /* Load, Flags, No WriteBack, Post Inc */
2272 LOADSMULT(instr
,LSBase
,0L) ;
2275 case 0x8e : /* Store, Flags, WriteBack, Post Inc */
2277 STORESMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2280 case 0x8f : /* Load, Flags, WriteBack, Post Inc */
2282 LOADSMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2286 case 0x90 : /* Store, No WriteBack, Pre Dec */
2287 STOREMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2290 case 0x91 : /* Load, No WriteBack, Pre Dec */
2291 LOADMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2294 case 0x92 : /* Store, WriteBack, Pre Dec */
2295 temp
= LSBase
- LSMNumRegs
;
2296 STOREMULT(instr
,temp
,temp
) ;
2299 case 0x93 : /* Load, WriteBack, Pre Dec */
2300 temp
= LSBase
- LSMNumRegs
;
2301 LOADMULT(instr
,temp
,temp
) ;
2304 case 0x94 : /* Store, Flags, No WriteBack, Pre Dec */
2305 STORESMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2308 case 0x95 : /* Load, Flags, No WriteBack, Pre Dec */
2309 LOADSMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2312 case 0x96 : /* Store, Flags, WriteBack, Pre Dec */
2313 temp
= LSBase
- LSMNumRegs
;
2314 STORESMULT(instr
,temp
,temp
) ;
2317 case 0x97 : /* Load, Flags, WriteBack, Pre Dec */
2318 temp
= LSBase
- LSMNumRegs
;
2319 LOADSMULT(instr
,temp
,temp
) ;
2323 case 0x98 : /* Store, No WriteBack, Pre Inc */
2324 STOREMULT(instr
,LSBase
+ 4L,0L) ;
2327 case 0x99 : /* Load, No WriteBack, Pre Inc */
2328 LOADMULT(instr
,LSBase
+ 4L,0L) ;
2331 case 0x9a : /* Store, WriteBack, Pre Inc */
2333 STOREMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2336 case 0x9b : /* Load, WriteBack, Pre Inc */
2338 LOADMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2341 case 0x9c : /* Store, Flags, No WriteBack, Pre Inc */
2342 STORESMULT(instr
,LSBase
+ 4L,0L) ;
2345 case 0x9d : /* Load, Flags, No WriteBack, Pre Inc */
2346 LOADSMULT(instr
,LSBase
+ 4L,0L) ;
2349 case 0x9e : /* Store, Flags, WriteBack, Pre Inc */
2351 STORESMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2354 case 0x9f : /* Load, Flags, WriteBack, Pre Inc */
2356 LOADSMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2359 /***************************************************************************\
2361 \***************************************************************************/
2363 case 0xa0 : case 0xa1 : case 0xa2 : case 0xa3 :
2364 case 0xa4 : case 0xa5 : case 0xa6 : case 0xa7 :
2365 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2369 /***************************************************************************\
2371 \***************************************************************************/
2373 case 0xa8 : case 0xa9 : case 0xaa : case 0xab :
2374 case 0xac : case 0xad : case 0xae : case 0xaf :
2375 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2379 /***************************************************************************\
2380 * Branch and Link forward *
2381 \***************************************************************************/
2383 case 0xb0 : case 0xb1 : case 0xb2 : case 0xb3 :
2384 case 0xb4 : case 0xb5 : case 0xb6 : case 0xb7 :
2386 state
->Reg
[14] = pc
+ 4 ; /* put PC into Link */
2388 state
->Reg
[14] = pc
+ 4 | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2390 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2394 /***************************************************************************\
2395 * Branch and Link backward *
2396 \***************************************************************************/
2398 case 0xb8 : case 0xb9 : case 0xba : case 0xbb :
2399 case 0xbc : case 0xbd : case 0xbe : case 0xbf :
2401 state
->Reg
[14] = pc
+ 4 ; /* put PC into Link */
2403 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2405 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2409 /***************************************************************************\
2410 * Co-Processor Data Transfers *
2411 \***************************************************************************/
2414 case 0xc4 : /* Store , No WriteBack , Post Dec */
2415 ARMul_STC(state
,instr
,LHS
) ;
2419 case 0xc5 : /* Load , No WriteBack , Post Dec */
2420 ARMul_LDC(state
,instr
,LHS
) ;
2424 case 0xc6 : /* Store , WriteBack , Post Dec */
2426 state
->Base
= lhs
- LSCOff
;
2427 ARMul_STC(state
,instr
,lhs
) ;
2431 case 0xc7 : /* Load , WriteBack , Post Dec */
2433 state
->Base
= lhs
- LSCOff
;
2434 ARMul_LDC(state
,instr
,lhs
) ;
2438 case 0xcc : /* Store , No WriteBack , Post Inc */
2439 ARMul_STC(state
,instr
,LHS
) ;
2443 case 0xcd : /* Load , No WriteBack , Post Inc */
2444 ARMul_LDC(state
,instr
,LHS
) ;
2448 case 0xce : /* Store , WriteBack , Post Inc */
2450 state
->Base
= lhs
+ LSCOff
;
2451 ARMul_STC(state
,instr
,LHS
) ;
2455 case 0xcf : /* Load , WriteBack , Post Inc */
2457 state
->Base
= lhs
+ LSCOff
;
2458 ARMul_LDC(state
,instr
,LHS
) ;
2463 case 0xd4 : /* Store , No WriteBack , Pre Dec */
2464 ARMul_STC(state
,instr
,LHS
- LSCOff
) ;
2468 case 0xd5 : /* Load , No WriteBack , Pre Dec */
2469 ARMul_LDC(state
,instr
,LHS
- LSCOff
) ;
2473 case 0xd6 : /* Store , WriteBack , Pre Dec */
2474 lhs
= LHS
- LSCOff
;
2476 ARMul_STC(state
,instr
,lhs
) ;
2480 case 0xd7 : /* Load , WriteBack , Pre Dec */
2481 lhs
= LHS
- LSCOff
;
2483 ARMul_LDC(state
,instr
,lhs
) ;
2487 case 0xdc : /* Store , No WriteBack , Pre Inc */
2488 ARMul_STC(state
,instr
,LHS
+ LSCOff
) ;
2492 case 0xdd : /* Load , No WriteBack , Pre Inc */
2493 ARMul_LDC(state
,instr
,LHS
+ LSCOff
) ;
2497 case 0xde : /* Store , WriteBack , Pre Inc */
2498 lhs
= LHS
+ LSCOff
;
2500 ARMul_STC(state
,instr
,lhs
) ;
2504 case 0xdf : /* Load , WriteBack , Pre Inc */
2505 lhs
= LHS
+ LSCOff
;
2507 ARMul_LDC(state
,instr
,lhs
) ;
2510 /***************************************************************************\
2511 * Co-Processor Register Transfers (MCR) and Data Ops *
2512 \***************************************************************************/
2514 case 0xe0 : case 0xe2 : case 0xe4 : case 0xe6 :
2515 case 0xe8 : case 0xea : case 0xec : case 0xee :
2516 if (BIT(4)) { /* MCR */
2517 if (DESTReg
== 15) {
2520 ARMul_MCR(state
,instr
,state
->Reg
[15] + isize
) ;
2522 ARMul_MCR(state
,instr
,ECC
| ER15INT
| EMODE
|
2523 ((state
->Reg
[15] + isize
) & R15PCBITS
) ) ;
2527 ARMul_MCR(state
,instr
,DEST
) ;
2529 else /* CDP Part 1 */
2530 ARMul_CDP(state
,instr
) ;
2533 /***************************************************************************\
2534 * Co-Processor Register Transfers (MRC) and Data Ops *
2535 \***************************************************************************/
2537 case 0xe1 : case 0xe3 : case 0xe5 : case 0xe7 :
2538 case 0xe9 : case 0xeb : case 0xed : case 0xef :
2539 if (BIT(4)) { /* MRC */
2540 temp
= ARMul_MRC(state
,instr
) ;
2541 if (DESTReg
== 15) {
2542 ASSIGNN((temp
& NBIT
) != 0) ;
2543 ASSIGNZ((temp
& ZBIT
) != 0) ;
2544 ASSIGNC((temp
& CBIT
) != 0) ;
2545 ASSIGNV((temp
& VBIT
) != 0) ;
2550 else /* CDP Part 2 */
2551 ARMul_CDP(state
,instr
) ;
2554 /***************************************************************************\
2556 \***************************************************************************/
2558 case 0xf0 : case 0xf1 : case 0xf2 : case 0xf3 :
2559 case 0xf4 : case 0xf5 : case 0xf6 : case 0xf7 :
2560 case 0xf8 : case 0xf9 : case 0xfa : case 0xfb :
2561 case 0xfc : case 0xfd : case 0xfe : case 0xff :
2562 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
) { /* a prefetch abort */
2563 ARMul_Abort(state
,ARMul_PrefetchAbortV
) ;
2567 if (!ARMul_OSHandleSWI(state
,BITS(0,23))) {
2568 ARMul_Abort(state
,ARMul_SWIV
) ;
2571 } /* 256 way main switch */
2578 #ifdef NEED_UI_LOOP_HOOK
2579 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
2581 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
2584 #endif /* NEED_UI_LOOP_HOOK */
2586 if (state
->Emulate
== ONCE
)
2587 state
->Emulate
= STOP
;
2588 else if (state
->Emulate
!= RUN
)
2590 } while (!stop_simulator
) ; /* do loop */
2592 state
->decoded
= decoded
;
2593 state
->loaded
= loaded
;
2596 } /* Emulate 26/32 in instruction based mode */
2599 /***************************************************************************\
2600 * This routine evaluates most Data Processing register RHS's with the S *
2601 * bit clear. It is intended to be called from the macro DPRegRHS, which *
2602 * filters the common case of an unshifted register with in line code *
2603 \***************************************************************************/
2605 static ARMword
GetDPRegRHS(ARMul_State
*state
, ARMword instr
)
2606 {ARMword shamt
, base
;
2609 if (BIT(4)) { /* shift amount in a register */
2614 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2617 base
= state
->Reg
[base
] ;
2618 ARMul_Icycles(state
,1,0L) ;
2619 shamt
= state
->Reg
[BITS(8,11)] & 0xff ;
2620 switch ((int)BITS(5,6)) {
2621 case LSL
: if (shamt
== 0)
2623 else if (shamt
>= 32)
2626 return(base
<< shamt
) ;
2627 case LSR
: if (shamt
== 0)
2629 else if (shamt
>= 32)
2632 return(base
>> shamt
) ;
2633 case ASR
: if (shamt
== 0)
2635 else if (shamt
>= 32)
2636 return((ARMword
)((long int)base
>> 31L)) ;
2638 return((ARMword
)((long int)base
>> (int)shamt
)) ;
2639 case ROR
: shamt
&= 0x1f ;
2643 return((base
<< (32 - shamt
)) | (base
>> shamt
)) ;
2646 else { /* shift amount is a constant */
2649 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2652 base
= state
->Reg
[base
] ;
2653 shamt
= BITS(7,11) ;
2654 switch ((int)BITS(5,6)) {
2655 case LSL
: return(base
<<shamt
) ;
2656 case LSR
: if (shamt
== 0)
2659 return(base
>> shamt
) ;
2660 case ASR
: if (shamt
== 0)
2661 return((ARMword
)((long int)base
>> 31L)) ;
2663 return((ARMword
)((long int)base
>> (int)shamt
)) ;
2664 case ROR
: if (shamt
==0) /* its an RRX */
2665 return((base
>> 1) | (CFLAG
<< 31)) ;
2667 return((base
<< (32 - shamt
)) | (base
>> shamt
)) ;
2670 return(0) ; /* just to shut up lint */
2672 /***************************************************************************\
2673 * This routine evaluates most Logical Data Processing register RHS's *
2674 * with the S bit set. It is intended to be called from the macro *
2675 * DPSRegRHS, which filters the common case of an unshifted register *
2676 * with in line code *
2677 \***************************************************************************/
2679 static ARMword
GetDPSRegRHS(ARMul_State
*state
, ARMword instr
)
2680 {ARMword shamt
, base
;
2683 if (BIT(4)) { /* shift amount in a register */
2688 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2691 base
= state
->Reg
[base
] ;
2692 ARMul_Icycles(state
,1,0L) ;
2693 shamt
= state
->Reg
[BITS(8,11)] & 0xff ;
2694 switch ((int)BITS(5,6)) {
2695 case LSL
: if (shamt
== 0)
2697 else if (shamt
== 32) {
2701 else if (shamt
> 32) {
2706 ASSIGNC((base
>> (32-shamt
)) & 1) ;
2707 return(base
<< shamt
) ;
2709 case LSR
: if (shamt
== 0)
2711 else if (shamt
== 32) {
2712 ASSIGNC(base
>> 31) ;
2715 else if (shamt
> 32) {
2720 ASSIGNC((base
>> (shamt
- 1)) & 1) ;
2721 return(base
>> shamt
) ;
2723 case ASR
: if (shamt
== 0)
2725 else if (shamt
>= 32) {
2726 ASSIGNC(base
>> 31L) ;
2727 return((ARMword
)((long int)base
>> 31L)) ;
2730 ASSIGNC((ARMword
)((long int)base
>> (int)(shamt
-1)) & 1) ;
2731 return((ARMword
)((long int)base
>> (int)shamt
)) ;
2733 case ROR
: if (shamt
== 0)
2737 ASSIGNC(base
>> 31) ;
2741 ASSIGNC((base
>> (shamt
-1)) & 1) ;
2742 return((base
<< (32-shamt
)) | (base
>> shamt
)) ;
2746 else { /* shift amount is a constant */
2749 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2752 base
= state
->Reg
[base
] ;
2753 shamt
= BITS(7,11) ;
2754 switch ((int)BITS(5,6)) {
2755 case LSL
: ASSIGNC((base
>> (32-shamt
)) & 1) ;
2756 return(base
<< shamt
) ;
2757 case LSR
: if (shamt
== 0) {
2758 ASSIGNC(base
>> 31) ;
2762 ASSIGNC((base
>> (shamt
- 1)) & 1) ;
2763 return(base
>> shamt
) ;
2765 case ASR
: if (shamt
== 0) {
2766 ASSIGNC(base
>> 31L) ;
2767 return((ARMword
)((long int)base
>> 31L)) ;
2770 ASSIGNC((ARMword
)((long int)base
>> (int)(shamt
-1)) & 1) ;
2771 return((ARMword
)((long int)base
>> (int)shamt
)) ;
2773 case ROR
: if (shamt
== 0) { /* its an RRX */
2776 return((base
>> 1) | (shamt
<< 31)) ;
2779 ASSIGNC((base
>> (shamt
- 1)) & 1) ;
2780 return((base
<< (32-shamt
)) | (base
>> shamt
)) ;
2784 return(0) ; /* just to shut up lint */
2787 /***************************************************************************\
2788 * This routine handles writes to register 15 when the S bit is not set. *
2789 \***************************************************************************/
2791 static void WriteR15(ARMul_State
*state
, ARMword src
)
2793 /* The ARM documentation implies (but doe snot state) that the bottom bit of the PC is never set */
2795 state
->Reg
[15] = src
& PCBITS
& ~ 0x1 ;
2797 state
->Reg
[15] = (src
& R15PCBITS
& ~ 0x1) | ECC
| ER15INT
| EMODE
;
2798 ARMul_R15Altered(state
) ;
2803 /***************************************************************************\
2804 * This routine handles writes to register 15 when the S bit is set. *
2805 \***************************************************************************/
2807 static void WriteSR15(ARMul_State
*state
, ARMword src
)
2810 state
->Reg
[15] = src
& PCBITS
;
2811 if (state
->Bank
> 0) {
2812 state
->Cpsr
= state
->Spsr
[state
->Bank
] ;
2813 ARMul_CPSRAltered(state
) ;
2816 if (state
->Bank
== USERBANK
)
2817 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
2819 state
->Reg
[15] = src
;
2820 ARMul_R15Altered(state
) ;
2825 /***************************************************************************\
2826 * This routine evaluates most Load and Store register RHS's. It is *
2827 * intended to be called from the macro LSRegRHS, which filters the *
2828 * common case of an unshifted register with in line code *
2829 \***************************************************************************/
2831 static ARMword
GetLSRegRHS(ARMul_State
*state
, ARMword instr
)
2832 {ARMword shamt
, base
;
2837 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
2840 base
= state
->Reg
[base
] ;
2842 shamt
= BITS(7,11) ;
2843 switch ((int)BITS(5,6)) {
2844 case LSL
: return(base
<< shamt
) ;
2845 case LSR
: if (shamt
== 0)
2848 return(base
>> shamt
) ;
2849 case ASR
: if (shamt
== 0)
2850 return((ARMword
)((long int)base
>> 31L)) ;
2852 return((ARMword
)((long int)base
>> (int)shamt
)) ;
2853 case ROR
: if (shamt
==0) /* its an RRX */
2854 return((base
>> 1) | (CFLAG
<< 31)) ;
2856 return((base
<< (32-shamt
)) | (base
>> shamt
)) ;
2858 return(0) ; /* just to shut up lint */
2861 /***************************************************************************\
2862 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
2863 \***************************************************************************/
2865 static ARMword
GetLS7RHS(ARMul_State
*state
, ARMword instr
)
2867 if (BIT(22) == 0) { /* register */
2870 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
2872 return state
->Reg
[RHSReg
] ;
2875 /* else immediate */
2876 return BITS(0,3) | (BITS(8,11) << 4) ;
2879 /***************************************************************************\
2880 * This function does the work of loading a word for a LDR instruction. *
2881 \***************************************************************************/
2883 static unsigned LoadWord(ARMul_State
*state
, ARMword instr
, ARMword address
)
2889 if (ADDREXCEPT(address
)) {
2890 INTERNALABORT(address
) ;
2893 dest
= ARMul_LoadWordN(state
,address
) ;
2894 if (state
->Aborted
) {
2896 return(state
->lateabtSig
) ;
2899 dest
= ARMul_Align(state
,address
,dest
) ;
2901 ARMul_Icycles(state
,1,0L) ;
2903 return(DESTReg
!= LHSReg
) ;
2907 /***************************************************************************\
2908 * This function does the work of loading a halfword. *
2909 \***************************************************************************/
2911 static unsigned LoadHalfWord(ARMul_State
*state
, ARMword instr
, ARMword address
,int signextend
)
2917 if (ADDREXCEPT(address
)) {
2918 INTERNALABORT(address
) ;
2921 dest
= ARMul_LoadHalfWord(state
,address
) ;
2922 if (state
->Aborted
) {
2924 return(state
->lateabtSig
) ;
2929 if (dest
& 1 << (16 - 1))
2930 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16) ;
2933 ARMul_Icycles(state
,1,0L) ;
2934 return(DESTReg
!= LHSReg
) ;
2938 /***************************************************************************\
2939 * This function does the work of loading a byte for a LDRB instruction. *
2940 \***************************************************************************/
2942 static unsigned LoadByte(ARMul_State
*state
, ARMword instr
, ARMword address
,int signextend
)
2948 if (ADDREXCEPT(address
)) {
2949 INTERNALABORT(address
) ;
2952 dest
= ARMul_LoadByte(state
,address
) ;
2953 if (state
->Aborted
) {
2955 return(state
->lateabtSig
) ;
2960 if (dest
& 1 << (8 - 1))
2961 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8) ;
2964 ARMul_Icycles(state
,1,0L) ;
2965 return(DESTReg
!= LHSReg
) ;
2968 /***************************************************************************\
2969 * This function does the work of storing a word from a STR instruction. *
2970 \***************************************************************************/
2972 static unsigned StoreWord(ARMul_State
*state
, ARMword instr
, ARMword address
)
2976 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
2979 ARMul_StoreWordN(state
,address
,DEST
) ;
2981 if (VECTORACCESS(address
) || ADDREXCEPT(address
)) {
2982 INTERNALABORT(address
) ;
2983 (void)ARMul_LoadWordN(state
,address
) ;
2986 ARMul_StoreWordN(state
,address
,DEST
) ;
2988 if (state
->Aborted
) {
2990 return(state
->lateabtSig
) ;
2996 /***************************************************************************\
2997 * This function does the work of storing a byte for a STRH instruction. *
2998 \***************************************************************************/
3000 static unsigned StoreHalfWord(ARMul_State
*state
, ARMword instr
, ARMword address
)
3005 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3009 ARMul_StoreHalfWord(state
,address
,DEST
);
3011 if (VECTORACCESS(address
) || ADDREXCEPT(address
)) {
3012 INTERNALABORT(address
) ;
3013 (void)ARMul_LoadHalfWord(state
,address
) ;
3016 ARMul_StoreHalfWord(state
,address
,DEST
) ;
3019 if (state
->Aborted
) {
3021 return(state
->lateabtSig
) ;
3028 /***************************************************************************\
3029 * This function does the work of storing a byte for a STRB instruction. *
3030 \***************************************************************************/
3032 static unsigned StoreByte(ARMul_State
*state
, ARMword instr
, ARMword address
)
3036 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3039 ARMul_StoreByte(state
,address
,DEST
) ;
3041 if (VECTORACCESS(address
) || ADDREXCEPT(address
)) {
3042 INTERNALABORT(address
) ;
3043 (void)ARMul_LoadByte(state
,address
) ;
3046 ARMul_StoreByte(state
,address
,DEST
) ;
3048 if (state
->Aborted
) {
3050 return(state
->lateabtSig
) ;
3056 /***************************************************************************\
3057 * This function does the work of loading the registers listed in an LDM *
3058 * instruction, when the S bit is clear. The code here is always increment *
3059 * after, it's up to the caller to get the input address correct and to *
3060 * handle base register modification. *
3061 \***************************************************************************/
3063 static void LoadMult(ARMul_State
*state
, ARMword instr
,
3064 ARMword address
, ARMword WBBase
)
3065 {ARMword dest
, temp
;
3069 UNDEF_LSMBaseInListWb
;
3072 if (ADDREXCEPT(address
)) {
3073 INTERNALABORT(address
) ;
3076 if (BIT(21) && LHSReg
!= 15)
3079 for (temp
= 0 ; !BIT(temp
) ; temp
++) ; /* N cycle first */
3080 dest
= ARMul_LoadWordN(state
,address
) ;
3081 if (!state
->abortSig
&& !state
->Aborted
)
3082 state
->Reg
[temp
++] = dest
;
3084 if (!state
->Aborted
)
3085 state
->Aborted
= ARMul_DataAbortV
;
3087 for (; temp
< 16 ; temp
++) /* S cycles from here on */
3088 if (BIT(temp
)) { /* load this register */
3090 dest
= ARMul_LoadWordS(state
,address
) ;
3091 if (!state
->abortSig
&& !state
->Aborted
)
3092 state
->Reg
[temp
] = dest
;
3094 if (!state
->Aborted
)
3095 state
->Aborted
= ARMul_DataAbortV
;
3098 if (BIT(15)) { /* PC is in the reg list */
3100 state
->Reg
[15] = PC
;
3105 ARMul_Icycles(state
,1,0L) ; /* to write back the final register */
3107 if (state
->Aborted
) {
3108 if (BIT(21) && LHSReg
!= 15)
3114 /***************************************************************************\
3115 * This function does the work of loading the registers listed in an LDM *
3116 * instruction, when the S bit is set. The code here is always increment *
3117 * after, it's up to the caller to get the input address correct and to *
3118 * handle base register modification. *
3119 \***************************************************************************/
3121 static void LoadSMult(ARMul_State
*state
, ARMword instr
,
3122 ARMword address
, ARMword WBBase
)
3123 {ARMword dest
, temp
;
3127 UNDEF_LSMBaseInListWb
;
3130 if (ADDREXCEPT(address
)) {
3131 INTERNALABORT(address
) ;
3135 if (!BIT(15) && state
->Bank
!= USERBANK
) {
3136 (void)ARMul_SwitchMode(state
,state
->Mode
,USER26MODE
) ; /* temporary reg bank switch */
3137 UNDEF_LSMUserBankWb
;
3140 if (BIT(21) && LHSReg
!= 15)
3143 for (temp
= 0 ; !BIT(temp
) ; temp
++) ; /* N cycle first */
3144 dest
= ARMul_LoadWordN(state
,address
) ;
3145 if (!state
->abortSig
)
3146 state
->Reg
[temp
++] = dest
;
3148 if (!state
->Aborted
)
3149 state
->Aborted
= ARMul_DataAbortV
;
3151 for (; temp
< 16 ; temp
++) /* S cycles from here on */
3152 if (BIT(temp
)) { /* load this register */
3154 dest
= ARMul_LoadWordS(state
,address
) ;
3155 if (!state
->abortSig
|| state
->Aborted
)
3156 state
->Reg
[temp
] = dest
;
3158 if (!state
->Aborted
)
3159 state
->Aborted
= ARMul_DataAbortV
;
3162 if (BIT(15)) { /* PC is in the reg list */
3164 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
) {
3165 state
->Cpsr
= GETSPSR(state
->Bank
) ;
3166 ARMul_CPSRAltered(state
) ;
3168 state
->Reg
[15] = PC
;
3170 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
) { /* protect bits in user mode */
3171 ASSIGNN((state
->Reg
[15] & NBIT
) != 0) ;
3172 ASSIGNZ((state
->Reg
[15] & ZBIT
) != 0) ;
3173 ASSIGNC((state
->Reg
[15] & CBIT
) != 0) ;
3174 ASSIGNV((state
->Reg
[15] & VBIT
) != 0) ;
3177 ARMul_R15Altered(state
) ;
3182 if (!BIT(15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3183 (void)ARMul_SwitchMode(state
,USER26MODE
,state
->Mode
) ; /* restore the correct bank */
3185 ARMul_Icycles(state
,1,0L) ; /* to write back the final register */
3187 if (state
->Aborted
) {
3188 if (BIT(21) && LHSReg
!= 15)
3195 /***************************************************************************\
3196 * This function does the work of storing the registers listed in an STM *
3197 * instruction, when the S bit is clear. The code here is always increment *
3198 * after, it's up to the caller to get the input address correct and to *
3199 * handle base register modification. *
3200 \***************************************************************************/
3202 static void StoreMult(ARMul_State
*state
, ARMword instr
,
3203 ARMword address
, ARMword WBBase
)
3208 UNDEF_LSMBaseInListWb
;
3210 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
3214 if (VECTORACCESS(address
) || ADDREXCEPT(address
)) {
3215 INTERNALABORT(address
) ;
3221 for (temp
= 0 ; !BIT(temp
) ; temp
++) ; /* N cycle first */
3223 ARMul_StoreWordN(state
,address
,state
->Reg
[temp
++]) ;
3225 if (state
->Aborted
) {
3226 (void)ARMul_LoadWordN(state
,address
) ;
3227 for ( ; temp
< 16 ; temp
++) /* Fake the Stores as Loads */
3228 if (BIT(temp
)) { /* save this register */
3230 (void)ARMul_LoadWordS(state
,address
) ;
3232 if (BIT(21) && LHSReg
!= 15)
3238 ARMul_StoreWordN(state
,address
,state
->Reg
[temp
++]) ;
3240 if (state
->abortSig
&& !state
->Aborted
)
3241 state
->Aborted
= ARMul_DataAbortV
;
3243 if (BIT(21) && LHSReg
!= 15)
3246 for ( ; temp
< 16 ; temp
++) /* S cycles from here on */
3247 if (BIT(temp
)) { /* save this register */
3249 ARMul_StoreWordS(state
,address
,state
->Reg
[temp
]) ;
3250 if (state
->abortSig
&& !state
->Aborted
)
3251 state
->Aborted
= ARMul_DataAbortV
;
3253 if (state
->Aborted
) {
3258 /***************************************************************************\
3259 * This function does the work of storing the registers listed in an STM *
3260 * instruction when the S bit is set. The code here is always increment *
3261 * after, it's up to the caller to get the input address correct and to *
3262 * handle base register modification. *
3263 \***************************************************************************/
3265 static void StoreSMult(ARMul_State
*state
, ARMword instr
,
3266 ARMword address
, ARMword WBBase
)
3271 UNDEF_LSMBaseInListWb
;
3274 if (VECTORACCESS(address
) || ADDREXCEPT(address
)) {
3275 INTERNALABORT(address
) ;
3281 if (state
->Bank
!= USERBANK
) {
3282 (void)ARMul_SwitchMode(state
,state
->Mode
,USER26MODE
) ; /* Force User Bank */
3283 UNDEF_LSMUserBankWb
;
3286 for (temp
= 0 ; !BIT(temp
) ; temp
++) ; /* N cycle first */
3288 ARMul_StoreWordN(state
,address
,state
->Reg
[temp
++]) ;
3290 if (state
->Aborted
) {
3291 (void)ARMul_LoadWordN(state
,address
) ;
3292 for ( ; temp
< 16 ; temp
++) /* Fake the Stores as Loads */
3293 if (BIT(temp
)) { /* save this register */
3295 (void)ARMul_LoadWordS(state
,address
) ;
3297 if (BIT(21) && LHSReg
!= 15)
3303 ARMul_StoreWordN(state
,address
,state
->Reg
[temp
++]) ;
3305 if (state
->abortSig
&& !state
->Aborted
)
3306 state
->Aborted
= ARMul_DataAbortV
;
3308 if (BIT(21) && LHSReg
!= 15)
3311 for (; temp
< 16 ; temp
++) /* S cycles from here on */
3312 if (BIT(temp
)) { /* save this register */
3314 ARMul_StoreWordS(state
,address
,state
->Reg
[temp
]) ;
3315 if (state
->abortSig
&& !state
->Aborted
)
3316 state
->Aborted
= ARMul_DataAbortV
;
3319 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3320 (void)ARMul_SwitchMode(state
,USER26MODE
,state
->Mode
) ; /* restore the correct bank */
3322 if (state
->Aborted
) {
3327 /***************************************************************************\
3328 * This function does the work of adding two 32bit values together, and *
3329 * calculating if a carry has occurred. *
3330 \***************************************************************************/
3332 static ARMword
Add32(ARMword a1
,ARMword a2
,int *carry
)
3334 ARMword result
= (a1
+ a2
);
3335 unsigned int uresult
= (unsigned int)result
;
3336 unsigned int ua1
= (unsigned int)a1
;
3338 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
3339 or (result > RdLo) then we have no carry: */
3340 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
3348 /***************************************************************************\
3349 * This function does the work of multiplying two 32bit values to give a *
3351 \***************************************************************************/
3353 static unsigned Multiply64(ARMul_State
*state
,ARMword instr
,int msigned
,int scc
)
3355 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
3356 ARMword RdHi
, RdLo
, Rm
;
3357 int scount
; /* cycle count */
3359 nRdHi
= BITS(16,19);
3360 nRdLo
= BITS(12,15);
3364 /* Needed to calculate the cycle count: */
3365 Rm
= state
->Reg
[nRm
];
3367 /* Check for illegal operand combinations first: */
3376 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
3378 ARMword Rs
= state
->Reg
[ nRs
];
3383 /* Compute sign of result and adjust operands if necessary. */
3385 sign
= (Rm
^ Rs
) & 0x80000000;
3387 if (((signed long)Rm
) < 0)
3390 if (((signed long)Rs
) < 0)
3394 /* We can split the 32x32 into four 16x16 operations. This ensures
3395 that we do not lose precision on 32bit only hosts: */
3396 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
3397 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3398 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
3399 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3401 /* We now need to add all of these results together, taking care
3402 to propogate the carries from the additions: */
3403 RdLo
= Add32(lo
,(mid1
<< 16),&carry
);
3405 RdLo
= Add32(RdLo
,(mid2
<< 16),&carry
);
3406 RdHi
+= (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
3410 /* Negate result if necessary. */
3414 if (RdLo
== 0xFFFFFFFF)
3423 state
->Reg
[nRdLo
] = RdLo
;
3424 state
->Reg
[nRdHi
] = RdHi
;
3426 } /* else undefined result */
3427 else fprintf (stderr
, "MULTIPLY64 - INVALID ARGUMENTS\n");
3431 if ((RdHi
== 0) && (RdLo
== 0))
3432 ARMul_NegZero(state
,RdHi
); /* zero value */
3434 ARMul_NegZero(state
,scc
); /* non-zero value */
3437 /* The cycle count depends on whether the instruction is a signed or
3438 unsigned multiply, and what bits are clear in the multiplier: */
3439 if (msigned
&& (Rm
& ((unsigned)1 << 31)))
3440 Rm
= ~Rm
; /* invert the bits to make the check against zero */
3442 if ((Rm
& 0xFFFFFF00) == 0)
3444 else if ((Rm
& 0xFFFF0000) == 0)
3446 else if ((Rm
& 0xFF000000) == 0)
3454 /***************************************************************************\
3455 * This function does the work of multiplying two 32bit values and adding *
3456 * a 64bit value to give a 64bit result. *
3457 \***************************************************************************/
3459 static unsigned MultiplyAdd64(ARMul_State
*state
,ARMword instr
,int msigned
,int scc
)
3466 nRdHi
= BITS(16,19);
3467 nRdLo
= BITS(12,15);
3469 RdHi
= state
->Reg
[nRdHi
] ;
3470 RdLo
= state
->Reg
[nRdLo
] ;
3472 scount
= Multiply64(state
,instr
,msigned
,LDEFAULT
);
3474 RdLo
= Add32(RdLo
,state
->Reg
[nRdLo
],&carry
);
3475 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
3477 state
->Reg
[nRdLo
] = RdLo
;
3478 state
->Reg
[nRdHi
] = RdHi
;
3481 if ((RdHi
== 0) && (RdLo
== 0))
3482 ARMul_NegZero(state
,RdHi
); /* zero value */
3484 ARMul_NegZero(state
,scc
); /* non-zero value */
3487 return scount
+ 1; /* extra cycle for addition */