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 3 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, see <http://www.gnu.org/licenses/>. */
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 void WriteR15Load (ARMul_State
*, ARMword
);
29 static ARMword
GetLSRegRHS (ARMul_State
*, ARMword
);
30 static ARMword
GetLS7RHS (ARMul_State
*, ARMword
);
31 static unsigned LoadWord (ARMul_State
*, ARMword
, ARMword
);
32 static unsigned LoadHalfWord (ARMul_State
*, ARMword
, ARMword
, int);
33 static unsigned LoadByte (ARMul_State
*, ARMword
, ARMword
, int);
34 static unsigned StoreWord (ARMul_State
*, ARMword
, ARMword
);
35 static unsigned StoreHalfWord (ARMul_State
*, ARMword
, ARMword
);
36 static unsigned StoreByte (ARMul_State
*, ARMword
, ARMword
);
37 static void LoadMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
38 static void StoreMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
39 static void LoadSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
40 static void StoreSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
41 static unsigned Multiply64 (ARMul_State
*, ARMword
, int, int);
42 static unsigned MultiplyAdd64 (ARMul_State
*, ARMword
, int, int);
43 static void Handle_Load_Double (ARMul_State
*, ARMword
);
44 static void Handle_Store_Double (ARMul_State
*, ARMword
);
46 #define LUNSIGNED (0) /* unsigned operation */
47 #define LSIGNED (1) /* signed operation */
48 #define LDEFAULT (0) /* default : do nothing */
49 #define LSCC (1) /* set condition codes on result */
51 extern int stop_simulator
;
53 /* Short-hand macros for LDR/STR. */
55 /* Store post decrement writeback. */
58 if (StoreHalfWord (state, instr, lhs)) \
59 LSBase = lhs - GetLS7RHS (state, instr);
61 /* Store post increment writeback. */
64 if (StoreHalfWord (state, instr, lhs)) \
65 LSBase = lhs + GetLS7RHS (state, instr);
67 /* Store pre decrement. */
69 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
71 /* Store pre decrement writeback. */
72 #define SHPREDOWNWB() \
73 temp = LHS - GetLS7RHS (state, instr); \
74 if (StoreHalfWord (state, instr, temp)) \
77 /* Store pre increment. */
79 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
81 /* Store pre increment writeback. */
83 temp = LHS + GetLS7RHS (state, instr); \
84 if (StoreHalfWord (state, instr, temp)) \
87 /* Load post decrement writeback. */
88 #define LHPOSTDOWN() \
92 temp = lhs - GetLS7RHS (state, instr); \
94 switch (BITS (5, 6)) \
97 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
101 if (LoadByte (state, instr, lhs, LSIGNED)) \
105 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
108 case 0: /* SWP handled elsewhere. */ \
117 /* Load post increment writeback. */
122 temp = lhs + GetLS7RHS (state, instr); \
124 switch (BITS (5, 6)) \
127 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
131 if (LoadByte (state, instr, lhs, LSIGNED)) \
135 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
138 case 0: /* SWP handled elsewhere. */ \
147 /* Load pre decrement. */
148 #define LHPREDOWN() \
152 temp = LHS - GetLS7RHS (state, instr); \
153 switch (BITS (5, 6)) \
156 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
159 (void) LoadByte (state, instr, temp, LSIGNED); \
162 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
165 /* SWP handled elsewhere. */ \
174 /* Load pre decrement writeback. */
175 #define LHPREDOWNWB() \
179 temp = LHS - GetLS7RHS (state, instr); \
180 switch (BITS (5, 6)) \
183 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
187 if (LoadByte (state, instr, temp, LSIGNED)) \
191 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
195 /* SWP handled elsewhere. */ \
204 /* Load pre increment. */
209 temp = LHS + GetLS7RHS (state, instr); \
210 switch (BITS (5, 6)) \
213 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
216 (void) LoadByte (state, instr, temp, LSIGNED); \
219 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
222 /* SWP handled elsewhere. */ \
231 /* Load pre increment writeback. */
232 #define LHPREUPWB() \
236 temp = LHS + GetLS7RHS (state, instr); \
237 switch (BITS (5, 6)) \
240 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
244 if (LoadByte (state, instr, temp, LSIGNED)) \
248 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
252 /* SWP handled elsewhere. */ \
261 /* Attempt to emulate an ARMv6 instruction.
262 Returns non-zero upon success. */
266 handle_v6_insn (ARMul_State
* state
, ARMword instr
)
273 switch (BITS (20, 27))
276 case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
277 case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
278 case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
279 case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
280 case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
281 case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
282 case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
283 case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
284 case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
285 case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
286 case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
287 case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
288 case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
289 case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
291 case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
292 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
293 case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
294 case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
295 case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
296 case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
297 case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
301 /* MOVW<c> <Rd>,#<imm16>
303 instr[27,20] = 0011 0000
306 instr[11, 0] = imm12. */
308 val
= (BITS (16, 19) << 12) | BITS (0, 11);
309 state
->Reg
[Rd
] = val
;
315 /* MOVT<c> <Rd>,#<imm16>
317 instr[27,20] = 0011 0100
320 instr[11, 0] = imm12. */
322 val
= (BITS (16, 19) << 12) | BITS (0, 11);
323 state
->Reg
[Rd
] &= 0xFFFF;
324 state
->Reg
[Rd
] |= val
<< 16;
339 if (Rd
== 15 || Rn
== 15 || Rm
== 15)
342 val1
= state
->Reg
[Rn
];
343 val2
= state
->Reg
[Rm
];
345 switch (BITS (4, 11))
347 case 0xF1: /* QADD16<c> <Rd>,<Rn>,<Rm>. */
350 for (i
= 0; i
< 32; i
+= 16)
352 n
= (val1
>> i
) & 0xFFFF;
356 m
= (val2
>> i
) & 0xFFFF;
364 else if (r
< -(0x8000))
367 state
->Reg
[Rd
] |= (r
& 0xFFFF) << i
;
371 case 0xF3: /* QASX<c> <Rd>,<Rn>,<Rm>. */
376 m
= (val2
>> 16) & 0xFFFF;
384 else if (r
< -(0x8000))
387 state
->Reg
[Rd
] = (r
& 0xFFFF);
389 n
= (val1
>> 16) & 0xFFFF;
401 else if (r
< -(0x8000))
404 state
->Reg
[Rd
] |= (r
& 0xFFFF) << 16;
407 case 0xF5: /* QSAX<c> <Rd>,<Rn>,<Rm>. */
412 m
= (val2
>> 16) & 0xFFFF;
420 else if (r
< -(0x8000))
423 state
->Reg
[Rd
] = (r
& 0xFFFF);
425 n
= (val1
>> 16) & 0xFFFF;
437 else if (r
< -(0x8000))
440 state
->Reg
[Rd
] |= (r
& 0xFFFF) << 16;
443 case 0xF7: /* QSUB16<c> <Rd>,<Rn>,<Rm>. */
446 for (i
= 0; i
< 32; i
+= 16)
448 n
= (val1
>> i
) & 0xFFFF;
452 m
= (val2
>> i
) & 0xFFFF;
460 else if (r
< -(0x8000))
463 state
->Reg
[Rd
] |= (r
& 0xFFFF) << i
;
467 case 0xF9: /* QADD8<c> <Rd>,<Rn>,<Rm>. */
470 for (i
= 0; i
< 32; i
+= 8)
472 n
= (val1
>> i
) & 0xFF;
476 m
= (val2
>> i
) & 0xFF;
487 state
->Reg
[Rd
] |= (r
& 0xFF) << i
;
491 case 0xFF: /* QSUB8<c> <Rd>,<Rn>,<Rm>. */
494 for (i
= 0; i
< 32; i
+= 8)
496 n
= (val1
>> i
) & 0xFF;
500 m
= (val2
>> i
) & 0xFF;
511 state
->Reg
[Rd
] |= (r
& 0xFF) << i
;
525 ARMword res1
, res2
, res3
, res4
;
527 /* U{ADD|SUB}{8|16}<c> <Rd>, <Rn>, <Rm>
529 instr[27,20] = 0110 0101
533 instr[ 7, 4] = opcode: UADD8 (1001), UADD16 (0001), USUB8 (1111), USUB16 (0111)
534 instr[ 3, 0] = Rm. */
535 if (BITS (8, 11) != 0xF)
542 if (Rn
== 15 || Rd
== 15 || Rm
== 15)
544 ARMul_UndefInstr (state
, instr
);
545 state
->Emulate
= FALSE
;
549 valn
= state
->Reg
[Rn
];
550 valm
= state
->Reg
[Rm
];
554 case 1: /* UADD16. */
555 res1
= (valn
& 0xFFFF) + (valm
& 0xFFFF);
557 state
->Cpsr
|= (GE0
| GE1
);
559 state
->Cpsr
&= ~ (GE0
| GE1
);
561 res2
= (valn
>> 16) + (valm
>> 16);
563 state
->Cpsr
|= (GE2
| GE3
);
565 state
->Cpsr
&= ~ (GE2
| GE3
);
567 state
->Reg
[Rd
] = (res1
& 0xFFFF) | (res2
<< 16);
570 case 7: /* USUB16. */
571 res1
= (valn
& 0xFFFF) - (valm
& 0xFFFF);
573 state
->Cpsr
|= (GE0
| GE1
);
575 state
->Cpsr
&= ~ (GE0
| GE1
);
577 res2
= (valn
>> 16) - (valm
>> 16);
579 state
->Cpsr
|= (GE2
| GE3
);
581 state
->Cpsr
&= ~ (GE2
| GE3
);
583 state
->Reg
[Rd
] = (res1
& 0xFFFF) | (res2
<< 16);
587 res1
= (valn
& 0xFF) + (valm
& 0xFF);
591 state
->Cpsr
&= ~ GE0
;
593 res2
= ((valn
>> 8) & 0xFF) + ((valm
>> 8) & 0xFF);
597 state
->Cpsr
&= ~ GE1
;
599 res3
= ((valn
>> 16) & 0xFF) + ((valm
>> 16) & 0xFF);
603 state
->Cpsr
&= ~ GE2
;
605 res4
= (valn
>> 24) + (valm
>> 24);
609 state
->Cpsr
&= ~ GE3
;
611 state
->Reg
[Rd
] = (res1
& 0xFF) | ((res2
<< 8) & 0xFF00)
612 | ((res3
<< 16) & 0xFF0000) | (res4
<< 24);
615 case 15: /* USUB8. */
616 res1
= (valn
& 0xFF) - (valm
& 0xFF);
620 state
->Cpsr
&= ~ GE0
;
622 res2
= ((valn
>> 8) & 0XFF) - ((valm
>> 8) & 0xFF);
626 state
->Cpsr
&= ~ GE1
;
628 res3
= ((valn
>> 16) & 0XFF) - ((valm
>> 16) & 0xFF);
632 state
->Cpsr
&= ~ GE2
;
634 res4
= (valn
>> 24) - (valm
>> 24) ;
638 state
->Cpsr
&= ~ GE3
;
640 state
->Reg
[Rd
] = (res1
& 0xFF) | ((res2
<< 8) & 0xFF00)
641 | ((res3
<< 16) & 0xFF0000) | (res4
<< 24);
654 /* PKHBT<c> <Rd>,<Rn>,<Rm>{,LSL #<imm>}
655 PKHTB<c> <Rd>,<Rn>,<Rm>{,ASR #<imm>}
656 SXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>}
657 SXTB16<c> <Rd>,<Rm>{,<rotation>}
658 SEL<c> <Rd>,<Rn>,<Rm>
661 instr[27,20] = 0110 1000
664 instr[11, 7] = imm5 (PKH), 11111 (SEL), rr000 (SXTAB16 & SXTB16),
665 instr[6] = tb (PKH), 0 (SEL), 1 (SXT)
666 instr[5] = opcode: PKH (0), SEL/SXT (1)
668 instr[ 3, 0] = Rm. */
675 /* FIXME: Add implementation of PKH. */
676 fprintf (stderr
, "PKH: NOT YET IMPLEMENTED\n");
677 ARMul_UndefInstr (state
, instr
);
683 /* FIXME: Add implementation of SXT. */
684 fprintf (stderr
, "SXT: NOT YET IMPLEMENTED\n");
685 ARMul_UndefInstr (state
, instr
);
692 if (Rn
== 15 || Rm
== 15 || Rd
== 15)
694 ARMul_UndefInstr (state
, instr
);
695 state
->Emulate
= FALSE
;
699 res
= (state
->Reg
[(state
->Cpsr
& GE0
) ? Rn
: Rm
]) & 0xFF;
700 res
|= (state
->Reg
[(state
->Cpsr
& GE1
) ? Rn
: Rm
]) & 0xFF00;
701 res
|= (state
->Reg
[(state
->Cpsr
& GE2
) ? Rn
: Rm
]) & 0xFF0000;
702 res
|= (state
->Reg
[(state
->Cpsr
& GE3
) ? Rn
: Rm
]) & 0xFF000000;
703 state
->Reg
[Rd
] = res
;
711 switch (BITS (4, 11))
713 case 0x07: ror
= 0; break;
714 case 0x47: ror
= 8; break;
715 case 0x87: ror
= 16; break;
716 case 0xc7: ror
= 24; break;
720 printf ("Unhandled v6 insn: ssat\n");
729 if (BITS (4, 6) == 0x7)
731 printf ("Unhandled v6 insn: ssat\n");
737 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
741 if (BITS (16, 19) == 0xf)
743 state
->Reg
[BITS (12, 15)] = Rm
;
746 state
->Reg
[BITS (12, 15)] += Rm
;
754 switch (BITS (4, 11))
756 case 0x07: ror
= 0; break;
757 case 0x47: ror
= 8; break;
758 case 0x87: ror
= 16; break;
759 case 0xc7: ror
= 24; break;
765 instr[27,20] = 0110 1011
768 instr[11, 4] = 1111 0011
769 instr[ 3, 0] = Rm. */
770 if (BITS (16, 19) != 0xF)
775 if (Rd
== 15 || Rm
== 15)
777 ARMul_UndefInstr (state
, instr
);
778 state
->Emulate
= FALSE
;
782 val
= state
->Reg
[Rm
] << 24;
783 val
|= ((state
->Reg
[Rm
] << 8) & 0xFF0000);
784 val
|= ((state
->Reg
[Rm
] >> 8) & 0xFF00);
785 val
|= ((state
->Reg
[Rm
] >> 24));
786 state
->Reg
[Rd
] = val
;
792 /* REV16<c> <Rd>,<Rm>. */
793 if (BITS (16, 19) != 0xF)
798 if (Rd
== 15 || Rm
== 15)
800 ARMul_UndefInstr (state
, instr
);
801 state
->Emulate
= FALSE
;
806 val
|= ((state
->Reg
[Rm
] >> 8) & 0x00FF00FF);
807 val
|= ((state
->Reg
[Rm
] << 8) & 0xFF00FF00);
808 state
->Reg
[Rd
] = val
;
819 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
823 if (BITS (16, 19) == 0xf)
825 state
->Reg
[BITS (12, 15)] = Rm
;
828 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
836 switch (BITS (4, 11))
838 case 0x07: ror
= 0; break;
839 case 0x47: ror
= 8; break;
840 case 0x87: ror
= 16; break;
841 case 0xc7: ror
= 24; break;
845 printf ("Unhandled v6 insn: usat\n");
854 if (BITS (4, 6) == 0x7)
856 printf ("Unhandled v6 insn: usat\n");
862 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
864 if (BITS (16, 19) == 0xf)
866 state
->Reg
[BITS (12, 15)] = Rm
;
869 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
878 switch (BITS (4, 11))
880 case 0x07: ror
= 0; break;
881 case 0x47: ror
= 8; break;
882 case 0x87: ror
= 16; break;
883 case 0xc7: ror
= 24; break;
885 case 0xf3: /* RBIT */
886 if (BITS (16, 19) != 0xF)
890 Rm
= state
->Reg
[BITS (0, 3)];
891 for (i
= 0; i
< 32; i
++)
893 state
->Reg
[Rd
] |= (1 << (31 - i
));
897 printf ("Unhandled v6 insn: revsh\n");
907 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
909 if (BITS (16, 19) == 0xf)
911 state
->Reg
[BITS (12, 15)] = Rm
;
914 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
925 /* BFC<c> <Rd>,#<lsb>,#<width>
926 BFI<c> <Rd>,<Rn>,#<lsb>,#<width>
929 instr[27,21] = 0111 110
933 instr[ 6, 4] = 001 1111
934 instr[ 3, 0] = Rn (BFI) / 1111 (BFC). */
936 if (BITS (4, 6) != 0x1)
942 ARMul_UndefInstr (state
, instr
);
943 state
->Emulate
= FALSE
;
950 ARMul_UndefInstr (state
, instr
);
951 state
->Emulate
= FALSE
;
955 mask
&= ~(-(1 << (msb
+ 1)));
956 state
->Reg
[Rd
] &= ~ mask
;
961 ARMword val
= state
->Reg
[Rn
] & ~(-(1 << ((msb
+ 1) - lsb
)));
962 state
->Reg
[Rd
] |= val
<< lsb
;
968 case 0x7a: /* SBFX<c> <Rd>,<Rn>,#<lsb>,#<width>. */
974 if (BITS (4, 6) != 0x5)
980 ARMul_UndefInstr (state
, instr
);
981 state
->Emulate
= FALSE
;
987 ARMul_UndefInstr (state
, instr
);
988 state
->Emulate
= FALSE
;
992 widthm1
= BITS (16, 20);
994 sval
= state
->Reg
[Rn
];
995 sval
<<= (31 - (lsb
+ widthm1
));
996 sval
>>= (31 - widthm1
);
997 state
->Reg
[Rd
] = sval
;
1008 /* UBFX<c> <Rd>,<Rn>,#<lsb>,#<width>
1010 instr[27,21] = 0111 111
1011 instr[20,16] = widthm1
1015 instr[ 3, 0] = Rn. */
1017 if (BITS (4, 6) != 0x5)
1023 ARMul_UndefInstr (state
, instr
);
1024 state
->Emulate
= FALSE
;
1030 ARMul_UndefInstr (state
, instr
);
1031 state
->Emulate
= FALSE
;
1035 widthm1
= BITS (16, 20);
1037 val
= state
->Reg
[Rn
];
1039 val
&= ~(-(1 << (widthm1
+ 1)));
1041 state
->Reg
[Rd
] = val
;
1046 case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
1051 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr
);
1057 handle_VFP_move (ARMul_State
* state
, ARMword instr
)
1059 switch (BITS (20, 27))
1063 switch (BITS (4, 11))
1068 /* VMOV two core <-> two VFP single precision. */
1069 int sreg
= (BITS (0, 3) << 1) | BIT (5);
1073 state
->Reg
[BITS (12, 15)] = VFP_uword (sreg
);
1074 state
->Reg
[BITS (16, 19)] = VFP_uword (sreg
+ 1);
1078 VFP_uword (sreg
) = state
->Reg
[BITS (12, 15)];
1079 VFP_uword (sreg
+ 1) = state
->Reg
[BITS (16, 19)];
1087 /* VMOV two core <-> VFP double precision. */
1088 int dreg
= BITS (0, 3) | (BIT (5) << 4);
1093 fprintf (stderr
, " VFP: VMOV: r%d r%d <= d%d\n",
1094 BITS (12, 15), BITS (16, 19), dreg
);
1096 state
->Reg
[BITS (12, 15)] = VFP_dword (dreg
);
1097 state
->Reg
[BITS (16, 19)] = VFP_dword (dreg
) >> 32;
1101 VFP_dword (dreg
) = state
->Reg
[BITS (16, 19)];
1102 VFP_dword (dreg
) <<= 32;
1103 VFP_dword (dreg
) |= state
->Reg
[BITS (12, 15)];
1106 fprintf (stderr
, " VFP: VMOV: d%d <= r%d r%d : %g\n",
1107 dreg
, BITS (16, 19), BITS (12, 15),
1114 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1121 /* VMOV single core <-> VFP single precision. */
1122 if (BITS (0, 6) != 0x10 || BITS (8, 11) != 0xA)
1123 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1126 int sreg
= (BITS (16, 19) << 1) | BIT (7);
1129 state
->Reg
[DESTReg
] = VFP_uword (sreg
);
1131 VFP_uword (sreg
) = state
->Reg
[DESTReg
];
1136 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1141 /* EMULATION of ARM6. */
1143 /* The PC pipeline value depends on whether ARM
1144 or Thumb instructions are being executed. */
1149 ARMul_Emulate32 (ARMul_State
* state
)
1151 ARMul_Emulate26 (ARMul_State
* state
)
1154 ARMword instr
; /* The current instruction. */
1155 ARMword dest
= 0; /* Almost the DestBus. */
1156 ARMword temp
; /* Ubiquitous third hand. */
1157 ARMword pc
= 0; /* The address of the current instruction. */
1158 ARMword lhs
; /* Almost the ABus and BBus. */
1160 ARMword decoded
= 0; /* Instruction pipeline. */
1163 /* Execute the next instruction. */
1165 if (state
->NextInstr
< PRIMEPIPE
)
1167 decoded
= state
->decoded
;
1168 loaded
= state
->loaded
;
1174 /* Just keep going. */
1177 switch (state
->NextInstr
)
1180 /* Advance the pipeline, and an S cycle. */
1181 state
->Reg
[15] += isize
;
1185 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1189 /* Advance the pipeline, and an N cycle. */
1190 state
->Reg
[15] += isize
;
1194 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
1199 /* Program counter advanced, and an S cycle. */
1203 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1208 /* Program counter advanced, and an N cycle. */
1212 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
1217 /* The program counter has been changed. */
1218 pc
= state
->Reg
[15];
1220 pc
= pc
& R15PCBITS
;
1222 state
->Reg
[15] = pc
+ (isize
* 2);
1224 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
1225 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
1226 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
1231 /* The program counter has been changed. */
1232 pc
= state
->Reg
[15];
1234 pc
= pc
& R15PCBITS
;
1236 state
->Reg
[15] = pc
+ (isize
* 2);
1238 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
1239 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
1240 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1245 if (state
->EventSet
)
1246 ARMul_EnvokeEvent (state
);
1248 if (! TFLAG
&& trace
)
1250 fprintf (stderr
, "pc: %x, ", pc
& ~1);
1252 fprintf (stderr
, "instr: %x\n", instr
);
1255 if (instr
== 0 || pc
< 0x10)
1257 ARMul_Abort (state
, ARMUndefinedInstrV
);
1258 state
->Emulate
= FALSE
;
1261 #if 0 /* Enable this code to help track down stack alignment bugs. */
1263 static ARMword old_sp
= -1;
1265 if (old_sp
!= state
->Reg
[13])
1267 old_sp
= state
->Reg
[13];
1268 fprintf (stderr
, "pc: %08x: SP set to %08x%s\n",
1269 pc
& ~1, old_sp
, (old_sp
% 8) ? " [UNALIGNED!]" : "");
1274 if (state
->Exception
)
1276 /* Any exceptions ? */
1277 if (state
->NresetSig
== LOW
)
1279 ARMul_Abort (state
, ARMul_ResetV
);
1282 else if (!state
->NfiqSig
&& !FFLAG
)
1284 ARMul_Abort (state
, ARMul_FIQV
);
1287 else if (!state
->NirqSig
&& !IFLAG
)
1289 ARMul_Abort (state
, ARMul_IRQV
);
1294 if (state
->CallDebug
> 0)
1296 if (state
->Emulate
< ONCE
)
1298 state
->NextInstr
= RESUME
;
1303 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n",
1304 (long) pc
, (long) instr
, (long) state
->Mode
);
1305 (void) fgetc (stdin
);
1308 else if (state
->Emulate
< ONCE
)
1310 state
->NextInstr
= RESUME
;
1317 /* Provide Thumb instruction decoding. If the processor is in Thumb
1318 mode, then we can simply decode the Thumb instruction, and map it
1319 to the corresponding ARM instruction (by directly loading the
1320 instr variable, and letting the normal ARM simulator
1321 execute). There are some caveats to ensure that the correct
1322 pipelined PC value is used when executing Thumb code, and also for
1323 dealing with the BL instruction. */
1328 /* Check if in Thumb mode. */
1329 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
1332 /* This is a Thumb instruction. */
1333 ARMul_UndefInstr (state
, instr
);
1337 /* Already processed. */
1341 /* ARM instruction available. */
1344 fprintf (stderr
, " emulate as: ");
1346 fprintf (stderr
, "%08x ", new);
1348 fprintf (stderr
, "\n");
1351 /* So continue instruction decoding. */
1361 /* Check the condition codes. */
1362 if ((temp
= TOPBITS (28)) == AL
)
1363 /* Vile deed in the need for speed. */
1366 /* Check the condition code. */
1367 switch ((int) TOPBITS (28))
1375 if (BITS (25, 27) == 5) /* BLX(1) */
1379 state
->Reg
[14] = pc
+ 4;
1381 /* Force entry into Thumb mode. */
1384 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
1386 dest
+= POSBRANCH
+ (BIT (24) << 1);
1388 WriteR15Branch (state
, dest
);
1391 else if ((instr
& 0xFC70F000) == 0xF450F000)
1392 /* The PLD instruction. Ignored. */
1394 else if ( ((instr
& 0xfe500f00) == 0xfc100100)
1395 || ((instr
& 0xfe500f00) == 0xfc000100))
1396 /* wldrw and wstrw are unconditional. */
1399 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
1400 ARMul_UndefInstr (state
, instr
);
1429 temp
= (CFLAG
&& !ZFLAG
);
1432 temp
= (!CFLAG
|| ZFLAG
);
1435 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
1438 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
1441 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
1444 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
1448 /* Handle the Clock counter here. */
1449 if (state
->is_XScale
)
1454 ok
= state
->CPRead
[14] (state
, 0, & cp14r0
);
1456 if (ok
&& (cp14r0
& ARMul_CP14_R0_ENABLE
))
1458 unsigned long newcycles
, nowtime
= ARMul_Time (state
);
1460 newcycles
= nowtime
- state
->LastTime
;
1461 state
->LastTime
= nowtime
;
1463 if (cp14r0
& ARMul_CP14_R0_CCD
)
1465 if (state
->CP14R0_CCD
== -1)
1466 state
->CP14R0_CCD
= newcycles
;
1468 state
->CP14R0_CCD
+= newcycles
;
1470 if (state
->CP14R0_CCD
>= 64)
1474 while (state
->CP14R0_CCD
>= 64)
1475 state
->CP14R0_CCD
-= 64, newcycles
++;
1485 state
->CP14R0_CCD
= -1;
1488 cp14r0
|= ARMul_CP14_R0_FLAG2
;
1489 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
1491 ok
= state
->CPRead
[14] (state
, 1, & cp14r1
);
1493 /* Coded like this for portability. */
1494 while (ok
&& newcycles
)
1496 if (cp14r1
== 0xffffffff)
1507 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
1509 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
1513 if (state
->CPRead
[13] (state
, 8, & temp
)
1514 && (temp
& ARMul_CP13_R8_PMUS
))
1515 ARMul_Abort (state
, ARMul_FIQV
);
1517 ARMul_Abort (state
, ARMul_IRQV
);
1523 /* Handle hardware instructions breakpoints here. */
1524 if (state
->is_XScale
)
1526 if ( (pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
1527 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
1529 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
1530 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1534 /* Actual execution of instructions begins here. */
1535 /* If the condition codes don't match, stop here. */
1540 if (state
->is_XScale
)
1542 if (BIT (20) == 0 && BITS (25, 27) == 0)
1544 if (BITS (4, 7) == 0xD)
1546 /* XScale Load Consecutive insn. */
1547 ARMword temp
= GetLS7RHS (state
, instr
);
1548 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
1549 ARMword addr
= BIT (24) ? temp2
: LHS
;
1552 ARMul_UndefInstr (state
, instr
);
1554 /* Alignment violation. */
1555 ARMul_Abort (state
, ARMul_DataAbortV
);
1558 int wb
= BIT (21) || (! BIT (24));
1560 state
->Reg
[BITS (12, 15)] =
1561 ARMul_LoadWordN (state
, addr
);
1562 state
->Reg
[BITS (12, 15) + 1] =
1563 ARMul_LoadWordN (state
, addr
+ 4);
1570 else if (BITS (4, 7) == 0xF)
1572 /* XScale Store Consecutive insn. */
1573 ARMword temp
= GetLS7RHS (state
, instr
);
1574 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
1575 ARMword addr
= BIT (24) ? temp2
: LHS
;
1578 ARMul_UndefInstr (state
, instr
);
1580 /* Alignment violation. */
1581 ARMul_Abort (state
, ARMul_DataAbortV
);
1584 ARMul_StoreWordN (state
, addr
,
1585 state
->Reg
[BITS (12, 15)]);
1586 ARMul_StoreWordN (state
, addr
+ 4,
1587 state
->Reg
[BITS (12, 15) + 1]);
1589 if (BIT (21)|| ! BIT (24))
1597 if (ARMul_HandleIwmmxt (state
, instr
))
1601 switch ((int) BITS (20, 27))
1603 /* Data Processing Register RHS Instructions. */
1605 case 0x00: /* AND reg and MUL */
1607 if (BITS (4, 11) == 0xB)
1609 /* STRH register offset, no write-back, down, post indexed. */
1613 if (BITS (4, 7) == 0xD)
1615 Handle_Load_Double (state
, instr
);
1618 if (BITS (4, 7) == 0xF)
1620 Handle_Store_Double (state
, instr
);
1624 if (BITS (4, 7) == 9)
1627 rhs
= state
->Reg
[MULRHSReg
];
1628 if (MULLHSReg
== MULDESTReg
)
1631 state
->Reg
[MULDESTReg
] = 0;
1633 else if (MULDESTReg
!= 15)
1634 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
1638 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1639 if (rhs
& (1L << dest
))
1642 /* Mult takes this many/2 I cycles. */
1643 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1654 case 0x01: /* ANDS reg and MULS */
1656 if ((BITS (4, 11) & 0xF9) == 0x9)
1657 /* LDR register offset, no write-back, down, post indexed. */
1659 /* Fall through to rest of decoding. */
1661 if (BITS (4, 7) == 9)
1664 rhs
= state
->Reg
[MULRHSReg
];
1666 if (MULLHSReg
== MULDESTReg
)
1669 state
->Reg
[MULDESTReg
] = 0;
1673 else if (MULDESTReg
!= 15)
1675 dest
= state
->Reg
[MULLHSReg
] * rhs
;
1676 ARMul_NegZero (state
, dest
);
1677 state
->Reg
[MULDESTReg
] = dest
;
1682 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1683 if (rhs
& (1L << dest
))
1686 /* Mult takes this many/2 I cycles. */
1687 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1698 case 0x02: /* EOR reg and MLA */
1700 if (BITS (4, 11) == 0xB)
1702 /* STRH register offset, write-back, down, post indexed. */
1707 if (BITS (4, 7) == 9)
1709 rhs
= state
->Reg
[MULRHSReg
];
1710 if (MULLHSReg
== MULDESTReg
)
1713 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
1715 else if (MULDESTReg
!= 15)
1716 state
->Reg
[MULDESTReg
] =
1717 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1721 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1722 if (rhs
& (1L << dest
))
1725 /* Mult takes this many/2 I cycles. */
1726 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1736 case 0x03: /* EORS reg and MLAS */
1738 if ((BITS (4, 11) & 0xF9) == 0x9)
1739 /* LDR register offset, write-back, down, post-indexed. */
1741 /* Fall through to rest of the decoding. */
1743 if (BITS (4, 7) == 9)
1746 rhs
= state
->Reg
[MULRHSReg
];
1748 if (MULLHSReg
== MULDESTReg
)
1751 dest
= state
->Reg
[MULACCReg
];
1752 ARMul_NegZero (state
, dest
);
1753 state
->Reg
[MULDESTReg
] = dest
;
1755 else if (MULDESTReg
!= 15)
1758 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1759 ARMul_NegZero (state
, dest
);
1760 state
->Reg
[MULDESTReg
] = dest
;
1765 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1766 if (rhs
& (1L << dest
))
1769 /* Mult takes this many/2 I cycles. */
1770 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1781 case 0x04: /* SUB reg */
1783 if (BITS (4, 7) == 0xB)
1785 /* STRH immediate offset, no write-back, down, post indexed. */
1789 if (BITS (4, 7) == 0xD)
1791 Handle_Load_Double (state
, instr
);
1794 if (BITS (4, 7) == 0xF)
1796 Handle_Store_Double (state
, instr
);
1805 case 0x05: /* SUBS reg */
1807 if ((BITS (4, 7) & 0x9) == 0x9)
1808 /* LDR immediate offset, no write-back, down, post indexed. */
1810 /* Fall through to the rest of the instruction decoding. */
1816 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1818 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1819 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1829 case 0x06: /* RSB reg */
1831 if (BITS (4, 7) == 0xB)
1833 /* STRH immediate offset, write-back, down, post indexed. */
1843 case 0x07: /* RSBS reg */
1845 if ((BITS (4, 7) & 0x9) == 0x9)
1846 /* LDR immediate offset, write-back, down, post indexed. */
1848 /* Fall through to remainder of instruction decoding. */
1854 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1856 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1857 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1867 case 0x08: /* ADD reg */
1869 if (BITS (4, 11) == 0xB)
1871 /* STRH register offset, no write-back, up, post indexed. */
1875 if (BITS (4, 7) == 0xD)
1877 Handle_Load_Double (state
, instr
);
1880 if (BITS (4, 7) == 0xF)
1882 Handle_Store_Double (state
, instr
);
1887 if (BITS (4, 7) == 0x9)
1891 ARMul_Icycles (state
,
1892 Multiply64 (state
, instr
, LUNSIGNED
,
1902 case 0x09: /* ADDS reg */
1904 if ((BITS (4, 11) & 0xF9) == 0x9)
1905 /* LDR register offset, no write-back, up, post indexed. */
1907 /* Fall through to remaining instruction decoding. */
1910 if (BITS (4, 7) == 0x9)
1914 ARMul_Icycles (state
,
1915 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
1923 ASSIGNZ (dest
== 0);
1924 if ((lhs
| rhs
) >> 30)
1926 /* Possible C,V,N to set. */
1927 ASSIGNN (NEG (dest
));
1928 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1929 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1940 case 0x0a: /* ADC reg */
1942 if (BITS (4, 11) == 0xB)
1944 /* STRH register offset, write-back, up, post-indexed. */
1948 if (BITS (4, 7) == 0x9)
1952 ARMul_Icycles (state
,
1953 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1959 dest
= LHS
+ rhs
+ CFLAG
;
1963 case 0x0b: /* ADCS reg */
1965 if ((BITS (4, 11) & 0xF9) == 0x9)
1966 /* LDR register offset, write-back, up, post indexed. */
1968 /* Fall through to remaining instruction decoding. */
1969 if (BITS (4, 7) == 0x9)
1973 ARMul_Icycles (state
,
1974 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1981 dest
= lhs
+ rhs
+ CFLAG
;
1982 ASSIGNZ (dest
== 0);
1983 if ((lhs
| rhs
) >> 30)
1985 /* Possible C,V,N to set. */
1986 ASSIGNN (NEG (dest
));
1987 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1988 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1999 case 0x0c: /* SBC reg */
2001 if (BITS (4, 7) == 0xB)
2003 /* STRH immediate offset, no write-back, up post indexed. */
2007 if (BITS (4, 7) == 0xD)
2009 Handle_Load_Double (state
, instr
);
2012 if (BITS (4, 7) == 0xF)
2014 Handle_Store_Double (state
, instr
);
2017 if (BITS (4, 7) == 0x9)
2021 ARMul_Icycles (state
,
2022 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
2028 dest
= LHS
- rhs
- !CFLAG
;
2032 case 0x0d: /* SBCS reg */
2034 if ((BITS (4, 7) & 0x9) == 0x9)
2035 /* LDR immediate offset, no write-back, up, post indexed. */
2038 if (BITS (4, 7) == 0x9)
2042 ARMul_Icycles (state
,
2043 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
2050 dest
= lhs
- rhs
- !CFLAG
;
2051 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2053 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2054 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2064 case 0x0e: /* RSC reg */
2066 if (BITS (4, 7) == 0xB)
2068 /* STRH immediate offset, write-back, up, post indexed. */
2073 if (BITS (4, 7) == 0x9)
2077 ARMul_Icycles (state
,
2078 MultiplyAdd64 (state
, instr
, LSIGNED
,
2084 dest
= rhs
- LHS
- !CFLAG
;
2088 case 0x0f: /* RSCS reg */
2090 if ((BITS (4, 7) & 0x9) == 0x9)
2091 /* LDR immediate offset, write-back, up, post indexed. */
2093 /* Fall through to remaining instruction decoding. */
2095 if (BITS (4, 7) == 0x9)
2099 ARMul_Icycles (state
,
2100 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
2107 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 0x10: /* TST reg and MRS CPSR and SWP word. */
2125 if (BIT (4) == 0 && BIT (7) == 1)
2127 /* ElSegundo SMLAxy insn. */
2128 ARMword op1
= state
->Reg
[BITS (0, 3)];
2129 ARMword op2
= state
->Reg
[BITS (8, 11)];
2130 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2144 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
2146 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
2150 if (BITS (4, 11) == 5)
2152 /* ElSegundo QADD insn. */
2153 ARMword op1
= state
->Reg
[BITS (0, 3)];
2154 ARMword op2
= state
->Reg
[BITS (16, 19)];
2155 ARMword result
= op1
+ op2
;
2156 if (AddOverflow (op1
, op2
, result
))
2158 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2161 state
->Reg
[BITS (12, 15)] = result
;
2166 if (BITS (4, 11) == 0xB)
2168 /* STRH register offset, no write-back, down, pre indexed. */
2172 if (BITS (4, 7) == 0xD)
2174 Handle_Load_Double (state
, instr
);
2177 if (BITS (4, 7) == 0xF)
2179 Handle_Store_Double (state
, instr
);
2183 if (BITS (4, 11) == 9)
2190 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2192 INTERNALABORT (temp
);
2193 (void) ARMul_LoadWordN (state
, temp
);
2194 (void) ARMul_LoadWordN (state
, temp
);
2198 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
2200 DEST
= ARMul_Align (state
, temp
, dest
);
2203 if (state
->abortSig
|| state
->Aborted
)
2206 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2209 DEST
= ECC
| EINT
| EMODE
;
2215 && handle_v6_insn (state
, instr
))
2222 case 0x11: /* TSTP reg */
2224 if ((BITS (4, 11) & 0xF9) == 0x9)
2225 /* LDR register offset, no write-back, down, pre indexed. */
2227 /* Continue with remaining instruction decode. */
2233 state
->Cpsr
= GETSPSR (state
->Bank
);
2234 ARMul_CPSRAltered (state
);
2246 ARMul_NegZero (state
, dest
);
2250 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
2253 if (BITS (4, 7) == 3)
2259 temp
= (pc
+ 2) | 1;
2263 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2264 state
->Reg
[14] = temp
;
2271 if (BIT (4) == 0 && BIT (7) == 1
2272 && (BIT (5) == 0 || BITS (12, 15) == 0))
2274 /* ElSegundo SMLAWy/SMULWy insn. */
2275 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2276 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2281 if (op1
& 0x80000000)
2286 result
= (op1
* op2
) >> 16;
2290 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2292 if (AddOverflow (result
, Rn
, result
+ Rn
))
2296 state
->Reg
[BITS (16, 19)] = result
;
2300 if (BITS (4, 11) == 5)
2302 /* ElSegundo QSUB insn. */
2303 ARMword op1
= state
->Reg
[BITS (0, 3)];
2304 ARMword op2
= state
->Reg
[BITS (16, 19)];
2305 ARMword result
= op1
- op2
;
2307 if (SubOverflow (op1
, op2
, result
))
2309 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2313 state
->Reg
[BITS (12, 15)] = result
;
2318 if (BITS (4, 11) == 0xB)
2320 /* STRH register offset, write-back, down, pre indexed. */
2324 if (BITS (4, 27) == 0x12FFF1)
2327 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2330 if (BITS (4, 7) == 0xD)
2332 Handle_Load_Double (state
, instr
);
2335 if (BITS (4, 7) == 0xF)
2337 Handle_Store_Double (state
, instr
);
2343 if (BITS (4, 7) == 0x7)
2345 extern int SWI_vector_installed
;
2347 /* Hardware is allowed to optionally override this
2348 instruction and treat it as a breakpoint. Since
2349 this is a simulator not hardware, we take the position
2350 that if a SWI vector was not installed, then an Abort
2351 vector was probably not installed either, and so
2352 normally this instruction would be ignored, even if an
2353 Abort is generated. This is a bad thing, since GDB
2354 uses this instruction for its breakpoints (at least in
2355 Thumb mode it does). So intercept the instruction here
2356 and generate a breakpoint SWI instead. */
2357 if (! SWI_vector_installed
)
2358 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
2361 /* BKPT - normally this will cause an abort, but on the
2362 XScale we must check the DCSR. */
2363 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
2364 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
2368 /* Force the next instruction to be refetched. */
2369 state
->NextInstr
= RESUME
;
2375 /* MSR reg to CPSR. */
2379 /* Don't allow TBIT to be set by MSR. */
2382 ARMul_FixCPSR (state
, instr
, temp
);
2385 else if (state
->is_v6
2386 && handle_v6_insn (state
, instr
))
2394 case 0x13: /* TEQP reg */
2396 if ((BITS (4, 11) & 0xF9) == 0x9)
2397 /* LDR register offset, write-back, down, pre indexed. */
2399 /* Continue with remaining instruction decode. */
2405 state
->Cpsr
= GETSPSR (state
->Bank
);
2406 ARMul_CPSRAltered (state
);
2418 ARMul_NegZero (state
, dest
);
2422 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
2425 if (BIT (4) == 0 && BIT (7) == 1)
2427 /* ElSegundo SMLALxy insn. */
2428 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2429 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2443 dest
= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
2444 dest
|= state
->Reg
[BITS (12, 15)];
2446 state
->Reg
[BITS (12, 15)] = dest
;
2447 state
->Reg
[BITS (16, 19)] = dest
>> 32;
2451 if (BITS (4, 11) == 5)
2453 /* ElSegundo QDADD insn. */
2454 ARMword op1
= state
->Reg
[BITS (0, 3)];
2455 ARMword op2
= state
->Reg
[BITS (16, 19)];
2456 ARMword op2d
= op2
+ op2
;
2459 if (AddOverflow (op2
, op2
, op2d
))
2462 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2465 result
= op1
+ op2d
;
2466 if (AddOverflow (op1
, op2d
, result
))
2469 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2472 state
->Reg
[BITS (12, 15)] = result
;
2477 if (BITS (4, 7) == 0xB)
2479 /* STRH immediate offset, no write-back, down, pre indexed. */
2483 if (BITS (4, 7) == 0xD)
2485 Handle_Load_Double (state
, instr
);
2488 if (BITS (4, 7) == 0xF)
2490 Handle_Store_Double (state
, instr
);
2494 if (BITS (4, 11) == 9)
2501 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2503 INTERNALABORT (temp
);
2504 (void) ARMul_LoadByte (state
, temp
);
2505 (void) ARMul_LoadByte (state
, temp
);
2509 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
2510 if (state
->abortSig
|| state
->Aborted
)
2513 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2517 DEST
= GETSPSR (state
->Bank
);
2520 else if (state
->is_v6
2521 && handle_v6_insn (state
, instr
))
2529 case 0x15: /* CMPP reg. */
2531 if ((BITS (4, 7) & 0x9) == 0x9)
2532 /* LDR immediate offset, no write-back, down, pre indexed. */
2534 /* Continue with remaining instruction decode. */
2540 state
->Cpsr
= GETSPSR (state
->Bank
);
2541 ARMul_CPSRAltered (state
);
2554 ARMul_NegZero (state
, dest
);
2555 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2557 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2558 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2568 case 0x16: /* CMN reg and MSR reg to SPSR */
2571 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
2573 /* ElSegundo SMULxy insn. */
2574 ARMword op1
= state
->Reg
[BITS (0, 3)];
2575 ARMword op2
= state
->Reg
[BITS (8, 11)];
2588 state
->Reg
[BITS (16, 19)] = op1
* op2
;
2592 if (BITS (4, 11) == 5)
2594 /* ElSegundo QDSUB insn. */
2595 ARMword op1
= state
->Reg
[BITS (0, 3)];
2596 ARMword op2
= state
->Reg
[BITS (16, 19)];
2597 ARMword op2d
= op2
+ op2
;
2600 if (AddOverflow (op2
, op2
, op2d
))
2603 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2606 result
= op1
- op2d
;
2607 if (SubOverflow (op1
, op2d
, result
))
2610 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2613 state
->Reg
[BITS (12, 15)] = result
;
2620 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
2622 /* ARM5 CLZ insn. */
2623 ARMword op1
= state
->Reg
[BITS (0, 3)];
2627 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
2630 state
->Reg
[BITS (12, 15)] = result
;
2635 if (BITS (4, 7) == 0xB)
2637 /* STRH immediate offset, write-back, down, pre indexed. */
2641 if (BITS (4, 7) == 0xD)
2643 Handle_Load_Double (state
, instr
);
2646 if (BITS (4, 7) == 0xF)
2648 Handle_Store_Double (state
, instr
);
2656 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
2662 && handle_v6_insn (state
, instr
))
2669 case 0x17: /* CMNP reg */
2671 if ((BITS (4, 7) & 0x9) == 0x9)
2672 /* LDR immediate offset, write-back, down, pre indexed. */
2674 /* Continue with remaining instruction decoding. */
2679 state
->Cpsr
= GETSPSR (state
->Bank
);
2680 ARMul_CPSRAltered (state
);
2694 ASSIGNZ (dest
== 0);
2695 if ((lhs
| rhs
) >> 30)
2697 /* Possible C,V,N to set. */
2698 ASSIGNN (NEG (dest
));
2699 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2700 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2711 case 0x18: /* ORR reg */
2713 if (BITS (4, 11) == 0xB)
2715 /* STRH register offset, no write-back, up, pre indexed. */
2719 if (BITS (4, 7) == 0xD)
2721 Handle_Load_Double (state
, instr
);
2724 if (BITS (4, 7) == 0xF)
2726 Handle_Store_Double (state
, instr
);
2735 case 0x19: /* ORRS reg */
2737 if ((BITS (4, 11) & 0xF9) == 0x9)
2738 /* LDR register offset, no write-back, up, pre indexed. */
2740 /* Continue with remaining instruction decoding. */
2747 case 0x1a: /* MOV reg */
2749 if (BITS (4, 11) == 0xB)
2751 /* STRH register offset, write-back, up, pre indexed. */
2755 if (BITS (4, 7) == 0xD)
2757 Handle_Load_Double (state
, instr
);
2760 if (BITS (4, 7) == 0xF)
2762 Handle_Store_Double (state
, instr
);
2770 case 0x1b: /* MOVS reg */
2772 if ((BITS (4, 11) & 0xF9) == 0x9)
2773 /* LDR register offset, write-back, up, pre indexed. */
2775 /* Continue with remaining instruction decoding. */
2781 case 0x1c: /* BIC reg */
2783 if (BITS (4, 7) == 0xB)
2785 /* STRH immediate offset, no write-back, up, pre indexed. */
2789 if (BITS (4, 7) == 0xD)
2791 Handle_Load_Double (state
, instr
);
2794 else if (BITS (4, 7) == 0xF)
2796 Handle_Store_Double (state
, instr
);
2805 case 0x1d: /* BICS reg */
2807 if ((BITS (4, 7) & 0x9) == 0x9)
2808 /* LDR immediate offset, no write-back, up, pre indexed. */
2810 /* Continue with instruction decoding. */
2817 case 0x1e: /* MVN reg */
2819 if (BITS (4, 7) == 0xB)
2821 /* STRH immediate offset, write-back, up, pre indexed. */
2825 if (BITS (4, 7) == 0xD)
2827 Handle_Load_Double (state
, instr
);
2830 if (BITS (4, 7) == 0xF)
2832 Handle_Store_Double (state
, instr
);
2840 case 0x1f: /* MVNS reg */
2842 if ((BITS (4, 7) & 0x9) == 0x9)
2843 /* LDR immediate offset, write-back, up, pre indexed. */
2845 /* Continue instruction decoding. */
2852 /* Data Processing Immediate RHS Instructions. */
2854 case 0x20: /* AND immed */
2855 dest
= LHS
& DPImmRHS
;
2859 case 0x21: /* ANDS immed */
2865 case 0x22: /* EOR immed */
2866 dest
= LHS
^ DPImmRHS
;
2870 case 0x23: /* EORS immed */
2876 case 0x24: /* SUB immed */
2877 dest
= LHS
- DPImmRHS
;
2881 case 0x25: /* SUBS immed */
2886 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2888 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2889 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2899 case 0x26: /* RSB immed */
2900 dest
= DPImmRHS
- LHS
;
2904 case 0x27: /* RSBS immed */
2909 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2911 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2912 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2922 case 0x28: /* ADD immed */
2923 dest
= LHS
+ DPImmRHS
;
2927 case 0x29: /* ADDS immed */
2931 ASSIGNZ (dest
== 0);
2933 if ((lhs
| rhs
) >> 30)
2935 /* Possible C,V,N to set. */
2936 ASSIGNN (NEG (dest
));
2937 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2938 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2949 case 0x2a: /* ADC immed */
2950 dest
= LHS
+ DPImmRHS
+ CFLAG
;
2954 case 0x2b: /* ADCS immed */
2957 dest
= lhs
+ rhs
+ CFLAG
;
2958 ASSIGNZ (dest
== 0);
2959 if ((lhs
| rhs
) >> 30)
2961 /* Possible C,V,N to set. */
2962 ASSIGNN (NEG (dest
));
2963 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2964 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2975 case 0x2c: /* SBC immed */
2976 dest
= LHS
- DPImmRHS
- !CFLAG
;
2980 case 0x2d: /* SBCS immed */
2983 dest
= lhs
- rhs
- !CFLAG
;
2984 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2986 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2987 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2997 case 0x2e: /* RSC immed */
2998 dest
= DPImmRHS
- LHS
- !CFLAG
;
3002 case 0x2f: /* RSCS immed */
3005 dest
= rhs
- lhs
- !CFLAG
;
3006 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
3008 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
3009 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
3019 case 0x30: /* MOVW immed */
3022 && handle_v6_insn (state
, instr
))
3025 dest
= BITS (0, 11);
3026 dest
|= (BITS (16, 19) << 12);
3030 case 0x31: /* TSTP immed */
3035 state
->Cpsr
= GETSPSR (state
->Bank
);
3036 ARMul_CPSRAltered (state
);
3038 temp
= LHS
& DPImmRHS
;
3047 ARMul_NegZero (state
, dest
);
3051 case 0x32: /* TEQ immed and MSR immed to CPSR */
3053 /* MSR immed to CPSR. */
3054 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
3056 else if (state
->is_v6
3057 && handle_v6_insn (state
, instr
))
3064 case 0x33: /* TEQP immed */
3069 state
->Cpsr
= GETSPSR (state
->Bank
);
3070 ARMul_CPSRAltered (state
);
3072 temp
= LHS
^ DPImmRHS
;
3078 DPSImmRHS
; /* TEQ immed */
3080 ARMul_NegZero (state
, dest
);
3084 case 0x34: /* MOVT immed */
3087 && handle_v6_insn (state
, instr
))
3091 dest
= BITS (0, 11);
3092 dest
|= (BITS (16, 19) << 12);
3093 DEST
|= (dest
<< 16);
3096 case 0x35: /* CMPP immed */
3101 state
->Cpsr
= GETSPSR (state
->Bank
);
3102 ARMul_CPSRAltered (state
);
3104 temp
= LHS
- DPImmRHS
;
3115 ARMul_NegZero (state
, dest
);
3117 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
3119 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
3120 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
3130 case 0x36: /* CMN immed and MSR immed to SPSR */
3132 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
3134 else if (state
->is_v6
3135 && handle_v6_insn (state
, instr
))
3142 case 0x37: /* CMNP immed. */
3147 state
->Cpsr
= GETSPSR (state
->Bank
);
3148 ARMul_CPSRAltered (state
);
3150 temp
= LHS
+ DPImmRHS
;
3161 ASSIGNZ (dest
== 0);
3162 if ((lhs
| rhs
) >> 30)
3164 /* Possible C,V,N to set. */
3165 ASSIGNN (NEG (dest
));
3166 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
3167 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3178 case 0x38: /* ORR immed. */
3179 dest
= LHS
| DPImmRHS
;
3183 case 0x39: /* ORRS immed. */
3189 case 0x3a: /* MOV immed. */
3194 case 0x3b: /* MOVS immed. */
3199 case 0x3c: /* BIC immed. */
3200 dest
= LHS
& ~DPImmRHS
;
3204 case 0x3d: /* BICS immed. */
3210 case 0x3e: /* MVN immed. */
3215 case 0x3f: /* MVNS immed. */
3221 /* Single Data Transfer Immediate RHS Instructions. */
3223 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
3225 if (StoreWord (state
, instr
, lhs
))
3226 LSBase
= lhs
- LSImmRHS
;
3229 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
3231 if (LoadWord (state
, instr
, lhs
))
3232 LSBase
= lhs
- LSImmRHS
;
3235 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
3236 UNDEF_LSRBaseEQDestWb
;
3239 temp
= lhs
- LSImmRHS
;
3240 state
->NtransSig
= LOW
;
3241 if (StoreWord (state
, instr
, lhs
))
3243 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3246 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
3247 UNDEF_LSRBaseEQDestWb
;
3250 state
->NtransSig
= LOW
;
3251 if (LoadWord (state
, instr
, lhs
))
3252 LSBase
= lhs
- LSImmRHS
;
3253 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3256 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
3258 if (StoreByte (state
, instr
, lhs
))
3259 LSBase
= lhs
- LSImmRHS
;
3262 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
3264 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3265 LSBase
= lhs
- LSImmRHS
;
3268 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
3269 UNDEF_LSRBaseEQDestWb
;
3272 state
->NtransSig
= LOW
;
3273 if (StoreByte (state
, instr
, lhs
))
3274 LSBase
= lhs
- LSImmRHS
;
3275 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3278 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
3279 UNDEF_LSRBaseEQDestWb
;
3282 state
->NtransSig
= LOW
;
3283 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3284 LSBase
= lhs
- LSImmRHS
;
3285 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3288 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
3290 if (StoreWord (state
, instr
, lhs
))
3291 LSBase
= lhs
+ LSImmRHS
;
3294 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
3296 if (LoadWord (state
, instr
, lhs
))
3297 LSBase
= lhs
+ LSImmRHS
;
3300 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
3301 UNDEF_LSRBaseEQDestWb
;
3304 state
->NtransSig
= LOW
;
3305 if (StoreWord (state
, instr
, lhs
))
3306 LSBase
= lhs
+ LSImmRHS
;
3307 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3310 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
3311 UNDEF_LSRBaseEQDestWb
;
3314 state
->NtransSig
= LOW
;
3315 if (LoadWord (state
, instr
, lhs
))
3316 LSBase
= lhs
+ LSImmRHS
;
3317 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3320 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
3322 if (StoreByte (state
, instr
, lhs
))
3323 LSBase
= lhs
+ LSImmRHS
;
3326 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
3328 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3329 LSBase
= lhs
+ LSImmRHS
;
3332 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
3333 UNDEF_LSRBaseEQDestWb
;
3336 state
->NtransSig
= LOW
;
3337 if (StoreByte (state
, instr
, lhs
))
3338 LSBase
= lhs
+ LSImmRHS
;
3339 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3342 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
3343 UNDEF_LSRBaseEQDestWb
;
3346 state
->NtransSig
= LOW
;
3347 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3348 LSBase
= lhs
+ LSImmRHS
;
3349 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3353 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
3354 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
3357 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
3358 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
3361 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
3362 UNDEF_LSRBaseEQDestWb
;
3364 temp
= LHS
- LSImmRHS
;
3365 if (StoreWord (state
, instr
, temp
))
3369 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
3370 UNDEF_LSRBaseEQDestWb
;
3372 temp
= LHS
- LSImmRHS
;
3373 if (LoadWord (state
, instr
, temp
))
3377 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
3378 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
3381 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
3382 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
3385 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
3386 UNDEF_LSRBaseEQDestWb
;
3388 temp
= LHS
- LSImmRHS
;
3389 if (StoreByte (state
, instr
, temp
))
3393 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
3394 UNDEF_LSRBaseEQDestWb
;
3396 temp
= LHS
- LSImmRHS
;
3397 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3401 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
3402 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
3405 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
3406 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
3409 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
3410 UNDEF_LSRBaseEQDestWb
;
3412 temp
= LHS
+ LSImmRHS
;
3413 if (StoreWord (state
, instr
, temp
))
3417 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
3418 UNDEF_LSRBaseEQDestWb
;
3420 temp
= LHS
+ LSImmRHS
;
3421 if (LoadWord (state
, instr
, temp
))
3425 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
3426 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
3429 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
3430 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
3433 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
3434 UNDEF_LSRBaseEQDestWb
;
3436 temp
= LHS
+ LSImmRHS
;
3437 if (StoreByte (state
, instr
, temp
))
3441 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
3442 UNDEF_LSRBaseEQDestWb
;
3444 temp
= LHS
+ LSImmRHS
;
3445 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3450 /* Single Data Transfer Register RHS Instructions. */
3452 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
3457 && handle_v6_insn (state
, instr
))
3460 ARMul_UndefInstr (state
, instr
);
3463 UNDEF_LSRBaseEQOffWb
;
3464 UNDEF_LSRBaseEQDestWb
;
3468 if (StoreWord (state
, instr
, lhs
))
3469 LSBase
= lhs
- LSRegRHS
;
3472 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
3477 && handle_v6_insn (state
, instr
))
3480 ARMul_UndefInstr (state
, instr
);
3483 UNDEF_LSRBaseEQOffWb
;
3484 UNDEF_LSRBaseEQDestWb
;
3488 temp
= lhs
- LSRegRHS
;
3489 if (LoadWord (state
, instr
, lhs
))
3493 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
3498 && handle_v6_insn (state
, instr
))
3501 ARMul_UndefInstr (state
, instr
);
3504 UNDEF_LSRBaseEQOffWb
;
3505 UNDEF_LSRBaseEQDestWb
;
3509 state
->NtransSig
= LOW
;
3510 if (StoreWord (state
, instr
, lhs
))
3511 LSBase
= lhs
- LSRegRHS
;
3512 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3515 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
3520 && handle_v6_insn (state
, instr
))
3523 ARMul_UndefInstr (state
, instr
);
3526 UNDEF_LSRBaseEQOffWb
;
3527 UNDEF_LSRBaseEQDestWb
;
3531 temp
= lhs
- LSRegRHS
;
3532 state
->NtransSig
= LOW
;
3533 if (LoadWord (state
, instr
, lhs
))
3535 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3538 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
3543 && handle_v6_insn (state
, instr
))
3546 ARMul_UndefInstr (state
, instr
);
3549 UNDEF_LSRBaseEQOffWb
;
3550 UNDEF_LSRBaseEQDestWb
;
3554 if (StoreByte (state
, instr
, lhs
))
3555 LSBase
= lhs
- LSRegRHS
;
3558 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
3563 && handle_v6_insn (state
, instr
))
3566 ARMul_UndefInstr (state
, instr
);
3569 UNDEF_LSRBaseEQOffWb
;
3570 UNDEF_LSRBaseEQDestWb
;
3574 temp
= lhs
- LSRegRHS
;
3575 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3579 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
3584 && handle_v6_insn (state
, instr
))
3587 ARMul_UndefInstr (state
, instr
);
3590 UNDEF_LSRBaseEQOffWb
;
3591 UNDEF_LSRBaseEQDestWb
;
3595 state
->NtransSig
= LOW
;
3596 if (StoreByte (state
, instr
, lhs
))
3597 LSBase
= lhs
- LSRegRHS
;
3598 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3601 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
3606 && handle_v6_insn (state
, instr
))
3609 ARMul_UndefInstr (state
, instr
);
3612 UNDEF_LSRBaseEQOffWb
;
3613 UNDEF_LSRBaseEQDestWb
;
3617 temp
= lhs
- LSRegRHS
;
3618 state
->NtransSig
= LOW
;
3619 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3621 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3624 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
3629 && handle_v6_insn (state
, instr
))
3632 ARMul_UndefInstr (state
, instr
);
3635 UNDEF_LSRBaseEQOffWb
;
3636 UNDEF_LSRBaseEQDestWb
;
3640 if (StoreWord (state
, instr
, lhs
))
3641 LSBase
= lhs
+ LSRegRHS
;
3644 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
3649 && handle_v6_insn (state
, instr
))
3652 ARMul_UndefInstr (state
, instr
);
3655 UNDEF_LSRBaseEQOffWb
;
3656 UNDEF_LSRBaseEQDestWb
;
3660 temp
= lhs
+ LSRegRHS
;
3661 if (LoadWord (state
, instr
, lhs
))
3665 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
3670 && handle_v6_insn (state
, instr
))
3673 ARMul_UndefInstr (state
, instr
);
3676 UNDEF_LSRBaseEQOffWb
;
3677 UNDEF_LSRBaseEQDestWb
;
3681 state
->NtransSig
= LOW
;
3682 if (StoreWord (state
, instr
, lhs
))
3683 LSBase
= lhs
+ LSRegRHS
;
3684 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3687 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
3692 && handle_v6_insn (state
, instr
))
3695 ARMul_UndefInstr (state
, instr
);
3698 UNDEF_LSRBaseEQOffWb
;
3699 UNDEF_LSRBaseEQDestWb
;
3703 temp
= lhs
+ LSRegRHS
;
3704 state
->NtransSig
= LOW
;
3705 if (LoadWord (state
, instr
, lhs
))
3707 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3710 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
3715 && handle_v6_insn (state
, instr
))
3718 ARMul_UndefInstr (state
, instr
);
3721 UNDEF_LSRBaseEQOffWb
;
3722 UNDEF_LSRBaseEQDestWb
;
3726 if (StoreByte (state
, instr
, lhs
))
3727 LSBase
= lhs
+ LSRegRHS
;
3730 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
3735 && handle_v6_insn (state
, instr
))
3738 ARMul_UndefInstr (state
, instr
);
3741 UNDEF_LSRBaseEQOffWb
;
3742 UNDEF_LSRBaseEQDestWb
;
3746 temp
= lhs
+ LSRegRHS
;
3747 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3751 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3756 && handle_v6_insn (state
, instr
))
3759 ARMul_UndefInstr (state
, instr
);
3762 UNDEF_LSRBaseEQOffWb
;
3763 UNDEF_LSRBaseEQDestWb
;
3767 state
->NtransSig
= LOW
;
3768 if (StoreByte (state
, instr
, lhs
))
3769 LSBase
= lhs
+ LSRegRHS
;
3770 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3773 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3778 && handle_v6_insn (state
, instr
))
3781 ARMul_UndefInstr (state
, instr
);
3784 UNDEF_LSRBaseEQOffWb
;
3785 UNDEF_LSRBaseEQDestWb
;
3789 temp
= lhs
+ LSRegRHS
;
3790 state
->NtransSig
= LOW
;
3791 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3793 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3797 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3802 && handle_v6_insn (state
, instr
))
3805 ARMul_UndefInstr (state
, instr
);
3808 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
3811 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3816 && handle_v6_insn (state
, instr
))
3819 ARMul_UndefInstr (state
, instr
);
3822 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
3825 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3830 && handle_v6_insn (state
, instr
))
3833 ARMul_UndefInstr (state
, instr
);
3836 UNDEF_LSRBaseEQOffWb
;
3837 UNDEF_LSRBaseEQDestWb
;
3840 temp
= LHS
- LSRegRHS
;
3841 if (StoreWord (state
, instr
, temp
))
3845 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3850 && handle_v6_insn (state
, instr
))
3853 ARMul_UndefInstr (state
, instr
);
3856 UNDEF_LSRBaseEQOffWb
;
3857 UNDEF_LSRBaseEQDestWb
;
3860 temp
= LHS
- LSRegRHS
;
3861 if (LoadWord (state
, instr
, temp
))
3865 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3870 && handle_v6_insn (state
, instr
))
3873 ARMul_UndefInstr (state
, instr
);
3876 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
3879 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3884 && handle_v6_insn (state
, instr
))
3887 ARMul_UndefInstr (state
, instr
);
3890 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
3893 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3898 && handle_v6_insn (state
, instr
))
3901 ARMul_UndefInstr (state
, instr
);
3904 UNDEF_LSRBaseEQOffWb
;
3905 UNDEF_LSRBaseEQDestWb
;
3908 temp
= LHS
- LSRegRHS
;
3909 if (StoreByte (state
, instr
, temp
))
3913 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3918 && handle_v6_insn (state
, instr
))
3921 ARMul_UndefInstr (state
, instr
);
3924 UNDEF_LSRBaseEQOffWb
;
3925 UNDEF_LSRBaseEQDestWb
;
3928 temp
= LHS
- LSRegRHS
;
3929 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3933 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3938 && handle_v6_insn (state
, instr
))
3941 ARMul_UndefInstr (state
, instr
);
3944 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
3947 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
3952 && handle_v6_insn (state
, instr
))
3955 ARMul_UndefInstr (state
, instr
);
3958 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
3961 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
3966 && handle_v6_insn (state
, instr
))
3969 ARMul_UndefInstr (state
, instr
);
3972 UNDEF_LSRBaseEQOffWb
;
3973 UNDEF_LSRBaseEQDestWb
;
3976 temp
= LHS
+ LSRegRHS
;
3977 if (StoreWord (state
, instr
, temp
))
3981 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
3986 && handle_v6_insn (state
, instr
))
3989 ARMul_UndefInstr (state
, instr
);
3992 UNDEF_LSRBaseEQOffWb
;
3993 UNDEF_LSRBaseEQDestWb
;
3996 temp
= LHS
+ LSRegRHS
;
3997 if (LoadWord (state
, instr
, temp
))
4001 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
4006 && handle_v6_insn (state
, instr
))
4009 ARMul_UndefInstr (state
, instr
);
4012 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
4015 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
4020 && handle_v6_insn (state
, instr
))
4023 ARMul_UndefInstr (state
, instr
);
4026 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
4029 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
4034 && handle_v6_insn (state
, instr
))
4037 ARMul_UndefInstr (state
, instr
);
4040 UNDEF_LSRBaseEQOffWb
;
4041 UNDEF_LSRBaseEQDestWb
;
4044 temp
= LHS
+ LSRegRHS
;
4045 if (StoreByte (state
, instr
, temp
))
4049 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
4052 /* Check for the special breakpoint opcode.
4053 This value should correspond to the value defined
4054 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
4055 if (BITS (0, 19) == 0xfdefe)
4057 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
4058 ARMul_Abort (state
, ARMul_SWIV
);
4061 else if (state
->is_v6
4062 && handle_v6_insn (state
, instr
))
4066 ARMul_UndefInstr (state
, instr
);
4069 UNDEF_LSRBaseEQOffWb
;
4070 UNDEF_LSRBaseEQDestWb
;
4073 temp
= LHS
+ LSRegRHS
;
4074 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
4079 /* Multiple Data Transfer Instructions. */
4081 case 0x80: /* Store, No WriteBack, Post Dec. */
4082 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4085 case 0x81: /* Load, No WriteBack, Post Dec. */
4086 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4089 case 0x82: /* Store, WriteBack, Post Dec. */
4090 temp
= LSBase
- LSMNumRegs
;
4091 STOREMULT (instr
, temp
+ 4L, temp
);
4094 case 0x83: /* Load, WriteBack, Post Dec. */
4095 temp
= LSBase
- LSMNumRegs
;
4096 LOADMULT (instr
, temp
+ 4L, temp
);
4099 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
4100 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4103 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
4104 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4107 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
4108 temp
= LSBase
- LSMNumRegs
;
4109 STORESMULT (instr
, temp
+ 4L, temp
);
4112 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
4113 temp
= LSBase
- LSMNumRegs
;
4114 LOADSMULT (instr
, temp
+ 4L, temp
);
4117 case 0x88: /* Store, No WriteBack, Post Inc. */
4118 STOREMULT (instr
, LSBase
, 0L);
4121 case 0x89: /* Load, No WriteBack, Post Inc. */
4122 LOADMULT (instr
, LSBase
, 0L);
4125 case 0x8a: /* Store, WriteBack, Post Inc. */
4127 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
4130 case 0x8b: /* Load, WriteBack, Post Inc. */
4132 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
4135 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
4136 STORESMULT (instr
, LSBase
, 0L);
4139 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
4140 LOADSMULT (instr
, LSBase
, 0L);
4143 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
4145 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
4148 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
4150 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
4153 case 0x90: /* Store, No WriteBack, Pre Dec. */
4154 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4157 case 0x91: /* Load, No WriteBack, Pre Dec. */
4158 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4161 case 0x92: /* Store, WriteBack, Pre Dec. */
4162 temp
= LSBase
- LSMNumRegs
;
4163 STOREMULT (instr
, temp
, temp
);
4166 case 0x93: /* Load, WriteBack, Pre Dec. */
4167 temp
= LSBase
- LSMNumRegs
;
4168 LOADMULT (instr
, temp
, temp
);
4171 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
4172 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4175 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
4176 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4179 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
4180 temp
= LSBase
- LSMNumRegs
;
4181 STORESMULT (instr
, temp
, temp
);
4184 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
4185 temp
= LSBase
- LSMNumRegs
;
4186 LOADSMULT (instr
, temp
, temp
);
4189 case 0x98: /* Store, No WriteBack, Pre Inc. */
4190 STOREMULT (instr
, LSBase
+ 4L, 0L);
4193 case 0x99: /* Load, No WriteBack, Pre Inc. */
4194 LOADMULT (instr
, LSBase
+ 4L, 0L);
4197 case 0x9a: /* Store, WriteBack, Pre Inc. */
4199 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4202 case 0x9b: /* Load, WriteBack, Pre Inc. */
4204 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4207 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
4208 STORESMULT (instr
, LSBase
+ 4L, 0L);
4211 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
4212 LOADSMULT (instr
, LSBase
+ 4L, 0L);
4215 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
4217 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4220 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
4222 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4226 /* Branch forward. */
4235 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4240 /* Branch backward. */
4249 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4253 /* Branch and Link forward. */
4262 /* Put PC into Link. */
4264 state
->Reg
[14] = pc
+ 4;
4266 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4268 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4271 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4274 /* Branch and Link backward. */
4283 /* Put PC into Link. */
4285 state
->Reg
[14] = pc
+ 4;
4287 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4289 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4292 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4295 /* Co-Processor Data Transfers. */
4299 if (CPNum
== 10 || CPNum
== 11)
4300 handle_VFP_move (state
, instr
);
4301 /* Reading from R15 is UNPREDICTABLE. */
4302 else if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
4303 ARMul_UndefInstr (state
, instr
);
4304 /* Is access to coprocessor 0 allowed ? */
4305 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4306 ARMul_UndefInstr (state
, instr
);
4307 /* Special treatment for XScale coprocessors. */
4308 else if (state
->is_XScale
)
4310 /* Only opcode 0 is supported. */
4311 if (BITS (4, 7) != 0x00)
4312 ARMul_UndefInstr (state
, instr
);
4313 /* Only coporcessor 0 is supported. */
4314 else if (CPNum
!= 0x00)
4315 ARMul_UndefInstr (state
, instr
);
4316 /* Only accumulator 0 is supported. */
4317 else if (BITS (0, 3) != 0x00)
4318 ARMul_UndefInstr (state
, instr
);
4321 /* XScale MAR insn. Move two registers into accumulator. */
4322 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
4323 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
4327 /* FIXME: Not sure what to do for other v5 processors. */
4328 ARMul_UndefInstr (state
, instr
);
4333 case 0xc0: /* Store , No WriteBack , Post Dec. */
4334 ARMul_STC (state
, instr
, LHS
);
4340 if (CPNum
== 10 || CPNum
== 11)
4341 handle_VFP_move (state
, instr
);
4342 /* Writes to R15 are UNPREDICATABLE. */
4343 else if (DESTReg
== 15 || LHSReg
== 15)
4344 ARMul_UndefInstr (state
, instr
);
4345 /* Is access to the coprocessor allowed ? */
4346 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4347 ARMul_UndefInstr (state
, instr
);
4348 /* Special handling for XScale coprcoessors. */
4349 else if (state
->is_XScale
)
4351 /* Only opcode 0 is supported. */
4352 if (BITS (4, 7) != 0x00)
4353 ARMul_UndefInstr (state
, instr
);
4354 /* Only coprocessor 0 is supported. */
4355 else if (CPNum
!= 0x00)
4356 ARMul_UndefInstr (state
, instr
);
4357 /* Only accumulator 0 is supported. */
4358 else if (BITS (0, 3) != 0x00)
4359 ARMul_UndefInstr (state
, instr
);
4362 /* XScale MRA insn. Move accumulator into two registers. */
4363 ARMword t1
= (state
->Accumulator
>> 32) & 255;
4368 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
4369 state
->Reg
[BITS (16, 19)] = t1
;
4374 /* FIXME: Not sure what to do for other v5 processors. */
4375 ARMul_UndefInstr (state
, instr
);
4380 case 0xc1: /* Load , No WriteBack , Post Dec. */
4381 ARMul_LDC (state
, instr
, LHS
);
4385 case 0xc6: /* Store , WriteBack , Post Dec. */
4387 state
->Base
= lhs
- LSCOff
;
4388 ARMul_STC (state
, instr
, lhs
);
4392 case 0xc7: /* Load , WriteBack , Post Dec. */
4394 state
->Base
= lhs
- LSCOff
;
4395 ARMul_LDC (state
, instr
, lhs
);
4399 case 0xcc: /* Store , No WriteBack , Post Inc. */
4400 ARMul_STC (state
, instr
, LHS
);
4404 case 0xcd: /* Load , No WriteBack , Post Inc. */
4405 ARMul_LDC (state
, instr
, LHS
);
4409 case 0xce: /* Store , WriteBack , Post Inc. */
4411 state
->Base
= lhs
+ LSCOff
;
4412 ARMul_STC (state
, instr
, LHS
);
4416 case 0xcf: /* Load , WriteBack , Post Inc. */
4418 state
->Base
= lhs
+ LSCOff
;
4419 ARMul_LDC (state
, instr
, LHS
);
4423 case 0xd4: /* Store , No WriteBack , Pre Dec. */
4424 ARMul_STC (state
, instr
, LHS
- LSCOff
);
4428 case 0xd5: /* Load , No WriteBack , Pre Dec. */
4429 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
4433 case 0xd6: /* Store , WriteBack , Pre Dec. */
4436 ARMul_STC (state
, instr
, lhs
);
4440 case 0xd7: /* Load , WriteBack , Pre Dec. */
4443 ARMul_LDC (state
, instr
, lhs
);
4447 case 0xdc: /* Store , No WriteBack , Pre Inc. */
4448 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
4452 case 0xdd: /* Load , No WriteBack , Pre Inc. */
4453 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
4457 case 0xde: /* Store , WriteBack , Pre Inc. */
4460 ARMul_STC (state
, instr
, lhs
);
4464 case 0xdf: /* Load , WriteBack , Pre Inc. */
4467 ARMul_LDC (state
, instr
, lhs
);
4471 /* Co-Processor Register Transfers (MCR) and Data Ops. */
4474 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4476 ARMul_UndefInstr (state
, instr
);
4479 if (state
->is_XScale
)
4480 switch (BITS (18, 19))
4483 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4485 /* XScale MIA instruction. Signed multiplication of
4486 two 32 bit values and addition to 40 bit accumulator. */
4487 ARMsdword Rm
= state
->Reg
[MULLHSReg
];
4488 ARMsdword Rs
= state
->Reg
[MULACCReg
];
4494 state
->Accumulator
+= Rm
* Rs
;
4500 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4502 /* XScale MIAPH instruction. */
4503 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
4504 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
4505 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
4506 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
4521 state
->Accumulator
+= t5
;
4526 state
->Accumulator
+= t5
;
4532 if (BITS (4, 11) == 1)
4534 /* XScale MIAxy instruction. */
4540 t1
= state
->Reg
[MULLHSReg
] >> 16;
4542 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
4545 t2
= state
->Reg
[MULACCReg
] >> 16;
4547 t2
= state
->Reg
[MULACCReg
] & 0xffff;
4557 state
->Accumulator
+= t5
;
4576 if (CPNum
== 10 || CPNum
== 11)
4577 handle_VFP_move (state
, instr
);
4579 else if (DESTReg
== 15)
4583 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
4585 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
4586 ((state
->Reg
[15] + isize
) & R15PCBITS
));
4590 ARMul_MCR (state
, instr
, DEST
);
4594 ARMul_CDP (state
, instr
);
4598 /* Co-Processor Register Transfers (MRC) and Data Ops. */
4609 if (CPNum
== 10 || CPNum
== 11)
4611 switch (BITS (20, 27))
4614 if (BITS (16, 19) == 0x1
4615 && BITS (0, 11) == 0xA10)
4620 ARMul_SetCPSR (state
, (state
->FPSCR
& 0xF0000000)
4621 | (ARMul_GetCPSR (state
) & 0x0FFFFFFF));
4624 fprintf (stderr
, " VFP: VMRS: set flags to %c%c%c%c\n",
4625 ARMul_GetCPSR (state
) & NBIT
? 'N' : '-',
4626 ARMul_GetCPSR (state
) & ZBIT
? 'Z' : '-',
4627 ARMul_GetCPSR (state
) & CBIT
? 'C' : '-',
4628 ARMul_GetCPSR (state
) & VBIT
? 'V' : '-');
4632 state
->Reg
[DESTReg
] = state
->FPSCR
;
4635 fprintf (stderr
, " VFP: VMRS: r%d = %x\n", DESTReg
, state
->Reg
[DESTReg
]);
4639 fprintf (stderr
, "SIM: VFP: Unimplemented: Compare op\n");
4644 /* VMOV reg <-> single precision. */
4645 if (BITS (0,6) != 0x10 || BITS (8,11) != 0xA)
4646 fprintf (stderr
, "SIM: VFP: Unimplemented: move op\n");
4648 state
->Reg
[BITS (12, 15)] = VFP_uword (BITS (16, 19) << 1 | BIT (7));
4650 VFP_uword (BITS (16, 19) << 1 | BIT (7)) = state
->Reg
[BITS (12, 15)];
4654 fprintf (stderr
, "SIM: VFP: Unimplemented: CDP op\n");
4661 temp
= ARMul_MRC (state
, instr
);
4664 ASSIGNN ((temp
& NBIT
) != 0);
4665 ASSIGNZ ((temp
& ZBIT
) != 0);
4666 ASSIGNC ((temp
& CBIT
) != 0);
4667 ASSIGNV ((temp
& VBIT
) != 0);
4675 ARMul_CDP (state
, instr
);
4679 /* SWI instruction. */
4696 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
4698 /* A prefetch abort. */
4699 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
4700 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
4704 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
4705 ARMul_Abort (state
, ARMul_SWIV
);
4715 if (state
->Emulate
== ONCE
)
4716 state
->Emulate
= STOP
;
4717 /* If we have changed mode, allow the PC to advance before stopping. */
4718 else if (state
->Emulate
== CHANGEMODE
)
4720 else if (state
->Emulate
!= RUN
)
4723 while (!stop_simulator
);
4725 state
->decoded
= decoded
;
4726 state
->loaded
= loaded
;
4732 /* This routine evaluates most Data Processing register RHS's with the S
4733 bit clear. It is intended to be called from the macro DPRegRHS, which
4734 filters the common case of an unshifted register with in line code. */
4737 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
4739 ARMword shamt
, base
;
4744 /* Shift amount in a register. */
4749 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4752 base
= state
->Reg
[base
];
4753 ARMul_Icycles (state
, 1, 0L);
4754 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4755 switch ((int) BITS (5, 6))
4760 else if (shamt
>= 32)
4763 return (base
<< shamt
);
4767 else if (shamt
>= 32)
4770 return (base
>> shamt
);
4774 else if (shamt
>= 32)
4775 return ((ARMword
) ((ARMsword
) base
>> 31L));
4777 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4783 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4788 /* Shift amount is a constant. */
4791 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4794 base
= state
->Reg
[base
];
4795 shamt
= BITS (7, 11);
4796 switch ((int) BITS (5, 6))
4799 return (base
<< shamt
);
4804 return (base
>> shamt
);
4807 return ((ARMword
) ((ARMsword
) base
>> 31L));
4809 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4813 return ((base
>> 1) | (CFLAG
<< 31));
4815 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4822 /* This routine evaluates most Logical Data Processing register RHS's
4823 with the S bit set. It is intended to be called from the macro
4824 DPSRegRHS, which filters the common case of an unshifted register
4825 with in line code. */
4828 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
4830 ARMword shamt
, base
;
4835 /* Shift amount in a register. */
4840 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4843 base
= state
->Reg
[base
];
4844 ARMul_Icycles (state
, 1, 0L);
4845 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4846 switch ((int) BITS (5, 6))
4851 else if (shamt
== 32)
4856 else if (shamt
> 32)
4863 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4864 return (base
<< shamt
);
4869 else if (shamt
== 32)
4871 ASSIGNC (base
>> 31);
4874 else if (shamt
> 32)
4881 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4882 return (base
>> shamt
);
4887 else if (shamt
>= 32)
4889 ASSIGNC (base
>> 31L);
4890 return ((ARMword
) ((ARMsword
) base
>> 31L));
4894 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4895 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4903 ASSIGNC (base
>> 31);
4908 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4909 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4915 /* Shift amount is a constant. */
4918 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4921 base
= state
->Reg
[base
];
4922 shamt
= BITS (7, 11);
4924 switch ((int) BITS (5, 6))
4927 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4928 return (base
<< shamt
);
4932 ASSIGNC (base
>> 31);
4937 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4938 return (base
>> shamt
);
4943 ASSIGNC (base
>> 31L);
4944 return ((ARMword
) ((ARMsword
) base
>> 31L));
4948 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4949 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4957 return ((base
>> 1) | (shamt
<< 31));
4961 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4962 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4970 /* This routine handles writes to register 15 when the S bit is not set. */
4973 WriteR15 (ARMul_State
* state
, ARMword src
)
4975 /* The ARM documentation states that the two least significant bits
4976 are discarded when setting PC, except in the cases handled by
4977 WriteR15Branch() below. It's probably an oversight: in THUMB
4978 mode, the second least significant bit should probably not be
4988 state
->Reg
[15] = src
& PCBITS
;
4990 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
4991 ARMul_R15Altered (state
);
4996 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4999 /* This routine handles writes to register 15 when the S bit is set. */
5002 WriteSR15 (ARMul_State
* state
, ARMword src
)
5005 if (state
->Bank
> 0)
5007 state
->Cpsr
= state
->Spsr
[state
->Bank
];
5008 ARMul_CPSRAltered (state
);
5016 state
->Reg
[15] = src
& PCBITS
;
5020 /* ARMul_R15Altered would have to support it. */
5026 if (state
->Bank
== USERBANK
)
5027 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
5029 state
->Reg
[15] = src
;
5031 ARMul_R15Altered (state
);
5035 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5038 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
5039 will switch to Thumb mode if the least significant bit is set. */
5042 WriteR15Branch (ARMul_State
* state
, ARMword src
)
5049 state
->Reg
[15] = src
& 0xfffffffe;
5054 state
->Reg
[15] = src
& 0xfffffffc;
5058 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5060 WriteR15 (state
, src
);
5064 /* Before ARM_v5 LDR and LDM of pc did not change mode. */
5067 WriteR15Load (ARMul_State
* state
, ARMword src
)
5070 WriteR15Branch (state
, src
);
5072 WriteR15 (state
, src
);
5075 /* This routine evaluates most Load and Store register RHS's. It is
5076 intended to be called from the macro LSRegRHS, which filters the
5077 common case of an unshifted register with in line code. */
5080 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
5082 ARMword shamt
, base
;
5087 /* Now forbidden, but ... */
5088 base
= ECC
| ER15INT
| R15PC
| EMODE
;
5091 base
= state
->Reg
[base
];
5093 shamt
= BITS (7, 11);
5094 switch ((int) BITS (5, 6))
5097 return (base
<< shamt
);
5102 return (base
>> shamt
);
5105 return ((ARMword
) ((ARMsword
) base
>> 31L));
5107 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
5111 return ((base
>> 1) | (CFLAG
<< 31));
5113 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
5120 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
5123 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
5130 /* Now forbidden, but ... */
5131 return ECC
| ER15INT
| R15PC
| EMODE
;
5133 return state
->Reg
[RHSReg
];
5137 return BITS (0, 3) | (BITS (8, 11) << 4);
5140 /* This function does the work of loading a word for a LDR instruction. */
5143 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5149 if (ADDREXCEPT (address
))
5150 INTERNALABORT (address
);
5153 dest
= ARMul_LoadWordN (state
, address
);
5158 return state
->lateabtSig
;
5161 dest
= ARMul_Align (state
, address
, dest
);
5163 ARMul_Icycles (state
, 1, 0L);
5165 return (DESTReg
!= LHSReg
);
5169 /* This function does the work of loading a halfword. */
5172 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
5179 if (ADDREXCEPT (address
))
5180 INTERNALABORT (address
);
5182 dest
= ARMul_LoadHalfWord (state
, address
);
5186 return state
->lateabtSig
;
5190 if (dest
& 1 << (16 - 1))
5191 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
5194 ARMul_Icycles (state
, 1, 0L);
5195 return (DESTReg
!= LHSReg
);
5200 /* This function does the work of loading a byte for a LDRB instruction. */
5203 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
5209 if (ADDREXCEPT (address
))
5210 INTERNALABORT (address
);
5212 dest
= ARMul_LoadByte (state
, address
);
5216 return state
->lateabtSig
;
5220 if (dest
& 1 << (8 - 1))
5221 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
5224 ARMul_Icycles (state
, 1, 0L);
5226 return (DESTReg
!= LHSReg
);
5229 /* This function does the work of loading two words for a LDRD instruction. */
5232 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
5236 ARMword write_back
= BIT (21);
5237 ARMword immediate
= BIT (22);
5238 ARMword add_to_base
= BIT (23);
5239 ARMword pre_indexed
= BIT (24);
5249 /* If the writeback bit is set, the pre-index bit must be clear. */
5250 if (write_back
&& ! pre_indexed
)
5252 ARMul_UndefInstr (state
, instr
);
5256 /* Extract the base address register. */
5259 /* Extract the destination register and check it. */
5262 /* Destination register must be even. */
5264 /* Destination register cannot be LR. */
5265 || (dest_reg
== 14))
5267 ARMul_UndefInstr (state
, instr
);
5271 /* Compute the base address. */
5272 base
= state
->Reg
[addr_reg
];
5274 /* Compute the offset. */
5275 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5277 /* Compute the sum of the two. */
5279 sum
= base
+ offset
;
5281 sum
= base
- offset
;
5283 /* If this is a pre-indexed mode use the sum. */
5289 if (state
->is_v6
&& (addr
& 0x3) == 0)
5290 /* Word alignment is enough for v6. */
5292 /* The address must be aligned on a 8 byte boundary. */
5293 else if (addr
& 0x7)
5296 ARMul_DATAABORT (addr
);
5298 ARMul_UndefInstr (state
, instr
);
5303 /* For pre indexed or post indexed addressing modes,
5304 check that the destination registers do not overlap
5305 the address registers. */
5306 if ((! pre_indexed
|| write_back
)
5307 && ( addr_reg
== dest_reg
5308 || addr_reg
== dest_reg
+ 1))
5310 ARMul_UndefInstr (state
, instr
);
5314 /* Load the words. */
5315 value1
= ARMul_LoadWordN (state
, addr
);
5316 value2
= ARMul_LoadWordN (state
, addr
+ 4);
5318 /* Check for data aborts. */
5325 ARMul_Icycles (state
, 2, 0L);
5327 /* Store the values. */
5328 state
->Reg
[dest_reg
] = value1
;
5329 state
->Reg
[dest_reg
+ 1] = value2
;
5331 /* Do the post addressing and writeback. */
5335 if (! pre_indexed
|| write_back
)
5336 state
->Reg
[addr_reg
] = addr
;
5339 /* This function does the work of storing two words for a STRD instruction. */
5342 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
5346 ARMword write_back
= BIT (21);
5347 ARMword immediate
= BIT (22);
5348 ARMword add_to_base
= BIT (23);
5349 ARMword pre_indexed
= BIT (24);
5357 /* If the writeback bit is set, the pre-index bit must be clear. */
5358 if (write_back
&& ! pre_indexed
)
5360 ARMul_UndefInstr (state
, instr
);
5364 /* Extract the base address register. */
5367 /* Base register cannot be PC. */
5370 ARMul_UndefInstr (state
, instr
);
5374 /* Extract the source register. */
5377 /* Source register must be even. */
5380 ARMul_UndefInstr (state
, instr
);
5384 /* Compute the base address. */
5385 base
= state
->Reg
[addr_reg
];
5387 /* Compute the offset. */
5388 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5390 /* Compute the sum of the two. */
5392 sum
= base
+ offset
;
5394 sum
= base
- offset
;
5396 /* If this is a pre-indexed mode use the sum. */
5402 /* The address must be aligned on a 8 byte boundary. */
5406 ARMul_DATAABORT (addr
);
5408 ARMul_UndefInstr (state
, instr
);
5413 /* For pre indexed or post indexed addressing modes,
5414 check that the destination registers do not overlap
5415 the address registers. */
5416 if ((! pre_indexed
|| write_back
)
5417 && ( addr_reg
== src_reg
5418 || addr_reg
== src_reg
+ 1))
5420 ARMul_UndefInstr (state
, instr
);
5424 /* Load the words. */
5425 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
5426 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
5434 /* Do the post addressing and writeback. */
5438 if (! pre_indexed
|| write_back
)
5439 state
->Reg
[addr_reg
] = addr
;
5442 /* This function does the work of storing a word from a STR instruction. */
5445 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5450 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5453 ARMul_StoreWordN (state
, address
, DEST
);
5455 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5457 INTERNALABORT (address
);
5458 (void) ARMul_LoadWordN (state
, address
);
5461 ARMul_StoreWordN (state
, address
, DEST
);
5466 return state
->lateabtSig
;
5472 /* This function does the work of storing a byte for a STRH instruction. */
5475 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5481 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5485 ARMul_StoreHalfWord (state
, address
, DEST
);
5487 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5489 INTERNALABORT (address
);
5490 (void) ARMul_LoadHalfWord (state
, address
);
5493 ARMul_StoreHalfWord (state
, address
, DEST
);
5499 return state
->lateabtSig
;
5506 /* This function does the work of storing a byte for a STRB instruction. */
5509 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
5514 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5517 ARMul_StoreByte (state
, address
, DEST
);
5519 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5521 INTERNALABORT (address
);
5522 (void) ARMul_LoadByte (state
, address
);
5525 ARMul_StoreByte (state
, address
, DEST
);
5530 return state
->lateabtSig
;
5536 /* This function does the work of loading the registers listed in an LDM
5537 instruction, when the S bit is clear. The code here is always increment
5538 after, it's up to the caller to get the input address correct and to
5539 handle base register modification. */
5542 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
5548 UNDEF_LSMBaseInListWb
;
5551 if (ADDREXCEPT (address
))
5552 INTERNALABORT (address
);
5554 if (BIT (21) && LHSReg
!= 15)
5557 /* N cycle first. */
5558 for (temp
= 0; !BIT (temp
); temp
++)
5561 dest
= ARMul_LoadWordN (state
, address
);
5563 if (!state
->abortSig
&& !state
->Aborted
)
5564 state
->Reg
[temp
++] = dest
;
5565 else if (!state
->Aborted
)
5567 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5568 state
->Aborted
= ARMul_DataAbortV
;
5571 /* S cycles from here on. */
5572 for (; temp
< 16; temp
++)
5575 /* Load this register. */
5577 dest
= ARMul_LoadWordS (state
, address
);
5579 if (!state
->abortSig
&& !state
->Aborted
)
5580 state
->Reg
[temp
] = dest
;
5581 else if (!state
->Aborted
)
5583 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5584 state
->Aborted
= ARMul_DataAbortV
;
5588 if (BIT (15) && !state
->Aborted
)
5589 /* PC is in the reg list. */
5590 WriteR15Load (state
, PC
);
5592 /* To write back the final register. */
5593 ARMul_Icycles (state
, 1, 0L);
5597 if (BIT (21) && LHSReg
!= 15)
5603 /* This function does the work of loading the registers listed in an LDM
5604 instruction, when the S bit is set. The code here is always increment
5605 after, it's up to the caller to get the input address correct and to
5606 handle base register modification. */
5609 LoadSMult (ARMul_State
* state
,
5618 UNDEF_LSMBaseInListWb
;
5623 if (ADDREXCEPT (address
))
5624 INTERNALABORT (address
);
5627 if (BIT (21) && LHSReg
!= 15)
5630 if (!BIT (15) && state
->Bank
!= USERBANK
)
5632 /* Temporary reg bank switch. */
5633 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5634 UNDEF_LSMUserBankWb
;
5637 /* N cycle first. */
5638 for (temp
= 0; !BIT (temp
); temp
++)
5641 dest
= ARMul_LoadWordN (state
, address
);
5643 if (!state
->abortSig
)
5644 state
->Reg
[temp
++] = dest
;
5645 else if (!state
->Aborted
)
5647 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5648 state
->Aborted
= ARMul_DataAbortV
;
5651 /* S cycles from here on. */
5652 for (; temp
< 16; temp
++)
5655 /* Load this register. */
5657 dest
= ARMul_LoadWordS (state
, address
);
5659 if (!state
->abortSig
&& !state
->Aborted
)
5660 state
->Reg
[temp
] = dest
;
5661 else if (!state
->Aborted
)
5663 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5664 state
->Aborted
= ARMul_DataAbortV
;
5668 if (BIT (15) && !state
->Aborted
)
5670 /* PC is in the reg list. */
5672 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5674 state
->Cpsr
= GETSPSR (state
->Bank
);
5675 ARMul_CPSRAltered (state
);
5678 WriteR15 (state
, PC
);
5680 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
5682 /* Protect bits in user mode. */
5683 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
5684 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
5685 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
5686 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
5689 ARMul_R15Altered (state
);
5695 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5696 /* Restore the correct bank. */
5697 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5699 /* To write back the final register. */
5700 ARMul_Icycles (state
, 1, 0L);
5704 if (BIT (21) && LHSReg
!= 15)
5711 /* This function does the work of storing the registers listed in an STM
5712 instruction, when the S bit is clear. The code here is always increment
5713 after, it's up to the caller to get the input address correct and to
5714 handle base register modification. */
5717 StoreMult (ARMul_State
* state
,
5726 UNDEF_LSMBaseInListWb
;
5729 /* N-cycle, increment the PC and update the NextInstr state. */
5733 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5734 INTERNALABORT (address
);
5740 /* N cycle first. */
5741 for (temp
= 0; !BIT (temp
); temp
++)
5745 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5749 (void) ARMul_LoadWordN (state
, address
);
5751 /* Fake the Stores as Loads. */
5752 for (; temp
< 16; temp
++)
5755 /* Save this register. */
5757 (void) ARMul_LoadWordS (state
, address
);
5760 if (BIT (21) && LHSReg
!= 15)
5766 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5769 if (state
->abortSig
&& !state
->Aborted
)
5771 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5772 state
->Aborted
= ARMul_DataAbortV
;
5775 if (BIT (21) && LHSReg
!= 15)
5778 /* S cycles from here on. */
5779 for (; temp
< 16; temp
++)
5782 /* Save this register. */
5785 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5787 if (state
->abortSig
&& !state
->Aborted
)
5789 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5790 state
->Aborted
= ARMul_DataAbortV
;
5798 /* This function does the work of storing the registers listed in an STM
5799 instruction when the S bit is set. The code here is always increment
5800 after, it's up to the caller to get the input address correct and to
5801 handle base register modification. */
5804 StoreSMult (ARMul_State
* state
,
5813 UNDEF_LSMBaseInListWb
;
5818 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5819 INTERNALABORT (address
);
5825 if (state
->Bank
!= USERBANK
)
5827 /* Force User Bank. */
5828 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5829 UNDEF_LSMUserBankWb
;
5832 for (temp
= 0; !BIT (temp
); temp
++)
5833 ; /* N cycle first. */
5836 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5840 (void) ARMul_LoadWordN (state
, address
);
5842 for (; temp
< 16; temp
++)
5843 /* Fake the Stores as Loads. */
5846 /* Save this register. */
5849 (void) ARMul_LoadWordS (state
, address
);
5852 if (BIT (21) && LHSReg
!= 15)
5859 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5862 if (state
->abortSig
&& !state
->Aborted
)
5864 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5865 state
->Aborted
= ARMul_DataAbortV
;
5868 /* S cycles from here on. */
5869 for (; temp
< 16; temp
++)
5872 /* Save this register. */
5875 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5877 if (state
->abortSig
&& !state
->Aborted
)
5879 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5880 state
->Aborted
= ARMul_DataAbortV
;
5884 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5885 /* Restore the correct bank. */
5886 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5888 if (BIT (21) && LHSReg
!= 15)
5895 /* This function does the work of adding two 32bit values
5896 together, and calculating if a carry has occurred. */
5899 Add32 (ARMword a1
, ARMword a2
, int *carry
)
5901 ARMword result
= (a1
+ a2
);
5902 unsigned int uresult
= (unsigned int) result
;
5903 unsigned int ua1
= (unsigned int) a1
;
5905 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5906 or (result > RdLo) then we have no carry. */
5907 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
5915 /* This function does the work of multiplying
5916 two 32bit values to give a 64bit result. */
5919 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5921 /* Operand register numbers. */
5922 int nRdHi
, nRdLo
, nRs
, nRm
;
5923 ARMword RdHi
= 0, RdLo
= 0, Rm
;
5927 nRdHi
= BITS (16, 19);
5928 nRdLo
= BITS (12, 15);
5932 /* Needed to calculate the cycle count. */
5933 Rm
= state
->Reg
[nRm
];
5935 /* Check for illegal operand combinations first. */
5942 /* Intermediate results. */
5943 ARMword lo
, mid1
, mid2
, hi
;
5945 ARMword Rs
= state
->Reg
[nRs
];
5953 /* BAD code can trigger this result. So only complain if debugging. */
5954 if (state
->Debug
&& (nRdHi
== nRm
|| nRdLo
== nRm
))
5955 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS: %d %d %d\n",
5959 /* Compute sign of result and adjust operands if necessary. */
5960 sign
= (Rm
^ Rs
) & 0x80000000;
5962 if (((ARMsword
) Rm
) < 0)
5965 if (((ARMsword
) Rs
) < 0)
5969 /* We can split the 32x32 into four 16x16 operations. This
5970 ensures that we do not lose precision on 32bit only hosts. */
5971 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
5972 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5973 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
5974 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5976 /* We now need to add all of these results together, taking
5977 care to propogate the carries from the additions. */
5978 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
5980 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
5982 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
5986 /* Negate result if necessary. */
5989 if (RdLo
== 0xFFFFFFFF)
5998 state
->Reg
[nRdLo
] = RdLo
;
5999 state
->Reg
[nRdHi
] = RdHi
;
6001 else if (state
->Debug
)
6002 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
6005 /* Ensure that both RdHi and RdLo are used to compute Z,
6006 but don't let RdLo's sign bit make it to N. */
6007 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6009 /* The cycle count depends on whether the instruction is a signed or
6010 unsigned multiply, and what bits are clear in the multiplier. */
6011 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
6012 /* Invert the bits to make the check against zero. */
6015 if ((Rm
& 0xFFFFFF00) == 0)
6017 else if ((Rm
& 0xFFFF0000) == 0)
6019 else if ((Rm
& 0xFF000000) == 0)
6027 /* This function does the work of multiplying two 32bit
6028 values and adding a 64bit value to give a 64bit result. */
6031 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
6038 nRdHi
= BITS (16, 19);
6039 nRdLo
= BITS (12, 15);
6041 RdHi
= state
->Reg
[nRdHi
];
6042 RdLo
= state
->Reg
[nRdLo
];
6044 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
6046 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
6047 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
6049 state
->Reg
[nRdLo
] = RdLo
;
6050 state
->Reg
[nRdHi
] = RdHi
;
6053 /* Ensure that both RdHi and RdLo are used to compute Z,
6054 but don't let RdLo's sign bit make it to N. */
6055 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6057 /* Extra cycle for addition. */