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 */
882 if (BITS(4,11) == 0xB) {
883 /* STRH register offset, no write-back, down, pre indexed */
888 if (BITS(4,11) == 9) { /* SWP */
893 if (VECTORACCESS(temp
) || ADDREXCEPT(temp
)) {
894 INTERNALABORT(temp
) ;
895 (void)ARMul_LoadWordN(state
,temp
) ;
896 (void)ARMul_LoadWordN(state
,temp
) ;
900 dest
= ARMul_SwapWord(state
,temp
,state
->Reg
[RHSReg
]) ;
902 DEST
= ARMul_Align(state
,temp
,dest
) ;
905 if (state
->abortSig
|| state
->Aborted
) {
909 else if ((BITS(0,11)==0) && (LHSReg
==15)) { /* MRS CPSR */
911 DEST
= ECC
| EINT
| EMODE
;
918 case 0x11 : /* TSTP reg */
920 if ((BITS(4,11) & 0xF9) == 0x9) {
921 /* LDR register offset, no write-back, down, pre indexed */
923 /* continue with remaining instruction decode */
926 if (DESTReg
== 15) { /* TSTP reg */
928 state
->Cpsr
= GETSPSR(state
->Bank
) ;
929 ARMul_CPSRAltered(state
) ;
939 ARMul_NegZero(state
,dest
) ;
943 case 0x12 : /* TEQ reg and MSR reg to CPSR (ARM6) */
945 if (BITS(4,11) == 0xB) {
946 /* STRH register offset, write-back, down, pre indexed */
952 if (BITS(4,27)==0x12FFF1) { /* BX */
953 /* Branch to the address in RHSReg. If bit0 of
954 destination address is 1 then switch to Thumb mode: */
955 ARMword addr
= state
->Reg
[RHSReg
];
957 /* If we read the PC then the bottom bit is clear */
958 if (RHSReg
== 15) addr
&= ~1;
960 /* Enable this for a helpful bit of debugging when
961 GDB is not yet fully working...
962 fprintf (stderr, "BX at %x to %x (go %s)\n",
963 state->Reg[15], addr, (addr & 1) ? "thumb": "arm" ); */
965 if (addr
& (1 << 0)) { /* Thumb bit */
967 state
->Reg
[15] = addr
& 0xfffffffe;
968 /* NOTE: The other CPSR flag setting blocks do not
969 seem to update the state->Cpsr state, but just do
970 the explicit flag. The copy from the seperate
971 flags to the register must happen later. */
975 state
->Reg
[15] = addr
& 0xfffffffc;
980 if (DESTReg
==15 && BITS(17,18)==0) { /* MSR reg to CPSR */
983 ARMul_FixCPSR(state
,instr
,temp
) ;
990 case 0x13 : /* TEQP reg */
992 if ((BITS(4,11) & 0xF9) == 0x9) {
993 /* LDR register offset, write-back, down, pre indexed */
995 /* continue with remaining instruction decode */
998 if (DESTReg
== 15) { /* TEQP reg */
1000 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1001 ARMul_CPSRAltered(state
) ;
1008 else { /* TEQ Reg */
1011 ARMul_NegZero(state
,dest
) ;
1015 case 0x14 : /* CMP reg and MRS SPSR and SWP byte */
1017 if (BITS(4,7) == 0xB) {
1018 /* STRH immediate offset, no write-back, down, pre indexed */
1023 if (BITS(4,11) == 9) { /* SWP */
1028 if (VECTORACCESS(temp
) || ADDREXCEPT(temp
)) {
1029 INTERNALABORT(temp
) ;
1030 (void)ARMul_LoadByte(state
,temp
) ;
1031 (void)ARMul_LoadByte(state
,temp
) ;
1035 DEST
= ARMul_SwapByte(state
,temp
,state
->Reg
[RHSReg
]) ;
1036 if (state
->abortSig
|| state
->Aborted
) {
1040 else if ((BITS(0,11)==0) && (LHSReg
==15)) { /* MRS SPSR */
1042 DEST
= GETSPSR(state
->Bank
) ;
1049 case 0x15 : /* CMPP reg */
1051 if ((BITS(4,7) & 0x9) == 0x9) {
1052 /* LDR immediate offset, no write-back, down, pre indexed */
1054 /* continue with remaining instruction decode */
1057 if (DESTReg
== 15) { /* CMPP reg */
1059 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1060 ARMul_CPSRAltered(state
) ;
1067 else { /* CMP reg */
1071 ARMul_NegZero(state
,dest
) ;
1072 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1073 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1074 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1083 case 0x16 : /* CMN reg and MSR reg to SPSR */
1085 if (BITS(4,7) == 0xB) {
1086 /* STRH immediate offset, write-back, down, pre indexed */
1091 if (DESTReg
==15 && BITS(17,18)==0) { /* MSR */
1093 ARMul_FixSPSR(state
,instr
,DPRegRHS
);
1100 case 0x17 : /* CMNP reg */
1102 if ((BITS(4,7) & 0x9) == 0x9) {
1103 /* LDR immediate offset, write-back, down, pre indexed */
1105 /* continue with remaining instruction decoding */
1108 if (DESTReg
== 15) {
1110 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1111 ARMul_CPSRAltered(state
) ;
1119 else { /* CMN reg */
1124 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1125 ASSIGNN(NEG(dest
)) ;
1126 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1127 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1137 case 0x18 : /* ORR reg */
1139 if (BITS(4,11) == 0xB) {
1140 /* STRH register offset, no write-back, up, pre indexed */
1150 case 0x19 : /* ORRS reg */
1152 if ((BITS(4,11) & 0xF9) == 0x9) {
1153 /* LDR register offset, no write-back, up, pre indexed */
1155 /* continue with remaining instruction decoding */
1163 case 0x1a : /* MOV reg */
1165 if (BITS(4,11) == 0xB) {
1166 /* STRH register offset, write-back, up, pre indexed */
1175 case 0x1b : /* MOVS reg */
1177 if ((BITS(4,11) & 0xF9) == 0x9) {
1178 /* LDR register offset, write-back, up, pre indexed */
1180 /* continue with remaining instruction decoding */
1187 case 0x1c : /* BIC reg */
1189 if (BITS(4,7) == 0xB) {
1190 /* STRH immediate offset, no write-back, up, pre indexed */
1200 case 0x1d : /* BICS reg */
1202 if ((BITS(4,7) & 0x9) == 0x9) {
1203 /* LDR immediate offset, no write-back, up, pre indexed */
1205 /* continue with instruction decoding */
1213 case 0x1e : /* MVN reg */
1215 if (BITS(4,7) == 0xB) {
1216 /* STRH immediate offset, write-back, up, pre indexed */
1225 case 0x1f : /* MVNS reg */
1227 if ((BITS(4,7) & 0x9) == 0x9) {
1228 /* LDR immediate offset, write-back, up, pre indexed */
1230 /* continue instruction decoding */
1237 /***************************************************************************\
1238 * Data Processing Immediate RHS Instructions *
1239 \***************************************************************************/
1241 case 0x20 : /* AND immed */
1242 dest
= LHS
& DPImmRHS
;
1246 case 0x21 : /* ANDS immed */
1252 case 0x22 : /* EOR immed */
1253 dest
= LHS
^ DPImmRHS
;
1257 case 0x23 : /* EORS immed */
1263 case 0x24 : /* SUB immed */
1264 dest
= LHS
- DPImmRHS
;
1268 case 0x25 : /* SUBS immed */
1272 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1273 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1274 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1283 case 0x26 : /* RSB immed */
1284 dest
= DPImmRHS
- LHS
;
1288 case 0x27 : /* RSBS immed */
1292 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31)) {
1293 ARMul_SubCarry(state
,rhs
,lhs
,dest
) ;
1294 ARMul_SubOverflow(state
,rhs
,lhs
,dest
) ;
1303 case 0x28 : /* ADD immed */
1304 dest
= LHS
+ DPImmRHS
;
1308 case 0x29 : /* ADDS immed */
1313 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1314 ASSIGNN(NEG(dest
)) ;
1315 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1316 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1326 case 0x2a : /* ADC immed */
1327 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1331 case 0x2b : /* ADCS immed */
1334 dest
= lhs
+ rhs
+ CFLAG
;
1336 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1337 ASSIGNN(NEG(dest
)) ;
1338 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1339 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1349 case 0x2c : /* SBC immed */
1350 dest
= LHS
- DPImmRHS
- !CFLAG
;
1354 case 0x2d : /* SBCS immed */
1357 dest
= lhs
- rhs
- !CFLAG
;
1358 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1359 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1360 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1369 case 0x2e : /* RSC immed */
1370 dest
= DPImmRHS
- LHS
- !CFLAG
;
1374 case 0x2f : /* RSCS immed */
1377 dest
= rhs
- lhs
- !CFLAG
;
1378 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31)) {
1379 ARMul_SubCarry(state
,rhs
,lhs
,dest
) ;
1380 ARMul_SubOverflow(state
,rhs
,lhs
,dest
) ;
1389 case 0x30 : /* TST immed */
1393 case 0x31 : /* TSTP immed */
1394 if (DESTReg
== 15) { /* TSTP immed */
1396 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1397 ARMul_CPSRAltered(state
) ;
1399 temp
= LHS
& DPImmRHS
;
1404 DPSImmRHS
; /* TST immed */
1406 ARMul_NegZero(state
,dest
) ;
1410 case 0x32 : /* TEQ immed and MSR immed to CPSR */
1411 if (DESTReg
==15 && BITS(17,18)==0) { /* MSR immed to CPSR */
1412 ARMul_FixCPSR(state
,instr
,DPImmRHS
) ;
1419 case 0x33 : /* TEQP immed */
1420 if (DESTReg
== 15) { /* TEQP immed */
1422 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1423 ARMul_CPSRAltered(state
) ;
1425 temp
= LHS
^ DPImmRHS
;
1430 DPSImmRHS
; /* TEQ immed */
1432 ARMul_NegZero(state
,dest
) ;
1436 case 0x34 : /* CMP immed */
1440 case 0x35 : /* CMPP immed */
1441 if (DESTReg
== 15) { /* CMPP immed */
1443 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1444 ARMul_CPSRAltered(state
) ;
1446 temp
= LHS
- DPImmRHS
;
1452 lhs
= LHS
; /* CMP immed */
1455 ARMul_NegZero(state
,dest
) ;
1456 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1457 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1458 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1467 case 0x36 : /* CMN immed and MSR immed to SPSR */
1468 if (DESTReg
==15 && BITS(17,18)==0) /* MSR */
1469 ARMul_FixSPSR(state
, instr
, DPImmRHS
) ;
1475 case 0x37 : /* CMNP immed */
1476 if (DESTReg
== 15) { /* CMNP immed */
1478 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1479 ARMul_CPSRAltered(state
) ;
1481 temp
= LHS
+ DPImmRHS
;
1487 lhs
= LHS
; /* CMN immed */
1491 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1492 ASSIGNN(NEG(dest
)) ;
1493 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1494 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1504 case 0x38 : /* ORR immed */
1505 dest
= LHS
| DPImmRHS
;
1509 case 0x39 : /* ORRS immed */
1515 case 0x3a : /* MOV immed */
1520 case 0x3b : /* MOVS immed */
1525 case 0x3c : /* BIC immed */
1526 dest
= LHS
& ~DPImmRHS
;
1530 case 0x3d : /* BICS immed */
1536 case 0x3e : /* MVN immed */
1541 case 0x3f : /* MVNS immed */
1546 /***************************************************************************\
1547 * Single Data Transfer Immediate RHS Instructions *
1548 \***************************************************************************/
1550 case 0x40 : /* Store Word, No WriteBack, Post Dec, Immed */
1552 if (StoreWord(state
,instr
,lhs
))
1553 LSBase
= lhs
- LSImmRHS
;
1556 case 0x41 : /* Load Word, No WriteBack, Post Dec, Immed */
1558 if (LoadWord(state
,instr
,lhs
))
1559 LSBase
= lhs
- LSImmRHS
;
1562 case 0x42 : /* Store Word, WriteBack, Post Dec, Immed */
1563 UNDEF_LSRBaseEQDestWb
;
1566 temp
= lhs
- LSImmRHS
;
1567 state
->NtransSig
= LOW
;
1568 if (StoreWord(state
,instr
,lhs
))
1570 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1573 case 0x43 : /* Load Word, WriteBack, Post Dec, Immed */
1574 UNDEF_LSRBaseEQDestWb
;
1577 state
->NtransSig
= LOW
;
1578 if (LoadWord(state
,instr
,lhs
))
1579 LSBase
= lhs
- LSImmRHS
;
1580 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1583 case 0x44 : /* Store Byte, No WriteBack, Post Dec, Immed */
1585 if (StoreByte(state
,instr
,lhs
))
1586 LSBase
= lhs
- LSImmRHS
;
1589 case 0x45 : /* Load Byte, No WriteBack, Post Dec, Immed */
1591 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1592 LSBase
= lhs
- LSImmRHS
;
1595 case 0x46 : /* Store Byte, WriteBack, Post Dec, Immed */
1596 UNDEF_LSRBaseEQDestWb
;
1599 state
->NtransSig
= LOW
;
1600 if (StoreByte(state
,instr
,lhs
))
1601 LSBase
= lhs
- LSImmRHS
;
1602 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1605 case 0x47 : /* Load Byte, WriteBack, Post Dec, Immed */
1606 UNDEF_LSRBaseEQDestWb
;
1609 state
->NtransSig
= LOW
;
1610 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1611 LSBase
= lhs
- LSImmRHS
;
1612 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1615 case 0x48 : /* Store Word, No WriteBack, Post Inc, Immed */
1617 if (StoreWord(state
,instr
,lhs
))
1618 LSBase
= lhs
+ LSImmRHS
;
1621 case 0x49 : /* Load Word, No WriteBack, Post Inc, Immed */
1623 if (LoadWord(state
,instr
,lhs
))
1624 LSBase
= lhs
+ LSImmRHS
;
1627 case 0x4a : /* Store Word, WriteBack, Post Inc, Immed */
1628 UNDEF_LSRBaseEQDestWb
;
1631 state
->NtransSig
= LOW
;
1632 if (StoreWord(state
,instr
,lhs
))
1633 LSBase
= lhs
+ LSImmRHS
;
1634 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1637 case 0x4b : /* Load Word, WriteBack, Post Inc, Immed */
1638 UNDEF_LSRBaseEQDestWb
;
1641 state
->NtransSig
= LOW
;
1642 if (LoadWord(state
,instr
,lhs
))
1643 LSBase
= lhs
+ LSImmRHS
;
1644 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1647 case 0x4c : /* Store Byte, No WriteBack, Post Inc, Immed */
1649 if (StoreByte(state
,instr
,lhs
))
1650 LSBase
= lhs
+ LSImmRHS
;
1653 case 0x4d : /* Load Byte, No WriteBack, Post Inc, Immed */
1655 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1656 LSBase
= lhs
+ LSImmRHS
;
1659 case 0x4e : /* Store Byte, WriteBack, Post Inc, Immed */
1660 UNDEF_LSRBaseEQDestWb
;
1663 state
->NtransSig
= LOW
;
1664 if (StoreByte(state
,instr
,lhs
))
1665 LSBase
= lhs
+ LSImmRHS
;
1666 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1669 case 0x4f : /* Load Byte, WriteBack, Post Inc, Immed */
1670 UNDEF_LSRBaseEQDestWb
;
1673 state
->NtransSig
= LOW
;
1674 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1675 LSBase
= lhs
+ LSImmRHS
;
1676 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1680 case 0x50 : /* Store Word, No WriteBack, Pre Dec, Immed */
1681 (void)StoreWord(state
,instr
,LHS
- LSImmRHS
) ;
1684 case 0x51 : /* Load Word, No WriteBack, Pre Dec, Immed */
1685 (void)LoadWord(state
,instr
,LHS
- LSImmRHS
) ;
1688 case 0x52 : /* Store Word, WriteBack, Pre Dec, Immed */
1689 UNDEF_LSRBaseEQDestWb
;
1691 temp
= LHS
- LSImmRHS
;
1692 if (StoreWord(state
,instr
,temp
))
1696 case 0x53 : /* Load Word, WriteBack, Pre Dec, Immed */
1697 UNDEF_LSRBaseEQDestWb
;
1699 temp
= LHS
- LSImmRHS
;
1700 if (LoadWord(state
,instr
,temp
))
1704 case 0x54 : /* Store Byte, No WriteBack, Pre Dec, Immed */
1705 (void)StoreByte(state
,instr
,LHS
- LSImmRHS
) ;
1708 case 0x55 : /* Load Byte, No WriteBack, Pre Dec, Immed */
1709 (void)LoadByte(state
,instr
,LHS
- LSImmRHS
,LUNSIGNED
) ;
1712 case 0x56 : /* Store Byte, WriteBack, Pre Dec, Immed */
1713 UNDEF_LSRBaseEQDestWb
;
1715 temp
= LHS
- LSImmRHS
;
1716 if (StoreByte(state
,instr
,temp
))
1720 case 0x57 : /* Load Byte, WriteBack, Pre Dec, Immed */
1721 UNDEF_LSRBaseEQDestWb
;
1723 temp
= LHS
- LSImmRHS
;
1724 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
1728 case 0x58 : /* Store Word, No WriteBack, Pre Inc, Immed */
1729 (void)StoreWord(state
,instr
,LHS
+ LSImmRHS
) ;
1732 case 0x59 : /* Load Word, No WriteBack, Pre Inc, Immed */
1733 (void)LoadWord(state
,instr
,LHS
+ LSImmRHS
) ;
1736 case 0x5a : /* Store Word, WriteBack, Pre Inc, Immed */
1737 UNDEF_LSRBaseEQDestWb
;
1739 temp
= LHS
+ LSImmRHS
;
1740 if (StoreWord(state
,instr
,temp
))
1744 case 0x5b : /* Load Word, WriteBack, Pre Inc, Immed */
1745 UNDEF_LSRBaseEQDestWb
;
1747 temp
= LHS
+ LSImmRHS
;
1748 if (LoadWord(state
,instr
,temp
))
1752 case 0x5c : /* Store Byte, No WriteBack, Pre Inc, Immed */
1753 (void)StoreByte(state
,instr
,LHS
+ LSImmRHS
) ;
1756 case 0x5d : /* Load Byte, No WriteBack, Pre Inc, Immed */
1757 (void)LoadByte(state
,instr
,LHS
+ LSImmRHS
,LUNSIGNED
) ;
1760 case 0x5e : /* Store Byte, WriteBack, Pre Inc, Immed */
1761 UNDEF_LSRBaseEQDestWb
;
1763 temp
= LHS
+ LSImmRHS
;
1764 if (StoreByte(state
,instr
,temp
))
1768 case 0x5f : /* Load Byte, WriteBack, Pre Inc, Immed */
1769 UNDEF_LSRBaseEQDestWb
;
1771 temp
= LHS
+ LSImmRHS
;
1772 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
1776 /***************************************************************************\
1777 * Single Data Transfer Register RHS Instructions *
1778 \***************************************************************************/
1780 case 0x60 : /* Store Word, No WriteBack, Post Dec, Reg */
1782 ARMul_UndefInstr(state
,instr
) ;
1785 UNDEF_LSRBaseEQOffWb
;
1786 UNDEF_LSRBaseEQDestWb
;
1790 if (StoreWord(state
,instr
,lhs
))
1791 LSBase
= lhs
- LSRegRHS
;
1794 case 0x61 : /* Load Word, No WriteBack, Post Dec, Reg */
1796 ARMul_UndefInstr(state
,instr
) ;
1799 UNDEF_LSRBaseEQOffWb
;
1800 UNDEF_LSRBaseEQDestWb
;
1804 if (LoadWord(state
,instr
,lhs
))
1805 LSBase
= lhs
- LSRegRHS
;
1808 case 0x62 : /* Store Word, WriteBack, Post Dec, Reg */
1810 ARMul_UndefInstr(state
,instr
) ;
1813 UNDEF_LSRBaseEQOffWb
;
1814 UNDEF_LSRBaseEQDestWb
;
1818 state
->NtransSig
= LOW
;
1819 if (StoreWord(state
,instr
,lhs
))
1820 LSBase
= lhs
- LSRegRHS
;
1821 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1824 case 0x63 : /* Load Word, WriteBack, Post Dec, Reg */
1826 ARMul_UndefInstr(state
,instr
) ;
1829 UNDEF_LSRBaseEQOffWb
;
1830 UNDEF_LSRBaseEQDestWb
;
1834 state
->NtransSig
= LOW
;
1835 if (LoadWord(state
,instr
,lhs
))
1836 LSBase
= lhs
- LSRegRHS
;
1837 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1840 case 0x64 : /* Store Byte, No WriteBack, Post Dec, Reg */
1842 ARMul_UndefInstr(state
,instr
) ;
1845 UNDEF_LSRBaseEQOffWb
;
1846 UNDEF_LSRBaseEQDestWb
;
1850 if (StoreByte(state
,instr
,lhs
))
1851 LSBase
= lhs
- LSRegRHS
;
1854 case 0x65 : /* Load Byte, No WriteBack, Post Dec, Reg */
1856 ARMul_UndefInstr(state
,instr
) ;
1859 UNDEF_LSRBaseEQOffWb
;
1860 UNDEF_LSRBaseEQDestWb
;
1864 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1865 LSBase
= lhs
- LSRegRHS
;
1868 case 0x66 : /* Store Byte, WriteBack, Post Dec, Reg */
1870 ARMul_UndefInstr(state
,instr
) ;
1873 UNDEF_LSRBaseEQOffWb
;
1874 UNDEF_LSRBaseEQDestWb
;
1878 state
->NtransSig
= LOW
;
1879 if (StoreByte(state
,instr
,lhs
))
1880 LSBase
= lhs
- LSRegRHS
;
1881 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1884 case 0x67 : /* Load Byte, WriteBack, Post Dec, Reg */
1886 ARMul_UndefInstr(state
,instr
) ;
1889 UNDEF_LSRBaseEQOffWb
;
1890 UNDEF_LSRBaseEQDestWb
;
1894 state
->NtransSig
= LOW
;
1895 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1896 LSBase
= lhs
- LSRegRHS
;
1897 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1900 case 0x68 : /* Store Word, No WriteBack, Post Inc, Reg */
1902 ARMul_UndefInstr(state
,instr
) ;
1905 UNDEF_LSRBaseEQOffWb
;
1906 UNDEF_LSRBaseEQDestWb
;
1910 if (StoreWord(state
,instr
,lhs
))
1911 LSBase
= lhs
+ LSRegRHS
;
1914 case 0x69 : /* Load Word, No WriteBack, Post Inc, Reg */
1916 ARMul_UndefInstr(state
,instr
) ;
1919 UNDEF_LSRBaseEQOffWb
;
1920 UNDEF_LSRBaseEQDestWb
;
1924 if (LoadWord(state
,instr
,lhs
))
1925 LSBase
= lhs
+ LSRegRHS
;
1928 case 0x6a : /* Store Word, WriteBack, Post Inc, Reg */
1930 ARMul_UndefInstr(state
,instr
) ;
1933 UNDEF_LSRBaseEQOffWb
;
1934 UNDEF_LSRBaseEQDestWb
;
1938 state
->NtransSig
= LOW
;
1939 if (StoreWord(state
,instr
,lhs
))
1940 LSBase
= lhs
+ LSRegRHS
;
1941 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1944 case 0x6b : /* Load Word, WriteBack, Post Inc, Reg */
1946 ARMul_UndefInstr(state
,instr
) ;
1949 UNDEF_LSRBaseEQOffWb
;
1950 UNDEF_LSRBaseEQDestWb
;
1954 state
->NtransSig
= LOW
;
1955 if (LoadWord(state
,instr
,lhs
))
1956 LSBase
= lhs
+ LSRegRHS
;
1957 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1960 case 0x6c : /* Store Byte, No WriteBack, Post Inc, Reg */
1962 ARMul_UndefInstr(state
,instr
) ;
1965 UNDEF_LSRBaseEQOffWb
;
1966 UNDEF_LSRBaseEQDestWb
;
1970 if (StoreByte(state
,instr
,lhs
))
1971 LSBase
= lhs
+ LSRegRHS
;
1974 case 0x6d : /* Load Byte, No WriteBack, Post Inc, Reg */
1976 ARMul_UndefInstr(state
,instr
) ;
1979 UNDEF_LSRBaseEQOffWb
;
1980 UNDEF_LSRBaseEQDestWb
;
1984 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1985 LSBase
= lhs
+ LSRegRHS
;
1988 case 0x6e : /* Store Byte, WriteBack, Post Inc, Reg */
1990 ARMul_UndefInstr(state
,instr
) ;
1993 UNDEF_LSRBaseEQOffWb
;
1994 UNDEF_LSRBaseEQDestWb
;
1998 state
->NtransSig
= LOW
;
1999 if (StoreByte(state
,instr
,lhs
))
2000 LSBase
= lhs
+ LSRegRHS
;
2001 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
2004 case 0x6f : /* Load Byte, WriteBack, Post Inc, Reg */
2006 ARMul_UndefInstr(state
,instr
) ;
2009 UNDEF_LSRBaseEQOffWb
;
2010 UNDEF_LSRBaseEQDestWb
;
2014 state
->NtransSig
= LOW
;
2015 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
2016 LSBase
= lhs
+ LSRegRHS
;
2017 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
2021 case 0x70 : /* Store Word, No WriteBack, Pre Dec, Reg */
2023 ARMul_UndefInstr(state
,instr
) ;
2026 (void)StoreWord(state
,instr
,LHS
- LSRegRHS
) ;
2029 case 0x71 : /* Load Word, No WriteBack, Pre Dec, Reg */
2031 ARMul_UndefInstr(state
,instr
) ;
2034 (void)LoadWord(state
,instr
,LHS
- LSRegRHS
) ;
2037 case 0x72 : /* Store Word, WriteBack, Pre Dec, Reg */
2039 ARMul_UndefInstr(state
,instr
) ;
2042 UNDEF_LSRBaseEQOffWb
;
2043 UNDEF_LSRBaseEQDestWb
;
2046 temp
= LHS
- LSRegRHS
;
2047 if (StoreWord(state
,instr
,temp
))
2051 case 0x73 : /* Load Word, WriteBack, Pre Dec, Reg */
2053 ARMul_UndefInstr(state
,instr
) ;
2056 UNDEF_LSRBaseEQOffWb
;
2057 UNDEF_LSRBaseEQDestWb
;
2060 temp
= LHS
- LSRegRHS
;
2061 if (LoadWord(state
,instr
,temp
))
2065 case 0x74 : /* Store Byte, No WriteBack, Pre Dec, Reg */
2067 ARMul_UndefInstr(state
,instr
) ;
2070 (void)StoreByte(state
,instr
,LHS
- LSRegRHS
) ;
2073 case 0x75 : /* Load Byte, No WriteBack, Pre Dec, Reg */
2075 ARMul_UndefInstr(state
,instr
) ;
2078 (void)LoadByte(state
,instr
,LHS
- LSRegRHS
,LUNSIGNED
) ;
2081 case 0x76 : /* Store Byte, WriteBack, Pre Dec, Reg */
2083 ARMul_UndefInstr(state
,instr
) ;
2086 UNDEF_LSRBaseEQOffWb
;
2087 UNDEF_LSRBaseEQDestWb
;
2090 temp
= LHS
- LSRegRHS
;
2091 if (StoreByte(state
,instr
,temp
))
2095 case 0x77 : /* Load Byte, WriteBack, Pre Dec, Reg */
2097 ARMul_UndefInstr(state
,instr
) ;
2100 UNDEF_LSRBaseEQOffWb
;
2101 UNDEF_LSRBaseEQDestWb
;
2104 temp
= LHS
- LSRegRHS
;
2105 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
2109 case 0x78 : /* Store Word, No WriteBack, Pre Inc, Reg */
2111 ARMul_UndefInstr(state
,instr
) ;
2114 (void)StoreWord(state
,instr
,LHS
+ LSRegRHS
) ;
2117 case 0x79 : /* Load Word, No WriteBack, Pre Inc, Reg */
2119 ARMul_UndefInstr(state
,instr
) ;
2122 (void)LoadWord(state
,instr
,LHS
+ LSRegRHS
) ;
2125 case 0x7a : /* Store Word, WriteBack, Pre Inc, Reg */
2127 ARMul_UndefInstr(state
,instr
) ;
2130 UNDEF_LSRBaseEQOffWb
;
2131 UNDEF_LSRBaseEQDestWb
;
2134 temp
= LHS
+ LSRegRHS
;
2135 if (StoreWord(state
,instr
,temp
))
2139 case 0x7b : /* Load Word, WriteBack, Pre Inc, Reg */
2141 ARMul_UndefInstr(state
,instr
) ;
2144 UNDEF_LSRBaseEQOffWb
;
2145 UNDEF_LSRBaseEQDestWb
;
2148 temp
= LHS
+ LSRegRHS
;
2149 if (LoadWord(state
,instr
,temp
))
2153 case 0x7c : /* Store Byte, No WriteBack, Pre Inc, Reg */
2155 ARMul_UndefInstr(state
,instr
) ;
2158 (void)StoreByte(state
,instr
,LHS
+ LSRegRHS
) ;
2161 case 0x7d : /* Load Byte, No WriteBack, Pre Inc, Reg */
2163 ARMul_UndefInstr(state
,instr
) ;
2166 (void)LoadByte(state
,instr
,LHS
+ LSRegRHS
,LUNSIGNED
) ;
2169 case 0x7e : /* Store Byte, WriteBack, Pre Inc, Reg */
2171 ARMul_UndefInstr(state
,instr
) ;
2174 UNDEF_LSRBaseEQOffWb
;
2175 UNDEF_LSRBaseEQDestWb
;
2178 temp
= LHS
+ LSRegRHS
;
2179 if (StoreByte(state
,instr
,temp
))
2183 case 0x7f : /* Load Byte, WriteBack, Pre Inc, Reg */
2186 /* Check for the special breakpoint opcode.
2187 This value should correspond to the value defined
2188 as ARM_BE_BREAKPOINT in gdb/arm-tdep.c. */
2189 if (BITS (0,19) == 0xfdefe)
2191 if (! ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2192 ARMul_Abort (state
, ARMul_SWIV
);
2195 ARMul_UndefInstr(state
,instr
) ;
2198 UNDEF_LSRBaseEQOffWb
;
2199 UNDEF_LSRBaseEQDestWb
;
2202 temp
= LHS
+ LSRegRHS
;
2203 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
2207 /***************************************************************************\
2208 * Multiple Data Transfer Instructions *
2209 \***************************************************************************/
2211 case 0x80 : /* Store, No WriteBack, Post Dec */
2212 STOREMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2215 case 0x81 : /* Load, No WriteBack, Post Dec */
2216 LOADMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2219 case 0x82 : /* Store, WriteBack, Post Dec */
2220 temp
= LSBase
- LSMNumRegs
;
2221 STOREMULT(instr
,temp
+ 4L,temp
) ;
2224 case 0x83 : /* Load, WriteBack, Post Dec */
2225 temp
= LSBase
- LSMNumRegs
;
2226 LOADMULT(instr
,temp
+ 4L,temp
) ;
2229 case 0x84 : /* Store, Flags, No WriteBack, Post Dec */
2230 STORESMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2233 case 0x85 : /* Load, Flags, No WriteBack, Post Dec */
2234 LOADSMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2237 case 0x86 : /* Store, Flags, WriteBack, Post Dec */
2238 temp
= LSBase
- LSMNumRegs
;
2239 STORESMULT(instr
,temp
+ 4L,temp
) ;
2242 case 0x87 : /* Load, Flags, WriteBack, Post Dec */
2243 temp
= LSBase
- LSMNumRegs
;
2244 LOADSMULT(instr
,temp
+ 4L,temp
) ;
2248 case 0x88 : /* Store, No WriteBack, Post Inc */
2249 STOREMULT(instr
,LSBase
,0L) ;
2252 case 0x89 : /* Load, No WriteBack, Post Inc */
2253 LOADMULT(instr
,LSBase
,0L) ;
2256 case 0x8a : /* Store, WriteBack, Post Inc */
2258 STOREMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2261 case 0x8b : /* Load, WriteBack, Post Inc */
2263 LOADMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2266 case 0x8c : /* Store, Flags, No WriteBack, Post Inc */
2267 STORESMULT(instr
,LSBase
,0L) ;
2270 case 0x8d : /* Load, Flags, No WriteBack, Post Inc */
2271 LOADSMULT(instr
,LSBase
,0L) ;
2274 case 0x8e : /* Store, Flags, WriteBack, Post Inc */
2276 STORESMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2279 case 0x8f : /* Load, Flags, WriteBack, Post Inc */
2281 LOADSMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2285 case 0x90 : /* Store, No WriteBack, Pre Dec */
2286 STOREMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2289 case 0x91 : /* Load, No WriteBack, Pre Dec */
2290 LOADMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2293 case 0x92 : /* Store, WriteBack, Pre Dec */
2294 temp
= LSBase
- LSMNumRegs
;
2295 STOREMULT(instr
,temp
,temp
) ;
2298 case 0x93 : /* Load, WriteBack, Pre Dec */
2299 temp
= LSBase
- LSMNumRegs
;
2300 LOADMULT(instr
,temp
,temp
) ;
2303 case 0x94 : /* Store, Flags, No WriteBack, Pre Dec */
2304 STORESMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2307 case 0x95 : /* Load, Flags, No WriteBack, Pre Dec */
2308 LOADSMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2311 case 0x96 : /* Store, Flags, WriteBack, Pre Dec */
2312 temp
= LSBase
- LSMNumRegs
;
2313 STORESMULT(instr
,temp
,temp
) ;
2316 case 0x97 : /* Load, Flags, WriteBack, Pre Dec */
2317 temp
= LSBase
- LSMNumRegs
;
2318 LOADSMULT(instr
,temp
,temp
) ;
2322 case 0x98 : /* Store, No WriteBack, Pre Inc */
2323 STOREMULT(instr
,LSBase
+ 4L,0L) ;
2326 case 0x99 : /* Load, No WriteBack, Pre Inc */
2327 LOADMULT(instr
,LSBase
+ 4L,0L) ;
2330 case 0x9a : /* Store, WriteBack, Pre Inc */
2332 STOREMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2335 case 0x9b : /* Load, WriteBack, Pre Inc */
2337 LOADMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2340 case 0x9c : /* Store, Flags, No WriteBack, Pre Inc */
2341 STORESMULT(instr
,LSBase
+ 4L,0L) ;
2344 case 0x9d : /* Load, Flags, No WriteBack, Pre Inc */
2345 LOADSMULT(instr
,LSBase
+ 4L,0L) ;
2348 case 0x9e : /* Store, Flags, WriteBack, Pre Inc */
2350 STORESMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2353 case 0x9f : /* Load, Flags, WriteBack, Pre Inc */
2355 LOADSMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2358 /***************************************************************************\
2360 \***************************************************************************/
2362 case 0xa0 : case 0xa1 : case 0xa2 : case 0xa3 :
2363 case 0xa4 : case 0xa5 : case 0xa6 : case 0xa7 :
2364 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2368 /***************************************************************************\
2370 \***************************************************************************/
2372 case 0xa8 : case 0xa9 : case 0xaa : case 0xab :
2373 case 0xac : case 0xad : case 0xae : case 0xaf :
2374 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2378 /***************************************************************************\
2379 * Branch and Link forward *
2380 \***************************************************************************/
2382 case 0xb0 : case 0xb1 : case 0xb2 : case 0xb3 :
2383 case 0xb4 : case 0xb5 : case 0xb6 : case 0xb7 :
2385 state
->Reg
[14] = pc
+ 4 ; /* put PC into Link */
2387 state
->Reg
[14] = pc
+ 4 | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2389 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2393 /***************************************************************************\
2394 * Branch and Link backward *
2395 \***************************************************************************/
2397 case 0xb8 : case 0xb9 : case 0xba : case 0xbb :
2398 case 0xbc : case 0xbd : case 0xbe : case 0xbf :
2400 state
->Reg
[14] = pc
+ 4 ; /* put PC into Link */
2402 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2404 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2408 /***************************************************************************\
2409 * Co-Processor Data Transfers *
2410 \***************************************************************************/
2413 case 0xc0 : /* Store , No WriteBack , Post Dec */
2414 ARMul_STC(state
,instr
,LHS
) ;
2418 case 0xc1 : /* Load , No WriteBack , Post Dec */
2419 ARMul_LDC(state
,instr
,LHS
) ;
2423 case 0xc6 : /* Store , WriteBack , Post Dec */
2425 state
->Base
= lhs
- LSCOff
;
2426 ARMul_STC(state
,instr
,lhs
) ;
2430 case 0xc7 : /* Load , WriteBack , Post Dec */
2432 state
->Base
= lhs
- LSCOff
;
2433 ARMul_LDC(state
,instr
,lhs
) ;
2437 case 0xcc : /* Store , No WriteBack , Post Inc */
2438 ARMul_STC(state
,instr
,LHS
) ;
2442 case 0xcd : /* Load , No WriteBack , Post Inc */
2443 ARMul_LDC(state
,instr
,LHS
) ;
2447 case 0xce : /* Store , WriteBack , Post Inc */
2449 state
->Base
= lhs
+ LSCOff
;
2450 ARMul_STC(state
,instr
,LHS
) ;
2454 case 0xcf : /* Load , WriteBack , Post Inc */
2456 state
->Base
= lhs
+ LSCOff
;
2457 ARMul_LDC(state
,instr
,LHS
) ;
2462 case 0xd4 : /* Store , No WriteBack , Pre Dec */
2463 ARMul_STC(state
,instr
,LHS
- LSCOff
) ;
2467 case 0xd5 : /* Load , No WriteBack , Pre Dec */
2468 ARMul_LDC(state
,instr
,LHS
- LSCOff
) ;
2472 case 0xd6 : /* Store , WriteBack , Pre Dec */
2473 lhs
= LHS
- LSCOff
;
2475 ARMul_STC(state
,instr
,lhs
) ;
2479 case 0xd7 : /* Load , WriteBack , Pre Dec */
2480 lhs
= LHS
- LSCOff
;
2482 ARMul_LDC(state
,instr
,lhs
) ;
2486 case 0xdc : /* Store , No WriteBack , Pre Inc */
2487 ARMul_STC(state
,instr
,LHS
+ LSCOff
) ;
2491 case 0xdd : /* Load , No WriteBack , Pre Inc */
2492 ARMul_LDC(state
,instr
,LHS
+ LSCOff
) ;
2496 case 0xde : /* Store , WriteBack , Pre Inc */
2497 lhs
= LHS
+ LSCOff
;
2499 ARMul_STC(state
,instr
,lhs
) ;
2503 case 0xdf : /* Load , WriteBack , Pre Inc */
2504 lhs
= LHS
+ LSCOff
;
2506 ARMul_LDC(state
,instr
,lhs
) ;
2509 /***************************************************************************\
2510 * Co-Processor Register Transfers (MCR) and Data Ops *
2511 \***************************************************************************/
2514 case 0xe0 : 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 */
This page took 0.130014 seconds and 4 git commands to generate.