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. */
26 static ARMword GetDPRegRHS (ARMul_State *, ARMword);
27 static ARMword GetDPSRegRHS (ARMul_State *, ARMword);
28 static void WriteR15 (ARMul_State *, ARMword);
29 static void WriteSR15 (ARMul_State *, ARMword);
30 static void WriteR15Branch (ARMul_State *, ARMword);
31 static ARMword GetLSRegRHS (ARMul_State *, ARMword);
32 static ARMword GetLS7RHS (ARMul_State *, ARMword);
33 static unsigned LoadWord (ARMul_State *, ARMword, ARMword);
34 static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int);
35 static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int);
36 static unsigned StoreWord (ARMul_State *, ARMword, ARMword);
37 static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword);
38 static unsigned StoreByte (ARMul_State *, ARMword, ARMword);
39 static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword);
40 static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword);
41 static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword);
42 static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword);
43 static unsigned Multiply64 (ARMul_State *, ARMword, int, int);
44 static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int);
45 static void Handle_Load_Double (ARMul_State *, ARMword);
46 static void Handle_Store_Double (ARMul_State *, ARMword);
48 #define LUNSIGNED (0) /* unsigned operation */
49 #define LSIGNED (1) /* signed operation */
50 #define LDEFAULT (0) /* default : do nothing */
51 #define LSCC (1) /* set condition codes on result */
53 #ifdef NEED_UI_LOOP_HOOK
54 /* How often to run the ui_loop update, when in use. */
55 #define UI_LOOP_POLL_INTERVAL 0x32000
57 /* Counter for the ui_loop_hook update. */
58 static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
60 /* Actual hook to call to run through gdb's gui event loop. */
61 extern int (*ui_loop_hook) (int);
62 #endif /* NEED_UI_LOOP_HOOK */
64 extern int stop_simulator;
66 /* Short-hand macros for LDR/STR. */
68 /* Store post decrement writeback. */
71 if (StoreHalfWord (state, instr, lhs)) \
72 LSBase = lhs - GetLS7RHS (state, instr);
74 /* Store post increment writeback. */
77 if (StoreHalfWord (state, instr, lhs)) \
78 LSBase = lhs + GetLS7RHS (state, instr);
80 /* Store pre decrement. */
82 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
84 /* Store pre decrement writeback. */
85 #define SHPREDOWNWB() \
86 temp = LHS - GetLS7RHS (state, instr); \
87 if (StoreHalfWord (state, instr, temp)) \
90 /* Store pre increment. */
92 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
94 /* Store pre increment writeback. */
96 temp = LHS + GetLS7RHS (state, instr); \
97 if (StoreHalfWord (state, instr, temp)) \
100 /* Load post decrement writeback. */
101 #define LHPOSTDOWN() \
105 temp = lhs - GetLS7RHS (state, instr); \
107 switch (BITS (5, 6)) \
110 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
114 if (LoadByte (state, instr, lhs, LSIGNED)) \
118 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
121 case 0: /* SWP handled elsewhere. */ \
130 /* Load post increment writeback. */
135 temp = lhs + GetLS7RHS (state, instr); \
137 switch (BITS (5, 6)) \
140 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
144 if (LoadByte (state, instr, lhs, LSIGNED)) \
148 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
151 case 0: /* SWP handled elsewhere. */ \
160 /* Load pre decrement. */
161 #define LHPREDOWN() \
165 temp = LHS - GetLS7RHS (state, instr); \
166 switch (BITS (5, 6)) \
169 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
172 (void) LoadByte (state, instr, temp, LSIGNED); \
175 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
178 /* SWP handled elsewhere. */ \
187 /* Load pre decrement writeback. */
188 #define LHPREDOWNWB() \
192 temp = LHS - GetLS7RHS (state, instr); \
193 switch (BITS (5, 6)) \
196 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
200 if (LoadByte (state, instr, temp, LSIGNED)) \
204 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
208 /* SWP handled elsewhere. */ \
217 /* Load pre increment. */
222 temp = LHS + GetLS7RHS (state, instr); \
223 switch (BITS (5, 6)) \
226 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
229 (void) LoadByte (state, instr, temp, LSIGNED); \
232 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
235 /* SWP handled elsewhere. */ \
244 /* Load pre increment writeback. */
245 #define LHPREUPWB() \
249 temp = LHS + GetLS7RHS (state, instr); \
250 switch (BITS (5, 6)) \
253 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
257 if (LoadByte (state, instr, temp, LSIGNED)) \
261 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
265 /* SWP handled elsewhere. */ \
274 /* EMULATION of ARM6. */
276 /* The PC pipeline value depends on whether ARM
277 or Thumb instructions are being executed. */
282 ARMul_Emulate32 (ARMul_State * state)
284 ARMul_Emulate26 (ARMul_State * state)
287 ARMword instr; /* The current instruction. */
288 ARMword dest = 0; /* Almost the DestBus. */
289 ARMword temp; /* Ubiquitous third hand. */
290 ARMword pc = 0; /* The address of the current instruction. */
291 ARMword lhs; /* Almost the ABus and BBus. */
293 ARMword decoded = 0; /* Instruction pipeline. */
296 /* Execute the next instruction. */
298 if (state->NextInstr < PRIMEPIPE)
300 decoded = state->decoded;
301 loaded = state->loaded;
307 /* Just keep going. */
310 switch (state->NextInstr)
313 /* Advance the pipeline, and an S cycle. */
314 state->Reg[15] += isize;
318 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
322 /* Advance the pipeline, and an N cycle. */
323 state->Reg[15] += isize;
327 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
332 /* Program counter advanced, and an S cycle. */
336 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
341 /* Program counter advanced, and an N cycle. */
345 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
350 /* The program counter has been changed. */
355 state->Reg[15] = pc + (isize * 2);
357 instr = ARMul_ReLoadInstr (state, pc, isize);
358 decoded = ARMul_ReLoadInstr (state, pc + isize, isize);
359 loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize);
364 /* The program counter has been changed. */
369 state->Reg[15] = pc + (isize * 2);
371 instr = ARMul_LoadInstrN (state, pc, isize);
372 decoded = ARMul_LoadInstrS (state, pc + (isize), isize);
373 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
379 ARMul_EnvokeEvent (state);
381 /* Enable this for a helpful bit of debugging when tracing is needed. */
382 fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr);
389 static ARMword old_sp = -1;
391 if (old_sp != state->Reg[13])
393 old_sp = state->Reg[13];
394 fprintf (stderr, "pc: %08x: SP set to %08x%s\n",
395 pc & ~1, old_sp, (old_sp % 8) ? " [UNALIGNED!]" : "");
401 if (state->Exception)
403 /* Any exceptions ? */
404 if (state->NresetSig == LOW)
406 ARMul_Abort (state, ARMul_ResetV);
409 else if (!state->NfiqSig && !FFLAG)
411 ARMul_Abort (state, ARMul_FIQV);
414 else if (!state->NirqSig && !IFLAG)
416 ARMul_Abort (state, ARMul_IRQV);
421 if (state->CallDebug > 0)
423 instr = ARMul_Debug (state, pc, instr);
424 if (state->Emulate < ONCE)
426 state->NextInstr = RESUME;
431 fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n", pc, instr,
433 (void) fgetc (stdin);
436 else if (state->Emulate < ONCE)
438 state->NextInstr = RESUME;
445 /* Provide Thumb instruction decoding. If the processor is in Thumb
446 mode, then we can simply decode the Thumb instruction, and map it
447 to the corresponding ARM instruction (by directly loading the
448 instr variable, and letting the normal ARM simulator
449 execute). There are some caveats to ensure that the correct
450 pipelined PC value is used when executing Thumb code, and also for
451 dealing with the BL instruction. */
456 /* Check if in Thumb mode. */
457 switch (ARMul_ThumbDecode (state, pc, instr, &new))
460 /* This is a Thumb instruction. */
461 ARMul_UndefInstr (state, instr);
465 /* Already processed. */
469 /* ARM instruction available. */
471 /* So continue instruction decoding. */
479 /* Check the condition codes. */
480 if ((temp = TOPBITS (28)) == AL)
481 /* Vile deed in the need for speed. */
484 /* Check the condition code. */
485 switch ((int) TOPBITS (28))
493 if (BITS (25, 27) == 5) /* BLX(1) */
497 state->Reg[14] = pc + 4;
499 /* Force entry into Thumb mode. */
502 dest += (NEGBRANCH + (BIT (24) << 1));
504 dest += POSBRANCH + (BIT (24) << 1);
506 WriteR15Branch (state, dest);
509 else if ((instr & 0xFC70F000) == 0xF450F000)
510 /* The PLD instruction. Ignored. */
513 else if ( ((instr & 0xfe500f00) == 0xfc100100)
514 || ((instr & 0xfe500f00) == 0xfc000100))
515 /* wldrw and wstrw are unconditional. */
519 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
520 ARMul_UndefInstr (state, instr);
549 temp = (CFLAG && !ZFLAG);
552 temp = (!CFLAG || ZFLAG);
555 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
558 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
561 temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
564 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
568 /* Handle the Clock counter here. */
569 if (state->is_XScale)
574 ok = state->CPRead[14] (state, 0, & cp14r0);
576 if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE))
578 unsigned long newcycles, nowtime = ARMul_Time (state);
580 newcycles = nowtime - state->LastTime;
581 state->LastTime = nowtime;
583 if (cp14r0 & ARMul_CP14_R0_CCD)
585 if (state->CP14R0_CCD == -1)
586 state->CP14R0_CCD = newcycles;
588 state->CP14R0_CCD += newcycles;
590 if (state->CP14R0_CCD >= 64)
594 while (state->CP14R0_CCD >= 64)
595 state->CP14R0_CCD -= 64, newcycles++;
605 state->CP14R0_CCD = -1;
607 cp14r0 |= ARMul_CP14_R0_FLAG2;
608 (void) state->CPWrite[14] (state, 0, cp14r0);
610 ok = state->CPRead[14] (state, 1, & cp14r1);
612 /* Coded like this for portability. */
613 while (ok && newcycles)
615 if (cp14r1 == 0xffffffff)
626 (void) state->CPWrite[14] (state, 1, cp14r1);
628 if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2))
632 if (state->CPRead[13] (state, 8, & temp)
633 && (temp & ARMul_CP13_R8_PMUS))
634 ARMul_Abort (state, ARMul_FIQV);
636 ARMul_Abort (state, ARMul_IRQV);
642 /* Handle hardware instructions breakpoints here. */
643 if (state->is_XScale)
645 if ( (pc | 3) == (read_cp15_reg (14, 0, 8) | 2)
646 || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2))
648 if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB))
649 ARMul_OSHandleSWI (state, SWI_Breakpoint);
653 /* Actual execution of instructions begins here. */
654 /* If the condition codes don't match, stop here. */
659 if (state->is_XScale)
661 if (BIT (20) == 0 && BITS (25, 27) == 0)
663 if (BITS (4, 7) == 0xD)
665 /* XScale Load Consecutive insn. */
666 ARMword temp = GetLS7RHS (state, instr);
667 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
668 ARMword addr = BIT (24) ? temp2 : LHS;
671 ARMul_UndefInstr (state, instr);
673 /* Alignment violation. */
674 ARMul_Abort (state, ARMul_DataAbortV);
677 int wb = BIT (21) || (! BIT (24));
679 state->Reg[BITS (12, 15)] =
680 ARMul_LoadWordN (state, addr);
681 state->Reg[BITS (12, 15) + 1] =
682 ARMul_LoadWordN (state, addr + 4);
689 else if (BITS (4, 7) == 0xF)
691 /* XScale Store Consecutive insn. */
692 ARMword temp = GetLS7RHS (state, instr);
693 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
694 ARMword addr = BIT (24) ? temp2 : LHS;
697 ARMul_UndefInstr (state, instr);
699 /* Alignment violation. */
700 ARMul_Abort (state, ARMul_DataAbortV);
703 ARMul_StoreWordN (state, addr,
704 state->Reg[BITS (12, 15)]);
705 ARMul_StoreWordN (state, addr + 4,
706 state->Reg[BITS (12, 15) + 1]);
708 if (BIT (21)|| ! BIT (24))
716 if (ARMul_HandleIwmmxt (state, instr))
721 switch ((int) BITS (20, 27))
723 /* Data Processing Register RHS Instructions. */
725 case 0x00: /* AND reg and MUL */
727 if (BITS (4, 11) == 0xB)
729 /* STRH register offset, no write-back, down, post indexed. */
733 if (BITS (4, 7) == 0xD)
735 Handle_Load_Double (state, instr);
738 if (BITS (4, 7) == 0xF)
740 Handle_Store_Double (state, instr);
744 if (BITS (4, 7) == 9)
747 rhs = state->Reg[MULRHSReg];
748 if (MULLHSReg == MULDESTReg)
751 state->Reg[MULDESTReg] = 0;
753 else if (MULDESTReg != 15)
754 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
758 for (dest = 0, temp = 0; dest < 32; dest ++)
759 if (rhs & (1L << dest))
762 /* Mult takes this many/2 I cycles. */
763 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
774 case 0x01: /* ANDS reg and MULS */
776 if ((BITS (4, 11) & 0xF9) == 0x9)
777 /* LDR register offset, no write-back, down, post indexed. */
779 /* Fall through to rest of decoding. */
781 if (BITS (4, 7) == 9)
784 rhs = state->Reg[MULRHSReg];
786 if (MULLHSReg == MULDESTReg)
789 state->Reg[MULDESTReg] = 0;
793 else if (MULDESTReg != 15)
795 dest = state->Reg[MULLHSReg] * rhs;
796 ARMul_NegZero (state, dest);
797 state->Reg[MULDESTReg] = dest;
802 for (dest = 0, temp = 0; dest < 32; dest ++)
803 if (rhs & (1L << dest))
806 /* Mult takes this many/2 I cycles. */
807 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
818 case 0x02: /* EOR reg and MLA */
820 if (BITS (4, 11) == 0xB)
822 /* STRH register offset, write-back, down, post indexed. */
827 if (BITS (4, 7) == 9)
829 rhs = state->Reg[MULRHSReg];
830 if (MULLHSReg == MULDESTReg)
833 state->Reg[MULDESTReg] = state->Reg[MULACCReg];
835 else if (MULDESTReg != 15)
836 state->Reg[MULDESTReg] =
837 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
841 for (dest = 0, temp = 0; dest < 32; dest ++)
842 if (rhs & (1L << dest))
845 /* Mult takes this many/2 I cycles. */
846 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
856 case 0x03: /* EORS reg and MLAS */
858 if ((BITS (4, 11) & 0xF9) == 0x9)
859 /* LDR register offset, write-back, down, post-indexed. */
861 /* Fall through to rest of the decoding. */
863 if (BITS (4, 7) == 9)
866 rhs = state->Reg[MULRHSReg];
868 if (MULLHSReg == MULDESTReg)
871 dest = state->Reg[MULACCReg];
872 ARMul_NegZero (state, dest);
873 state->Reg[MULDESTReg] = dest;
875 else if (MULDESTReg != 15)
878 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
879 ARMul_NegZero (state, dest);
880 state->Reg[MULDESTReg] = dest;
885 for (dest = 0, temp = 0; dest < 32; dest ++)
886 if (rhs & (1L << dest))
889 /* Mult takes this many/2 I cycles. */
890 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
901 case 0x04: /* SUB reg */
903 if (BITS (4, 7) == 0xB)
905 /* STRH immediate offset, no write-back, down, post indexed. */
909 if (BITS (4, 7) == 0xD)
911 Handle_Load_Double (state, instr);
914 if (BITS (4, 7) == 0xF)
916 Handle_Store_Double (state, instr);
925 case 0x05: /* SUBS reg */
927 if ((BITS (4, 7) & 0x9) == 0x9)
928 /* LDR immediate offset, no write-back, down, post indexed. */
930 /* Fall through to the rest of the instruction decoding. */
936 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
938 ARMul_SubCarry (state, lhs, rhs, dest);
939 ARMul_SubOverflow (state, lhs, rhs, dest);
949 case 0x06: /* RSB reg */
951 if (BITS (4, 7) == 0xB)
953 /* STRH immediate offset, write-back, down, post indexed. */
963 case 0x07: /* RSBS reg */
965 if ((BITS (4, 7) & 0x9) == 0x9)
966 /* LDR immediate offset, write-back, down, post indexed. */
968 /* Fall through to remainder of instruction decoding. */
974 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
976 ARMul_SubCarry (state, rhs, lhs, dest);
977 ARMul_SubOverflow (state, rhs, lhs, dest);
987 case 0x08: /* ADD reg */
989 if (BITS (4, 11) == 0xB)
991 /* STRH register offset, no write-back, up, post indexed. */
995 if (BITS (4, 7) == 0xD)
997 Handle_Load_Double (state, instr);
1000 if (BITS (4, 7) == 0xF)
1002 Handle_Store_Double (state, instr);
1007 if (BITS (4, 7) == 0x9)
1011 ARMul_Icycles (state,
1012 Multiply64 (state, instr, LUNSIGNED,
1022 case 0x09: /* ADDS reg */
1024 if ((BITS (4, 11) & 0xF9) == 0x9)
1025 /* LDR register offset, no write-back, up, post indexed. */
1027 /* Fall through to remaining instruction decoding. */
1030 if (BITS (4, 7) == 0x9)
1034 ARMul_Icycles (state,
1035 Multiply64 (state, instr, LUNSIGNED, LSCC),
1043 ASSIGNZ (dest == 0);
1044 if ((lhs | rhs) >> 30)
1046 /* Possible C,V,N to set. */
1047 ASSIGNN (NEG (dest));
1048 ARMul_AddCarry (state, lhs, rhs, dest);
1049 ARMul_AddOverflow (state, lhs, rhs, dest);
1060 case 0x0a: /* ADC reg */
1062 if (BITS (4, 11) == 0xB)
1064 /* STRH register offset, write-back, up, post-indexed. */
1068 if (BITS (4, 7) == 0x9)
1072 ARMul_Icycles (state,
1073 MultiplyAdd64 (state, instr, LUNSIGNED,
1079 dest = LHS + rhs + CFLAG;
1083 case 0x0b: /* ADCS reg */
1085 if ((BITS (4, 11) & 0xF9) == 0x9)
1086 /* LDR register offset, write-back, up, post indexed. */
1088 /* Fall through to remaining instruction decoding. */
1089 if (BITS (4, 7) == 0x9)
1093 ARMul_Icycles (state,
1094 MultiplyAdd64 (state, instr, LUNSIGNED,
1101 dest = lhs + rhs + CFLAG;
1102 ASSIGNZ (dest == 0);
1103 if ((lhs | rhs) >> 30)
1105 /* Possible C,V,N to set. */
1106 ASSIGNN (NEG (dest));
1107 ARMul_AddCarry (state, lhs, rhs, dest);
1108 ARMul_AddOverflow (state, lhs, rhs, dest);
1119 case 0x0c: /* SBC reg */
1121 if (BITS (4, 7) == 0xB)
1123 /* STRH immediate offset, no write-back, up post indexed. */
1127 if (BITS (4, 7) == 0xD)
1129 Handle_Load_Double (state, instr);
1132 if (BITS (4, 7) == 0xF)
1134 Handle_Store_Double (state, instr);
1137 if (BITS (4, 7) == 0x9)
1141 ARMul_Icycles (state,
1142 Multiply64 (state, instr, LSIGNED, LDEFAULT),
1148 dest = LHS - rhs - !CFLAG;
1152 case 0x0d: /* SBCS reg */
1154 if ((BITS (4, 7) & 0x9) == 0x9)
1155 /* LDR immediate offset, no write-back, up, post indexed. */
1158 if (BITS (4, 7) == 0x9)
1162 ARMul_Icycles (state,
1163 Multiply64 (state, instr, LSIGNED, LSCC),
1170 dest = lhs - rhs - !CFLAG;
1171 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1173 ARMul_SubCarry (state, lhs, rhs, dest);
1174 ARMul_SubOverflow (state, lhs, rhs, dest);
1184 case 0x0e: /* RSC reg */
1186 if (BITS (4, 7) == 0xB)
1188 /* STRH immediate offset, write-back, up, post indexed. */
1193 if (BITS (4, 7) == 0x9)
1197 ARMul_Icycles (state,
1198 MultiplyAdd64 (state, instr, LSIGNED,
1204 dest = rhs - LHS - !CFLAG;
1208 case 0x0f: /* RSCS reg */
1210 if ((BITS (4, 7) & 0x9) == 0x9)
1211 /* LDR immediate offset, write-back, up, post indexed. */
1213 /* Fall through to remaining instruction decoding. */
1215 if (BITS (4, 7) == 0x9)
1219 ARMul_Icycles (state,
1220 MultiplyAdd64 (state, instr, LSIGNED, LSCC),
1227 dest = rhs - lhs - !CFLAG;
1229 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1231 ARMul_SubCarry (state, rhs, lhs, dest);
1232 ARMul_SubOverflow (state, rhs, lhs, dest);
1242 case 0x10: /* TST reg and MRS CPSR and SWP word. */
1245 if (BIT (4) == 0 && BIT (7) == 1)
1247 /* ElSegundo SMLAxy insn. */
1248 ARMword op1 = state->Reg[BITS (0, 3)];
1249 ARMword op2 = state->Reg[BITS (8, 11)];
1250 ARMword Rn = state->Reg[BITS (12, 15)];
1264 if (AddOverflow (op1, Rn, op1 + Rn))
1266 state->Reg[BITS (16, 19)] = op1 + Rn;
1270 if (BITS (4, 11) == 5)
1272 /* ElSegundo QADD insn. */
1273 ARMword op1 = state->Reg[BITS (0, 3)];
1274 ARMword op2 = state->Reg[BITS (16, 19)];
1275 ARMword result = op1 + op2;
1276 if (AddOverflow (op1, op2, result))
1278 result = POS (result) ? 0x80000000 : 0x7fffffff;
1281 state->Reg[BITS (12, 15)] = result;
1286 if (BITS (4, 11) == 0xB)
1288 /* STRH register offset, no write-back, down, pre indexed. */
1292 if (BITS (4, 7) == 0xD)
1294 Handle_Load_Double (state, instr);
1297 if (BITS (4, 7) == 0xF)
1299 Handle_Store_Double (state, instr);
1303 if (BITS (4, 11) == 9)
1310 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
1312 INTERNALABORT (temp);
1313 (void) ARMul_LoadWordN (state, temp);
1314 (void) ARMul_LoadWordN (state, temp);
1318 dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
1320 DEST = ARMul_Align (state, temp, dest);
1323 if (state->abortSig || state->Aborted)
1326 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
1329 DEST = ECC | EINT | EMODE;
1337 case 0x11: /* TSTP reg */
1339 if ((BITS (4, 11) & 0xF9) == 0x9)
1340 /* LDR register offset, no write-back, down, pre indexed. */
1342 /* Continue with remaining instruction decode. */
1348 state->Cpsr = GETSPSR (state->Bank);
1349 ARMul_CPSRAltered (state);
1361 ARMul_NegZero (state, dest);
1365 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
1368 if (BITS (4, 7) == 3)
1374 temp = (pc + 2) | 1;
1378 WriteR15Branch (state, state->Reg[RHSReg]);
1379 state->Reg[14] = temp;
1386 if (BIT (4) == 0 && BIT (7) == 1
1387 && (BIT (5) == 0 || BITS (12, 15) == 0))
1389 /* ElSegundo SMLAWy/SMULWy insn. */
1390 unsigned long long op1 = state->Reg[BITS (0, 3)];
1391 unsigned long long op2 = state->Reg[BITS (8, 11)];
1392 unsigned long long result;
1396 if (op1 & 0x80000000)
1401 result = (op1 * op2) >> 16;
1405 ARMword Rn = state->Reg[BITS (12, 15)];
1407 if (AddOverflow (result, Rn, result + Rn))
1411 state->Reg[BITS (16, 19)] = result;
1415 if (BITS (4, 11) == 5)
1417 /* ElSegundo QSUB insn. */
1418 ARMword op1 = state->Reg[BITS (0, 3)];
1419 ARMword op2 = state->Reg[BITS (16, 19)];
1420 ARMword result = op1 - op2;
1422 if (SubOverflow (op1, op2, result))
1424 result = POS (result) ? 0x80000000 : 0x7fffffff;
1428 state->Reg[BITS (12, 15)] = result;
1433 if (BITS (4, 11) == 0xB)
1435 /* STRH register offset, write-back, down, pre indexed. */
1439 if (BITS (4, 27) == 0x12FFF1)
1442 WriteR15Branch (state, state->Reg[RHSReg]);
1445 if (BITS (4, 7) == 0xD)
1447 Handle_Load_Double (state, instr);
1450 if (BITS (4, 7) == 0xF)
1452 Handle_Store_Double (state, instr);
1458 if (BITS (4, 7) == 0x7)
1461 extern int SWI_vector_installed;
1463 /* Hardware is allowed to optionally override this
1464 instruction and treat it as a breakpoint. Since
1465 this is a simulator not hardware, we take the position
1466 that if a SWI vector was not installed, then an Abort
1467 vector was probably not installed either, and so
1468 normally this instruction would be ignored, even if an
1469 Abort is generated. This is a bad thing, since GDB
1470 uses this instruction for its breakpoints (at least in
1471 Thumb mode it does). So intercept the instruction here
1472 and generate a breakpoint SWI instead. */
1473 if (! SWI_vector_installed)
1474 ARMul_OSHandleSWI (state, SWI_Breakpoint);
1477 /* BKPT - normally this will cause an abort, but on the
1478 XScale we must check the DCSR. */
1479 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
1480 if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT))
1484 /* Force the next instruction to be refetched. */
1485 state->NextInstr = RESUME;
1491 /* MSR reg to CPSR. */
1495 /* Don't allow TBIT to be set by MSR. */
1498 ARMul_FixCPSR (state, instr, temp);
1505 case 0x13: /* TEQP reg */
1507 if ((BITS (4, 11) & 0xF9) == 0x9)
1508 /* LDR register offset, write-back, down, pre indexed. */
1510 /* Continue with remaining instruction decode. */
1516 state->Cpsr = GETSPSR (state->Bank);
1517 ARMul_CPSRAltered (state);
1529 ARMul_NegZero (state, dest);
1533 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
1536 if (BIT (4) == 0 && BIT (7) == 1)
1538 /* ElSegundo SMLALxy insn. */
1539 unsigned long long op1 = state->Reg[BITS (0, 3)];
1540 unsigned long long op2 = state->Reg[BITS (8, 11)];
1541 unsigned long long dest;
1542 unsigned long long result;
1555 dest = (unsigned long long) state->Reg[BITS (16, 19)] << 32;
1556 dest |= state->Reg[BITS (12, 15)];
1558 state->Reg[BITS (12, 15)] = dest;
1559 state->Reg[BITS (16, 19)] = dest >> 32;
1563 if (BITS (4, 11) == 5)
1565 /* ElSegundo QDADD insn. */
1566 ARMword op1 = state->Reg[BITS (0, 3)];
1567 ARMword op2 = state->Reg[BITS (16, 19)];
1568 ARMword op2d = op2 + op2;
1571 if (AddOverflow (op2, op2, op2d))
1574 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1577 result = op1 + op2d;
1578 if (AddOverflow (op1, op2d, result))
1581 result = POS (result) ? 0x80000000 : 0x7fffffff;
1584 state->Reg[BITS (12, 15)] = result;
1589 if (BITS (4, 7) == 0xB)
1591 /* STRH immediate offset, no write-back, down, pre indexed. */
1595 if (BITS (4, 7) == 0xD)
1597 Handle_Load_Double (state, instr);
1600 if (BITS (4, 7) == 0xF)
1602 Handle_Store_Double (state, instr);
1606 if (BITS (4, 11) == 9)
1613 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
1615 INTERNALABORT (temp);
1616 (void) ARMul_LoadByte (state, temp);
1617 (void) ARMul_LoadByte (state, temp);
1621 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
1622 if (state->abortSig || state->Aborted)
1625 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
1629 DEST = GETSPSR (state->Bank);
1636 case 0x15: /* CMPP reg. */
1638 if ((BITS (4, 7) & 0x9) == 0x9)
1639 /* LDR immediate offset, no write-back, down, pre indexed. */
1641 /* Continue with remaining instruction decode. */
1647 state->Cpsr = GETSPSR (state->Bank);
1648 ARMul_CPSRAltered (state);
1661 ARMul_NegZero (state, dest);
1662 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1664 ARMul_SubCarry (state, lhs, rhs, dest);
1665 ARMul_SubOverflow (state, lhs, rhs, dest);
1675 case 0x16: /* CMN reg and MSR reg to SPSR */
1678 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1680 /* ElSegundo SMULxy insn. */
1681 ARMword op1 = state->Reg[BITS (0, 3)];
1682 ARMword op2 = state->Reg[BITS (8, 11)];
1683 ARMword Rn = state->Reg[BITS (12, 15)];
1696 state->Reg[BITS (16, 19)] = op1 * op2;
1700 if (BITS (4, 11) == 5)
1702 /* ElSegundo QDSUB insn. */
1703 ARMword op1 = state->Reg[BITS (0, 3)];
1704 ARMword op2 = state->Reg[BITS (16, 19)];
1705 ARMword op2d = op2 + op2;
1708 if (AddOverflow (op2, op2, op2d))
1711 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1714 result = op1 - op2d;
1715 if (SubOverflow (op1, op2d, result))
1718 result = POS (result) ? 0x80000000 : 0x7fffffff;
1721 state->Reg[BITS (12, 15)] = result;
1728 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1730 /* ARM5 CLZ insn. */
1731 ARMword op1 = state->Reg[BITS (0, 3)];
1735 for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
1738 state->Reg[BITS (12, 15)] = result;
1743 if (BITS (4, 7) == 0xB)
1745 /* STRH immediate offset, write-back, down, pre indexed. */
1749 if (BITS (4, 7) == 0xD)
1751 Handle_Load_Double (state, instr);
1754 if (BITS (4, 7) == 0xF)
1756 Handle_Store_Double (state, instr);
1764 ARMul_FixSPSR (state, instr, DPRegRHS);
1772 case 0x17: /* CMNP reg */
1774 if ((BITS (4, 7) & 0x9) == 0x9)
1775 /* LDR immediate offset, write-back, down, pre indexed. */
1777 /* Continue with remaining instruction decoding. */
1782 state->Cpsr = GETSPSR (state->Bank);
1783 ARMul_CPSRAltered (state);
1797 ASSIGNZ (dest == 0);
1798 if ((lhs | rhs) >> 30)
1800 /* Possible C,V,N to set. */
1801 ASSIGNN (NEG (dest));
1802 ARMul_AddCarry (state, lhs, rhs, dest);
1803 ARMul_AddOverflow (state, lhs, rhs, dest);
1814 case 0x18: /* ORR reg */
1816 if (BITS (4, 11) == 0xB)
1818 /* STRH register offset, no write-back, up, pre indexed. */
1822 if (BITS (4, 7) == 0xD)
1824 Handle_Load_Double (state, instr);
1827 if (BITS (4, 7) == 0xF)
1829 Handle_Store_Double (state, instr);
1838 case 0x19: /* ORRS reg */
1840 if ((BITS (4, 11) & 0xF9) == 0x9)
1841 /* LDR register offset, no write-back, up, pre indexed. */
1843 /* Continue with remaining instruction decoding. */
1850 case 0x1a: /* MOV reg */
1852 if (BITS (4, 11) == 0xB)
1854 /* STRH register offset, write-back, up, pre indexed. */
1858 if (BITS (4, 7) == 0xD)
1860 Handle_Load_Double (state, instr);
1863 if (BITS (4, 7) == 0xF)
1865 Handle_Store_Double (state, instr);
1873 case 0x1b: /* MOVS reg */
1875 if ((BITS (4, 11) & 0xF9) == 0x9)
1876 /* LDR register offset, write-back, up, pre indexed. */
1878 /* Continue with remaining instruction decoding. */
1884 case 0x1c: /* BIC reg */
1886 if (BITS (4, 7) == 0xB)
1888 /* STRH immediate offset, no write-back, up, pre indexed. */
1892 if (BITS (4, 7) == 0xD)
1894 Handle_Load_Double (state, instr);
1897 else if (BITS (4, 7) == 0xF)
1899 Handle_Store_Double (state, instr);
1908 case 0x1d: /* BICS reg */
1910 if ((BITS (4, 7) & 0x9) == 0x9)
1911 /* LDR immediate offset, no write-back, up, pre indexed. */
1913 /* Continue with instruction decoding. */
1920 case 0x1e: /* MVN reg */
1922 if (BITS (4, 7) == 0xB)
1924 /* STRH immediate offset, write-back, up, pre indexed. */
1928 if (BITS (4, 7) == 0xD)
1930 Handle_Load_Double (state, instr);
1933 if (BITS (4, 7) == 0xF)
1935 Handle_Store_Double (state, instr);
1943 case 0x1f: /* MVNS reg */
1945 if ((BITS (4, 7) & 0x9) == 0x9)
1946 /* LDR immediate offset, write-back, up, pre indexed. */
1948 /* Continue instruction decoding. */
1955 /* Data Processing Immediate RHS Instructions. */
1957 case 0x20: /* AND immed */
1958 dest = LHS & DPImmRHS;
1962 case 0x21: /* ANDS immed */
1968 case 0x22: /* EOR immed */
1969 dest = LHS ^ DPImmRHS;
1973 case 0x23: /* EORS immed */
1979 case 0x24: /* SUB immed */
1980 dest = LHS - DPImmRHS;
1984 case 0x25: /* SUBS immed */
1989 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1991 ARMul_SubCarry (state, lhs, rhs, dest);
1992 ARMul_SubOverflow (state, lhs, rhs, dest);
2002 case 0x26: /* RSB immed */
2003 dest = DPImmRHS - LHS;
2007 case 0x27: /* RSBS immed */
2012 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
2014 ARMul_SubCarry (state, rhs, lhs, dest);
2015 ARMul_SubOverflow (state, rhs, lhs, dest);
2025 case 0x28: /* ADD immed */
2026 dest = LHS + DPImmRHS;
2030 case 0x29: /* ADDS immed */
2034 ASSIGNZ (dest == 0);
2036 if ((lhs | rhs) >> 30)
2038 /* Possible C,V,N to set. */
2039 ASSIGNN (NEG (dest));
2040 ARMul_AddCarry (state, lhs, rhs, dest);
2041 ARMul_AddOverflow (state, lhs, rhs, dest);
2052 case 0x2a: /* ADC immed */
2053 dest = LHS + DPImmRHS + CFLAG;
2057 case 0x2b: /* ADCS immed */
2060 dest = lhs + rhs + CFLAG;
2061 ASSIGNZ (dest == 0);
2062 if ((lhs | rhs) >> 30)
2064 /* Possible C,V,N to set. */
2065 ASSIGNN (NEG (dest));
2066 ARMul_AddCarry (state, lhs, rhs, dest);
2067 ARMul_AddOverflow (state, lhs, rhs, dest);
2078 case 0x2c: /* SBC immed */
2079 dest = LHS - DPImmRHS - !CFLAG;
2083 case 0x2d: /* SBCS immed */
2086 dest = lhs - rhs - !CFLAG;
2087 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2089 ARMul_SubCarry (state, lhs, rhs, dest);
2090 ARMul_SubOverflow (state, lhs, rhs, dest);
2100 case 0x2e: /* RSC immed */
2101 dest = DPImmRHS - LHS - !CFLAG;
2105 case 0x2f: /* RSCS immed */
2108 dest = rhs - lhs - !CFLAG;
2109 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
2111 ARMul_SubCarry (state, rhs, lhs, dest);
2112 ARMul_SubOverflow (state, rhs, lhs, dest);
2122 case 0x30: /* TST immed */
2126 case 0x31: /* TSTP immed */
2131 state->Cpsr = GETSPSR (state->Bank);
2132 ARMul_CPSRAltered (state);
2134 temp = LHS & DPImmRHS;
2143 ARMul_NegZero (state, dest);
2147 case 0x32: /* TEQ immed and MSR immed to CPSR */
2149 /* MSR immed to CPSR. */
2150 ARMul_FixCPSR (state, instr, DPImmRHS);
2155 case 0x33: /* TEQP immed */
2160 state->Cpsr = GETSPSR (state->Bank);
2161 ARMul_CPSRAltered (state);
2163 temp = LHS ^ DPImmRHS;
2169 DPSImmRHS; /* TEQ immed */
2171 ARMul_NegZero (state, dest);
2175 case 0x34: /* CMP immed */
2179 case 0x35: /* CMPP immed */
2184 state->Cpsr = GETSPSR (state->Bank);
2185 ARMul_CPSRAltered (state);
2187 temp = LHS - DPImmRHS;
2198 ARMul_NegZero (state, dest);
2200 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2202 ARMul_SubCarry (state, lhs, rhs, dest);
2203 ARMul_SubOverflow (state, lhs, rhs, dest);
2213 case 0x36: /* CMN immed and MSR immed to SPSR */
2215 ARMul_FixSPSR (state, instr, DPImmRHS);
2220 case 0x37: /* CMNP immed. */
2225 state->Cpsr = GETSPSR (state->Bank);
2226 ARMul_CPSRAltered (state);
2228 temp = LHS + DPImmRHS;
2239 ASSIGNZ (dest == 0);
2240 if ((lhs | rhs) >> 30)
2242 /* Possible C,V,N to set. */
2243 ASSIGNN (NEG (dest));
2244 ARMul_AddCarry (state, lhs, rhs, dest);
2245 ARMul_AddOverflow (state, lhs, rhs, dest);
2256 case 0x38: /* ORR immed. */
2257 dest = LHS | DPImmRHS;
2261 case 0x39: /* ORRS immed. */
2267 case 0x3a: /* MOV immed. */
2272 case 0x3b: /* MOVS immed. */
2277 case 0x3c: /* BIC immed. */
2278 dest = LHS & ~DPImmRHS;
2282 case 0x3d: /* BICS immed. */
2288 case 0x3e: /* MVN immed. */
2293 case 0x3f: /* MVNS immed. */
2299 /* Single Data Transfer Immediate RHS Instructions. */
2301 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2303 if (StoreWord (state, instr, lhs))
2304 LSBase = lhs - LSImmRHS;
2307 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2309 if (LoadWord (state, instr, lhs))
2310 LSBase = lhs - LSImmRHS;
2313 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2314 UNDEF_LSRBaseEQDestWb;
2317 temp = lhs - LSImmRHS;
2318 state->NtransSig = LOW;
2319 if (StoreWord (state, instr, lhs))
2321 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2324 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2325 UNDEF_LSRBaseEQDestWb;
2328 state->NtransSig = LOW;
2329 if (LoadWord (state, instr, lhs))
2330 LSBase = lhs - LSImmRHS;
2331 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2334 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2336 if (StoreByte (state, instr, lhs))
2337 LSBase = lhs - LSImmRHS;
2340 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2342 if (LoadByte (state, instr, lhs, LUNSIGNED))
2343 LSBase = lhs - LSImmRHS;
2346 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2347 UNDEF_LSRBaseEQDestWb;
2350 state->NtransSig = LOW;
2351 if (StoreByte (state, instr, lhs))
2352 LSBase = lhs - LSImmRHS;
2353 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2356 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2357 UNDEF_LSRBaseEQDestWb;
2360 state->NtransSig = LOW;
2361 if (LoadByte (state, instr, lhs, LUNSIGNED))
2362 LSBase = lhs - LSImmRHS;
2363 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2366 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2368 if (StoreWord (state, instr, lhs))
2369 LSBase = lhs + LSImmRHS;
2372 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2374 if (LoadWord (state, instr, lhs))
2375 LSBase = lhs + LSImmRHS;
2378 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2379 UNDEF_LSRBaseEQDestWb;
2382 state->NtransSig = LOW;
2383 if (StoreWord (state, instr, lhs))
2384 LSBase = lhs + LSImmRHS;
2385 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2388 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2389 UNDEF_LSRBaseEQDestWb;
2392 state->NtransSig = LOW;
2393 if (LoadWord (state, instr, lhs))
2394 LSBase = lhs + LSImmRHS;
2395 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2398 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2400 if (StoreByte (state, instr, lhs))
2401 LSBase = lhs + LSImmRHS;
2404 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2406 if (LoadByte (state, instr, lhs, LUNSIGNED))
2407 LSBase = lhs + LSImmRHS;
2410 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2411 UNDEF_LSRBaseEQDestWb;
2414 state->NtransSig = LOW;
2415 if (StoreByte (state, instr, lhs))
2416 LSBase = lhs + LSImmRHS;
2417 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2420 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2421 UNDEF_LSRBaseEQDestWb;
2424 state->NtransSig = LOW;
2425 if (LoadByte (state, instr, lhs, LUNSIGNED))
2426 LSBase = lhs + LSImmRHS;
2427 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2431 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2432 (void) StoreWord (state, instr, LHS - LSImmRHS);
2435 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2436 (void) LoadWord (state, instr, LHS - LSImmRHS);
2439 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2440 UNDEF_LSRBaseEQDestWb;
2442 temp = LHS - LSImmRHS;
2443 if (StoreWord (state, instr, temp))
2447 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2448 UNDEF_LSRBaseEQDestWb;
2450 temp = LHS - LSImmRHS;
2451 if (LoadWord (state, instr, temp))
2455 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2456 (void) StoreByte (state, instr, LHS - LSImmRHS);
2459 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2460 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
2463 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2464 UNDEF_LSRBaseEQDestWb;
2466 temp = LHS - LSImmRHS;
2467 if (StoreByte (state, instr, temp))
2471 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2472 UNDEF_LSRBaseEQDestWb;
2474 temp = LHS - LSImmRHS;
2475 if (LoadByte (state, instr, temp, LUNSIGNED))
2479 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2480 (void) StoreWord (state, instr, LHS + LSImmRHS);
2483 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2484 (void) LoadWord (state, instr, LHS + LSImmRHS);
2487 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2488 UNDEF_LSRBaseEQDestWb;
2490 temp = LHS + LSImmRHS;
2491 if (StoreWord (state, instr, temp))
2495 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2496 UNDEF_LSRBaseEQDestWb;
2498 temp = LHS + LSImmRHS;
2499 if (LoadWord (state, instr, temp))
2503 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2504 (void) StoreByte (state, instr, LHS + LSImmRHS);
2507 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2508 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
2511 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2512 UNDEF_LSRBaseEQDestWb;
2514 temp = LHS + LSImmRHS;
2515 if (StoreByte (state, instr, temp))
2519 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2520 UNDEF_LSRBaseEQDestWb;
2522 temp = LHS + LSImmRHS;
2523 if (LoadByte (state, instr, temp, LUNSIGNED))
2528 /* Single Data Transfer Register RHS Instructions. */
2530 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2533 ARMul_UndefInstr (state, instr);
2536 UNDEF_LSRBaseEQOffWb;
2537 UNDEF_LSRBaseEQDestWb;
2541 if (StoreWord (state, instr, lhs))
2542 LSBase = lhs - LSRegRHS;
2545 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2548 ARMul_UndefInstr (state, instr);
2551 UNDEF_LSRBaseEQOffWb;
2552 UNDEF_LSRBaseEQDestWb;
2556 temp = lhs - LSRegRHS;
2557 if (LoadWord (state, instr, lhs))
2561 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2564 ARMul_UndefInstr (state, instr);
2567 UNDEF_LSRBaseEQOffWb;
2568 UNDEF_LSRBaseEQDestWb;
2572 state->NtransSig = LOW;
2573 if (StoreWord (state, instr, lhs))
2574 LSBase = lhs - LSRegRHS;
2575 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2578 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2581 ARMul_UndefInstr (state, instr);
2584 UNDEF_LSRBaseEQOffWb;
2585 UNDEF_LSRBaseEQDestWb;
2589 temp = lhs - LSRegRHS;
2590 state->NtransSig = LOW;
2591 if (LoadWord (state, instr, lhs))
2593 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2596 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2599 ARMul_UndefInstr (state, instr);
2602 UNDEF_LSRBaseEQOffWb;
2603 UNDEF_LSRBaseEQDestWb;
2607 if (StoreByte (state, instr, lhs))
2608 LSBase = lhs - LSRegRHS;
2611 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2614 ARMul_UndefInstr (state, instr);
2617 UNDEF_LSRBaseEQOffWb;
2618 UNDEF_LSRBaseEQDestWb;
2622 temp = lhs - LSRegRHS;
2623 if (LoadByte (state, instr, lhs, LUNSIGNED))
2627 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2630 ARMul_UndefInstr (state, instr);
2633 UNDEF_LSRBaseEQOffWb;
2634 UNDEF_LSRBaseEQDestWb;
2638 state->NtransSig = LOW;
2639 if (StoreByte (state, instr, lhs))
2640 LSBase = lhs - LSRegRHS;
2641 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2644 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2647 ARMul_UndefInstr (state, instr);
2650 UNDEF_LSRBaseEQOffWb;
2651 UNDEF_LSRBaseEQDestWb;
2655 temp = lhs - LSRegRHS;
2656 state->NtransSig = LOW;
2657 if (LoadByte (state, instr, lhs, LUNSIGNED))
2659 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2662 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2665 ARMul_UndefInstr (state, instr);
2668 UNDEF_LSRBaseEQOffWb;
2669 UNDEF_LSRBaseEQDestWb;
2673 if (StoreWord (state, instr, lhs))
2674 LSBase = lhs + LSRegRHS;
2677 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2680 ARMul_UndefInstr (state, instr);
2683 UNDEF_LSRBaseEQOffWb;
2684 UNDEF_LSRBaseEQDestWb;
2688 temp = lhs + LSRegRHS;
2689 if (LoadWord (state, instr, lhs))
2693 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2696 ARMul_UndefInstr (state, instr);
2699 UNDEF_LSRBaseEQOffWb;
2700 UNDEF_LSRBaseEQDestWb;
2704 state->NtransSig = LOW;
2705 if (StoreWord (state, instr, lhs))
2706 LSBase = lhs + LSRegRHS;
2707 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2710 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2713 ARMul_UndefInstr (state, instr);
2716 UNDEF_LSRBaseEQOffWb;
2717 UNDEF_LSRBaseEQDestWb;
2721 temp = lhs + LSRegRHS;
2722 state->NtransSig = LOW;
2723 if (LoadWord (state, instr, lhs))
2725 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2728 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2731 ARMul_UndefInstr (state, instr);
2734 UNDEF_LSRBaseEQOffWb;
2735 UNDEF_LSRBaseEQDestWb;
2739 if (StoreByte (state, instr, lhs))
2740 LSBase = lhs + LSRegRHS;
2743 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
2746 ARMul_UndefInstr (state, instr);
2749 UNDEF_LSRBaseEQOffWb;
2750 UNDEF_LSRBaseEQDestWb;
2754 temp = lhs + LSRegRHS;
2755 if (LoadByte (state, instr, lhs, LUNSIGNED))
2759 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
2762 ARMul_UndefInstr (state, instr);
2765 UNDEF_LSRBaseEQOffWb;
2766 UNDEF_LSRBaseEQDestWb;
2770 state->NtransSig = LOW;
2771 if (StoreByte (state, instr, lhs))
2772 LSBase = lhs + LSRegRHS;
2773 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2776 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
2779 ARMul_UndefInstr (state, instr);
2782 UNDEF_LSRBaseEQOffWb;
2783 UNDEF_LSRBaseEQDestWb;
2787 temp = lhs + LSRegRHS;
2788 state->NtransSig = LOW;
2789 if (LoadByte (state, instr, lhs, LUNSIGNED))
2791 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2795 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
2798 ARMul_UndefInstr (state, instr);
2801 (void) StoreWord (state, instr, LHS - LSRegRHS);
2804 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
2807 ARMul_UndefInstr (state, instr);
2810 (void) LoadWord (state, instr, LHS - LSRegRHS);
2813 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
2816 ARMul_UndefInstr (state, instr);
2819 UNDEF_LSRBaseEQOffWb;
2820 UNDEF_LSRBaseEQDestWb;
2823 temp = LHS - LSRegRHS;
2824 if (StoreWord (state, instr, temp))
2828 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
2831 ARMul_UndefInstr (state, instr);
2834 UNDEF_LSRBaseEQOffWb;
2835 UNDEF_LSRBaseEQDestWb;
2838 temp = LHS - LSRegRHS;
2839 if (LoadWord (state, instr, temp))
2843 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
2846 ARMul_UndefInstr (state, instr);
2849 (void) StoreByte (state, instr, LHS - LSRegRHS);
2852 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
2855 ARMul_UndefInstr (state, instr);
2858 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
2861 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
2864 ARMul_UndefInstr (state, instr);
2867 UNDEF_LSRBaseEQOffWb;
2868 UNDEF_LSRBaseEQDestWb;
2871 temp = LHS - LSRegRHS;
2872 if (StoreByte (state, instr, temp))
2876 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
2879 ARMul_UndefInstr (state, instr);
2882 UNDEF_LSRBaseEQOffWb;
2883 UNDEF_LSRBaseEQDestWb;
2886 temp = LHS - LSRegRHS;
2887 if (LoadByte (state, instr, temp, LUNSIGNED))
2891 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
2894 ARMul_UndefInstr (state, instr);
2897 (void) StoreWord (state, instr, LHS + LSRegRHS);
2900 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
2903 ARMul_UndefInstr (state, instr);
2906 (void) LoadWord (state, instr, LHS + LSRegRHS);
2909 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
2912 ARMul_UndefInstr (state, instr);
2915 UNDEF_LSRBaseEQOffWb;
2916 UNDEF_LSRBaseEQDestWb;
2919 temp = LHS + LSRegRHS;
2920 if (StoreWord (state, instr, temp))
2924 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
2927 ARMul_UndefInstr (state, instr);
2930 UNDEF_LSRBaseEQOffWb;
2931 UNDEF_LSRBaseEQDestWb;
2934 temp = LHS + LSRegRHS;
2935 if (LoadWord (state, instr, temp))
2939 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
2942 ARMul_UndefInstr (state, instr);
2945 (void) StoreByte (state, instr, LHS + LSRegRHS);
2948 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
2951 ARMul_UndefInstr (state, instr);
2954 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
2957 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
2960 ARMul_UndefInstr (state, instr);
2963 UNDEF_LSRBaseEQOffWb;
2964 UNDEF_LSRBaseEQDestWb;
2967 temp = LHS + LSRegRHS;
2968 if (StoreByte (state, instr, temp))
2972 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
2975 /* Check for the special breakpoint opcode.
2976 This value should correspond to the value defined
2977 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2978 if (BITS (0, 19) == 0xfdefe)
2980 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
2981 ARMul_Abort (state, ARMul_SWIV);
2984 ARMul_UndefInstr (state, instr);
2987 UNDEF_LSRBaseEQOffWb;
2988 UNDEF_LSRBaseEQDestWb;
2991 temp = LHS + LSRegRHS;
2992 if (LoadByte (state, instr, temp, LUNSIGNED))
2997 /* Multiple Data Transfer Instructions. */
2999 case 0x80: /* Store, No WriteBack, Post Dec. */
3000 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3003 case 0x81: /* Load, No WriteBack, Post Dec. */
3004 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3007 case 0x82: /* Store, WriteBack, Post Dec. */
3008 temp = LSBase - LSMNumRegs;
3009 STOREMULT (instr, temp + 4L, temp);
3012 case 0x83: /* Load, WriteBack, Post Dec. */
3013 temp = LSBase - LSMNumRegs;
3014 LOADMULT (instr, temp + 4L, temp);
3017 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
3018 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3021 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
3022 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3025 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
3026 temp = LSBase - LSMNumRegs;
3027 STORESMULT (instr, temp + 4L, temp);
3030 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3031 temp = LSBase - LSMNumRegs;
3032 LOADSMULT (instr, temp + 4L, temp);
3035 case 0x88: /* Store, No WriteBack, Post Inc. */
3036 STOREMULT (instr, LSBase, 0L);
3039 case 0x89: /* Load, No WriteBack, Post Inc. */
3040 LOADMULT (instr, LSBase, 0L);
3043 case 0x8a: /* Store, WriteBack, Post Inc. */
3045 STOREMULT (instr, temp, temp + LSMNumRegs);
3048 case 0x8b: /* Load, WriteBack, Post Inc. */
3050 LOADMULT (instr, temp, temp + LSMNumRegs);
3053 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3054 STORESMULT (instr, LSBase, 0L);
3057 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3058 LOADSMULT (instr, LSBase, 0L);
3061 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3063 STORESMULT (instr, temp, temp + LSMNumRegs);
3066 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3068 LOADSMULT (instr, temp, temp + LSMNumRegs);
3071 case 0x90: /* Store, No WriteBack, Pre Dec. */
3072 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
3075 case 0x91: /* Load, No WriteBack, Pre Dec. */
3076 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
3079 case 0x92: /* Store, WriteBack, Pre Dec. */
3080 temp = LSBase - LSMNumRegs;
3081 STOREMULT (instr, temp, temp);
3084 case 0x93: /* Load, WriteBack, Pre Dec. */
3085 temp = LSBase - LSMNumRegs;
3086 LOADMULT (instr, temp, temp);
3089 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3090 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
3093 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3094 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
3097 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3098 temp = LSBase - LSMNumRegs;
3099 STORESMULT (instr, temp, temp);
3102 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3103 temp = LSBase - LSMNumRegs;
3104 LOADSMULT (instr, temp, temp);
3107 case 0x98: /* Store, No WriteBack, Pre Inc. */
3108 STOREMULT (instr, LSBase + 4L, 0L);
3111 case 0x99: /* Load, No WriteBack, Pre Inc. */
3112 LOADMULT (instr, LSBase + 4L, 0L);
3115 case 0x9a: /* Store, WriteBack, Pre Inc. */
3117 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
3120 case 0x9b: /* Load, WriteBack, Pre Inc. */
3122 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
3125 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3126 STORESMULT (instr, LSBase + 4L, 0L);
3129 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3130 LOADSMULT (instr, LSBase + 4L, 0L);
3133 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3135 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
3138 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3140 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
3144 /* Branch forward. */
3153 state->Reg[15] = pc + 8 + POSBRANCH;
3158 /* Branch backward. */
3167 state->Reg[15] = pc + 8 + NEGBRANCH;
3172 /* Branch and Link forward. */
3181 /* Put PC into Link. */
3183 state->Reg[14] = pc + 4;
3185 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3187 state->Reg[15] = pc + 8 + POSBRANCH;
3192 /* Branch and Link backward. */
3201 /* Put PC into Link. */
3203 state->Reg[14] = pc + 4;
3205 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3207 state->Reg[15] = pc + 8 + NEGBRANCH;
3212 /* Co-Processor Data Transfers. */
3216 /* Reading from R15 is UNPREDICTABLE. */
3217 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3218 ARMul_UndefInstr (state, instr);
3219 /* Is access to coprocessor 0 allowed ? */
3220 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3221 ARMul_UndefInstr (state, instr);
3222 /* Special treatment for XScale coprocessors. */
3223 else if (state->is_XScale)
3225 /* Only opcode 0 is supported. */
3226 if (BITS (4, 7) != 0x00)
3227 ARMul_UndefInstr (state, instr);
3228 /* Only coporcessor 0 is supported. */
3229 else if (CPNum != 0x00)
3230 ARMul_UndefInstr (state, instr);
3231 /* Only accumulator 0 is supported. */
3232 else if (BITS (0, 3) != 0x00)
3233 ARMul_UndefInstr (state, instr);
3236 /* XScale MAR insn. Move two registers into accumulator. */
3237 state->Accumulator = state->Reg[BITS (12, 15)];
3238 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
3242 /* FIXME: Not sure what to do for other v5 processors. */
3243 ARMul_UndefInstr (state, instr);
3248 case 0xc0: /* Store , No WriteBack , Post Dec. */
3249 ARMul_STC (state, instr, LHS);
3255 /* Writes to R15 are UNPREDICATABLE. */
3256 if (DESTReg == 15 || LHSReg == 15)
3257 ARMul_UndefInstr (state, instr);
3258 /* Is access to the coprocessor allowed ? */
3259 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3260 ARMul_UndefInstr (state, instr);
3261 /* Special handling for XScale coprcoessors. */
3262 else if (state->is_XScale)
3264 /* Only opcode 0 is supported. */
3265 if (BITS (4, 7) != 0x00)
3266 ARMul_UndefInstr (state, instr);
3267 /* Only coprocessor 0 is supported. */
3268 else if (CPNum != 0x00)
3269 ARMul_UndefInstr (state, instr);
3270 /* Only accumulator 0 is supported. */
3271 else if (BITS (0, 3) != 0x00)
3272 ARMul_UndefInstr (state, instr);
3275 /* XScale MRA insn. Move accumulator into two registers. */
3276 ARMword t1 = (state->Accumulator >> 32) & 255;
3281 state->Reg[BITS (12, 15)] = state->Accumulator;
3282 state->Reg[BITS (16, 19)] = t1;
3287 /* FIXME: Not sure what to do for other v5 processors. */
3288 ARMul_UndefInstr (state, instr);
3293 case 0xc1: /* Load , No WriteBack , Post Dec. */
3294 ARMul_LDC (state, instr, LHS);
3298 case 0xc6: /* Store , WriteBack , Post Dec. */
3300 state->Base = lhs - LSCOff;
3301 ARMul_STC (state, instr, lhs);
3305 case 0xc7: /* Load , WriteBack , Post Dec. */
3307 state->Base = lhs - LSCOff;
3308 ARMul_LDC (state, instr, lhs);
3312 case 0xcc: /* Store , No WriteBack , Post Inc. */
3313 ARMul_STC (state, instr, LHS);
3317 case 0xcd: /* Load , No WriteBack , Post Inc. */
3318 ARMul_LDC (state, instr, LHS);
3322 case 0xce: /* Store , WriteBack , Post Inc. */
3324 state->Base = lhs + LSCOff;
3325 ARMul_STC (state, instr, LHS);
3329 case 0xcf: /* Load , WriteBack , Post Inc. */
3331 state->Base = lhs + LSCOff;
3332 ARMul_LDC (state, instr, LHS);
3336 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3337 ARMul_STC (state, instr, LHS - LSCOff);
3341 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3342 ARMul_LDC (state, instr, LHS - LSCOff);
3346 case 0xd6: /* Store , WriteBack , Pre Dec. */
3349 ARMul_STC (state, instr, lhs);
3353 case 0xd7: /* Load , WriteBack , Pre Dec. */
3356 ARMul_LDC (state, instr, lhs);
3360 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3361 ARMul_STC (state, instr, LHS + LSCOff);
3365 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3366 ARMul_LDC (state, instr, LHS + LSCOff);
3370 case 0xde: /* Store , WriteBack , Pre Inc. */
3373 ARMul_STC (state, instr, lhs);
3377 case 0xdf: /* Load , WriteBack , Pre Inc. */
3380 ARMul_LDC (state, instr, lhs);
3384 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3387 if (! CP_ACCESS_ALLOWED (state, CPNum))
3389 ARMul_UndefInstr (state, instr);
3392 if (state->is_XScale)
3393 switch (BITS (18, 19))
3396 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3398 /* XScale MIA instruction. Signed multiplication of
3399 two 32 bit values and addition to 40 bit accumulator. */
3400 long long Rm = state->Reg[MULLHSReg];
3401 long long Rs = state->Reg[MULACCReg];
3407 state->Accumulator += Rm * Rs;
3413 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3415 /* XScale MIAPH instruction. */
3416 ARMword t1 = state->Reg[MULLHSReg] >> 16;
3417 ARMword t2 = state->Reg[MULACCReg] >> 16;
3418 ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
3419 ARMword t4 = state->Reg[MULACCReg] & 0xffff;
3434 state->Accumulator += t5;
3439 state->Accumulator += t5;
3445 if (BITS (4, 11) == 1)
3447 /* XScale MIAxy instruction. */
3453 t1 = state->Reg[MULLHSReg] >> 16;
3455 t1 = state->Reg[MULLHSReg] & 0xffff;
3458 t2 = state->Reg[MULACCReg] >> 16;
3460 t2 = state->Reg[MULACCReg] & 0xffff;
3470 state->Accumulator += t5;
3494 ARMul_MCR (state, instr, state->Reg[15] + isize);
3496 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
3497 ((state->Reg[15] + isize) & R15PCBITS));
3501 ARMul_MCR (state, instr, DEST);
3505 ARMul_CDP (state, instr);
3509 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3521 temp = ARMul_MRC (state, instr);
3524 ASSIGNN ((temp & NBIT) != 0);
3525 ASSIGNZ ((temp & ZBIT) != 0);
3526 ASSIGNC ((temp & CBIT) != 0);
3527 ASSIGNV ((temp & VBIT) != 0);
3534 ARMul_CDP (state, instr);
3538 /* SWI instruction. */
3555 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
3557 /* A prefetch abort. */
3558 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
3559 ARMul_Abort (state, ARMul_PrefetchAbortV);
3563 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
3564 ARMul_Abort (state, ARMul_SWIV);
3574 #ifdef NEED_UI_LOOP_HOOK
3575 if (ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
3577 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
3580 #endif /* NEED_UI_LOOP_HOOK */
3582 if (state->Emulate == ONCE)
3583 state->Emulate = STOP;
3584 /* If we have changed mode, allow the PC to advance before stopping. */
3585 else if (state->Emulate == CHANGEMODE)
3587 else if (state->Emulate != RUN)
3590 while (!stop_simulator);
3592 state->decoded = decoded;
3593 state->loaded = loaded;
3599 /* This routine evaluates most Data Processing register RHS's with the S
3600 bit clear. It is intended to be called from the macro DPRegRHS, which
3601 filters the common case of an unshifted register with in line code. */
3604 GetDPRegRHS (ARMul_State * state, ARMword instr)
3606 ARMword shamt, base;
3611 /* Shift amount in a register. */
3616 base = ECC | ER15INT | R15PC | EMODE;
3619 base = state->Reg[base];
3620 ARMul_Icycles (state, 1, 0L);
3621 shamt = state->Reg[BITS (8, 11)] & 0xff;
3622 switch ((int) BITS (5, 6))
3627 else if (shamt >= 32)
3630 return (base << shamt);
3634 else if (shamt >= 32)
3637 return (base >> shamt);
3641 else if (shamt >= 32)
3642 return ((ARMword) ((long int) base >> 31L));
3644 return ((ARMword) ((long int) base >> (int) shamt));
3650 return ((base << (32 - shamt)) | (base >> shamt));
3655 /* Shift amount is a constant. */
3658 base = ECC | ER15INT | R15PC | EMODE;
3661 base = state->Reg[base];
3662 shamt = BITS (7, 11);
3663 switch ((int) BITS (5, 6))
3666 return (base << shamt);
3671 return (base >> shamt);
3674 return ((ARMword) ((long int) base >> 31L));
3676 return ((ARMword) ((long int) base >> (int) shamt));
3680 return ((base >> 1) | (CFLAG << 31));
3682 return ((base << (32 - shamt)) | (base >> shamt));
3689 /* This routine evaluates most Logical Data Processing register RHS's
3690 with the S bit set. It is intended to be called from the macro
3691 DPSRegRHS, which filters the common case of an unshifted register
3692 with in line code. */
3695 GetDPSRegRHS (ARMul_State * state, ARMword instr)
3697 ARMword shamt, base;
3702 /* Shift amount in a register. */
3707 base = ECC | ER15INT | R15PC | EMODE;
3710 base = state->Reg[base];
3711 ARMul_Icycles (state, 1, 0L);
3712 shamt = state->Reg[BITS (8, 11)] & 0xff;
3713 switch ((int) BITS (5, 6))
3718 else if (shamt == 32)
3723 else if (shamt > 32)
3730 ASSIGNC ((base >> (32 - shamt)) & 1);
3731 return (base << shamt);
3736 else if (shamt == 32)
3738 ASSIGNC (base >> 31);
3741 else if (shamt > 32)
3748 ASSIGNC ((base >> (shamt - 1)) & 1);
3749 return (base >> shamt);
3754 else if (shamt >= 32)
3756 ASSIGNC (base >> 31L);
3757 return ((ARMword) ((long int) base >> 31L));
3761 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3762 return ((ARMword) ((long int) base >> (int) shamt));
3770 ASSIGNC (base >> 31);
3775 ASSIGNC ((base >> (shamt - 1)) & 1);
3776 return ((base << (32 - shamt)) | (base >> shamt));
3782 /* Shift amount is a constant. */
3785 base = ECC | ER15INT | R15PC | EMODE;
3788 base = state->Reg[base];
3789 shamt = BITS (7, 11);
3791 switch ((int) BITS (5, 6))
3794 ASSIGNC ((base >> (32 - shamt)) & 1);
3795 return (base << shamt);
3799 ASSIGNC (base >> 31);
3804 ASSIGNC ((base >> (shamt - 1)) & 1);
3805 return (base >> shamt);
3810 ASSIGNC (base >> 31L);
3811 return ((ARMword) ((long int) base >> 31L));
3815 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3816 return ((ARMword) ((long int) base >> (int) shamt));
3824 return ((base >> 1) | (shamt << 31));
3828 ASSIGNC ((base >> (shamt - 1)) & 1);
3829 return ((base << (32 - shamt)) | (base >> shamt));
3837 /* This routine handles writes to register 15 when the S bit is not set. */
3840 WriteR15 (ARMul_State * state, ARMword src)
3842 /* The ARM documentation states that the two least significant bits
3843 are discarded when setting PC, except in the cases handled by
3844 WriteR15Branch() below. It's probably an oversight: in THUMB
3845 mode, the second least significant bit should probably not be
3855 state->Reg[15] = src & PCBITS;
3857 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
3858 ARMul_R15Altered (state);
3864 /* This routine handles writes to register 15 when the S bit is set. */
3867 WriteSR15 (ARMul_State * state, ARMword src)
3870 if (state->Bank > 0)
3872 state->Cpsr = state->Spsr[state->Bank];
3873 ARMul_CPSRAltered (state);
3881 state->Reg[15] = src & PCBITS;
3885 /* ARMul_R15Altered would have to support it. */
3891 if (state->Bank == USERBANK)
3892 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
3894 state->Reg[15] = src;
3896 ARMul_R15Altered (state);
3901 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3902 will switch to Thumb mode if the least significant bit is set. */
3905 WriteR15Branch (ARMul_State * state, ARMword src)
3912 state->Reg[15] = src & 0xfffffffe;
3917 state->Reg[15] = src & 0xfffffffc;
3921 WriteR15 (state, src);
3925 /* This routine evaluates most Load and Store register RHS's. It is
3926 intended to be called from the macro LSRegRHS, which filters the
3927 common case of an unshifted register with in line code. */
3930 GetLSRegRHS (ARMul_State * state, ARMword instr)
3932 ARMword shamt, base;
3937 /* Now forbidden, but ... */
3938 base = ECC | ER15INT | R15PC | EMODE;
3941 base = state->Reg[base];
3943 shamt = BITS (7, 11);
3944 switch ((int) BITS (5, 6))
3947 return (base << shamt);
3952 return (base >> shamt);
3955 return ((ARMword) ((long int) base >> 31L));
3957 return ((ARMword) ((long int) base >> (int) shamt));
3961 return ((base >> 1) | (CFLAG << 31));
3963 return ((base << (32 - shamt)) | (base >> shamt));
3970 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
3973 GetLS7RHS (ARMul_State * state, ARMword instr)
3980 /* Now forbidden, but ... */
3981 return ECC | ER15INT | R15PC | EMODE;
3983 return state->Reg[RHSReg];
3987 return BITS (0, 3) | (BITS (8, 11) << 4);
3990 /* This function does the work of loading a word for a LDR instruction. */
3993 LoadWord (ARMul_State * state, ARMword instr, ARMword address)
3999 if (ADDREXCEPT (address))
4000 INTERNALABORT (address);
4003 dest = ARMul_LoadWordN (state, address);
4008 return state->lateabtSig;
4011 dest = ARMul_Align (state, address, dest);
4013 ARMul_Icycles (state, 1, 0L);
4015 return (DESTReg != LHSReg);
4019 /* This function does the work of loading a halfword. */
4022 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
4029 if (ADDREXCEPT (address))
4030 INTERNALABORT (address);
4032 dest = ARMul_LoadHalfWord (state, address);
4036 return state->lateabtSig;
4040 if (dest & 1 << (16 - 1))
4041 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
4044 ARMul_Icycles (state, 1, 0L);
4045 return (DESTReg != LHSReg);
4050 /* This function does the work of loading a byte for a LDRB instruction. */
4053 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
4059 if (ADDREXCEPT (address))
4060 INTERNALABORT (address);
4062 dest = ARMul_LoadByte (state, address);
4066 return state->lateabtSig;
4070 if (dest & 1 << (8 - 1))
4071 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
4074 ARMul_Icycles (state, 1, 0L);
4076 return (DESTReg != LHSReg);
4079 /* This function does the work of loading two words for a LDRD instruction. */
4082 Handle_Load_Double (ARMul_State * state, ARMword instr)
4086 ARMword write_back = BIT (21);
4087 ARMword immediate = BIT (22);
4088 ARMword add_to_base = BIT (23);
4089 ARMword pre_indexed = BIT (24);
4099 /* If the writeback bit is set, the pre-index bit must be clear. */
4100 if (write_back && ! pre_indexed)
4102 ARMul_UndefInstr (state, instr);
4106 /* Extract the base address register. */
4109 /* Extract the destination register and check it. */
4112 /* Destination register must be even. */
4114 /* Destination register cannot be LR. */
4115 || (dest_reg == 14))
4117 ARMul_UndefInstr (state, instr);
4121 /* Compute the base address. */
4122 base = state->Reg[addr_reg];
4124 /* Compute the offset. */
4125 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4127 /* Compute the sum of the two. */
4129 sum = base + offset;
4131 sum = base - offset;
4133 /* If this is a pre-indexed mode use the sum. */
4139 /* The address must be aligned on a 8 byte boundary. */
4143 ARMul_DATAABORT (addr);
4145 ARMul_UndefInstr (state, instr);
4150 /* For pre indexed or post indexed addressing modes,
4151 check that the destination registers do not overlap
4152 the address registers. */
4153 if ((! pre_indexed || write_back)
4154 && ( addr_reg == dest_reg
4155 || addr_reg == dest_reg + 1))
4157 ARMul_UndefInstr (state, instr);
4161 /* Load the words. */
4162 value1 = ARMul_LoadWordN (state, addr);
4163 value2 = ARMul_LoadWordN (state, addr + 4);
4165 /* Check for data aborts. */
4172 ARMul_Icycles (state, 2, 0L);
4174 /* Store the values. */
4175 state->Reg[dest_reg] = value1;
4176 state->Reg[dest_reg + 1] = value2;
4178 /* Do the post addressing and writeback. */
4182 if (! pre_indexed || write_back)
4183 state->Reg[addr_reg] = addr;
4186 /* This function does the work of storing two words for a STRD instruction. */
4189 Handle_Store_Double (ARMul_State * state, ARMword instr)
4193 ARMword write_back = BIT (21);
4194 ARMword immediate = BIT (22);
4195 ARMword add_to_base = BIT (23);
4196 ARMword pre_indexed = BIT (24);
4204 /* If the writeback bit is set, the pre-index bit must be clear. */
4205 if (write_back && ! pre_indexed)
4207 ARMul_UndefInstr (state, instr);
4211 /* Extract the base address register. */
4214 /* Base register cannot be PC. */
4217 ARMul_UndefInstr (state, instr);
4221 /* Extract the source register. */
4224 /* Source register must be even. */
4227 ARMul_UndefInstr (state, instr);
4231 /* Compute the base address. */
4232 base = state->Reg[addr_reg];
4234 /* Compute the offset. */
4235 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4237 /* Compute the sum of the two. */
4239 sum = base + offset;
4241 sum = base - offset;
4243 /* If this is a pre-indexed mode use the sum. */
4249 /* The address must be aligned on a 8 byte boundary. */
4253 ARMul_DATAABORT (addr);
4255 ARMul_UndefInstr (state, instr);
4260 /* For pre indexed or post indexed addressing modes,
4261 check that the destination registers do not overlap
4262 the address registers. */
4263 if ((! pre_indexed || write_back)
4264 && ( addr_reg == src_reg
4265 || addr_reg == src_reg + 1))
4267 ARMul_UndefInstr (state, instr);
4271 /* Load the words. */
4272 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
4273 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
4281 /* Do the post addressing and writeback. */
4285 if (! pre_indexed || write_back)
4286 state->Reg[addr_reg] = addr;
4289 /* This function does the work of storing a word from a STR instruction. */
4292 StoreWord (ARMul_State * state, ARMword instr, ARMword address)
4297 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4300 ARMul_StoreWordN (state, address, DEST);
4302 if (VECTORACCESS (address) || ADDREXCEPT (address))
4304 INTERNALABORT (address);
4305 (void) ARMul_LoadWordN (state, address);
4308 ARMul_StoreWordN (state, address, DEST);
4313 return state->lateabtSig;
4319 /* This function does the work of storing a byte for a STRH instruction. */
4322 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
4328 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4332 ARMul_StoreHalfWord (state, address, DEST);
4334 if (VECTORACCESS (address) || ADDREXCEPT (address))
4336 INTERNALABORT (address);
4337 (void) ARMul_LoadHalfWord (state, address);
4340 ARMul_StoreHalfWord (state, address, DEST);
4346 return state->lateabtSig;
4353 /* This function does the work of storing a byte for a STRB instruction. */
4356 StoreByte (ARMul_State * state, ARMword instr, ARMword address)
4361 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4364 ARMul_StoreByte (state, address, DEST);
4366 if (VECTORACCESS (address) || ADDREXCEPT (address))
4368 INTERNALABORT (address);
4369 (void) ARMul_LoadByte (state, address);
4372 ARMul_StoreByte (state, address, DEST);
4377 return state->lateabtSig;
4383 /* This function does the work of loading the registers listed in an LDM
4384 instruction, when the S bit is clear. The code here is always increment
4385 after, it's up to the caller to get the input address correct and to
4386 handle base register modification. */
4389 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
4395 UNDEF_LSMBaseInListWb;
4398 if (ADDREXCEPT (address))
4399 INTERNALABORT (address);
4401 if (BIT (21) && LHSReg != 15)
4404 /* N cycle first. */
4405 for (temp = 0; !BIT (temp); temp++)
4408 dest = ARMul_LoadWordN (state, address);
4410 if (!state->abortSig && !state->Aborted)
4411 state->Reg[temp++] = dest;
4412 else if (!state->Aborted)
4414 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4415 state->Aborted = ARMul_DataAbortV;
4418 /* S cycles from here on. */
4419 for (; temp < 16; temp ++)
4422 /* Load this register. */
4424 dest = ARMul_LoadWordS (state, address);
4426 if (!state->abortSig && !state->Aborted)
4427 state->Reg[temp] = dest;
4428 else if (!state->Aborted)
4430 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4431 state->Aborted = ARMul_DataAbortV;
4435 if (BIT (15) && !state->Aborted)
4436 /* PC is in the reg list. */
4437 WriteR15Branch (state, PC);
4439 /* To write back the final register. */
4440 ARMul_Icycles (state, 1, 0L);
4444 if (BIT (21) && LHSReg != 15)
4450 /* This function does the work of loading the registers listed in an LDM
4451 instruction, when the S bit is set. The code here is always increment
4452 after, it's up to the caller to get the input address correct and to
4453 handle base register modification. */
4456 LoadSMult (ARMul_State * state,
4465 UNDEF_LSMBaseInListWb;
4470 if (ADDREXCEPT (address))
4471 INTERNALABORT (address);
4474 if (BIT (21) && LHSReg != 15)
4477 if (!BIT (15) && state->Bank != USERBANK)
4479 /* Temporary reg bank switch. */
4480 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4481 UNDEF_LSMUserBankWb;
4484 /* N cycle first. */
4485 for (temp = 0; !BIT (temp); temp ++)
4488 dest = ARMul_LoadWordN (state, address);
4490 if (!state->abortSig)
4491 state->Reg[temp++] = dest;
4492 else if (!state->Aborted)
4494 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4495 state->Aborted = ARMul_DataAbortV;
4498 /* S cycles from here on. */
4499 for (; temp < 16; temp++)
4502 /* Load this register. */
4504 dest = ARMul_LoadWordS (state, address);
4506 if (!state->abortSig && !state->Aborted)
4507 state->Reg[temp] = dest;
4508 else if (!state->Aborted)
4510 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4511 state->Aborted = ARMul_DataAbortV;
4515 if (BIT (15) && !state->Aborted)
4517 /* PC is in the reg list. */
4519 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4521 state->Cpsr = GETSPSR (state->Bank);
4522 ARMul_CPSRAltered (state);
4525 WriteR15 (state, PC);
4527 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
4529 /* Protect bits in user mode. */
4530 ASSIGNN ((state->Reg[15] & NBIT) != 0);
4531 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
4532 ASSIGNC ((state->Reg[15] & CBIT) != 0);
4533 ASSIGNV ((state->Reg[15] & VBIT) != 0);
4536 ARMul_R15Altered (state);
4542 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
4543 /* Restore the correct bank. */
4544 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4546 /* To write back the final register. */
4547 ARMul_Icycles (state, 1, 0L);
4551 if (BIT (21) && LHSReg != 15)
4558 /* This function does the work of storing the registers listed in an STM
4559 instruction, when the S bit is clear. The code here is always increment
4560 after, it's up to the caller to get the input address correct and to
4561 handle base register modification. */
4564 StoreMult (ARMul_State * state,
4573 UNDEF_LSMBaseInListWb;
4576 /* N-cycle, increment the PC and update the NextInstr state. */
4580 if (VECTORACCESS (address) || ADDREXCEPT (address))
4581 INTERNALABORT (address);
4587 /* N cycle first. */
4588 for (temp = 0; !BIT (temp); temp ++)
4592 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4596 (void) ARMul_LoadWordN (state, address);
4598 /* Fake the Stores as Loads. */
4599 for (; temp < 16; temp++)
4602 /* Save this register. */
4604 (void) ARMul_LoadWordS (state, address);
4607 if (BIT (21) && LHSReg != 15)
4613 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4616 if (state->abortSig && !state->Aborted)
4618 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4619 state->Aborted = ARMul_DataAbortV;
4622 if (BIT (21) && LHSReg != 15)
4625 /* S cycles from here on. */
4626 for (; temp < 16; temp ++)
4629 /* Save this register. */
4632 ARMul_StoreWordS (state, address, state->Reg[temp]);
4634 if (state->abortSig && !state->Aborted)
4636 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4637 state->Aborted = ARMul_DataAbortV;
4645 /* This function does the work of storing the registers listed in an STM
4646 instruction when the S bit is set. The code here is always increment
4647 after, it's up to the caller to get the input address correct and to
4648 handle base register modification. */
4651 StoreSMult (ARMul_State * state,
4660 UNDEF_LSMBaseInListWb;
4665 if (VECTORACCESS (address) || ADDREXCEPT (address))
4666 INTERNALABORT (address);
4672 if (state->Bank != USERBANK)
4674 /* Force User Bank. */
4675 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4676 UNDEF_LSMUserBankWb;
4679 for (temp = 0; !BIT (temp); temp++)
4680 ; /* N cycle first. */
4683 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4687 (void) ARMul_LoadWordN (state, address);
4689 for (; temp < 16; temp++)
4690 /* Fake the Stores as Loads. */
4693 /* Save this register. */
4696 (void) ARMul_LoadWordS (state, address);
4699 if (BIT (21) && LHSReg != 15)
4706 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4709 if (state->abortSig && !state->Aborted)
4711 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4712 state->Aborted = ARMul_DataAbortV;
4715 /* S cycles from here on. */
4716 for (; temp < 16; temp++)
4719 /* Save this register. */
4722 ARMul_StoreWordS (state, address, state->Reg[temp]);
4724 if (state->abortSig && !state->Aborted)
4726 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4727 state->Aborted = ARMul_DataAbortV;
4731 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4732 /* Restore the correct bank. */
4733 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4735 if (BIT (21) && LHSReg != 15)
4742 /* This function does the work of adding two 32bit values
4743 together, and calculating if a carry has occurred. */
4746 Add32 (ARMword a1, ARMword a2, int *carry)
4748 ARMword result = (a1 + a2);
4749 unsigned int uresult = (unsigned int) result;
4750 unsigned int ua1 = (unsigned int) a1;
4752 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4753 or (result > RdLo) then we have no carry. */
4754 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
4762 /* This function does the work of multiplying
4763 two 32bit values to give a 64bit result. */
4766 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
4768 /* Operand register numbers. */
4769 int nRdHi, nRdLo, nRs, nRm;
4770 ARMword RdHi = 0, RdLo = 0, Rm;
4774 nRdHi = BITS (16, 19);
4775 nRdLo = BITS (12, 15);
4779 /* Needed to calculate the cycle count. */
4780 Rm = state->Reg[nRm];
4782 /* Check for illegal operand combinations first. */
4791 /* Intermediate results. */
4792 ARMword lo, mid1, mid2, hi;
4794 ARMword Rs = state->Reg[nRs];
4799 /* Compute sign of result and adjust operands if necessary. */
4800 sign = (Rm ^ Rs) & 0x80000000;
4802 if (((signed long) Rm) < 0)
4805 if (((signed long) Rs) < 0)
4809 /* We can split the 32x32 into four 16x16 operations. This
4810 ensures that we do not lose precision on 32bit only hosts. */
4811 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
4812 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4813 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
4814 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4816 /* We now need to add all of these results together, taking
4817 care to propogate the carries from the additions. */
4818 RdLo = Add32 (lo, (mid1 << 16), &carry);
4820 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
4822 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
4826 /* Negate result if necessary. */
4829 if (RdLo == 0xFFFFFFFF)
4838 state->Reg[nRdLo] = RdLo;
4839 state->Reg[nRdHi] = RdHi;
4842 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4845 /* Ensure that both RdHi and RdLo are used to compute Z,
4846 but don't let RdLo's sign bit make it to N. */
4847 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4849 /* The cycle count depends on whether the instruction is a signed or
4850 unsigned multiply, and what bits are clear in the multiplier. */
4851 if (msigned && (Rm & ((unsigned) 1 << 31)))
4852 /* Invert the bits to make the check against zero. */
4855 if ((Rm & 0xFFFFFF00) == 0)
4857 else if ((Rm & 0xFFFF0000) == 0)
4859 else if ((Rm & 0xFF000000) == 0)
4867 /* This function does the work of multiplying two 32bit
4868 values and adding a 64bit value to give a 64bit result. */
4871 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
4878 nRdHi = BITS (16, 19);
4879 nRdLo = BITS (12, 15);
4881 RdHi = state->Reg[nRdHi];
4882 RdLo = state->Reg[nRdLo];
4884 scount = Multiply64 (state, instr, msigned, LDEFAULT);
4886 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
4887 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
4889 state->Reg[nRdLo] = RdLo;
4890 state->Reg[nRdHi] = RdHi;
4893 /* Ensure that both RdHi and RdLo are used to compute Z,
4894 but don't let RdLo's sign bit make it to N. */
4895 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4897 /* Extra cycle for addition. */