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 void WriteR15Branch (ARMul_State
* state
, ARMword src
);
28 static ARMword
GetLSRegRHS (ARMul_State
* state
, ARMword instr
);
29 static ARMword
GetLS7RHS (ARMul_State
* state
, ARMword instr
);
30 static unsigned LoadWord (ARMul_State
* state
, ARMword instr
,
32 static unsigned LoadHalfWord (ARMul_State
* state
, ARMword instr
,
33 ARMword address
, int signextend
);
34 static unsigned LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
,
36 static unsigned StoreWord (ARMul_State
* state
, ARMword instr
,
38 static unsigned StoreHalfWord (ARMul_State
* state
, ARMword instr
,
40 static unsigned StoreByte (ARMul_State
* state
, ARMword instr
,
42 static void LoadMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
44 static void StoreMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
46 static void LoadSMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
48 static void StoreSMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
50 static unsigned Multiply64 (ARMul_State
* state
, ARMword instr
,
51 int signextend
, int scc
);
52 static unsigned MultiplyAdd64 (ARMul_State
* state
, ARMword instr
,
53 int signextend
, int scc
);
54 static void Handle_Load_Double (ARMul_State
* state
, ARMword instr
);
55 static void Handle_Store_Double (ARMul_State
* state
, ARMword instr
);
57 #define LUNSIGNED (0) /* unsigned operation */
58 #define LSIGNED (1) /* signed operation */
59 #define LDEFAULT (0) /* default : do nothing */
60 #define LSCC (1) /* set condition codes on result */
62 #ifdef NEED_UI_LOOP_HOOK
63 /* How often to run the ui_loop update, when in use */
64 #define UI_LOOP_POLL_INTERVAL 0x32000
66 /* Counter for the ui_loop_hook update */
67 static long ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
69 /* Actual hook to call to run through gdb's gui event loop */
70 extern int (*ui_loop_hook
) (int);
71 #endif /* NEED_UI_LOOP_HOOK */
73 extern int stop_simulator
;
75 /***************************************************************************\
76 * short-hand macros for LDR/STR *
77 \***************************************************************************/
79 /* store post decrement writeback */
82 if (StoreHalfWord(state, instr, lhs)) \
83 LSBase = lhs - GetLS7RHS(state, instr) ;
85 /* store post increment writeback */
88 if (StoreHalfWord(state, instr, lhs)) \
89 LSBase = lhs + GetLS7RHS(state, instr) ;
91 /* store pre decrement */
93 (void)StoreHalfWord(state, instr, LHS - GetLS7RHS(state, instr)) ;
95 /* store pre decrement writeback */
96 #define SHPREDOWNWB() \
97 temp = LHS - GetLS7RHS(state, instr) ; \
98 if (StoreHalfWord(state, instr, temp)) \
101 /* store pre increment */
103 (void)StoreHalfWord(state, instr, LHS + GetLS7RHS(state, instr)) ;
105 /* store pre increment writeback */
106 #define SHPREUPWB() \
107 temp = LHS + GetLS7RHS(state, instr) ; \
108 if (StoreHalfWord(state, instr, temp)) \
111 /* Load post decrement writeback. */
112 #define LHPOSTDOWN() \
116 temp = lhs - GetLS7RHS (state, instr); \
118 switch (BITS (5, 6)) \
121 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
125 if (LoadByte (state, instr, lhs, LSIGNED)) \
129 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
132 case 0: /* SWP handled elsewhere. */ \
141 /* Load post increment writeback. */
146 temp = lhs + GetLS7RHS (state, instr); \
148 switch (BITS (5, 6)) \
151 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
155 if (LoadByte (state, instr, lhs, LSIGNED)) \
159 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
162 case 0: /* SWP handled elsewhere. */ \
172 /* load pre decrement */
173 #define LHPREDOWN() \
176 temp = LHS - GetLS7RHS(state,instr) ; \
177 switch (BITS(5,6)) { \
179 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
182 (void)LoadByte(state,instr,temp,LSIGNED) ; \
185 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
187 case 0: /* SWP handled elsewhere */ \
196 /* load pre decrement writeback */
197 #define LHPREDOWNWB() \
200 temp = LHS - GetLS7RHS(state, instr) ; \
201 switch (BITS(5,6)) { \
203 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
207 if (LoadByte(state,instr,temp,LSIGNED)) \
211 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
214 case 0: /* SWP handled elsewhere */ \
223 /* load pre increment */
227 temp = LHS + GetLS7RHS(state,instr) ; \
228 switch (BITS(5,6)) { \
230 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
233 (void)LoadByte(state,instr,temp,LSIGNED) ; \
236 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
238 case 0: /* SWP handled elsewhere */ \
247 /* load pre increment writeback */
248 #define LHPREUPWB() \
251 temp = LHS + GetLS7RHS(state, instr) ; \
252 switch (BITS(5,6)) { \
254 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
258 if (LoadByte(state,instr,temp,LSIGNED)) \
262 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
265 case 0: /* SWP handled elsewhere */ \
274 /***************************************************************************\
275 * EMULATION of ARM6 *
276 \***************************************************************************/
278 /* The PC pipeline value depends on whether ARM or Thumb instructions
279 are being executed: */
284 ARMul_Emulate32 (register ARMul_State
* state
)
286 ARMul_Emulate26 (register ARMul_State
* state
)
289 register ARMword instr
, /* the current instruction */
290 dest
= 0, /* almost the DestBus */
291 temp
, /* ubiquitous third hand */
292 pc
= 0; /* the address of the current instruction */
293 ARMword lhs
, rhs
; /* almost the ABus and BBus */
294 ARMword decoded
= 0, loaded
= 0; /* instruction pipeline */
296 /***************************************************************************\
297 * Execute the next instruction *
298 \***************************************************************************/
300 if (state
->NextInstr
< PRIMEPIPE
)
302 decoded
= state
->decoded
;
303 loaded
= state
->loaded
;
308 { /* just keep going */
310 switch (state
->NextInstr
)
313 state
->Reg
[15] += isize
; /* Advance the pipeline, and an S cycle */
317 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
321 state
->Reg
[15] += isize
; /* Advance the pipeline, and an N cycle */
325 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
330 pc
+= isize
; /* Program counter advanced, and an S cycle */
333 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
338 pc
+= isize
; /* Program counter advanced, and an N cycle */
341 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
345 case RESUME
: /* The program counter has been changed */
350 state
->Reg
[15] = pc
+ (isize
* 2);
352 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
353 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
354 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
358 default: /* The program counter has been changed */
363 state
->Reg
[15] = pc
+ (isize
* 2);
365 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
366 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
367 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
372 ARMul_EnvokeEvent (state
);
375 /* Enable this for a helpful bit of debugging when tracing is needed. */
376 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
381 if (state
->Exception
)
382 { /* Any exceptions */
383 if (state
->NresetSig
== LOW
)
385 ARMul_Abort (state
, ARMul_ResetV
);
388 else if (!state
->NfiqSig
&& !FFLAG
)
390 ARMul_Abort (state
, ARMul_FIQV
);
393 else if (!state
->NirqSig
&& !IFLAG
)
395 ARMul_Abort (state
, ARMul_IRQV
);
400 if (state
->CallDebug
> 0)
402 instr
= ARMul_Debug (state
, pc
, instr
);
403 if (state
->Emulate
< ONCE
)
405 state
->NextInstr
= RESUME
;
410 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
412 (void) fgetc (stdin
);
415 else if (state
->Emulate
< ONCE
)
417 state
->NextInstr
= RESUME
;
424 /* Provide Thumb instruction decoding. If the processor is in Thumb
425 mode, then we can simply decode the Thumb instruction, and map it
426 to the corresponding ARM instruction (by directly loading the
427 instr variable, and letting the normal ARM simulator
428 execute). There are some caveats to ensure that the correct
429 pipelined PC value is used when executing Thumb code, and also for
430 dealing with the BL instruction. */
432 { /* check if in Thumb mode */
434 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
437 ARMul_UndefInstr (state
, instr
); /* This is a Thumb instruction */
440 case t_branch
: /* already processed */
443 case t_decoded
: /* ARM instruction available */
444 instr
= new; /* so continue instruction decoding */
450 /***************************************************************************\
451 * Check the condition codes *
452 \***************************************************************************/
453 if ((temp
= TOPBITS (28)) == AL
)
454 goto mainswitch
; /* vile deed in the need for speed */
456 switch ((int) TOPBITS (28))
457 { /* check the condition code */
464 if (BITS (25, 27) == 5) /* BLX(1) */
468 state
->Reg
[14] = pc
+ 4;
470 dest
= pc
+ 8 + 1; /* Force entry into Thumb mode. */
472 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
474 dest
+= POSBRANCH
+ (BIT (24) << 1);
476 WriteR15Branch (state
, dest
);
479 else if ((instr
& 0xFC70F000) == 0xF450F000)
480 /* The PLD instruction. Ignored. */
483 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
484 ARMul_UndefInstr (state
, instr
);
513 temp
= (CFLAG
&& !ZFLAG
);
516 temp
= (!CFLAG
|| ZFLAG
);
519 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
522 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
525 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
528 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
532 /* Handle the Clock counter here. */
533 if (state
->is_XScale
)
535 ARMword cp14r0
= state
->CPRead
[14] (state
, 0, 0);
537 if (cp14r0
&& ARMul_CP14_R0_ENABLE
)
539 unsigned long newcycles
, nowtime
= ARMul_Time(state
);
541 newcycles
= nowtime
- state
->LastTime
;
542 state
->LastTime
= nowtime
;
543 if (cp14r0
&& ARMul_CP14_R0_CCD
)
545 if (state
->CP14R0_CCD
== -1)
546 state
->CP14R0_CCD
= newcycles
;
548 state
->CP14R0_CCD
+= newcycles
;
549 if (state
->CP14R0_CCD
>= 64)
552 while (state
->CP14R0_CCD
>= 64)
553 state
->CP14R0_CCD
-= 64, newcycles
++;
562 state
->CP14R0_CCD
= -1;
564 cp14r0
|= ARMul_CP14_R0_FLAG2
;
565 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
567 cp14r1
= state
->CPRead
[14] (state
, 1, 0);
569 /* coded like this for portability */
572 if (cp14r1
== 0xffffffff)
581 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
582 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
584 if (state
->CPRead
[13] (state
, 8, 0)
585 && ARMul_CP13_R8_PMUS
)
586 ARMul_Abort (state
, ARMul_FIQV
);
588 ARMul_Abort (state
, ARMul_IRQV
);
594 /* Handle hardware instructions breakpoints here. */
595 if (state
->is_XScale
)
597 if ((pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
598 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
600 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
601 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
605 /***************************************************************************\
606 * Actual execution of instructions begins here *
607 \***************************************************************************/
610 { /* if the condition codes don't match, stop here */
613 if (state
->is_XScale
)
615 if (BIT (20) == 0 && BITS (25, 27) == 0)
617 if (BITS (4, 7) == 0xD)
619 /* XScale Load Consecutive insn. */
620 ARMword temp
= GetLS7RHS (state
, instr
);
621 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
622 ARMword addr
= BIT (24) ? temp2
: temp
;
625 ARMul_UndefInstr (state
, instr
);
627 /* Alignment violation. */
628 ARMul_Abort (state
, ARMul_DataAbortV
);
631 int wb
= BIT (24) && BIT (21);
633 state
->Reg
[BITS (12, 15)] =
634 ARMul_LoadWordN (state
, addr
);
635 state
->Reg
[BITS (12, 15) + 1] =
636 ARMul_LoadWordN (state
, addr
+ 4);
643 else if (BITS (4, 7) == 0xF)
645 /* XScale Store Consecutive insn. */
646 ARMword temp
= GetLS7RHS (state
, instr
);
647 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
648 ARMword addr
= BIT (24) ? temp2
: temp
;
651 ARMul_UndefInstr (state
, instr
);
653 /* Alignment violation. */
654 ARMul_Abort (state
, ARMul_DataAbortV
);
657 ARMul_StoreWordN (state
, addr
,
658 state
->Reg
[BITS (12, 15)]);
659 ARMul_StoreWordN (state
, addr
+ 4,
660 state
->Reg
[BITS (12, 15) + 1]);
671 switch ((int) BITS (20, 27))
674 /***************************************************************************\
675 * Data Processing Register RHS Instructions *
676 \***************************************************************************/
678 case 0x00: /* AND reg and MUL */
680 if (BITS (4, 11) == 0xB)
682 /* STRH register offset, no write-back, down, post indexed */
686 if (BITS (4, 7) == 0xD)
688 Handle_Load_Double (state
, instr
);
691 if (BITS (4, 7) == 0xF)
693 Handle_Store_Double (state
, instr
);
697 if (BITS (4, 7) == 9)
699 rhs
= state
->Reg
[MULRHSReg
];
700 if (MULLHSReg
== MULDESTReg
)
703 state
->Reg
[MULDESTReg
] = 0;
705 else if (MULDESTReg
!= 15)
706 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
711 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
712 if (rhs
& (1L << dest
))
713 temp
= dest
; /* mult takes this many/2 I cycles */
714 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
724 case 0x01: /* ANDS reg and MULS */
726 if ((BITS (4, 11) & 0xF9) == 0x9)
728 /* LDR register offset, no write-back, down, post indexed */
730 /* fall through to rest of decoding */
733 if (BITS (4, 7) == 9)
735 rhs
= state
->Reg
[MULRHSReg
];
736 if (MULLHSReg
== MULDESTReg
)
739 state
->Reg
[MULDESTReg
] = 0;
743 else if (MULDESTReg
!= 15)
745 dest
= state
->Reg
[MULLHSReg
] * rhs
;
746 ARMul_NegZero (state
, dest
);
747 state
->Reg
[MULDESTReg
] = dest
;
753 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
754 if (rhs
& (1L << dest
))
755 temp
= dest
; /* mult takes this many/2 I cycles */
756 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
766 case 0x02: /* EOR reg and MLA */
768 if (BITS (4, 11) == 0xB)
770 /* STRH register offset, write-back, down, post indexed */
775 if (BITS (4, 7) == 9)
777 rhs
= state
->Reg
[MULRHSReg
];
778 if (MULLHSReg
== MULDESTReg
)
781 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
783 else if (MULDESTReg
!= 15)
784 state
->Reg
[MULDESTReg
] =
785 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
790 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
791 if (rhs
& (1L << dest
))
792 temp
= dest
; /* mult takes this many/2 I cycles */
793 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
803 case 0x03: /* EORS reg and MLAS */
805 if ((BITS (4, 11) & 0xF9) == 0x9)
807 /* LDR register offset, write-back, down, post-indexed */
809 /* fall through to rest of the decoding */
812 if (BITS (4, 7) == 9)
814 rhs
= state
->Reg
[MULRHSReg
];
815 if (MULLHSReg
== MULDESTReg
)
818 dest
= state
->Reg
[MULACCReg
];
819 ARMul_NegZero (state
, dest
);
820 state
->Reg
[MULDESTReg
] = dest
;
822 else if (MULDESTReg
!= 15)
825 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
826 ARMul_NegZero (state
, dest
);
827 state
->Reg
[MULDESTReg
] = dest
;
833 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
834 if (rhs
& (1L << dest
))
835 temp
= dest
; /* mult takes this many/2 I cycles */
836 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
846 case 0x04: /* SUB reg */
848 if (BITS (4, 7) == 0xB)
850 /* STRH immediate offset, no write-back, down, post indexed */
854 if (BITS (4, 7) == 0xD)
856 Handle_Load_Double (state
, instr
);
859 if (BITS (4, 7) == 0xF)
861 Handle_Store_Double (state
, instr
);
870 case 0x05: /* SUBS reg */
872 if ((BITS (4, 7) & 0x9) == 0x9)
874 /* LDR immediate offset, no write-back, down, post indexed */
876 /* fall through to the rest of the instruction decoding */
882 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
884 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
885 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
895 case 0x06: /* RSB reg */
897 if (BITS (4, 7) == 0xB)
899 /* STRH immediate offset, write-back, down, post indexed */
909 case 0x07: /* RSBS reg */
911 if ((BITS (4, 7) & 0x9) == 0x9)
913 /* LDR immediate offset, write-back, down, post indexed */
915 /* fall through to remainder of instruction decoding */
921 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
923 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
924 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
934 case 0x08: /* ADD reg */
936 if (BITS (4, 11) == 0xB)
938 /* STRH register offset, no write-back, up, post indexed */
942 if (BITS (4, 7) == 0xD)
944 Handle_Load_Double (state
, instr
);
947 if (BITS (4, 7) == 0xF)
949 Handle_Store_Double (state
, instr
);
954 if (BITS (4, 7) == 0x9)
957 ARMul_Icycles (state
,
958 Multiply64 (state
, instr
, LUNSIGNED
,
968 case 0x09: /* ADDS reg */
970 if ((BITS (4, 11) & 0xF9) == 0x9)
972 /* LDR register offset, no write-back, up, post indexed */
974 /* fall through to remaining instruction decoding */
978 if (BITS (4, 7) == 0x9)
981 ARMul_Icycles (state
,
982 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
991 if ((lhs
| rhs
) >> 30)
992 { /* possible C,V,N to set */
993 ASSIGNN (NEG (dest
));
994 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
995 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1006 case 0x0a: /* ADC reg */
1008 if (BITS (4, 11) == 0xB)
1010 /* STRH register offset, write-back, up, post-indexed */
1016 if (BITS (4, 7) == 0x9)
1019 ARMul_Icycles (state
,
1020 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1026 dest
= LHS
+ rhs
+ CFLAG
;
1030 case 0x0b: /* ADCS reg */
1032 if ((BITS (4, 11) & 0xF9) == 0x9)
1034 /* LDR register offset, write-back, up, post indexed */
1036 /* fall through to remaining instruction decoding */
1040 if (BITS (4, 7) == 0x9)
1043 ARMul_Icycles (state
,
1044 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1051 dest
= lhs
+ rhs
+ CFLAG
;
1052 ASSIGNZ (dest
== 0);
1053 if ((lhs
| rhs
) >> 30)
1054 { /* possible C,V,N to set */
1055 ASSIGNN (NEG (dest
));
1056 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1057 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1068 case 0x0c: /* SBC reg */
1070 if (BITS (4, 7) == 0xB)
1072 /* STRH immediate offset, no write-back, up post indexed */
1076 if (BITS (4, 7) == 0xD)
1078 Handle_Load_Double (state
, instr
);
1081 if (BITS (4, 7) == 0xF)
1083 Handle_Store_Double (state
, instr
);
1088 if (BITS (4, 7) == 0x9)
1091 ARMul_Icycles (state
,
1092 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
1098 dest
= LHS
- rhs
- !CFLAG
;
1102 case 0x0d: /* SBCS reg */
1104 if ((BITS (4, 7) & 0x9) == 0x9)
1106 /* LDR immediate offset, no write-back, up, post indexed */
1111 if (BITS (4, 7) == 0x9)
1114 ARMul_Icycles (state
,
1115 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
1122 dest
= lhs
- rhs
- !CFLAG
;
1123 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1125 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1126 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1136 case 0x0e: /* RSC reg */
1138 if (BITS (4, 7) == 0xB)
1140 /* STRH immediate offset, write-back, up, post indexed */
1146 if (BITS (4, 7) == 0x9)
1149 ARMul_Icycles (state
,
1150 MultiplyAdd64 (state
, instr
, LSIGNED
,
1156 dest
= rhs
- LHS
- !CFLAG
;
1160 case 0x0f: /* RSCS reg */
1162 if ((BITS (4, 7) & 0x9) == 0x9)
1164 /* LDR immediate offset, write-back, up, post indexed */
1166 /* fall through to remaining instruction decoding */
1170 if (BITS (4, 7) == 0x9)
1173 ARMul_Icycles (state
,
1174 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
1181 dest
= rhs
- lhs
- !CFLAG
;
1182 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1184 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1185 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1195 case 0x10: /* TST reg and MRS CPSR and SWP word */
1198 if (BIT (4) == 0 && BIT (7) == 1)
1200 /* ElSegundo SMLAxy insn. */
1201 ARMword op1
= state
->Reg
[BITS (0, 3)];
1202 ARMword op2
= state
->Reg
[BITS (8, 11)];
1203 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1217 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
1219 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
1223 if (BITS (4, 11) == 5)
1225 /* ElSegundo QADD insn. */
1226 ARMword op1
= state
->Reg
[BITS (0, 3)];
1227 ARMword op2
= state
->Reg
[BITS (16, 19)];
1228 ARMword result
= op1
+ op2
;
1229 if (AddOverflow (op1
, op2
, result
))
1231 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1234 state
->Reg
[BITS (12, 15)] = result
;
1239 if (BITS (4, 11) == 0xB)
1241 /* STRH register offset, no write-back, down, pre indexed */
1245 if (BITS (4, 7) == 0xD)
1247 Handle_Load_Double (state
, instr
);
1250 if (BITS (4, 7) == 0xF)
1252 Handle_Store_Double (state
, instr
);
1256 if (BITS (4, 11) == 9)
1262 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1264 INTERNALABORT (temp
);
1265 (void) ARMul_LoadWordN (state
, temp
);
1266 (void) ARMul_LoadWordN (state
, temp
);
1270 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1272 DEST
= ARMul_Align (state
, temp
, dest
);
1275 if (state
->abortSig
|| state
->Aborted
)
1280 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1283 DEST
= ECC
| EINT
| EMODE
;
1291 case 0x11: /* TSTP reg */
1293 if ((BITS (4, 11) & 0xF9) == 0x9)
1295 /* LDR register offset, no write-back, down, pre indexed */
1297 /* continue with remaining instruction decode */
1303 state
->Cpsr
= GETSPSR (state
->Bank
);
1304 ARMul_CPSRAltered (state
);
1315 ARMul_NegZero (state
, dest
);
1319 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6) */
1322 if (BITS (4, 7) == 3)
1328 temp
= (pc
+ 2) | 1;
1332 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1333 state
->Reg
[14] = temp
;
1340 if (BIT (4) == 0 && BIT (7) == 1
1341 && (BIT (5) == 0 || BITS (12, 15) == 0))
1343 /* ElSegundo SMLAWy/SMULWy insn. */
1344 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1345 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1346 unsigned long long result
;
1350 if (op1
& 0x80000000)
1355 result
= (op1
* op2
) >> 16;
1359 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1361 if (AddOverflow (result
, Rn
, result
+ Rn
))
1365 state
->Reg
[BITS (16, 19)] = result
;
1369 if (BITS (4, 11) == 5)
1371 /* ElSegundo QSUB insn. */
1372 ARMword op1
= state
->Reg
[BITS (0, 3)];
1373 ARMword op2
= state
->Reg
[BITS (16, 19)];
1374 ARMword result
= op1
- op2
;
1376 if (SubOverflow (op1
, op2
, result
))
1378 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1382 state
->Reg
[BITS (12, 15)] = result
;
1387 if (BITS (4, 11) == 0xB)
1389 /* STRH register offset, write-back, down, pre indexed */
1393 if (BITS (4, 27) == 0x12FFF1)
1396 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1399 if (BITS (4, 7) == 0xD)
1401 Handle_Load_Double (state
, instr
);
1404 if (BITS (4, 7) == 0xF)
1406 Handle_Store_Double (state
, instr
);
1412 if (BITS (4, 7) == 0x7)
1415 extern int SWI_vector_installed
;
1417 /* Hardware is allowed to optionally override this
1418 instruction and treat it as a breakpoint. Since
1419 this is a simulator not hardware, we take the position
1420 that if a SWI vector was not installed, then an Abort
1421 vector was probably not installed either, and so
1422 normally this instruction would be ignored, even if an
1423 Abort is generated. This is a bad thing, since GDB
1424 uses this instruction for its breakpoints (at least in
1425 Thumb mode it does). So intercept the instruction here
1426 and generate a breakpoint SWI instead. */
1427 if (! SWI_vector_installed
)
1428 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1431 /* BKPT - normally this will cause an abort, but on the
1432 XScale we must check the DCSR. */
1433 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
1434 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
1438 /* Force the next instruction to be refetched. */
1439 state
->NextInstr
= RESUME
;
1445 /* MSR reg to CPSR */
1449 /* Don't allow TBIT to be set by MSR. */
1452 ARMul_FixCPSR (state
, instr
, temp
);
1460 case 0x13: /* TEQP reg */
1462 if ((BITS (4, 11) & 0xF9) == 0x9)
1464 /* LDR register offset, write-back, down, pre indexed */
1466 /* continue with remaining instruction decode */
1472 state
->Cpsr
= GETSPSR (state
->Bank
);
1473 ARMul_CPSRAltered (state
);
1484 ARMul_NegZero (state
, dest
);
1488 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1491 if (BIT (4) == 0 && BIT (7) == 1)
1493 /* ElSegundo SMLALxy insn. */
1494 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1495 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1496 unsigned long long dest
;
1497 unsigned long long result
;
1510 dest
= (unsigned long long) state
->Reg
[BITS (16, 19)] << 32;
1511 dest
|= state
->Reg
[BITS (12, 15)];
1513 state
->Reg
[BITS (12, 15)] = dest
;
1514 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1518 if (BITS (4, 11) == 5)
1520 /* ElSegundo QDADD insn. */
1521 ARMword op1
= state
->Reg
[BITS (0, 3)];
1522 ARMword op2
= state
->Reg
[BITS (16, 19)];
1523 ARMword op2d
= op2
+ op2
;
1526 if (AddOverflow (op2
, op2
, op2d
))
1529 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1532 result
= op1
+ op2d
;
1533 if (AddOverflow (op1
, op2d
, result
))
1536 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1539 state
->Reg
[BITS (12, 15)] = result
;
1544 if (BITS (4, 7) == 0xB)
1546 /* STRH immediate offset, no write-back, down, pre indexed */
1550 if (BITS (4, 7) == 0xD)
1552 Handle_Load_Double (state
, instr
);
1555 if (BITS (4, 7) == 0xF)
1557 Handle_Store_Double (state
, instr
);
1561 if (BITS (4, 11) == 9)
1567 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1569 INTERNALABORT (temp
);
1570 (void) ARMul_LoadByte (state
, temp
);
1571 (void) ARMul_LoadByte (state
, temp
);
1575 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1576 if (state
->abortSig
|| state
->Aborted
)
1581 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1584 DEST
= GETSPSR (state
->Bank
);
1592 case 0x15: /* CMPP reg */
1594 if ((BITS (4, 7) & 0x9) == 0x9)
1596 /* LDR immediate offset, no write-back, down, pre indexed */
1598 /* continue with remaining instruction decode */
1604 state
->Cpsr
= GETSPSR (state
->Bank
);
1605 ARMul_CPSRAltered (state
);
1617 ARMul_NegZero (state
, dest
);
1618 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1620 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1621 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1631 case 0x16: /* CMN reg and MSR reg to SPSR */
1634 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1636 /* ElSegundo SMULxy insn. */
1637 ARMword op1
= state
->Reg
[BITS (0, 3)];
1638 ARMword op2
= state
->Reg
[BITS (8, 11)];
1639 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1652 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1656 if (BITS (4, 11) == 5)
1658 /* ElSegundo QDSUB insn. */
1659 ARMword op1
= state
->Reg
[BITS (0, 3)];
1660 ARMword op2
= state
->Reg
[BITS (16, 19)];
1661 ARMword op2d
= op2
+ op2
;
1664 if (AddOverflow (op2
, op2
, op2d
))
1667 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1670 result
= op1
- op2d
;
1671 if (SubOverflow (op1
, op2d
, result
))
1674 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1677 state
->Reg
[BITS (12, 15)] = result
;
1684 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1686 /* ARM5 CLZ insn. */
1687 ARMword op1
= state
->Reg
[BITS (0, 3)];
1691 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1694 state
->Reg
[BITS (12, 15)] = result
;
1699 if (BITS (4, 7) == 0xB)
1701 /* STRH immediate offset, write-back, down, pre indexed */
1705 if (BITS (4, 7) == 0xD)
1707 Handle_Load_Double (state
, instr
);
1710 if (BITS (4, 7) == 0xF)
1712 Handle_Store_Double (state
, instr
);
1719 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1727 case 0x17: /* CMNP reg */
1729 if ((BITS (4, 7) & 0x9) == 0x9)
1731 /* LDR immediate offset, write-back, down, pre indexed */
1733 /* continue with remaining instruction decoding */
1739 state
->Cpsr
= GETSPSR (state
->Bank
);
1740 ARMul_CPSRAltered (state
);
1753 ASSIGNZ (dest
== 0);
1754 if ((lhs
| rhs
) >> 30)
1755 { /* possible C,V,N to set */
1756 ASSIGNN (NEG (dest
));
1757 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1758 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1769 case 0x18: /* ORR reg */
1771 if (BITS (4, 11) == 0xB)
1773 /* STRH register offset, no write-back, up, pre indexed */
1777 if (BITS (4, 7) == 0xD)
1779 Handle_Load_Double (state
, instr
);
1782 if (BITS (4, 7) == 0xF)
1784 Handle_Store_Double (state
, instr
);
1793 case 0x19: /* ORRS reg */
1795 if ((BITS (4, 11) & 0xF9) == 0x9)
1797 /* LDR register offset, no write-back, up, pre indexed */
1799 /* continue with remaining instruction decoding */
1807 case 0x1a: /* MOV reg */
1809 if (BITS (4, 11) == 0xB)
1811 /* STRH register offset, write-back, up, pre indexed */
1815 if (BITS (4, 7) == 0xD)
1817 Handle_Load_Double (state
, instr
);
1820 if (BITS (4, 7) == 0xF)
1822 Handle_Store_Double (state
, instr
);
1830 case 0x1b: /* MOVS reg */
1832 if ((BITS (4, 11) & 0xF9) == 0x9)
1834 /* LDR register offset, write-back, up, pre indexed */
1836 /* continue with remaining instruction decoding */
1843 case 0x1c: /* BIC reg */
1845 if (BITS (4, 7) == 0xB)
1847 /* STRH immediate offset, no write-back, up, pre indexed */
1851 if (BITS (4, 7) == 0xD)
1853 Handle_Load_Double (state
, instr
);
1856 else if (BITS (4, 7) == 0xF)
1858 Handle_Store_Double (state
, instr
);
1867 case 0x1d: /* BICS reg */
1869 if ((BITS (4, 7) & 0x9) == 0x9)
1871 /* LDR immediate offset, no write-back, up, pre indexed */
1873 /* continue with instruction decoding */
1881 case 0x1e: /* MVN reg */
1883 if (BITS (4, 7) == 0xB)
1885 /* STRH immediate offset, write-back, up, pre indexed */
1889 if (BITS (4, 7) == 0xD)
1891 Handle_Load_Double (state
, instr
);
1894 if (BITS (4, 7) == 0xF)
1896 Handle_Store_Double (state
, instr
);
1904 case 0x1f: /* MVNS reg */
1906 if ((BITS (4, 7) & 0x9) == 0x9)
1908 /* LDR immediate offset, write-back, up, pre indexed */
1910 /* continue instruction decoding */
1917 /***************************************************************************\
1918 * Data Processing Immediate RHS Instructions *
1919 \***************************************************************************/
1921 case 0x20: /* AND immed */
1922 dest
= LHS
& DPImmRHS
;
1926 case 0x21: /* ANDS immed */
1932 case 0x22: /* EOR immed */
1933 dest
= LHS
^ DPImmRHS
;
1937 case 0x23: /* EORS immed */
1943 case 0x24: /* SUB immed */
1944 dest
= LHS
- DPImmRHS
;
1948 case 0x25: /* SUBS immed */
1952 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1954 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1955 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1965 case 0x26: /* RSB immed */
1966 dest
= DPImmRHS
- LHS
;
1970 case 0x27: /* RSBS immed */
1974 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1976 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1977 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1987 case 0x28: /* ADD immed */
1988 dest
= LHS
+ DPImmRHS
;
1992 case 0x29: /* ADDS immed */
1996 ASSIGNZ (dest
== 0);
1997 if ((lhs
| rhs
) >> 30)
1998 { /* possible C,V,N to set */
1999 ASSIGNN (NEG (dest
));
2000 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2001 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2012 case 0x2a: /* ADC immed */
2013 dest
= LHS
+ DPImmRHS
+ CFLAG
;
2017 case 0x2b: /* ADCS immed */
2020 dest
= lhs
+ rhs
+ CFLAG
;
2021 ASSIGNZ (dest
== 0);
2022 if ((lhs
| rhs
) >> 30)
2023 { /* possible C,V,N to set */
2024 ASSIGNN (NEG (dest
));
2025 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2026 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2037 case 0x2c: /* SBC immed */
2038 dest
= LHS
- DPImmRHS
- !CFLAG
;
2042 case 0x2d: /* SBCS immed */
2045 dest
= lhs
- rhs
- !CFLAG
;
2046 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2048 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2049 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2059 case 0x2e: /* RSC immed */
2060 dest
= DPImmRHS
- LHS
- !CFLAG
;
2064 case 0x2f: /* RSCS immed */
2067 dest
= rhs
- lhs
- !CFLAG
;
2068 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2070 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2071 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2081 case 0x30: /* TST immed */
2085 case 0x31: /* TSTP immed */
2089 state
->Cpsr
= GETSPSR (state
->Bank
);
2090 ARMul_CPSRAltered (state
);
2092 temp
= LHS
& DPImmRHS
;
2098 DPSImmRHS
; /* TST immed */
2100 ARMul_NegZero (state
, dest
);
2104 case 0x32: /* TEQ immed and MSR immed to CPSR */
2106 { /* MSR immed to CPSR */
2107 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2115 case 0x33: /* TEQP immed */
2119 state
->Cpsr
= GETSPSR (state
->Bank
);
2120 ARMul_CPSRAltered (state
);
2122 temp
= LHS
^ DPImmRHS
;
2128 DPSImmRHS
; /* TEQ immed */
2130 ARMul_NegZero (state
, dest
);
2134 case 0x34: /* CMP immed */
2138 case 0x35: /* CMPP immed */
2142 state
->Cpsr
= GETSPSR (state
->Bank
);
2143 ARMul_CPSRAltered (state
);
2145 temp
= LHS
- DPImmRHS
;
2152 lhs
= LHS
; /* CMP immed */
2155 ARMul_NegZero (state
, dest
);
2156 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2158 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2159 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2169 case 0x36: /* CMN immed and MSR immed to SPSR */
2170 if (DESTReg
== 15) /* MSR */
2171 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2178 case 0x37: /* CMNP immed */
2182 state
->Cpsr
= GETSPSR (state
->Bank
);
2183 ARMul_CPSRAltered (state
);
2185 temp
= LHS
+ DPImmRHS
;
2192 lhs
= LHS
; /* CMN immed */
2195 ASSIGNZ (dest
== 0);
2196 if ((lhs
| rhs
) >> 30)
2197 { /* possible C,V,N to set */
2198 ASSIGNN (NEG (dest
));
2199 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2200 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2211 case 0x38: /* ORR immed */
2212 dest
= LHS
| DPImmRHS
;
2216 case 0x39: /* ORRS immed */
2222 case 0x3a: /* MOV immed */
2227 case 0x3b: /* MOVS immed */
2232 case 0x3c: /* BIC immed */
2233 dest
= LHS
& ~DPImmRHS
;
2237 case 0x3d: /* BICS immed */
2243 case 0x3e: /* MVN immed */
2248 case 0x3f: /* MVNS immed */
2253 /***************************************************************************\
2254 * Single Data Transfer Immediate RHS Instructions *
2255 \***************************************************************************/
2257 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
2259 if (StoreWord (state
, instr
, lhs
))
2260 LSBase
= lhs
- LSImmRHS
;
2263 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
2265 if (LoadWord (state
, instr
, lhs
))
2266 LSBase
= lhs
- LSImmRHS
;
2269 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
2270 UNDEF_LSRBaseEQDestWb
;
2273 temp
= lhs
- LSImmRHS
;
2274 state
->NtransSig
= LOW
;
2275 if (StoreWord (state
, instr
, lhs
))
2277 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2280 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
2281 UNDEF_LSRBaseEQDestWb
;
2284 state
->NtransSig
= LOW
;
2285 if (LoadWord (state
, instr
, lhs
))
2286 LSBase
= lhs
- LSImmRHS
;
2287 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2290 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
2292 if (StoreByte (state
, instr
, lhs
))
2293 LSBase
= lhs
- LSImmRHS
;
2296 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
2298 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2299 LSBase
= lhs
- LSImmRHS
;
2302 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
2303 UNDEF_LSRBaseEQDestWb
;
2306 state
->NtransSig
= LOW
;
2307 if (StoreByte (state
, instr
, lhs
))
2308 LSBase
= lhs
- LSImmRHS
;
2309 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2312 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
2313 UNDEF_LSRBaseEQDestWb
;
2316 state
->NtransSig
= LOW
;
2317 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2318 LSBase
= lhs
- LSImmRHS
;
2319 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2322 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
2324 if (StoreWord (state
, instr
, lhs
))
2325 LSBase
= lhs
+ LSImmRHS
;
2328 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
2330 if (LoadWord (state
, instr
, lhs
))
2331 LSBase
= lhs
+ LSImmRHS
;
2334 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
2335 UNDEF_LSRBaseEQDestWb
;
2338 state
->NtransSig
= LOW
;
2339 if (StoreWord (state
, instr
, lhs
))
2340 LSBase
= lhs
+ LSImmRHS
;
2341 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2344 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
2345 UNDEF_LSRBaseEQDestWb
;
2348 state
->NtransSig
= LOW
;
2349 if (LoadWord (state
, instr
, lhs
))
2350 LSBase
= lhs
+ LSImmRHS
;
2351 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2354 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
2356 if (StoreByte (state
, instr
, lhs
))
2357 LSBase
= lhs
+ LSImmRHS
;
2360 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
2362 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2363 LSBase
= lhs
+ LSImmRHS
;
2366 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
2367 UNDEF_LSRBaseEQDestWb
;
2370 state
->NtransSig
= LOW
;
2371 if (StoreByte (state
, instr
, lhs
))
2372 LSBase
= lhs
+ LSImmRHS
;
2373 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2376 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
2377 UNDEF_LSRBaseEQDestWb
;
2380 state
->NtransSig
= LOW
;
2381 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2382 LSBase
= lhs
+ LSImmRHS
;
2383 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2387 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
2388 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2391 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
2392 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2395 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
2396 UNDEF_LSRBaseEQDestWb
;
2398 temp
= LHS
- LSImmRHS
;
2399 if (StoreWord (state
, instr
, temp
))
2403 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
2404 UNDEF_LSRBaseEQDestWb
;
2406 temp
= LHS
- LSImmRHS
;
2407 if (LoadWord (state
, instr
, temp
))
2411 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
2412 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2415 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
2416 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2419 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
2420 UNDEF_LSRBaseEQDestWb
;
2422 temp
= LHS
- LSImmRHS
;
2423 if (StoreByte (state
, instr
, temp
))
2427 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
2428 UNDEF_LSRBaseEQDestWb
;
2430 temp
= LHS
- LSImmRHS
;
2431 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2435 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
2436 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2439 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
2440 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2443 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
2444 UNDEF_LSRBaseEQDestWb
;
2446 temp
= LHS
+ LSImmRHS
;
2447 if (StoreWord (state
, instr
, temp
))
2451 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
2452 UNDEF_LSRBaseEQDestWb
;
2454 temp
= LHS
+ LSImmRHS
;
2455 if (LoadWord (state
, instr
, temp
))
2459 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
2460 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2463 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
2464 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2467 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
2468 UNDEF_LSRBaseEQDestWb
;
2470 temp
= LHS
+ LSImmRHS
;
2471 if (StoreByte (state
, instr
, temp
))
2475 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
2476 UNDEF_LSRBaseEQDestWb
;
2478 temp
= LHS
+ LSImmRHS
;
2479 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2483 /***************************************************************************\
2484 * Single Data Transfer Register RHS Instructions *
2485 \***************************************************************************/
2487 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
2490 ARMul_UndefInstr (state
, instr
);
2493 UNDEF_LSRBaseEQOffWb
;
2494 UNDEF_LSRBaseEQDestWb
;
2498 if (StoreWord (state
, instr
, lhs
))
2499 LSBase
= lhs
- LSRegRHS
;
2502 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
2505 ARMul_UndefInstr (state
, instr
);
2508 UNDEF_LSRBaseEQOffWb
;
2509 UNDEF_LSRBaseEQDestWb
;
2513 temp
= lhs
- LSRegRHS
;
2514 if (LoadWord (state
, instr
, lhs
))
2518 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2521 ARMul_UndefInstr (state
, instr
);
2524 UNDEF_LSRBaseEQOffWb
;
2525 UNDEF_LSRBaseEQDestWb
;
2529 state
->NtransSig
= LOW
;
2530 if (StoreWord (state
, instr
, lhs
))
2531 LSBase
= lhs
- LSRegRHS
;
2532 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2535 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2538 ARMul_UndefInstr (state
, instr
);
2541 UNDEF_LSRBaseEQOffWb
;
2542 UNDEF_LSRBaseEQDestWb
;
2546 temp
= lhs
- LSRegRHS
;
2547 state
->NtransSig
= LOW
;
2548 if (LoadWord (state
, instr
, lhs
))
2550 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2553 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2556 ARMul_UndefInstr (state
, instr
);
2559 UNDEF_LSRBaseEQOffWb
;
2560 UNDEF_LSRBaseEQDestWb
;
2564 if (StoreByte (state
, instr
, lhs
))
2565 LSBase
= lhs
- LSRegRHS
;
2568 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2571 ARMul_UndefInstr (state
, instr
);
2574 UNDEF_LSRBaseEQOffWb
;
2575 UNDEF_LSRBaseEQDestWb
;
2579 temp
= lhs
- LSRegRHS
;
2580 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2584 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2587 ARMul_UndefInstr (state
, instr
);
2590 UNDEF_LSRBaseEQOffWb
;
2591 UNDEF_LSRBaseEQDestWb
;
2595 state
->NtransSig
= LOW
;
2596 if (StoreByte (state
, instr
, lhs
))
2597 LSBase
= lhs
- LSRegRHS
;
2598 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2601 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2604 ARMul_UndefInstr (state
, instr
);
2607 UNDEF_LSRBaseEQOffWb
;
2608 UNDEF_LSRBaseEQDestWb
;
2612 temp
= lhs
- LSRegRHS
;
2613 state
->NtransSig
= LOW
;
2614 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2616 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2619 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2622 ARMul_UndefInstr (state
, instr
);
2625 UNDEF_LSRBaseEQOffWb
;
2626 UNDEF_LSRBaseEQDestWb
;
2630 if (StoreWord (state
, instr
, lhs
))
2631 LSBase
= lhs
+ LSRegRHS
;
2634 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2637 ARMul_UndefInstr (state
, instr
);
2640 UNDEF_LSRBaseEQOffWb
;
2641 UNDEF_LSRBaseEQDestWb
;
2645 temp
= lhs
+ LSRegRHS
;
2646 if (LoadWord (state
, instr
, lhs
))
2650 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2653 ARMul_UndefInstr (state
, instr
);
2656 UNDEF_LSRBaseEQOffWb
;
2657 UNDEF_LSRBaseEQDestWb
;
2661 state
->NtransSig
= LOW
;
2662 if (StoreWord (state
, instr
, lhs
))
2663 LSBase
= lhs
+ LSRegRHS
;
2664 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2667 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2670 ARMul_UndefInstr (state
, instr
);
2673 UNDEF_LSRBaseEQOffWb
;
2674 UNDEF_LSRBaseEQDestWb
;
2678 temp
= lhs
+ LSRegRHS
;
2679 state
->NtransSig
= LOW
;
2680 if (LoadWord (state
, instr
, lhs
))
2682 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2685 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2688 ARMul_UndefInstr (state
, instr
);
2691 UNDEF_LSRBaseEQOffWb
;
2692 UNDEF_LSRBaseEQDestWb
;
2696 if (StoreByte (state
, instr
, lhs
))
2697 LSBase
= lhs
+ LSRegRHS
;
2700 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2703 ARMul_UndefInstr (state
, instr
);
2706 UNDEF_LSRBaseEQOffWb
;
2707 UNDEF_LSRBaseEQDestWb
;
2711 temp
= lhs
+ LSRegRHS
;
2712 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2716 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2719 ARMul_UndefInstr (state
, instr
);
2722 UNDEF_LSRBaseEQOffWb
;
2723 UNDEF_LSRBaseEQDestWb
;
2727 state
->NtransSig
= LOW
;
2728 if (StoreByte (state
, instr
, lhs
))
2729 LSBase
= lhs
+ LSRegRHS
;
2730 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2733 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2736 ARMul_UndefInstr (state
, instr
);
2739 UNDEF_LSRBaseEQOffWb
;
2740 UNDEF_LSRBaseEQDestWb
;
2744 temp
= lhs
+ LSRegRHS
;
2745 state
->NtransSig
= LOW
;
2746 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2748 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2752 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2755 ARMul_UndefInstr (state
, instr
);
2758 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2761 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2764 ARMul_UndefInstr (state
, instr
);
2767 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2770 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2773 ARMul_UndefInstr (state
, instr
);
2776 UNDEF_LSRBaseEQOffWb
;
2777 UNDEF_LSRBaseEQDestWb
;
2780 temp
= LHS
- LSRegRHS
;
2781 if (StoreWord (state
, instr
, temp
))
2785 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2788 ARMul_UndefInstr (state
, instr
);
2791 UNDEF_LSRBaseEQOffWb
;
2792 UNDEF_LSRBaseEQDestWb
;
2795 temp
= LHS
- LSRegRHS
;
2796 if (LoadWord (state
, instr
, temp
))
2800 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2803 ARMul_UndefInstr (state
, instr
);
2806 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2809 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2812 ARMul_UndefInstr (state
, instr
);
2815 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2818 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2821 ARMul_UndefInstr (state
, instr
);
2824 UNDEF_LSRBaseEQOffWb
;
2825 UNDEF_LSRBaseEQDestWb
;
2828 temp
= LHS
- LSRegRHS
;
2829 if (StoreByte (state
, instr
, temp
))
2833 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2836 ARMul_UndefInstr (state
, instr
);
2839 UNDEF_LSRBaseEQOffWb
;
2840 UNDEF_LSRBaseEQDestWb
;
2843 temp
= LHS
- LSRegRHS
;
2844 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2848 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2851 ARMul_UndefInstr (state
, instr
);
2854 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2857 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2860 ARMul_UndefInstr (state
, instr
);
2863 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2866 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2869 ARMul_UndefInstr (state
, instr
);
2872 UNDEF_LSRBaseEQOffWb
;
2873 UNDEF_LSRBaseEQDestWb
;
2876 temp
= LHS
+ LSRegRHS
;
2877 if (StoreWord (state
, instr
, temp
))
2881 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2884 ARMul_UndefInstr (state
, instr
);
2887 UNDEF_LSRBaseEQOffWb
;
2888 UNDEF_LSRBaseEQDestWb
;
2891 temp
= LHS
+ LSRegRHS
;
2892 if (LoadWord (state
, instr
, temp
))
2896 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2899 ARMul_UndefInstr (state
, instr
);
2902 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2905 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2908 ARMul_UndefInstr (state
, instr
);
2911 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2914 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2917 ARMul_UndefInstr (state
, instr
);
2920 UNDEF_LSRBaseEQOffWb
;
2921 UNDEF_LSRBaseEQDestWb
;
2924 temp
= LHS
+ LSRegRHS
;
2925 if (StoreByte (state
, instr
, temp
))
2929 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2932 /* Check for the special breakpoint opcode.
2933 This value should correspond to the value defined
2934 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2935 if (BITS (0, 19) == 0xfdefe)
2937 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2938 ARMul_Abort (state
, ARMul_SWIV
);
2941 ARMul_UndefInstr (state
, instr
);
2944 UNDEF_LSRBaseEQOffWb
;
2945 UNDEF_LSRBaseEQDestWb
;
2948 temp
= LHS
+ LSRegRHS
;
2949 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2953 /***************************************************************************\
2954 * Multiple Data Transfer Instructions *
2955 \***************************************************************************/
2957 case 0x80: /* Store, No WriteBack, Post Dec */
2958 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2961 case 0x81: /* Load, No WriteBack, Post Dec */
2962 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2965 case 0x82: /* Store, WriteBack, Post Dec */
2966 temp
= LSBase
- LSMNumRegs
;
2967 STOREMULT (instr
, temp
+ 4L, temp
);
2970 case 0x83: /* Load, WriteBack, Post Dec */
2971 temp
= LSBase
- LSMNumRegs
;
2972 LOADMULT (instr
, temp
+ 4L, temp
);
2975 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2976 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2979 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2980 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2983 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2984 temp
= LSBase
- LSMNumRegs
;
2985 STORESMULT (instr
, temp
+ 4L, temp
);
2988 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2989 temp
= LSBase
- LSMNumRegs
;
2990 LOADSMULT (instr
, temp
+ 4L, temp
);
2993 case 0x88: /* Store, No WriteBack, Post Inc */
2994 STOREMULT (instr
, LSBase
, 0L);
2997 case 0x89: /* Load, No WriteBack, Post Inc */
2998 LOADMULT (instr
, LSBase
, 0L);
3001 case 0x8a: /* Store, WriteBack, Post Inc */
3003 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
3006 case 0x8b: /* Load, WriteBack, Post Inc */
3008 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
3011 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
3012 STORESMULT (instr
, LSBase
, 0L);
3015 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
3016 LOADSMULT (instr
, LSBase
, 0L);
3019 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
3021 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
3024 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
3026 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
3029 case 0x90: /* Store, No WriteBack, Pre Dec */
3030 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3033 case 0x91: /* Load, No WriteBack, Pre Dec */
3034 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3037 case 0x92: /* Store, WriteBack, Pre Dec */
3038 temp
= LSBase
- LSMNumRegs
;
3039 STOREMULT (instr
, temp
, temp
);
3042 case 0x93: /* Load, WriteBack, Pre Dec */
3043 temp
= LSBase
- LSMNumRegs
;
3044 LOADMULT (instr
, temp
, temp
);
3047 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
3048 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3051 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
3052 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3055 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
3056 temp
= LSBase
- LSMNumRegs
;
3057 STORESMULT (instr
, temp
, temp
);
3060 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
3061 temp
= LSBase
- LSMNumRegs
;
3062 LOADSMULT (instr
, temp
, temp
);
3065 case 0x98: /* Store, No WriteBack, Pre Inc */
3066 STOREMULT (instr
, LSBase
+ 4L, 0L);
3069 case 0x99: /* Load, No WriteBack, Pre Inc */
3070 LOADMULT (instr
, LSBase
+ 4L, 0L);
3073 case 0x9a: /* Store, WriteBack, Pre Inc */
3075 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3078 case 0x9b: /* Load, WriteBack, Pre Inc */
3080 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3083 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
3084 STORESMULT (instr
, LSBase
+ 4L, 0L);
3087 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
3088 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3091 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
3093 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3096 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
3098 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3101 /***************************************************************************\
3103 \***************************************************************************/
3113 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3117 /***************************************************************************\
3119 \***************************************************************************/
3129 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3133 /***************************************************************************\
3134 * Branch and Link forward *
3135 \***************************************************************************/
3146 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3148 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3150 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3154 /***************************************************************************\
3155 * Branch and Link backward *
3156 \***************************************************************************/
3167 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
3169 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
3171 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3175 /***************************************************************************\
3176 * Co-Processor Data Transfers *
3177 \***************************************************************************/
3180 if (state
->is_XScale
)
3182 if (BITS (4, 7) != 0x00)
3183 ARMul_UndefInstr (state
, instr
);
3185 if (BITS (8, 11) != 0x00)
3186 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3188 /* XScale MAR insn. Move two registers into accumulator. */
3189 if (BITS (0, 3) == 0x00)
3191 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3192 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3195 /* Access to any other acc is unpredicatable. */
3200 case 0xc0: /* Store , No WriteBack , Post Dec */
3201 ARMul_STC (state
, instr
, LHS
);
3205 if (state
->is_XScale
)
3207 if (BITS (4, 7) != 0x00)
3208 ARMul_UndefInstr (state
, instr
);
3210 if (BITS (8, 11) != 0x00)
3211 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3213 /* XScale MRA insn. Move accumulator into two registers. */
3214 if (BITS (0, 3) == 0x00)
3216 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3221 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3222 state
->Reg
[BITS (16, 19)] = t1
;
3225 /* Access to any other acc is unpredicatable. */
3230 case 0xc1: /* Load , No WriteBack , Post Dec */
3231 ARMul_LDC (state
, instr
, LHS
);
3235 case 0xc6: /* Store , WriteBack , Post Dec */
3237 state
->Base
= lhs
- LSCOff
;
3238 ARMul_STC (state
, instr
, lhs
);
3242 case 0xc7: /* Load , WriteBack , Post Dec */
3244 state
->Base
= lhs
- LSCOff
;
3245 ARMul_LDC (state
, instr
, lhs
);
3249 case 0xcc: /* Store , No WriteBack , Post Inc */
3250 ARMul_STC (state
, instr
, LHS
);
3254 case 0xcd: /* Load , No WriteBack , Post Inc */
3255 ARMul_LDC (state
, instr
, LHS
);
3259 case 0xce: /* Store , WriteBack , Post Inc */
3261 state
->Base
= lhs
+ LSCOff
;
3262 ARMul_STC (state
, instr
, LHS
);
3266 case 0xcf: /* Load , WriteBack , Post Inc */
3268 state
->Base
= lhs
+ LSCOff
;
3269 ARMul_LDC (state
, instr
, LHS
);
3274 case 0xd4: /* Store , No WriteBack , Pre Dec */
3275 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3279 case 0xd5: /* Load , No WriteBack , Pre Dec */
3280 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3284 case 0xd6: /* Store , WriteBack , Pre Dec */
3287 ARMul_STC (state
, instr
, lhs
);
3291 case 0xd7: /* Load , WriteBack , Pre Dec */
3294 ARMul_LDC (state
, instr
, lhs
);
3298 case 0xdc: /* Store , No WriteBack , Pre Inc */
3299 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3303 case 0xdd: /* Load , No WriteBack , Pre Inc */
3304 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3308 case 0xde: /* Store , WriteBack , Pre Inc */
3311 ARMul_STC (state
, instr
, lhs
);
3315 case 0xdf: /* Load , WriteBack , Pre Inc */
3318 ARMul_LDC (state
, instr
, lhs
);
3321 /***************************************************************************\
3322 * Co-Processor Register Transfers (MCR) and Data Ops *
3323 \***************************************************************************/
3326 if (state
->is_XScale
)
3327 switch (BITS (18, 19))
3331 /* XScale MIA instruction. Signed multiplication of two 32 bit
3332 values and addition to 40 bit accumulator. */
3333 long long Rm
= state
->Reg
[MULLHSReg
];
3334 long long Rs
= state
->Reg
[MULACCReg
];
3340 state
->Accumulator
+= Rm
* Rs
;
3346 /* XScale MIAPH instruction. */
3347 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3348 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3349 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3350 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3365 state
->Accumulator
+= t5
;
3370 state
->Accumulator
+= t5
;
3376 /* XScale MIAxy instruction. */
3382 t1
= state
->Reg
[MULLHSReg
] >> 16;
3384 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3387 t2
= state
->Reg
[MULACCReg
] >> 16;
3389 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3399 state
->Accumulator
+= t5
;
3421 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3423 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3424 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3428 ARMul_MCR (state
, instr
, DEST
);
3430 else /* CDP Part 1 */
3431 ARMul_CDP (state
, instr
);
3434 /***************************************************************************\
3435 * Co-Processor Register Transfers (MRC) and Data Ops *
3436 \***************************************************************************/
3448 temp
= ARMul_MRC (state
, instr
);
3451 ASSIGNN ((temp
& NBIT
) != 0);
3452 ASSIGNZ ((temp
& ZBIT
) != 0);
3453 ASSIGNC ((temp
& CBIT
) != 0);
3454 ASSIGNV ((temp
& VBIT
) != 0);
3459 else /* CDP Part 2 */
3460 ARMul_CDP (state
, instr
);
3463 /***************************************************************************\
3465 \***************************************************************************/
3483 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3485 /* A prefetch abort. */
3486 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
3487 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3491 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3493 ARMul_Abort (state
, ARMul_SWIV
);
3496 } /* 256 way main switch */
3503 #ifdef NEED_UI_LOOP_HOOK
3504 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3506 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3509 #endif /* NEED_UI_LOOP_HOOK */
3511 if (state
->Emulate
== ONCE
)
3512 state
->Emulate
= STOP
;
3513 /* If we have changed mode, allow the PC to advance before stopping. */
3514 else if (state
->Emulate
== CHANGEMODE
)
3516 else if (state
->Emulate
!= RUN
)
3519 while (!stop_simulator
); /* do loop */
3521 state
->decoded
= decoded
;
3522 state
->loaded
= loaded
;
3526 } /* Emulate 26/32 in instruction based mode */
3529 /***************************************************************************\
3530 * This routine evaluates most Data Processing register RHS's with the S *
3531 * bit clear. It is intended to be called from the macro DPRegRHS, which *
3532 * filters the common case of an unshifted register with in line code *
3533 \***************************************************************************/
3536 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3538 ARMword shamt
, base
;
3542 { /* shift amount in a register */
3547 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3550 base
= state
->Reg
[base
];
3551 ARMul_Icycles (state
, 1, 0L);
3552 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3553 switch ((int) BITS (5, 6))
3558 else if (shamt
>= 32)
3561 return (base
<< shamt
);
3565 else if (shamt
>= 32)
3568 return (base
>> shamt
);
3572 else if (shamt
>= 32)
3573 return ((ARMword
) ((long int) base
>> 31L));
3575 return ((ARMword
) ((long int) base
>> (int) shamt
));
3581 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3585 { /* shift amount is a constant */
3588 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3591 base
= state
->Reg
[base
];
3592 shamt
= BITS (7, 11);
3593 switch ((int) BITS (5, 6))
3596 return (base
<< shamt
);
3601 return (base
>> shamt
);
3604 return ((ARMword
) ((long int) base
>> 31L));
3606 return ((ARMword
) ((long int) base
>> (int) shamt
));
3608 if (shamt
== 0) /* its an RRX */
3609 return ((base
>> 1) | (CFLAG
<< 31));
3611 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3614 return (0); /* just to shut up lint */
3617 /***************************************************************************\
3618 * This routine evaluates most Logical Data Processing register RHS's *
3619 * with the S bit set. It is intended to be called from the macro *
3620 * DPSRegRHS, which filters the common case of an unshifted register *
3621 * with in line code *
3622 \***************************************************************************/
3625 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3627 ARMword shamt
, base
;
3631 { /* shift amount in a register */
3636 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3639 base
= state
->Reg
[base
];
3640 ARMul_Icycles (state
, 1, 0L);
3641 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3642 switch ((int) BITS (5, 6))
3647 else if (shamt
== 32)
3652 else if (shamt
> 32)
3659 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3660 return (base
<< shamt
);
3665 else if (shamt
== 32)
3667 ASSIGNC (base
>> 31);
3670 else if (shamt
> 32)
3677 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3678 return (base
>> shamt
);
3683 else if (shamt
>= 32)
3685 ASSIGNC (base
>> 31L);
3686 return ((ARMword
) ((long int) base
>> 31L));
3690 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3691 return ((ARMword
) ((long int) base
>> (int) shamt
));
3699 ASSIGNC (base
>> 31);
3704 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3705 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3710 { /* shift amount is a constant */
3713 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3716 base
= state
->Reg
[base
];
3717 shamt
= BITS (7, 11);
3718 switch ((int) BITS (5, 6))
3721 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3722 return (base
<< shamt
);
3726 ASSIGNC (base
>> 31);
3731 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3732 return (base
>> shamt
);
3737 ASSIGNC (base
>> 31L);
3738 return ((ARMword
) ((long int) base
>> 31L));
3742 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3743 return ((ARMword
) ((long int) base
>> (int) shamt
));
3750 return ((base
>> 1) | (shamt
<< 31));
3754 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3755 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3759 return (0); /* just to shut up lint */
3762 /***************************************************************************\
3763 * This routine handles writes to register 15 when the S bit is not set. *
3764 \***************************************************************************/
3767 WriteR15 (ARMul_State
* state
, ARMword src
)
3769 /* The ARM documentation states that the two least significant bits
3770 are discarded when setting PC, except in the cases handled by
3771 WriteR15Branch() below. It's probably an oversight: in THUMB
3772 mode, the second least significant bit should probably not be
3781 state
->Reg
[15] = src
& PCBITS
;
3783 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
3784 ARMul_R15Altered (state
);
3789 /***************************************************************************\
3790 * This routine handles writes to register 15 when the S bit is set. *
3791 \***************************************************************************/
3794 WriteSR15 (ARMul_State
* state
, ARMword src
)
3797 if (state
->Bank
> 0)
3799 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3800 ARMul_CPSRAltered (state
);
3808 state
->Reg
[15] = src
& PCBITS
;
3812 abort (); /* ARMul_R15Altered would have to support it. */
3816 if (state
->Bank
== USERBANK
)
3817 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3819 state
->Reg
[15] = src
;
3820 ARMul_R15Altered (state
);
3825 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3826 will switch to Thumb mode if the least significant bit is set. */
3829 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3835 state
->Reg
[15] = src
& 0xfffffffe;
3840 state
->Reg
[15] = src
& 0xfffffffc;
3844 WriteR15 (state
, src
);
3848 /***************************************************************************\
3849 * This routine evaluates most Load and Store register RHS's. It is *
3850 * intended to be called from the macro LSRegRHS, which filters the *
3851 * common case of an unshifted register with in line code *
3852 \***************************************************************************/
3855 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3857 ARMword shamt
, base
;
3862 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3865 base
= state
->Reg
[base
];
3867 shamt
= BITS (7, 11);
3868 switch ((int) BITS (5, 6))
3871 return (base
<< shamt
);
3876 return (base
>> shamt
);
3879 return ((ARMword
) ((long int) base
>> 31L));
3881 return ((ARMword
) ((long int) base
>> (int) shamt
));
3883 if (shamt
== 0) /* its an RRX */
3884 return ((base
>> 1) | (CFLAG
<< 31));
3886 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3888 return (0); /* just to shut up lint */
3891 /***************************************************************************\
3892 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3893 \***************************************************************************/
3896 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3902 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3904 return state
->Reg
[RHSReg
];
3907 /* else immediate */
3908 return BITS (0, 3) | (BITS (8, 11) << 4);
3911 /***************************************************************************\
3912 * This function does the work of loading a word for a LDR instruction. *
3913 \***************************************************************************/
3916 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3922 if (ADDREXCEPT (address
))
3924 INTERNALABORT (address
);
3927 dest
= ARMul_LoadWordN (state
, address
);
3931 return (state
->lateabtSig
);
3934 dest
= ARMul_Align (state
, address
, dest
);
3936 ARMul_Icycles (state
, 1, 0L);
3938 return (DESTReg
!= LHSReg
);
3942 /***************************************************************************\
3943 * This function does the work of loading a halfword. *
3944 \***************************************************************************/
3947 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3954 if (ADDREXCEPT (address
))
3956 INTERNALABORT (address
);
3959 dest
= ARMul_LoadHalfWord (state
, address
);
3963 return (state
->lateabtSig
);
3968 if (dest
& 1 << (16 - 1))
3969 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3972 ARMul_Icycles (state
, 1, 0L);
3973 return (DESTReg
!= LHSReg
);
3978 /***************************************************************************\
3979 * This function does the work of loading a byte for a LDRB instruction. *
3980 \***************************************************************************/
3983 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3989 if (ADDREXCEPT (address
))
3991 INTERNALABORT (address
);
3994 dest
= ARMul_LoadByte (state
, address
);
3998 return (state
->lateabtSig
);
4003 if (dest
& 1 << (8 - 1))
4004 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
4007 ARMul_Icycles (state
, 1, 0L);
4008 return (DESTReg
!= LHSReg
);
4011 /***************************************************************************\
4012 * This function does the work of loading two words for a LDRD instruction. *
4013 \***************************************************************************/
4016 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
4020 ARMword write_back
= BIT (21);
4021 ARMword immediate
= BIT (22);
4022 ARMword add_to_base
= BIT (23);
4023 ARMword pre_indexed
= BIT (24);
4033 /* If the writeback bit is set, the pre-index bit must be clear. */
4034 if (write_back
&& ! pre_indexed
)
4036 ARMul_UndefInstr (state
, instr
);
4040 /* Extract the base address register. */
4043 /* Extract the destination register and check it. */
4046 /* Destination register must be even. */
4048 /* Destination register cannot be LR. */
4049 || (dest_reg
== 14))
4051 ARMul_UndefInstr (state
, instr
);
4055 /* Compute the base address. */
4056 base
= state
->Reg
[addr_reg
];
4058 /* Compute the offset. */
4059 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4061 /* Compute the sum of the two. */
4063 sum
= base
+ offset
;
4065 sum
= base
- offset
;
4067 /* If this is a pre-indexed mode use the sum. */
4073 /* The address must be aligned on a 8 byte boundary. */
4077 ARMul_DATAABORT (addr
);
4079 ARMul_UndefInstr (state
, instr
);
4084 /* For pre indexed or post indexed addressing modes,
4085 check that the destination registers do not overlap
4086 the address registers. */
4087 if ((! pre_indexed
|| write_back
)
4088 && ( addr_reg
== dest_reg
4089 || addr_reg
== dest_reg
+ 1))
4091 ARMul_UndefInstr (state
, instr
);
4095 /* Load the words. */
4096 value1
= ARMul_LoadWordN (state
, addr
);
4097 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4099 /* Check for data aborts. */
4106 ARMul_Icycles (state
, 2, 0L);
4108 /* Store the values. */
4109 state
->Reg
[dest_reg
] = value1
;
4110 state
->Reg
[dest_reg
+ 1] = value2
;
4112 /* Do the post addressing and writeback. */
4116 if (! pre_indexed
|| write_back
)
4117 state
->Reg
[addr_reg
] = addr
;
4120 /***************************************************************************\
4121 * This function does the work of storing two words for a STRD instruction. *
4122 \***************************************************************************/
4125 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4129 ARMword write_back
= BIT (21);
4130 ARMword immediate
= BIT (22);
4131 ARMword add_to_base
= BIT (23);
4132 ARMword pre_indexed
= BIT (24);
4140 /* If the writeback bit is set, the pre-index bit must be clear. */
4141 if (write_back
&& ! pre_indexed
)
4143 ARMul_UndefInstr (state
, instr
);
4147 /* Extract the base address register. */
4150 /* Base register cannot be PC. */
4153 ARMul_UndefInstr (state
, instr
);
4157 /* Extract the source register. */
4160 /* Source register must be even. */
4163 ARMul_UndefInstr (state
, instr
);
4167 /* Compute the base address. */
4168 base
= state
->Reg
[addr_reg
];
4170 /* Compute the offset. */
4171 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4173 /* Compute the sum of the two. */
4175 sum
= base
+ offset
;
4177 sum
= base
- offset
;
4179 /* If this is a pre-indexed mode use the sum. */
4185 /* The address must be aligned on a 8 byte boundary. */
4189 ARMul_DATAABORT (addr
);
4191 ARMul_UndefInstr (state
, instr
);
4196 /* For pre indexed or post indexed addressing modes,
4197 check that the destination registers do not overlap
4198 the address registers. */
4199 if ((! pre_indexed
|| write_back
)
4200 && ( addr_reg
== src_reg
4201 || addr_reg
== src_reg
+ 1))
4203 ARMul_UndefInstr (state
, instr
);
4207 /* Load the words. */
4208 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4209 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4217 /* Do the post addressing and writeback. */
4221 if (! pre_indexed
|| write_back
)
4222 state
->Reg
[addr_reg
] = addr
;
4225 /***************************************************************************\
4226 * This function does the work of storing a word from a STR instruction. *
4227 \***************************************************************************/
4230 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4235 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4238 ARMul_StoreWordN (state
, address
, DEST
);
4240 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4242 INTERNALABORT (address
);
4243 (void) ARMul_LoadWordN (state
, address
);
4246 ARMul_StoreWordN (state
, address
, DEST
);
4251 return (state
->lateabtSig
);
4257 /***************************************************************************\
4258 * This function does the work of storing a byte for a STRH instruction. *
4259 \***************************************************************************/
4262 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4268 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4272 ARMul_StoreHalfWord (state
, address
, DEST
);
4274 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4276 INTERNALABORT (address
);
4277 (void) ARMul_LoadHalfWord (state
, address
);
4280 ARMul_StoreHalfWord (state
, address
, DEST
);
4286 return (state
->lateabtSig
);
4294 /***************************************************************************\
4295 * This function does the work of storing a byte for a STRB instruction. *
4296 \***************************************************************************/
4299 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4304 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4307 ARMul_StoreByte (state
, address
, DEST
);
4309 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4311 INTERNALABORT (address
);
4312 (void) ARMul_LoadByte (state
, address
);
4315 ARMul_StoreByte (state
, address
, DEST
);
4320 return (state
->lateabtSig
);
4326 /***************************************************************************\
4327 * This function does the work of loading the registers listed in an LDM *
4328 * instruction, when the S bit is clear. The code here is always increment *
4329 * after, it's up to the caller to get the input address correct and to *
4330 * handle base register modification. *
4331 \***************************************************************************/
4334 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4340 UNDEF_LSMBaseInListWb
;
4343 if (ADDREXCEPT (address
))
4345 INTERNALABORT (address
);
4348 if (BIT (21) && LHSReg
!= 15)
4351 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4352 dest
= ARMul_LoadWordN (state
, address
);
4353 if (!state
->abortSig
&& !state
->Aborted
)
4354 state
->Reg
[temp
++] = dest
;
4355 else if (!state
->Aborted
)
4357 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4358 state
->Aborted
= ARMul_DataAbortV
;
4361 for (; temp
< 16; temp
++) /* S cycles from here on */
4363 { /* load this register */
4365 dest
= ARMul_LoadWordS (state
, address
);
4366 if (!state
->abortSig
&& !state
->Aborted
)
4367 state
->Reg
[temp
] = dest
;
4368 else if (!state
->Aborted
)
4370 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4371 state
->Aborted
= ARMul_DataAbortV
;
4375 if (BIT (15) && !state
->Aborted
)
4376 { /* PC is in the reg list */
4377 WriteR15Branch(state
, PC
);
4380 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
4384 if (BIT (21) && LHSReg
!= 15)
4390 /***************************************************************************\
4391 * This function does the work of loading the registers listed in an LDM *
4392 * instruction, when the S bit is set. The code here is always increment *
4393 * after, it's up to the caller to get the input address correct and to *
4394 * handle base register modification. *
4395 \***************************************************************************/
4398 LoadSMult (ARMul_State
* state
,
4407 UNDEF_LSMBaseInListWb
;
4412 if (ADDREXCEPT (address
))
4414 INTERNALABORT (address
);
4418 if (BIT (21) && LHSReg
!= 15)
4421 if (!BIT (15) && state
->Bank
!= USERBANK
)
4423 /* Temporary reg bank switch. */
4424 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4425 UNDEF_LSMUserBankWb
;
4428 for (temp
= 0; !BIT (temp
); temp
++)
4429 ; /* N cycle first. */
4431 dest
= ARMul_LoadWordN (state
, address
);
4433 if (!state
->abortSig
)
4434 state
->Reg
[temp
++] = dest
;
4435 else if (!state
->Aborted
)
4437 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4438 state
->Aborted
= ARMul_DataAbortV
;
4441 for (; temp
< 16; temp
++)
4442 /* S cycles from here on. */
4445 /* Load this register. */
4447 dest
= ARMul_LoadWordS (state
, address
);
4449 if (!state
->abortSig
&& !state
->Aborted
)
4450 state
->Reg
[temp
] = dest
;
4451 else if (!state
->Aborted
)
4453 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4454 state
->Aborted
= ARMul_DataAbortV
;
4458 if (BIT (15) && !state
->Aborted
)
4460 /* PC is in the reg list. */
4462 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4464 state
->Cpsr
= GETSPSR (state
->Bank
);
4465 ARMul_CPSRAltered (state
);
4468 WriteR15 (state
, PC
);
4470 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4472 /* Protect bits in user mode. */
4473 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4474 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4475 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4476 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4479 ARMul_R15Altered (state
);
4485 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4486 /* Restore the correct bank. */
4487 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4489 /* To write back the final register. */
4490 ARMul_Icycles (state
, 1, 0L);
4494 if (BIT (21) && LHSReg
!= 15)
4501 /***************************************************************************\
4502 * This function does the work of storing the registers listed in an STM *
4503 * instruction, when the S bit is clear. The code here is always increment *
4504 * after, it's up to the caller to get the input address correct and to *
4505 * handle base register modification. *
4506 \***************************************************************************/
4509 StoreMult (ARMul_State
* state
, ARMword instr
,
4510 ARMword address
, ARMword WBBase
)
4516 UNDEF_LSMBaseInListWb
;
4519 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
4523 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4525 INTERNALABORT (address
);
4531 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4533 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4537 (void) ARMul_LoadWordN (state
, address
);
4538 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
4540 { /* save this register */
4542 (void) ARMul_LoadWordS (state
, address
);
4544 if (BIT (21) && LHSReg
!= 15)
4550 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4553 if (state
->abortSig
&& !state
->Aborted
)
4555 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4556 state
->Aborted
= ARMul_DataAbortV
;
4559 if (BIT (21) && LHSReg
!= 15)
4562 for (; temp
< 16; temp
++) /* S cycles from here on */
4564 { /* save this register */
4567 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4569 if (state
->abortSig
&& !state
->Aborted
)
4571 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4572 state
->Aborted
= ARMul_DataAbortV
;
4582 /***************************************************************************\
4583 * This function does the work of storing the registers listed in an STM *
4584 * instruction when the S bit is set. The code here is always increment *
4585 * after, it's up to the caller to get the input address correct and to *
4586 * handle base register modification. *
4587 \***************************************************************************/
4590 StoreSMult (ARMul_State
* state
,
4599 UNDEF_LSMBaseInListWb
;
4604 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4606 INTERNALABORT (address
);
4613 if (state
->Bank
!= USERBANK
)
4615 /* Force User Bank. */
4616 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4617 UNDEF_LSMUserBankWb
;
4620 for (temp
= 0; !BIT (temp
); temp
++)
4621 ; /* N cycle first. */
4624 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4628 (void) ARMul_LoadWordN (state
, address
);
4630 for (; temp
< 16; temp
++)
4631 /* Fake the Stores as Loads. */
4634 /* Save this register. */
4637 (void) ARMul_LoadWordS (state
, address
);
4640 if (BIT (21) && LHSReg
!= 15)
4648 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4651 if (state
->abortSig
&& !state
->Aborted
)
4653 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4654 state
->Aborted
= ARMul_DataAbortV
;
4657 for (; temp
< 16; temp
++)
4658 /* S cycles from here on. */
4661 /* Save this register. */
4664 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4666 if (state
->abortSig
&& !state
->Aborted
)
4668 XScale_set_fsr_far(state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4669 state
->Aborted
= ARMul_DataAbortV
;
4673 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4674 /* Restore the correct bank. */
4675 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4677 if (BIT (21) && LHSReg
!= 15)
4686 /***************************************************************************\
4687 * This function does the work of adding two 32bit values together, and *
4688 * calculating if a carry has occurred. *
4689 \***************************************************************************/
4692 Add32 (ARMword a1
, ARMword a2
, int *carry
)
4694 ARMword result
= (a1
+ a2
);
4695 unsigned int uresult
= (unsigned int) result
;
4696 unsigned int ua1
= (unsigned int) a1
;
4698 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4699 or (result > RdLo) then we have no carry: */
4700 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
4708 /***************************************************************************\
4709 * This function does the work of multiplying two 32bit values to give a *
4711 \***************************************************************************/
4714 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4716 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
4717 ARMword RdHi
= 0, RdLo
= 0, Rm
;
4718 int scount
; /* cycle count */
4720 nRdHi
= BITS (16, 19);
4721 nRdLo
= BITS (12, 15);
4725 /* Needed to calculate the cycle count: */
4726 Rm
= state
->Reg
[nRm
];
4728 /* Check for illegal operand combinations first: */
4732 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
4734 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
4736 ARMword Rs
= state
->Reg
[nRs
];
4741 /* Compute sign of result and adjust operands if necessary. */
4743 sign
= (Rm
^ Rs
) & 0x80000000;
4745 if (((signed long) Rm
) < 0)
4748 if (((signed long) Rs
) < 0)
4752 /* We can split the 32x32 into four 16x16 operations. This ensures
4753 that we do not lose precision on 32bit only hosts: */
4754 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
4755 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4756 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
4757 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4759 /* We now need to add all of these results together, taking care
4760 to propogate the carries from the additions: */
4761 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
4763 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
4765 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
4769 /* Negate result if necessary. */
4773 if (RdLo
== 0xFFFFFFFF)
4782 state
->Reg
[nRdLo
] = RdLo
;
4783 state
->Reg
[nRdHi
] = RdHi
;
4784 } /* else undefined result */
4786 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4790 /* Ensure that both RdHi and RdLo are used to compute Z, but
4791 don't let RdLo's sign bit make it to N. */
4792 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4795 /* The cycle count depends on whether the instruction is a signed or
4796 unsigned multiply, and what bits are clear in the multiplier: */
4797 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
4798 Rm
= ~Rm
; /* invert the bits to make the check against zero */
4800 if ((Rm
& 0xFFFFFF00) == 0)
4802 else if ((Rm
& 0xFFFF0000) == 0)
4804 else if ((Rm
& 0xFF000000) == 0)
4812 /***************************************************************************\
4813 * This function does the work of multiplying two 32bit values and adding *
4814 * a 64bit value to give a 64bit result. *
4815 \***************************************************************************/
4818 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4825 nRdHi
= BITS (16, 19);
4826 nRdLo
= BITS (12, 15);
4828 RdHi
= state
->Reg
[nRdHi
];
4829 RdLo
= state
->Reg
[nRdLo
];
4831 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
4833 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
4834 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
4836 state
->Reg
[nRdLo
] = RdLo
;
4837 state
->Reg
[nRdHi
] = RdHi
;
4841 /* Ensure that both RdHi and RdLo are used to compute Z, but
4842 don't let RdLo's sign bit make it to N. */
4843 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4846 return scount
+ 1; /* extra cycle for addition */
This page took 0.124088 seconds and 5 git commands to generate.