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. */
24 static ARMword
GetDPRegRHS (ARMul_State
*, ARMword
);
25 static ARMword
GetDPSRegRHS (ARMul_State
*, ARMword
);
26 static void WriteR15 (ARMul_State
*, ARMword
);
27 static void WriteSR15 (ARMul_State
*, ARMword
);
28 static void WriteR15Branch (ARMul_State
*, ARMword
);
29 static ARMword
GetLSRegRHS (ARMul_State
*, ARMword
);
30 static ARMword
GetLS7RHS (ARMul_State
*, ARMword
);
31 static unsigned LoadWord (ARMul_State
*, ARMword
, ARMword
);
32 static unsigned LoadHalfWord (ARMul_State
*, ARMword
, ARMword
, int);
33 static unsigned LoadByte (ARMul_State
*, ARMword
, ARMword
, int);
34 static unsigned StoreWord (ARMul_State
*, ARMword
, ARMword
);
35 static unsigned StoreHalfWord (ARMul_State
*, ARMword
, ARMword
);
36 static unsigned StoreByte (ARMul_State
*, ARMword
, ARMword
);
37 static void LoadMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
38 static void StoreMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
39 static void LoadSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
40 static void StoreSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
41 static unsigned Multiply64 (ARMul_State
*, ARMword
, int, int);
42 static unsigned MultiplyAdd64 (ARMul_State
*, ARMword
, int, int);
43 static void Handle_Load_Double (ARMul_State
*, ARMword
);
44 static void Handle_Store_Double (ARMul_State
*, ARMword
);
46 #define LUNSIGNED (0) /* unsigned operation */
47 #define LSIGNED (1) /* signed operation */
48 #define LDEFAULT (0) /* default : do nothing */
49 #define LSCC (1) /* set condition codes on result */
51 #ifdef NEED_UI_LOOP_HOOK
52 /* How often to run the ui_loop update, when in use. */
53 #define UI_LOOP_POLL_INTERVAL 0x32000
55 /* Counter for the ui_loop_hook update. */
56 static long ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
58 /* Actual hook to call to run through gdb's gui event loop. */
59 extern int (*deprecated_ui_loop_hook
) (int);
60 #endif /* NEED_UI_LOOP_HOOK */
62 extern int stop_simulator
;
64 /* Short-hand macros for LDR/STR. */
66 /* Store post decrement writeback. */
69 if (StoreHalfWord (state, instr, lhs)) \
70 LSBase = lhs - GetLS7RHS (state, instr);
72 /* Store post increment writeback. */
75 if (StoreHalfWord (state, instr, lhs)) \
76 LSBase = lhs + GetLS7RHS (state, instr);
78 /* Store pre decrement. */
80 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
82 /* Store pre decrement writeback. */
83 #define SHPREDOWNWB() \
84 temp = LHS - GetLS7RHS (state, instr); \
85 if (StoreHalfWord (state, instr, temp)) \
88 /* Store pre increment. */
90 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
92 /* Store pre increment writeback. */
94 temp = LHS + GetLS7RHS (state, instr); \
95 if (StoreHalfWord (state, instr, temp)) \
98 /* Load post decrement writeback. */
99 #define LHPOSTDOWN() \
103 temp = lhs - GetLS7RHS (state, instr); \
105 switch (BITS (5, 6)) \
108 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
112 if (LoadByte (state, instr, lhs, LSIGNED)) \
116 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
119 case 0: /* SWP handled elsewhere. */ \
128 /* Load post increment writeback. */
133 temp = lhs + GetLS7RHS (state, instr); \
135 switch (BITS (5, 6)) \
138 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
142 if (LoadByte (state, instr, lhs, LSIGNED)) \
146 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
149 case 0: /* SWP handled elsewhere. */ \
158 /* Load pre decrement. */
159 #define LHPREDOWN() \
163 temp = LHS - GetLS7RHS (state, instr); \
164 switch (BITS (5, 6)) \
167 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
170 (void) LoadByte (state, instr, temp, LSIGNED); \
173 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
176 /* SWP handled elsewhere. */ \
185 /* Load pre decrement writeback. */
186 #define LHPREDOWNWB() \
190 temp = LHS - GetLS7RHS (state, instr); \
191 switch (BITS (5, 6)) \
194 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
198 if (LoadByte (state, instr, temp, LSIGNED)) \
202 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
206 /* SWP handled elsewhere. */ \
215 /* Load pre increment. */
220 temp = LHS + GetLS7RHS (state, instr); \
221 switch (BITS (5, 6)) \
224 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
227 (void) LoadByte (state, instr, temp, LSIGNED); \
230 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
233 /* SWP handled elsewhere. */ \
242 /* Load pre increment writeback. */
243 #define LHPREUPWB() \
247 temp = LHS + GetLS7RHS (state, instr); \
248 switch (BITS (5, 6)) \
251 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
255 if (LoadByte (state, instr, temp, LSIGNED)) \
259 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
263 /* SWP handled elsewhere. */ \
272 /* EMULATION of ARM6. */
274 /* The PC pipeline value depends on whether ARM
275 or Thumb instructions are being executed. */
280 ARMul_Emulate32 (ARMul_State
* state
)
282 ARMul_Emulate26 (ARMul_State
* state
)
285 ARMword instr
; /* The current instruction. */
286 ARMword dest
= 0; /* Almost the DestBus. */
287 ARMword temp
; /* Ubiquitous third hand. */
288 ARMword pc
= 0; /* The address of the current instruction. */
289 ARMword lhs
; /* Almost the ABus and BBus. */
291 ARMword decoded
= 0; /* Instruction pipeline. */
294 /* Execute the next instruction. */
296 if (state
->NextInstr
< PRIMEPIPE
)
298 decoded
= state
->decoded
;
299 loaded
= state
->loaded
;
305 /* Just keep going. */
308 switch (state
->NextInstr
)
311 /* Advance the pipeline, and an S cycle. */
312 state
->Reg
[15] += isize
;
316 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
320 /* Advance the pipeline, and an N cycle. */
321 state
->Reg
[15] += isize
;
325 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
330 /* Program counter advanced, and an S cycle. */
334 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
339 /* Program counter advanced, and an N cycle. */
343 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
348 /* The program counter has been changed. */
353 state
->Reg
[15] = pc
+ (isize
* 2);
355 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
356 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
357 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
362 /* The program counter has been changed. */
367 state
->Reg
[15] = pc
+ (isize
* 2);
369 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
370 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
371 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
377 ARMul_EnvokeEvent (state
);
378 #if 0 /* Enable this for a helpful bit of debugging when tracing is needed. */
379 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
383 #if 0 /* Enable this code to help track down stack alignment bugs. */
385 static ARMword old_sp
= -1;
387 if (old_sp
!= state
->Reg
[13])
389 old_sp
= state
->Reg
[13];
390 fprintf (stderr
, "pc: %08x: SP set to %08x%s\n",
391 pc
& ~1, old_sp
, (old_sp
% 8) ? " [UNALIGNED!]" : "");
396 if (state
->Exception
)
398 /* Any exceptions ? */
399 if (state
->NresetSig
== LOW
)
401 ARMul_Abort (state
, ARMul_ResetV
);
404 else if (!state
->NfiqSig
&& !FFLAG
)
406 ARMul_Abort (state
, ARMul_FIQV
);
409 else if (!state
->NirqSig
&& !IFLAG
)
411 ARMul_Abort (state
, ARMul_IRQV
);
416 if (state
->CallDebug
> 0)
418 instr
= ARMul_Debug (state
, pc
, instr
);
419 if (state
->Emulate
< ONCE
)
421 state
->NextInstr
= RESUME
;
426 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
428 (void) fgetc (stdin
);
431 else if (state
->Emulate
< ONCE
)
433 state
->NextInstr
= RESUME
;
440 /* Provide Thumb instruction decoding. If the processor is in Thumb
441 mode, then we can simply decode the Thumb instruction, and map it
442 to the corresponding ARM instruction (by directly loading the
443 instr variable, and letting the normal ARM simulator
444 execute). There are some caveats to ensure that the correct
445 pipelined PC value is used when executing Thumb code, and also for
446 dealing with the BL instruction. */
451 /* Check if in Thumb mode. */
452 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
455 /* This is a Thumb instruction. */
456 ARMul_UndefInstr (state
, instr
);
460 /* Already processed. */
464 /* ARM instruction available. */
466 /* So continue instruction decoding. */
474 /* Check the condition codes. */
475 if ((temp
= TOPBITS (28)) == AL
)
476 /* Vile deed in the need for speed. */
479 /* Check the condition code. */
480 switch ((int) TOPBITS (28))
488 if (BITS (25, 27) == 5) /* BLX(1) */
492 state
->Reg
[14] = pc
+ 4;
494 /* Force entry into Thumb mode. */
497 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
499 dest
+= POSBRANCH
+ (BIT (24) << 1);
501 WriteR15Branch (state
, dest
);
504 else if ((instr
& 0xFC70F000) == 0xF450F000)
505 /* The PLD instruction. Ignored. */
507 else if ( ((instr
& 0xfe500f00) == 0xfc100100)
508 || ((instr
& 0xfe500f00) == 0xfc000100))
509 /* wldrw and wstrw are unconditional. */
512 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
513 ARMul_UndefInstr (state
, instr
);
542 temp
= (CFLAG
&& !ZFLAG
);
545 temp
= (!CFLAG
|| ZFLAG
);
548 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
551 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
554 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
557 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
561 /* Handle the Clock counter here. */
562 if (state
->is_XScale
)
567 ok
= state
->CPRead
[14] (state
, 0, & cp14r0
);
569 if (ok
&& (cp14r0
& ARMul_CP14_R0_ENABLE
))
571 unsigned long newcycles
, nowtime
= ARMul_Time (state
);
573 newcycles
= nowtime
- state
->LastTime
;
574 state
->LastTime
= nowtime
;
576 if (cp14r0
& ARMul_CP14_R0_CCD
)
578 if (state
->CP14R0_CCD
== -1)
579 state
->CP14R0_CCD
= newcycles
;
581 state
->CP14R0_CCD
+= newcycles
;
583 if (state
->CP14R0_CCD
>= 64)
587 while (state
->CP14R0_CCD
>= 64)
588 state
->CP14R0_CCD
-= 64, newcycles
++;
598 state
->CP14R0_CCD
= -1;
600 cp14r0
|= ARMul_CP14_R0_FLAG2
;
601 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
603 ok
= state
->CPRead
[14] (state
, 1, & cp14r1
);
605 /* Coded like this for portability. */
606 while (ok
&& newcycles
)
608 if (cp14r1
== 0xffffffff)
619 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
621 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
625 if (state
->CPRead
[13] (state
, 8, & temp
)
626 && (temp
& ARMul_CP13_R8_PMUS
))
627 ARMul_Abort (state
, ARMul_FIQV
);
629 ARMul_Abort (state
, ARMul_IRQV
);
635 /* Handle hardware instructions breakpoints here. */
636 if (state
->is_XScale
)
638 if ( (pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
639 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
641 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
642 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
646 /* Actual execution of instructions begins here. */
647 /* If the condition codes don't match, stop here. */
652 if (state
->is_XScale
)
654 if (BIT (20) == 0 && BITS (25, 27) == 0)
656 if (BITS (4, 7) == 0xD)
658 /* XScale Load Consecutive insn. */
659 ARMword temp
= GetLS7RHS (state
, instr
);
660 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
661 ARMword addr
= BIT (24) ? temp2
: LHS
;
664 ARMul_UndefInstr (state
, instr
);
666 /* Alignment violation. */
667 ARMul_Abort (state
, ARMul_DataAbortV
);
670 int wb
= BIT (21) || (! BIT (24));
672 state
->Reg
[BITS (12, 15)] =
673 ARMul_LoadWordN (state
, addr
);
674 state
->Reg
[BITS (12, 15) + 1] =
675 ARMul_LoadWordN (state
, addr
+ 4);
682 else if (BITS (4, 7) == 0xF)
684 /* XScale Store Consecutive insn. */
685 ARMword temp
= GetLS7RHS (state
, instr
);
686 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
687 ARMword addr
= BIT (24) ? temp2
: LHS
;
690 ARMul_UndefInstr (state
, instr
);
692 /* Alignment violation. */
693 ARMul_Abort (state
, ARMul_DataAbortV
);
696 ARMul_StoreWordN (state
, addr
,
697 state
->Reg
[BITS (12, 15)]);
698 ARMul_StoreWordN (state
, addr
+ 4,
699 state
->Reg
[BITS (12, 15) + 1]);
701 if (BIT (21)|| ! BIT (24))
709 if (ARMul_HandleIwmmxt (state
, instr
))
713 switch ((int) BITS (20, 27))
715 /* Data Processing Register RHS Instructions. */
717 case 0x00: /* AND reg and MUL */
719 if (BITS (4, 11) == 0xB)
721 /* STRH register offset, no write-back, down, post indexed. */
725 if (BITS (4, 7) == 0xD)
727 Handle_Load_Double (state
, instr
);
730 if (BITS (4, 7) == 0xF)
732 Handle_Store_Double (state
, instr
);
736 if (BITS (4, 7) == 9)
739 rhs
= state
->Reg
[MULRHSReg
];
740 if (MULLHSReg
== MULDESTReg
)
743 state
->Reg
[MULDESTReg
] = 0;
745 else if (MULDESTReg
!= 15)
746 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
750 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
751 if (rhs
& (1L << dest
))
754 /* Mult takes this many/2 I cycles. */
755 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
766 case 0x01: /* ANDS reg and MULS */
768 if ((BITS (4, 11) & 0xF9) == 0x9)
769 /* LDR register offset, no write-back, down, post indexed. */
771 /* Fall through to rest of decoding. */
773 if (BITS (4, 7) == 9)
776 rhs
= state
->Reg
[MULRHSReg
];
778 if (MULLHSReg
== MULDESTReg
)
781 state
->Reg
[MULDESTReg
] = 0;
785 else if (MULDESTReg
!= 15)
787 dest
= state
->Reg
[MULLHSReg
] * rhs
;
788 ARMul_NegZero (state
, dest
);
789 state
->Reg
[MULDESTReg
] = dest
;
794 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
795 if (rhs
& (1L << dest
))
798 /* Mult takes this many/2 I cycles. */
799 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
810 case 0x02: /* EOR reg and MLA */
812 if (BITS (4, 11) == 0xB)
814 /* STRH register offset, write-back, down, post indexed. */
819 if (BITS (4, 7) == 9)
821 rhs
= state
->Reg
[MULRHSReg
];
822 if (MULLHSReg
== MULDESTReg
)
825 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
827 else if (MULDESTReg
!= 15)
828 state
->Reg
[MULDESTReg
] =
829 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
833 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
834 if (rhs
& (1L << dest
))
837 /* Mult takes this many/2 I cycles. */
838 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
848 case 0x03: /* EORS reg and MLAS */
850 if ((BITS (4, 11) & 0xF9) == 0x9)
851 /* LDR register offset, write-back, down, post-indexed. */
853 /* Fall through to rest of the decoding. */
855 if (BITS (4, 7) == 9)
858 rhs
= state
->Reg
[MULRHSReg
];
860 if (MULLHSReg
== MULDESTReg
)
863 dest
= state
->Reg
[MULACCReg
];
864 ARMul_NegZero (state
, dest
);
865 state
->Reg
[MULDESTReg
] = dest
;
867 else if (MULDESTReg
!= 15)
870 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
871 ARMul_NegZero (state
, dest
);
872 state
->Reg
[MULDESTReg
] = dest
;
877 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
878 if (rhs
& (1L << dest
))
881 /* Mult takes this many/2 I cycles. */
882 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
893 case 0x04: /* SUB reg */
895 if (BITS (4, 7) == 0xB)
897 /* STRH immediate offset, no write-back, down, post indexed. */
901 if (BITS (4, 7) == 0xD)
903 Handle_Load_Double (state
, instr
);
906 if (BITS (4, 7) == 0xF)
908 Handle_Store_Double (state
, instr
);
917 case 0x05: /* SUBS reg */
919 if ((BITS (4, 7) & 0x9) == 0x9)
920 /* LDR immediate offset, no write-back, down, post indexed. */
922 /* Fall through to the rest of the instruction decoding. */
928 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
930 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
931 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
941 case 0x06: /* RSB reg */
943 if (BITS (4, 7) == 0xB)
945 /* STRH immediate offset, write-back, down, post indexed. */
955 case 0x07: /* RSBS reg */
957 if ((BITS (4, 7) & 0x9) == 0x9)
958 /* LDR immediate offset, write-back, down, post indexed. */
960 /* Fall through to remainder of instruction decoding. */
966 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
968 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
969 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
979 case 0x08: /* ADD reg */
981 if (BITS (4, 11) == 0xB)
983 /* STRH register offset, no write-back, up, post indexed. */
987 if (BITS (4, 7) == 0xD)
989 Handle_Load_Double (state
, instr
);
992 if (BITS (4, 7) == 0xF)
994 Handle_Store_Double (state
, instr
);
999 if (BITS (4, 7) == 0x9)
1003 ARMul_Icycles (state
,
1004 Multiply64 (state
, instr
, LUNSIGNED
,
1014 case 0x09: /* ADDS reg */
1016 if ((BITS (4, 11) & 0xF9) == 0x9)
1017 /* LDR register offset, no write-back, up, post indexed. */
1019 /* Fall through to remaining instruction decoding. */
1022 if (BITS (4, 7) == 0x9)
1026 ARMul_Icycles (state
,
1027 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
1035 ASSIGNZ (dest
== 0);
1036 if ((lhs
| rhs
) >> 30)
1038 /* Possible C,V,N to set. */
1039 ASSIGNN (NEG (dest
));
1040 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1041 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1052 case 0x0a: /* ADC reg */
1054 if (BITS (4, 11) == 0xB)
1056 /* STRH register offset, write-back, up, post-indexed. */
1060 if (BITS (4, 7) == 0x9)
1064 ARMul_Icycles (state
,
1065 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1071 dest
= LHS
+ rhs
+ CFLAG
;
1075 case 0x0b: /* ADCS reg */
1077 if ((BITS (4, 11) & 0xF9) == 0x9)
1078 /* LDR register offset, write-back, up, post indexed. */
1080 /* Fall through to remaining instruction decoding. */
1081 if (BITS (4, 7) == 0x9)
1085 ARMul_Icycles (state
,
1086 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1093 dest
= lhs
+ rhs
+ CFLAG
;
1094 ASSIGNZ (dest
== 0);
1095 if ((lhs
| rhs
) >> 30)
1097 /* Possible C,V,N to set. */
1098 ASSIGNN (NEG (dest
));
1099 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1100 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1111 case 0x0c: /* SBC reg */
1113 if (BITS (4, 7) == 0xB)
1115 /* STRH immediate offset, no write-back, up post indexed. */
1119 if (BITS (4, 7) == 0xD)
1121 Handle_Load_Double (state
, instr
);
1124 if (BITS (4, 7) == 0xF)
1126 Handle_Store_Double (state
, instr
);
1129 if (BITS (4, 7) == 0x9)
1133 ARMul_Icycles (state
,
1134 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
1140 dest
= LHS
- rhs
- !CFLAG
;
1144 case 0x0d: /* SBCS reg */
1146 if ((BITS (4, 7) & 0x9) == 0x9)
1147 /* LDR immediate offset, no write-back, up, post indexed. */
1150 if (BITS (4, 7) == 0x9)
1154 ARMul_Icycles (state
,
1155 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
1162 dest
= lhs
- rhs
- !CFLAG
;
1163 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1165 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1166 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1176 case 0x0e: /* RSC reg */
1178 if (BITS (4, 7) == 0xB)
1180 /* STRH immediate offset, write-back, up, post indexed. */
1185 if (BITS (4, 7) == 0x9)
1189 ARMul_Icycles (state
,
1190 MultiplyAdd64 (state
, instr
, LSIGNED
,
1196 dest
= rhs
- LHS
- !CFLAG
;
1200 case 0x0f: /* RSCS reg */
1202 if ((BITS (4, 7) & 0x9) == 0x9)
1203 /* LDR immediate offset, write-back, up, post indexed. */
1205 /* Fall through to remaining instruction decoding. */
1207 if (BITS (4, 7) == 0x9)
1211 ARMul_Icycles (state
,
1212 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
1219 dest
= rhs
- lhs
- !CFLAG
;
1221 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1223 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1224 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1234 case 0x10: /* TST reg and MRS CPSR and SWP word. */
1237 if (BIT (4) == 0 && BIT (7) == 1)
1239 /* ElSegundo SMLAxy insn. */
1240 ARMword op1
= state
->Reg
[BITS (0, 3)];
1241 ARMword op2
= state
->Reg
[BITS (8, 11)];
1242 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1256 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
1258 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
1262 if (BITS (4, 11) == 5)
1264 /* ElSegundo QADD insn. */
1265 ARMword op1
= state
->Reg
[BITS (0, 3)];
1266 ARMword op2
= state
->Reg
[BITS (16, 19)];
1267 ARMword result
= op1
+ op2
;
1268 if (AddOverflow (op1
, op2
, result
))
1270 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1273 state
->Reg
[BITS (12, 15)] = result
;
1278 if (BITS (4, 11) == 0xB)
1280 /* STRH register offset, no write-back, down, pre indexed. */
1284 if (BITS (4, 7) == 0xD)
1286 Handle_Load_Double (state
, instr
);
1289 if (BITS (4, 7) == 0xF)
1291 Handle_Store_Double (state
, instr
);
1295 if (BITS (4, 11) == 9)
1302 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1304 INTERNALABORT (temp
);
1305 (void) ARMul_LoadWordN (state
, temp
);
1306 (void) ARMul_LoadWordN (state
, temp
);
1310 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1312 DEST
= ARMul_Align (state
, temp
, dest
);
1315 if (state
->abortSig
|| state
->Aborted
)
1318 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1321 DEST
= ECC
| EINT
| EMODE
;
1329 case 0x11: /* TSTP reg */
1331 if ((BITS (4, 11) & 0xF9) == 0x9)
1332 /* LDR register offset, no write-back, down, pre indexed. */
1334 /* Continue with remaining instruction decode. */
1340 state
->Cpsr
= GETSPSR (state
->Bank
);
1341 ARMul_CPSRAltered (state
);
1353 ARMul_NegZero (state
, dest
);
1357 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
1360 if (BITS (4, 7) == 3)
1366 temp
= (pc
+ 2) | 1;
1370 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1371 state
->Reg
[14] = temp
;
1378 if (BIT (4) == 0 && BIT (7) == 1
1379 && (BIT (5) == 0 || BITS (12, 15) == 0))
1381 /* ElSegundo SMLAWy/SMULWy insn. */
1382 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1383 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1384 unsigned long long result
;
1388 if (op1
& 0x80000000)
1393 result
= (op1
* op2
) >> 16;
1397 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1399 if (AddOverflow (result
, Rn
, result
+ Rn
))
1403 state
->Reg
[BITS (16, 19)] = result
;
1407 if (BITS (4, 11) == 5)
1409 /* ElSegundo QSUB insn. */
1410 ARMword op1
= state
->Reg
[BITS (0, 3)];
1411 ARMword op2
= state
->Reg
[BITS (16, 19)];
1412 ARMword result
= op1
- op2
;
1414 if (SubOverflow (op1
, op2
, result
))
1416 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1420 state
->Reg
[BITS (12, 15)] = result
;
1425 if (BITS (4, 11) == 0xB)
1427 /* STRH register offset, write-back, down, pre indexed. */
1431 if (BITS (4, 27) == 0x12FFF1)
1434 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1437 if (BITS (4, 7) == 0xD)
1439 Handle_Load_Double (state
, instr
);
1442 if (BITS (4, 7) == 0xF)
1444 Handle_Store_Double (state
, instr
);
1450 if (BITS (4, 7) == 0x7)
1453 extern int SWI_vector_installed
;
1455 /* Hardware is allowed to optionally override this
1456 instruction and treat it as a breakpoint. Since
1457 this is a simulator not hardware, we take the position
1458 that if a SWI vector was not installed, then an Abort
1459 vector was probably not installed either, and so
1460 normally this instruction would be ignored, even if an
1461 Abort is generated. This is a bad thing, since GDB
1462 uses this instruction for its breakpoints (at least in
1463 Thumb mode it does). So intercept the instruction here
1464 and generate a breakpoint SWI instead. */
1465 if (! SWI_vector_installed
)
1466 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1469 /* BKPT - normally this will cause an abort, but on the
1470 XScale we must check the DCSR. */
1471 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
1472 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
1476 /* Force the next instruction to be refetched. */
1477 state
->NextInstr
= RESUME
;
1483 /* MSR reg to CPSR. */
1487 /* Don't allow TBIT to be set by MSR. */
1490 ARMul_FixCPSR (state
, instr
, temp
);
1497 case 0x13: /* TEQP reg */
1499 if ((BITS (4, 11) & 0xF9) == 0x9)
1500 /* LDR register offset, write-back, down, pre indexed. */
1502 /* Continue with remaining instruction decode. */
1508 state
->Cpsr
= GETSPSR (state
->Bank
);
1509 ARMul_CPSRAltered (state
);
1521 ARMul_NegZero (state
, dest
);
1525 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
1528 if (BIT (4) == 0 && BIT (7) == 1)
1530 /* ElSegundo SMLALxy insn. */
1531 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1532 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1533 unsigned long long dest
;
1534 unsigned long long result
;
1547 dest
= (unsigned long long) state
->Reg
[BITS (16, 19)] << 32;
1548 dest
|= state
->Reg
[BITS (12, 15)];
1550 state
->Reg
[BITS (12, 15)] = dest
;
1551 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1555 if (BITS (4, 11) == 5)
1557 /* ElSegundo QDADD insn. */
1558 ARMword op1
= state
->Reg
[BITS (0, 3)];
1559 ARMword op2
= state
->Reg
[BITS (16, 19)];
1560 ARMword op2d
= op2
+ op2
;
1563 if (AddOverflow (op2
, op2
, op2d
))
1566 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1569 result
= op1
+ op2d
;
1570 if (AddOverflow (op1
, op2d
, result
))
1573 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1576 state
->Reg
[BITS (12, 15)] = result
;
1581 if (BITS (4, 7) == 0xB)
1583 /* STRH immediate offset, no write-back, down, pre indexed. */
1587 if (BITS (4, 7) == 0xD)
1589 Handle_Load_Double (state
, instr
);
1592 if (BITS (4, 7) == 0xF)
1594 Handle_Store_Double (state
, instr
);
1598 if (BITS (4, 11) == 9)
1605 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1607 INTERNALABORT (temp
);
1608 (void) ARMul_LoadByte (state
, temp
);
1609 (void) ARMul_LoadByte (state
, temp
);
1613 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1614 if (state
->abortSig
|| state
->Aborted
)
1617 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1621 DEST
= GETSPSR (state
->Bank
);
1628 case 0x15: /* CMPP reg. */
1630 if ((BITS (4, 7) & 0x9) == 0x9)
1631 /* LDR immediate offset, no write-back, down, pre indexed. */
1633 /* Continue with remaining instruction decode. */
1639 state
->Cpsr
= GETSPSR (state
->Bank
);
1640 ARMul_CPSRAltered (state
);
1653 ARMul_NegZero (state
, dest
);
1654 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1656 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1657 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1667 case 0x16: /* CMN reg and MSR reg to SPSR */
1670 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1672 /* ElSegundo SMULxy insn. */
1673 ARMword op1
= state
->Reg
[BITS (0, 3)];
1674 ARMword op2
= state
->Reg
[BITS (8, 11)];
1675 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1688 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1692 if (BITS (4, 11) == 5)
1694 /* ElSegundo QDSUB insn. */
1695 ARMword op1
= state
->Reg
[BITS (0, 3)];
1696 ARMword op2
= state
->Reg
[BITS (16, 19)];
1697 ARMword op2d
= op2
+ op2
;
1700 if (AddOverflow (op2
, op2
, op2d
))
1703 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1706 result
= op1
- op2d
;
1707 if (SubOverflow (op1
, op2d
, result
))
1710 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1713 state
->Reg
[BITS (12, 15)] = result
;
1720 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1722 /* ARM5 CLZ insn. */
1723 ARMword op1
= state
->Reg
[BITS (0, 3)];
1727 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1730 state
->Reg
[BITS (12, 15)] = result
;
1735 if (BITS (4, 7) == 0xB)
1737 /* STRH immediate offset, write-back, down, pre indexed. */
1741 if (BITS (4, 7) == 0xD)
1743 Handle_Load_Double (state
, instr
);
1746 if (BITS (4, 7) == 0xF)
1748 Handle_Store_Double (state
, instr
);
1756 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1764 case 0x17: /* CMNP reg */
1766 if ((BITS (4, 7) & 0x9) == 0x9)
1767 /* LDR immediate offset, write-back, down, pre indexed. */
1769 /* Continue with remaining instruction decoding. */
1774 state
->Cpsr
= GETSPSR (state
->Bank
);
1775 ARMul_CPSRAltered (state
);
1789 ASSIGNZ (dest
== 0);
1790 if ((lhs
| rhs
) >> 30)
1792 /* Possible C,V,N to set. */
1793 ASSIGNN (NEG (dest
));
1794 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1795 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1806 case 0x18: /* ORR reg */
1808 if (BITS (4, 11) == 0xB)
1810 /* STRH register offset, no write-back, up, pre indexed. */
1814 if (BITS (4, 7) == 0xD)
1816 Handle_Load_Double (state
, instr
);
1819 if (BITS (4, 7) == 0xF)
1821 Handle_Store_Double (state
, instr
);
1830 case 0x19: /* ORRS reg */
1832 if ((BITS (4, 11) & 0xF9) == 0x9)
1833 /* LDR register offset, no write-back, up, pre indexed. */
1835 /* Continue with remaining instruction decoding. */
1842 case 0x1a: /* MOV reg */
1844 if (BITS (4, 11) == 0xB)
1846 /* STRH register offset, write-back, up, pre indexed. */
1850 if (BITS (4, 7) == 0xD)
1852 Handle_Load_Double (state
, instr
);
1855 if (BITS (4, 7) == 0xF)
1857 Handle_Store_Double (state
, instr
);
1865 case 0x1b: /* MOVS reg */
1867 if ((BITS (4, 11) & 0xF9) == 0x9)
1868 /* LDR register offset, write-back, up, pre indexed. */
1870 /* Continue with remaining instruction decoding. */
1876 case 0x1c: /* BIC reg */
1878 if (BITS (4, 7) == 0xB)
1880 /* STRH immediate offset, no write-back, up, pre indexed. */
1884 if (BITS (4, 7) == 0xD)
1886 Handle_Load_Double (state
, instr
);
1889 else if (BITS (4, 7) == 0xF)
1891 Handle_Store_Double (state
, instr
);
1900 case 0x1d: /* BICS reg */
1902 if ((BITS (4, 7) & 0x9) == 0x9)
1903 /* LDR immediate offset, no write-back, up, pre indexed. */
1905 /* Continue with instruction decoding. */
1912 case 0x1e: /* MVN reg */
1914 if (BITS (4, 7) == 0xB)
1916 /* STRH immediate offset, write-back, up, pre indexed. */
1920 if (BITS (4, 7) == 0xD)
1922 Handle_Load_Double (state
, instr
);
1925 if (BITS (4, 7) == 0xF)
1927 Handle_Store_Double (state
, instr
);
1935 case 0x1f: /* MVNS reg */
1937 if ((BITS (4, 7) & 0x9) == 0x9)
1938 /* LDR immediate offset, write-back, up, pre indexed. */
1940 /* Continue instruction decoding. */
1947 /* Data Processing Immediate RHS Instructions. */
1949 case 0x20: /* AND immed */
1950 dest
= LHS
& DPImmRHS
;
1954 case 0x21: /* ANDS immed */
1960 case 0x22: /* EOR immed */
1961 dest
= LHS
^ DPImmRHS
;
1965 case 0x23: /* EORS immed */
1971 case 0x24: /* SUB immed */
1972 dest
= LHS
- DPImmRHS
;
1976 case 0x25: /* SUBS immed */
1981 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1983 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1984 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1994 case 0x26: /* RSB immed */
1995 dest
= DPImmRHS
- LHS
;
1999 case 0x27: /* RSBS immed */
2004 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2006 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2007 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2017 case 0x28: /* ADD immed */
2018 dest
= LHS
+ DPImmRHS
;
2022 case 0x29: /* ADDS immed */
2026 ASSIGNZ (dest
== 0);
2028 if ((lhs
| rhs
) >> 30)
2030 /* Possible C,V,N to set. */
2031 ASSIGNN (NEG (dest
));
2032 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2033 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2044 case 0x2a: /* ADC immed */
2045 dest
= LHS
+ DPImmRHS
+ CFLAG
;
2049 case 0x2b: /* ADCS immed */
2052 dest
= lhs
+ rhs
+ CFLAG
;
2053 ASSIGNZ (dest
== 0);
2054 if ((lhs
| rhs
) >> 30)
2056 /* Possible C,V,N to set. */
2057 ASSIGNN (NEG (dest
));
2058 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2059 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2070 case 0x2c: /* SBC immed */
2071 dest
= LHS
- DPImmRHS
- !CFLAG
;
2075 case 0x2d: /* SBCS immed */
2078 dest
= lhs
- rhs
- !CFLAG
;
2079 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2081 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2082 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2092 case 0x2e: /* RSC immed */
2093 dest
= DPImmRHS
- LHS
- !CFLAG
;
2097 case 0x2f: /* RSCS immed */
2100 dest
= rhs
- lhs
- !CFLAG
;
2101 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2103 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2104 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2114 case 0x30: /* TST immed */
2118 case 0x31: /* TSTP immed */
2123 state
->Cpsr
= GETSPSR (state
->Bank
);
2124 ARMul_CPSRAltered (state
);
2126 temp
= LHS
& DPImmRHS
;
2135 ARMul_NegZero (state
, dest
);
2139 case 0x32: /* TEQ immed and MSR immed to CPSR */
2141 /* MSR immed to CPSR. */
2142 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
2147 case 0x33: /* TEQP immed */
2152 state
->Cpsr
= GETSPSR (state
->Bank
);
2153 ARMul_CPSRAltered (state
);
2155 temp
= LHS
^ DPImmRHS
;
2161 DPSImmRHS
; /* TEQ immed */
2163 ARMul_NegZero (state
, dest
);
2167 case 0x34: /* CMP immed */
2171 case 0x35: /* CMPP immed */
2176 state
->Cpsr
= GETSPSR (state
->Bank
);
2177 ARMul_CPSRAltered (state
);
2179 temp
= LHS
- DPImmRHS
;
2190 ARMul_NegZero (state
, dest
);
2192 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2194 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2195 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2205 case 0x36: /* CMN immed and MSR immed to SPSR */
2207 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
2212 case 0x37: /* CMNP immed. */
2217 state
->Cpsr
= GETSPSR (state
->Bank
);
2218 ARMul_CPSRAltered (state
);
2220 temp
= LHS
+ DPImmRHS
;
2231 ASSIGNZ (dest
== 0);
2232 if ((lhs
| rhs
) >> 30)
2234 /* Possible C,V,N to set. */
2235 ASSIGNN (NEG (dest
));
2236 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2237 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2248 case 0x38: /* ORR immed. */
2249 dest
= LHS
| DPImmRHS
;
2253 case 0x39: /* ORRS immed. */
2259 case 0x3a: /* MOV immed. */
2264 case 0x3b: /* MOVS immed. */
2269 case 0x3c: /* BIC immed. */
2270 dest
= LHS
& ~DPImmRHS
;
2274 case 0x3d: /* BICS immed. */
2280 case 0x3e: /* MVN immed. */
2285 case 0x3f: /* MVNS immed. */
2291 /* Single Data Transfer Immediate RHS Instructions. */
2293 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2295 if (StoreWord (state
, instr
, lhs
))
2296 LSBase
= lhs
- LSImmRHS
;
2299 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2301 if (LoadWord (state
, instr
, lhs
))
2302 LSBase
= lhs
- LSImmRHS
;
2305 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2306 UNDEF_LSRBaseEQDestWb
;
2309 temp
= lhs
- LSImmRHS
;
2310 state
->NtransSig
= LOW
;
2311 if (StoreWord (state
, instr
, lhs
))
2313 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2316 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2317 UNDEF_LSRBaseEQDestWb
;
2320 state
->NtransSig
= LOW
;
2321 if (LoadWord (state
, instr
, lhs
))
2322 LSBase
= lhs
- LSImmRHS
;
2323 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2326 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2328 if (StoreByte (state
, instr
, lhs
))
2329 LSBase
= lhs
- LSImmRHS
;
2332 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2334 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2335 LSBase
= lhs
- LSImmRHS
;
2338 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2339 UNDEF_LSRBaseEQDestWb
;
2342 state
->NtransSig
= LOW
;
2343 if (StoreByte (state
, instr
, lhs
))
2344 LSBase
= lhs
- LSImmRHS
;
2345 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2348 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2349 UNDEF_LSRBaseEQDestWb
;
2352 state
->NtransSig
= LOW
;
2353 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2354 LSBase
= lhs
- LSImmRHS
;
2355 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2358 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2360 if (StoreWord (state
, instr
, lhs
))
2361 LSBase
= lhs
+ LSImmRHS
;
2364 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2366 if (LoadWord (state
, instr
, lhs
))
2367 LSBase
= lhs
+ LSImmRHS
;
2370 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2371 UNDEF_LSRBaseEQDestWb
;
2374 state
->NtransSig
= LOW
;
2375 if (StoreWord (state
, instr
, lhs
))
2376 LSBase
= lhs
+ LSImmRHS
;
2377 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2380 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2381 UNDEF_LSRBaseEQDestWb
;
2384 state
->NtransSig
= LOW
;
2385 if (LoadWord (state
, instr
, lhs
))
2386 LSBase
= lhs
+ LSImmRHS
;
2387 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2390 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2392 if (StoreByte (state
, instr
, lhs
))
2393 LSBase
= lhs
+ LSImmRHS
;
2396 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2398 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2399 LSBase
= lhs
+ LSImmRHS
;
2402 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2403 UNDEF_LSRBaseEQDestWb
;
2406 state
->NtransSig
= LOW
;
2407 if (StoreByte (state
, instr
, lhs
))
2408 LSBase
= lhs
+ LSImmRHS
;
2409 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2412 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2413 UNDEF_LSRBaseEQDestWb
;
2416 state
->NtransSig
= LOW
;
2417 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2418 LSBase
= lhs
+ LSImmRHS
;
2419 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2423 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2424 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2427 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2428 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2431 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2432 UNDEF_LSRBaseEQDestWb
;
2434 temp
= LHS
- LSImmRHS
;
2435 if (StoreWord (state
, instr
, temp
))
2439 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2440 UNDEF_LSRBaseEQDestWb
;
2442 temp
= LHS
- LSImmRHS
;
2443 if (LoadWord (state
, instr
, temp
))
2447 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2448 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2451 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2452 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2455 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2456 UNDEF_LSRBaseEQDestWb
;
2458 temp
= LHS
- LSImmRHS
;
2459 if (StoreByte (state
, instr
, temp
))
2463 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2464 UNDEF_LSRBaseEQDestWb
;
2466 temp
= LHS
- LSImmRHS
;
2467 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2471 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2472 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2475 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2476 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2479 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2480 UNDEF_LSRBaseEQDestWb
;
2482 temp
= LHS
+ LSImmRHS
;
2483 if (StoreWord (state
, instr
, temp
))
2487 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2488 UNDEF_LSRBaseEQDestWb
;
2490 temp
= LHS
+ LSImmRHS
;
2491 if (LoadWord (state
, instr
, temp
))
2495 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2496 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2499 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2500 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2503 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2504 UNDEF_LSRBaseEQDestWb
;
2506 temp
= LHS
+ LSImmRHS
;
2507 if (StoreByte (state
, instr
, temp
))
2511 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2512 UNDEF_LSRBaseEQDestWb
;
2514 temp
= LHS
+ LSImmRHS
;
2515 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2520 /* Single Data Transfer Register RHS Instructions. */
2522 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2525 ARMul_UndefInstr (state
, instr
);
2528 UNDEF_LSRBaseEQOffWb
;
2529 UNDEF_LSRBaseEQDestWb
;
2533 if (StoreWord (state
, instr
, lhs
))
2534 LSBase
= lhs
- LSRegRHS
;
2537 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2540 ARMul_UndefInstr (state
, instr
);
2543 UNDEF_LSRBaseEQOffWb
;
2544 UNDEF_LSRBaseEQDestWb
;
2548 temp
= lhs
- LSRegRHS
;
2549 if (LoadWord (state
, instr
, lhs
))
2553 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2556 ARMul_UndefInstr (state
, instr
);
2559 UNDEF_LSRBaseEQOffWb
;
2560 UNDEF_LSRBaseEQDestWb
;
2564 state
->NtransSig
= LOW
;
2565 if (StoreWord (state
, instr
, lhs
))
2566 LSBase
= lhs
- LSRegRHS
;
2567 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2570 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2573 ARMul_UndefInstr (state
, instr
);
2576 UNDEF_LSRBaseEQOffWb
;
2577 UNDEF_LSRBaseEQDestWb
;
2581 temp
= lhs
- LSRegRHS
;
2582 state
->NtransSig
= LOW
;
2583 if (LoadWord (state
, instr
, lhs
))
2585 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2588 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2591 ARMul_UndefInstr (state
, instr
);
2594 UNDEF_LSRBaseEQOffWb
;
2595 UNDEF_LSRBaseEQDestWb
;
2599 if (StoreByte (state
, instr
, lhs
))
2600 LSBase
= lhs
- LSRegRHS
;
2603 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2606 ARMul_UndefInstr (state
, instr
);
2609 UNDEF_LSRBaseEQOffWb
;
2610 UNDEF_LSRBaseEQDestWb
;
2614 temp
= lhs
- LSRegRHS
;
2615 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2619 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2622 ARMul_UndefInstr (state
, instr
);
2625 UNDEF_LSRBaseEQOffWb
;
2626 UNDEF_LSRBaseEQDestWb
;
2630 state
->NtransSig
= LOW
;
2631 if (StoreByte (state
, instr
, lhs
))
2632 LSBase
= lhs
- LSRegRHS
;
2633 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2636 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2639 ARMul_UndefInstr (state
, instr
);
2642 UNDEF_LSRBaseEQOffWb
;
2643 UNDEF_LSRBaseEQDestWb
;
2647 temp
= lhs
- LSRegRHS
;
2648 state
->NtransSig
= LOW
;
2649 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2651 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2654 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2657 ARMul_UndefInstr (state
, instr
);
2660 UNDEF_LSRBaseEQOffWb
;
2661 UNDEF_LSRBaseEQDestWb
;
2665 if (StoreWord (state
, instr
, lhs
))
2666 LSBase
= lhs
+ LSRegRHS
;
2669 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2672 ARMul_UndefInstr (state
, instr
);
2675 UNDEF_LSRBaseEQOffWb
;
2676 UNDEF_LSRBaseEQDestWb
;
2680 temp
= lhs
+ LSRegRHS
;
2681 if (LoadWord (state
, instr
, lhs
))
2685 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2688 ARMul_UndefInstr (state
, instr
);
2691 UNDEF_LSRBaseEQOffWb
;
2692 UNDEF_LSRBaseEQDestWb
;
2696 state
->NtransSig
= LOW
;
2697 if (StoreWord (state
, instr
, lhs
))
2698 LSBase
= lhs
+ LSRegRHS
;
2699 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2702 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2705 ARMul_UndefInstr (state
, instr
);
2708 UNDEF_LSRBaseEQOffWb
;
2709 UNDEF_LSRBaseEQDestWb
;
2713 temp
= lhs
+ LSRegRHS
;
2714 state
->NtransSig
= LOW
;
2715 if (LoadWord (state
, instr
, lhs
))
2717 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2720 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2723 ARMul_UndefInstr (state
, instr
);
2726 UNDEF_LSRBaseEQOffWb
;
2727 UNDEF_LSRBaseEQDestWb
;
2731 if (StoreByte (state
, instr
, lhs
))
2732 LSBase
= lhs
+ LSRegRHS
;
2735 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
2738 ARMul_UndefInstr (state
, instr
);
2741 UNDEF_LSRBaseEQOffWb
;
2742 UNDEF_LSRBaseEQDestWb
;
2746 temp
= lhs
+ LSRegRHS
;
2747 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2751 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
2754 ARMul_UndefInstr (state
, instr
);
2757 UNDEF_LSRBaseEQOffWb
;
2758 UNDEF_LSRBaseEQDestWb
;
2762 state
->NtransSig
= LOW
;
2763 if (StoreByte (state
, instr
, lhs
))
2764 LSBase
= lhs
+ LSRegRHS
;
2765 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2768 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
2771 ARMul_UndefInstr (state
, instr
);
2774 UNDEF_LSRBaseEQOffWb
;
2775 UNDEF_LSRBaseEQDestWb
;
2779 temp
= lhs
+ LSRegRHS
;
2780 state
->NtransSig
= LOW
;
2781 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2783 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2787 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
2790 ARMul_UndefInstr (state
, instr
);
2793 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2796 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
2799 ARMul_UndefInstr (state
, instr
);
2802 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2805 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
2808 ARMul_UndefInstr (state
, instr
);
2811 UNDEF_LSRBaseEQOffWb
;
2812 UNDEF_LSRBaseEQDestWb
;
2815 temp
= LHS
- LSRegRHS
;
2816 if (StoreWord (state
, instr
, temp
))
2820 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
2823 ARMul_UndefInstr (state
, instr
);
2826 UNDEF_LSRBaseEQOffWb
;
2827 UNDEF_LSRBaseEQDestWb
;
2830 temp
= LHS
- LSRegRHS
;
2831 if (LoadWord (state
, instr
, temp
))
2835 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
2838 ARMul_UndefInstr (state
, instr
);
2841 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2844 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
2847 ARMul_UndefInstr (state
, instr
);
2850 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2853 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
2856 ARMul_UndefInstr (state
, instr
);
2859 UNDEF_LSRBaseEQOffWb
;
2860 UNDEF_LSRBaseEQDestWb
;
2863 temp
= LHS
- LSRegRHS
;
2864 if (StoreByte (state
, instr
, temp
))
2868 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
2871 ARMul_UndefInstr (state
, instr
);
2874 UNDEF_LSRBaseEQOffWb
;
2875 UNDEF_LSRBaseEQDestWb
;
2878 temp
= LHS
- LSRegRHS
;
2879 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2883 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
2886 ARMul_UndefInstr (state
, instr
);
2889 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2892 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
2895 ARMul_UndefInstr (state
, instr
);
2898 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2901 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
2904 ARMul_UndefInstr (state
, instr
);
2907 UNDEF_LSRBaseEQOffWb
;
2908 UNDEF_LSRBaseEQDestWb
;
2911 temp
= LHS
+ LSRegRHS
;
2912 if (StoreWord (state
, instr
, temp
))
2916 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
2919 ARMul_UndefInstr (state
, instr
);
2922 UNDEF_LSRBaseEQOffWb
;
2923 UNDEF_LSRBaseEQDestWb
;
2926 temp
= LHS
+ LSRegRHS
;
2927 if (LoadWord (state
, instr
, temp
))
2931 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
2934 ARMul_UndefInstr (state
, instr
);
2937 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2940 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
2943 ARMul_UndefInstr (state
, instr
);
2946 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2949 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
2952 ARMul_UndefInstr (state
, instr
);
2955 UNDEF_LSRBaseEQOffWb
;
2956 UNDEF_LSRBaseEQDestWb
;
2959 temp
= LHS
+ LSRegRHS
;
2960 if (StoreByte (state
, instr
, temp
))
2964 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
2967 /* Check for the special breakpoint opcode.
2968 This value should correspond to the value defined
2969 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2970 if (BITS (0, 19) == 0xfdefe)
2972 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2973 ARMul_Abort (state
, ARMul_SWIV
);
2976 ARMul_UndefInstr (state
, instr
);
2979 UNDEF_LSRBaseEQOffWb
;
2980 UNDEF_LSRBaseEQDestWb
;
2983 temp
= LHS
+ LSRegRHS
;
2984 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2989 /* Multiple Data Transfer Instructions. */
2991 case 0x80: /* Store, No WriteBack, Post Dec. */
2992 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2995 case 0x81: /* Load, No WriteBack, Post Dec. */
2996 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2999 case 0x82: /* Store, WriteBack, Post Dec. */
3000 temp
= LSBase
- LSMNumRegs
;
3001 STOREMULT (instr
, temp
+ 4L, temp
);
3004 case 0x83: /* Load, WriteBack, Post Dec. */
3005 temp
= LSBase
- LSMNumRegs
;
3006 LOADMULT (instr
, temp
+ 4L, temp
);
3009 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
3010 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3013 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
3014 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
3017 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
3018 temp
= LSBase
- LSMNumRegs
;
3019 STORESMULT (instr
, temp
+ 4L, temp
);
3022 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3023 temp
= LSBase
- LSMNumRegs
;
3024 LOADSMULT (instr
, temp
+ 4L, temp
);
3027 case 0x88: /* Store, No WriteBack, Post Inc. */
3028 STOREMULT (instr
, LSBase
, 0L);
3031 case 0x89: /* Load, No WriteBack, Post Inc. */
3032 LOADMULT (instr
, LSBase
, 0L);
3035 case 0x8a: /* Store, WriteBack, Post Inc. */
3037 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
3040 case 0x8b: /* Load, WriteBack, Post Inc. */
3042 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
3045 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3046 STORESMULT (instr
, LSBase
, 0L);
3049 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3050 LOADSMULT (instr
, LSBase
, 0L);
3053 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3055 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
3058 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3060 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
3063 case 0x90: /* Store, No WriteBack, Pre Dec. */
3064 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3067 case 0x91: /* Load, No WriteBack, Pre Dec. */
3068 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3071 case 0x92: /* Store, WriteBack, Pre Dec. */
3072 temp
= LSBase
- LSMNumRegs
;
3073 STOREMULT (instr
, temp
, temp
);
3076 case 0x93: /* Load, WriteBack, Pre Dec. */
3077 temp
= LSBase
- LSMNumRegs
;
3078 LOADMULT (instr
, temp
, temp
);
3081 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3082 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3085 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3086 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
3089 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3090 temp
= LSBase
- LSMNumRegs
;
3091 STORESMULT (instr
, temp
, temp
);
3094 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3095 temp
= LSBase
- LSMNumRegs
;
3096 LOADSMULT (instr
, temp
, temp
);
3099 case 0x98: /* Store, No WriteBack, Pre Inc. */
3100 STOREMULT (instr
, LSBase
+ 4L, 0L);
3103 case 0x99: /* Load, No WriteBack, Pre Inc. */
3104 LOADMULT (instr
, LSBase
+ 4L, 0L);
3107 case 0x9a: /* Store, WriteBack, Pre Inc. */
3109 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3112 case 0x9b: /* Load, WriteBack, Pre Inc. */
3114 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3117 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3118 STORESMULT (instr
, LSBase
+ 4L, 0L);
3121 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3122 LOADSMULT (instr
, LSBase
+ 4L, 0L);
3125 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3127 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3130 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3132 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
3136 /* Branch forward. */
3145 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3150 /* Branch backward. */
3159 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3164 /* Branch and Link forward. */
3173 /* Put PC into Link. */
3175 state
->Reg
[14] = pc
+ 4;
3177 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3179 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
3184 /* Branch and Link backward. */
3193 /* Put PC into Link. */
3195 state
->Reg
[14] = pc
+ 4;
3197 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
3199 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
3204 /* Co-Processor Data Transfers. */
3208 /* Reading from R15 is UNPREDICTABLE. */
3209 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3210 ARMul_UndefInstr (state
, instr
);
3211 /* Is access to coprocessor 0 allowed ? */
3212 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3213 ARMul_UndefInstr (state
, instr
);
3214 /* Special treatment for XScale coprocessors. */
3215 else if (state
->is_XScale
)
3217 /* Only opcode 0 is supported. */
3218 if (BITS (4, 7) != 0x00)
3219 ARMul_UndefInstr (state
, instr
);
3220 /* Only coporcessor 0 is supported. */
3221 else if (CPNum
!= 0x00)
3222 ARMul_UndefInstr (state
, instr
);
3223 /* Only accumulator 0 is supported. */
3224 else if (BITS (0, 3) != 0x00)
3225 ARMul_UndefInstr (state
, instr
);
3228 /* XScale MAR insn. Move two registers into accumulator. */
3229 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3230 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3234 /* FIXME: Not sure what to do for other v5 processors. */
3235 ARMul_UndefInstr (state
, instr
);
3240 case 0xc0: /* Store , No WriteBack , Post Dec. */
3241 ARMul_STC (state
, instr
, LHS
);
3247 /* Writes to R15 are UNPREDICATABLE. */
3248 if (DESTReg
== 15 || LHSReg
== 15)
3249 ARMul_UndefInstr (state
, instr
);
3250 /* Is access to the coprocessor allowed ? */
3251 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3252 ARMul_UndefInstr (state
, instr
);
3253 /* Special handling for XScale coprcoessors. */
3254 else if (state
->is_XScale
)
3256 /* Only opcode 0 is supported. */
3257 if (BITS (4, 7) != 0x00)
3258 ARMul_UndefInstr (state
, instr
);
3259 /* Only coprocessor 0 is supported. */
3260 else if (CPNum
!= 0x00)
3261 ARMul_UndefInstr (state
, instr
);
3262 /* Only accumulator 0 is supported. */
3263 else if (BITS (0, 3) != 0x00)
3264 ARMul_UndefInstr (state
, instr
);
3267 /* XScale MRA insn. Move accumulator into two registers. */
3268 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3273 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3274 state
->Reg
[BITS (16, 19)] = t1
;
3279 /* FIXME: Not sure what to do for other v5 processors. */
3280 ARMul_UndefInstr (state
, instr
);
3285 case 0xc1: /* Load , No WriteBack , Post Dec. */
3286 ARMul_LDC (state
, instr
, LHS
);
3290 case 0xc6: /* Store , WriteBack , Post Dec. */
3292 state
->Base
= lhs
- LSCOff
;
3293 ARMul_STC (state
, instr
, lhs
);
3297 case 0xc7: /* Load , WriteBack , Post Dec. */
3299 state
->Base
= lhs
- LSCOff
;
3300 ARMul_LDC (state
, instr
, lhs
);
3304 case 0xcc: /* Store , No WriteBack , Post Inc. */
3305 ARMul_STC (state
, instr
, LHS
);
3309 case 0xcd: /* Load , No WriteBack , Post Inc. */
3310 ARMul_LDC (state
, instr
, LHS
);
3314 case 0xce: /* Store , WriteBack , Post Inc. */
3316 state
->Base
= lhs
+ LSCOff
;
3317 ARMul_STC (state
, instr
, LHS
);
3321 case 0xcf: /* Load , WriteBack , Post Inc. */
3323 state
->Base
= lhs
+ LSCOff
;
3324 ARMul_LDC (state
, instr
, LHS
);
3328 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3329 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3333 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3334 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3338 case 0xd6: /* Store , WriteBack , Pre Dec. */
3341 ARMul_STC (state
, instr
, lhs
);
3345 case 0xd7: /* Load , WriteBack , Pre Dec. */
3348 ARMul_LDC (state
, instr
, lhs
);
3352 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3353 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3357 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3358 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3362 case 0xde: /* Store , WriteBack , Pre Inc. */
3365 ARMul_STC (state
, instr
, lhs
);
3369 case 0xdf: /* Load , WriteBack , Pre Inc. */
3372 ARMul_LDC (state
, instr
, lhs
);
3376 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3379 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
3381 ARMul_UndefInstr (state
, instr
);
3384 if (state
->is_XScale
)
3385 switch (BITS (18, 19))
3388 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3390 /* XScale MIA instruction. Signed multiplication of
3391 two 32 bit values and addition to 40 bit accumulator. */
3392 long long Rm
= state
->Reg
[MULLHSReg
];
3393 long long Rs
= state
->Reg
[MULACCReg
];
3399 state
->Accumulator
+= Rm
* Rs
;
3405 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3407 /* XScale MIAPH instruction. */
3408 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3409 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3410 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3411 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3426 state
->Accumulator
+= t5
;
3431 state
->Accumulator
+= t5
;
3437 if (BITS (4, 11) == 1)
3439 /* XScale MIAxy instruction. */
3445 t1
= state
->Reg
[MULLHSReg
] >> 16;
3447 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3450 t2
= state
->Reg
[MULACCReg
] >> 16;
3452 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3462 state
->Accumulator
+= t5
;
3486 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3488 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3489 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3493 ARMul_MCR (state
, instr
, DEST
);
3497 ARMul_CDP (state
, instr
);
3501 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3513 temp
= ARMul_MRC (state
, instr
);
3516 ASSIGNN ((temp
& NBIT
) != 0);
3517 ASSIGNZ ((temp
& ZBIT
) != 0);
3518 ASSIGNC ((temp
& CBIT
) != 0);
3519 ASSIGNV ((temp
& VBIT
) != 0);
3526 ARMul_CDP (state
, instr
);
3530 /* SWI instruction. */
3547 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3549 /* A prefetch abort. */
3550 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
3551 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3555 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3556 ARMul_Abort (state
, ARMul_SWIV
);
3566 #ifdef NEED_UI_LOOP_HOOK
3567 if (deprecated_ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3569 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3570 deprecated_ui_loop_hook (0);
3572 #endif /* NEED_UI_LOOP_HOOK */
3574 if (state
->Emulate
== ONCE
)
3575 state
->Emulate
= STOP
;
3576 /* If we have changed mode, allow the PC to advance before stopping. */
3577 else if (state
->Emulate
== CHANGEMODE
)
3579 else if (state
->Emulate
!= RUN
)
3582 while (!stop_simulator
);
3584 state
->decoded
= decoded
;
3585 state
->loaded
= loaded
;
3591 /* This routine evaluates most Data Processing register RHS's with the S
3592 bit clear. It is intended to be called from the macro DPRegRHS, which
3593 filters the common case of an unshifted register with in line code. */
3596 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3598 ARMword shamt
, base
;
3603 /* Shift amount in a register. */
3608 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3611 base
= state
->Reg
[base
];
3612 ARMul_Icycles (state
, 1, 0L);
3613 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3614 switch ((int) BITS (5, 6))
3619 else if (shamt
>= 32)
3622 return (base
<< shamt
);
3626 else if (shamt
>= 32)
3629 return (base
>> shamt
);
3633 else if (shamt
>= 32)
3634 return ((ARMword
) ((long int) base
>> 31L));
3636 return ((ARMword
) ((long int) base
>> (int) shamt
));
3642 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3647 /* Shift amount is a constant. */
3650 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3653 base
= state
->Reg
[base
];
3654 shamt
= BITS (7, 11);
3655 switch ((int) BITS (5, 6))
3658 return (base
<< shamt
);
3663 return (base
>> shamt
);
3666 return ((ARMword
) ((long int) base
>> 31L));
3668 return ((ARMword
) ((long int) base
>> (int) shamt
));
3672 return ((base
>> 1) | (CFLAG
<< 31));
3674 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3681 /* This routine evaluates most Logical Data Processing register RHS's
3682 with the S bit set. It is intended to be called from the macro
3683 DPSRegRHS, which filters the common case of an unshifted register
3684 with in line code. */
3687 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3689 ARMword shamt
, base
;
3694 /* Shift amount in a register. */
3699 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3702 base
= state
->Reg
[base
];
3703 ARMul_Icycles (state
, 1, 0L);
3704 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3705 switch ((int) BITS (5, 6))
3710 else if (shamt
== 32)
3715 else if (shamt
> 32)
3722 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3723 return (base
<< shamt
);
3728 else if (shamt
== 32)
3730 ASSIGNC (base
>> 31);
3733 else if (shamt
> 32)
3740 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3741 return (base
>> shamt
);
3746 else if (shamt
>= 32)
3748 ASSIGNC (base
>> 31L);
3749 return ((ARMword
) ((long int) base
>> 31L));
3753 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3754 return ((ARMword
) ((long int) base
>> (int) shamt
));
3762 ASSIGNC (base
>> 31);
3767 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3768 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3774 /* Shift amount is a constant. */
3777 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3780 base
= state
->Reg
[base
];
3781 shamt
= BITS (7, 11);
3783 switch ((int) BITS (5, 6))
3786 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3787 return (base
<< shamt
);
3791 ASSIGNC (base
>> 31);
3796 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3797 return (base
>> shamt
);
3802 ASSIGNC (base
>> 31L);
3803 return ((ARMword
) ((long int) base
>> 31L));
3807 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3808 return ((ARMword
) ((long int) base
>> (int) shamt
));
3816 return ((base
>> 1) | (shamt
<< 31));
3820 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3821 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3829 /* This routine handles writes to register 15 when the S bit is not set. */
3832 WriteR15 (ARMul_State
* state
, ARMword src
)
3834 /* The ARM documentation states that the two least significant bits
3835 are discarded when setting PC, except in the cases handled by
3836 WriteR15Branch() below. It's probably an oversight: in THUMB
3837 mode, the second least significant bit should probably not be
3847 state
->Reg
[15] = src
& PCBITS
;
3849 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
3850 ARMul_R15Altered (state
);
3856 /* This routine handles writes to register 15 when the S bit is set. */
3859 WriteSR15 (ARMul_State
* state
, ARMword src
)
3862 if (state
->Bank
> 0)
3864 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3865 ARMul_CPSRAltered (state
);
3873 state
->Reg
[15] = src
& PCBITS
;
3877 /* ARMul_R15Altered would have to support it. */
3883 if (state
->Bank
== USERBANK
)
3884 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3886 state
->Reg
[15] = src
;
3888 ARMul_R15Altered (state
);
3893 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3894 will switch to Thumb mode if the least significant bit is set. */
3897 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3904 state
->Reg
[15] = src
& 0xfffffffe;
3909 state
->Reg
[15] = src
& 0xfffffffc;
3913 WriteR15 (state
, src
);
3917 /* This routine evaluates most Load and Store register RHS's. It is
3918 intended to be called from the macro LSRegRHS, which filters the
3919 common case of an unshifted register with in line code. */
3922 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3924 ARMword shamt
, base
;
3929 /* Now forbidden, but ... */
3930 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3933 base
= state
->Reg
[base
];
3935 shamt
= BITS (7, 11);
3936 switch ((int) BITS (5, 6))
3939 return (base
<< shamt
);
3944 return (base
>> shamt
);
3947 return ((ARMword
) ((long int) base
>> 31L));
3949 return ((ARMword
) ((long int) base
>> (int) shamt
));
3953 return ((base
>> 1) | (CFLAG
<< 31));
3955 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3962 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
3965 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3972 /* Now forbidden, but ... */
3973 return ECC
| ER15INT
| R15PC
| EMODE
;
3975 return state
->Reg
[RHSReg
];
3979 return BITS (0, 3) | (BITS (8, 11) << 4);
3982 /* This function does the work of loading a word for a LDR instruction. */
3985 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3991 if (ADDREXCEPT (address
))
3992 INTERNALABORT (address
);
3995 dest
= ARMul_LoadWordN (state
, address
);
4000 return state
->lateabtSig
;
4003 dest
= ARMul_Align (state
, address
, dest
);
4005 ARMul_Icycles (state
, 1, 0L);
4007 return (DESTReg
!= LHSReg
);
4011 /* This function does the work of loading a halfword. */
4014 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
4021 if (ADDREXCEPT (address
))
4022 INTERNALABORT (address
);
4024 dest
= ARMul_LoadHalfWord (state
, address
);
4028 return state
->lateabtSig
;
4032 if (dest
& 1 << (16 - 1))
4033 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
4036 ARMul_Icycles (state
, 1, 0L);
4037 return (DESTReg
!= LHSReg
);
4042 /* This function does the work of loading a byte for a LDRB instruction. */
4045 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
4051 if (ADDREXCEPT (address
))
4052 INTERNALABORT (address
);
4054 dest
= ARMul_LoadByte (state
, address
);
4058 return state
->lateabtSig
;
4062 if (dest
& 1 << (8 - 1))
4063 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
4066 ARMul_Icycles (state
, 1, 0L);
4068 return (DESTReg
!= LHSReg
);
4071 /* This function does the work of loading two words for a LDRD instruction. */
4074 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
4078 ARMword write_back
= BIT (21);
4079 ARMword immediate
= BIT (22);
4080 ARMword add_to_base
= BIT (23);
4081 ARMword pre_indexed
= BIT (24);
4091 /* If the writeback bit is set, the pre-index bit must be clear. */
4092 if (write_back
&& ! pre_indexed
)
4094 ARMul_UndefInstr (state
, instr
);
4098 /* Extract the base address register. */
4101 /* Extract the destination register and check it. */
4104 /* Destination register must be even. */
4106 /* Destination register cannot be LR. */
4107 || (dest_reg
== 14))
4109 ARMul_UndefInstr (state
, instr
);
4113 /* Compute the base address. */
4114 base
= state
->Reg
[addr_reg
];
4116 /* Compute the offset. */
4117 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4119 /* Compute the sum of the two. */
4121 sum
= base
+ offset
;
4123 sum
= base
- offset
;
4125 /* If this is a pre-indexed mode use the sum. */
4131 /* The address must be aligned on a 8 byte boundary. */
4135 ARMul_DATAABORT (addr
);
4137 ARMul_UndefInstr (state
, instr
);
4142 /* For pre indexed or post indexed addressing modes,
4143 check that the destination registers do not overlap
4144 the address registers. */
4145 if ((! pre_indexed
|| write_back
)
4146 && ( addr_reg
== dest_reg
4147 || addr_reg
== dest_reg
+ 1))
4149 ARMul_UndefInstr (state
, instr
);
4153 /* Load the words. */
4154 value1
= ARMul_LoadWordN (state
, addr
);
4155 value2
= ARMul_LoadWordN (state
, addr
+ 4);
4157 /* Check for data aborts. */
4164 ARMul_Icycles (state
, 2, 0L);
4166 /* Store the values. */
4167 state
->Reg
[dest_reg
] = value1
;
4168 state
->Reg
[dest_reg
+ 1] = value2
;
4170 /* Do the post addressing and writeback. */
4174 if (! pre_indexed
|| write_back
)
4175 state
->Reg
[addr_reg
] = addr
;
4178 /* This function does the work of storing two words for a STRD instruction. */
4181 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
4185 ARMword write_back
= BIT (21);
4186 ARMword immediate
= BIT (22);
4187 ARMword add_to_base
= BIT (23);
4188 ARMword pre_indexed
= BIT (24);
4196 /* If the writeback bit is set, the pre-index bit must be clear. */
4197 if (write_back
&& ! pre_indexed
)
4199 ARMul_UndefInstr (state
, instr
);
4203 /* Extract the base address register. */
4206 /* Base register cannot be PC. */
4209 ARMul_UndefInstr (state
, instr
);
4213 /* Extract the source register. */
4216 /* Source register must be even. */
4219 ARMul_UndefInstr (state
, instr
);
4223 /* Compute the base address. */
4224 base
= state
->Reg
[addr_reg
];
4226 /* Compute the offset. */
4227 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
4229 /* Compute the sum of the two. */
4231 sum
= base
+ offset
;
4233 sum
= base
- offset
;
4235 /* If this is a pre-indexed mode use the sum. */
4241 /* The address must be aligned on a 8 byte boundary. */
4245 ARMul_DATAABORT (addr
);
4247 ARMul_UndefInstr (state
, instr
);
4252 /* For pre indexed or post indexed addressing modes,
4253 check that the destination registers do not overlap
4254 the address registers. */
4255 if ((! pre_indexed
|| write_back
)
4256 && ( addr_reg
== src_reg
4257 || addr_reg
== src_reg
+ 1))
4259 ARMul_UndefInstr (state
, instr
);
4263 /* Load the words. */
4264 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
4265 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
4273 /* Do the post addressing and writeback. */
4277 if (! pre_indexed
|| write_back
)
4278 state
->Reg
[addr_reg
] = addr
;
4281 /* This function does the work of storing a word from a STR instruction. */
4284 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4289 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4292 ARMul_StoreWordN (state
, address
, DEST
);
4294 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4296 INTERNALABORT (address
);
4297 (void) ARMul_LoadWordN (state
, address
);
4300 ARMul_StoreWordN (state
, address
, DEST
);
4305 return state
->lateabtSig
;
4311 /* This function does the work of storing a byte for a STRH instruction. */
4314 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
4320 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4324 ARMul_StoreHalfWord (state
, address
, DEST
);
4326 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4328 INTERNALABORT (address
);
4329 (void) ARMul_LoadHalfWord (state
, address
);
4332 ARMul_StoreHalfWord (state
, address
, DEST
);
4338 return state
->lateabtSig
;
4345 /* This function does the work of storing a byte for a STRB instruction. */
4348 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
4353 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
4356 ARMul_StoreByte (state
, address
, DEST
);
4358 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4360 INTERNALABORT (address
);
4361 (void) ARMul_LoadByte (state
, address
);
4364 ARMul_StoreByte (state
, address
, DEST
);
4369 return state
->lateabtSig
;
4375 /* This function does the work of loading the registers listed in an LDM
4376 instruction, when the S bit is clear. The code here is always increment
4377 after, it's up to the caller to get the input address correct and to
4378 handle base register modification. */
4381 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
4387 UNDEF_LSMBaseInListWb
;
4390 if (ADDREXCEPT (address
))
4391 INTERNALABORT (address
);
4393 if (BIT (21) && LHSReg
!= 15)
4396 /* N cycle first. */
4397 for (temp
= 0; !BIT (temp
); temp
++)
4400 dest
= ARMul_LoadWordN (state
, address
);
4402 if (!state
->abortSig
&& !state
->Aborted
)
4403 state
->Reg
[temp
++] = dest
;
4404 else if (!state
->Aborted
)
4406 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4407 state
->Aborted
= ARMul_DataAbortV
;
4410 /* S cycles from here on. */
4411 for (; temp
< 16; temp
++)
4414 /* Load this register. */
4416 dest
= ARMul_LoadWordS (state
, address
);
4418 if (!state
->abortSig
&& !state
->Aborted
)
4419 state
->Reg
[temp
] = dest
;
4420 else if (!state
->Aborted
)
4422 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4423 state
->Aborted
= ARMul_DataAbortV
;
4427 if (BIT (15) && !state
->Aborted
)
4428 /* PC is in the reg list. */
4429 WriteR15Branch (state
, PC
);
4431 /* To write back the final register. */
4432 ARMul_Icycles (state
, 1, 0L);
4436 if (BIT (21) && LHSReg
!= 15)
4442 /* This function does the work of loading the registers listed in an LDM
4443 instruction, when the S bit is set. The code here is always increment
4444 after, it's up to the caller to get the input address correct and to
4445 handle base register modification. */
4448 LoadSMult (ARMul_State
* state
,
4457 UNDEF_LSMBaseInListWb
;
4462 if (ADDREXCEPT (address
))
4463 INTERNALABORT (address
);
4466 if (BIT (21) && LHSReg
!= 15)
4469 if (!BIT (15) && state
->Bank
!= USERBANK
)
4471 /* Temporary reg bank switch. */
4472 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4473 UNDEF_LSMUserBankWb
;
4476 /* N cycle first. */
4477 for (temp
= 0; !BIT (temp
); temp
++)
4480 dest
= ARMul_LoadWordN (state
, address
);
4482 if (!state
->abortSig
)
4483 state
->Reg
[temp
++] = dest
;
4484 else if (!state
->Aborted
)
4486 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4487 state
->Aborted
= ARMul_DataAbortV
;
4490 /* S cycles from here on. */
4491 for (; temp
< 16; temp
++)
4494 /* Load this register. */
4496 dest
= ARMul_LoadWordS (state
, address
);
4498 if (!state
->abortSig
&& !state
->Aborted
)
4499 state
->Reg
[temp
] = dest
;
4500 else if (!state
->Aborted
)
4502 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4503 state
->Aborted
= ARMul_DataAbortV
;
4507 if (BIT (15) && !state
->Aborted
)
4509 /* PC is in the reg list. */
4511 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4513 state
->Cpsr
= GETSPSR (state
->Bank
);
4514 ARMul_CPSRAltered (state
);
4517 WriteR15 (state
, PC
);
4519 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4521 /* Protect bits in user mode. */
4522 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4523 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4524 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4525 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4528 ARMul_R15Altered (state
);
4534 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4535 /* Restore the correct bank. */
4536 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4538 /* To write back the final register. */
4539 ARMul_Icycles (state
, 1, 0L);
4543 if (BIT (21) && LHSReg
!= 15)
4550 /* This function does the work of storing the registers listed in an STM
4551 instruction, when the S bit is clear. The code here is always increment
4552 after, it's up to the caller to get the input address correct and to
4553 handle base register modification. */
4556 StoreMult (ARMul_State
* state
,
4565 UNDEF_LSMBaseInListWb
;
4568 /* N-cycle, increment the PC and update the NextInstr state. */
4572 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4573 INTERNALABORT (address
);
4579 /* N cycle first. */
4580 for (temp
= 0; !BIT (temp
); temp
++)
4584 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4588 (void) ARMul_LoadWordN (state
, address
);
4590 /* Fake the Stores as Loads. */
4591 for (; temp
< 16; temp
++)
4594 /* Save this register. */
4596 (void) ARMul_LoadWordS (state
, address
);
4599 if (BIT (21) && LHSReg
!= 15)
4605 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4608 if (state
->abortSig
&& !state
->Aborted
)
4610 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4611 state
->Aborted
= ARMul_DataAbortV
;
4614 if (BIT (21) && LHSReg
!= 15)
4617 /* S cycles from here on. */
4618 for (; temp
< 16; temp
++)
4621 /* Save this register. */
4624 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4626 if (state
->abortSig
&& !state
->Aborted
)
4628 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4629 state
->Aborted
= ARMul_DataAbortV
;
4637 /* This function does the work of storing the registers listed in an STM
4638 instruction when the S bit is set. The code here is always increment
4639 after, it's up to the caller to get the input address correct and to
4640 handle base register modification. */
4643 StoreSMult (ARMul_State
* state
,
4652 UNDEF_LSMBaseInListWb
;
4657 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4658 INTERNALABORT (address
);
4664 if (state
->Bank
!= USERBANK
)
4666 /* Force User Bank. */
4667 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
4668 UNDEF_LSMUserBankWb
;
4671 for (temp
= 0; !BIT (temp
); temp
++)
4672 ; /* N cycle first. */
4675 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4679 (void) ARMul_LoadWordN (state
, address
);
4681 for (; temp
< 16; temp
++)
4682 /* Fake the Stores as Loads. */
4685 /* Save this register. */
4688 (void) ARMul_LoadWordS (state
, address
);
4691 if (BIT (21) && LHSReg
!= 15)
4698 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4701 if (state
->abortSig
&& !state
->Aborted
)
4703 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4704 state
->Aborted
= ARMul_DataAbortV
;
4707 /* S cycles from here on. */
4708 for (; temp
< 16; temp
++)
4711 /* Save this register. */
4714 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4716 if (state
->abortSig
&& !state
->Aborted
)
4718 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
4719 state
->Aborted
= ARMul_DataAbortV
;
4723 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4724 /* Restore the correct bank. */
4725 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
4727 if (BIT (21) && LHSReg
!= 15)
4734 /* This function does the work of adding two 32bit values
4735 together, and calculating if a carry has occurred. */
4738 Add32 (ARMword a1
, ARMword a2
, int *carry
)
4740 ARMword result
= (a1
+ a2
);
4741 unsigned int uresult
= (unsigned int) result
;
4742 unsigned int ua1
= (unsigned int) a1
;
4744 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4745 or (result > RdLo) then we have no carry. */
4746 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
4754 /* This function does the work of multiplying
4755 two 32bit values to give a 64bit result. */
4758 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4760 /* Operand register numbers. */
4761 int nRdHi
, nRdLo
, nRs
, nRm
;
4762 ARMword RdHi
= 0, RdLo
= 0, Rm
;
4766 nRdHi
= BITS (16, 19);
4767 nRdLo
= BITS (12, 15);
4771 /* Needed to calculate the cycle count. */
4772 Rm
= state
->Reg
[nRm
];
4774 /* Check for illegal operand combinations first. */
4783 /* Intermediate results. */
4784 ARMword lo
, mid1
, mid2
, hi
;
4786 ARMword Rs
= state
->Reg
[nRs
];
4791 /* Compute sign of result and adjust operands if necessary. */
4792 sign
= (Rm
^ Rs
) & 0x80000000;
4794 if (((signed long) Rm
) < 0)
4797 if (((signed long) Rs
) < 0)
4801 /* We can split the 32x32 into four 16x16 operations. This
4802 ensures that we do not lose precision on 32bit only hosts. */
4803 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
4804 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4805 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
4806 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4808 /* We now need to add all of these results together, taking
4809 care to propogate the carries from the additions. */
4810 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
4812 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
4814 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
4818 /* Negate result if necessary. */
4821 if (RdLo
== 0xFFFFFFFF)
4830 state
->Reg
[nRdLo
] = RdLo
;
4831 state
->Reg
[nRdHi
] = RdHi
;
4834 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4837 /* Ensure that both RdHi and RdLo are used to compute Z,
4838 but don't let RdLo's sign bit make it to N. */
4839 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4841 /* The cycle count depends on whether the instruction is a signed or
4842 unsigned multiply, and what bits are clear in the multiplier. */
4843 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
4844 /* Invert the bits to make the check against zero. */
4847 if ((Rm
& 0xFFFFFF00) == 0)
4849 else if ((Rm
& 0xFFFF0000) == 0)
4851 else if ((Rm
& 0xFF000000) == 0)
4859 /* This function does the work of multiplying two 32bit
4860 values and adding a 64bit value to give a 64bit result. */
4863 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4870 nRdHi
= BITS (16, 19);
4871 nRdLo
= BITS (12, 15);
4873 RdHi
= state
->Reg
[nRdHi
];
4874 RdLo
= state
->Reg
[nRdLo
];
4876 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
4878 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
4879 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
4881 state
->Reg
[nRdLo
] = RdLo
;
4882 state
->Reg
[nRdHi
] = RdHi
;
4885 /* Ensure that both RdHi and RdLo are used to compute Z,
4886 but don't let RdLo's sign bit make it to N. */
4887 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4889 /* Extra cycle for addition. */
This page took 0.135261 seconds and 4 git commands to generate.