36b7bba4d106aca41cf76a719149fba939a7c4ab
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 */
467 switch ((int)BITS(20,27)) {
469 /***************************************************************************\
470 * Data Processing Register RHS Instructions *
471 \***************************************************************************/
473 case 0x00 : /* AND reg and MUL */
475 if (BITS(4,11) == 0xB) {
476 /* STRH register offset, no write-back, down, post indexed */
480 /* TODO: CHECK: should 0xD and 0xF generate undefined intruction aborts? */
482 if (BITS(4,7) == 9) { /* MUL */
483 rhs
= state
->Reg
[MULRHSReg
] ;
484 if (MULLHSReg
== MULDESTReg
) {
486 state
->Reg
[MULDESTReg
] = 0 ;
488 else if (MULDESTReg
!= 15)
489 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
493 for (dest
= 0, temp
= 0 ; dest
< 32 ; dest
++)
494 if (rhs
& (1L << dest
))
495 temp
= dest
; /* mult takes this many/2 I cycles */
496 ARMul_Icycles(state
,ARMul_MultTable
[temp
],0L) ;
505 case 0x01 : /* ANDS reg and MULS */
507 if ((BITS(4,11) & 0xF9) == 0x9) {
508 /* LDR register offset, no write-back, down, post indexed */
510 /* fall through to rest of decoding */
513 if (BITS(4,7) == 9) { /* MULS */
514 rhs
= state
->Reg
[MULRHSReg
] ;
515 if (MULLHSReg
== MULDESTReg
) {
517 state
->Reg
[MULDESTReg
] = 0 ;
521 else if (MULDESTReg
!= 15) {
522 dest
= state
->Reg
[MULLHSReg
] * rhs
;
523 ARMul_NegZero(state
,dest
) ;
524 state
->Reg
[MULDESTReg
] = dest
;
529 for (dest
= 0, temp
= 0 ; dest
< 32 ; dest
++)
530 if (rhs
& (1L << dest
))
531 temp
= dest
; /* mult takes this many/2 I cycles */
532 ARMul_Icycles(state
,ARMul_MultTable
[temp
],0L) ;
534 else { /* ANDS reg */
541 case 0x02 : /* EOR reg and MLA */
543 if (BITS(4,11) == 0xB) {
544 /* STRH register offset, write-back, down, post indexed */
549 if (BITS(4,7) == 9) { /* MLA */
550 rhs
= state
->Reg
[MULRHSReg
] ;
551 if (MULLHSReg
== MULDESTReg
) {
553 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
] ;
555 else if (MULDESTReg
!= 15)
556 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
] ;
560 for (dest
= 0, temp
= 0 ; dest
< 32 ; dest
++)
561 if (rhs
& (1L << dest
))
562 temp
= dest
; /* mult takes this many/2 I cycles */
563 ARMul_Icycles(state
,ARMul_MultTable
[temp
],0L) ;
572 case 0x03 : /* EORS reg and MLAS */
574 if ((BITS(4,11) & 0xF9) == 0x9) {
575 /* LDR register offset, write-back, down, post-indexed */
577 /* fall through to rest of the decoding */
580 if (BITS(4,7) == 9) { /* MLAS */
581 rhs
= state
->Reg
[MULRHSReg
] ;
582 if (MULLHSReg
== MULDESTReg
) {
584 dest
= state
->Reg
[MULACCReg
] ;
585 ARMul_NegZero(state
,dest
) ;
586 state
->Reg
[MULDESTReg
] = dest
;
588 else if (MULDESTReg
!= 15) {
589 dest
= state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
] ;
590 ARMul_NegZero(state
,dest
) ;
591 state
->Reg
[MULDESTReg
] = dest
;
596 for (dest
= 0, temp
= 0 ; dest
< 32 ; dest
++)
597 if (rhs
& (1L << dest
))
598 temp
= dest
; /* mult takes this many/2 I cycles */
599 ARMul_Icycles(state
,ARMul_MultTable
[temp
],0L) ;
601 else { /* EORS Reg */
608 case 0x04 : /* SUB reg */
610 if (BITS(4,7) == 0xB) {
611 /* STRH immediate offset, no write-back, down, post indexed */
621 case 0x05 : /* SUBS reg */
623 if ((BITS(4,7) & 0x9) == 0x9) {
624 /* LDR immediate offset, no write-back, down, post indexed */
626 /* fall through to the rest of the instruction decoding */
632 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
633 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
634 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
643 case 0x06 : /* RSB reg */
645 if (BITS(4,7) == 0xB) {
646 /* STRH immediate offset, write-back, down, post indexed */
656 case 0x07 : /* RSBS reg */
658 if ((BITS(4,7) & 0x9) == 0x9) {
659 /* LDR immediate offset, write-back, down, post indexed */
661 /* fall through to remainder of instruction decoding */
667 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31)) {
668 ARMul_SubCarry(state
,rhs
,lhs
,dest
) ;
669 ARMul_SubOverflow(state
,rhs
,lhs
,dest
) ;
678 case 0x08 : /* ADD reg */
680 if (BITS(4,11) == 0xB) {
681 /* STRH register offset, no write-back, up, post indexed */
687 if (BITS(4,7) == 0x9) { /* MULL */
689 ARMul_Icycles(state
,Multiply64(state
,instr
,LUNSIGNED
,LDEFAULT
),0L) ;
698 case 0x09 : /* ADDS reg */
700 if ((BITS(4,11) & 0xF9) == 0x9) {
701 /* LDR register offset, no write-back, up, post indexed */
703 /* fall through to remaining instruction decoding */
707 if (BITS(4,7) == 0x9) { /* MULL */
709 ARMul_Icycles(state
,Multiply64(state
,instr
,LUNSIGNED
,LSCC
),0L) ;
717 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
719 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
720 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
730 case 0x0a : /* ADC reg */
732 if (BITS(4,11) == 0xB) {
733 /* STRH register offset, write-back, up, post-indexed */
739 if (BITS(4,7) == 0x9) { /* MULL */
741 ARMul_Icycles(state
,MultiplyAdd64(state
,instr
,LUNSIGNED
,LDEFAULT
),0L) ;
746 dest
= LHS
+ rhs
+ CFLAG
;
750 case 0x0b : /* ADCS reg */
752 if ((BITS(4,11) & 0xF9) == 0x9) {
753 /* LDR register offset, write-back, up, post indexed */
755 /* fall through to remaining instruction decoding */
759 if (BITS(4,7) == 0x9) { /* MULL */
761 ARMul_Icycles(state
,MultiplyAdd64(state
,instr
,LUNSIGNED
,LSCC
),0L) ;
767 dest
= lhs
+ rhs
+ CFLAG
;
769 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
771 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
772 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
782 case 0x0c : /* SBC reg */
784 if (BITS(4,7) == 0xB) {
785 /* STRH immediate offset, no write-back, up post indexed */
791 if (BITS(4,7) == 0x9) { /* MULL */
793 ARMul_Icycles(state
,Multiply64(state
,instr
,LSIGNED
,LDEFAULT
),0L) ;
798 dest
= LHS
- rhs
- !CFLAG
;
802 case 0x0d : /* SBCS reg */
804 if ((BITS(4,7) & 0x9) == 0x9) {
805 /* LDR immediate offset, no write-back, up, post indexed */
810 if (BITS(4,7) == 0x9) { /* MULL */
812 ARMul_Icycles(state
,Multiply64(state
,instr
,LSIGNED
,LSCC
),0L) ;
818 dest
= lhs
- rhs
- !CFLAG
;
819 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
820 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
821 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
830 case 0x0e : /* RSC reg */
832 if (BITS(4,7) == 0xB) {
833 /* STRH immediate offset, write-back, up, post indexed */
839 if (BITS(4,7) == 0x9) { /* MULL */
841 ARMul_Icycles(state
,MultiplyAdd64(state
,instr
,LSIGNED
,LDEFAULT
),0L) ;
846 dest
= rhs
- LHS
- !CFLAG
;
850 case 0x0f : /* RSCS reg */
852 if ((BITS(4,7) & 0x9) == 0x9) {
853 /* LDR immediate offset, write-back, up, post indexed */
855 /* fall through to remaining instruction decoding */
859 if (BITS(4,7) == 0x9) { /* MULL */
861 ARMul_Icycles(state
,MultiplyAdd64(state
,instr
,LSIGNED
,LSCC
),0L) ;
867 dest
= rhs
- lhs
- !CFLAG
;
868 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31)) {
869 ARMul_SubCarry(state
,rhs
,lhs
,dest
) ;
870 ARMul_SubOverflow(state
,rhs
,lhs
,dest
) ;
879 case 0x10 : /* TST reg and MRS CPSR and SWP word */
881 if (BITS(4,11) == 0xB) {
882 /* STRH register offset, no write-back, down, pre indexed */
887 if (BITS(4,11) == 9) { /* SWP */
892 if (VECTORACCESS(temp
) || ADDREXCEPT(temp
)) {
893 INTERNALABORT(temp
) ;
894 (void)ARMul_LoadWordN(state
,temp
) ;
895 (void)ARMul_LoadWordN(state
,temp
) ;
899 dest
= ARMul_SwapWord(state
,temp
,state
->Reg
[RHSReg
]) ;
901 DEST
= ARMul_Align(state
,temp
,dest
) ;
904 if (state
->abortSig
|| state
->Aborted
) {
908 else if ((BITS(0,11)==0) && (LHSReg
==15)) { /* MRS CPSR */
910 DEST
= ECC
| EINT
| EMODE
;
917 case 0x11 : /* TSTP reg */
919 if ((BITS(4,11) & 0xF9) == 0x9) {
920 /* LDR register offset, no write-back, down, pre indexed */
922 /* continue with remaining instruction decode */
925 if (DESTReg
== 15) { /* TSTP reg */
927 state
->Cpsr
= GETSPSR(state
->Bank
) ;
928 ARMul_CPSRAltered(state
) ;
938 ARMul_NegZero(state
,dest
) ;
942 case 0x12 : /* TEQ reg and MSR reg to CPSR (ARM6) */
944 if (BITS(4,11) == 0xB) {
945 /* STRH register offset, write-back, down, pre indexed */
951 if (BITS(4,27)==0x12FFF1) { /* BX */
952 /* Branch to the address in RHSReg. If bit0 of
953 destination address is 1 then switch to Thumb mode: */
954 ARMword addr
= state
->Reg
[RHSReg
];
956 /* If we read the PC then the bottom bit is clear */
957 if (RHSReg
== 15) addr
&= ~1;
959 /* Enable this for a helpful bit of debugging when
960 GDB is not yet fully working...
961 fprintf (stderr, "BX at %x to %x (go %s)\n",
962 state->Reg[15], addr, (addr & 1) ? "thumb": "arm" ); */
964 if (addr
& (1 << 0)) { /* Thumb bit */
966 state
->Reg
[15] = addr
& 0xfffffffe;
967 /* NOTE: The other CPSR flag setting blocks do not
968 seem to update the state->Cpsr state, but just do
969 the explicit flag. The copy from the seperate
970 flags to the register must happen later. */
974 state
->Reg
[15] = addr
& 0xfffffffc;
979 if (DESTReg
==15 && BITS(17,18)==0) { /* MSR reg to CPSR */
982 ARMul_FixCPSR(state
,instr
,temp
) ;
989 case 0x13 : /* TEQP reg */
991 if ((BITS(4,11) & 0xF9) == 0x9) {
992 /* LDR register offset, write-back, down, pre indexed */
994 /* continue with remaining instruction decode */
997 if (DESTReg
== 15) { /* TEQP reg */
999 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1000 ARMul_CPSRAltered(state
) ;
1007 else { /* TEQ Reg */
1010 ARMul_NegZero(state
,dest
) ;
1014 case 0x14 : /* CMP reg and MRS SPSR and SWP byte */
1016 if (BITS(4,7) == 0xB) {
1017 /* STRH immediate offset, no write-back, down, pre indexed */
1022 if (BITS(4,11) == 9) { /* SWP */
1027 if (VECTORACCESS(temp
) || ADDREXCEPT(temp
)) {
1028 INTERNALABORT(temp
) ;
1029 (void)ARMul_LoadByte(state
,temp
) ;
1030 (void)ARMul_LoadByte(state
,temp
) ;
1034 DEST
= ARMul_SwapByte(state
,temp
,state
->Reg
[RHSReg
]) ;
1035 if (state
->abortSig
|| state
->Aborted
) {
1039 else if ((BITS(0,11)==0) && (LHSReg
==15)) { /* MRS SPSR */
1041 DEST
= GETSPSR(state
->Bank
) ;
1048 case 0x15 : /* CMPP reg */
1050 if ((BITS(4,7) & 0x9) == 0x9) {
1051 /* LDR immediate offset, no write-back, down, pre indexed */
1053 /* continue with remaining instruction decode */
1056 if (DESTReg
== 15) { /* CMPP reg */
1058 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1059 ARMul_CPSRAltered(state
) ;
1066 else { /* CMP reg */
1070 ARMul_NegZero(state
,dest
) ;
1071 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1072 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1073 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1082 case 0x16 : /* CMN reg and MSR reg to SPSR */
1084 if (BITS(4,7) == 0xB) {
1085 /* STRH immediate offset, write-back, down, pre indexed */
1090 if (DESTReg
==15 && BITS(17,18)==0) { /* MSR */
1092 ARMul_FixSPSR(state
,instr
,DPRegRHS
);
1099 case 0x17 : /* CMNP reg */
1101 if ((BITS(4,7) & 0x9) == 0x9) {
1102 /* LDR immediate offset, write-back, down, pre indexed */
1104 /* continue with remaining instruction decoding */
1107 if (DESTReg
== 15) {
1109 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1110 ARMul_CPSRAltered(state
) ;
1118 else { /* CMN reg */
1123 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1124 ASSIGNN(NEG(dest
)) ;
1125 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1126 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1136 case 0x18 : /* ORR reg */
1138 if (BITS(4,11) == 0xB) {
1139 /* STRH register offset, no write-back, up, pre indexed */
1149 case 0x19 : /* ORRS reg */
1151 if ((BITS(4,11) & 0xF9) == 0x9) {
1152 /* LDR register offset, no write-back, up, pre indexed */
1154 /* continue with remaining instruction decoding */
1162 case 0x1a : /* MOV reg */
1164 if (BITS(4,11) == 0xB) {
1165 /* STRH register offset, write-back, up, pre indexed */
1174 case 0x1b : /* MOVS reg */
1176 if ((BITS(4,11) & 0xF9) == 0x9) {
1177 /* LDR register offset, write-back, up, pre indexed */
1179 /* continue with remaining instruction decoding */
1186 case 0x1c : /* BIC reg */
1188 if (BITS(4,7) == 0xB) {
1189 /* STRH immediate offset, no write-back, up, pre indexed */
1199 case 0x1d : /* BICS reg */
1201 if ((BITS(4,7) & 0x9) == 0x9) {
1202 /* LDR immediate offset, no write-back, up, pre indexed */
1204 /* continue with instruction decoding */
1212 case 0x1e : /* MVN reg */
1214 if (BITS(4,7) == 0xB) {
1215 /* STRH immediate offset, write-back, up, pre indexed */
1224 case 0x1f : /* MVNS reg */
1226 if ((BITS(4,7) & 0x9) == 0x9) {
1227 /* LDR immediate offset, write-back, up, pre indexed */
1229 /* continue instruction decoding */
1236 /***************************************************************************\
1237 * Data Processing Immediate RHS Instructions *
1238 \***************************************************************************/
1240 case 0x20 : /* AND immed */
1241 dest
= LHS
& DPImmRHS
;
1245 case 0x21 : /* ANDS immed */
1251 case 0x22 : /* EOR immed */
1252 dest
= LHS
^ DPImmRHS
;
1256 case 0x23 : /* EORS immed */
1262 case 0x24 : /* SUB immed */
1263 dest
= LHS
- DPImmRHS
;
1267 case 0x25 : /* SUBS immed */
1271 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1272 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1273 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1282 case 0x26 : /* RSB immed */
1283 dest
= DPImmRHS
- LHS
;
1287 case 0x27 : /* RSBS immed */
1291 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31)) {
1292 ARMul_SubCarry(state
,rhs
,lhs
,dest
) ;
1293 ARMul_SubOverflow(state
,rhs
,lhs
,dest
) ;
1302 case 0x28 : /* ADD immed */
1303 dest
= LHS
+ DPImmRHS
;
1307 case 0x29 : /* ADDS immed */
1312 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1313 ASSIGNN(NEG(dest
)) ;
1314 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1315 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1325 case 0x2a : /* ADC immed */
1326 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1330 case 0x2b : /* ADCS immed */
1333 dest
= lhs
+ rhs
+ CFLAG
;
1335 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1336 ASSIGNN(NEG(dest
)) ;
1337 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1338 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1348 case 0x2c : /* SBC immed */
1349 dest
= LHS
- DPImmRHS
- !CFLAG
;
1353 case 0x2d : /* SBCS immed */
1356 dest
= lhs
- rhs
- !CFLAG
;
1357 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1358 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1359 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1368 case 0x2e : /* RSC immed */
1369 dest
= DPImmRHS
- LHS
- !CFLAG
;
1373 case 0x2f : /* RSCS immed */
1376 dest
= rhs
- lhs
- !CFLAG
;
1377 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31)) {
1378 ARMul_SubCarry(state
,rhs
,lhs
,dest
) ;
1379 ARMul_SubOverflow(state
,rhs
,lhs
,dest
) ;
1388 case 0x30 : /* TST immed */
1392 case 0x31 : /* TSTP immed */
1393 if (DESTReg
== 15) { /* TSTP immed */
1395 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1396 ARMul_CPSRAltered(state
) ;
1398 temp
= LHS
& DPImmRHS
;
1403 DPSImmRHS
; /* TST immed */
1405 ARMul_NegZero(state
,dest
) ;
1409 case 0x32 : /* TEQ immed and MSR immed to CPSR */
1410 if (DESTReg
==15 && BITS(17,18)==0) { /* MSR immed to CPSR */
1411 ARMul_FixCPSR(state
,instr
,DPImmRHS
) ;
1418 case 0x33 : /* TEQP immed */
1419 if (DESTReg
== 15) { /* TEQP immed */
1421 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1422 ARMul_CPSRAltered(state
) ;
1424 temp
= LHS
^ DPImmRHS
;
1429 DPSImmRHS
; /* TEQ immed */
1431 ARMul_NegZero(state
,dest
) ;
1435 case 0x34 : /* CMP immed */
1439 case 0x35 : /* CMPP immed */
1440 if (DESTReg
== 15) { /* CMPP immed */
1442 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1443 ARMul_CPSRAltered(state
) ;
1445 temp
= LHS
- DPImmRHS
;
1451 lhs
= LHS
; /* CMP immed */
1454 ARMul_NegZero(state
,dest
) ;
1455 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31)) {
1456 ARMul_SubCarry(state
,lhs
,rhs
,dest
) ;
1457 ARMul_SubOverflow(state
,lhs
,rhs
,dest
) ;
1466 case 0x36 : /* CMN immed and MSR immed to SPSR */
1467 if (DESTReg
==15 && BITS(17,18)==0) /* MSR */
1468 ARMul_FixSPSR(state
, instr
, DPImmRHS
) ;
1474 case 0x37 : /* CMNP immed */
1475 if (DESTReg
== 15) { /* CMNP immed */
1477 state
->Cpsr
= GETSPSR(state
->Bank
) ;
1478 ARMul_CPSRAltered(state
) ;
1480 temp
= LHS
+ DPImmRHS
;
1486 lhs
= LHS
; /* CMN immed */
1490 if ((lhs
| rhs
) >> 30) { /* possible C,V,N to set */
1491 ASSIGNN(NEG(dest
)) ;
1492 ARMul_AddCarry(state
,lhs
,rhs
,dest
) ;
1493 ARMul_AddOverflow(state
,lhs
,rhs
,dest
) ;
1503 case 0x38 : /* ORR immed */
1504 dest
= LHS
| DPImmRHS
;
1508 case 0x39 : /* ORRS immed */
1514 case 0x3a : /* MOV immed */
1519 case 0x3b : /* MOVS immed */
1524 case 0x3c : /* BIC immed */
1525 dest
= LHS
& ~DPImmRHS
;
1529 case 0x3d : /* BICS immed */
1535 case 0x3e : /* MVN immed */
1540 case 0x3f : /* MVNS immed */
1545 /***************************************************************************\
1546 * Single Data Transfer Immediate RHS Instructions *
1547 \***************************************************************************/
1549 case 0x40 : /* Store Word, No WriteBack, Post Dec, Immed */
1551 if (StoreWord(state
,instr
,lhs
))
1552 LSBase
= lhs
- LSImmRHS
;
1555 case 0x41 : /* Load Word, No WriteBack, Post Dec, Immed */
1557 if (LoadWord(state
,instr
,lhs
))
1558 LSBase
= lhs
- LSImmRHS
;
1561 case 0x42 : /* Store Word, WriteBack, Post Dec, Immed */
1562 UNDEF_LSRBaseEQDestWb
;
1565 temp
= lhs
- LSImmRHS
;
1566 state
->NtransSig
= LOW
;
1567 if (StoreWord(state
,instr
,lhs
))
1569 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1572 case 0x43 : /* Load Word, WriteBack, Post Dec, Immed */
1573 UNDEF_LSRBaseEQDestWb
;
1576 state
->NtransSig
= LOW
;
1577 if (LoadWord(state
,instr
,lhs
))
1578 LSBase
= lhs
- LSImmRHS
;
1579 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1582 case 0x44 : /* Store Byte, No WriteBack, Post Dec, Immed */
1584 if (StoreByte(state
,instr
,lhs
))
1585 LSBase
= lhs
- LSImmRHS
;
1588 case 0x45 : /* Load Byte, No WriteBack, Post Dec, Immed */
1590 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1591 LSBase
= lhs
- LSImmRHS
;
1594 case 0x46 : /* Store Byte, WriteBack, Post Dec, Immed */
1595 UNDEF_LSRBaseEQDestWb
;
1598 state
->NtransSig
= LOW
;
1599 if (StoreByte(state
,instr
,lhs
))
1600 LSBase
= lhs
- LSImmRHS
;
1601 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1604 case 0x47 : /* Load Byte, WriteBack, Post Dec, Immed */
1605 UNDEF_LSRBaseEQDestWb
;
1608 state
->NtransSig
= LOW
;
1609 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1610 LSBase
= lhs
- LSImmRHS
;
1611 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1614 case 0x48 : /* Store Word, No WriteBack, Post Inc, Immed */
1616 if (StoreWord(state
,instr
,lhs
))
1617 LSBase
= lhs
+ LSImmRHS
;
1620 case 0x49 : /* Load Word, No WriteBack, Post Inc, Immed */
1622 if (LoadWord(state
,instr
,lhs
))
1623 LSBase
= lhs
+ LSImmRHS
;
1626 case 0x4a : /* Store Word, WriteBack, Post Inc, Immed */
1627 UNDEF_LSRBaseEQDestWb
;
1630 state
->NtransSig
= LOW
;
1631 if (StoreWord(state
,instr
,lhs
))
1632 LSBase
= lhs
+ LSImmRHS
;
1633 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1636 case 0x4b : /* Load Word, WriteBack, Post Inc, Immed */
1637 UNDEF_LSRBaseEQDestWb
;
1640 state
->NtransSig
= LOW
;
1641 if (LoadWord(state
,instr
,lhs
))
1642 LSBase
= lhs
+ LSImmRHS
;
1643 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1646 case 0x4c : /* Store Byte, No WriteBack, Post Inc, Immed */
1648 if (StoreByte(state
,instr
,lhs
))
1649 LSBase
= lhs
+ LSImmRHS
;
1652 case 0x4d : /* Load Byte, No WriteBack, Post Inc, Immed */
1654 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1655 LSBase
= lhs
+ LSImmRHS
;
1658 case 0x4e : /* Store Byte, WriteBack, Post Inc, Immed */
1659 UNDEF_LSRBaseEQDestWb
;
1662 state
->NtransSig
= LOW
;
1663 if (StoreByte(state
,instr
,lhs
))
1664 LSBase
= lhs
+ LSImmRHS
;
1665 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1668 case 0x4f : /* Load Byte, WriteBack, Post Inc, Immed */
1669 UNDEF_LSRBaseEQDestWb
;
1672 state
->NtransSig
= LOW
;
1673 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1674 LSBase
= lhs
+ LSImmRHS
;
1675 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1679 case 0x50 : /* Store Word, No WriteBack, Pre Dec, Immed */
1680 (void)StoreWord(state
,instr
,LHS
- LSImmRHS
) ;
1683 case 0x51 : /* Load Word, No WriteBack, Pre Dec, Immed */
1684 (void)LoadWord(state
,instr
,LHS
- LSImmRHS
) ;
1687 case 0x52 : /* Store Word, WriteBack, Pre Dec, Immed */
1688 UNDEF_LSRBaseEQDestWb
;
1690 temp
= LHS
- LSImmRHS
;
1691 if (StoreWord(state
,instr
,temp
))
1695 case 0x53 : /* Load Word, WriteBack, Pre Dec, Immed */
1696 UNDEF_LSRBaseEQDestWb
;
1698 temp
= LHS
- LSImmRHS
;
1699 if (LoadWord(state
,instr
,temp
))
1703 case 0x54 : /* Store Byte, No WriteBack, Pre Dec, Immed */
1704 (void)StoreByte(state
,instr
,LHS
- LSImmRHS
) ;
1707 case 0x55 : /* Load Byte, No WriteBack, Pre Dec, Immed */
1708 (void)LoadByte(state
,instr
,LHS
- LSImmRHS
,LUNSIGNED
) ;
1711 case 0x56 : /* Store Byte, WriteBack, Pre Dec, Immed */
1712 UNDEF_LSRBaseEQDestWb
;
1714 temp
= LHS
- LSImmRHS
;
1715 if (StoreByte(state
,instr
,temp
))
1719 case 0x57 : /* Load Byte, WriteBack, Pre Dec, Immed */
1720 UNDEF_LSRBaseEQDestWb
;
1722 temp
= LHS
- LSImmRHS
;
1723 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
1727 case 0x58 : /* Store Word, No WriteBack, Pre Inc, Immed */
1728 (void)StoreWord(state
,instr
,LHS
+ LSImmRHS
) ;
1731 case 0x59 : /* Load Word, No WriteBack, Pre Inc, Immed */
1732 (void)LoadWord(state
,instr
,LHS
+ LSImmRHS
) ;
1735 case 0x5a : /* Store Word, WriteBack, Pre Inc, Immed */
1736 UNDEF_LSRBaseEQDestWb
;
1738 temp
= LHS
+ LSImmRHS
;
1739 if (StoreWord(state
,instr
,temp
))
1743 case 0x5b : /* Load Word, WriteBack, Pre Inc, Immed */
1744 UNDEF_LSRBaseEQDestWb
;
1746 temp
= LHS
+ LSImmRHS
;
1747 if (LoadWord(state
,instr
,temp
))
1751 case 0x5c : /* Store Byte, No WriteBack, Pre Inc, Immed */
1752 (void)StoreByte(state
,instr
,LHS
+ LSImmRHS
) ;
1755 case 0x5d : /* Load Byte, No WriteBack, Pre Inc, Immed */
1756 (void)LoadByte(state
,instr
,LHS
+ LSImmRHS
,LUNSIGNED
) ;
1759 case 0x5e : /* Store Byte, WriteBack, Pre Inc, Immed */
1760 UNDEF_LSRBaseEQDestWb
;
1762 temp
= LHS
+ LSImmRHS
;
1763 if (StoreByte(state
,instr
,temp
))
1767 case 0x5f : /* Load Byte, WriteBack, Pre Inc, Immed */
1768 UNDEF_LSRBaseEQDestWb
;
1770 temp
= LHS
+ LSImmRHS
;
1771 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
1775 /***************************************************************************\
1776 * Single Data Transfer Register RHS Instructions *
1777 \***************************************************************************/
1779 case 0x60 : /* Store Word, No WriteBack, Post Dec, Reg */
1781 ARMul_UndefInstr(state
,instr
) ;
1784 UNDEF_LSRBaseEQOffWb
;
1785 UNDEF_LSRBaseEQDestWb
;
1789 if (StoreWord(state
,instr
,lhs
))
1790 LSBase
= lhs
- LSRegRHS
;
1793 case 0x61 : /* Load Word, No WriteBack, Post Dec, Reg */
1795 ARMul_UndefInstr(state
,instr
) ;
1798 UNDEF_LSRBaseEQOffWb
;
1799 UNDEF_LSRBaseEQDestWb
;
1803 if (LoadWord(state
,instr
,lhs
))
1804 LSBase
= lhs
- LSRegRHS
;
1807 case 0x62 : /* Store Word, WriteBack, Post Dec, Reg */
1809 ARMul_UndefInstr(state
,instr
) ;
1812 UNDEF_LSRBaseEQOffWb
;
1813 UNDEF_LSRBaseEQDestWb
;
1817 state
->NtransSig
= LOW
;
1818 if (StoreWord(state
,instr
,lhs
))
1819 LSBase
= lhs
- LSRegRHS
;
1820 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1823 case 0x63 : /* Load Word, WriteBack, Post Dec, Reg */
1825 ARMul_UndefInstr(state
,instr
) ;
1828 UNDEF_LSRBaseEQOffWb
;
1829 UNDEF_LSRBaseEQDestWb
;
1833 state
->NtransSig
= LOW
;
1834 if (LoadWord(state
,instr
,lhs
))
1835 LSBase
= lhs
- LSRegRHS
;
1836 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1839 case 0x64 : /* Store Byte, No WriteBack, Post Dec, Reg */
1841 ARMul_UndefInstr(state
,instr
) ;
1844 UNDEF_LSRBaseEQOffWb
;
1845 UNDEF_LSRBaseEQDestWb
;
1849 if (StoreByte(state
,instr
,lhs
))
1850 LSBase
= lhs
- LSRegRHS
;
1853 case 0x65 : /* Load Byte, No WriteBack, Post Dec, Reg */
1855 ARMul_UndefInstr(state
,instr
) ;
1858 UNDEF_LSRBaseEQOffWb
;
1859 UNDEF_LSRBaseEQDestWb
;
1863 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1864 LSBase
= lhs
- LSRegRHS
;
1867 case 0x66 : /* Store Byte, WriteBack, Post Dec, Reg */
1869 ARMul_UndefInstr(state
,instr
) ;
1872 UNDEF_LSRBaseEQOffWb
;
1873 UNDEF_LSRBaseEQDestWb
;
1877 state
->NtransSig
= LOW
;
1878 if (StoreByte(state
,instr
,lhs
))
1879 LSBase
= lhs
- LSRegRHS
;
1880 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1883 case 0x67 : /* Load Byte, WriteBack, Post Dec, Reg */
1885 ARMul_UndefInstr(state
,instr
) ;
1888 UNDEF_LSRBaseEQOffWb
;
1889 UNDEF_LSRBaseEQDestWb
;
1893 state
->NtransSig
= LOW
;
1894 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1895 LSBase
= lhs
- LSRegRHS
;
1896 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1899 case 0x68 : /* Store Word, No WriteBack, Post Inc, Reg */
1901 ARMul_UndefInstr(state
,instr
) ;
1904 UNDEF_LSRBaseEQOffWb
;
1905 UNDEF_LSRBaseEQDestWb
;
1909 if (StoreWord(state
,instr
,lhs
))
1910 LSBase
= lhs
+ LSRegRHS
;
1913 case 0x69 : /* Load Word, No WriteBack, Post Inc, Reg */
1915 ARMul_UndefInstr(state
,instr
) ;
1918 UNDEF_LSRBaseEQOffWb
;
1919 UNDEF_LSRBaseEQDestWb
;
1923 if (LoadWord(state
,instr
,lhs
))
1924 LSBase
= lhs
+ LSRegRHS
;
1927 case 0x6a : /* Store Word, WriteBack, Post Inc, Reg */
1929 ARMul_UndefInstr(state
,instr
) ;
1932 UNDEF_LSRBaseEQOffWb
;
1933 UNDEF_LSRBaseEQDestWb
;
1937 state
->NtransSig
= LOW
;
1938 if (StoreWord(state
,instr
,lhs
))
1939 LSBase
= lhs
+ LSRegRHS
;
1940 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1943 case 0x6b : /* Load Word, WriteBack, Post Inc, Reg */
1945 ARMul_UndefInstr(state
,instr
) ;
1948 UNDEF_LSRBaseEQOffWb
;
1949 UNDEF_LSRBaseEQDestWb
;
1953 state
->NtransSig
= LOW
;
1954 if (LoadWord(state
,instr
,lhs
))
1955 LSBase
= lhs
+ LSRegRHS
;
1956 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
1959 case 0x6c : /* Store Byte, No WriteBack, Post Inc, Reg */
1961 ARMul_UndefInstr(state
,instr
) ;
1964 UNDEF_LSRBaseEQOffWb
;
1965 UNDEF_LSRBaseEQDestWb
;
1969 if (StoreByte(state
,instr
,lhs
))
1970 LSBase
= lhs
+ LSRegRHS
;
1973 case 0x6d : /* Load Byte, No WriteBack, Post Inc, Reg */
1975 ARMul_UndefInstr(state
,instr
) ;
1978 UNDEF_LSRBaseEQOffWb
;
1979 UNDEF_LSRBaseEQDestWb
;
1983 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
1984 LSBase
= lhs
+ LSRegRHS
;
1987 case 0x6e : /* Store Byte, WriteBack, Post Inc, Reg */
1989 ARMul_UndefInstr(state
,instr
) ;
1992 UNDEF_LSRBaseEQOffWb
;
1993 UNDEF_LSRBaseEQDestWb
;
1997 state
->NtransSig
= LOW
;
1998 if (StoreByte(state
,instr
,lhs
))
1999 LSBase
= lhs
+ LSRegRHS
;
2000 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
2003 case 0x6f : /* Load Byte, WriteBack, Post Inc, Reg */
2005 ARMul_UndefInstr(state
,instr
) ;
2008 UNDEF_LSRBaseEQOffWb
;
2009 UNDEF_LSRBaseEQDestWb
;
2013 state
->NtransSig
= LOW
;
2014 if (LoadByte(state
,instr
,lhs
,LUNSIGNED
))
2015 LSBase
= lhs
+ LSRegRHS
;
2016 state
->NtransSig
= (state
->Mode
& 3)?HIGH
:LOW
;
2020 case 0x70 : /* Store Word, No WriteBack, Pre Dec, Reg */
2022 ARMul_UndefInstr(state
,instr
) ;
2025 (void)StoreWord(state
,instr
,LHS
- LSRegRHS
) ;
2028 case 0x71 : /* Load Word, No WriteBack, Pre Dec, Reg */
2030 ARMul_UndefInstr(state
,instr
) ;
2033 (void)LoadWord(state
,instr
,LHS
- LSRegRHS
) ;
2036 case 0x72 : /* Store Word, WriteBack, Pre Dec, Reg */
2038 ARMul_UndefInstr(state
,instr
) ;
2041 UNDEF_LSRBaseEQOffWb
;
2042 UNDEF_LSRBaseEQDestWb
;
2045 temp
= LHS
- LSRegRHS
;
2046 if (StoreWord(state
,instr
,temp
))
2050 case 0x73 : /* Load Word, WriteBack, Pre Dec, Reg */
2052 ARMul_UndefInstr(state
,instr
) ;
2055 UNDEF_LSRBaseEQOffWb
;
2056 UNDEF_LSRBaseEQDestWb
;
2059 temp
= LHS
- LSRegRHS
;
2060 if (LoadWord(state
,instr
,temp
))
2064 case 0x74 : /* Store Byte, No WriteBack, Pre Dec, Reg */
2066 ARMul_UndefInstr(state
,instr
) ;
2069 (void)StoreByte(state
,instr
,LHS
- LSRegRHS
) ;
2072 case 0x75 : /* Load Byte, No WriteBack, Pre Dec, Reg */
2074 ARMul_UndefInstr(state
,instr
) ;
2077 (void)LoadByte(state
,instr
,LHS
- LSRegRHS
,LUNSIGNED
) ;
2080 case 0x76 : /* Store Byte, WriteBack, Pre Dec, Reg */
2082 ARMul_UndefInstr(state
,instr
) ;
2085 UNDEF_LSRBaseEQOffWb
;
2086 UNDEF_LSRBaseEQDestWb
;
2089 temp
= LHS
- LSRegRHS
;
2090 if (StoreByte(state
,instr
,temp
))
2094 case 0x77 : /* Load Byte, WriteBack, Pre Dec, Reg */
2096 ARMul_UndefInstr(state
,instr
) ;
2099 UNDEF_LSRBaseEQOffWb
;
2100 UNDEF_LSRBaseEQDestWb
;
2103 temp
= LHS
- LSRegRHS
;
2104 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
2108 case 0x78 : /* Store Word, No WriteBack, Pre Inc, Reg */
2110 ARMul_UndefInstr(state
,instr
) ;
2113 (void)StoreWord(state
,instr
,LHS
+ LSRegRHS
) ;
2116 case 0x79 : /* Load Word, No WriteBack, Pre Inc, Reg */
2118 ARMul_UndefInstr(state
,instr
) ;
2121 (void)LoadWord(state
,instr
,LHS
+ LSRegRHS
) ;
2124 case 0x7a : /* Store Word, WriteBack, Pre Inc, Reg */
2126 ARMul_UndefInstr(state
,instr
) ;
2129 UNDEF_LSRBaseEQOffWb
;
2130 UNDEF_LSRBaseEQDestWb
;
2133 temp
= LHS
+ LSRegRHS
;
2134 if (StoreWord(state
,instr
,temp
))
2138 case 0x7b : /* Load Word, WriteBack, Pre Inc, Reg */
2140 ARMul_UndefInstr(state
,instr
) ;
2143 UNDEF_LSRBaseEQOffWb
;
2144 UNDEF_LSRBaseEQDestWb
;
2147 temp
= LHS
+ LSRegRHS
;
2148 if (LoadWord(state
,instr
,temp
))
2152 case 0x7c : /* Store Byte, No WriteBack, Pre Inc, Reg */
2154 ARMul_UndefInstr(state
,instr
) ;
2157 (void)StoreByte(state
,instr
,LHS
+ LSRegRHS
) ;
2160 case 0x7d : /* Load Byte, No WriteBack, Pre Inc, Reg */
2162 ARMul_UndefInstr(state
,instr
) ;
2165 (void)LoadByte(state
,instr
,LHS
+ LSRegRHS
,LUNSIGNED
) ;
2168 case 0x7e : /* Store Byte, WriteBack, Pre Inc, Reg */
2170 ARMul_UndefInstr(state
,instr
) ;
2173 UNDEF_LSRBaseEQOffWb
;
2174 UNDEF_LSRBaseEQDestWb
;
2177 temp
= LHS
+ LSRegRHS
;
2178 if (StoreByte(state
,instr
,temp
))
2182 case 0x7f : /* Load Byte, WriteBack, Pre Inc, Reg */
2185 /* Check for the special breakpoint opcode.
2186 This value should correspond to the value defined
2187 as ARM_BE_BREAKPOINT in gdb/arm-tdep.c. */
2188 if (BITS (0,19) == 0xfdefe)
2190 if (! ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2191 ARMul_Abort (state
, ARMul_SWIV
);
2194 ARMul_UndefInstr(state
,instr
) ;
2197 UNDEF_LSRBaseEQOffWb
;
2198 UNDEF_LSRBaseEQDestWb
;
2201 temp
= LHS
+ LSRegRHS
;
2202 if (LoadByte(state
,instr
,temp
,LUNSIGNED
))
2206 /***************************************************************************\
2207 * Multiple Data Transfer Instructions *
2208 \***************************************************************************/
2210 case 0x80 : /* Store, No WriteBack, Post Dec */
2211 STOREMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2214 case 0x81 : /* Load, No WriteBack, Post Dec */
2215 LOADMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2218 case 0x82 : /* Store, WriteBack, Post Dec */
2219 temp
= LSBase
- LSMNumRegs
;
2220 STOREMULT(instr
,temp
+ 4L,temp
) ;
2223 case 0x83 : /* Load, WriteBack, Post Dec */
2224 temp
= LSBase
- LSMNumRegs
;
2225 LOADMULT(instr
,temp
+ 4L,temp
) ;
2228 case 0x84 : /* Store, Flags, No WriteBack, Post Dec */
2229 STORESMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2232 case 0x85 : /* Load, Flags, No WriteBack, Post Dec */
2233 LOADSMULT(instr
,LSBase
- LSMNumRegs
+ 4L,0L) ;
2236 case 0x86 : /* Store, Flags, WriteBack, Post Dec */
2237 temp
= LSBase
- LSMNumRegs
;
2238 STORESMULT(instr
,temp
+ 4L,temp
) ;
2241 case 0x87 : /* Load, Flags, WriteBack, Post Dec */
2242 temp
= LSBase
- LSMNumRegs
;
2243 LOADSMULT(instr
,temp
+ 4L,temp
) ;
2247 case 0x88 : /* Store, No WriteBack, Post Inc */
2248 STOREMULT(instr
,LSBase
,0L) ;
2251 case 0x89 : /* Load, No WriteBack, Post Inc */
2252 LOADMULT(instr
,LSBase
,0L) ;
2255 case 0x8a : /* Store, WriteBack, Post Inc */
2257 STOREMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2260 case 0x8b : /* Load, WriteBack, Post Inc */
2262 LOADMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2265 case 0x8c : /* Store, Flags, No WriteBack, Post Inc */
2266 STORESMULT(instr
,LSBase
,0L) ;
2269 case 0x8d : /* Load, Flags, No WriteBack, Post Inc */
2270 LOADSMULT(instr
,LSBase
,0L) ;
2273 case 0x8e : /* Store, Flags, WriteBack, Post Inc */
2275 STORESMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2278 case 0x8f : /* Load, Flags, WriteBack, Post Inc */
2280 LOADSMULT(instr
,temp
,temp
+ LSMNumRegs
) ;
2284 case 0x90 : /* Store, No WriteBack, Pre Dec */
2285 STOREMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2288 case 0x91 : /* Load, No WriteBack, Pre Dec */
2289 LOADMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2292 case 0x92 : /* Store, WriteBack, Pre Dec */
2293 temp
= LSBase
- LSMNumRegs
;
2294 STOREMULT(instr
,temp
,temp
) ;
2297 case 0x93 : /* Load, WriteBack, Pre Dec */
2298 temp
= LSBase
- LSMNumRegs
;
2299 LOADMULT(instr
,temp
,temp
) ;
2302 case 0x94 : /* Store, Flags, No WriteBack, Pre Dec */
2303 STORESMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2306 case 0x95 : /* Load, Flags, No WriteBack, Pre Dec */
2307 LOADSMULT(instr
,LSBase
- LSMNumRegs
,0L) ;
2310 case 0x96 : /* Store, Flags, WriteBack, Pre Dec */
2311 temp
= LSBase
- LSMNumRegs
;
2312 STORESMULT(instr
,temp
,temp
) ;
2315 case 0x97 : /* Load, Flags, WriteBack, Pre Dec */
2316 temp
= LSBase
- LSMNumRegs
;
2317 LOADSMULT(instr
,temp
,temp
) ;
2321 case 0x98 : /* Store, No WriteBack, Pre Inc */
2322 STOREMULT(instr
,LSBase
+ 4L,0L) ;
2325 case 0x99 : /* Load, No WriteBack, Pre Inc */
2326 LOADMULT(instr
,LSBase
+ 4L,0L) ;
2329 case 0x9a : /* Store, WriteBack, Pre Inc */
2331 STOREMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2334 case 0x9b : /* Load, WriteBack, Pre Inc */
2336 LOADMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2339 case 0x9c : /* Store, Flags, No WriteBack, Pre Inc */
2340 STORESMULT(instr
,LSBase
+ 4L,0L) ;
2343 case 0x9d : /* Load, Flags, No WriteBack, Pre Inc */
2344 LOADSMULT(instr
,LSBase
+ 4L,0L) ;
2347 case 0x9e : /* Store, Flags, WriteBack, Pre Inc */
2349 STORESMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2352 case 0x9f : /* Load, Flags, WriteBack, Pre Inc */
2354 LOADSMULT(instr
,temp
+ 4L,temp
+ LSMNumRegs
) ;
2357 /***************************************************************************\
2359 \***************************************************************************/
2361 case 0xa0 : case 0xa1 : case 0xa2 : case 0xa3 :
2362 case 0xa4 : case 0xa5 : case 0xa6 : case 0xa7 :
2363 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2367 /***************************************************************************\
2369 \***************************************************************************/
2371 case 0xa8 : case 0xa9 : case 0xaa : case 0xab :
2372 case 0xac : case 0xad : case 0xae : case 0xaf :
2373 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2377 /***************************************************************************\
2378 * Branch and Link forward *
2379 \***************************************************************************/
2381 case 0xb0 : case 0xb1 : case 0xb2 : case 0xb3 :
2382 case 0xb4 : case 0xb5 : case 0xb6 : case 0xb7 :
2384 state
->Reg
[14] = pc
+ 4 ; /* put PC into Link */
2386 state
->Reg
[14] = pc
+ 4 | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2388 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2392 /***************************************************************************\
2393 * Branch and Link backward *
2394 \***************************************************************************/
2396 case 0xb8 : case 0xb9 : case 0xba : case 0xbb :
2397 case 0xbc : case 0xbd : case 0xbe : case 0xbf :
2399 state
->Reg
[14] = pc
+ 4 ; /* put PC into Link */
2401 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2403 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2407 /***************************************************************************\
2408 * Co-Processor Data Transfers *
2409 \***************************************************************************/
2412 case 0xc4 : /* Store , No WriteBack , Post Dec */
2413 ARMul_STC(state
,instr
,LHS
) ;
2417 case 0xc5 : /* Load , No WriteBack , Post Dec */
2418 ARMul_LDC(state
,instr
,LHS
) ;
2422 case 0xc6 : /* Store , WriteBack , Post Dec */
2424 state
->Base
= lhs
- LSCOff
;
2425 ARMul_STC(state
,instr
,lhs
) ;
2429 case 0xc7 : /* Load , WriteBack , Post Dec */
2431 state
->Base
= lhs
- LSCOff
;
2432 ARMul_LDC(state
,instr
,lhs
) ;
2436 case 0xcc : /* Store , No WriteBack , Post Inc */
2437 ARMul_STC(state
,instr
,LHS
) ;
2441 case 0xcd : /* Load , No WriteBack , Post Inc */
2442 ARMul_LDC(state
,instr
,LHS
) ;
2446 case 0xce : /* Store , WriteBack , Post Inc */
2448 state
->Base
= lhs
+ LSCOff
;
2449 ARMul_STC(state
,instr
,LHS
) ;
2453 case 0xcf : /* Load , WriteBack , Post Inc */
2455 state
->Base
= lhs
+ LSCOff
;
2456 ARMul_LDC(state
,instr
,LHS
) ;
2461 case 0xd4 : /* Store , No WriteBack , Pre Dec */
2462 ARMul_STC(state
,instr
,LHS
- LSCOff
) ;
2466 case 0xd5 : /* Load , No WriteBack , Pre Dec */
2467 ARMul_LDC(state
,instr
,LHS
- LSCOff
) ;
2471 case 0xd6 : /* Store , WriteBack , Pre Dec */
2472 lhs
= LHS
- LSCOff
;
2474 ARMul_STC(state
,instr
,lhs
) ;
2478 case 0xd7 : /* Load , WriteBack , Pre Dec */
2479 lhs
= LHS
- LSCOff
;
2481 ARMul_LDC(state
,instr
,lhs
) ;
2485 case 0xdc : /* Store , No WriteBack , Pre Inc */
2486 ARMul_STC(state
,instr
,LHS
+ LSCOff
) ;
2490 case 0xdd : /* Load , No WriteBack , Pre Inc */
2491 ARMul_LDC(state
,instr
,LHS
+ LSCOff
) ;
2495 case 0xde : /* Store , WriteBack , Pre Inc */
2496 lhs
= LHS
+ LSCOff
;
2498 ARMul_STC(state
,instr
,lhs
) ;
2502 case 0xdf : /* Load , WriteBack , Pre Inc */
2503 lhs
= LHS
+ LSCOff
;
2505 ARMul_LDC(state
,instr
,lhs
) ;
2508 /***************************************************************************\
2509 * Co-Processor Register Transfers (MCR) and Data Ops *
2510 \***************************************************************************/
2512 case 0xe0 : case 0xe2 : case 0xe4 : case 0xe6 :
2513 case 0xe8 : case 0xea : case 0xec : case 0xee :
2514 if (BIT(4)) { /* MCR */
2515 if (DESTReg
== 15) {
2518 ARMul_MCR(state
,instr
,state
->Reg
[15] + isize
) ;
2520 ARMul_MCR(state
,instr
,ECC
| ER15INT
| EMODE
|
2521 ((state
->Reg
[15] + isize
) & R15PCBITS
) ) ;
2525 ARMul_MCR(state
,instr
,DEST
) ;
2527 else /* CDP Part 1 */
2528 ARMul_CDP(state
,instr
) ;
2531 /***************************************************************************\
2532 * Co-Processor Register Transfers (MRC) and Data Ops *
2533 \***************************************************************************/
2535 case 0xe1 : case 0xe3 : case 0xe5 : case 0xe7 :
2536 case 0xe9 : case 0xeb : case 0xed : case 0xef :
2537 if (BIT(4)) { /* MRC */
2538 temp
= ARMul_MRC(state
,instr
) ;
2539 if (DESTReg
== 15) {
2540 ASSIGNN((temp
& NBIT
) != 0) ;
2541 ASSIGNZ((temp
& ZBIT
) != 0) ;
2542 ASSIGNC((temp
& CBIT
) != 0) ;
2543 ASSIGNV((temp
& VBIT
) != 0) ;
2548 else /* CDP Part 2 */
2549 ARMul_CDP(state
,instr
) ;
2552 /***************************************************************************\
2554 \***************************************************************************/
2556 case 0xf0 : case 0xf1 : case 0xf2 : case 0xf3 :
2557 case 0xf4 : case 0xf5 : case 0xf6 : case 0xf7 :
2558 case 0xf8 : case 0xf9 : case 0xfa : case 0xfb :
2559 case 0xfc : case 0xfd : case 0xfe : case 0xff :
2560 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
) { /* a prefetch abort */
2561 ARMul_Abort(state
,ARMul_PrefetchAbortV
) ;
2565 if (!ARMul_OSHandleSWI(state
,BITS(0,23))) {
2566 ARMul_Abort(state
,ARMul_SWIV
) ;
2569 } /* 256 way main switch */
2576 #ifdef NEED_UI_LOOP_HOOK
2577 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
2579 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
2582 #endif /* NEED_UI_LOOP_HOOK */
2584 if (state
->Emulate
== ONCE
)
2585 state
->Emulate
= STOP
;
2586 else if (state
->Emulate
!= RUN
)
2588 } while (!stop_simulator
) ; /* do loop */
2590 state
->decoded
= decoded
;
2591 state
->loaded
= loaded
;
2594 } /* Emulate 26/32 in instruction based mode */
2597 /***************************************************************************\
2598 * This routine evaluates most Data Processing register RHS's with the S *
2599 * bit clear. It is intended to be called from the macro DPRegRHS, which *
2600 * filters the common case of an unshifted register with in line code *
2601 \***************************************************************************/
2603 static ARMword
GetDPRegRHS(ARMul_State
*state
, ARMword instr
)
2604 {ARMword shamt
, base
;
2607 if (BIT(4)) { /* shift amount in a register */
2612 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2615 base
= state
->Reg
[base
] ;
2616 ARMul_Icycles(state
,1,0L) ;
2617 shamt
= state
->Reg
[BITS(8,11)] & 0xff ;
2618 switch ((int)BITS(5,6)) {
2619 case LSL
: if (shamt
== 0)
2621 else if (shamt
>= 32)
2624 return(base
<< shamt
) ;
2625 case LSR
: if (shamt
== 0)
2627 else if (shamt
>= 32)
2630 return(base
>> shamt
) ;
2631 case ASR
: if (shamt
== 0)
2633 else if (shamt
>= 32)
2634 return((ARMword
)((long int)base
>> 31L)) ;
2636 return((ARMword
)((long int)base
>> (int)shamt
)) ;
2637 case ROR
: shamt
&= 0x1f ;
2641 return((base
<< (32 - shamt
)) | (base
>> shamt
)) ;
2644 else { /* shift amount is a constant */
2647 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2650 base
= state
->Reg
[base
] ;
2651 shamt
= BITS(7,11) ;
2652 switch ((int)BITS(5,6)) {
2653 case LSL
: return(base
<<shamt
) ;
2654 case LSR
: if (shamt
== 0)
2657 return(base
>> shamt
) ;
2658 case ASR
: if (shamt
== 0)
2659 return((ARMword
)((long int)base
>> 31L)) ;
2661 return((ARMword
)((long int)base
>> (int)shamt
)) ;
2662 case ROR
: if (shamt
==0) /* its an RRX */
2663 return((base
>> 1) | (CFLAG
<< 31)) ;
2665 return((base
<< (32 - shamt
)) | (base
>> shamt
)) ;
2668 return(0) ; /* just to shut up lint */
2670 /***************************************************************************\
2671 * This routine evaluates most Logical Data Processing register RHS's *
2672 * with the S bit set. It is intended to be called from the macro *
2673 * DPSRegRHS, which filters the common case of an unshifted register *
2674 * with in line code *
2675 \***************************************************************************/
2677 static ARMword
GetDPSRegRHS(ARMul_State
*state
, ARMword instr
)
2678 {ARMword shamt
, base
;
2681 if (BIT(4)) { /* shift amount in a register */
2686 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2689 base
= state
->Reg
[base
] ;
2690 ARMul_Icycles(state
,1,0L) ;
2691 shamt
= state
->Reg
[BITS(8,11)] & 0xff ;
2692 switch ((int)BITS(5,6)) {
2693 case LSL
: if (shamt
== 0)
2695 else if (shamt
== 32) {
2699 else if (shamt
> 32) {
2704 ASSIGNC((base
>> (32-shamt
)) & 1) ;
2705 return(base
<< shamt
) ;
2707 case LSR
: if (shamt
== 0)
2709 else if (shamt
== 32) {
2710 ASSIGNC(base
>> 31) ;
2713 else if (shamt
> 32) {
2718 ASSIGNC((base
>> (shamt
- 1)) & 1) ;
2719 return(base
>> shamt
) ;
2721 case ASR
: if (shamt
== 0)
2723 else if (shamt
>= 32) {
2724 ASSIGNC(base
>> 31L) ;
2725 return((ARMword
)((long int)base
>> 31L)) ;
2728 ASSIGNC((ARMword
)((long int)base
>> (int)(shamt
-1)) & 1) ;
2729 return((ARMword
)((long int)base
>> (int)shamt
)) ;
2731 case ROR
: if (shamt
== 0)
2735 ASSIGNC(base
>> 31) ;
2739 ASSIGNC((base
>> (shamt
-1)) & 1) ;
2740 return((base
<< (32-shamt
)) | (base
>> shamt
)) ;
2744 else { /* shift amount is a constant */
2747 base
= ECC
| ER15INT
| R15PC
| EMODE
;
2750 base
= state
->Reg
[base
] ;
2751 shamt
= BITS(7,11) ;
2752 switch ((int)BITS(5,6)) {
2753 case LSL
: ASSIGNC((base
>> (32-shamt
)) & 1) ;
2754 return(base
<< shamt
) ;
2755 case LSR
: if (shamt
== 0) {
2756 ASSIGNC(base
>> 31) ;
2760 ASSIGNC((base
>> (shamt
- 1)) & 1) ;
2761 return(base
>> shamt
) ;
2763 case ASR
: if (shamt
== 0) {
2764 ASSIGNC(base
>> 31L) ;
2765 return((ARMword
)((long int)base
>> 31L)) ;
2768 ASSIGNC((ARMword
)((long int)base
>> (int)(shamt
-1)) & 1) ;
2769 return((ARMword
)((long int)base
>> (int)shamt
)) ;
2771 case ROR
: if (shamt
== 0) { /* its an RRX */
2774 return((base
>> 1) | (shamt
<< 31)) ;
2777 ASSIGNC((base
>> (shamt
- 1)) & 1) ;
2778 return((base
<< (32-shamt
)) | (base
>> shamt
)) ;
2782 return(0) ; /* just to shut up lint */
2785 /***************************************************************************\
2786 * This routine handles writes to register 15 when the S bit is not set. *
2787 \***************************************************************************/
2789 static void WriteR15(ARMul_State
*state
, ARMword src
)
2791 /* The ARM documentation implies (but doe snot state) that the bottom bit of the PC is never set */
2793 state
->Reg
[15] = src
& PCBITS
& ~ 0x1 ;
2795 state
->Reg
[15] = (src
& R15PCBITS
& ~ 0x1) | ECC
| ER15INT
| EMODE
;
2796 ARMul_R15Altered(state
) ;
2801 /***************************************************************************\
2802 * This routine handles writes to register 15 when the S bit is set. *
2803 \***************************************************************************/
2805 static void WriteSR15(ARMul_State
*state
, ARMword src
)
2808 state
->Reg
[15] = src
& PCBITS
;
2809 if (state
->Bank
> 0) {
2810 state
->Cpsr
= state
->Spsr
[state
->Bank
] ;
2811 ARMul_CPSRAltered(state
) ;
2814 if (state
->Bank
== USERBANK
)
2815 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
2817 state
->Reg
[15] = src
;
2818 ARMul_R15Altered(state
) ;
2823 /***************************************************************************\
2824 * This routine evaluates most Load and Store register RHS's. It is *
2825 * intended to be called from the macro LSRegRHS, which filters the *
2826 * common case of an unshifted register with in line code *
2827 \***************************************************************************/
2829 static ARMword
GetLSRegRHS(ARMul_State
*state
, ARMword instr
)
2830 {ARMword shamt
, base
;
2835 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
2838 base
= state
->Reg
[base
] ;
2840 shamt
= BITS(7,11) ;
2841 switch ((int)BITS(5,6)) {
2842 case LSL
: return(base
<< shamt
) ;
2843 case LSR
: if (shamt
== 0)
2846 return(base
>> shamt
) ;
2847 case ASR
: if (shamt
== 0)
2848 return((ARMword
)((long int)base
>> 31L)) ;
2850 return((ARMword
)((long int)base
>> (int)shamt
)) ;
2851 case ROR
: if (shamt
==0) /* its an RRX */
2852 return((base
>> 1) | (CFLAG
<< 31)) ;
2854 return((base
<< (32-shamt
)) | (base
>> shamt
)) ;
2856 return(0) ; /* just to shut up lint */
2859 /***************************************************************************\
2860 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
2861 \***************************************************************************/
2863 static ARMword
GetLS7RHS(ARMul_State
*state
, ARMword instr
)
2865 if (BIT(22) == 0) { /* register */
2868 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
2870 return state
->Reg
[RHSReg
] ;
2873 /* else immediate */
2874 return BITS(0,3) | (BITS(8,11) << 4) ;
2877 /***************************************************************************\
2878 * This function does the work of loading a word for a LDR instruction. *
2879 \***************************************************************************/
2881 static unsigned LoadWord(ARMul_State
*state
, ARMword instr
, ARMword address
)
2887 if (ADDREXCEPT(address
)) {
2888 INTERNALABORT(address
) ;
2891 dest
= ARMul_LoadWordN(state
,address
) ;
2892 if (state
->Aborted
) {
2894 return(state
->lateabtSig
) ;
2897 dest
= ARMul_Align(state
,address
,dest
) ;
2899 ARMul_Icycles(state
,1,0L) ;
2901 return(DESTReg
!= LHSReg
) ;
2905 /***************************************************************************\
2906 * This function does the work of loading a halfword. *
2907 \***************************************************************************/
2909 static unsigned LoadHalfWord(ARMul_State
*state
, ARMword instr
, ARMword address
,int signextend
)
2915 if (ADDREXCEPT(address
)) {
2916 INTERNALABORT(address
) ;
2919 dest
= ARMul_LoadHalfWord(state
,address
) ;
2920 if (state
->Aborted
) {
2922 return(state
->lateabtSig
) ;
2927 if (dest
& 1 << (16 - 1))
2928 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16) ;
2931 ARMul_Icycles(state
,1,0L) ;
2932 return(DESTReg
!= LHSReg
) ;
2936 /***************************************************************************\
2937 * This function does the work of loading a byte for a LDRB instruction. *
2938 \***************************************************************************/
2940 static unsigned LoadByte(ARMul_State
*state
, ARMword instr
, ARMword address
,int signextend
)
2946 if (ADDREXCEPT(address
)) {
2947 INTERNALABORT(address
) ;
2950 dest
= ARMul_LoadByte(state
,address
) ;
2951 if (state
->Aborted
) {
2953 return(state
->lateabtSig
) ;
2958 if (dest
& 1 << (8 - 1))
2959 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8) ;
2962 ARMul_Icycles(state
,1,0L) ;
2963 return(DESTReg
!= LHSReg
) ;
2966 /***************************************************************************\
2967 * This function does the work of storing a word from a STR instruction. *
2968 \***************************************************************************/
2970 static unsigned StoreWord(ARMul_State
*state
, ARMword instr
, ARMword address
)
2974 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
2977 ARMul_StoreWordN(state
,address
,DEST
) ;
2979 if (VECTORACCESS(address
) || ADDREXCEPT(address
)) {
2980 INTERNALABORT(address
) ;
2981 (void)ARMul_LoadWordN(state
,address
) ;
2984 ARMul_StoreWordN(state
,address
,DEST
) ;
2986 if (state
->Aborted
) {
2988 return(state
->lateabtSig
) ;
2994 /***************************************************************************\
2995 * This function does the work of storing a byte for a STRH instruction. *
2996 \***************************************************************************/
2998 static unsigned StoreHalfWord(ARMul_State
*state
, ARMword instr
, ARMword address
)
3003 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3007 ARMul_StoreHalfWord(state
,address
,DEST
);
3009 if (VECTORACCESS(address
) || ADDREXCEPT(address
)) {
3010 INTERNALABORT(address
) ;
3011 (void)ARMul_LoadHalfWord(state
,address
) ;
3014 ARMul_StoreHalfWord(state
,address
,DEST
) ;
3017 if (state
->Aborted
) {
3019 return(state
->lateabtSig
) ;
3026 /***************************************************************************\
3027 * This function does the work of storing a byte for a STRB instruction. *
3028 \***************************************************************************/
3030 static unsigned StoreByte(ARMul_State
*state
, ARMword instr
, ARMword address
)
3034 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3037 ARMul_StoreByte(state
,address
,DEST
) ;
3039 if (VECTORACCESS(address
) || ADDREXCEPT(address
)) {
3040 INTERNALABORT(address
) ;
3041 (void)ARMul_LoadByte(state
,address
) ;
3044 ARMul_StoreByte(state
,address
,DEST
) ;
3046 if (state
->Aborted
) {
3048 return(state
->lateabtSig
) ;
3054 /***************************************************************************\
3055 * This function does the work of loading the registers listed in an LDM *
3056 * instruction, when the S bit is clear. The code here is always increment *
3057 * after, it's up to the caller to get the input address correct and to *
3058 * handle base register modification. *
3059 \***************************************************************************/
3061 static void LoadMult(ARMul_State
*state
, ARMword instr
,
3062 ARMword address
, ARMword WBBase
)
3063 {ARMword dest
, temp
;
3067 UNDEF_LSMBaseInListWb
;
3070 if (ADDREXCEPT(address
)) {
3071 INTERNALABORT(address
) ;
3074 if (BIT(21) && LHSReg
!= 15)
3077 for (temp
= 0 ; !BIT(temp
) ; temp
++) ; /* N cycle first */
3078 dest
= ARMul_LoadWordN(state
,address
) ;
3079 if (!state
->abortSig
&& !state
->Aborted
)
3080 state
->Reg
[temp
++] = dest
;
3082 if (!state
->Aborted
)
3083 state
->Aborted
= ARMul_DataAbortV
;
3085 for (; temp
< 16 ; temp
++) /* S cycles from here on */
3086 if (BIT(temp
)) { /* load this register */
3088 dest
= ARMul_LoadWordS(state
,address
) ;
3089 if (!state
->abortSig
&& !state
->Aborted
)
3090 state
->Reg
[temp
] = dest
;
3092 if (!state
->Aborted
)
3093 state
->Aborted
= ARMul_DataAbortV
;
3096 if (BIT(15)) { /* PC is in the reg list */
3098 state
->Reg
[15] = PC
;
3103 ARMul_Icycles(state
,1,0L) ; /* to write back the final register */
3105 if (state
->Aborted
) {
3106 if (BIT(21) && LHSReg
!= 15)
3112 /***************************************************************************\
3113 * This function does the work of loading the registers listed in an LDM *
3114 * instruction, when the S bit is set. The code here is always increment *
3115 * after, it's up to the caller to get the input address correct and to *
3116 * handle base register modification. *
3117 \***************************************************************************/
3119 static void LoadSMult(ARMul_State
*state
, ARMword instr
,
3120 ARMword address
, ARMword WBBase
)
3121 {ARMword dest
, temp
;
3125 UNDEF_LSMBaseInListWb
;
3128 if (ADDREXCEPT(address
)) {
3129 INTERNALABORT(address
) ;
3133 if (!BIT(15) && state
->Bank
!= USERBANK
) {
3134 (void)ARMul_SwitchMode(state
,state
->Mode
,USER26MODE
) ; /* temporary reg bank switch */
3135 UNDEF_LSMUserBankWb
;
3138 if (BIT(21) && LHSReg
!= 15)
3141 for (temp
= 0 ; !BIT(temp
) ; temp
++) ; /* N cycle first */
3142 dest
= ARMul_LoadWordN(state
,address
) ;
3143 if (!state
->abortSig
)
3144 state
->Reg
[temp
++] = dest
;
3146 if (!state
->Aborted
)
3147 state
->Aborted
= ARMul_DataAbortV
;
3149 for (; temp
< 16 ; temp
++) /* S cycles from here on */
3150 if (BIT(temp
)) { /* load this register */
3152 dest
= ARMul_LoadWordS(state
,address
) ;
3153 if (!state
->abortSig
|| state
->Aborted
)
3154 state
->Reg
[temp
] = dest
;
3156 if (!state
->Aborted
)
3157 state
->Aborted
= ARMul_DataAbortV
;
3160 if (BIT(15)) { /* PC is in the reg list */
3162 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
) {
3163 state
->Cpsr
= GETSPSR(state
->Bank
) ;
3164 ARMul_CPSRAltered(state
) ;
3166 state
->Reg
[15] = PC
;
3168 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
) { /* protect bits in user mode */
3169 ASSIGNN((state
->Reg
[15] & NBIT
) != 0) ;
3170 ASSIGNZ((state
->Reg
[15] & ZBIT
) != 0) ;
3171 ASSIGNC((state
->Reg
[15] & CBIT
) != 0) ;
3172 ASSIGNV((state
->Reg
[15] & VBIT
) != 0) ;
3175 ARMul_R15Altered(state
) ;
3180 if (!BIT(15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3181 (void)ARMul_SwitchMode(state
,USER26MODE
,state
->Mode
) ; /* restore the correct bank */
3183 ARMul_Icycles(state
,1,0L) ; /* to write back the final register */
3185 if (state
->Aborted
) {
3186 if (BIT(21) && LHSReg
!= 15)
3193 /***************************************************************************\
3194 * This function does the work of storing the registers listed in an STM *
3195 * instruction, when the S bit is clear. The code here is always increment *
3196 * after, it's up to the caller to get the input address correct and to *
3197 * handle base register modification. *
3198 \***************************************************************************/
3200 static void StoreMult(ARMul_State
*state
, ARMword instr
,
3201 ARMword address
, ARMword WBBase
)
3206 UNDEF_LSMBaseInListWb
;
3208 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
3212 if (VECTORACCESS(address
) || ADDREXCEPT(address
)) {
3213 INTERNALABORT(address
) ;
3219 for (temp
= 0 ; !BIT(temp
) ; temp
++) ; /* N cycle first */
3221 ARMul_StoreWordN(state
,address
,state
->Reg
[temp
++]) ;
3223 if (state
->Aborted
) {
3224 (void)ARMul_LoadWordN(state
,address
) ;
3225 for ( ; temp
< 16 ; temp
++) /* Fake the Stores as Loads */
3226 if (BIT(temp
)) { /* save this register */
3228 (void)ARMul_LoadWordS(state
,address
) ;
3230 if (BIT(21) && LHSReg
!= 15)
3236 ARMul_StoreWordN(state
,address
,state
->Reg
[temp
++]) ;
3238 if (state
->abortSig
&& !state
->Aborted
)
3239 state
->Aborted
= ARMul_DataAbortV
;
3241 if (BIT(21) && LHSReg
!= 15)
3244 for ( ; temp
< 16 ; temp
++) /* S cycles from here on */
3245 if (BIT(temp
)) { /* save this register */
3247 ARMul_StoreWordS(state
,address
,state
->Reg
[temp
]) ;
3248 if (state
->abortSig
&& !state
->Aborted
)
3249 state
->Aborted
= ARMul_DataAbortV
;
3251 if (state
->Aborted
) {
3256 /***************************************************************************\
3257 * This function does the work of storing the registers listed in an STM *
3258 * instruction when the S bit is set. The code here is always increment *
3259 * after, it's up to the caller to get the input address correct and to *
3260 * handle base register modification. *
3261 \***************************************************************************/
3263 static void StoreSMult(ARMul_State
*state
, ARMword instr
,
3264 ARMword address
, ARMword WBBase
)
3269 UNDEF_LSMBaseInListWb
;
3272 if (VECTORACCESS(address
) || ADDREXCEPT(address
)) {
3273 INTERNALABORT(address
) ;
3279 if (state
->Bank
!= USERBANK
) {
3280 (void)ARMul_SwitchMode(state
,state
->Mode
,USER26MODE
) ; /* Force User Bank */
3281 UNDEF_LSMUserBankWb
;
3284 for (temp
= 0 ; !BIT(temp
) ; temp
++) ; /* N cycle first */
3286 ARMul_StoreWordN(state
,address
,state
->Reg
[temp
++]) ;
3288 if (state
->Aborted
) {
3289 (void)ARMul_LoadWordN(state
,address
) ;
3290 for ( ; temp
< 16 ; temp
++) /* Fake the Stores as Loads */
3291 if (BIT(temp
)) { /* save this register */
3293 (void)ARMul_LoadWordS(state
,address
) ;
3295 if (BIT(21) && LHSReg
!= 15)
3301 ARMul_StoreWordN(state
,address
,state
->Reg
[temp
++]) ;
3303 if (state
->abortSig
&& !state
->Aborted
)
3304 state
->Aborted
= ARMul_DataAbortV
;
3306 if (BIT(21) && LHSReg
!= 15)
3309 for (; temp
< 16 ; temp
++) /* S cycles from here on */
3310 if (BIT(temp
)) { /* save this register */
3312 ARMul_StoreWordS(state
,address
,state
->Reg
[temp
]) ;
3313 if (state
->abortSig
&& !state
->Aborted
)
3314 state
->Aborted
= ARMul_DataAbortV
;
3317 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
3318 (void)ARMul_SwitchMode(state
,USER26MODE
,state
->Mode
) ; /* restore the correct bank */
3320 if (state
->Aborted
) {
3325 /***************************************************************************\
3326 * This function does the work of adding two 32bit values together, and *
3327 * calculating if a carry has occurred. *
3328 \***************************************************************************/
3330 static ARMword
Add32(ARMword a1
,ARMword a2
,int *carry
)
3332 ARMword result
= (a1
+ a2
);
3333 unsigned int uresult
= (unsigned int)result
;
3334 unsigned int ua1
= (unsigned int)a1
;
3336 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
3337 or (result > RdLo) then we have no carry: */
3338 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
3346 /***************************************************************************\
3347 * This function does the work of multiplying two 32bit values to give a *
3349 \***************************************************************************/
3351 static unsigned Multiply64(ARMul_State
*state
,ARMword instr
,int msigned
,int scc
)
3353 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
3354 ARMword RdHi
, RdLo
, Rm
;
3355 int scount
; /* cycle count */
3357 nRdHi
= BITS(16,19);
3358 nRdLo
= BITS(12,15);
3362 /* Needed to calculate the cycle count: */
3363 Rm
= state
->Reg
[nRm
];
3365 /* Check for illegal operand combinations first: */
3374 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
3376 ARMword Rs
= state
->Reg
[ nRs
];
3381 /* Compute sign of result and adjust operands if necessary. */
3383 sign
= (Rm
^ Rs
) & 0x80000000;
3385 if (((signed long)Rm
) < 0)
3388 if (((signed long)Rs
) < 0)
3392 /* We can split the 32x32 into four 16x16 operations. This ensures
3393 that we do not lose precision on 32bit only hosts: */
3394 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
3395 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3396 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
3397 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
3399 /* We now need to add all of these results together, taking care
3400 to propogate the carries from the additions: */
3401 RdLo
= Add32(lo
,(mid1
<< 16),&carry
);
3403 RdLo
= Add32(RdLo
,(mid2
<< 16),&carry
);
3404 RdHi
+= (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
3408 /* Negate result if necessary. */
3412 if (RdLo
== 0xFFFFFFFF)
3421 state
->Reg
[nRdLo
] = RdLo
;
3422 state
->Reg
[nRdHi
] = RdHi
;
3424 } /* else undefined result */
3425 else fprintf (stderr
, "MULTIPLY64 - INVALID ARGUMENTS\n");
3429 if ((RdHi
== 0) && (RdLo
== 0))
3430 ARMul_NegZero(state
,RdHi
); /* zero value */
3432 ARMul_NegZero(state
,scc
); /* non-zero value */
3435 /* The cycle count depends on whether the instruction is a signed or
3436 unsigned multiply, and what bits are clear in the multiplier: */
3437 if (msigned
&& (Rm
& ((unsigned)1 << 31)))
3438 Rm
= ~Rm
; /* invert the bits to make the check against zero */
3440 if ((Rm
& 0xFFFFFF00) == 0)
3442 else if ((Rm
& 0xFFFF0000) == 0)
3444 else if ((Rm
& 0xFF000000) == 0)
3452 /***************************************************************************\
3453 * This function does the work of multiplying two 32bit values and adding *
3454 * a 64bit value to give a 64bit result. *
3455 \***************************************************************************/
3457 static unsigned MultiplyAdd64(ARMul_State
*state
,ARMword instr
,int msigned
,int scc
)
3464 nRdHi
= BITS(16,19);
3465 nRdLo
= BITS(12,15);
3467 RdHi
= state
->Reg
[nRdHi
] ;
3468 RdLo
= state
->Reg
[nRdLo
] ;
3470 scount
= Multiply64(state
,instr
,msigned
,LDEFAULT
);
3472 RdLo
= Add32(RdLo
,state
->Reg
[nRdLo
],&carry
);
3473 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
3475 state
->Reg
[nRdLo
] = RdLo
;
3476 state
->Reg
[nRdHi
] = RdHi
;
3479 if ((RdHi
== 0) && (RdLo
== 0))
3480 ARMul_NegZero(state
,RdHi
); /* zero value */
3482 ARMul_NegZero(state
,scc
); /* non-zero value */
3485 return scount
+ 1; /* extra cycle for addition */
This page took 0.142573 seconds and 4 git commands to generate.