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. */
22 static ARMword GetDPRegRHS(ARMul_State *state, ARMword instr) ;
23 static ARMword GetDPSRegRHS(ARMul_State *state, ARMword instr) ;
24 static void WriteR15(ARMul_State *state, ARMword src) ;
25 static void WriteSR15(ARMul_State *state, ARMword src) ;
26 static ARMword GetLSRegRHS(ARMul_State *state, ARMword instr) ;
27 static ARMword GetLS7RHS(ARMul_State *state, ARMword instr) ;
28 static unsigned LoadWord(ARMul_State *state, ARMword instr, ARMword address) ;
29 static unsigned LoadHalfWord(ARMul_State *state, ARMword instr, ARMword address,int signextend) ;
30 static unsigned LoadByte(ARMul_State *state, ARMword instr, ARMword address,int signextend) ;
31 static unsigned StoreWord(ARMul_State *state, ARMword instr, ARMword address) ;
32 static unsigned StoreHalfWord(ARMul_State *state, ARMword instr, ARMword address) ;
33 static unsigned StoreByte(ARMul_State *state, ARMword instr, ARMword address) ;
34 static void LoadMult(ARMul_State *state, ARMword address, ARMword instr, ARMword WBBase) ;
35 static void StoreMult(ARMul_State *state, ARMword address, ARMword instr, ARMword WBBase) ;
36 static void LoadSMult(ARMul_State *state, ARMword address, ARMword instr, ARMword WBBase) ;
37 static void StoreSMult(ARMul_State *state, ARMword address, ARMword instr, ARMword WBBase) ;
38 static unsigned Multiply64(ARMul_State *state, ARMword instr,int signextend,int scc) ;
39 static unsigned MultiplyAdd64(ARMul_State *state, ARMword instr,int signextend,int scc) ;
41 #define LUNSIGNED (0) /* unsigned operation */
42 #define LSIGNED (1) /* signed operation */
43 #define LDEFAULT (0) /* default : do nothing */
44 #define LSCC (1) /* set condition codes on result */
46 /***************************************************************************\
47 * short-hand macros for LDR/STR *
48 \***************************************************************************/
50 /* store post decrement writeback */
53 if (StoreHalfWord(state, instr, lhs)) \
54 LSBase = lhs - GetLS7RHS(state, instr) ;
56 /* store post increment writeback */
59 if (StoreHalfWord(state, instr, lhs)) \
60 LSBase = lhs + GetLS7RHS(state, instr) ;
62 /* store pre decrement */
64 (void)StoreHalfWord(state, instr, LHS - GetLS7RHS(state, instr)) ;
66 /* store pre decrement writeback */
67 #define SHPREDOWNWB() \
68 temp = LHS - GetLS7RHS(state, instr) ; \
69 if (StoreHalfWord(state, instr, temp)) \
72 /* store pre increment */
74 (void)StoreHalfWord(state, instr, LHS + GetLS7RHS(state, instr)) ;
76 /* store pre increment writeback */
78 temp = LHS + GetLS7RHS(state, instr) ; \
79 if (StoreHalfWord(state, instr, temp)) \
82 /* load post decrement writeback */
83 #define LHPOSTDOWN() \
87 switch (BITS(5,6)) { \
89 if (LoadHalfWord(state,instr,lhs,LUNSIGNED)) \
90 LSBase = lhs - GetLS7RHS(state,instr) ; \
93 if (LoadByte(state,instr,lhs,LSIGNED)) \
94 LSBase = lhs - GetLS7RHS(state,instr) ; \
97 if (LoadHalfWord(state,instr,lhs,LSIGNED)) \
98 LSBase = lhs - GetLS7RHS(state,instr) ; \
100 case 0: /* SWP handled elsewhere */ \
109 /* load post increment writeback */
114 switch (BITS(5,6)) { \
116 if (LoadHalfWord(state,instr,lhs,LUNSIGNED)) \
117 LSBase = lhs + GetLS7RHS(state,instr) ; \
120 if (LoadByte(state,instr,lhs,LSIGNED)) \
121 LSBase = lhs + GetLS7RHS(state,instr) ; \
124 if (LoadHalfWord(state,instr,lhs,LSIGNED)) \
125 LSBase = lhs + GetLS7RHS(state,instr) ; \
127 case 0: /* SWP handled elsewhere */ \
136 /* load pre decrement */
137 #define LHPREDOWN() \
140 temp = LHS - GetLS7RHS(state,instr) ; \
141 switch (BITS(5,6)) { \
143 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
146 (void)LoadByte(state,instr,temp,LSIGNED) ; \
149 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
151 case 0: /* SWP handled elsewhere */ \
160 /* load pre decrement writeback */
161 #define LHPREDOWNWB() \
164 temp = LHS - GetLS7RHS(state, instr) ; \
165 switch (BITS(5,6)) { \
167 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
171 if (LoadByte(state,instr,temp,LSIGNED)) \
175 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
178 case 0: /* SWP handled elsewhere */ \
187 /* load pre increment */
191 temp = LHS + GetLS7RHS(state,instr) ; \
192 switch (BITS(5,6)) { \
194 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
197 (void)LoadByte(state,instr,temp,LSIGNED) ; \
200 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
202 case 0: /* SWP handled elsewhere */ \
211 /* load pre increment writeback */
212 #define LHPREUPWB() \
215 temp = LHS + GetLS7RHS(state, instr) ; \
216 switch (BITS(5,6)) { \
218 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
222 if (LoadByte(state,instr,temp,LSIGNED)) \
226 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
229 case 0: /* SWP handled elsewhere */ \
238 /***************************************************************************\
239 * EMULATION of ARM6 *
240 \***************************************************************************/
242 /* The PC pipeline value depends on whether ARM or Thumb instructions
243 are being executed: */
247 ARMword ARMul_Emulate32(register ARMul_State *state)
250 ARMword ARMul_Emulate26(register ARMul_State *state)
253 register ARMword instr, /* the current instruction */
254 dest, /* almost the DestBus */
255 temp, /* ubiquitous third hand */
256 pc ; /* the address of the current instruction */
257 ARMword lhs, rhs ; /* almost the ABus and BBus */
258 ARMword decoded, loaded ; /* instruction pipeline */
260 /***************************************************************************\
261 * Execute the next instruction *
262 \***************************************************************************/
264 if (state->NextInstr < PRIMEPIPE) {
265 decoded = state->decoded ;
266 loaded = state->loaded ;
270 do { /* just keep going */
277 switch (state->NextInstr) {
279 state->Reg[15] += isize ; /* Advance the pipeline, and an S cycle */
283 loaded = ARMul_LoadInstrS(state,pc+(isize * 2),isize) ;
287 state->Reg[15] += isize ; /* Advance the pipeline, and an N cycle */
291 loaded = ARMul_LoadInstrN(state,pc+(isize * 2),isize) ;
296 pc += isize ; /* Program counter advanced, and an S cycle */
299 loaded = ARMul_LoadInstrS(state,pc+(isize * 2),isize) ;
304 pc += isize ; /* Program counter advanced, and an N cycle */
307 loaded = ARMul_LoadInstrN(state,pc+(isize * 2),isize) ;
311 case RESUME : /* The program counter has been changed */
312 pc = state->Reg[15] ;
314 pc = pc & R15PCBITS ;
316 state->Reg[15] = pc + (isize * 2) ;
318 instr = ARMul_ReLoadInstr(state,pc,isize) ;
319 decoded = ARMul_ReLoadInstr(state,pc + isize,isize) ;
320 loaded = ARMul_ReLoadInstr(state,pc + isize * 2,isize) ;
324 default : /* The program counter has been changed */
325 pc = state->Reg[15] ;
327 pc = pc & R15PCBITS ;
329 state->Reg[15] = pc + (isize * 2) ;
331 instr = ARMul_LoadInstrN(state,pc,isize) ;
332 decoded = ARMul_LoadInstrS(state,pc + (isize),isize) ;
333 loaded = ARMul_LoadInstrS(state,pc + (isize * 2),isize) ;
338 ARMul_EnvokeEvent(state) ;
341 /* Enable this for a helpful bit of debugging when tracing is needed. */
342 fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr);
343 if (instr == 0) abort ();
346 if (state->Exception) { /* Any exceptions */
347 if (state->NresetSig == LOW) {
348 ARMul_Abort(state,ARMul_ResetV) ;
351 else if (!state->NfiqSig && !FFLAG) {
352 ARMul_Abort(state,ARMul_FIQV) ;
355 else if (!state->NirqSig && !IFLAG) {
356 ARMul_Abort(state,ARMul_IRQV) ;
361 if (state->CallDebug > 0) {
362 instr = ARMul_Debug(state,pc,instr) ;
363 if (state->Emulate < ONCE) {
364 state->NextInstr = RESUME ;
368 fprintf(stderr,"At %08lx Instr %08lx Mode %02lx\n",pc,instr,state->Mode) ;
373 if (state->Emulate < ONCE) {
374 state->NextInstr = RESUME ;
381 /* Provide Thumb instruction decoding. If the processor is in Thumb
382 mode, then we can simply decode the Thumb instruction, and map it
383 to the corresponding ARM instruction (by directly loading the
384 instr variable, and letting the normal ARM simulator
385 execute). There are some caveats to ensure that the correct
386 pipelined PC value is used when executing Thumb code, and also for
387 dealing with the BL instruction. */
388 if (TFLAG) { /* check if in Thumb mode */
390 switch (ARMul_ThumbDecode(state,pc,instr,&new)) {
392 ARMul_UndefInstr(state,instr); /* This is a Thumb instruction */
395 case t_branch: /* already processed */
398 case t_decoded: /* ARM instruction available */
399 instr = new; /* so continue instruction decoding */
405 /***************************************************************************\
406 * Check the condition codes *
407 \***************************************************************************/
408 if ((temp = TOPBITS(28)) == AL)
409 goto mainswitch ; /* vile deed in the need for speed */
411 switch ((int)TOPBITS(28)) { /* check the condition code */
412 case AL : temp=TRUE ;
414 case NV : temp=FALSE ;
416 case EQ : temp=ZFLAG ;
418 case NE : temp=!ZFLAG ;
420 case VS : temp=VFLAG ;
422 case VC : temp=!VFLAG ;
424 case MI : temp=NFLAG ;
426 case PL : temp=!NFLAG ;
428 case CS : temp=CFLAG ;
430 case CC : temp=!CFLAG ;
432 case HI : temp=(CFLAG && !ZFLAG) ;
434 case LS : temp=(!CFLAG || ZFLAG) ;
436 case GE : temp=((!NFLAG && !VFLAG) || (NFLAG && VFLAG)) ;
438 case LT : temp=((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) ;
440 case GT : temp=((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG)) ;
442 case LE : temp=((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG ;
446 /***************************************************************************\
447 * Actual execution of instructions begins here *
448 \***************************************************************************/
450 if (temp) { /* if the condition codes don't match, stop here */
453 switch ((int)BITS(20,27)) {
455 /***************************************************************************\
456 * Data Processing Register RHS Instructions *
457 \***************************************************************************/
459 case 0x00 : /* AND reg and MUL */
461 if (BITS(4,11) == 0xB) {
462 /* STRH register offset, no write-back, down, post indexed */
466 /* TODO: CHECK: should 0xD and 0xF generate undefined intruction aborts? */
468 if (BITS(4,7) == 9) { /* MUL */
469 rhs = state->Reg[MULRHSReg] ;
470 if (MULLHSReg == MULDESTReg) {
472 state->Reg[MULDESTReg] = 0 ;
474 else if (MULDESTReg != 15)
475 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs ;
479 for (dest = 0, temp = 0 ; dest < 32 ; dest++)
480 if (rhs & (1L << dest))
481 temp = dest ; /* mult takes this many/2 I cycles */
482 ARMul_Icycles(state,ARMul_MultTable[temp],0L) ;
491 case 0x01 : /* ANDS reg and MULS */
493 if ((BITS(4,11) & 0xF9) == 0x9) {
494 /* LDR register offset, no write-back, down, post indexed */
496 /* fall through to rest of decoding */
499 if (BITS(4,7) == 9) { /* MULS */
500 rhs = state->Reg[MULRHSReg] ;
501 if (MULLHSReg == MULDESTReg) {
503 state->Reg[MULDESTReg] = 0 ;
507 else if (MULDESTReg != 15) {
508 dest = state->Reg[MULLHSReg] * rhs ;
509 ARMul_NegZero(state,dest) ;
510 state->Reg[MULDESTReg] = dest ;
515 for (dest = 0, temp = 0 ; dest < 32 ; dest++)
516 if (rhs & (1L << dest))
517 temp = dest ; /* mult takes this many/2 I cycles */
518 ARMul_Icycles(state,ARMul_MultTable[temp],0L) ;
520 else { /* ANDS reg */
527 case 0x02 : /* EOR reg and MLA */
529 if (BITS(4,11) == 0xB) {
530 /* STRH register offset, write-back, down, post indexed */
535 if (BITS(4,7) == 9) { /* MLA */
536 rhs = state->Reg[MULRHSReg] ;
537 if (MULLHSReg == MULDESTReg) {
539 state->Reg[MULDESTReg] = state->Reg[MULACCReg] ;
541 else if (MULDESTReg != 15)
542 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg] ;
546 for (dest = 0, temp = 0 ; dest < 32 ; dest++)
547 if (rhs & (1L << dest))
548 temp = dest ; /* mult takes this many/2 I cycles */
549 ARMul_Icycles(state,ARMul_MultTable[temp],0L) ;
558 case 0x03 : /* EORS reg and MLAS */
560 if ((BITS(4,11) & 0xF9) == 0x9) {
561 /* LDR register offset, write-back, down, post-indexed */
563 /* fall through to rest of the decoding */
566 if (BITS(4,7) == 9) { /* MLAS */
567 rhs = state->Reg[MULRHSReg] ;
568 if (MULLHSReg == MULDESTReg) {
570 dest = state->Reg[MULACCReg] ;
571 ARMul_NegZero(state,dest) ;
572 state->Reg[MULDESTReg] = dest ;
574 else if (MULDESTReg != 15) {
575 dest = state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg] ;
576 ARMul_NegZero(state,dest) ;
577 state->Reg[MULDESTReg] = dest ;
582 for (dest = 0, temp = 0 ; dest < 32 ; dest++)
583 if (rhs & (1L << dest))
584 temp = dest ; /* mult takes this many/2 I cycles */
585 ARMul_Icycles(state,ARMul_MultTable[temp],0L) ;
587 else { /* EORS Reg */
594 case 0x04 : /* SUB reg */
596 if (BITS(4,7) == 0xB) {
597 /* STRH immediate offset, no write-back, down, post indexed */
607 case 0x05 : /* SUBS reg */
609 if ((BITS(4,7) & 0x9) == 0x9) {
610 /* LDR immediate offset, no write-back, down, post indexed */
612 /* fall through to the rest of the instruction decoding */
618 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
619 ARMul_SubCarry(state,lhs,rhs,dest) ;
620 ARMul_SubOverflow(state,lhs,rhs,dest) ;
629 case 0x06 : /* RSB reg */
631 if (BITS(4,7) == 0xB) {
632 /* STRH immediate offset, write-back, down, post indexed */
642 case 0x07 : /* RSBS reg */
644 if ((BITS(4,7) & 0x9) == 0x9) {
645 /* LDR immediate offset, write-back, down, post indexed */
647 /* fall through to remainder of instruction decoding */
653 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
654 ARMul_SubCarry(state,rhs,lhs,dest) ;
655 ARMul_SubOverflow(state,rhs,lhs,dest) ;
664 case 0x08 : /* ADD reg */
666 if (BITS(4,11) == 0xB) {
667 /* STRH register offset, no write-back, up, post indexed */
673 if (BITS(4,7) == 0x9) { /* MULL */
675 ARMul_Icycles(state,Multiply64(state,instr,LUNSIGNED,LDEFAULT),0L) ;
684 case 0x09 : /* ADDS reg */
686 if ((BITS(4,11) & 0xF9) == 0x9) {
687 /* LDR register offset, no write-back, up, post indexed */
689 /* fall through to remaining instruction decoding */
693 if (BITS(4,7) == 0x9) { /* MULL */
695 ARMul_Icycles(state,Multiply64(state,instr,LUNSIGNED,LSCC),0L) ;
703 if ((lhs | rhs) >> 30) { /* possible C,V,N to set */
705 ARMul_AddCarry(state,lhs,rhs,dest) ;
706 ARMul_AddOverflow(state,lhs,rhs,dest) ;
716 case 0x0a : /* ADC reg */
718 if (BITS(4,11) == 0xB) {
719 /* STRH register offset, write-back, up, post-indexed */
725 if (BITS(4,7) == 0x9) { /* MULL */
727 ARMul_Icycles(state,MultiplyAdd64(state,instr,LUNSIGNED,LDEFAULT),0L) ;
732 dest = LHS + rhs + CFLAG ;
736 case 0x0b : /* ADCS reg */
738 if ((BITS(4,11) & 0xF9) == 0x9) {
739 /* LDR register offset, write-back, up, post indexed */
741 /* fall through to remaining instruction decoding */
745 if (BITS(4,7) == 0x9) { /* MULL */
747 ARMul_Icycles(state,MultiplyAdd64(state,instr,LUNSIGNED,LSCC),0L) ;
753 dest = lhs + rhs + CFLAG ;
755 if ((lhs | rhs) >> 30) { /* possible C,V,N to set */
757 ARMul_AddCarry(state,lhs,rhs,dest) ;
758 ARMul_AddOverflow(state,lhs,rhs,dest) ;
768 case 0x0c : /* SBC reg */
770 if (BITS(4,7) == 0xB) {
771 /* STRH immediate offset, no write-back, up post indexed */
777 if (BITS(4,7) == 0x9) { /* MULL */
779 ARMul_Icycles(state,Multiply64(state,instr,LSIGNED,LDEFAULT),0L) ;
784 dest = LHS - rhs - !CFLAG ;
788 case 0x0d : /* SBCS reg */
790 if ((BITS(4,7) & 0x9) == 0x9) {
791 /* LDR immediate offset, no write-back, up, post indexed */
796 if (BITS(4,7) == 0x9) { /* MULL */
798 ARMul_Icycles(state,Multiply64(state,instr,LSIGNED,LSCC),0L) ;
804 dest = lhs - rhs - !CFLAG ;
805 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
806 ARMul_SubCarry(state,lhs,rhs,dest) ;
807 ARMul_SubOverflow(state,lhs,rhs,dest) ;
816 case 0x0e : /* RSC reg */
818 if (BITS(4,7) == 0xB) {
819 /* STRH immediate offset, write-back, up, post indexed */
825 if (BITS(4,7) == 0x9) { /* MULL */
827 ARMul_Icycles(state,MultiplyAdd64(state,instr,LSIGNED,LDEFAULT),0L) ;
832 dest = rhs - LHS - !CFLAG ;
836 case 0x0f : /* RSCS reg */
838 if ((BITS(4,7) & 0x9) == 0x9) {
839 /* LDR immediate offset, write-back, up, post indexed */
841 /* fall through to remaining instruction decoding */
845 if (BITS(4,7) == 0x9) { /* MULL */
847 ARMul_Icycles(state,MultiplyAdd64(state,instr,LSIGNED,LSCC),0L) ;
853 dest = rhs - lhs - !CFLAG ;
854 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
855 ARMul_SubCarry(state,rhs,lhs,dest) ;
856 ARMul_SubOverflow(state,rhs,lhs,dest) ;
865 case 0x10 : /* TST reg and MRS CPSR and SWP word */
867 if (BITS(4,11) == 0xB) {
868 /* STRH register offset, no write-back, down, pre indexed */
873 if (BITS(4,11) == 9) { /* SWP */
878 if (VECTORACCESS(temp) || ADDREXCEPT(temp)) {
879 INTERNALABORT(temp) ;
880 (void)ARMul_LoadWordN(state,temp) ;
881 (void)ARMul_LoadWordN(state,temp) ;
885 dest = ARMul_SwapWord(state,temp,state->Reg[RHSReg]) ;
887 DEST = ARMul_Align(state,temp,dest) ;
890 if (state->abortSig || state->Aborted) {
894 else if ((BITS(0,11)==0) && (LHSReg==15)) { /* MRS CPSR */
896 DEST = ECC | EINT | EMODE ;
903 case 0x11 : /* TSTP reg */
905 if ((BITS(4,11) & 0xF9) == 0x9) {
906 /* LDR register offset, no write-back, down, pre indexed */
908 /* continue with remaining instruction decode */
911 if (DESTReg == 15) { /* TSTP reg */
913 state->Cpsr = GETSPSR(state->Bank) ;
914 ARMul_CPSRAltered(state) ;
924 ARMul_NegZero(state,dest) ;
928 case 0x12 : /* TEQ reg and MSR reg to CPSR (ARM6) */
930 if (BITS(4,11) == 0xB) {
931 /* STRH register offset, write-back, down, pre indexed */
937 if (BITS(4,27)==0x12FFF1) { /* BX */
938 /* Branch to the address in RHSReg. If bit0 of
939 destination address is 1 then switch to Thumb mode: */
940 ARMword addr = state->Reg[RHSReg];
942 /* If we read the PC then the bottom bit is clear */
943 if (RHSReg == 15) addr &= ~1;
945 /* Enable this for a helpful bit of debugging when
946 GDB is not yet fully working...
947 fprintf (stderr, "BX at %x to %x (go %s)\n",
948 state->Reg[15], addr, (addr & 1) ? "thumb": "arm" ); */
950 if (addr & (1 << 0)) { /* Thumb bit */
952 state->Reg[15] = addr & 0xfffffffe;
953 /* NOTE: The other CPSR flag setting blocks do not
954 seem to update the state->Cpsr state, but just do
955 the explicit flag. The copy from the seperate
956 flags to the register must happen later. */
960 state->Reg[15] = addr & 0xfffffffc;
965 if (DESTReg==15 && BITS(17,18)==0) { /* MSR reg to CPSR */
968 ARMul_FixCPSR(state,instr,temp) ;
975 case 0x13 : /* TEQP reg */
977 if ((BITS(4,11) & 0xF9) == 0x9) {
978 /* LDR register offset, write-back, down, pre indexed */
980 /* continue with remaining instruction decode */
983 if (DESTReg == 15) { /* TEQP reg */
985 state->Cpsr = GETSPSR(state->Bank) ;
986 ARMul_CPSRAltered(state) ;
996 ARMul_NegZero(state,dest) ;
1000 case 0x14 : /* CMP reg and MRS SPSR and SWP byte */
1002 if (BITS(4,7) == 0xB) {
1003 /* STRH immediate offset, no write-back, down, pre indexed */
1008 if (BITS(4,11) == 9) { /* SWP */
1013 if (VECTORACCESS(temp) || ADDREXCEPT(temp)) {
1014 INTERNALABORT(temp) ;
1015 (void)ARMul_LoadByte(state,temp) ;
1016 (void)ARMul_LoadByte(state,temp) ;
1020 DEST = ARMul_SwapByte(state,temp,state->Reg[RHSReg]) ;
1021 if (state->abortSig || state->Aborted) {
1025 else if ((BITS(0,11)==0) && (LHSReg==15)) { /* MRS SPSR */
1027 DEST = GETSPSR(state->Bank) ;
1034 case 0x15 : /* CMPP reg */
1036 if ((BITS(4,7) & 0x9) == 0x9) {
1037 /* LDR immediate offset, no write-back, down, pre indexed */
1039 /* continue with remaining instruction decode */
1042 if (DESTReg == 15) { /* CMPP reg */
1044 state->Cpsr = GETSPSR(state->Bank) ;
1045 ARMul_CPSRAltered(state) ;
1052 else { /* CMP reg */
1056 ARMul_NegZero(state,dest) ;
1057 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1058 ARMul_SubCarry(state,lhs,rhs,dest) ;
1059 ARMul_SubOverflow(state,lhs,rhs,dest) ;
1068 case 0x16 : /* CMN reg and MSR reg to SPSR */
1070 if (BITS(4,7) == 0xB) {
1071 /* STRH immediate offset, write-back, down, pre indexed */
1076 if (DESTReg==15 && BITS(17,18)==0) { /* MSR */
1078 ARMul_FixSPSR(state,instr,DPRegRHS);
1085 case 0x17 : /* CMNP reg */
1087 if ((BITS(4,7) & 0x9) == 0x9) {
1088 /* LDR immediate offset, write-back, down, pre indexed */
1090 /* continue with remaining instruction decoding */
1093 if (DESTReg == 15) {
1095 state->Cpsr = GETSPSR(state->Bank) ;
1096 ARMul_CPSRAltered(state) ;
1104 else { /* CMN reg */
1109 if ((lhs | rhs) >> 30) { /* possible C,V,N to set */
1110 ASSIGNN(NEG(dest)) ;
1111 ARMul_AddCarry(state,lhs,rhs,dest) ;
1112 ARMul_AddOverflow(state,lhs,rhs,dest) ;
1122 case 0x18 : /* ORR reg */
1124 if (BITS(4,11) == 0xB) {
1125 /* STRH register offset, no write-back, up, pre indexed */
1135 case 0x19 : /* ORRS reg */
1137 if ((BITS(4,11) & 0xF9) == 0x9) {
1138 /* LDR register offset, no write-back, up, pre indexed */
1140 /* continue with remaining instruction decoding */
1148 case 0x1a : /* MOV reg */
1150 if (BITS(4,11) == 0xB) {
1151 /* STRH register offset, write-back, up, pre indexed */
1160 case 0x1b : /* MOVS reg */
1162 if ((BITS(4,11) & 0xF9) == 0x9) {
1163 /* LDR register offset, write-back, up, pre indexed */
1165 /* continue with remaining instruction decoding */
1172 case 0x1c : /* BIC reg */
1174 if (BITS(4,7) == 0xB) {
1175 /* STRH immediate offset, no write-back, up, pre indexed */
1185 case 0x1d : /* BICS reg */
1187 if ((BITS(4,7) & 0x9) == 0x9) {
1188 /* LDR immediate offset, no write-back, up, pre indexed */
1190 /* continue with instruction decoding */
1198 case 0x1e : /* MVN reg */
1200 if (BITS(4,7) == 0xB) {
1201 /* STRH immediate offset, write-back, up, pre indexed */
1210 case 0x1f : /* MVNS reg */
1212 if ((BITS(4,7) & 0x9) == 0x9) {
1213 /* LDR immediate offset, write-back, up, pre indexed */
1215 /* continue instruction decoding */
1222 /***************************************************************************\
1223 * Data Processing Immediate RHS Instructions *
1224 \***************************************************************************/
1226 case 0x20 : /* AND immed */
1227 dest = LHS & DPImmRHS ;
1231 case 0x21 : /* ANDS immed */
1237 case 0x22 : /* EOR immed */
1238 dest = LHS ^ DPImmRHS ;
1242 case 0x23 : /* EORS immed */
1248 case 0x24 : /* SUB immed */
1249 dest = LHS - DPImmRHS ;
1253 case 0x25 : /* SUBS immed */
1257 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1258 ARMul_SubCarry(state,lhs,rhs,dest) ;
1259 ARMul_SubOverflow(state,lhs,rhs,dest) ;
1268 case 0x26 : /* RSB immed */
1269 dest = DPImmRHS - LHS ;
1273 case 0x27 : /* RSBS immed */
1277 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
1278 ARMul_SubCarry(state,rhs,lhs,dest) ;
1279 ARMul_SubOverflow(state,rhs,lhs,dest) ;
1288 case 0x28 : /* ADD immed */
1289 dest = LHS + DPImmRHS ;
1293 case 0x29 : /* ADDS immed */
1298 if ((lhs | rhs) >> 30) { /* possible C,V,N to set */
1299 ASSIGNN(NEG(dest)) ;
1300 ARMul_AddCarry(state,lhs,rhs,dest) ;
1301 ARMul_AddOverflow(state,lhs,rhs,dest) ;
1311 case 0x2a : /* ADC immed */
1312 dest = LHS + DPImmRHS + CFLAG ;
1316 case 0x2b : /* ADCS immed */
1319 dest = lhs + rhs + CFLAG ;
1321 if ((lhs | rhs) >> 30) { /* possible C,V,N to set */
1322 ASSIGNN(NEG(dest)) ;
1323 ARMul_AddCarry(state,lhs,rhs,dest) ;
1324 ARMul_AddOverflow(state,lhs,rhs,dest) ;
1334 case 0x2c : /* SBC immed */
1335 dest = LHS - DPImmRHS - !CFLAG ;
1339 case 0x2d : /* SBCS immed */
1342 dest = lhs - rhs - !CFLAG ;
1343 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1344 ARMul_SubCarry(state,lhs,rhs,dest) ;
1345 ARMul_SubOverflow(state,lhs,rhs,dest) ;
1354 case 0x2e : /* RSC immed */
1355 dest = DPImmRHS - LHS - !CFLAG ;
1359 case 0x2f : /* RSCS immed */
1362 dest = rhs - lhs - !CFLAG ;
1363 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
1364 ARMul_SubCarry(state,rhs,lhs,dest) ;
1365 ARMul_SubOverflow(state,rhs,lhs,dest) ;
1374 case 0x30 : /* TST immed */
1378 case 0x31 : /* TSTP immed */
1379 if (DESTReg == 15) { /* TSTP immed */
1381 state->Cpsr = GETSPSR(state->Bank) ;
1382 ARMul_CPSRAltered(state) ;
1384 temp = LHS & DPImmRHS ;
1389 DPSImmRHS ; /* TST immed */
1391 ARMul_NegZero(state,dest) ;
1395 case 0x32 : /* TEQ immed and MSR immed to CPSR */
1396 if (DESTReg==15 && BITS(17,18)==0) { /* MSR immed to CPSR */
1397 ARMul_FixCPSR(state,instr,DPImmRHS) ;
1404 case 0x33 : /* TEQP immed */
1405 if (DESTReg == 15) { /* TEQP immed */
1407 state->Cpsr = GETSPSR(state->Bank) ;
1408 ARMul_CPSRAltered(state) ;
1410 temp = LHS ^ DPImmRHS ;
1415 DPSImmRHS ; /* TEQ immed */
1417 ARMul_NegZero(state,dest) ;
1421 case 0x34 : /* CMP immed */
1425 case 0x35 : /* CMPP immed */
1426 if (DESTReg == 15) { /* CMPP immed */
1428 state->Cpsr = GETSPSR(state->Bank) ;
1429 ARMul_CPSRAltered(state) ;
1431 temp = LHS - DPImmRHS ;
1437 lhs = LHS ; /* CMP immed */
1440 ARMul_NegZero(state,dest) ;
1441 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1442 ARMul_SubCarry(state,lhs,rhs,dest) ;
1443 ARMul_SubOverflow(state,lhs,rhs,dest) ;
1452 case 0x36 : /* CMN immed and MSR immed to SPSR */
1453 if (DESTReg==15 && BITS(17,18)==0) /* MSR */
1454 ARMul_FixSPSR(state, instr, DPImmRHS) ;
1460 case 0x37 : /* CMNP immed */
1461 if (DESTReg == 15) { /* CMNP immed */
1463 state->Cpsr = GETSPSR(state->Bank) ;
1464 ARMul_CPSRAltered(state) ;
1466 temp = LHS + DPImmRHS ;
1472 lhs = LHS ; /* CMN immed */
1476 if ((lhs | rhs) >> 30) { /* possible C,V,N to set */
1477 ASSIGNN(NEG(dest)) ;
1478 ARMul_AddCarry(state,lhs,rhs,dest) ;
1479 ARMul_AddOverflow(state,lhs,rhs,dest) ;
1489 case 0x38 : /* ORR immed */
1490 dest = LHS | DPImmRHS ;
1494 case 0x39 : /* ORRS immed */
1500 case 0x3a : /* MOV immed */
1505 case 0x3b : /* MOVS immed */
1510 case 0x3c : /* BIC immed */
1511 dest = LHS & ~DPImmRHS ;
1515 case 0x3d : /* BICS immed */
1521 case 0x3e : /* MVN immed */
1526 case 0x3f : /* MVNS immed */
1531 /***************************************************************************\
1532 * Single Data Transfer Immediate RHS Instructions *
1533 \***************************************************************************/
1535 case 0x40 : /* Store Word, No WriteBack, Post Dec, Immed */
1537 if (StoreWord(state,instr,lhs))
1538 LSBase = lhs - LSImmRHS ;
1541 case 0x41 : /* Load Word, No WriteBack, Post Dec, Immed */
1543 if (LoadWord(state,instr,lhs))
1544 LSBase = lhs - LSImmRHS ;
1547 case 0x42 : /* Store Word, WriteBack, Post Dec, Immed */
1548 UNDEF_LSRBaseEQDestWb ;
1551 temp = lhs - LSImmRHS ;
1552 state->NtransSig = LOW ;
1553 if (StoreWord(state,instr,lhs))
1555 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1558 case 0x43 : /* Load Word, WriteBack, Post Dec, Immed */
1559 UNDEF_LSRBaseEQDestWb ;
1562 state->NtransSig = LOW ;
1563 if (LoadWord(state,instr,lhs))
1564 LSBase = lhs - LSImmRHS ;
1565 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1568 case 0x44 : /* Store Byte, No WriteBack, Post Dec, Immed */
1570 if (StoreByte(state,instr,lhs))
1571 LSBase = lhs - LSImmRHS ;
1574 case 0x45 : /* Load Byte, No WriteBack, Post Dec, Immed */
1576 if (LoadByte(state,instr,lhs,LUNSIGNED))
1577 LSBase = lhs - LSImmRHS ;
1580 case 0x46 : /* Store Byte, WriteBack, Post Dec, Immed */
1581 UNDEF_LSRBaseEQDestWb ;
1584 state->NtransSig = LOW ;
1585 if (StoreByte(state,instr,lhs))
1586 LSBase = lhs - LSImmRHS ;
1587 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1590 case 0x47 : /* Load Byte, WriteBack, Post Dec, Immed */
1591 UNDEF_LSRBaseEQDestWb ;
1594 state->NtransSig = LOW ;
1595 if (LoadByte(state,instr,lhs,LUNSIGNED))
1596 LSBase = lhs - LSImmRHS ;
1597 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1600 case 0x48 : /* Store Word, No WriteBack, Post Inc, Immed */
1602 if (StoreWord(state,instr,lhs))
1603 LSBase = lhs + LSImmRHS ;
1606 case 0x49 : /* Load Word, No WriteBack, Post Inc, Immed */
1608 if (LoadWord(state,instr,lhs))
1609 LSBase = lhs + LSImmRHS ;
1612 case 0x4a : /* Store Word, WriteBack, Post Inc, Immed */
1613 UNDEF_LSRBaseEQDestWb ;
1616 state->NtransSig = LOW ;
1617 if (StoreWord(state,instr,lhs))
1618 LSBase = lhs + LSImmRHS ;
1619 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1622 case 0x4b : /* Load Word, WriteBack, Post Inc, Immed */
1623 UNDEF_LSRBaseEQDestWb ;
1626 state->NtransSig = LOW ;
1627 if (LoadWord(state,instr,lhs))
1628 LSBase = lhs + LSImmRHS ;
1629 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1632 case 0x4c : /* Store Byte, No WriteBack, Post Inc, Immed */
1634 if (StoreByte(state,instr,lhs))
1635 LSBase = lhs + LSImmRHS ;
1638 case 0x4d : /* Load Byte, No WriteBack, Post Inc, Immed */
1640 if (LoadByte(state,instr,lhs,LUNSIGNED))
1641 LSBase = lhs + LSImmRHS ;
1644 case 0x4e : /* Store Byte, WriteBack, Post Inc, Immed */
1645 UNDEF_LSRBaseEQDestWb ;
1648 state->NtransSig = LOW ;
1649 if (StoreByte(state,instr,lhs))
1650 LSBase = lhs + LSImmRHS ;
1651 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1654 case 0x4f : /* Load Byte, WriteBack, Post Inc, Immed */
1655 UNDEF_LSRBaseEQDestWb ;
1658 state->NtransSig = LOW ;
1659 if (LoadByte(state,instr,lhs,LUNSIGNED))
1660 LSBase = lhs + LSImmRHS ;
1661 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1665 case 0x50 : /* Store Word, No WriteBack, Pre Dec, Immed */
1666 (void)StoreWord(state,instr,LHS - LSImmRHS) ;
1669 case 0x51 : /* Load Word, No WriteBack, Pre Dec, Immed */
1670 (void)LoadWord(state,instr,LHS - LSImmRHS) ;
1673 case 0x52 : /* Store Word, WriteBack, Pre Dec, Immed */
1674 UNDEF_LSRBaseEQDestWb ;
1676 temp = LHS - LSImmRHS ;
1677 if (StoreWord(state,instr,temp))
1681 case 0x53 : /* Load Word, WriteBack, Pre Dec, Immed */
1682 UNDEF_LSRBaseEQDestWb ;
1684 temp = LHS - LSImmRHS ;
1685 if (LoadWord(state,instr,temp))
1689 case 0x54 : /* Store Byte, No WriteBack, Pre Dec, Immed */
1690 (void)StoreByte(state,instr,LHS - LSImmRHS) ;
1693 case 0x55 : /* Load Byte, No WriteBack, Pre Dec, Immed */
1694 (void)LoadByte(state,instr,LHS - LSImmRHS,LUNSIGNED) ;
1697 case 0x56 : /* Store Byte, WriteBack, Pre Dec, Immed */
1698 UNDEF_LSRBaseEQDestWb ;
1700 temp = LHS - LSImmRHS ;
1701 if (StoreByte(state,instr,temp))
1705 case 0x57 : /* Load Byte, WriteBack, Pre Dec, Immed */
1706 UNDEF_LSRBaseEQDestWb ;
1708 temp = LHS - LSImmRHS ;
1709 if (LoadByte(state,instr,temp,LUNSIGNED))
1713 case 0x58 : /* Store Word, No WriteBack, Pre Inc, Immed */
1714 (void)StoreWord(state,instr,LHS + LSImmRHS) ;
1717 case 0x59 : /* Load Word, No WriteBack, Pre Inc, Immed */
1718 (void)LoadWord(state,instr,LHS + LSImmRHS) ;
1721 case 0x5a : /* Store Word, WriteBack, Pre Inc, Immed */
1722 UNDEF_LSRBaseEQDestWb ;
1724 temp = LHS + LSImmRHS ;
1725 if (StoreWord(state,instr,temp))
1729 case 0x5b : /* Load Word, WriteBack, Pre Inc, Immed */
1730 UNDEF_LSRBaseEQDestWb ;
1732 temp = LHS + LSImmRHS ;
1733 if (LoadWord(state,instr,temp))
1737 case 0x5c : /* Store Byte, No WriteBack, Pre Inc, Immed */
1738 (void)StoreByte(state,instr,LHS + LSImmRHS) ;
1741 case 0x5d : /* Load Byte, No WriteBack, Pre Inc, Immed */
1742 (void)LoadByte(state,instr,LHS + LSImmRHS,LUNSIGNED) ;
1745 case 0x5e : /* Store Byte, WriteBack, Pre Inc, Immed */
1746 UNDEF_LSRBaseEQDestWb ;
1748 temp = LHS + LSImmRHS ;
1749 if (StoreByte(state,instr,temp))
1753 case 0x5f : /* Load Byte, WriteBack, Pre Inc, Immed */
1754 UNDEF_LSRBaseEQDestWb ;
1756 temp = LHS + LSImmRHS ;
1757 if (LoadByte(state,instr,temp,LUNSIGNED))
1761 /***************************************************************************\
1762 * Single Data Transfer Register RHS Instructions *
1763 \***************************************************************************/
1765 case 0x60 : /* Store Word, No WriteBack, Post Dec, Reg */
1767 ARMul_UndefInstr(state,instr) ;
1770 UNDEF_LSRBaseEQOffWb ;
1771 UNDEF_LSRBaseEQDestWb ;
1775 if (StoreWord(state,instr,lhs))
1776 LSBase = lhs - LSRegRHS ;
1779 case 0x61 : /* Load Word, No WriteBack, Post Dec, Reg */
1781 ARMul_UndefInstr(state,instr) ;
1784 UNDEF_LSRBaseEQOffWb ;
1785 UNDEF_LSRBaseEQDestWb ;
1789 if (LoadWord(state,instr,lhs))
1790 LSBase = lhs - LSRegRHS ;
1793 case 0x62 : /* Store Word, WriteBack, Post Dec, Reg */
1795 ARMul_UndefInstr(state,instr) ;
1798 UNDEF_LSRBaseEQOffWb ;
1799 UNDEF_LSRBaseEQDestWb ;
1803 state->NtransSig = LOW ;
1804 if (StoreWord(state,instr,lhs))
1805 LSBase = lhs - LSRegRHS ;
1806 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1809 case 0x63 : /* Load Word, WriteBack, Post Dec, Reg */
1811 ARMul_UndefInstr(state,instr) ;
1814 UNDEF_LSRBaseEQOffWb ;
1815 UNDEF_LSRBaseEQDestWb ;
1819 state->NtransSig = LOW ;
1820 if (LoadWord(state,instr,lhs))
1821 LSBase = lhs - LSRegRHS ;
1822 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1825 case 0x64 : /* Store Byte, No WriteBack, Post Dec, Reg */
1827 ARMul_UndefInstr(state,instr) ;
1830 UNDEF_LSRBaseEQOffWb ;
1831 UNDEF_LSRBaseEQDestWb ;
1835 if (StoreByte(state,instr,lhs))
1836 LSBase = lhs - LSRegRHS ;
1839 case 0x65 : /* Load Byte, No WriteBack, Post Dec, Reg */
1841 ARMul_UndefInstr(state,instr) ;
1844 UNDEF_LSRBaseEQOffWb ;
1845 UNDEF_LSRBaseEQDestWb ;
1849 if (LoadByte(state,instr,lhs,LUNSIGNED))
1850 LSBase = lhs - LSRegRHS ;
1853 case 0x66 : /* Store Byte, WriteBack, Post Dec, Reg */
1855 ARMul_UndefInstr(state,instr) ;
1858 UNDEF_LSRBaseEQOffWb ;
1859 UNDEF_LSRBaseEQDestWb ;
1863 state->NtransSig = LOW ;
1864 if (StoreByte(state,instr,lhs))
1865 LSBase = lhs - LSRegRHS ;
1866 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1869 case 0x67 : /* Load Byte, WriteBack, Post Dec, Reg */
1871 ARMul_UndefInstr(state,instr) ;
1874 UNDEF_LSRBaseEQOffWb ;
1875 UNDEF_LSRBaseEQDestWb ;
1879 state->NtransSig = LOW ;
1880 if (LoadByte(state,instr,lhs,LUNSIGNED))
1881 LSBase = lhs - LSRegRHS ;
1882 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1885 case 0x68 : /* Store Word, No WriteBack, Post Inc, Reg */
1887 ARMul_UndefInstr(state,instr) ;
1890 UNDEF_LSRBaseEQOffWb ;
1891 UNDEF_LSRBaseEQDestWb ;
1895 if (StoreWord(state,instr,lhs))
1896 LSBase = lhs + LSRegRHS ;
1899 case 0x69 : /* Load Word, No WriteBack, Post Inc, Reg */
1901 ARMul_UndefInstr(state,instr) ;
1904 UNDEF_LSRBaseEQOffWb ;
1905 UNDEF_LSRBaseEQDestWb ;
1909 if (LoadWord(state,instr,lhs))
1910 LSBase = lhs + LSRegRHS ;
1913 case 0x6a : /* Store Word, WriteBack, Post Inc, Reg */
1915 ARMul_UndefInstr(state,instr) ;
1918 UNDEF_LSRBaseEQOffWb ;
1919 UNDEF_LSRBaseEQDestWb ;
1923 state->NtransSig = LOW ;
1924 if (StoreWord(state,instr,lhs))
1925 LSBase = lhs + LSRegRHS ;
1926 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1929 case 0x6b : /* Load Word, WriteBack, Post Inc, Reg */
1931 ARMul_UndefInstr(state,instr) ;
1934 UNDEF_LSRBaseEQOffWb ;
1935 UNDEF_LSRBaseEQDestWb ;
1939 state->NtransSig = LOW ;
1940 if (LoadWord(state,instr,lhs))
1941 LSBase = lhs + LSRegRHS ;
1942 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1945 case 0x6c : /* Store Byte, No WriteBack, Post Inc, Reg */
1947 ARMul_UndefInstr(state,instr) ;
1950 UNDEF_LSRBaseEQOffWb ;
1951 UNDEF_LSRBaseEQDestWb ;
1955 if (StoreByte(state,instr,lhs))
1956 LSBase = lhs + LSRegRHS ;
1959 case 0x6d : /* Load Byte, No WriteBack, Post Inc, Reg */
1961 ARMul_UndefInstr(state,instr) ;
1964 UNDEF_LSRBaseEQOffWb ;
1965 UNDEF_LSRBaseEQDestWb ;
1969 if (LoadByte(state,instr,lhs,LUNSIGNED))
1970 LSBase = lhs + LSRegRHS ;
1973 case 0x6e : /* Store Byte, WriteBack, Post Inc, Reg */
1975 ARMul_UndefInstr(state,instr) ;
1978 UNDEF_LSRBaseEQOffWb ;
1979 UNDEF_LSRBaseEQDestWb ;
1983 state->NtransSig = LOW ;
1984 if (StoreByte(state,instr,lhs))
1985 LSBase = lhs + LSRegRHS ;
1986 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
1989 case 0x6f : /* Load Byte, WriteBack, Post Inc, Reg */
1991 ARMul_UndefInstr(state,instr) ;
1994 UNDEF_LSRBaseEQOffWb ;
1995 UNDEF_LSRBaseEQDestWb ;
1999 state->NtransSig = LOW ;
2000 if (LoadByte(state,instr,lhs,LUNSIGNED))
2001 LSBase = lhs + LSRegRHS ;
2002 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
2006 case 0x70 : /* Store Word, No WriteBack, Pre Dec, Reg */
2008 ARMul_UndefInstr(state,instr) ;
2011 (void)StoreWord(state,instr,LHS - LSRegRHS) ;
2014 case 0x71 : /* Load Word, No WriteBack, Pre Dec, Reg */
2016 ARMul_UndefInstr(state,instr) ;
2019 (void)LoadWord(state,instr,LHS - LSRegRHS) ;
2022 case 0x72 : /* Store Word, WriteBack, Pre Dec, Reg */
2024 ARMul_UndefInstr(state,instr) ;
2027 UNDEF_LSRBaseEQOffWb ;
2028 UNDEF_LSRBaseEQDestWb ;
2031 temp = LHS - LSRegRHS ;
2032 if (StoreWord(state,instr,temp))
2036 case 0x73 : /* Load Word, WriteBack, Pre Dec, Reg */
2038 ARMul_UndefInstr(state,instr) ;
2041 UNDEF_LSRBaseEQOffWb ;
2042 UNDEF_LSRBaseEQDestWb ;
2045 temp = LHS - LSRegRHS ;
2046 if (LoadWord(state,instr,temp))
2050 case 0x74 : /* Store Byte, No WriteBack, Pre Dec, Reg */
2052 ARMul_UndefInstr(state,instr) ;
2055 (void)StoreByte(state,instr,LHS - LSRegRHS) ;
2058 case 0x75 : /* Load Byte, No WriteBack, Pre Dec, Reg */
2060 ARMul_UndefInstr(state,instr) ;
2063 (void)LoadByte(state,instr,LHS - LSRegRHS,LUNSIGNED) ;
2066 case 0x76 : /* Store Byte, WriteBack, Pre Dec, Reg */
2068 ARMul_UndefInstr(state,instr) ;
2071 UNDEF_LSRBaseEQOffWb ;
2072 UNDEF_LSRBaseEQDestWb ;
2075 temp = LHS - LSRegRHS ;
2076 if (StoreByte(state,instr,temp))
2080 case 0x77 : /* Load Byte, WriteBack, Pre Dec, Reg */
2082 ARMul_UndefInstr(state,instr) ;
2085 UNDEF_LSRBaseEQOffWb ;
2086 UNDEF_LSRBaseEQDestWb ;
2089 temp = LHS - LSRegRHS ;
2090 if (LoadByte(state,instr,temp,LUNSIGNED))
2094 case 0x78 : /* Store Word, No WriteBack, Pre Inc, Reg */
2096 ARMul_UndefInstr(state,instr) ;
2099 (void)StoreWord(state,instr,LHS + LSRegRHS) ;
2102 case 0x79 : /* Load Word, No WriteBack, Pre Inc, Reg */
2104 ARMul_UndefInstr(state,instr) ;
2107 (void)LoadWord(state,instr,LHS + LSRegRHS) ;
2110 case 0x7a : /* Store Word, WriteBack, Pre Inc, Reg */
2112 ARMul_UndefInstr(state,instr) ;
2115 UNDEF_LSRBaseEQOffWb ;
2116 UNDEF_LSRBaseEQDestWb ;
2119 temp = LHS + LSRegRHS ;
2120 if (StoreWord(state,instr,temp))
2124 case 0x7b : /* Load Word, WriteBack, Pre Inc, Reg */
2126 ARMul_UndefInstr(state,instr) ;
2129 UNDEF_LSRBaseEQOffWb ;
2130 UNDEF_LSRBaseEQDestWb ;
2133 temp = LHS + LSRegRHS ;
2134 if (LoadWord(state,instr,temp))
2138 case 0x7c : /* Store Byte, No WriteBack, Pre Inc, Reg */
2140 ARMul_UndefInstr(state,instr) ;
2143 (void)StoreByte(state,instr,LHS + LSRegRHS) ;
2146 case 0x7d : /* Load Byte, No WriteBack, Pre Inc, Reg */
2148 ARMul_UndefInstr(state,instr) ;
2151 (void)LoadByte(state,instr,LHS + LSRegRHS,LUNSIGNED) ;
2154 case 0x7e : /* Store Byte, WriteBack, Pre Inc, Reg */
2156 ARMul_UndefInstr(state,instr) ;
2159 UNDEF_LSRBaseEQOffWb ;
2160 UNDEF_LSRBaseEQDestWb ;
2163 temp = LHS + LSRegRHS ;
2164 if (StoreByte(state,instr,temp))
2168 case 0x7f : /* Load Byte, WriteBack, Pre Inc, Reg */
2170 ARMul_UndefInstr(state,instr) ;
2173 UNDEF_LSRBaseEQOffWb ;
2174 UNDEF_LSRBaseEQDestWb ;
2177 temp = LHS + LSRegRHS ;
2178 if (LoadByte(state,instr,temp,LUNSIGNED))
2182 /***************************************************************************\
2183 * Multiple Data Transfer Instructions *
2184 \***************************************************************************/
2186 case 0x80 : /* Store, No WriteBack, Post Dec */
2187 STOREMULT(instr,LSBase - LSMNumRegs + 4L,0L) ;
2190 case 0x81 : /* Load, No WriteBack, Post Dec */
2191 LOADMULT(instr,LSBase - LSMNumRegs + 4L,0L) ;
2194 case 0x82 : /* Store, WriteBack, Post Dec */
2195 temp = LSBase - LSMNumRegs ;
2196 STOREMULT(instr,temp + 4L,temp) ;
2199 case 0x83 : /* Load, WriteBack, Post Dec */
2200 temp = LSBase - LSMNumRegs ;
2201 LOADMULT(instr,temp + 4L,temp) ;
2204 case 0x84 : /* Store, Flags, No WriteBack, Post Dec */
2205 STORESMULT(instr,LSBase - LSMNumRegs + 4L,0L) ;
2208 case 0x85 : /* Load, Flags, No WriteBack, Post Dec */
2209 LOADSMULT(instr,LSBase - LSMNumRegs + 4L,0L) ;
2212 case 0x86 : /* Store, Flags, WriteBack, Post Dec */
2213 temp = LSBase - LSMNumRegs ;
2214 STORESMULT(instr,temp + 4L,temp) ;
2217 case 0x87 : /* Load, Flags, WriteBack, Post Dec */
2218 temp = LSBase - LSMNumRegs ;
2219 LOADSMULT(instr,temp + 4L,temp) ;
2223 case 0x88 : /* Store, No WriteBack, Post Inc */
2224 STOREMULT(instr,LSBase,0L) ;
2227 case 0x89 : /* Load, No WriteBack, Post Inc */
2228 LOADMULT(instr,LSBase,0L) ;
2231 case 0x8a : /* Store, WriteBack, Post Inc */
2233 STOREMULT(instr,temp,temp + LSMNumRegs) ;
2236 case 0x8b : /* Load, WriteBack, Post Inc */
2238 LOADMULT(instr,temp,temp + LSMNumRegs) ;
2241 case 0x8c : /* Store, Flags, No WriteBack, Post Inc */
2242 STORESMULT(instr,LSBase,0L) ;
2245 case 0x8d : /* Load, Flags, No WriteBack, Post Inc */
2246 LOADSMULT(instr,LSBase,0L) ;
2249 case 0x8e : /* Store, Flags, WriteBack, Post Inc */
2251 STORESMULT(instr,temp,temp + LSMNumRegs) ;
2254 case 0x8f : /* Load, Flags, WriteBack, Post Inc */
2256 LOADSMULT(instr,temp,temp + LSMNumRegs) ;
2260 case 0x90 : /* Store, No WriteBack, Pre Dec */
2261 STOREMULT(instr,LSBase - LSMNumRegs,0L) ;
2264 case 0x91 : /* Load, No WriteBack, Pre Dec */
2265 LOADMULT(instr,LSBase - LSMNumRegs,0L) ;
2268 case 0x92 : /* Store, WriteBack, Pre Dec */
2269 temp = LSBase - LSMNumRegs ;
2270 STOREMULT(instr,temp,temp) ;
2273 case 0x93 : /* Load, WriteBack, Pre Dec */
2274 temp = LSBase - LSMNumRegs ;
2275 LOADMULT(instr,temp,temp) ;
2278 case 0x94 : /* Store, Flags, No WriteBack, Pre Dec */
2279 STORESMULT(instr,LSBase - LSMNumRegs,0L) ;
2282 case 0x95 : /* Load, Flags, No WriteBack, Pre Dec */
2283 LOADSMULT(instr,LSBase - LSMNumRegs,0L) ;
2286 case 0x96 : /* Store, Flags, WriteBack, Pre Dec */
2287 temp = LSBase - LSMNumRegs ;
2288 STORESMULT(instr,temp,temp) ;
2291 case 0x97 : /* Load, Flags, WriteBack, Pre Dec */
2292 temp = LSBase - LSMNumRegs ;
2293 LOADSMULT(instr,temp,temp) ;
2297 case 0x98 : /* Store, No WriteBack, Pre Inc */
2298 STOREMULT(instr,LSBase + 4L,0L) ;
2301 case 0x99 : /* Load, No WriteBack, Pre Inc */
2302 LOADMULT(instr,LSBase + 4L,0L) ;
2305 case 0x9a : /* Store, WriteBack, Pre Inc */
2307 STOREMULT(instr,temp + 4L,temp + LSMNumRegs) ;
2310 case 0x9b : /* Load, WriteBack, Pre Inc */
2312 LOADMULT(instr,temp + 4L,temp + LSMNumRegs) ;
2315 case 0x9c : /* Store, Flags, No WriteBack, Pre Inc */
2316 STORESMULT(instr,LSBase + 4L,0L) ;
2319 case 0x9d : /* Load, Flags, No WriteBack, Pre Inc */
2320 LOADSMULT(instr,LSBase + 4L,0L) ;
2323 case 0x9e : /* Store, Flags, WriteBack, Pre Inc */
2325 STORESMULT(instr,temp + 4L,temp + LSMNumRegs) ;
2328 case 0x9f : /* Load, Flags, WriteBack, Pre Inc */
2330 LOADSMULT(instr,temp + 4L,temp + LSMNumRegs) ;
2333 /***************************************************************************\
2335 \***************************************************************************/
2337 case 0xa0 : case 0xa1 : case 0xa2 : case 0xa3 :
2338 case 0xa4 : case 0xa5 : case 0xa6 : case 0xa7 :
2339 state->Reg[15] = pc + 8 + POSBRANCH ;
2343 /***************************************************************************\
2345 \***************************************************************************/
2347 case 0xa8 : case 0xa9 : case 0xaa : case 0xab :
2348 case 0xac : case 0xad : case 0xae : case 0xaf :
2349 state->Reg[15] = pc + 8 + NEGBRANCH ;
2353 /***************************************************************************\
2354 * Branch and Link forward *
2355 \***************************************************************************/
2357 case 0xb0 : case 0xb1 : case 0xb2 : case 0xb3 :
2358 case 0xb4 : case 0xb5 : case 0xb6 : case 0xb7 :
2360 state->Reg[14] = pc + 4 ; /* put PC into Link */
2362 state->Reg[14] = pc + 4 | ECC | ER15INT | EMODE ; /* put PC into Link */
2364 state->Reg[15] = pc + 8 + POSBRANCH ;
2368 /***************************************************************************\
2369 * Branch and Link backward *
2370 \***************************************************************************/
2372 case 0xb8 : case 0xb9 : case 0xba : case 0xbb :
2373 case 0xbc : case 0xbd : case 0xbe : case 0xbf :
2375 state->Reg[14] = pc + 4 ; /* put PC into Link */
2377 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE ; /* put PC into Link */
2379 state->Reg[15] = pc + 8 + NEGBRANCH ;
2383 /***************************************************************************\
2384 * Co-Processor Data Transfers *
2385 \***************************************************************************/
2388 case 0xc4 : /* Store , No WriteBack , Post Dec */
2389 ARMul_STC(state,instr,LHS) ;
2393 case 0xc5 : /* Load , No WriteBack , Post Dec */
2394 ARMul_LDC(state,instr,LHS) ;
2398 case 0xc6 : /* Store , WriteBack , Post Dec */
2400 state->Base = lhs - LSCOff ;
2401 ARMul_STC(state,instr,lhs) ;
2405 case 0xc7 : /* Load , WriteBack , Post Dec */
2407 state->Base = lhs - LSCOff ;
2408 ARMul_LDC(state,instr,lhs) ;
2412 case 0xcc : /* Store , No WriteBack , Post Inc */
2413 ARMul_STC(state,instr,LHS) ;
2417 case 0xcd : /* Load , No WriteBack , Post Inc */
2418 ARMul_LDC(state,instr,LHS) ;
2422 case 0xce : /* Store , WriteBack , Post Inc */
2424 state->Base = lhs + LSCOff ;
2425 ARMul_STC(state,instr,LHS) ;
2429 case 0xcf : /* Load , WriteBack , Post Inc */
2431 state->Base = lhs + LSCOff ;
2432 ARMul_LDC(state,instr,LHS) ;
2437 case 0xd4 : /* Store , No WriteBack , Pre Dec */
2438 ARMul_STC(state,instr,LHS - LSCOff) ;
2442 case 0xd5 : /* Load , No WriteBack , Pre Dec */
2443 ARMul_LDC(state,instr,LHS - LSCOff) ;
2447 case 0xd6 : /* Store , WriteBack , Pre Dec */
2448 lhs = LHS - LSCOff ;
2450 ARMul_STC(state,instr,lhs) ;
2454 case 0xd7 : /* Load , WriteBack , Pre Dec */
2455 lhs = LHS - LSCOff ;
2457 ARMul_LDC(state,instr,lhs) ;
2461 case 0xdc : /* Store , No WriteBack , Pre Inc */
2462 ARMul_STC(state,instr,LHS + LSCOff) ;
2466 case 0xdd : /* Load , No WriteBack , Pre Inc */
2467 ARMul_LDC(state,instr,LHS + LSCOff) ;
2471 case 0xde : /* Store , WriteBack , Pre Inc */
2472 lhs = LHS + LSCOff ;
2474 ARMul_STC(state,instr,lhs) ;
2478 case 0xdf : /* Load , WriteBack , Pre Inc */
2479 lhs = LHS + LSCOff ;
2481 ARMul_LDC(state,instr,lhs) ;
2484 /***************************************************************************\
2485 * Co-Processor Register Transfers (MCR) and Data Ops *
2486 \***************************************************************************/
2488 case 0xe0 : case 0xe2 : case 0xe4 : case 0xe6 :
2489 case 0xe8 : case 0xea : case 0xec : case 0xee :
2490 if (BIT(4)) { /* MCR */
2491 if (DESTReg == 15) {
2494 ARMul_MCR(state,instr,state->Reg[15] + isize) ;
2496 ARMul_MCR(state,instr,ECC | ER15INT | EMODE |
2497 ((state->Reg[15] + isize) & R15PCBITS) ) ;
2501 ARMul_MCR(state,instr,DEST) ;
2503 else /* CDP Part 1 */
2504 ARMul_CDP(state,instr) ;
2507 /***************************************************************************\
2508 * Co-Processor Register Transfers (MRC) and Data Ops *
2509 \***************************************************************************/
2511 case 0xe1 : case 0xe3 : case 0xe5 : case 0xe7 :
2512 case 0xe9 : case 0xeb : case 0xed : case 0xef :
2513 if (BIT(4)) { /* MRC */
2514 temp = ARMul_MRC(state,instr) ;
2515 if (DESTReg == 15) {
2516 ASSIGNN((temp & NBIT) != 0) ;
2517 ASSIGNZ((temp & ZBIT) != 0) ;
2518 ASSIGNC((temp & CBIT) != 0) ;
2519 ASSIGNV((temp & VBIT) != 0) ;
2524 else /* CDP Part 2 */
2525 ARMul_CDP(state,instr) ;
2528 /***************************************************************************\
2530 \***************************************************************************/
2532 case 0xf0 : case 0xf1 : case 0xf2 : case 0xf3 :
2533 case 0xf4 : case 0xf5 : case 0xf6 : case 0xf7 :
2534 case 0xf8 : case 0xf9 : case 0xfa : case 0xfb :
2535 case 0xfc : case 0xfd : case 0xfe : case 0xff :
2536 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc) { /* a prefetch abort */
2537 ARMul_Abort(state,ARMul_PrefetchAbortV) ;
2541 if (!ARMul_OSHandleSWI(state,BITS(0,23))) {
2542 ARMul_Abort(state,ARMul_SWIV) ;
2545 } /* 256 way main switch */
2552 if (state->Emulate == ONCE)
2553 state->Emulate = STOP;
2554 else if (state->Emulate != RUN)
2556 } while (1) ; /* do loop */
2558 state->decoded = decoded ;
2559 state->loaded = loaded ;
2562 } /* Emulate 26/32 in instruction based mode */
2565 /***************************************************************************\
2566 * This routine evaluates most Data Processing register RHS's with the S *
2567 * bit clear. It is intended to be called from the macro DPRegRHS, which *
2568 * filters the common case of an unshifted register with in line code *
2569 \***************************************************************************/
2571 static ARMword GetDPRegRHS(ARMul_State *state, ARMword instr)
2572 {ARMword shamt , base ;
2575 if (BIT(4)) { /* shift amount in a register */
2580 base = ECC | ER15INT | R15PC | EMODE ;
2583 base = state->Reg[base] ;
2584 ARMul_Icycles(state,1,0L) ;
2585 shamt = state->Reg[BITS(8,11)] & 0xff ;
2586 switch ((int)BITS(5,6)) {
2587 case LSL : if (shamt == 0)
2589 else if (shamt >= 32)
2592 return(base << shamt) ;
2593 case LSR : if (shamt == 0)
2595 else if (shamt >= 32)
2598 return(base >> shamt) ;
2599 case ASR : if (shamt == 0)
2601 else if (shamt >= 32)
2602 return((ARMword)((long int)base >> 31L)) ;
2604 return((ARMword)((long int)base >> (int)shamt)) ;
2605 case ROR : shamt &= 0x1f ;
2609 return((base << (32 - shamt)) | (base >> shamt)) ;
2612 else { /* shift amount is a constant */
2615 base = ECC | ER15INT | R15PC | EMODE ;
2618 base = state->Reg[base] ;
2619 shamt = BITS(7,11) ;
2620 switch ((int)BITS(5,6)) {
2621 case LSL : return(base<<shamt) ;
2622 case LSR : if (shamt == 0)
2625 return(base >> shamt) ;
2626 case ASR : if (shamt == 0)
2627 return((ARMword)((long int)base >> 31L)) ;
2629 return((ARMword)((long int)base >> (int)shamt)) ;
2630 case ROR : if (shamt==0) /* its an RRX */
2631 return((base >> 1) | (CFLAG << 31)) ;
2633 return((base << (32 - shamt)) | (base >> shamt)) ;
2636 return(0) ; /* just to shut up lint */
2638 /***************************************************************************\
2639 * This routine evaluates most Logical Data Processing register RHS's *
2640 * with the S bit set. It is intended to be called from the macro *
2641 * DPSRegRHS, which filters the common case of an unshifted register *
2642 * with in line code *
2643 \***************************************************************************/
2645 static ARMword GetDPSRegRHS(ARMul_State *state, ARMword instr)
2646 {ARMword shamt , base ;
2649 if (BIT(4)) { /* shift amount in a register */
2654 base = ECC | ER15INT | R15PC | EMODE ;
2657 base = state->Reg[base] ;
2658 ARMul_Icycles(state,1,0L) ;
2659 shamt = state->Reg[BITS(8,11)] & 0xff ;
2660 switch ((int)BITS(5,6)) {
2661 case LSL : if (shamt == 0)
2663 else if (shamt == 32) {
2667 else if (shamt > 32) {
2672 ASSIGNC((base >> (32-shamt)) & 1) ;
2673 return(base << shamt) ;
2675 case LSR : if (shamt == 0)
2677 else if (shamt == 32) {
2678 ASSIGNC(base >> 31) ;
2681 else if (shamt > 32) {
2686 ASSIGNC((base >> (shamt - 1)) & 1) ;
2687 return(base >> shamt) ;
2689 case ASR : if (shamt == 0)
2691 else if (shamt >= 32) {
2692 ASSIGNC(base >> 31L) ;
2693 return((ARMword)((long int)base >> 31L)) ;
2696 ASSIGNC((ARMword)((long int)base >> (int)(shamt-1)) & 1) ;
2697 return((ARMword)((long int)base >> (int)shamt)) ;
2699 case ROR : if (shamt == 0)
2703 ASSIGNC(base >> 31) ;
2707 ASSIGNC((base >> (shamt-1)) & 1) ;
2708 return((base << (32-shamt)) | (base >> shamt)) ;
2712 else { /* shift amount is a constant */
2715 base = ECC | ER15INT | R15PC | EMODE ;
2718 base = state->Reg[base] ;
2719 shamt = BITS(7,11) ;
2720 switch ((int)BITS(5,6)) {
2721 case LSL : ASSIGNC((base >> (32-shamt)) & 1) ;
2722 return(base << shamt) ;
2723 case LSR : if (shamt == 0) {
2724 ASSIGNC(base >> 31) ;
2728 ASSIGNC((base >> (shamt - 1)) & 1) ;
2729 return(base >> shamt) ;
2731 case ASR : if (shamt == 0) {
2732 ASSIGNC(base >> 31L) ;
2733 return((ARMword)((long int)base >> 31L)) ;
2736 ASSIGNC((ARMword)((long int)base >> (int)(shamt-1)) & 1) ;
2737 return((ARMword)((long int)base >> (int)shamt)) ;
2739 case ROR : if (shamt == 0) { /* its an RRX */
2742 return((base >> 1) | (shamt << 31)) ;
2745 ASSIGNC((base >> (shamt - 1)) & 1) ;
2746 return((base << (32-shamt)) | (base >> shamt)) ;
2750 return(0) ; /* just to shut up lint */
2753 /***************************************************************************\
2754 * This routine handles writes to register 15 when the S bit is not set. *
2755 \***************************************************************************/
2757 static void WriteR15(ARMul_State *state, ARMword src)
2759 /* The ARM documentation implies (but doe snot state) that the bottom bit of the PC is never set */
2761 state->Reg[15] = src & PCBITS & ~ 0x1 ;
2763 state->Reg[15] = (src & R15PCBITS & ~ 0x1) | ECC | ER15INT | EMODE ;
2764 ARMul_R15Altered(state) ;
2769 /***************************************************************************\
2770 * This routine handles writes to register 15 when the S bit is set. *
2771 \***************************************************************************/
2773 static void WriteSR15(ARMul_State *state, ARMword src)
2776 state->Reg[15] = src & PCBITS ;
2777 if (state->Bank > 0) {
2778 state->Cpsr = state->Spsr[state->Bank] ;
2779 ARMul_CPSRAltered(state) ;
2782 if (state->Bank == USERBANK)
2783 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE ;
2785 state->Reg[15] = src ;
2786 ARMul_R15Altered(state) ;
2791 /***************************************************************************\
2792 * This routine evaluates most Load and Store register RHS's. It is *
2793 * intended to be called from the macro LSRegRHS, which filters the *
2794 * common case of an unshifted register with in line code *
2795 \***************************************************************************/
2797 static ARMword GetLSRegRHS(ARMul_State *state, ARMword instr)
2798 {ARMword shamt, base ;
2803 base = ECC | ER15INT | R15PC | EMODE ; /* Now forbidden, but .... */
2806 base = state->Reg[base] ;
2808 shamt = BITS(7,11) ;
2809 switch ((int)BITS(5,6)) {
2810 case LSL : return(base << shamt) ;
2811 case LSR : if (shamt == 0)
2814 return(base >> shamt) ;
2815 case ASR : if (shamt == 0)
2816 return((ARMword)((long int)base >> 31L)) ;
2818 return((ARMword)((long int)base >> (int)shamt)) ;
2819 case ROR : if (shamt==0) /* its an RRX */
2820 return((base >> 1) | (CFLAG << 31)) ;
2822 return((base << (32-shamt)) | (base >> shamt)) ;
2824 return(0) ; /* just to shut up lint */
2827 /***************************************************************************\
2828 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
2829 \***************************************************************************/
2831 static ARMword GetLS7RHS(ARMul_State *state, ARMword instr)
2833 if (BIT(22) == 0) { /* register */
2836 return ECC | ER15INT | R15PC | EMODE ; /* Now forbidden, but ... */
2838 return state->Reg[RHSReg] ;
2841 /* else immediate */
2842 return BITS(0,3) | (BITS(8,11) << 4) ;
2845 /***************************************************************************\
2846 * This function does the work of loading a word for a LDR instruction. *
2847 \***************************************************************************/
2849 static unsigned LoadWord(ARMul_State *state, ARMword instr, ARMword address)
2855 if (ADDREXCEPT(address)) {
2856 INTERNALABORT(address) ;
2859 dest = ARMul_LoadWordN(state,address) ;
2860 if (state->Aborted) {
2862 return(state->lateabtSig) ;
2865 dest = ARMul_Align(state,address,dest) ;
2867 ARMul_Icycles(state,1,0L) ;
2869 return(DESTReg != LHSReg) ;
2873 /***************************************************************************\
2874 * This function does the work of loading a halfword. *
2875 \***************************************************************************/
2877 static unsigned LoadHalfWord(ARMul_State *state, ARMword instr, ARMword address,int signextend)
2883 if (ADDREXCEPT(address)) {
2884 INTERNALABORT(address) ;
2887 dest = ARMul_LoadHalfWord(state,address) ;
2888 if (state->Aborted) {
2890 return(state->lateabtSig) ;
2895 if (dest & 1 << (16 - 1))
2896 dest = (dest & ((1 << 16) - 1)) - (1 << 16) ;
2899 ARMul_Icycles(state,1,0L) ;
2900 return(DESTReg != LHSReg) ;
2904 /***************************************************************************\
2905 * This function does the work of loading a byte for a LDRB instruction. *
2906 \***************************************************************************/
2908 static unsigned LoadByte(ARMul_State *state, ARMword instr, ARMword address,int signextend)
2914 if (ADDREXCEPT(address)) {
2915 INTERNALABORT(address) ;
2918 dest = ARMul_LoadByte(state,address) ;
2919 if (state->Aborted) {
2921 return(state->lateabtSig) ;
2926 if (dest & 1 << (8 - 1))
2927 dest = (dest & ((1 << 8) - 1)) - (1 << 8) ;
2930 ARMul_Icycles(state,1,0L) ;
2931 return(DESTReg != LHSReg) ;
2934 /***************************************************************************\
2935 * This function does the work of storing a word from a STR instruction. *
2936 \***************************************************************************/
2938 static unsigned StoreWord(ARMul_State *state, ARMword instr, ARMword address)
2942 state->Reg[15] = ECC | ER15INT | R15PC | EMODE ;
2945 ARMul_StoreWordN(state,address,DEST) ;
2947 if (VECTORACCESS(address) || ADDREXCEPT(address)) {
2948 INTERNALABORT(address) ;
2949 (void)ARMul_LoadWordN(state,address) ;
2952 ARMul_StoreWordN(state,address,DEST) ;
2954 if (state->Aborted) {
2956 return(state->lateabtSig) ;
2962 /***************************************************************************\
2963 * This function does the work of storing a byte for a STRH instruction. *
2964 \***************************************************************************/
2966 static unsigned StoreHalfWord(ARMul_State *state, ARMword instr, ARMword address)
2971 state->Reg[15] = ECC | ER15INT | R15PC | EMODE ;
2975 ARMul_StoreHalfWord(state,address,DEST);
2977 if (VECTORACCESS(address) || ADDREXCEPT(address)) {
2978 INTERNALABORT(address) ;
2979 (void)ARMul_LoadHalfWord(state,address) ;
2982 ARMul_StoreHalfWord(state,address,DEST) ;
2985 if (state->Aborted) {
2987 return(state->lateabtSig) ;
2994 /***************************************************************************\
2995 * This function does the work of storing a byte for a STRB instruction. *
2996 \***************************************************************************/
2998 static unsigned StoreByte(ARMul_State *state, ARMword instr, ARMword address)
3002 state->Reg[15] = ECC | ER15INT | R15PC | EMODE ;
3005 ARMul_StoreByte(state,address,DEST) ;
3007 if (VECTORACCESS(address) || ADDREXCEPT(address)) {
3008 INTERNALABORT(address) ;
3009 (void)ARMul_LoadByte(state,address) ;
3012 ARMul_StoreByte(state,address,DEST) ;
3014 if (state->Aborted) {
3016 return(state->lateabtSig) ;
3022 /***************************************************************************\
3023 * This function does the work of loading the registers listed in an LDM *
3024 * instruction, when the S bit is clear. The code here is always increment *
3025 * after, it's up to the caller to get the input address correct and to *
3026 * handle base register modification. *
3027 \***************************************************************************/
3029 static void LoadMult(ARMul_State *state, ARMword instr,
3030 ARMword address, ARMword WBBase)
3031 {ARMword dest, temp ;
3035 UNDEF_LSMBaseInListWb ;
3038 if (ADDREXCEPT(address)) {
3039 INTERNALABORT(address) ;
3042 if (BIT(21) && LHSReg != 15)
3045 for (temp = 0 ; !BIT(temp) ; temp++) ; /* N cycle first */
3046 dest = ARMul_LoadWordN(state,address) ;
3047 if (!state->abortSig && !state->Aborted)
3048 state->Reg[temp++] = dest ;
3050 if (!state->Aborted)
3051 state->Aborted = ARMul_DataAbortV ;
3053 for (; temp < 16 ; temp++) /* S cycles from here on */
3054 if (BIT(temp)) { /* load this register */
3056 dest = ARMul_LoadWordS(state,address) ;
3057 if (!state->abortSig && !state->Aborted)
3058 state->Reg[temp] = dest ;
3060 if (!state->Aborted)
3061 state->Aborted = ARMul_DataAbortV ;
3064 if (BIT(15)) { /* PC is in the reg list */
3066 state->Reg[15] = PC ;
3071 ARMul_Icycles(state,1,0L) ; /* to write back the final register */
3073 if (state->Aborted) {
3074 if (BIT(21) && LHSReg != 15)
3080 /***************************************************************************\
3081 * This function does the work of loading the registers listed in an LDM *
3082 * instruction, when the S bit is set. The code here is always increment *
3083 * after, it's up to the caller to get the input address correct and to *
3084 * handle base register modification. *
3085 \***************************************************************************/
3087 static void LoadSMult(ARMul_State *state, ARMword instr,
3088 ARMword address, ARMword WBBase)
3089 {ARMword dest, temp ;
3093 UNDEF_LSMBaseInListWb ;
3096 if (ADDREXCEPT(address)) {
3097 INTERNALABORT(address) ;
3101 if (!BIT(15) && state->Bank != USERBANK) {
3102 (void)ARMul_SwitchMode(state,state->Mode,USER26MODE) ; /* temporary reg bank switch */
3103 UNDEF_LSMUserBankWb ;
3106 if (BIT(21) && LHSReg != 15)
3109 for (temp = 0 ; !BIT(temp) ; temp++) ; /* N cycle first */
3110 dest = ARMul_LoadWordN(state,address) ;
3111 if (!state->abortSig)
3112 state->Reg[temp++] = dest ;
3114 if (!state->Aborted)
3115 state->Aborted = ARMul_DataAbortV ;
3117 for (; temp < 16 ; temp++) /* S cycles from here on */
3118 if (BIT(temp)) { /* load this register */
3120 dest = ARMul_LoadWordS(state,address) ;
3121 if (!state->abortSig || state->Aborted)
3122 state->Reg[temp] = dest ;
3124 if (!state->Aborted)
3125 state->Aborted = ARMul_DataAbortV ;
3128 if (BIT(15)) { /* PC is in the reg list */
3130 if (state->Mode != USER26MODE && state->Mode != USER32MODE) {
3131 state->Cpsr = GETSPSR(state->Bank) ;
3132 ARMul_CPSRAltered(state) ;
3134 state->Reg[15] = PC ;
3136 if (state->Mode == USER26MODE || state->Mode == USER32MODE) { /* protect bits in user mode */
3137 ASSIGNN((state->Reg[15] & NBIT) != 0) ;
3138 ASSIGNZ((state->Reg[15] & ZBIT) != 0) ;
3139 ASSIGNC((state->Reg[15] & CBIT) != 0) ;
3140 ASSIGNV((state->Reg[15] & VBIT) != 0) ;
3143 ARMul_R15Altered(state) ;
3148 if (!BIT(15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
3149 (void)ARMul_SwitchMode(state,USER26MODE,state->Mode) ; /* restore the correct bank */
3151 ARMul_Icycles(state,1,0L) ; /* to write back the final register */
3153 if (state->Aborted) {
3154 if (BIT(21) && LHSReg != 15)
3161 /***************************************************************************\
3162 * This function does the work of storing the registers listed in an STM *
3163 * instruction, when the S bit is clear. The code here is always increment *
3164 * after, it's up to the caller to get the input address correct and to *
3165 * handle base register modification. *
3166 \***************************************************************************/
3168 static void StoreMult(ARMul_State *state, ARMword instr,
3169 ARMword address, ARMword WBBase)
3174 UNDEF_LSMBaseInListWb ;
3176 BUSUSEDINCPCN ; /* N-cycle, increment the PC and update the NextInstr state */
3180 if (VECTORACCESS(address) || ADDREXCEPT(address)) {
3181 INTERNALABORT(address) ;
3187 for (temp = 0 ; !BIT(temp) ; temp++) ; /* N cycle first */
3189 ARMul_StoreWordN(state,address,state->Reg[temp++]) ;
3191 if (state->Aborted) {
3192 (void)ARMul_LoadWordN(state,address) ;
3193 for ( ; temp < 16 ; temp++) /* Fake the Stores as Loads */
3194 if (BIT(temp)) { /* save this register */
3196 (void)ARMul_LoadWordS(state,address) ;
3198 if (BIT(21) && LHSReg != 15)
3204 ARMul_StoreWordN(state,address,state->Reg[temp++]) ;
3206 if (state->abortSig && !state->Aborted)
3207 state->Aborted = ARMul_DataAbortV ;
3209 if (BIT(21) && LHSReg != 15)
3212 for ( ; temp < 16 ; temp++) /* S cycles from here on */
3213 if (BIT(temp)) { /* save this register */
3215 ARMul_StoreWordS(state,address,state->Reg[temp]) ;
3216 if (state->abortSig && !state->Aborted)
3217 state->Aborted = ARMul_DataAbortV ;
3219 if (state->Aborted) {
3224 /***************************************************************************\
3225 * This function does the work of storing the registers listed in an STM *
3226 * instruction when the S bit is set. The code here is always increment *
3227 * after, it's up to the caller to get the input address correct and to *
3228 * handle base register modification. *
3229 \***************************************************************************/
3231 static void StoreSMult(ARMul_State *state, ARMword instr,
3232 ARMword address, ARMword WBBase)
3237 UNDEF_LSMBaseInListWb ;
3240 if (VECTORACCESS(address) || ADDREXCEPT(address)) {
3241 INTERNALABORT(address) ;
3247 if (state->Bank != USERBANK) {
3248 (void)ARMul_SwitchMode(state,state->Mode,USER26MODE) ; /* Force User Bank */
3249 UNDEF_LSMUserBankWb ;
3252 for (temp = 0 ; !BIT(temp) ; temp++) ; /* N cycle first */
3254 ARMul_StoreWordN(state,address,state->Reg[temp++]) ;
3256 if (state->Aborted) {
3257 (void)ARMul_LoadWordN(state,address) ;
3258 for ( ; temp < 16 ; temp++) /* Fake the Stores as Loads */
3259 if (BIT(temp)) { /* save this register */
3261 (void)ARMul_LoadWordS(state,address) ;
3263 if (BIT(21) && LHSReg != 15)
3269 ARMul_StoreWordN(state,address,state->Reg[temp++]) ;
3271 if (state->abortSig && !state->Aborted)
3272 state->Aborted = ARMul_DataAbortV ;
3274 if (BIT(21) && LHSReg != 15)
3277 for (; temp < 16 ; temp++) /* S cycles from here on */
3278 if (BIT(temp)) { /* save this register */
3280 ARMul_StoreWordS(state,address,state->Reg[temp]) ;
3281 if (state->abortSig && !state->Aborted)
3282 state->Aborted = ARMul_DataAbortV ;
3285 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
3286 (void)ARMul_SwitchMode(state,USER26MODE,state->Mode) ; /* restore the correct bank */
3288 if (state->Aborted) {
3293 /***************************************************************************\
3294 * This function does the work of adding two 32bit values together, and *
3295 * calculating if a carry has occurred. *
3296 \***************************************************************************/
3298 static ARMword Add32(ARMword a1,ARMword a2,int *carry)
3300 ARMword result = (a1 + a2);
3301 unsigned int uresult = (unsigned int)result;
3302 unsigned int ua1 = (unsigned int)a1;
3304 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
3305 or (result > RdLo) then we have no carry: */
3306 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
3314 /***************************************************************************\
3315 * This function does the work of multiplying two 32bit values to give a *
3317 \***************************************************************************/
3319 static unsigned Multiply64(ARMul_State *state,ARMword instr,int msigned,int scc)
3321 int nRdHi, nRdLo, nRs, nRm; /* operand register numbers */
3322 ARMword RdHi, RdLo, Rm;
3323 int scount; /* cycle count */
3325 nRdHi = BITS(16,19);
3326 nRdLo = BITS(12,15);
3330 /* Needed to calculate the cycle count: */
3331 Rm = state->Reg[nRm];
3333 /* Check for illegal operand combinations first: */
3342 ARMword lo, mid1, mid2, hi; /* intermediate results */
3344 ARMword Rs = state->Reg[ nRs ];
3349 /* Compute sign of result and adjust operands if necessary. */
3351 sign = (Rm ^ Rs) & 0x80000000;
3353 if (((signed long)Rm) < 0)
3356 if (((signed long)Rs) < 0)
3360 /* We can split the 32x32 into four 16x16 operations. This ensures
3361 that we do not lose precision on 32bit only hosts: */
3362 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
3363 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
3364 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
3365 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
3367 /* We now need to add all of these results together, taking care
3368 to propogate the carries from the additions: */
3369 RdLo = Add32(lo,(mid1 << 16),&carry);
3371 RdLo = Add32(RdLo,(mid2 << 16),&carry);
3372 RdHi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
3376 /* Negate result if necessary. */
3380 if (RdLo == 0xFFFFFFFF)
3389 state->Reg[nRdLo] = RdLo;
3390 state->Reg[nRdHi] = RdHi;
3392 } /* else undefined result */
3393 else fprintf (stderr, "MULTIPLY64 - INVALID ARGUMENTS\n");
3397 if ((RdHi == 0) && (RdLo == 0))
3398 ARMul_NegZero(state,RdHi); /* zero value */
3400 ARMul_NegZero(state,scc); /* non-zero value */
3403 /* The cycle count depends on whether the instruction is a signed or
3404 unsigned multiply, and what bits are clear in the multiplier: */
3405 if (msigned && (Rm & ((unsigned)1 << 31)))
3406 Rm = ~Rm; /* invert the bits to make the check against zero */
3408 if ((Rm & 0xFFFFFF00) == 0)
3410 else if ((Rm & 0xFFFF0000) == 0)
3412 else if ((Rm & 0xFF000000) == 0)
3420 /***************************************************************************\
3421 * This function does the work of multiplying two 32bit values and adding *
3422 * a 64bit value to give a 64bit result. *
3423 \***************************************************************************/
3425 static unsigned MultiplyAdd64(ARMul_State *state,ARMword instr,int msigned,int scc)
3432 nRdHi = BITS(16,19);
3433 nRdLo = BITS(12,15);
3435 RdHi = state->Reg[nRdHi] ;
3436 RdLo = state->Reg[nRdLo] ;
3438 scount = Multiply64(state,instr,msigned,LDEFAULT);
3440 RdLo = Add32(RdLo,state->Reg[nRdLo],&carry);
3441 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
3443 state->Reg[nRdLo] = RdLo;
3444 state->Reg[nRdHi] = RdHi;
3447 if ((RdHi == 0) && (RdLo == 0))
3448 ARMul_NegZero(state,RdHi); /* zero value */
3450 ARMul_NegZero(state,scc); /* non-zero value */
3453 return scount + 1; /* extra cycle for addition */