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 *, ARMword);
24 static ARMword GetDPSRegRHS (ARMul_State *, ARMword);
25 static void WriteR15 (ARMul_State *, ARMword);
26 static void WriteSR15 (ARMul_State *, ARMword);
27 static void WriteR15Branch (ARMul_State *, ARMword);
28 static ARMword GetLSRegRHS (ARMul_State *, ARMword);
29 static ARMword GetLS7RHS (ARMul_State *, ARMword);
30 static unsigned LoadWord (ARMul_State *, ARMword, ARMword);
31 static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int);
32 static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int);
33 static unsigned StoreWord (ARMul_State *, ARMword, ARMword);
34 static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword);
35 static unsigned StoreByte (ARMul_State *, ARMword, ARMword);
36 static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword);
37 static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword);
38 static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword);
39 static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword);
40 static unsigned Multiply64 (ARMul_State *, ARMword, int, int);
41 static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int);
42 static void Handle_Load_Double (ARMul_State *, ARMword);
43 static void Handle_Store_Double (ARMul_State *, ARMword);
45 #define LUNSIGNED (0) /* unsigned operation */
46 #define LSIGNED (1) /* signed operation */
47 #define LDEFAULT (0) /* default : do nothing */
48 #define LSCC (1) /* set condition codes on result */
50 #ifdef NEED_UI_LOOP_HOOK
51 /* How often to run the ui_loop update, when in use. */
52 #define UI_LOOP_POLL_INTERVAL 0x32000
54 /* Counter for the ui_loop_hook update. */
55 static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
57 /* Actual hook to call to run through gdb's gui event loop. */
58 extern int (*ui_loop_hook) (int);
59 #endif /* NEED_UI_LOOP_HOOK */
61 extern int stop_simulator;
63 /* Short-hand macros for LDR/STR. */
65 /* Store post decrement writeback. */
68 if (StoreHalfWord (state, instr, lhs)) \
69 LSBase = lhs - GetLS7RHS (state, instr);
71 /* Store post increment writeback. */
74 if (StoreHalfWord (state, instr, lhs)) \
75 LSBase = lhs + GetLS7RHS (state, instr);
77 /* Store pre decrement. */
79 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
81 /* Store pre decrement writeback. */
82 #define SHPREDOWNWB() \
83 temp = LHS - GetLS7RHS (state, instr); \
84 if (StoreHalfWord (state, instr, temp)) \
87 /* Store pre increment. */
89 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
91 /* Store pre increment writeback. */
93 temp = LHS + GetLS7RHS (state, instr); \
94 if (StoreHalfWord (state, instr, temp)) \
97 /* Load post decrement writeback. */
98 #define LHPOSTDOWN() \
102 temp = lhs - GetLS7RHS (state, instr); \
104 switch (BITS (5, 6)) \
107 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
111 if (LoadByte (state, instr, lhs, LSIGNED)) \
115 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
118 case 0: /* SWP handled elsewhere. */ \
127 /* Load post increment writeback. */
132 temp = lhs + GetLS7RHS (state, instr); \
134 switch (BITS (5, 6)) \
137 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
141 if (LoadByte (state, instr, lhs, LSIGNED)) \
145 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
148 case 0: /* SWP handled elsewhere. */ \
157 /* Load pre decrement. */
158 #define LHPREDOWN() \
162 temp = LHS - GetLS7RHS (state, instr); \
163 switch (BITS (5, 6)) \
166 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
169 (void) LoadByte (state, instr, temp, LSIGNED); \
172 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
175 /* SWP handled elsewhere. */ \
184 /* Load pre decrement writeback. */
185 #define LHPREDOWNWB() \
189 temp = LHS - GetLS7RHS (state, instr); \
190 switch (BITS (5, 6)) \
193 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
197 if (LoadByte (state, instr, temp, LSIGNED)) \
201 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
205 /* SWP handled elsewhere. */ \
214 /* Load pre increment. */
219 temp = LHS + GetLS7RHS (state, instr); \
220 switch (BITS (5, 6)) \
223 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
226 (void) LoadByte (state, instr, temp, LSIGNED); \
229 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
232 /* SWP handled elsewhere. */ \
241 /* Load pre increment writeback. */
242 #define LHPREUPWB() \
246 temp = LHS + GetLS7RHS (state, instr); \
247 switch (BITS (5, 6)) \
250 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
254 if (LoadByte (state, instr, temp, LSIGNED)) \
258 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
262 /* SWP handled elsewhere. */ \
271 /* EMULATION of ARM6. */
273 /* The PC pipeline value depends on whether ARM
274 or Thumb instructions are being executed. */
279 ARMul_Emulate32 (ARMul_State * state)
281 ARMul_Emulate26 (ARMul_State * state)
284 ARMword instr; /* The current instruction. */
285 ARMword dest = 0; /* Almost the DestBus. */
286 ARMword temp; /* Ubiquitous third hand. */
287 ARMword pc = 0; /* The address of the current instruction. */
288 ARMword lhs; /* Almost the ABus and BBus. */
290 ARMword decoded = 0; /* Instruction pipeline. */
293 /* Execute the next instruction. */
295 if (state->NextInstr < PRIMEPIPE)
297 decoded = state->decoded;
298 loaded = state->loaded;
304 /* Just keep going. */
307 switch (state->NextInstr)
310 /* Advance the pipeline, and an S cycle. */
311 state->Reg[15] += isize;
315 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
319 /* Advance the pipeline, and an N cycle. */
320 state->Reg[15] += isize;
324 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
329 /* Program counter advanced, and an S cycle. */
333 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
338 /* Program counter advanced, and an N cycle. */
342 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
347 /* The program counter has been changed. */
352 state->Reg[15] = pc + (isize * 2);
354 instr = ARMul_ReLoadInstr (state, pc, isize);
355 decoded = ARMul_ReLoadInstr (state, pc + isize, isize);
356 loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize);
361 /* The program counter has been changed. */
366 state->Reg[15] = pc + (isize * 2);
368 instr = ARMul_LoadInstrN (state, pc, isize);
369 decoded = ARMul_LoadInstrS (state, pc + (isize), isize);
370 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
376 ARMul_EnvokeEvent (state);
378 /* Enable this for a helpful bit of debugging when tracing is needed. */
379 fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr);
384 if (state->Exception)
386 /* Any exceptions ? */
387 if (state->NresetSig == LOW)
389 ARMul_Abort (state, ARMul_ResetV);
392 else if (!state->NfiqSig && !FFLAG)
394 ARMul_Abort (state, ARMul_FIQV);
397 else if (!state->NirqSig && !IFLAG)
399 ARMul_Abort (state, ARMul_IRQV);
404 if (state->CallDebug > 0)
406 instr = ARMul_Debug (state, pc, instr);
407 if (state->Emulate < ONCE)
409 state->NextInstr = RESUME;
414 fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n", pc, instr,
416 (void) fgetc (stdin);
419 else if (state->Emulate < ONCE)
421 state->NextInstr = RESUME;
428 /* Provide Thumb instruction decoding. If the processor is in Thumb
429 mode, then we can simply decode the Thumb instruction, and map it
430 to the corresponding ARM instruction (by directly loading the
431 instr variable, and letting the normal ARM simulator
432 execute). There are some caveats to ensure that the correct
433 pipelined PC value is used when executing Thumb code, and also for
434 dealing with the BL instruction. */
439 /* Check if in Thumb mode. */
440 switch (ARMul_ThumbDecode (state, pc, instr, &new))
443 /* This is a Thumb instruction. */
444 ARMul_UndefInstr (state, instr);
448 /* Already processed. */
452 /* ARM instruction available. */
454 /* So continue instruction decoding. */
462 /* Check the condition codes. */
463 if ((temp = TOPBITS (28)) == AL)
464 /* Vile deed in the need for speed. */
467 /* Check the condition code. */
468 switch ((int) TOPBITS (28))
476 if (BITS (25, 27) == 5) /* BLX(1) */
480 state->Reg[14] = pc + 4;
482 /* Force entry into Thumb mode. */
485 dest += (NEGBRANCH + (BIT (24) << 1));
487 dest += POSBRANCH + (BIT (24) << 1);
489 WriteR15Branch (state, dest);
492 else if ((instr & 0xFC70F000) == 0xF450F000)
493 /* The PLD instruction. Ignored. */
496 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
497 ARMul_UndefInstr (state, instr);
526 temp = (CFLAG && !ZFLAG);
529 temp = (!CFLAG || ZFLAG);
532 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
535 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
538 temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
541 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
545 /* Handle the Clock counter here. */
546 if (state->is_XScale)
551 ok = state->CPRead[14] (state, 0, & cp14r0);
553 if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE))
555 unsigned long newcycles, nowtime = ARMul_Time (state);
557 newcycles = nowtime - state->LastTime;
558 state->LastTime = nowtime;
560 if (cp14r0 & ARMul_CP14_R0_CCD)
562 if (state->CP14R0_CCD == -1)
563 state->CP14R0_CCD = newcycles;
565 state->CP14R0_CCD += newcycles;
567 if (state->CP14R0_CCD >= 64)
571 while (state->CP14R0_CCD >= 64)
572 state->CP14R0_CCD -= 64, newcycles++;
582 state->CP14R0_CCD = -1;
584 cp14r0 |= ARMul_CP14_R0_FLAG2;
585 (void) state->CPWrite[14] (state, 0, cp14r0);
587 ok = state->CPRead[14] (state, 1, & cp14r1);
589 /* Coded like this for portability. */
590 while (ok && newcycles)
592 if (cp14r1 == 0xffffffff)
603 (void) state->CPWrite[14] (state, 1, cp14r1);
605 if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2))
609 if (state->CPRead[13] (state, 8, & temp)
610 && (temp & ARMul_CP13_R8_PMUS))
611 ARMul_Abort (state, ARMul_FIQV);
613 ARMul_Abort (state, ARMul_IRQV);
619 /* Handle hardware instructions breakpoints here. */
620 if (state->is_XScale)
622 if ( (pc | 3) == (read_cp15_reg (14, 0, 8) | 2)
623 || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2))
625 if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB))
626 ARMul_OSHandleSWI (state, SWI_Breakpoint);
630 /* Actual execution of instructions begins here. */
631 /* If the condition codes don't match, stop here. */
636 if (state->is_XScale)
638 if (BIT (20) == 0 && BITS (25, 27) == 0)
640 if (BITS (4, 7) == 0xD)
642 /* XScale Load Consecutive insn. */
643 ARMword temp = GetLS7RHS (state, instr);
644 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
645 ARMword addr = BIT (24) ? temp2 : LHS;
648 ARMul_UndefInstr (state, instr);
650 /* Alignment violation. */
651 ARMul_Abort (state, ARMul_DataAbortV);
654 int wb = BIT (21) || (! BIT (24));
656 state->Reg[BITS (12, 15)] =
657 ARMul_LoadWordN (state, addr);
658 state->Reg[BITS (12, 15) + 1] =
659 ARMul_LoadWordN (state, addr + 4);
666 else if (BITS (4, 7) == 0xF)
668 /* XScale Store Consecutive insn. */
669 ARMword temp = GetLS7RHS (state, instr);
670 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
671 ARMword addr = BIT (24) ? temp2 : LHS;
674 ARMul_UndefInstr (state, instr);
676 /* Alignment violation. */
677 ARMul_Abort (state, ARMul_DataAbortV);
680 ARMul_StoreWordN (state, addr,
681 state->Reg[BITS (12, 15)]);
682 ARMul_StoreWordN (state, addr + 4,
683 state->Reg[BITS (12, 15) + 1]);
685 if (BIT (21)|| ! BIT (24))
694 switch ((int) BITS (20, 27))
696 /* Data Processing Register RHS Instructions. */
698 case 0x00: /* AND reg and MUL */
700 if (BITS (4, 11) == 0xB)
702 /* STRH register offset, no write-back, down, post indexed. */
706 if (BITS (4, 7) == 0xD)
708 Handle_Load_Double (state, instr);
711 if (BITS (4, 7) == 0xF)
713 Handle_Store_Double (state, instr);
717 if (BITS (4, 7) == 9)
720 rhs = state->Reg[MULRHSReg];
721 if (MULLHSReg == MULDESTReg)
724 state->Reg[MULDESTReg] = 0;
726 else if (MULDESTReg != 15)
727 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
731 for (dest = 0, temp = 0; dest < 32; dest ++)
732 if (rhs & (1L << dest))
735 /* Mult takes this many/2 I cycles. */
736 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
747 case 0x01: /* ANDS reg and MULS */
749 if ((BITS (4, 11) & 0xF9) == 0x9)
750 /* LDR register offset, no write-back, down, post indexed. */
752 /* Fall through to rest of decoding. */
754 if (BITS (4, 7) == 9)
757 rhs = state->Reg[MULRHSReg];
759 if (MULLHSReg == MULDESTReg)
762 state->Reg[MULDESTReg] = 0;
766 else if (MULDESTReg != 15)
768 dest = state->Reg[MULLHSReg] * rhs;
769 ARMul_NegZero (state, dest);
770 state->Reg[MULDESTReg] = dest;
775 for (dest = 0, temp = 0; dest < 32; dest ++)
776 if (rhs & (1L << dest))
779 /* Mult takes this many/2 I cycles. */
780 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
791 case 0x02: /* EOR reg and MLA */
793 if (BITS (4, 11) == 0xB)
795 /* STRH register offset, write-back, down, post indexed. */
800 if (BITS (4, 7) == 9)
802 rhs = state->Reg[MULRHSReg];
803 if (MULLHSReg == MULDESTReg)
806 state->Reg[MULDESTReg] = state->Reg[MULACCReg];
808 else if (MULDESTReg != 15)
809 state->Reg[MULDESTReg] =
810 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
814 for (dest = 0, temp = 0; dest < 32; dest ++)
815 if (rhs & (1L << dest))
818 /* Mult takes this many/2 I cycles. */
819 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
829 case 0x03: /* EORS reg and MLAS */
831 if ((BITS (4, 11) & 0xF9) == 0x9)
832 /* LDR register offset, write-back, down, post-indexed. */
834 /* Fall through to rest of the decoding. */
836 if (BITS (4, 7) == 9)
839 rhs = state->Reg[MULRHSReg];
841 if (MULLHSReg == MULDESTReg)
844 dest = state->Reg[MULACCReg];
845 ARMul_NegZero (state, dest);
846 state->Reg[MULDESTReg] = dest;
848 else if (MULDESTReg != 15)
851 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
852 ARMul_NegZero (state, dest);
853 state->Reg[MULDESTReg] = dest;
858 for (dest = 0, temp = 0; dest < 32; dest ++)
859 if (rhs & (1L << dest))
862 /* Mult takes this many/2 I cycles. */
863 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
874 case 0x04: /* SUB reg */
876 if (BITS (4, 7) == 0xB)
878 /* STRH immediate offset, no write-back, down, post indexed. */
882 if (BITS (4, 7) == 0xD)
884 Handle_Load_Double (state, instr);
887 if (BITS (4, 7) == 0xF)
889 Handle_Store_Double (state, instr);
898 case 0x05: /* SUBS reg */
900 if ((BITS (4, 7) & 0x9) == 0x9)
901 /* LDR immediate offset, no write-back, down, post indexed. */
903 /* Fall through to the rest of the instruction decoding. */
909 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
911 ARMul_SubCarry (state, lhs, rhs, dest);
912 ARMul_SubOverflow (state, lhs, rhs, dest);
922 case 0x06: /* RSB reg */
924 if (BITS (4, 7) == 0xB)
926 /* STRH immediate offset, write-back, down, post indexed. */
936 case 0x07: /* RSBS reg */
938 if ((BITS (4, 7) & 0x9) == 0x9)
939 /* LDR immediate offset, write-back, down, post indexed. */
941 /* Fall through to remainder of instruction decoding. */
947 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
949 ARMul_SubCarry (state, rhs, lhs, dest);
950 ARMul_SubOverflow (state, rhs, lhs, dest);
960 case 0x08: /* ADD reg */
962 if (BITS (4, 11) == 0xB)
964 /* STRH register offset, no write-back, up, post indexed. */
968 if (BITS (4, 7) == 0xD)
970 Handle_Load_Double (state, instr);
973 if (BITS (4, 7) == 0xF)
975 Handle_Store_Double (state, instr);
980 if (BITS (4, 7) == 0x9)
984 ARMul_Icycles (state,
985 Multiply64 (state, instr, LUNSIGNED,
995 case 0x09: /* ADDS reg */
997 if ((BITS (4, 11) & 0xF9) == 0x9)
998 /* LDR register offset, no write-back, up, post indexed. */
1000 /* Fall through to remaining instruction decoding. */
1003 if (BITS (4, 7) == 0x9)
1007 ARMul_Icycles (state,
1008 Multiply64 (state, instr, LUNSIGNED, LSCC),
1016 ASSIGNZ (dest == 0);
1017 if ((lhs | rhs) >> 30)
1019 /* Possible C,V,N to set. */
1020 ASSIGNN (NEG (dest));
1021 ARMul_AddCarry (state, lhs, rhs, dest);
1022 ARMul_AddOverflow (state, lhs, rhs, dest);
1033 case 0x0a: /* ADC reg */
1035 if (BITS (4, 11) == 0xB)
1037 /* STRH register offset, write-back, up, post-indexed. */
1041 if (BITS (4, 7) == 0x9)
1045 ARMul_Icycles (state,
1046 MultiplyAdd64 (state, instr, LUNSIGNED,
1052 dest = LHS + rhs + CFLAG;
1056 case 0x0b: /* ADCS reg */
1058 if ((BITS (4, 11) & 0xF9) == 0x9)
1059 /* LDR register offset, write-back, up, post indexed. */
1061 /* Fall through to remaining instruction decoding. */
1062 if (BITS (4, 7) == 0x9)
1066 ARMul_Icycles (state,
1067 MultiplyAdd64 (state, instr, LUNSIGNED,
1074 dest = lhs + rhs + CFLAG;
1075 ASSIGNZ (dest == 0);
1076 if ((lhs | rhs) >> 30)
1078 /* Possible C,V,N to set. */
1079 ASSIGNN (NEG (dest));
1080 ARMul_AddCarry (state, lhs, rhs, dest);
1081 ARMul_AddOverflow (state, lhs, rhs, dest);
1092 case 0x0c: /* SBC reg */
1094 if (BITS (4, 7) == 0xB)
1096 /* STRH immediate offset, no write-back, up post indexed. */
1100 if (BITS (4, 7) == 0xD)
1102 Handle_Load_Double (state, instr);
1105 if (BITS (4, 7) == 0xF)
1107 Handle_Store_Double (state, instr);
1110 if (BITS (4, 7) == 0x9)
1114 ARMul_Icycles (state,
1115 Multiply64 (state, instr, LSIGNED, LDEFAULT),
1121 dest = LHS - rhs - !CFLAG;
1125 case 0x0d: /* SBCS reg */
1127 if ((BITS (4, 7) & 0x9) == 0x9)
1128 /* LDR immediate offset, no write-back, up, post indexed. */
1131 if (BITS (4, 7) == 0x9)
1135 ARMul_Icycles (state,
1136 Multiply64 (state, instr, LSIGNED, LSCC),
1143 dest = lhs - rhs - !CFLAG;
1144 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1146 ARMul_SubCarry (state, lhs, rhs, dest);
1147 ARMul_SubOverflow (state, lhs, rhs, dest);
1157 case 0x0e: /* RSC reg */
1159 if (BITS (4, 7) == 0xB)
1161 /* STRH immediate offset, write-back, up, post indexed. */
1166 if (BITS (4, 7) == 0x9)
1170 ARMul_Icycles (state,
1171 MultiplyAdd64 (state, instr, LSIGNED,
1177 dest = rhs - LHS - !CFLAG;
1181 case 0x0f: /* RSCS reg */
1183 if ((BITS (4, 7) & 0x9) == 0x9)
1184 /* LDR immediate offset, write-back, up, post indexed. */
1186 /* Fall through to remaining instruction decoding. */
1188 if (BITS (4, 7) == 0x9)
1192 ARMul_Icycles (state,
1193 MultiplyAdd64 (state, instr, LSIGNED, LSCC),
1200 dest = rhs - lhs - !CFLAG;
1202 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1204 ARMul_SubCarry (state, rhs, lhs, dest);
1205 ARMul_SubOverflow (state, rhs, lhs, dest);
1215 case 0x10: /* TST reg and MRS CPSR and SWP word. */
1218 if (BIT (4) == 0 && BIT (7) == 1)
1220 /* ElSegundo SMLAxy insn. */
1221 ARMword op1 = state->Reg[BITS (0, 3)];
1222 ARMword op2 = state->Reg[BITS (8, 11)];
1223 ARMword Rn = state->Reg[BITS (12, 15)];
1237 if (AddOverflow (op1, Rn, op1 + Rn))
1239 state->Reg[BITS (16, 19)] = op1 + Rn;
1243 if (BITS (4, 11) == 5)
1245 /* ElSegundo QADD insn. */
1246 ARMword op1 = state->Reg[BITS (0, 3)];
1247 ARMword op2 = state->Reg[BITS (16, 19)];
1248 ARMword result = op1 + op2;
1249 if (AddOverflow (op1, op2, result))
1251 result = POS (result) ? 0x80000000 : 0x7fffffff;
1254 state->Reg[BITS (12, 15)] = result;
1259 if (BITS (4, 11) == 0xB)
1261 /* STRH register offset, no write-back, down, pre indexed. */
1265 if (BITS (4, 7) == 0xD)
1267 Handle_Load_Double (state, instr);
1270 if (BITS (4, 7) == 0xF)
1272 Handle_Store_Double (state, instr);
1276 if (BITS (4, 11) == 9)
1283 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
1285 INTERNALABORT (temp);
1286 (void) ARMul_LoadWordN (state, temp);
1287 (void) ARMul_LoadWordN (state, temp);
1291 dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
1293 DEST = ARMul_Align (state, temp, dest);
1296 if (state->abortSig || state->Aborted)
1299 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
1302 DEST = ECC | EINT | EMODE;
1310 case 0x11: /* TSTP reg */
1312 if ((BITS (4, 11) & 0xF9) == 0x9)
1313 /* LDR register offset, no write-back, down, pre indexed. */
1315 /* Continue with remaining instruction decode. */
1321 state->Cpsr = GETSPSR (state->Bank);
1322 ARMul_CPSRAltered (state);
1334 ARMul_NegZero (state, dest);
1338 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
1341 if (BITS (4, 7) == 3)
1347 temp = (pc + 2) | 1;
1351 WriteR15Branch (state, state->Reg[RHSReg]);
1352 state->Reg[14] = temp;
1359 if (BIT (4) == 0 && BIT (7) == 1
1360 && (BIT (5) == 0 || BITS (12, 15) == 0))
1362 /* ElSegundo SMLAWy/SMULWy insn. */
1363 unsigned long long op1 = state->Reg[BITS (0, 3)];
1364 unsigned long long op2 = state->Reg[BITS (8, 11)];
1365 unsigned long long result;
1369 if (op1 & 0x80000000)
1374 result = (op1 * op2) >> 16;
1378 ARMword Rn = state->Reg[BITS (12, 15)];
1380 if (AddOverflow (result, Rn, result + Rn))
1384 state->Reg[BITS (16, 19)] = result;
1388 if (BITS (4, 11) == 5)
1390 /* ElSegundo QSUB insn. */
1391 ARMword op1 = state->Reg[BITS (0, 3)];
1392 ARMword op2 = state->Reg[BITS (16, 19)];
1393 ARMword result = op1 - op2;
1395 if (SubOverflow (op1, op2, result))
1397 result = POS (result) ? 0x80000000 : 0x7fffffff;
1401 state->Reg[BITS (12, 15)] = result;
1406 if (BITS (4, 11) == 0xB)
1408 /* STRH register offset, write-back, down, pre indexed. */
1412 if (BITS (4, 27) == 0x12FFF1)
1415 WriteR15Branch (state, state->Reg[RHSReg]);
1418 if (BITS (4, 7) == 0xD)
1420 Handle_Load_Double (state, instr);
1423 if (BITS (4, 7) == 0xF)
1425 Handle_Store_Double (state, instr);
1431 if (BITS (4, 7) == 0x7)
1434 extern int SWI_vector_installed;
1436 /* Hardware is allowed to optionally override this
1437 instruction and treat it as a breakpoint. Since
1438 this is a simulator not hardware, we take the position
1439 that if a SWI vector was not installed, then an Abort
1440 vector was probably not installed either, and so
1441 normally this instruction would be ignored, even if an
1442 Abort is generated. This is a bad thing, since GDB
1443 uses this instruction for its breakpoints (at least in
1444 Thumb mode it does). So intercept the instruction here
1445 and generate a breakpoint SWI instead. */
1446 if (! SWI_vector_installed)
1447 ARMul_OSHandleSWI (state, SWI_Breakpoint);
1450 /* BKPT - normally this will cause an abort, but on the
1451 XScale we must check the DCSR. */
1452 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
1453 if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT))
1457 /* Force the next instruction to be refetched. */
1458 state->NextInstr = RESUME;
1464 /* MSR reg to CPSR. */
1468 /* Don't allow TBIT to be set by MSR. */
1471 ARMul_FixCPSR (state, instr, temp);
1478 case 0x13: /* TEQP reg */
1480 if ((BITS (4, 11) & 0xF9) == 0x9)
1481 /* LDR register offset, write-back, down, pre indexed. */
1483 /* Continue with remaining instruction decode. */
1489 state->Cpsr = GETSPSR (state->Bank);
1490 ARMul_CPSRAltered (state);
1502 ARMul_NegZero (state, dest);
1506 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
1509 if (BIT (4) == 0 && BIT (7) == 1)
1511 /* ElSegundo SMLALxy insn. */
1512 unsigned long long op1 = state->Reg[BITS (0, 3)];
1513 unsigned long long op2 = state->Reg[BITS (8, 11)];
1514 unsigned long long dest;
1515 unsigned long long result;
1528 dest = (unsigned long long) state->Reg[BITS (16, 19)] << 32;
1529 dest |= state->Reg[BITS (12, 15)];
1531 state->Reg[BITS (12, 15)] = dest;
1532 state->Reg[BITS (16, 19)] = dest >> 32;
1536 if (BITS (4, 11) == 5)
1538 /* ElSegundo QDADD insn. */
1539 ARMword op1 = state->Reg[BITS (0, 3)];
1540 ARMword op2 = state->Reg[BITS (16, 19)];
1541 ARMword op2d = op2 + op2;
1544 if (AddOverflow (op2, op2, op2d))
1547 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1550 result = op1 + op2d;
1551 if (AddOverflow (op1, op2d, result))
1554 result = POS (result) ? 0x80000000 : 0x7fffffff;
1557 state->Reg[BITS (12, 15)] = result;
1562 if (BITS (4, 7) == 0xB)
1564 /* STRH immediate offset, no write-back, down, pre indexed. */
1568 if (BITS (4, 7) == 0xD)
1570 Handle_Load_Double (state, instr);
1573 if (BITS (4, 7) == 0xF)
1575 Handle_Store_Double (state, instr);
1579 if (BITS (4, 11) == 9)
1586 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
1588 INTERNALABORT (temp);
1589 (void) ARMul_LoadByte (state, temp);
1590 (void) ARMul_LoadByte (state, temp);
1594 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
1595 if (state->abortSig || state->Aborted)
1598 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
1602 DEST = GETSPSR (state->Bank);
1609 case 0x15: /* CMPP reg. */
1611 if ((BITS (4, 7) & 0x9) == 0x9)
1612 /* LDR immediate offset, no write-back, down, pre indexed. */
1614 /* Continue with remaining instruction decode. */
1620 state->Cpsr = GETSPSR (state->Bank);
1621 ARMul_CPSRAltered (state);
1634 ARMul_NegZero (state, dest);
1635 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1637 ARMul_SubCarry (state, lhs, rhs, dest);
1638 ARMul_SubOverflow (state, lhs, rhs, dest);
1648 case 0x16: /* CMN reg and MSR reg to SPSR */
1651 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1653 /* ElSegundo SMULxy insn. */
1654 ARMword op1 = state->Reg[BITS (0, 3)];
1655 ARMword op2 = state->Reg[BITS (8, 11)];
1656 ARMword Rn = state->Reg[BITS (12, 15)];
1669 state->Reg[BITS (16, 19)] = op1 * op2;
1673 if (BITS (4, 11) == 5)
1675 /* ElSegundo QDSUB insn. */
1676 ARMword op1 = state->Reg[BITS (0, 3)];
1677 ARMword op2 = state->Reg[BITS (16, 19)];
1678 ARMword op2d = op2 + op2;
1681 if (AddOverflow (op2, op2, op2d))
1684 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1687 result = op1 - op2d;
1688 if (SubOverflow (op1, op2d, result))
1691 result = POS (result) ? 0x80000000 : 0x7fffffff;
1694 state->Reg[BITS (12, 15)] = result;
1701 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1703 /* ARM5 CLZ insn. */
1704 ARMword op1 = state->Reg[BITS (0, 3)];
1708 for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
1711 state->Reg[BITS (12, 15)] = result;
1716 if (BITS (4, 7) == 0xB)
1718 /* STRH immediate offset, write-back, down, pre indexed. */
1722 if (BITS (4, 7) == 0xD)
1724 Handle_Load_Double (state, instr);
1727 if (BITS (4, 7) == 0xF)
1729 Handle_Store_Double (state, instr);
1737 ARMul_FixSPSR (state, instr, DPRegRHS);
1745 case 0x17: /* CMNP reg */
1747 if ((BITS (4, 7) & 0x9) == 0x9)
1748 /* LDR immediate offset, write-back, down, pre indexed. */
1750 /* Continue with remaining instruction decoding. */
1755 state->Cpsr = GETSPSR (state->Bank);
1756 ARMul_CPSRAltered (state);
1770 ASSIGNZ (dest == 0);
1771 if ((lhs | rhs) >> 30)
1773 /* Possible C,V,N to set. */
1774 ASSIGNN (NEG (dest));
1775 ARMul_AddCarry (state, lhs, rhs, dest);
1776 ARMul_AddOverflow (state, lhs, rhs, dest);
1787 case 0x18: /* ORR reg */
1789 if (BITS (4, 11) == 0xB)
1791 /* STRH register offset, no write-back, up, pre indexed. */
1795 if (BITS (4, 7) == 0xD)
1797 Handle_Load_Double (state, instr);
1800 if (BITS (4, 7) == 0xF)
1802 Handle_Store_Double (state, instr);
1811 case 0x19: /* ORRS reg */
1813 if ((BITS (4, 11) & 0xF9) == 0x9)
1814 /* LDR register offset, no write-back, up, pre indexed. */
1816 /* Continue with remaining instruction decoding. */
1823 case 0x1a: /* MOV reg */
1825 if (BITS (4, 11) == 0xB)
1827 /* STRH register offset, write-back, up, pre indexed. */
1831 if (BITS (4, 7) == 0xD)
1833 Handle_Load_Double (state, instr);
1836 if (BITS (4, 7) == 0xF)
1838 Handle_Store_Double (state, instr);
1846 case 0x1b: /* MOVS reg */
1848 if ((BITS (4, 11) & 0xF9) == 0x9)
1849 /* LDR register offset, write-back, up, pre indexed. */
1851 /* Continue with remaining instruction decoding. */
1857 case 0x1c: /* BIC reg */
1859 if (BITS (4, 7) == 0xB)
1861 /* STRH immediate offset, no write-back, up, pre indexed. */
1865 if (BITS (4, 7) == 0xD)
1867 Handle_Load_Double (state, instr);
1870 else if (BITS (4, 7) == 0xF)
1872 Handle_Store_Double (state, instr);
1881 case 0x1d: /* BICS reg */
1883 if ((BITS (4, 7) & 0x9) == 0x9)
1884 /* LDR immediate offset, no write-back, up, pre indexed. */
1886 /* Continue with instruction decoding. */
1893 case 0x1e: /* MVN reg */
1895 if (BITS (4, 7) == 0xB)
1897 /* STRH immediate offset, write-back, up, pre indexed. */
1901 if (BITS (4, 7) == 0xD)
1903 Handle_Load_Double (state, instr);
1906 if (BITS (4, 7) == 0xF)
1908 Handle_Store_Double (state, instr);
1916 case 0x1f: /* MVNS reg */
1918 if ((BITS (4, 7) & 0x9) == 0x9)
1919 /* LDR immediate offset, write-back, up, pre indexed. */
1921 /* Continue instruction decoding. */
1928 /* Data Processing Immediate RHS Instructions. */
1930 case 0x20: /* AND immed */
1931 dest = LHS & DPImmRHS;
1935 case 0x21: /* ANDS immed */
1941 case 0x22: /* EOR immed */
1942 dest = LHS ^ DPImmRHS;
1946 case 0x23: /* EORS immed */
1952 case 0x24: /* SUB immed */
1953 dest = LHS - DPImmRHS;
1957 case 0x25: /* SUBS immed */
1962 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1964 ARMul_SubCarry (state, lhs, rhs, dest);
1965 ARMul_SubOverflow (state, lhs, rhs, dest);
1975 case 0x26: /* RSB immed */
1976 dest = DPImmRHS - LHS;
1980 case 0x27: /* RSBS immed */
1985 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1987 ARMul_SubCarry (state, rhs, lhs, dest);
1988 ARMul_SubOverflow (state, rhs, lhs, dest);
1998 case 0x28: /* ADD immed */
1999 dest = LHS + DPImmRHS;
2003 case 0x29: /* ADDS immed */
2007 ASSIGNZ (dest == 0);
2009 if ((lhs | rhs) >> 30)
2011 /* Possible C,V,N to set. */
2012 ASSIGNN (NEG (dest));
2013 ARMul_AddCarry (state, lhs, rhs, dest);
2014 ARMul_AddOverflow (state, lhs, rhs, dest);
2025 case 0x2a: /* ADC immed */
2026 dest = LHS + DPImmRHS + CFLAG;
2030 case 0x2b: /* ADCS immed */
2033 dest = lhs + rhs + CFLAG;
2034 ASSIGNZ (dest == 0);
2035 if ((lhs | rhs) >> 30)
2037 /* Possible C,V,N to set. */
2038 ASSIGNN (NEG (dest));
2039 ARMul_AddCarry (state, lhs, rhs, dest);
2040 ARMul_AddOverflow (state, lhs, rhs, dest);
2051 case 0x2c: /* SBC immed */
2052 dest = LHS - DPImmRHS - !CFLAG;
2056 case 0x2d: /* SBCS immed */
2059 dest = lhs - rhs - !CFLAG;
2060 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2062 ARMul_SubCarry (state, lhs, rhs, dest);
2063 ARMul_SubOverflow (state, lhs, rhs, dest);
2073 case 0x2e: /* RSC immed */
2074 dest = DPImmRHS - LHS - !CFLAG;
2078 case 0x2f: /* RSCS immed */
2081 dest = rhs - lhs - !CFLAG;
2082 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
2084 ARMul_SubCarry (state, rhs, lhs, dest);
2085 ARMul_SubOverflow (state, rhs, lhs, dest);
2095 case 0x30: /* TST immed */
2099 case 0x31: /* TSTP immed */
2104 state->Cpsr = GETSPSR (state->Bank);
2105 ARMul_CPSRAltered (state);
2107 temp = LHS & DPImmRHS;
2116 ARMul_NegZero (state, dest);
2120 case 0x32: /* TEQ immed and MSR immed to CPSR */
2122 /* MSR immed to CPSR. */
2123 ARMul_FixCPSR (state, instr, DPImmRHS);
2128 case 0x33: /* TEQP immed */
2133 state->Cpsr = GETSPSR (state->Bank);
2134 ARMul_CPSRAltered (state);
2136 temp = LHS ^ DPImmRHS;
2142 DPSImmRHS; /* TEQ immed */
2144 ARMul_NegZero (state, dest);
2148 case 0x34: /* CMP immed */
2152 case 0x35: /* CMPP immed */
2157 state->Cpsr = GETSPSR (state->Bank);
2158 ARMul_CPSRAltered (state);
2160 temp = LHS - DPImmRHS;
2171 ARMul_NegZero (state, dest);
2173 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2175 ARMul_SubCarry (state, lhs, rhs, dest);
2176 ARMul_SubOverflow (state, lhs, rhs, dest);
2186 case 0x36: /* CMN immed and MSR immed to SPSR */
2188 ARMul_FixSPSR (state, instr, DPImmRHS);
2193 case 0x37: /* CMNP immed. */
2198 state->Cpsr = GETSPSR (state->Bank);
2199 ARMul_CPSRAltered (state);
2201 temp = LHS + DPImmRHS;
2212 ASSIGNZ (dest == 0);
2213 if ((lhs | rhs) >> 30)
2215 /* Possible C,V,N to set. */
2216 ASSIGNN (NEG (dest));
2217 ARMul_AddCarry (state, lhs, rhs, dest);
2218 ARMul_AddOverflow (state, lhs, rhs, dest);
2229 case 0x38: /* ORR immed. */
2230 dest = LHS | DPImmRHS;
2234 case 0x39: /* ORRS immed. */
2240 case 0x3a: /* MOV immed. */
2245 case 0x3b: /* MOVS immed. */
2250 case 0x3c: /* BIC immed. */
2251 dest = LHS & ~DPImmRHS;
2255 case 0x3d: /* BICS immed. */
2261 case 0x3e: /* MVN immed. */
2266 case 0x3f: /* MVNS immed. */
2272 /* Single Data Transfer Immediate RHS Instructions. */
2274 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2276 if (StoreWord (state, instr, lhs))
2277 LSBase = lhs - LSImmRHS;
2280 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2282 if (LoadWord (state, instr, lhs))
2283 LSBase = lhs - LSImmRHS;
2286 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2287 UNDEF_LSRBaseEQDestWb;
2290 temp = lhs - LSImmRHS;
2291 state->NtransSig = LOW;
2292 if (StoreWord (state, instr, lhs))
2294 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2297 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2298 UNDEF_LSRBaseEQDestWb;
2301 state->NtransSig = LOW;
2302 if (LoadWord (state, instr, lhs))
2303 LSBase = lhs - LSImmRHS;
2304 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2307 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2309 if (StoreByte (state, instr, lhs))
2310 LSBase = lhs - LSImmRHS;
2313 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2315 if (LoadByte (state, instr, lhs, LUNSIGNED))
2316 LSBase = lhs - LSImmRHS;
2319 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2320 UNDEF_LSRBaseEQDestWb;
2323 state->NtransSig = LOW;
2324 if (StoreByte (state, instr, lhs))
2325 LSBase = lhs - LSImmRHS;
2326 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2329 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2330 UNDEF_LSRBaseEQDestWb;
2333 state->NtransSig = LOW;
2334 if (LoadByte (state, instr, lhs, LUNSIGNED))
2335 LSBase = lhs - LSImmRHS;
2336 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2339 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2341 if (StoreWord (state, instr, lhs))
2342 LSBase = lhs + LSImmRHS;
2345 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2347 if (LoadWord (state, instr, lhs))
2348 LSBase = lhs + LSImmRHS;
2351 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2352 UNDEF_LSRBaseEQDestWb;
2355 state->NtransSig = LOW;
2356 if (StoreWord (state, instr, lhs))
2357 LSBase = lhs + LSImmRHS;
2358 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2361 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2362 UNDEF_LSRBaseEQDestWb;
2365 state->NtransSig = LOW;
2366 if (LoadWord (state, instr, lhs))
2367 LSBase = lhs + LSImmRHS;
2368 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2371 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2373 if (StoreByte (state, instr, lhs))
2374 LSBase = lhs + LSImmRHS;
2377 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2379 if (LoadByte (state, instr, lhs, LUNSIGNED))
2380 LSBase = lhs + LSImmRHS;
2383 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2384 UNDEF_LSRBaseEQDestWb;
2387 state->NtransSig = LOW;
2388 if (StoreByte (state, instr, lhs))
2389 LSBase = lhs + LSImmRHS;
2390 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2393 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2394 UNDEF_LSRBaseEQDestWb;
2397 state->NtransSig = LOW;
2398 if (LoadByte (state, instr, lhs, LUNSIGNED))
2399 LSBase = lhs + LSImmRHS;
2400 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2404 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2405 (void) StoreWord (state, instr, LHS - LSImmRHS);
2408 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2409 (void) LoadWord (state, instr, LHS - LSImmRHS);
2412 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2413 UNDEF_LSRBaseEQDestWb;
2415 temp = LHS - LSImmRHS;
2416 if (StoreWord (state, instr, temp))
2420 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2421 UNDEF_LSRBaseEQDestWb;
2423 temp = LHS - LSImmRHS;
2424 if (LoadWord (state, instr, temp))
2428 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2429 (void) StoreByte (state, instr, LHS - LSImmRHS);
2432 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2433 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
2436 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2437 UNDEF_LSRBaseEQDestWb;
2439 temp = LHS - LSImmRHS;
2440 if (StoreByte (state, instr, temp))
2444 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2445 UNDEF_LSRBaseEQDestWb;
2447 temp = LHS - LSImmRHS;
2448 if (LoadByte (state, instr, temp, LUNSIGNED))
2452 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2453 (void) StoreWord (state, instr, LHS + LSImmRHS);
2456 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2457 (void) LoadWord (state, instr, LHS + LSImmRHS);
2460 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2461 UNDEF_LSRBaseEQDestWb;
2463 temp = LHS + LSImmRHS;
2464 if (StoreWord (state, instr, temp))
2468 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2469 UNDEF_LSRBaseEQDestWb;
2471 temp = LHS + LSImmRHS;
2472 if (LoadWord (state, instr, temp))
2476 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2477 (void) StoreByte (state, instr, LHS + LSImmRHS);
2480 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2481 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
2484 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2485 UNDEF_LSRBaseEQDestWb;
2487 temp = LHS + LSImmRHS;
2488 if (StoreByte (state, instr, temp))
2492 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2493 UNDEF_LSRBaseEQDestWb;
2495 temp = LHS + LSImmRHS;
2496 if (LoadByte (state, instr, temp, LUNSIGNED))
2501 /* Single Data Transfer Register RHS Instructions. */
2503 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2506 ARMul_UndefInstr (state, instr);
2509 UNDEF_LSRBaseEQOffWb;
2510 UNDEF_LSRBaseEQDestWb;
2514 if (StoreWord (state, instr, lhs))
2515 LSBase = lhs - LSRegRHS;
2518 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2521 ARMul_UndefInstr (state, instr);
2524 UNDEF_LSRBaseEQOffWb;
2525 UNDEF_LSRBaseEQDestWb;
2529 temp = lhs - LSRegRHS;
2530 if (LoadWord (state, instr, lhs))
2534 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2537 ARMul_UndefInstr (state, instr);
2540 UNDEF_LSRBaseEQOffWb;
2541 UNDEF_LSRBaseEQDestWb;
2545 state->NtransSig = LOW;
2546 if (StoreWord (state, instr, lhs))
2547 LSBase = lhs - LSRegRHS;
2548 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2551 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2554 ARMul_UndefInstr (state, instr);
2557 UNDEF_LSRBaseEQOffWb;
2558 UNDEF_LSRBaseEQDestWb;
2562 temp = lhs - LSRegRHS;
2563 state->NtransSig = LOW;
2564 if (LoadWord (state, instr, lhs))
2566 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2569 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2572 ARMul_UndefInstr (state, instr);
2575 UNDEF_LSRBaseEQOffWb;
2576 UNDEF_LSRBaseEQDestWb;
2580 if (StoreByte (state, instr, lhs))
2581 LSBase = lhs - LSRegRHS;
2584 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2587 ARMul_UndefInstr (state, instr);
2590 UNDEF_LSRBaseEQOffWb;
2591 UNDEF_LSRBaseEQDestWb;
2595 temp = lhs - LSRegRHS;
2596 if (LoadByte (state, instr, lhs, LUNSIGNED))
2600 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2603 ARMul_UndefInstr (state, instr);
2606 UNDEF_LSRBaseEQOffWb;
2607 UNDEF_LSRBaseEQDestWb;
2611 state->NtransSig = LOW;
2612 if (StoreByte (state, instr, lhs))
2613 LSBase = lhs - LSRegRHS;
2614 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2617 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2620 ARMul_UndefInstr (state, instr);
2623 UNDEF_LSRBaseEQOffWb;
2624 UNDEF_LSRBaseEQDestWb;
2628 temp = lhs - LSRegRHS;
2629 state->NtransSig = LOW;
2630 if (LoadByte (state, instr, lhs, LUNSIGNED))
2632 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2635 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2638 ARMul_UndefInstr (state, instr);
2641 UNDEF_LSRBaseEQOffWb;
2642 UNDEF_LSRBaseEQDestWb;
2646 if (StoreWord (state, instr, lhs))
2647 LSBase = lhs + LSRegRHS;
2650 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2653 ARMul_UndefInstr (state, instr);
2656 UNDEF_LSRBaseEQOffWb;
2657 UNDEF_LSRBaseEQDestWb;
2661 temp = lhs + LSRegRHS;
2662 if (LoadWord (state, instr, lhs))
2666 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2669 ARMul_UndefInstr (state, instr);
2672 UNDEF_LSRBaseEQOffWb;
2673 UNDEF_LSRBaseEQDestWb;
2677 state->NtransSig = LOW;
2678 if (StoreWord (state, instr, lhs))
2679 LSBase = lhs + LSRegRHS;
2680 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2683 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2686 ARMul_UndefInstr (state, instr);
2689 UNDEF_LSRBaseEQOffWb;
2690 UNDEF_LSRBaseEQDestWb;
2694 temp = lhs + LSRegRHS;
2695 state->NtransSig = LOW;
2696 if (LoadWord (state, instr, lhs))
2698 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2701 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2704 ARMul_UndefInstr (state, instr);
2707 UNDEF_LSRBaseEQOffWb;
2708 UNDEF_LSRBaseEQDestWb;
2712 if (StoreByte (state, instr, lhs))
2713 LSBase = lhs + LSRegRHS;
2716 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
2719 ARMul_UndefInstr (state, instr);
2722 UNDEF_LSRBaseEQOffWb;
2723 UNDEF_LSRBaseEQDestWb;
2727 temp = lhs + LSRegRHS;
2728 if (LoadByte (state, instr, lhs, LUNSIGNED))
2732 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
2735 ARMul_UndefInstr (state, instr);
2738 UNDEF_LSRBaseEQOffWb;
2739 UNDEF_LSRBaseEQDestWb;
2743 state->NtransSig = LOW;
2744 if (StoreByte (state, instr, lhs))
2745 LSBase = lhs + LSRegRHS;
2746 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2749 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
2752 ARMul_UndefInstr (state, instr);
2755 UNDEF_LSRBaseEQOffWb;
2756 UNDEF_LSRBaseEQDestWb;
2760 temp = lhs + LSRegRHS;
2761 state->NtransSig = LOW;
2762 if (LoadByte (state, instr, lhs, LUNSIGNED))
2764 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2768 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
2771 ARMul_UndefInstr (state, instr);
2774 (void) StoreWord (state, instr, LHS - LSRegRHS);
2777 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
2780 ARMul_UndefInstr (state, instr);
2783 (void) LoadWord (state, instr, LHS - LSRegRHS);
2786 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
2789 ARMul_UndefInstr (state, instr);
2792 UNDEF_LSRBaseEQOffWb;
2793 UNDEF_LSRBaseEQDestWb;
2796 temp = LHS - LSRegRHS;
2797 if (StoreWord (state, instr, temp))
2801 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
2804 ARMul_UndefInstr (state, instr);
2807 UNDEF_LSRBaseEQOffWb;
2808 UNDEF_LSRBaseEQDestWb;
2811 temp = LHS - LSRegRHS;
2812 if (LoadWord (state, instr, temp))
2816 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
2819 ARMul_UndefInstr (state, instr);
2822 (void) StoreByte (state, instr, LHS - LSRegRHS);
2825 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
2828 ARMul_UndefInstr (state, instr);
2831 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
2834 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
2837 ARMul_UndefInstr (state, instr);
2840 UNDEF_LSRBaseEQOffWb;
2841 UNDEF_LSRBaseEQDestWb;
2844 temp = LHS - LSRegRHS;
2845 if (StoreByte (state, instr, temp))
2849 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
2852 ARMul_UndefInstr (state, instr);
2855 UNDEF_LSRBaseEQOffWb;
2856 UNDEF_LSRBaseEQDestWb;
2859 temp = LHS - LSRegRHS;
2860 if (LoadByte (state, instr, temp, LUNSIGNED))
2864 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
2867 ARMul_UndefInstr (state, instr);
2870 (void) StoreWord (state, instr, LHS + LSRegRHS);
2873 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
2876 ARMul_UndefInstr (state, instr);
2879 (void) LoadWord (state, instr, LHS + LSRegRHS);
2882 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
2885 ARMul_UndefInstr (state, instr);
2888 UNDEF_LSRBaseEQOffWb;
2889 UNDEF_LSRBaseEQDestWb;
2892 temp = LHS + LSRegRHS;
2893 if (StoreWord (state, instr, temp))
2897 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
2900 ARMul_UndefInstr (state, instr);
2903 UNDEF_LSRBaseEQOffWb;
2904 UNDEF_LSRBaseEQDestWb;
2907 temp = LHS + LSRegRHS;
2908 if (LoadWord (state, instr, temp))
2912 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
2915 ARMul_UndefInstr (state, instr);
2918 (void) StoreByte (state, instr, LHS + LSRegRHS);
2921 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
2924 ARMul_UndefInstr (state, instr);
2927 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
2930 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
2933 ARMul_UndefInstr (state, instr);
2936 UNDEF_LSRBaseEQOffWb;
2937 UNDEF_LSRBaseEQDestWb;
2940 temp = LHS + LSRegRHS;
2941 if (StoreByte (state, instr, temp))
2945 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
2948 /* Check for the special breakpoint opcode.
2949 This value should correspond to the value defined
2950 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2951 if (BITS (0, 19) == 0xfdefe)
2953 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
2954 ARMul_Abort (state, ARMul_SWIV);
2957 ARMul_UndefInstr (state, instr);
2960 UNDEF_LSRBaseEQOffWb;
2961 UNDEF_LSRBaseEQDestWb;
2964 temp = LHS + LSRegRHS;
2965 if (LoadByte (state, instr, temp, LUNSIGNED))
2970 /* Multiple Data Transfer Instructions. */
2972 case 0x80: /* Store, No WriteBack, Post Dec. */
2973 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2976 case 0x81: /* Load, No WriteBack, Post Dec. */
2977 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2980 case 0x82: /* Store, WriteBack, Post Dec. */
2981 temp = LSBase - LSMNumRegs;
2982 STOREMULT (instr, temp + 4L, temp);
2985 case 0x83: /* Load, WriteBack, Post Dec. */
2986 temp = LSBase - LSMNumRegs;
2987 LOADMULT (instr, temp + 4L, temp);
2990 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
2991 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2994 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
2995 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2998 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
2999 temp = LSBase - LSMNumRegs;
3000 STORESMULT (instr, temp + 4L, temp);
3003 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3004 temp = LSBase - LSMNumRegs;
3005 LOADSMULT (instr, temp + 4L, temp);
3008 case 0x88: /* Store, No WriteBack, Post Inc. */
3009 STOREMULT (instr, LSBase, 0L);
3012 case 0x89: /* Load, No WriteBack, Post Inc. */
3013 LOADMULT (instr, LSBase, 0L);
3016 case 0x8a: /* Store, WriteBack, Post Inc. */
3018 STOREMULT (instr, temp, temp + LSMNumRegs);
3021 case 0x8b: /* Load, WriteBack, Post Inc. */
3023 LOADMULT (instr, temp, temp + LSMNumRegs);
3026 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3027 STORESMULT (instr, LSBase, 0L);
3030 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3031 LOADSMULT (instr, LSBase, 0L);
3034 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3036 STORESMULT (instr, temp, temp + LSMNumRegs);
3039 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3041 LOADSMULT (instr, temp, temp + LSMNumRegs);
3044 case 0x90: /* Store, No WriteBack, Pre Dec. */
3045 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
3048 case 0x91: /* Load, No WriteBack, Pre Dec. */
3049 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
3052 case 0x92: /* Store, WriteBack, Pre Dec. */
3053 temp = LSBase - LSMNumRegs;
3054 STOREMULT (instr, temp, temp);
3057 case 0x93: /* Load, WriteBack, Pre Dec. */
3058 temp = LSBase - LSMNumRegs;
3059 LOADMULT (instr, temp, temp);
3062 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3063 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
3066 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3067 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
3070 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3071 temp = LSBase - LSMNumRegs;
3072 STORESMULT (instr, temp, temp);
3075 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3076 temp = LSBase - LSMNumRegs;
3077 LOADSMULT (instr, temp, temp);
3080 case 0x98: /* Store, No WriteBack, Pre Inc. */
3081 STOREMULT (instr, LSBase + 4L, 0L);
3084 case 0x99: /* Load, No WriteBack, Pre Inc. */
3085 LOADMULT (instr, LSBase + 4L, 0L);
3088 case 0x9a: /* Store, WriteBack, Pre Inc. */
3090 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
3093 case 0x9b: /* Load, WriteBack, Pre Inc. */
3095 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
3098 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3099 STORESMULT (instr, LSBase + 4L, 0L);
3102 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3103 LOADSMULT (instr, LSBase + 4L, 0L);
3106 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3108 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
3111 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3113 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
3117 /* Branch forward. */
3126 state->Reg[15] = pc + 8 + POSBRANCH;
3131 /* Branch backward. */
3140 state->Reg[15] = pc + 8 + NEGBRANCH;
3145 /* Branch and Link forward. */
3154 /* Put PC into Link. */
3156 state->Reg[14] = pc + 4;
3158 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3160 state->Reg[15] = pc + 8 + POSBRANCH;
3165 /* Branch and Link backward. */
3174 /* Put PC into Link. */
3176 state->Reg[14] = pc + 4;
3178 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3180 state->Reg[15] = pc + 8 + NEGBRANCH;
3185 /* Co-Processor Data Transfers. */
3189 /* Reading from R15 is UNPREDICTABLE. */
3190 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3191 ARMul_UndefInstr (state, instr);
3192 /* Is access to coprocessor 0 allowed ? */
3193 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3194 ARMul_UndefInstr (state, instr);
3195 /* Special treatment for XScale coprocessors. */
3196 else if (state->is_XScale)
3198 /* Only opcode 0 is supported. */
3199 if (BITS (4, 7) != 0x00)
3200 ARMul_UndefInstr (state, instr);
3201 /* Only coporcessor 0 is supported. */
3202 else if (CPNum != 0x00)
3203 ARMul_UndefInstr (state, instr);
3204 /* Only accumulator 0 is supported. */
3205 else if (BITS (0, 3) != 0x00)
3206 ARMul_UndefInstr (state, instr);
3209 /* XScale MAR insn. Move two registers into accumulator. */
3210 state->Accumulator = state->Reg[BITS (12, 15)];
3211 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
3215 /* FIXME: Not sure what to do for other v5 processors. */
3216 ARMul_UndefInstr (state, instr);
3221 case 0xc0: /* Store , No WriteBack , Post Dec. */
3222 ARMul_STC (state, instr, LHS);
3228 /* Writes to R15 are UNPREDICATABLE. */
3229 if (DESTReg == 15 || LHSReg == 15)
3230 ARMul_UndefInstr (state, instr);
3231 /* Is access to the coprocessor allowed ? */
3232 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3233 ARMul_UndefInstr (state, instr);
3234 /* Special handling for XScale coprcoessors. */
3235 else if (state->is_XScale)
3237 /* Only opcode 0 is supported. */
3238 if (BITS (4, 7) != 0x00)
3239 ARMul_UndefInstr (state, instr);
3240 /* Only coprocessor 0 is supported. */
3241 else if (CPNum != 0x00)
3242 ARMul_UndefInstr (state, instr);
3243 /* Only accumulator 0 is supported. */
3244 else if (BITS (0, 3) != 0x00)
3245 ARMul_UndefInstr (state, instr);
3248 /* XScale MRA insn. Move accumulator into two registers. */
3249 ARMword t1 = (state->Accumulator >> 32) & 255;
3254 state->Reg[BITS (12, 15)] = state->Accumulator;
3255 state->Reg[BITS (16, 19)] = t1;
3260 /* FIXME: Not sure what to do for other v5 processors. */
3261 ARMul_UndefInstr (state, instr);
3266 case 0xc1: /* Load , No WriteBack , Post Dec. */
3267 ARMul_LDC (state, instr, LHS);
3271 case 0xc6: /* Store , WriteBack , Post Dec. */
3273 state->Base = lhs - LSCOff;
3274 ARMul_STC (state, instr, lhs);
3278 case 0xc7: /* Load , WriteBack , Post Dec. */
3280 state->Base = lhs - LSCOff;
3281 ARMul_LDC (state, instr, lhs);
3285 case 0xcc: /* Store , No WriteBack , Post Inc. */
3286 ARMul_STC (state, instr, LHS);
3290 case 0xcd: /* Load , No WriteBack , Post Inc. */
3291 ARMul_LDC (state, instr, LHS);
3295 case 0xce: /* Store , WriteBack , Post Inc. */
3297 state->Base = lhs + LSCOff;
3298 ARMul_STC (state, instr, LHS);
3302 case 0xcf: /* Load , WriteBack , Post Inc. */
3304 state->Base = lhs + LSCOff;
3305 ARMul_LDC (state, instr, LHS);
3309 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3310 ARMul_STC (state, instr, LHS - LSCOff);
3314 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3315 ARMul_LDC (state, instr, LHS - LSCOff);
3319 case 0xd6: /* Store , WriteBack , Pre Dec. */
3322 ARMul_STC (state, instr, lhs);
3326 case 0xd7: /* Load , WriteBack , Pre Dec. */
3329 ARMul_LDC (state, instr, lhs);
3333 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3334 ARMul_STC (state, instr, LHS + LSCOff);
3338 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3339 ARMul_LDC (state, instr, LHS + LSCOff);
3343 case 0xde: /* Store , WriteBack , Pre Inc. */
3346 ARMul_STC (state, instr, lhs);
3350 case 0xdf: /* Load , WriteBack , Pre Inc. */
3353 ARMul_LDC (state, instr, lhs);
3357 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3360 if (! CP_ACCESS_ALLOWED (state, CPNum))
3362 ARMul_UndefInstr (state, instr);
3365 if (state->is_XScale)
3366 switch (BITS (18, 19))
3370 /* XScale MIA instruction. Signed multiplication of two 32 bit
3371 values and addition to 40 bit accumulator. */
3372 long long Rm = state->Reg[MULLHSReg];
3373 long long Rs = state->Reg[MULACCReg];
3379 state->Accumulator += Rm * Rs;
3385 /* XScale MIAPH instruction. */
3386 ARMword t1 = state->Reg[MULLHSReg] >> 16;
3387 ARMword t2 = state->Reg[MULACCReg] >> 16;
3388 ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
3389 ARMword t4 = state->Reg[MULACCReg] & 0xffff;
3404 state->Accumulator += t5;
3409 state->Accumulator += t5;
3415 /* XScale MIAxy instruction. */
3421 t1 = state->Reg[MULLHSReg] >> 16;
3423 t1 = state->Reg[MULLHSReg] & 0xffff;
3426 t2 = state->Reg[MULACCReg] >> 16;
3428 t2 = state->Reg[MULACCReg] & 0xffff;
3438 state->Accumulator += t5;
3461 ARMul_MCR (state, instr, state->Reg[15] + isize);
3463 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
3464 ((state->Reg[15] + isize) & R15PCBITS));
3468 ARMul_MCR (state, instr, DEST);
3472 ARMul_CDP (state, instr);
3476 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3488 temp = ARMul_MRC (state, instr);
3491 ASSIGNN ((temp & NBIT) != 0);
3492 ASSIGNZ ((temp & ZBIT) != 0);
3493 ASSIGNC ((temp & CBIT) != 0);
3494 ASSIGNV ((temp & VBIT) != 0);
3501 ARMul_CDP (state, instr);
3505 /* SWI instruction. */
3522 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
3524 /* A prefetch abort. */
3525 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
3526 ARMul_Abort (state, ARMul_PrefetchAbortV);
3530 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
3531 ARMul_Abort (state, ARMul_SWIV);
3541 #ifdef NEED_UI_LOOP_HOOK
3542 if (ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
3544 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
3547 #endif /* NEED_UI_LOOP_HOOK */
3549 if (state->Emulate == ONCE)
3550 state->Emulate = STOP;
3551 /* If we have changed mode, allow the PC to advance before stopping. */
3552 else if (state->Emulate == CHANGEMODE)
3554 else if (state->Emulate != RUN)
3557 while (!stop_simulator);
3559 state->decoded = decoded;
3560 state->loaded = loaded;
3566 /* This routine evaluates most Data Processing register RHS's with the S
3567 bit clear. It is intended to be called from the macro DPRegRHS, which
3568 filters the common case of an unshifted register with in line code. */
3571 GetDPRegRHS (ARMul_State * state, ARMword instr)
3573 ARMword shamt, base;
3578 /* Shift amount in a register. */
3583 base = ECC | ER15INT | R15PC | EMODE;
3586 base = state->Reg[base];
3587 ARMul_Icycles (state, 1, 0L);
3588 shamt = state->Reg[BITS (8, 11)] & 0xff;
3589 switch ((int) BITS (5, 6))
3594 else if (shamt >= 32)
3597 return (base << shamt);
3601 else if (shamt >= 32)
3604 return (base >> shamt);
3608 else if (shamt >= 32)
3609 return ((ARMword) ((long int) base >> 31L));
3611 return ((ARMword) ((long int) base >> (int) shamt));
3617 return ((base << (32 - shamt)) | (base >> shamt));
3622 /* Shift amount is a constant. */
3625 base = ECC | ER15INT | R15PC | EMODE;
3628 base = state->Reg[base];
3629 shamt = BITS (7, 11);
3630 switch ((int) BITS (5, 6))
3633 return (base << shamt);
3638 return (base >> shamt);
3641 return ((ARMword) ((long int) base >> 31L));
3643 return ((ARMword) ((long int) base >> (int) shamt));
3647 return ((base >> 1) | (CFLAG << 31));
3649 return ((base << (32 - shamt)) | (base >> shamt));
3656 /* This routine evaluates most Logical Data Processing register RHS's
3657 with the S bit set. It is intended to be called from the macro
3658 DPSRegRHS, which filters the common case of an unshifted register
3659 with in line code. */
3662 GetDPSRegRHS (ARMul_State * state, ARMword instr)
3664 ARMword shamt, base;
3669 /* Shift amount in a register. */
3674 base = ECC | ER15INT | R15PC | EMODE;
3677 base = state->Reg[base];
3678 ARMul_Icycles (state, 1, 0L);
3679 shamt = state->Reg[BITS (8, 11)] & 0xff;
3680 switch ((int) BITS (5, 6))
3685 else if (shamt == 32)
3690 else if (shamt > 32)
3697 ASSIGNC ((base >> (32 - shamt)) & 1);
3698 return (base << shamt);
3703 else if (shamt == 32)
3705 ASSIGNC (base >> 31);
3708 else if (shamt > 32)
3715 ASSIGNC ((base >> (shamt - 1)) & 1);
3716 return (base >> shamt);
3721 else if (shamt >= 32)
3723 ASSIGNC (base >> 31L);
3724 return ((ARMword) ((long int) base >> 31L));
3728 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3729 return ((ARMword) ((long int) base >> (int) shamt));
3737 ASSIGNC (base >> 31);
3742 ASSIGNC ((base >> (shamt - 1)) & 1);
3743 return ((base << (32 - shamt)) | (base >> shamt));
3749 /* Shift amount is a constant. */
3752 base = ECC | ER15INT | R15PC | EMODE;
3755 base = state->Reg[base];
3756 shamt = BITS (7, 11);
3758 switch ((int) BITS (5, 6))
3761 ASSIGNC ((base >> (32 - shamt)) & 1);
3762 return (base << shamt);
3766 ASSIGNC (base >> 31);
3771 ASSIGNC ((base >> (shamt - 1)) & 1);
3772 return (base >> shamt);
3777 ASSIGNC (base >> 31L);
3778 return ((ARMword) ((long int) base >> 31L));
3782 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3783 return ((ARMword) ((long int) base >> (int) shamt));
3791 return ((base >> 1) | (shamt << 31));
3795 ASSIGNC ((base >> (shamt - 1)) & 1);
3796 return ((base << (32 - shamt)) | (base >> shamt));
3804 /* This routine handles writes to register 15 when the S bit is not set. */
3807 WriteR15 (ARMul_State * state, ARMword src)
3809 /* The ARM documentation states that the two least significant bits
3810 are discarded when setting PC, except in the cases handled by
3811 WriteR15Branch() below. It's probably an oversight: in THUMB
3812 mode, the second least significant bit should probably not be
3822 state->Reg[15] = src & PCBITS;
3824 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
3825 ARMul_R15Altered (state);
3831 /* This routine handles writes to register 15 when the S bit is set. */
3834 WriteSR15 (ARMul_State * state, ARMword src)
3837 if (state->Bank > 0)
3839 state->Cpsr = state->Spsr[state->Bank];
3840 ARMul_CPSRAltered (state);
3848 state->Reg[15] = src & PCBITS;
3852 /* ARMul_R15Altered would have to support it. */
3858 if (state->Bank == USERBANK)
3859 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
3861 state->Reg[15] = src;
3863 ARMul_R15Altered (state);
3868 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3869 will switch to Thumb mode if the least significant bit is set. */
3872 WriteR15Branch (ARMul_State * state, ARMword src)
3879 state->Reg[15] = src & 0xfffffffe;
3884 state->Reg[15] = src & 0xfffffffc;
3888 WriteR15 (state, src);
3892 /* This routine evaluates most Load and Store register RHS's. It is
3893 intended to be called from the macro LSRegRHS, which filters the
3894 common case of an unshifted register with in line code. */
3897 GetLSRegRHS (ARMul_State * state, ARMword instr)
3899 ARMword shamt, base;
3904 /* Now forbidden, but ... */
3905 base = ECC | ER15INT | R15PC | EMODE;
3908 base = state->Reg[base];
3910 shamt = BITS (7, 11);
3911 switch ((int) BITS (5, 6))
3914 return (base << shamt);
3919 return (base >> shamt);
3922 return ((ARMword) ((long int) base >> 31L));
3924 return ((ARMword) ((long int) base >> (int) shamt));
3928 return ((base >> 1) | (CFLAG << 31));
3930 return ((base << (32 - shamt)) | (base >> shamt));
3937 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
3940 GetLS7RHS (ARMul_State * state, ARMword instr)
3947 /* Now forbidden, but ... */
3948 return ECC | ER15INT | R15PC | EMODE;
3950 return state->Reg[RHSReg];
3954 return BITS (0, 3) | (BITS (8, 11) << 4);
3957 /* This function does the work of loading a word for a LDR instruction. */
3960 LoadWord (ARMul_State * state, ARMword instr, ARMword address)
3966 if (ADDREXCEPT (address))
3967 INTERNALABORT (address);
3970 dest = ARMul_LoadWordN (state, address);
3975 return state->lateabtSig;
3978 dest = ARMul_Align (state, address, dest);
3980 ARMul_Icycles (state, 1, 0L);
3982 return (DESTReg != LHSReg);
3986 /* This function does the work of loading a halfword. */
3989 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
3996 if (ADDREXCEPT (address))
3997 INTERNALABORT (address);
3999 dest = ARMul_LoadHalfWord (state, address);
4003 return state->lateabtSig;
4007 if (dest & 1 << (16 - 1))
4008 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
4011 ARMul_Icycles (state, 1, 0L);
4012 return (DESTReg != LHSReg);
4017 /* This function does the work of loading a byte for a LDRB instruction. */
4020 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
4026 if (ADDREXCEPT (address))
4027 INTERNALABORT (address);
4029 dest = ARMul_LoadByte (state, address);
4033 return state->lateabtSig;
4037 if (dest & 1 << (8 - 1))
4038 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
4041 ARMul_Icycles (state, 1, 0L);
4043 return (DESTReg != LHSReg);
4046 /* This function does the work of loading two words for a LDRD instruction. */
4049 Handle_Load_Double (ARMul_State * state, ARMword instr)
4053 ARMword write_back = BIT (21);
4054 ARMword immediate = BIT (22);
4055 ARMword add_to_base = BIT (23);
4056 ARMword pre_indexed = BIT (24);
4066 /* If the writeback bit is set, the pre-index bit must be clear. */
4067 if (write_back && ! pre_indexed)
4069 ARMul_UndefInstr (state, instr);
4073 /* Extract the base address register. */
4076 /* Extract the destination register and check it. */
4079 /* Destination register must be even. */
4081 /* Destination register cannot be LR. */
4082 || (dest_reg == 14))
4084 ARMul_UndefInstr (state, instr);
4088 /* Compute the base address. */
4089 base = state->Reg[addr_reg];
4091 /* Compute the offset. */
4092 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4094 /* Compute the sum of the two. */
4096 sum = base + offset;
4098 sum = base - offset;
4100 /* If this is a pre-indexed mode use the sum. */
4106 /* The address must be aligned on a 8 byte boundary. */
4110 ARMul_DATAABORT (addr);
4112 ARMul_UndefInstr (state, instr);
4117 /* For pre indexed or post indexed addressing modes,
4118 check that the destination registers do not overlap
4119 the address registers. */
4120 if ((! pre_indexed || write_back)
4121 && ( addr_reg == dest_reg
4122 || addr_reg == dest_reg + 1))
4124 ARMul_UndefInstr (state, instr);
4128 /* Load the words. */
4129 value1 = ARMul_LoadWordN (state, addr);
4130 value2 = ARMul_LoadWordN (state, addr + 4);
4132 /* Check for data aborts. */
4139 ARMul_Icycles (state, 2, 0L);
4141 /* Store the values. */
4142 state->Reg[dest_reg] = value1;
4143 state->Reg[dest_reg + 1] = value2;
4145 /* Do the post addressing and writeback. */
4149 if (! pre_indexed || write_back)
4150 state->Reg[addr_reg] = addr;
4153 /* This function does the work of storing two words for a STRD instruction. */
4156 Handle_Store_Double (ARMul_State * state, ARMword instr)
4160 ARMword write_back = BIT (21);
4161 ARMword immediate = BIT (22);
4162 ARMword add_to_base = BIT (23);
4163 ARMword pre_indexed = BIT (24);
4171 /* If the writeback bit is set, the pre-index bit must be clear. */
4172 if (write_back && ! pre_indexed)
4174 ARMul_UndefInstr (state, instr);
4178 /* Extract the base address register. */
4181 /* Base register cannot be PC. */
4184 ARMul_UndefInstr (state, instr);
4188 /* Extract the source register. */
4191 /* Source register must be even. */
4194 ARMul_UndefInstr (state, instr);
4198 /* Compute the base address. */
4199 base = state->Reg[addr_reg];
4201 /* Compute the offset. */
4202 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4204 /* Compute the sum of the two. */
4206 sum = base + offset;
4208 sum = base - offset;
4210 /* If this is a pre-indexed mode use the sum. */
4216 /* The address must be aligned on a 8 byte boundary. */
4220 ARMul_DATAABORT (addr);
4222 ARMul_UndefInstr (state, instr);
4227 /* For pre indexed or post indexed addressing modes,
4228 check that the destination registers do not overlap
4229 the address registers. */
4230 if ((! pre_indexed || write_back)
4231 && ( addr_reg == src_reg
4232 || addr_reg == src_reg + 1))
4234 ARMul_UndefInstr (state, instr);
4238 /* Load the words. */
4239 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
4240 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
4248 /* Do the post addressing and writeback. */
4252 if (! pre_indexed || write_back)
4253 state->Reg[addr_reg] = addr;
4256 /* This function does the work of storing a word from a STR instruction. */
4259 StoreWord (ARMul_State * state, ARMword instr, ARMword address)
4264 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4267 ARMul_StoreWordN (state, address, DEST);
4269 if (VECTORACCESS (address) || ADDREXCEPT (address))
4271 INTERNALABORT (address);
4272 (void) ARMul_LoadWordN (state, address);
4275 ARMul_StoreWordN (state, address, DEST);
4280 return state->lateabtSig;
4286 /* This function does the work of storing a byte for a STRH instruction. */
4289 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
4295 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4299 ARMul_StoreHalfWord (state, address, DEST);
4301 if (VECTORACCESS (address) || ADDREXCEPT (address))
4303 INTERNALABORT (address);
4304 (void) ARMul_LoadHalfWord (state, address);
4307 ARMul_StoreHalfWord (state, address, DEST);
4313 return state->lateabtSig;
4320 /* This function does the work of storing a byte for a STRB instruction. */
4323 StoreByte (ARMul_State * state, ARMword instr, ARMword address)
4328 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4331 ARMul_StoreByte (state, address, DEST);
4333 if (VECTORACCESS (address) || ADDREXCEPT (address))
4335 INTERNALABORT (address);
4336 (void) ARMul_LoadByte (state, address);
4339 ARMul_StoreByte (state, address, DEST);
4344 return state->lateabtSig;
4350 /* This function does the work of loading the registers listed in an LDM
4351 instruction, when the S bit is clear. The code here is always increment
4352 after, it's up to the caller to get the input address correct and to
4353 handle base register modification. */
4356 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
4362 UNDEF_LSMBaseInListWb;
4365 if (ADDREXCEPT (address))
4366 INTERNALABORT (address);
4368 if (BIT (21) && LHSReg != 15)
4371 /* N cycle first. */
4372 for (temp = 0; !BIT (temp); temp++)
4375 dest = ARMul_LoadWordN (state, address);
4377 if (!state->abortSig && !state->Aborted)
4378 state->Reg[temp++] = dest;
4379 else if (!state->Aborted)
4381 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4382 state->Aborted = ARMul_DataAbortV;
4385 /* S cycles from here on. */
4386 for (; temp < 16; temp ++)
4389 /* Load this register. */
4391 dest = ARMul_LoadWordS (state, address);
4393 if (!state->abortSig && !state->Aborted)
4394 state->Reg[temp] = dest;
4395 else if (!state->Aborted)
4397 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4398 state->Aborted = ARMul_DataAbortV;
4402 if (BIT (15) && !state->Aborted)
4403 /* PC is in the reg list. */
4404 WriteR15Branch (state, PC);
4406 /* To write back the final register. */
4407 ARMul_Icycles (state, 1, 0L);
4411 if (BIT (21) && LHSReg != 15)
4417 /* This function does the work of loading the registers listed in an LDM
4418 instruction, when the S bit is set. The code here is always increment
4419 after, it's up to the caller to get the input address correct and to
4420 handle base register modification. */
4423 LoadSMult (ARMul_State * state,
4432 UNDEF_LSMBaseInListWb;
4437 if (ADDREXCEPT (address))
4438 INTERNALABORT (address);
4441 if (BIT (21) && LHSReg != 15)
4444 if (!BIT (15) && state->Bank != USERBANK)
4446 /* Temporary reg bank switch. */
4447 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4448 UNDEF_LSMUserBankWb;
4451 /* N cycle first. */
4452 for (temp = 0; !BIT (temp); temp ++)
4455 dest = ARMul_LoadWordN (state, address);
4457 if (!state->abortSig)
4458 state->Reg[temp++] = dest;
4459 else if (!state->Aborted)
4461 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4462 state->Aborted = ARMul_DataAbortV;
4465 /* S cycles from here on. */
4466 for (; temp < 16; temp++)
4469 /* Load this register. */
4471 dest = ARMul_LoadWordS (state, address);
4473 if (!state->abortSig && !state->Aborted)
4474 state->Reg[temp] = dest;
4475 else if (!state->Aborted)
4477 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4478 state->Aborted = ARMul_DataAbortV;
4482 if (BIT (15) && !state->Aborted)
4484 /* PC is in the reg list. */
4486 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4488 state->Cpsr = GETSPSR (state->Bank);
4489 ARMul_CPSRAltered (state);
4492 WriteR15 (state, PC);
4494 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
4496 /* Protect bits in user mode. */
4497 ASSIGNN ((state->Reg[15] & NBIT) != 0);
4498 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
4499 ASSIGNC ((state->Reg[15] & CBIT) != 0);
4500 ASSIGNV ((state->Reg[15] & VBIT) != 0);
4503 ARMul_R15Altered (state);
4509 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
4510 /* Restore the correct bank. */
4511 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4513 /* To write back the final register. */
4514 ARMul_Icycles (state, 1, 0L);
4518 if (BIT (21) && LHSReg != 15)
4525 /* This function does the work of storing the registers listed in an STM
4526 instruction, when the S bit is clear. The code here is always increment
4527 after, it's up to the caller to get the input address correct and to
4528 handle base register modification. */
4531 StoreMult (ARMul_State * state,
4540 UNDEF_LSMBaseInListWb;
4543 /* N-cycle, increment the PC and update the NextInstr state. */
4547 if (VECTORACCESS (address) || ADDREXCEPT (address))
4548 INTERNALABORT (address);
4554 /* N cycle first. */
4555 for (temp = 0; !BIT (temp); temp ++)
4559 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4563 (void) ARMul_LoadWordN (state, address);
4565 /* Fake the Stores as Loads. */
4566 for (; temp < 16; temp++)
4569 /* Save this register. */
4571 (void) ARMul_LoadWordS (state, address);
4574 if (BIT (21) && LHSReg != 15)
4580 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4583 if (state->abortSig && !state->Aborted)
4585 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4586 state->Aborted = ARMul_DataAbortV;
4589 if (BIT (21) && LHSReg != 15)
4592 /* S cycles from here on. */
4593 for (; temp < 16; temp ++)
4596 /* Save this register. */
4599 ARMul_StoreWordS (state, address, state->Reg[temp]);
4601 if (state->abortSig && !state->Aborted)
4603 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4604 state->Aborted = ARMul_DataAbortV;
4612 /* This function does the work of storing the registers listed in an STM
4613 instruction when the S bit is set. The code here is always increment
4614 after, it's up to the caller to get the input address correct and to
4615 handle base register modification. */
4618 StoreSMult (ARMul_State * state,
4627 UNDEF_LSMBaseInListWb;
4632 if (VECTORACCESS (address) || ADDREXCEPT (address))
4633 INTERNALABORT (address);
4639 if (state->Bank != USERBANK)
4641 /* Force User Bank. */
4642 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4643 UNDEF_LSMUserBankWb;
4646 for (temp = 0; !BIT (temp); temp++)
4647 ; /* N cycle first. */
4650 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4654 (void) ARMul_LoadWordN (state, address);
4656 for (; temp < 16; temp++)
4657 /* Fake the Stores as Loads. */
4660 /* Save this register. */
4663 (void) ARMul_LoadWordS (state, address);
4666 if (BIT (21) && LHSReg != 15)
4673 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4676 if (state->abortSig && !state->Aborted)
4678 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4679 state->Aborted = ARMul_DataAbortV;
4682 /* S cycles from here on. */
4683 for (; temp < 16; temp++)
4686 /* Save this register. */
4689 ARMul_StoreWordS (state, address, state->Reg[temp]);
4691 if (state->abortSig && !state->Aborted)
4693 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4694 state->Aborted = ARMul_DataAbortV;
4698 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4699 /* Restore the correct bank. */
4700 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4702 if (BIT (21) && LHSReg != 15)
4709 /* This function does the work of adding two 32bit values
4710 together, and calculating if a carry has occurred. */
4713 Add32 (ARMword a1, ARMword a2, int *carry)
4715 ARMword result = (a1 + a2);
4716 unsigned int uresult = (unsigned int) result;
4717 unsigned int ua1 = (unsigned int) a1;
4719 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4720 or (result > RdLo) then we have no carry. */
4721 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
4729 /* This function does the work of multiplying
4730 two 32bit values to give a 64bit result. */
4733 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
4735 /* Operand register numbers. */
4736 int nRdHi, nRdLo, nRs, nRm;
4737 ARMword RdHi = 0, RdLo = 0, Rm;
4741 nRdHi = BITS (16, 19);
4742 nRdLo = BITS (12, 15);
4746 /* Needed to calculate the cycle count. */
4747 Rm = state->Reg[nRm];
4749 /* Check for illegal operand combinations first. */
4758 /* Intermediate results. */
4759 ARMword lo, mid1, mid2, hi;
4761 ARMword Rs = state->Reg[nRs];
4766 /* Compute sign of result and adjust operands if necessary. */
4767 sign = (Rm ^ Rs) & 0x80000000;
4769 if (((signed long) Rm) < 0)
4772 if (((signed long) Rs) < 0)
4776 /* We can split the 32x32 into four 16x16 operations. This
4777 ensures that we do not lose precision on 32bit only hosts. */
4778 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
4779 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4780 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
4781 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4783 /* We now need to add all of these results together, taking
4784 care to propogate the carries from the additions. */
4785 RdLo = Add32 (lo, (mid1 << 16), &carry);
4787 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
4789 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
4793 /* Negate result if necessary. */
4796 if (RdLo == 0xFFFFFFFF)
4805 state->Reg[nRdLo] = RdLo;
4806 state->Reg[nRdHi] = RdHi;
4809 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4812 /* Ensure that both RdHi and RdLo are used to compute Z,
4813 but don't let RdLo's sign bit make it to N. */
4814 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4816 /* The cycle count depends on whether the instruction is a signed or
4817 unsigned multiply, and what bits are clear in the multiplier. */
4818 if (msigned && (Rm & ((unsigned) 1 << 31)))
4819 /* Invert the bits to make the check against zero. */
4822 if ((Rm & 0xFFFFFF00) == 0)
4824 else if ((Rm & 0xFFFF0000) == 0)
4826 else if ((Rm & 0xFF000000) == 0)
4834 /* This function does the work of multiplying two 32bit
4835 values and adding a 64bit value to give a 64bit result. */
4838 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
4845 nRdHi = BITS (16, 19);
4846 nRdLo = BITS (12, 15);
4848 RdHi = state->Reg[nRdHi];
4849 RdLo = state->Reg[nRdLo];
4851 scount = Multiply64 (state, instr, msigned, LDEFAULT);
4853 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
4854 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
4856 state->Reg[nRdLo] = RdLo;
4857 state->Reg[nRdHi] = RdHi;
4860 /* Ensure that both RdHi and RdLo are used to compute Z,
4861 but don't let RdLo's sign bit make it to N. */
4862 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4864 /* Extra cycle for addition. */