3a72277683e62b40f367e50e29815e98cd9d4891
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. */
1145 ARMul_Emulate32 (ARMul_State
* state
)
1147 ARMul_Emulate26 (ARMul_State
* state
)
1150 ARMword instr
; /* The current instruction. */
1151 ARMword dest
= 0; /* Almost the DestBus. */
1152 ARMword temp
; /* Ubiquitous third hand. */
1153 ARMword pc
= 0; /* The address of the current instruction. */
1154 ARMword lhs
; /* Almost the ABus and BBus. */
1156 ARMword decoded
= 0; /* Instruction pipeline. */
1159 /* Execute the next instruction. */
1161 if (state
->NextInstr
< PRIMEPIPE
)
1163 decoded
= state
->decoded
;
1164 loaded
= state
->loaded
;
1170 /* Just keep going. */
1173 switch (state
->NextInstr
)
1176 /* Advance the pipeline, and an S cycle. */
1177 state
->Reg
[15] += isize
;
1181 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1185 /* Advance the pipeline, and an N cycle. */
1186 state
->Reg
[15] += isize
;
1190 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
1195 /* Program counter advanced, and an S cycle. */
1199 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1204 /* Program counter advanced, and an N cycle. */
1208 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
1213 /* The program counter has been changed. */
1214 pc
= state
->Reg
[15];
1216 pc
= pc
& R15PCBITS
;
1218 state
->Reg
[15] = pc
+ (isize
* 2);
1220 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
1221 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
1222 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
1227 /* The program counter has been changed. */
1228 pc
= state
->Reg
[15];
1230 pc
= pc
& R15PCBITS
;
1232 state
->Reg
[15] = pc
+ (isize
* 2);
1234 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
1235 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
1236 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1241 if (state
->EventSet
)
1242 ARMul_EnvokeEvent (state
);
1244 if (! TFLAG
&& trace
)
1246 fprintf (stderr
, "pc: %x, ", pc
& ~1);
1248 fprintf (stderr
, "instr: %x\n", instr
);
1251 if (instr
== 0 || pc
< 0x10)
1253 ARMul_Abort (state
, ARMUndefinedInstrV
);
1254 state
->Emulate
= FALSE
;
1257 #if 0 /* Enable this code to help track down stack alignment bugs. */
1259 static ARMword old_sp
= -1;
1261 if (old_sp
!= state
->Reg
[13])
1263 old_sp
= state
->Reg
[13];
1264 fprintf (stderr
, "pc: %08x: SP set to %08x%s\n",
1265 pc
& ~1, old_sp
, (old_sp
% 8) ? " [UNALIGNED!]" : "");
1270 if (state
->Exception
)
1272 /* Any exceptions ? */
1273 if (state
->NresetSig
== LOW
)
1275 ARMul_Abort (state
, ARMul_ResetV
);
1278 else if (!state
->NfiqSig
&& !FFLAG
)
1280 ARMul_Abort (state
, ARMul_FIQV
);
1283 else if (!state
->NirqSig
&& !IFLAG
)
1285 ARMul_Abort (state
, ARMul_IRQV
);
1290 if (state
->CallDebug
> 0)
1292 if (state
->Emulate
< ONCE
)
1294 state
->NextInstr
= RESUME
;
1299 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n",
1300 (long) pc
, (long) instr
, (long) state
->Mode
);
1301 (void) fgetc (stdin
);
1304 else if (state
->Emulate
< ONCE
)
1306 state
->NextInstr
= RESUME
;
1313 /* Provide Thumb instruction decoding. If the processor is in Thumb
1314 mode, then we can simply decode the Thumb instruction, and map it
1315 to the corresponding ARM instruction (by directly loading the
1316 instr variable, and letting the normal ARM simulator
1317 execute). There are some caveats to ensure that the correct
1318 pipelined PC value is used when executing Thumb code, and also for
1319 dealing with the BL instruction. */
1324 /* Check if in Thumb mode. */
1325 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
1328 /* This is a Thumb instruction. */
1329 ARMul_UndefInstr (state
, instr
);
1333 /* Already processed. */
1337 /* ARM instruction available. */
1340 fprintf (stderr
, " emulate as: ");
1342 fprintf (stderr
, "%08x ", new);
1344 fprintf (stderr
, "\n");
1347 /* So continue instruction decoding. */
1357 /* Check the condition codes. */
1358 if ((temp
= TOPBITS (28)) == AL
)
1359 /* Vile deed in the need for speed. */
1362 /* Check the condition code. */
1363 switch ((int) TOPBITS (28))
1371 if (BITS (25, 27) == 5) /* BLX(1) */
1375 state
->Reg
[14] = pc
+ 4;
1377 /* Force entry into Thumb mode. */
1380 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
1382 dest
+= POSBRANCH
+ (BIT (24) << 1);
1384 WriteR15Branch (state
, dest
);
1387 else if ((instr
& 0xFC70F000) == 0xF450F000)
1388 /* The PLD instruction. Ignored. */
1390 else if ( ((instr
& 0xfe500f00) == 0xfc100100)
1391 || ((instr
& 0xfe500f00) == 0xfc000100))
1392 /* wldrw and wstrw are unconditional. */
1395 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
1396 ARMul_UndefInstr (state
, instr
);
1425 temp
= (CFLAG
&& !ZFLAG
);
1428 temp
= (!CFLAG
|| ZFLAG
);
1431 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
1434 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
1437 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
1440 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
1444 /* Handle the Clock counter here. */
1445 if (state
->is_XScale
)
1450 ok
= state
->CPRead
[14] (state
, 0, & cp14r0
);
1452 if (ok
&& (cp14r0
& ARMul_CP14_R0_ENABLE
))
1454 unsigned long newcycles
, nowtime
= ARMul_Time (state
);
1456 newcycles
= nowtime
- state
->LastTime
;
1457 state
->LastTime
= nowtime
;
1459 if (cp14r0
& ARMul_CP14_R0_CCD
)
1461 if (state
->CP14R0_CCD
== -1)
1462 state
->CP14R0_CCD
= newcycles
;
1464 state
->CP14R0_CCD
+= newcycles
;
1466 if (state
->CP14R0_CCD
>= 64)
1470 while (state
->CP14R0_CCD
>= 64)
1471 state
->CP14R0_CCD
-= 64, newcycles
++;
1481 state
->CP14R0_CCD
= -1;
1484 cp14r0
|= ARMul_CP14_R0_FLAG2
;
1485 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
1487 ok
= state
->CPRead
[14] (state
, 1, & cp14r1
);
1489 /* Coded like this for portability. */
1490 while (ok
&& newcycles
)
1492 if (cp14r1
== 0xffffffff)
1503 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
1505 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
1509 if (state
->CPRead
[13] (state
, 8, & temp
)
1510 && (temp
& ARMul_CP13_R8_PMUS
))
1511 ARMul_Abort (state
, ARMul_FIQV
);
1513 ARMul_Abort (state
, ARMul_IRQV
);
1519 /* Handle hardware instructions breakpoints here. */
1520 if (state
->is_XScale
)
1522 if ( (pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
1523 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
1525 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
1526 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1530 /* Actual execution of instructions begins here. */
1531 /* If the condition codes don't match, stop here. */
1536 if (state
->is_XScale
)
1538 if (BIT (20) == 0 && BITS (25, 27) == 0)
1540 if (BITS (4, 7) == 0xD)
1542 /* XScale Load Consecutive insn. */
1543 ARMword temp
= GetLS7RHS (state
, instr
);
1544 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
1545 ARMword addr
= BIT (24) ? temp2
: LHS
;
1548 ARMul_UndefInstr (state
, instr
);
1550 /* Alignment violation. */
1551 ARMul_Abort (state
, ARMul_DataAbortV
);
1554 int wb
= BIT (21) || (! BIT (24));
1556 state
->Reg
[BITS (12, 15)] =
1557 ARMul_LoadWordN (state
, addr
);
1558 state
->Reg
[BITS (12, 15) + 1] =
1559 ARMul_LoadWordN (state
, addr
+ 4);
1566 else if (BITS (4, 7) == 0xF)
1568 /* XScale Store Consecutive insn. */
1569 ARMword temp
= GetLS7RHS (state
, instr
);
1570 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
1571 ARMword addr
= BIT (24) ? temp2
: LHS
;
1574 ARMul_UndefInstr (state
, instr
);
1576 /* Alignment violation. */
1577 ARMul_Abort (state
, ARMul_DataAbortV
);
1580 ARMul_StoreWordN (state
, addr
,
1581 state
->Reg
[BITS (12, 15)]);
1582 ARMul_StoreWordN (state
, addr
+ 4,
1583 state
->Reg
[BITS (12, 15) + 1]);
1585 if (BIT (21)|| ! BIT (24))
1593 if (ARMul_HandleIwmmxt (state
, instr
))
1597 switch ((int) BITS (20, 27))
1599 /* Data Processing Register RHS Instructions. */
1601 case 0x00: /* AND reg and MUL */
1603 if (BITS (4, 11) == 0xB)
1605 /* STRH register offset, no write-back, down, post indexed. */
1609 if (BITS (4, 7) == 0xD)
1611 Handle_Load_Double (state
, instr
);
1614 if (BITS (4, 7) == 0xF)
1616 Handle_Store_Double (state
, instr
);
1620 if (BITS (4, 7) == 9)
1623 rhs
= state
->Reg
[MULRHSReg
];
1624 if (MULLHSReg
== MULDESTReg
)
1627 state
->Reg
[MULDESTReg
] = 0;
1629 else if (MULDESTReg
!= 15)
1630 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
1634 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1635 if (rhs
& (1L << dest
))
1638 /* Mult takes this many/2 I cycles. */
1639 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1650 case 0x01: /* ANDS reg and MULS */
1652 if ((BITS (4, 11) & 0xF9) == 0x9)
1653 /* LDR register offset, no write-back, down, post indexed. */
1655 /* Fall through to rest of decoding. */
1657 if (BITS (4, 7) == 9)
1660 rhs
= state
->Reg
[MULRHSReg
];
1662 if (MULLHSReg
== MULDESTReg
)
1665 state
->Reg
[MULDESTReg
] = 0;
1669 else if (MULDESTReg
!= 15)
1671 dest
= state
->Reg
[MULLHSReg
] * rhs
;
1672 ARMul_NegZero (state
, dest
);
1673 state
->Reg
[MULDESTReg
] = dest
;
1678 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1679 if (rhs
& (1L << dest
))
1682 /* Mult takes this many/2 I cycles. */
1683 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1694 case 0x02: /* EOR reg and MLA */
1696 if (BITS (4, 11) == 0xB)
1698 /* STRH register offset, write-back, down, post indexed. */
1703 if (BITS (4, 7) == 9)
1705 rhs
= state
->Reg
[MULRHSReg
];
1706 if (MULLHSReg
== MULDESTReg
)
1709 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
1711 else if (MULDESTReg
!= 15)
1712 state
->Reg
[MULDESTReg
] =
1713 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1717 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1718 if (rhs
& (1L << dest
))
1721 /* Mult takes this many/2 I cycles. */
1722 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1732 case 0x03: /* EORS reg and MLAS */
1734 if ((BITS (4, 11) & 0xF9) == 0x9)
1735 /* LDR register offset, write-back, down, post-indexed. */
1737 /* Fall through to rest of the decoding. */
1739 if (BITS (4, 7) == 9)
1742 rhs
= state
->Reg
[MULRHSReg
];
1744 if (MULLHSReg
== MULDESTReg
)
1747 dest
= state
->Reg
[MULACCReg
];
1748 ARMul_NegZero (state
, dest
);
1749 state
->Reg
[MULDESTReg
] = dest
;
1751 else if (MULDESTReg
!= 15)
1754 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1755 ARMul_NegZero (state
, dest
);
1756 state
->Reg
[MULDESTReg
] = dest
;
1761 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1762 if (rhs
& (1L << dest
))
1765 /* Mult takes this many/2 I cycles. */
1766 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1777 case 0x04: /* SUB reg */
1779 if (BITS (4, 7) == 0xB)
1781 /* STRH immediate offset, no write-back, down, post indexed. */
1785 if (BITS (4, 7) == 0xD)
1787 Handle_Load_Double (state
, instr
);
1790 if (BITS (4, 7) == 0xF)
1792 Handle_Store_Double (state
, instr
);
1801 case 0x05: /* SUBS reg */
1803 if ((BITS (4, 7) & 0x9) == 0x9)
1804 /* LDR immediate offset, no write-back, down, post indexed. */
1806 /* Fall through to the rest of the instruction decoding. */
1812 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1814 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1815 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1825 case 0x06: /* RSB reg */
1827 if (BITS (4, 7) == 0xB)
1829 /* STRH immediate offset, write-back, down, post indexed. */
1839 case 0x07: /* RSBS reg */
1841 if ((BITS (4, 7) & 0x9) == 0x9)
1842 /* LDR immediate offset, write-back, down, post indexed. */
1844 /* Fall through to remainder of instruction decoding. */
1850 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1852 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1853 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1863 case 0x08: /* ADD reg */
1865 if (BITS (4, 11) == 0xB)
1867 /* STRH register offset, no write-back, up, post indexed. */
1871 if (BITS (4, 7) == 0xD)
1873 Handle_Load_Double (state
, instr
);
1876 if (BITS (4, 7) == 0xF)
1878 Handle_Store_Double (state
, instr
);
1883 if (BITS (4, 7) == 0x9)
1887 ARMul_Icycles (state
,
1888 Multiply64 (state
, instr
, LUNSIGNED
,
1898 case 0x09: /* ADDS reg */
1900 if ((BITS (4, 11) & 0xF9) == 0x9)
1901 /* LDR register offset, no write-back, up, post indexed. */
1903 /* Fall through to remaining instruction decoding. */
1906 if (BITS (4, 7) == 0x9)
1910 ARMul_Icycles (state
,
1911 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
1919 ASSIGNZ (dest
== 0);
1920 if ((lhs
| rhs
) >> 30)
1922 /* Possible C,V,N to set. */
1923 ASSIGNN (NEG (dest
));
1924 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1925 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1936 case 0x0a: /* ADC reg */
1938 if (BITS (4, 11) == 0xB)
1940 /* STRH register offset, write-back, up, post-indexed. */
1944 if (BITS (4, 7) == 0x9)
1948 ARMul_Icycles (state
,
1949 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1955 dest
= LHS
+ rhs
+ CFLAG
;
1959 case 0x0b: /* ADCS reg */
1961 if ((BITS (4, 11) & 0xF9) == 0x9)
1962 /* LDR register offset, write-back, up, post indexed. */
1964 /* Fall through to remaining instruction decoding. */
1965 if (BITS (4, 7) == 0x9)
1969 ARMul_Icycles (state
,
1970 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1977 dest
= lhs
+ rhs
+ CFLAG
;
1978 ASSIGNZ (dest
== 0);
1979 if ((lhs
| rhs
) >> 30)
1981 /* Possible C,V,N to set. */
1982 ASSIGNN (NEG (dest
));
1983 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1984 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1995 case 0x0c: /* SBC reg */
1997 if (BITS (4, 7) == 0xB)
1999 /* STRH immediate offset, no write-back, up post indexed. */
2003 if (BITS (4, 7) == 0xD)
2005 Handle_Load_Double (state
, instr
);
2008 if (BITS (4, 7) == 0xF)
2010 Handle_Store_Double (state
, instr
);
2013 if (BITS (4, 7) == 0x9)
2017 ARMul_Icycles (state
,
2018 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
2024 dest
= LHS
- rhs
- !CFLAG
;
2028 case 0x0d: /* SBCS reg */
2030 if ((BITS (4, 7) & 0x9) == 0x9)
2031 /* LDR immediate offset, no write-back, up, post indexed. */
2034 if (BITS (4, 7) == 0x9)
2038 ARMul_Icycles (state
,
2039 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
2046 dest
= lhs
- rhs
- !CFLAG
;
2047 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2049 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2050 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2060 case 0x0e: /* RSC reg */
2062 if (BITS (4, 7) == 0xB)
2064 /* STRH immediate offset, write-back, up, post indexed. */
2069 if (BITS (4, 7) == 0x9)
2073 ARMul_Icycles (state
,
2074 MultiplyAdd64 (state
, instr
, LSIGNED
,
2080 dest
= rhs
- LHS
- !CFLAG
;
2084 case 0x0f: /* RSCS reg */
2086 if ((BITS (4, 7) & 0x9) == 0x9)
2087 /* LDR immediate offset, write-back, up, post indexed. */
2089 /* Fall through to remaining instruction decoding. */
2091 if (BITS (4, 7) == 0x9)
2095 ARMul_Icycles (state
,
2096 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
2103 dest
= rhs
- lhs
- !CFLAG
;
2105 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2107 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2108 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2118 case 0x10: /* TST reg and MRS CPSR and SWP word. */
2121 if (BIT (4) == 0 && BIT (7) == 1)
2123 /* ElSegundo SMLAxy insn. */
2124 ARMword op1
= state
->Reg
[BITS (0, 3)];
2125 ARMword op2
= state
->Reg
[BITS (8, 11)];
2126 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2140 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
2142 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
2146 if (BITS (4, 11) == 5)
2148 /* ElSegundo QADD insn. */
2149 ARMword op1
= state
->Reg
[BITS (0, 3)];
2150 ARMword op2
= state
->Reg
[BITS (16, 19)];
2151 ARMword result
= op1
+ op2
;
2152 if (AddOverflow (op1
, op2
, result
))
2154 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2157 state
->Reg
[BITS (12, 15)] = result
;
2162 if (BITS (4, 11) == 0xB)
2164 /* STRH register offset, no write-back, down, pre indexed. */
2168 if (BITS (4, 7) == 0xD)
2170 Handle_Load_Double (state
, instr
);
2173 if (BITS (4, 7) == 0xF)
2175 Handle_Store_Double (state
, instr
);
2179 if (BITS (4, 11) == 9)
2186 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2188 INTERNALABORT (temp
);
2189 (void) ARMul_LoadWordN (state
, temp
);
2190 (void) ARMul_LoadWordN (state
, temp
);
2194 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
2196 DEST
= ARMul_Align (state
, temp
, dest
);
2199 if (state
->abortSig
|| state
->Aborted
)
2202 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2205 DEST
= ECC
| EINT
| EMODE
;
2211 && handle_v6_insn (state
, instr
))
2218 case 0x11: /* TSTP reg */
2220 if ((BITS (4, 11) & 0xF9) == 0x9)
2221 /* LDR register offset, no write-back, down, pre indexed. */
2223 /* Continue with remaining instruction decode. */
2229 state
->Cpsr
= GETSPSR (state
->Bank
);
2230 ARMul_CPSRAltered (state
);
2242 ARMul_NegZero (state
, dest
);
2246 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
2249 if (BITS (4, 7) == 3)
2255 temp
= (pc
+ 2) | 1;
2259 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2260 state
->Reg
[14] = temp
;
2267 if (BIT (4) == 0 && BIT (7) == 1
2268 && (BIT (5) == 0 || BITS (12, 15) == 0))
2270 /* ElSegundo SMLAWy/SMULWy insn. */
2271 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2272 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2277 if (op1
& 0x80000000)
2282 result
= (op1
* op2
) >> 16;
2286 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2288 if (AddOverflow (result
, Rn
, result
+ Rn
))
2292 state
->Reg
[BITS (16, 19)] = result
;
2296 if (BITS (4, 11) == 5)
2298 /* ElSegundo QSUB insn. */
2299 ARMword op1
= state
->Reg
[BITS (0, 3)];
2300 ARMword op2
= state
->Reg
[BITS (16, 19)];
2301 ARMword result
= op1
- op2
;
2303 if (SubOverflow (op1
, op2
, result
))
2305 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2309 state
->Reg
[BITS (12, 15)] = result
;
2314 if (BITS (4, 11) == 0xB)
2316 /* STRH register offset, write-back, down, pre indexed. */
2320 if (BITS (4, 27) == 0x12FFF1)
2323 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2326 if (BITS (4, 7) == 0xD)
2328 Handle_Load_Double (state
, instr
);
2331 if (BITS (4, 7) == 0xF)
2333 Handle_Store_Double (state
, instr
);
2339 if (BITS (4, 7) == 0x7)
2341 extern int SWI_vector_installed
;
2343 /* Hardware is allowed to optionally override this
2344 instruction and treat it as a breakpoint. Since
2345 this is a simulator not hardware, we take the position
2346 that if a SWI vector was not installed, then an Abort
2347 vector was probably not installed either, and so
2348 normally this instruction would be ignored, even if an
2349 Abort is generated. This is a bad thing, since GDB
2350 uses this instruction for its breakpoints (at least in
2351 Thumb mode it does). So intercept the instruction here
2352 and generate a breakpoint SWI instead. */
2353 if (! SWI_vector_installed
)
2354 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
2357 /* BKPT - normally this will cause an abort, but on the
2358 XScale we must check the DCSR. */
2359 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
2360 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
2364 /* Force the next instruction to be refetched. */
2365 state
->NextInstr
= RESUME
;
2371 /* MSR reg to CPSR. */
2375 /* Don't allow TBIT to be set by MSR. */
2378 ARMul_FixCPSR (state
, instr
, temp
);
2381 else if (state
->is_v6
2382 && handle_v6_insn (state
, instr
))
2390 case 0x13: /* TEQP reg */
2392 if ((BITS (4, 11) & 0xF9) == 0x9)
2393 /* LDR register offset, write-back, down, pre indexed. */
2395 /* Continue with remaining instruction decode. */
2401 state
->Cpsr
= GETSPSR (state
->Bank
);
2402 ARMul_CPSRAltered (state
);
2414 ARMul_NegZero (state
, dest
);
2418 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
2421 if (BIT (4) == 0 && BIT (7) == 1)
2423 /* ElSegundo SMLALxy insn. */
2424 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2425 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2439 dest
= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
2440 dest
|= state
->Reg
[BITS (12, 15)];
2442 state
->Reg
[BITS (12, 15)] = dest
;
2443 state
->Reg
[BITS (16, 19)] = dest
>> 32;
2447 if (BITS (4, 11) == 5)
2449 /* ElSegundo QDADD insn. */
2450 ARMword op1
= state
->Reg
[BITS (0, 3)];
2451 ARMword op2
= state
->Reg
[BITS (16, 19)];
2452 ARMword op2d
= op2
+ op2
;
2455 if (AddOverflow (op2
, op2
, op2d
))
2458 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2461 result
= op1
+ op2d
;
2462 if (AddOverflow (op1
, op2d
, result
))
2465 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2468 state
->Reg
[BITS (12, 15)] = result
;
2473 if (BITS (4, 7) == 0xB)
2475 /* STRH immediate offset, no write-back, down, pre indexed. */
2479 if (BITS (4, 7) == 0xD)
2481 Handle_Load_Double (state
, instr
);
2484 if (BITS (4, 7) == 0xF)
2486 Handle_Store_Double (state
, instr
);
2490 if (BITS (4, 11) == 9)
2497 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2499 INTERNALABORT (temp
);
2500 (void) ARMul_LoadByte (state
, temp
);
2501 (void) ARMul_LoadByte (state
, temp
);
2505 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
2506 if (state
->abortSig
|| state
->Aborted
)
2509 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2513 DEST
= GETSPSR (state
->Bank
);
2516 else if (state
->is_v6
2517 && handle_v6_insn (state
, instr
))
2525 case 0x15: /* CMPP reg. */
2527 if ((BITS (4, 7) & 0x9) == 0x9)
2528 /* LDR immediate offset, no write-back, down, pre indexed. */
2530 /* Continue with remaining instruction decode. */
2536 state
->Cpsr
= GETSPSR (state
->Bank
);
2537 ARMul_CPSRAltered (state
);
2550 ARMul_NegZero (state
, dest
);
2551 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2553 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2554 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2564 case 0x16: /* CMN reg and MSR reg to SPSR */
2567 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
2569 /* ElSegundo SMULxy insn. */
2570 ARMword op1
= state
->Reg
[BITS (0, 3)];
2571 ARMword op2
= state
->Reg
[BITS (8, 11)];
2584 state
->Reg
[BITS (16, 19)] = op1
* op2
;
2588 if (BITS (4, 11) == 5)
2590 /* ElSegundo QDSUB insn. */
2591 ARMword op1
= state
->Reg
[BITS (0, 3)];
2592 ARMword op2
= state
->Reg
[BITS (16, 19)];
2593 ARMword op2d
= op2
+ op2
;
2596 if (AddOverflow (op2
, op2
, op2d
))
2599 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2602 result
= op1
- op2d
;
2603 if (SubOverflow (op1
, op2d
, result
))
2606 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2609 state
->Reg
[BITS (12, 15)] = result
;
2616 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
2618 /* ARM5 CLZ insn. */
2619 ARMword op1
= state
->Reg
[BITS (0, 3)];
2623 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
2626 state
->Reg
[BITS (12, 15)] = result
;
2631 if (BITS (4, 7) == 0xB)
2633 /* STRH immediate offset, write-back, down, pre indexed. */
2637 if (BITS (4, 7) == 0xD)
2639 Handle_Load_Double (state
, instr
);
2642 if (BITS (4, 7) == 0xF)
2644 Handle_Store_Double (state
, instr
);
2652 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
2658 && handle_v6_insn (state
, instr
))
2665 case 0x17: /* CMNP reg */
2667 if ((BITS (4, 7) & 0x9) == 0x9)
2668 /* LDR immediate offset, write-back, down, pre indexed. */
2670 /* Continue with remaining instruction decoding. */
2675 state
->Cpsr
= GETSPSR (state
->Bank
);
2676 ARMul_CPSRAltered (state
);
2690 ASSIGNZ (dest
== 0);
2691 if ((lhs
| rhs
) >> 30)
2693 /* Possible C,V,N to set. */
2694 ASSIGNN (NEG (dest
));
2695 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2696 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2707 case 0x18: /* ORR reg */
2709 if (BITS (4, 11) == 0xB)
2711 /* STRH register offset, no write-back, up, pre indexed. */
2715 if (BITS (4, 7) == 0xD)
2717 Handle_Load_Double (state
, instr
);
2720 if (BITS (4, 7) == 0xF)
2722 Handle_Store_Double (state
, instr
);
2731 case 0x19: /* ORRS reg */
2733 if ((BITS (4, 11) & 0xF9) == 0x9)
2734 /* LDR register offset, no write-back, up, pre indexed. */
2736 /* Continue with remaining instruction decoding. */
2743 case 0x1a: /* MOV reg */
2745 if (BITS (4, 11) == 0xB)
2747 /* STRH register offset, write-back, up, pre indexed. */
2751 if (BITS (4, 7) == 0xD)
2753 Handle_Load_Double (state
, instr
);
2756 if (BITS (4, 7) == 0xF)
2758 Handle_Store_Double (state
, instr
);
2766 case 0x1b: /* MOVS reg */
2768 if ((BITS (4, 11) & 0xF9) == 0x9)
2769 /* LDR register offset, write-back, up, pre indexed. */
2771 /* Continue with remaining instruction decoding. */
2777 case 0x1c: /* BIC reg */
2779 if (BITS (4, 7) == 0xB)
2781 /* STRH immediate offset, no write-back, up, pre indexed. */
2785 if (BITS (4, 7) == 0xD)
2787 Handle_Load_Double (state
, instr
);
2790 else if (BITS (4, 7) == 0xF)
2792 Handle_Store_Double (state
, instr
);
2801 case 0x1d: /* BICS reg */
2803 if ((BITS (4, 7) & 0x9) == 0x9)
2804 /* LDR immediate offset, no write-back, up, pre indexed. */
2806 /* Continue with instruction decoding. */
2813 case 0x1e: /* MVN reg */
2815 if (BITS (4, 7) == 0xB)
2817 /* STRH immediate offset, write-back, up, pre indexed. */
2821 if (BITS (4, 7) == 0xD)
2823 Handle_Load_Double (state
, instr
);
2826 if (BITS (4, 7) == 0xF)
2828 Handle_Store_Double (state
, instr
);
2836 case 0x1f: /* MVNS reg */
2838 if ((BITS (4, 7) & 0x9) == 0x9)
2839 /* LDR immediate offset, write-back, up, pre indexed. */
2841 /* Continue instruction decoding. */
2848 /* Data Processing Immediate RHS Instructions. */
2850 case 0x20: /* AND immed */
2851 dest
= LHS
& DPImmRHS
;
2855 case 0x21: /* ANDS immed */
2861 case 0x22: /* EOR immed */
2862 dest
= LHS
^ DPImmRHS
;
2866 case 0x23: /* EORS immed */
2872 case 0x24: /* SUB immed */
2873 dest
= LHS
- DPImmRHS
;
2877 case 0x25: /* SUBS immed */
2882 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2884 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2885 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2895 case 0x26: /* RSB immed */
2896 dest
= DPImmRHS
- LHS
;
2900 case 0x27: /* RSBS immed */
2905 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2907 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2908 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2918 case 0x28: /* ADD immed */
2919 dest
= LHS
+ DPImmRHS
;
2923 case 0x29: /* ADDS immed */
2927 ASSIGNZ (dest
== 0);
2929 if ((lhs
| rhs
) >> 30)
2931 /* Possible C,V,N to set. */
2932 ASSIGNN (NEG (dest
));
2933 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2934 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2945 case 0x2a: /* ADC immed */
2946 dest
= LHS
+ DPImmRHS
+ CFLAG
;
2950 case 0x2b: /* ADCS immed */
2953 dest
= lhs
+ rhs
+ CFLAG
;
2954 ASSIGNZ (dest
== 0);
2955 if ((lhs
| rhs
) >> 30)
2957 /* Possible C,V,N to set. */
2958 ASSIGNN (NEG (dest
));
2959 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2960 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2971 case 0x2c: /* SBC immed */
2972 dest
= LHS
- DPImmRHS
- !CFLAG
;
2976 case 0x2d: /* SBCS immed */
2979 dest
= lhs
- rhs
- !CFLAG
;
2980 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2982 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2983 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2993 case 0x2e: /* RSC immed */
2994 dest
= DPImmRHS
- LHS
- !CFLAG
;
2998 case 0x2f: /* RSCS immed */
3001 dest
= rhs
- lhs
- !CFLAG
;
3002 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
3004 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
3005 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
3015 case 0x30: /* MOVW immed */
3018 && handle_v6_insn (state
, instr
))
3021 dest
= BITS (0, 11);
3022 dest
|= (BITS (16, 19) << 12);
3026 case 0x31: /* TSTP immed */
3031 state
->Cpsr
= GETSPSR (state
->Bank
);
3032 ARMul_CPSRAltered (state
);
3034 temp
= LHS
& DPImmRHS
;
3043 ARMul_NegZero (state
, dest
);
3047 case 0x32: /* TEQ immed and MSR immed to CPSR */
3049 /* MSR immed to CPSR. */
3050 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
3052 else if (state
->is_v6
3053 && handle_v6_insn (state
, instr
))
3060 case 0x33: /* TEQP immed */
3065 state
->Cpsr
= GETSPSR (state
->Bank
);
3066 ARMul_CPSRAltered (state
);
3068 temp
= LHS
^ DPImmRHS
;
3074 DPSImmRHS
; /* TEQ immed */
3076 ARMul_NegZero (state
, dest
);
3080 case 0x34: /* MOVT immed */
3083 && handle_v6_insn (state
, instr
))
3087 dest
= BITS (0, 11);
3088 dest
|= (BITS (16, 19) << 12);
3089 DEST
|= (dest
<< 16);
3092 case 0x35: /* CMPP immed */
3097 state
->Cpsr
= GETSPSR (state
->Bank
);
3098 ARMul_CPSRAltered (state
);
3100 temp
= LHS
- DPImmRHS
;
3111 ARMul_NegZero (state
, dest
);
3113 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
3115 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
3116 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
3126 case 0x36: /* CMN immed and MSR immed to SPSR */
3128 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
3130 else if (state
->is_v6
3131 && handle_v6_insn (state
, instr
))
3138 case 0x37: /* CMNP immed. */
3143 state
->Cpsr
= GETSPSR (state
->Bank
);
3144 ARMul_CPSRAltered (state
);
3146 temp
= LHS
+ DPImmRHS
;
3157 ASSIGNZ (dest
== 0);
3158 if ((lhs
| rhs
) >> 30)
3160 /* Possible C,V,N to set. */
3161 ASSIGNN (NEG (dest
));
3162 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
3163 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3174 case 0x38: /* ORR immed. */
3175 dest
= LHS
| DPImmRHS
;
3179 case 0x39: /* ORRS immed. */
3185 case 0x3a: /* MOV immed. */
3190 case 0x3b: /* MOVS immed. */
3195 case 0x3c: /* BIC immed. */
3196 dest
= LHS
& ~DPImmRHS
;
3200 case 0x3d: /* BICS immed. */
3206 case 0x3e: /* MVN immed. */
3211 case 0x3f: /* MVNS immed. */
3217 /* Single Data Transfer Immediate RHS Instructions. */
3219 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
3221 if (StoreWord (state
, instr
, lhs
))
3222 LSBase
= lhs
- LSImmRHS
;
3225 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
3227 if (LoadWord (state
, instr
, lhs
))
3228 LSBase
= lhs
- LSImmRHS
;
3231 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
3232 UNDEF_LSRBaseEQDestWb
;
3235 temp
= lhs
- LSImmRHS
;
3236 state
->NtransSig
= LOW
;
3237 if (StoreWord (state
, instr
, lhs
))
3239 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3242 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
3243 UNDEF_LSRBaseEQDestWb
;
3246 state
->NtransSig
= LOW
;
3247 if (LoadWord (state
, instr
, lhs
))
3248 LSBase
= lhs
- LSImmRHS
;
3249 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3252 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
3254 if (StoreByte (state
, instr
, lhs
))
3255 LSBase
= lhs
- LSImmRHS
;
3258 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
3260 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3261 LSBase
= lhs
- LSImmRHS
;
3264 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
3265 UNDEF_LSRBaseEQDestWb
;
3268 state
->NtransSig
= LOW
;
3269 if (StoreByte (state
, instr
, lhs
))
3270 LSBase
= lhs
- LSImmRHS
;
3271 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3274 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
3275 UNDEF_LSRBaseEQDestWb
;
3278 state
->NtransSig
= LOW
;
3279 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3280 LSBase
= lhs
- LSImmRHS
;
3281 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3284 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
3286 if (StoreWord (state
, instr
, lhs
))
3287 LSBase
= lhs
+ LSImmRHS
;
3290 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
3292 if (LoadWord (state
, instr
, lhs
))
3293 LSBase
= lhs
+ LSImmRHS
;
3296 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
3297 UNDEF_LSRBaseEQDestWb
;
3300 state
->NtransSig
= LOW
;
3301 if (StoreWord (state
, instr
, lhs
))
3302 LSBase
= lhs
+ LSImmRHS
;
3303 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3306 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
3307 UNDEF_LSRBaseEQDestWb
;
3310 state
->NtransSig
= LOW
;
3311 if (LoadWord (state
, instr
, lhs
))
3312 LSBase
= lhs
+ LSImmRHS
;
3313 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3316 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
3318 if (StoreByte (state
, instr
, lhs
))
3319 LSBase
= lhs
+ LSImmRHS
;
3322 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
3324 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3325 LSBase
= lhs
+ LSImmRHS
;
3328 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
3329 UNDEF_LSRBaseEQDestWb
;
3332 state
->NtransSig
= LOW
;
3333 if (StoreByte (state
, instr
, lhs
))
3334 LSBase
= lhs
+ LSImmRHS
;
3335 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3338 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
3339 UNDEF_LSRBaseEQDestWb
;
3342 state
->NtransSig
= LOW
;
3343 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3344 LSBase
= lhs
+ LSImmRHS
;
3345 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3349 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
3350 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
3353 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
3354 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
3357 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
3358 UNDEF_LSRBaseEQDestWb
;
3360 temp
= LHS
- LSImmRHS
;
3361 if (StoreWord (state
, instr
, temp
))
3365 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
3366 UNDEF_LSRBaseEQDestWb
;
3368 temp
= LHS
- LSImmRHS
;
3369 if (LoadWord (state
, instr
, temp
))
3373 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
3374 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
3377 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
3378 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
3381 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
3382 UNDEF_LSRBaseEQDestWb
;
3384 temp
= LHS
- LSImmRHS
;
3385 if (StoreByte (state
, instr
, temp
))
3389 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
3390 UNDEF_LSRBaseEQDestWb
;
3392 temp
= LHS
- LSImmRHS
;
3393 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3397 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
3398 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
3401 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
3402 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
3405 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
3406 UNDEF_LSRBaseEQDestWb
;
3408 temp
= LHS
+ LSImmRHS
;
3409 if (StoreWord (state
, instr
, temp
))
3413 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
3414 UNDEF_LSRBaseEQDestWb
;
3416 temp
= LHS
+ LSImmRHS
;
3417 if (LoadWord (state
, instr
, temp
))
3421 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
3422 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
3425 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
3426 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
3429 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
3430 UNDEF_LSRBaseEQDestWb
;
3432 temp
= LHS
+ LSImmRHS
;
3433 if (StoreByte (state
, instr
, temp
))
3437 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
3438 UNDEF_LSRBaseEQDestWb
;
3440 temp
= LHS
+ LSImmRHS
;
3441 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3446 /* Single Data Transfer Register RHS Instructions. */
3448 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
3453 && handle_v6_insn (state
, instr
))
3456 ARMul_UndefInstr (state
, instr
);
3459 UNDEF_LSRBaseEQOffWb
;
3460 UNDEF_LSRBaseEQDestWb
;
3464 if (StoreWord (state
, instr
, lhs
))
3465 LSBase
= lhs
- LSRegRHS
;
3468 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
3473 && handle_v6_insn (state
, instr
))
3476 ARMul_UndefInstr (state
, instr
);
3479 UNDEF_LSRBaseEQOffWb
;
3480 UNDEF_LSRBaseEQDestWb
;
3484 temp
= lhs
- LSRegRHS
;
3485 if (LoadWord (state
, instr
, lhs
))
3489 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
3494 && handle_v6_insn (state
, instr
))
3497 ARMul_UndefInstr (state
, instr
);
3500 UNDEF_LSRBaseEQOffWb
;
3501 UNDEF_LSRBaseEQDestWb
;
3505 state
->NtransSig
= LOW
;
3506 if (StoreWord (state
, instr
, lhs
))
3507 LSBase
= lhs
- LSRegRHS
;
3508 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3511 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
3516 && handle_v6_insn (state
, instr
))
3519 ARMul_UndefInstr (state
, instr
);
3522 UNDEF_LSRBaseEQOffWb
;
3523 UNDEF_LSRBaseEQDestWb
;
3527 temp
= lhs
- LSRegRHS
;
3528 state
->NtransSig
= LOW
;
3529 if (LoadWord (state
, instr
, lhs
))
3531 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3534 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
3539 && handle_v6_insn (state
, instr
))
3542 ARMul_UndefInstr (state
, instr
);
3545 UNDEF_LSRBaseEQOffWb
;
3546 UNDEF_LSRBaseEQDestWb
;
3550 if (StoreByte (state
, instr
, lhs
))
3551 LSBase
= lhs
- LSRegRHS
;
3554 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
3559 && handle_v6_insn (state
, instr
))
3562 ARMul_UndefInstr (state
, instr
);
3565 UNDEF_LSRBaseEQOffWb
;
3566 UNDEF_LSRBaseEQDestWb
;
3570 temp
= lhs
- LSRegRHS
;
3571 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3575 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
3580 && handle_v6_insn (state
, instr
))
3583 ARMul_UndefInstr (state
, instr
);
3586 UNDEF_LSRBaseEQOffWb
;
3587 UNDEF_LSRBaseEQDestWb
;
3591 state
->NtransSig
= LOW
;
3592 if (StoreByte (state
, instr
, lhs
))
3593 LSBase
= lhs
- LSRegRHS
;
3594 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3597 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
3602 && handle_v6_insn (state
, instr
))
3605 ARMul_UndefInstr (state
, instr
);
3608 UNDEF_LSRBaseEQOffWb
;
3609 UNDEF_LSRBaseEQDestWb
;
3613 temp
= lhs
- LSRegRHS
;
3614 state
->NtransSig
= LOW
;
3615 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3617 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3620 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
3625 && handle_v6_insn (state
, instr
))
3628 ARMul_UndefInstr (state
, instr
);
3631 UNDEF_LSRBaseEQOffWb
;
3632 UNDEF_LSRBaseEQDestWb
;
3636 if (StoreWord (state
, instr
, lhs
))
3637 LSBase
= lhs
+ LSRegRHS
;
3640 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
3645 && handle_v6_insn (state
, instr
))
3648 ARMul_UndefInstr (state
, instr
);
3651 UNDEF_LSRBaseEQOffWb
;
3652 UNDEF_LSRBaseEQDestWb
;
3656 temp
= lhs
+ LSRegRHS
;
3657 if (LoadWord (state
, instr
, lhs
))
3661 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
3666 && handle_v6_insn (state
, instr
))
3669 ARMul_UndefInstr (state
, instr
);
3672 UNDEF_LSRBaseEQOffWb
;
3673 UNDEF_LSRBaseEQDestWb
;
3677 state
->NtransSig
= LOW
;
3678 if (StoreWord (state
, instr
, lhs
))
3679 LSBase
= lhs
+ LSRegRHS
;
3680 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3683 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
3688 && handle_v6_insn (state
, instr
))
3691 ARMul_UndefInstr (state
, instr
);
3694 UNDEF_LSRBaseEQOffWb
;
3695 UNDEF_LSRBaseEQDestWb
;
3699 temp
= lhs
+ LSRegRHS
;
3700 state
->NtransSig
= LOW
;
3701 if (LoadWord (state
, instr
, lhs
))
3703 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3706 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
3711 && handle_v6_insn (state
, instr
))
3714 ARMul_UndefInstr (state
, instr
);
3717 UNDEF_LSRBaseEQOffWb
;
3718 UNDEF_LSRBaseEQDestWb
;
3722 if (StoreByte (state
, instr
, lhs
))
3723 LSBase
= lhs
+ LSRegRHS
;
3726 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
3731 && handle_v6_insn (state
, instr
))
3734 ARMul_UndefInstr (state
, instr
);
3737 UNDEF_LSRBaseEQOffWb
;
3738 UNDEF_LSRBaseEQDestWb
;
3742 temp
= lhs
+ LSRegRHS
;
3743 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3747 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3752 && handle_v6_insn (state
, instr
))
3755 ARMul_UndefInstr (state
, instr
);
3758 UNDEF_LSRBaseEQOffWb
;
3759 UNDEF_LSRBaseEQDestWb
;
3763 state
->NtransSig
= LOW
;
3764 if (StoreByte (state
, instr
, lhs
))
3765 LSBase
= lhs
+ LSRegRHS
;
3766 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3769 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3774 && handle_v6_insn (state
, instr
))
3777 ARMul_UndefInstr (state
, instr
);
3780 UNDEF_LSRBaseEQOffWb
;
3781 UNDEF_LSRBaseEQDestWb
;
3785 temp
= lhs
+ LSRegRHS
;
3786 state
->NtransSig
= LOW
;
3787 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3789 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3793 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3798 && handle_v6_insn (state
, instr
))
3801 ARMul_UndefInstr (state
, instr
);
3804 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
3807 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3812 && handle_v6_insn (state
, instr
))
3815 ARMul_UndefInstr (state
, instr
);
3818 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
3821 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3826 && handle_v6_insn (state
, instr
))
3829 ARMul_UndefInstr (state
, instr
);
3832 UNDEF_LSRBaseEQOffWb
;
3833 UNDEF_LSRBaseEQDestWb
;
3836 temp
= LHS
- LSRegRHS
;
3837 if (StoreWord (state
, instr
, temp
))
3841 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3846 && handle_v6_insn (state
, instr
))
3849 ARMul_UndefInstr (state
, instr
);
3852 UNDEF_LSRBaseEQOffWb
;
3853 UNDEF_LSRBaseEQDestWb
;
3856 temp
= LHS
- LSRegRHS
;
3857 if (LoadWord (state
, instr
, temp
))
3861 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3866 && handle_v6_insn (state
, instr
))
3869 ARMul_UndefInstr (state
, instr
);
3872 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
3875 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3880 && handle_v6_insn (state
, instr
))
3883 ARMul_UndefInstr (state
, instr
);
3886 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
3889 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3894 && handle_v6_insn (state
, instr
))
3897 ARMul_UndefInstr (state
, instr
);
3900 UNDEF_LSRBaseEQOffWb
;
3901 UNDEF_LSRBaseEQDestWb
;
3904 temp
= LHS
- LSRegRHS
;
3905 if (StoreByte (state
, instr
, temp
))
3909 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3914 && handle_v6_insn (state
, instr
))
3917 ARMul_UndefInstr (state
, instr
);
3920 UNDEF_LSRBaseEQOffWb
;
3921 UNDEF_LSRBaseEQDestWb
;
3924 temp
= LHS
- LSRegRHS
;
3925 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3929 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3934 && handle_v6_insn (state
, instr
))
3937 ARMul_UndefInstr (state
, instr
);
3940 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
3943 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
3948 && handle_v6_insn (state
, instr
))
3951 ARMul_UndefInstr (state
, instr
);
3954 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
3957 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
3962 && handle_v6_insn (state
, instr
))
3965 ARMul_UndefInstr (state
, instr
);
3968 UNDEF_LSRBaseEQOffWb
;
3969 UNDEF_LSRBaseEQDestWb
;
3972 temp
= LHS
+ LSRegRHS
;
3973 if (StoreWord (state
, instr
, temp
))
3977 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
3982 && handle_v6_insn (state
, instr
))
3985 ARMul_UndefInstr (state
, instr
);
3988 UNDEF_LSRBaseEQOffWb
;
3989 UNDEF_LSRBaseEQDestWb
;
3992 temp
= LHS
+ LSRegRHS
;
3993 if (LoadWord (state
, instr
, temp
))
3997 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
4002 && handle_v6_insn (state
, instr
))
4005 ARMul_UndefInstr (state
, instr
);
4008 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
4011 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
4016 && handle_v6_insn (state
, instr
))
4019 ARMul_UndefInstr (state
, instr
);
4022 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
4025 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
4030 && handle_v6_insn (state
, instr
))
4033 ARMul_UndefInstr (state
, instr
);
4036 UNDEF_LSRBaseEQOffWb
;
4037 UNDEF_LSRBaseEQDestWb
;
4040 temp
= LHS
+ LSRegRHS
;
4041 if (StoreByte (state
, instr
, temp
))
4045 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
4048 /* Check for the special breakpoint opcode.
4049 This value should correspond to the value defined
4050 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
4051 if (BITS (0, 19) == 0xfdefe)
4053 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
4054 ARMul_Abort (state
, ARMul_SWIV
);
4057 else if (state
->is_v6
4058 && handle_v6_insn (state
, instr
))
4062 ARMul_UndefInstr (state
, instr
);
4065 UNDEF_LSRBaseEQOffWb
;
4066 UNDEF_LSRBaseEQDestWb
;
4069 temp
= LHS
+ LSRegRHS
;
4070 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
4075 /* Multiple Data Transfer Instructions. */
4077 case 0x80: /* Store, No WriteBack, Post Dec. */
4078 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4081 case 0x81: /* Load, No WriteBack, Post Dec. */
4082 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4085 case 0x82: /* Store, WriteBack, Post Dec. */
4086 temp
= LSBase
- LSMNumRegs
;
4087 STOREMULT (instr
, temp
+ 4L, temp
);
4090 case 0x83: /* Load, WriteBack, Post Dec. */
4091 temp
= LSBase
- LSMNumRegs
;
4092 LOADMULT (instr
, temp
+ 4L, temp
);
4095 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
4096 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4099 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
4100 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4103 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
4104 temp
= LSBase
- LSMNumRegs
;
4105 STORESMULT (instr
, temp
+ 4L, temp
);
4108 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
4109 temp
= LSBase
- LSMNumRegs
;
4110 LOADSMULT (instr
, temp
+ 4L, temp
);
4113 case 0x88: /* Store, No WriteBack, Post Inc. */
4114 STOREMULT (instr
, LSBase
, 0L);
4117 case 0x89: /* Load, No WriteBack, Post Inc. */
4118 LOADMULT (instr
, LSBase
, 0L);
4121 case 0x8a: /* Store, WriteBack, Post Inc. */
4123 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
4126 case 0x8b: /* Load, WriteBack, Post Inc. */
4128 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
4131 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
4132 STORESMULT (instr
, LSBase
, 0L);
4135 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
4136 LOADSMULT (instr
, LSBase
, 0L);
4139 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
4141 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
4144 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
4146 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
4149 case 0x90: /* Store, No WriteBack, Pre Dec. */
4150 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4153 case 0x91: /* Load, No WriteBack, Pre Dec. */
4154 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4157 case 0x92: /* Store, WriteBack, Pre Dec. */
4158 temp
= LSBase
- LSMNumRegs
;
4159 STOREMULT (instr
, temp
, temp
);
4162 case 0x93: /* Load, WriteBack, Pre Dec. */
4163 temp
= LSBase
- LSMNumRegs
;
4164 LOADMULT (instr
, temp
, temp
);
4167 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
4168 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4171 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
4172 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4175 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
4176 temp
= LSBase
- LSMNumRegs
;
4177 STORESMULT (instr
, temp
, temp
);
4180 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
4181 temp
= LSBase
- LSMNumRegs
;
4182 LOADSMULT (instr
, temp
, temp
);
4185 case 0x98: /* Store, No WriteBack, Pre Inc. */
4186 STOREMULT (instr
, LSBase
+ 4L, 0L);
4189 case 0x99: /* Load, No WriteBack, Pre Inc. */
4190 LOADMULT (instr
, LSBase
+ 4L, 0L);
4193 case 0x9a: /* Store, WriteBack, Pre Inc. */
4195 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4198 case 0x9b: /* Load, WriteBack, Pre Inc. */
4200 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4203 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
4204 STORESMULT (instr
, LSBase
+ 4L, 0L);
4207 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
4208 LOADSMULT (instr
, LSBase
+ 4L, 0L);
4211 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
4213 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4216 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
4218 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4222 /* Branch forward. */
4231 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4236 /* Branch backward. */
4245 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4249 /* Branch and Link forward. */
4258 /* Put PC into Link. */
4260 state
->Reg
[14] = pc
+ 4;
4262 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4264 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4267 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4270 /* Branch and Link backward. */
4279 /* Put PC into Link. */
4281 state
->Reg
[14] = pc
+ 4;
4283 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4285 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4288 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4291 /* Co-Processor Data Transfers. */
4295 if (CPNum
== 10 || CPNum
== 11)
4296 handle_VFP_move (state
, instr
);
4297 /* Reading from R15 is UNPREDICTABLE. */
4298 else if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
4299 ARMul_UndefInstr (state
, instr
);
4300 /* Is access to coprocessor 0 allowed ? */
4301 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4302 ARMul_UndefInstr (state
, instr
);
4303 /* Special treatment for XScale coprocessors. */
4304 else if (state
->is_XScale
)
4306 /* Only opcode 0 is supported. */
4307 if (BITS (4, 7) != 0x00)
4308 ARMul_UndefInstr (state
, instr
);
4309 /* Only coporcessor 0 is supported. */
4310 else if (CPNum
!= 0x00)
4311 ARMul_UndefInstr (state
, instr
);
4312 /* Only accumulator 0 is supported. */
4313 else if (BITS (0, 3) != 0x00)
4314 ARMul_UndefInstr (state
, instr
);
4317 /* XScale MAR insn. Move two registers into accumulator. */
4318 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
4319 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
4323 /* FIXME: Not sure what to do for other v5 processors. */
4324 ARMul_UndefInstr (state
, instr
);
4329 case 0xc0: /* Store , No WriteBack , Post Dec. */
4330 ARMul_STC (state
, instr
, LHS
);
4336 if (CPNum
== 10 || CPNum
== 11)
4337 handle_VFP_move (state
, instr
);
4338 /* Writes to R15 are UNPREDICATABLE. */
4339 else if (DESTReg
== 15 || LHSReg
== 15)
4340 ARMul_UndefInstr (state
, instr
);
4341 /* Is access to the coprocessor allowed ? */
4342 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4343 ARMul_UndefInstr (state
, instr
);
4344 /* Special handling for XScale coprcoessors. */
4345 else if (state
->is_XScale
)
4347 /* Only opcode 0 is supported. */
4348 if (BITS (4, 7) != 0x00)
4349 ARMul_UndefInstr (state
, instr
);
4350 /* Only coprocessor 0 is supported. */
4351 else if (CPNum
!= 0x00)
4352 ARMul_UndefInstr (state
, instr
);
4353 /* Only accumulator 0 is supported. */
4354 else if (BITS (0, 3) != 0x00)
4355 ARMul_UndefInstr (state
, instr
);
4358 /* XScale MRA insn. Move accumulator into two registers. */
4359 ARMword t1
= (state
->Accumulator
>> 32) & 255;
4364 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
4365 state
->Reg
[BITS (16, 19)] = t1
;
4370 /* FIXME: Not sure what to do for other v5 processors. */
4371 ARMul_UndefInstr (state
, instr
);
4376 case 0xc1: /* Load , No WriteBack , Post Dec. */
4377 ARMul_LDC (state
, instr
, LHS
);
4381 case 0xc6: /* Store , WriteBack , Post Dec. */
4383 state
->Base
= lhs
- LSCOff
;
4384 ARMul_STC (state
, instr
, lhs
);
4388 case 0xc7: /* Load , WriteBack , Post Dec. */
4390 state
->Base
= lhs
- LSCOff
;
4391 ARMul_LDC (state
, instr
, lhs
);
4395 case 0xcc: /* Store , No WriteBack , Post Inc. */
4396 ARMul_STC (state
, instr
, LHS
);
4400 case 0xcd: /* Load , No WriteBack , Post Inc. */
4401 ARMul_LDC (state
, instr
, LHS
);
4405 case 0xce: /* Store , WriteBack , Post Inc. */
4407 state
->Base
= lhs
+ LSCOff
;
4408 ARMul_STC (state
, instr
, LHS
);
4412 case 0xcf: /* Load , WriteBack , Post Inc. */
4414 state
->Base
= lhs
+ LSCOff
;
4415 ARMul_LDC (state
, instr
, LHS
);
4419 case 0xd4: /* Store , No WriteBack , Pre Dec. */
4420 ARMul_STC (state
, instr
, LHS
- LSCOff
);
4424 case 0xd5: /* Load , No WriteBack , Pre Dec. */
4425 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
4429 case 0xd6: /* Store , WriteBack , Pre Dec. */
4432 ARMul_STC (state
, instr
, lhs
);
4436 case 0xd7: /* Load , WriteBack , Pre Dec. */
4439 ARMul_LDC (state
, instr
, lhs
);
4443 case 0xdc: /* Store , No WriteBack , Pre Inc. */
4444 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
4448 case 0xdd: /* Load , No WriteBack , Pre Inc. */
4449 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
4453 case 0xde: /* Store , WriteBack , Pre Inc. */
4456 ARMul_STC (state
, instr
, lhs
);
4460 case 0xdf: /* Load , WriteBack , Pre Inc. */
4463 ARMul_LDC (state
, instr
, lhs
);
4467 /* Co-Processor Register Transfers (MCR) and Data Ops. */
4470 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4472 ARMul_UndefInstr (state
, instr
);
4475 if (state
->is_XScale
)
4476 switch (BITS (18, 19))
4479 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4481 /* XScale MIA instruction. Signed multiplication of
4482 two 32 bit values and addition to 40 bit accumulator. */
4483 ARMsdword Rm
= state
->Reg
[MULLHSReg
];
4484 ARMsdword Rs
= state
->Reg
[MULACCReg
];
4490 state
->Accumulator
+= Rm
* Rs
;
4496 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4498 /* XScale MIAPH instruction. */
4499 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
4500 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
4501 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
4502 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
4517 state
->Accumulator
+= t5
;
4522 state
->Accumulator
+= t5
;
4528 if (BITS (4, 11) == 1)
4530 /* XScale MIAxy instruction. */
4536 t1
= state
->Reg
[MULLHSReg
] >> 16;
4538 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
4541 t2
= state
->Reg
[MULACCReg
] >> 16;
4543 t2
= state
->Reg
[MULACCReg
] & 0xffff;
4553 state
->Accumulator
+= t5
;
4572 if (CPNum
== 10 || CPNum
== 11)
4573 handle_VFP_move (state
, instr
);
4575 else if (DESTReg
== 15)
4579 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
4581 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
4582 ((state
->Reg
[15] + isize
) & R15PCBITS
));
4586 ARMul_MCR (state
, instr
, DEST
);
4590 ARMul_CDP (state
, instr
);
4594 /* Co-Processor Register Transfers (MRC) and Data Ops. */
4605 if (CPNum
== 10 || CPNum
== 11)
4607 switch (BITS (20, 27))
4610 if (BITS (16, 19) == 0x1
4611 && BITS (0, 11) == 0xA10)
4616 ARMul_SetCPSR (state
, (state
->FPSCR
& 0xF0000000)
4617 | (ARMul_GetCPSR (state
) & 0x0FFFFFFF));
4620 fprintf (stderr
, " VFP: VMRS: set flags to %c%c%c%c\n",
4621 ARMul_GetCPSR (state
) & NBIT
? 'N' : '-',
4622 ARMul_GetCPSR (state
) & ZBIT
? 'Z' : '-',
4623 ARMul_GetCPSR (state
) & CBIT
? 'C' : '-',
4624 ARMul_GetCPSR (state
) & VBIT
? 'V' : '-');
4628 state
->Reg
[DESTReg
] = state
->FPSCR
;
4631 fprintf (stderr
, " VFP: VMRS: r%d = %x\n", DESTReg
, state
->Reg
[DESTReg
]);
4635 fprintf (stderr
, "SIM: VFP: Unimplemented: Compare op\n");
4640 /* VMOV reg <-> single precision. */
4641 if (BITS (0,6) != 0x10 || BITS (8,11) != 0xA)
4642 fprintf (stderr
, "SIM: VFP: Unimplemented: move op\n");
4644 state
->Reg
[BITS (12, 15)] = VFP_uword (BITS (16, 19) << 1 | BIT (7));
4646 VFP_uword (BITS (16, 19) << 1 | BIT (7)) = state
->Reg
[BITS (12, 15)];
4650 fprintf (stderr
, "SIM: VFP: Unimplemented: CDP op\n");
4657 temp
= ARMul_MRC (state
, instr
);
4660 ASSIGNN ((temp
& NBIT
) != 0);
4661 ASSIGNZ ((temp
& ZBIT
) != 0);
4662 ASSIGNC ((temp
& CBIT
) != 0);
4663 ASSIGNV ((temp
& VBIT
) != 0);
4671 ARMul_CDP (state
, instr
);
4675 /* SWI instruction. */
4692 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
4694 /* A prefetch abort. */
4695 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
4696 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
4700 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
4701 ARMul_Abort (state
, ARMul_SWIV
);
4711 if (state
->Emulate
== ONCE
)
4712 state
->Emulate
= STOP
;
4713 /* If we have changed mode, allow the PC to advance before stopping. */
4714 else if (state
->Emulate
== CHANGEMODE
)
4716 else if (state
->Emulate
!= RUN
)
4719 while (!stop_simulator
);
4721 state
->decoded
= decoded
;
4722 state
->loaded
= loaded
;
4728 /* This routine evaluates most Data Processing register RHS's with the S
4729 bit clear. It is intended to be called from the macro DPRegRHS, which
4730 filters the common case of an unshifted register with in line code. */
4733 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
4735 ARMword shamt
, base
;
4740 /* Shift amount in a register. */
4745 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4748 base
= state
->Reg
[base
];
4749 ARMul_Icycles (state
, 1, 0L);
4750 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4751 switch ((int) BITS (5, 6))
4756 else if (shamt
>= 32)
4759 return (base
<< shamt
);
4763 else if (shamt
>= 32)
4766 return (base
>> shamt
);
4770 else if (shamt
>= 32)
4771 return ((ARMword
) ((ARMsword
) base
>> 31L));
4773 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4779 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4784 /* Shift amount is a constant. */
4787 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4790 base
= state
->Reg
[base
];
4791 shamt
= BITS (7, 11);
4792 switch ((int) BITS (5, 6))
4795 return (base
<< shamt
);
4800 return (base
>> shamt
);
4803 return ((ARMword
) ((ARMsword
) base
>> 31L));
4805 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4809 return ((base
>> 1) | (CFLAG
<< 31));
4811 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4818 /* This routine evaluates most Logical Data Processing register RHS's
4819 with the S bit set. It is intended to be called from the macro
4820 DPSRegRHS, which filters the common case of an unshifted register
4821 with in line code. */
4824 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
4826 ARMword shamt
, base
;
4831 /* Shift amount in a register. */
4836 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4839 base
= state
->Reg
[base
];
4840 ARMul_Icycles (state
, 1, 0L);
4841 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4842 switch ((int) BITS (5, 6))
4847 else if (shamt
== 32)
4852 else if (shamt
> 32)
4859 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4860 return (base
<< shamt
);
4865 else if (shamt
== 32)
4867 ASSIGNC (base
>> 31);
4870 else if (shamt
> 32)
4877 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4878 return (base
>> shamt
);
4883 else if (shamt
>= 32)
4885 ASSIGNC (base
>> 31L);
4886 return ((ARMword
) ((ARMsword
) base
>> 31L));
4890 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4891 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4899 ASSIGNC (base
>> 31);
4904 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4905 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4911 /* Shift amount is a constant. */
4914 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4917 base
= state
->Reg
[base
];
4918 shamt
= BITS (7, 11);
4920 switch ((int) BITS (5, 6))
4923 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4924 return (base
<< shamt
);
4928 ASSIGNC (base
>> 31);
4933 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4934 return (base
>> shamt
);
4939 ASSIGNC (base
>> 31L);
4940 return ((ARMword
) ((ARMsword
) base
>> 31L));
4944 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4945 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4953 return ((base
>> 1) | (shamt
<< 31));
4957 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4958 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4966 /* This routine handles writes to register 15 when the S bit is not set. */
4969 WriteR15 (ARMul_State
* state
, ARMword src
)
4971 /* The ARM documentation states that the two least significant bits
4972 are discarded when setting PC, except in the cases handled by
4973 WriteR15Branch() below. It's probably an oversight: in THUMB
4974 mode, the second least significant bit should probably not be
4984 state
->Reg
[15] = src
& PCBITS
;
4986 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
4987 ARMul_R15Altered (state
);
4992 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4995 /* This routine handles writes to register 15 when the S bit is set. */
4998 WriteSR15 (ARMul_State
* state
, ARMword src
)
5001 if (state
->Bank
> 0)
5003 state
->Cpsr
= state
->Spsr
[state
->Bank
];
5004 ARMul_CPSRAltered (state
);
5012 state
->Reg
[15] = src
& PCBITS
;
5016 /* ARMul_R15Altered would have to support it. */
5022 if (state
->Bank
== USERBANK
)
5023 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
5025 state
->Reg
[15] = src
;
5027 ARMul_R15Altered (state
);
5031 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5034 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
5035 will switch to Thumb mode if the least significant bit is set. */
5038 WriteR15Branch (ARMul_State
* state
, ARMword src
)
5045 state
->Reg
[15] = src
& 0xfffffffe;
5050 state
->Reg
[15] = src
& 0xfffffffc;
5054 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5056 WriteR15 (state
, src
);
5060 /* Before ARM_v5 LDR and LDM of pc did not change mode. */
5063 WriteR15Load (ARMul_State
* state
, ARMword src
)
5066 WriteR15Branch (state
, src
);
5068 WriteR15 (state
, src
);
5071 /* This routine evaluates most Load and Store register RHS's. It is
5072 intended to be called from the macro LSRegRHS, which filters the
5073 common case of an unshifted register with in line code. */
5076 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
5078 ARMword shamt
, base
;
5083 /* Now forbidden, but ... */
5084 base
= ECC
| ER15INT
| R15PC
| EMODE
;
5087 base
= state
->Reg
[base
];
5089 shamt
= BITS (7, 11);
5090 switch ((int) BITS (5, 6))
5093 return (base
<< shamt
);
5098 return (base
>> shamt
);
5101 return ((ARMword
) ((ARMsword
) base
>> 31L));
5103 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
5107 return ((base
>> 1) | (CFLAG
<< 31));
5109 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
5116 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
5119 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
5126 /* Now forbidden, but ... */
5127 return ECC
| ER15INT
| R15PC
| EMODE
;
5129 return state
->Reg
[RHSReg
];
5133 return BITS (0, 3) | (BITS (8, 11) << 4);
5136 /* This function does the work of loading a word for a LDR instruction. */
5139 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5145 if (ADDREXCEPT (address
))
5146 INTERNALABORT (address
);
5149 dest
= ARMul_LoadWordN (state
, address
);
5154 return state
->lateabtSig
;
5157 dest
= ARMul_Align (state
, address
, dest
);
5159 ARMul_Icycles (state
, 1, 0L);
5161 return (DESTReg
!= LHSReg
);
5165 /* This function does the work of loading a halfword. */
5168 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
5175 if (ADDREXCEPT (address
))
5176 INTERNALABORT (address
);
5178 dest
= ARMul_LoadHalfWord (state
, address
);
5182 return state
->lateabtSig
;
5186 if (dest
& 1 << (16 - 1))
5187 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
5190 ARMul_Icycles (state
, 1, 0L);
5191 return (DESTReg
!= LHSReg
);
5196 /* This function does the work of loading a byte for a LDRB instruction. */
5199 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
5205 if (ADDREXCEPT (address
))
5206 INTERNALABORT (address
);
5208 dest
= ARMul_LoadByte (state
, address
);
5212 return state
->lateabtSig
;
5216 if (dest
& 1 << (8 - 1))
5217 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
5220 ARMul_Icycles (state
, 1, 0L);
5222 return (DESTReg
!= LHSReg
);
5225 /* This function does the work of loading two words for a LDRD instruction. */
5228 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
5232 ARMword write_back
= BIT (21);
5233 ARMword immediate
= BIT (22);
5234 ARMword add_to_base
= BIT (23);
5235 ARMword pre_indexed
= BIT (24);
5245 /* If the writeback bit is set, the pre-index bit must be clear. */
5246 if (write_back
&& ! pre_indexed
)
5248 ARMul_UndefInstr (state
, instr
);
5252 /* Extract the base address register. */
5255 /* Extract the destination register and check it. */
5258 /* Destination register must be even. */
5260 /* Destination register cannot be LR. */
5261 || (dest_reg
== 14))
5263 ARMul_UndefInstr (state
, instr
);
5267 /* Compute the base address. */
5268 base
= state
->Reg
[addr_reg
];
5270 /* Compute the offset. */
5271 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5273 /* Compute the sum of the two. */
5275 sum
= base
+ offset
;
5277 sum
= base
- offset
;
5279 /* If this is a pre-indexed mode use the sum. */
5285 if (state
->is_v6
&& (addr
& 0x3) == 0)
5286 /* Word alignment is enough for v6. */
5288 /* The address must be aligned on a 8 byte boundary. */
5289 else if (addr
& 0x7)
5292 ARMul_DATAABORT (addr
);
5294 ARMul_UndefInstr (state
, instr
);
5299 /* For pre indexed or post indexed addressing modes,
5300 check that the destination registers do not overlap
5301 the address registers. */
5302 if ((! pre_indexed
|| write_back
)
5303 && ( addr_reg
== dest_reg
5304 || addr_reg
== dest_reg
+ 1))
5306 ARMul_UndefInstr (state
, instr
);
5310 /* Load the words. */
5311 value1
= ARMul_LoadWordN (state
, addr
);
5312 value2
= ARMul_LoadWordN (state
, addr
+ 4);
5314 /* Check for data aborts. */
5321 ARMul_Icycles (state
, 2, 0L);
5323 /* Store the values. */
5324 state
->Reg
[dest_reg
] = value1
;
5325 state
->Reg
[dest_reg
+ 1] = value2
;
5327 /* Do the post addressing and writeback. */
5331 if (! pre_indexed
|| write_back
)
5332 state
->Reg
[addr_reg
] = addr
;
5335 /* This function does the work of storing two words for a STRD instruction. */
5338 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
5342 ARMword write_back
= BIT (21);
5343 ARMword immediate
= BIT (22);
5344 ARMword add_to_base
= BIT (23);
5345 ARMword pre_indexed
= BIT (24);
5353 /* If the writeback bit is set, the pre-index bit must be clear. */
5354 if (write_back
&& ! pre_indexed
)
5356 ARMul_UndefInstr (state
, instr
);
5360 /* Extract the base address register. */
5363 /* Base register cannot be PC. */
5366 ARMul_UndefInstr (state
, instr
);
5370 /* Extract the source register. */
5373 /* Source register must be even. */
5376 ARMul_UndefInstr (state
, instr
);
5380 /* Compute the base address. */
5381 base
= state
->Reg
[addr_reg
];
5383 /* Compute the offset. */
5384 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5386 /* Compute the sum of the two. */
5388 sum
= base
+ offset
;
5390 sum
= base
- offset
;
5392 /* If this is a pre-indexed mode use the sum. */
5398 /* The address must be aligned on a 8 byte boundary. */
5402 ARMul_DATAABORT (addr
);
5404 ARMul_UndefInstr (state
, instr
);
5409 /* For pre indexed or post indexed addressing modes,
5410 check that the destination registers do not overlap
5411 the address registers. */
5412 if ((! pre_indexed
|| write_back
)
5413 && ( addr_reg
== src_reg
5414 || addr_reg
== src_reg
+ 1))
5416 ARMul_UndefInstr (state
, instr
);
5420 /* Load the words. */
5421 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
5422 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
5430 /* Do the post addressing and writeback. */
5434 if (! pre_indexed
|| write_back
)
5435 state
->Reg
[addr_reg
] = addr
;
5438 /* This function does the work of storing a word from a STR instruction. */
5441 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5446 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5449 ARMul_StoreWordN (state
, address
, DEST
);
5451 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5453 INTERNALABORT (address
);
5454 (void) ARMul_LoadWordN (state
, address
);
5457 ARMul_StoreWordN (state
, address
, DEST
);
5462 return state
->lateabtSig
;
5468 /* This function does the work of storing a byte for a STRH instruction. */
5471 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5477 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5481 ARMul_StoreHalfWord (state
, address
, DEST
);
5483 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5485 INTERNALABORT (address
);
5486 (void) ARMul_LoadHalfWord (state
, address
);
5489 ARMul_StoreHalfWord (state
, address
, DEST
);
5495 return state
->lateabtSig
;
5502 /* This function does the work of storing a byte for a STRB instruction. */
5505 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
5510 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5513 ARMul_StoreByte (state
, address
, DEST
);
5515 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5517 INTERNALABORT (address
);
5518 (void) ARMul_LoadByte (state
, address
);
5521 ARMul_StoreByte (state
, address
, DEST
);
5526 return state
->lateabtSig
;
5532 /* This function does the work of loading the registers listed in an LDM
5533 instruction, when the S bit is clear. The code here is always increment
5534 after, it's up to the caller to get the input address correct and to
5535 handle base register modification. */
5538 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
5544 UNDEF_LSMBaseInListWb
;
5547 if (ADDREXCEPT (address
))
5548 INTERNALABORT (address
);
5550 if (BIT (21) && LHSReg
!= 15)
5553 /* N cycle first. */
5554 for (temp
= 0; !BIT (temp
); temp
++)
5557 dest
= ARMul_LoadWordN (state
, address
);
5559 if (!state
->abortSig
&& !state
->Aborted
)
5560 state
->Reg
[temp
++] = dest
;
5561 else if (!state
->Aborted
)
5563 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5564 state
->Aborted
= ARMul_DataAbortV
;
5567 /* S cycles from here on. */
5568 for (; temp
< 16; temp
++)
5571 /* Load this register. */
5573 dest
= ARMul_LoadWordS (state
, address
);
5575 if (!state
->abortSig
&& !state
->Aborted
)
5576 state
->Reg
[temp
] = dest
;
5577 else if (!state
->Aborted
)
5579 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5580 state
->Aborted
= ARMul_DataAbortV
;
5584 if (BIT (15) && !state
->Aborted
)
5585 /* PC is in the reg list. */
5586 WriteR15Load (state
, PC
);
5588 /* To write back the final register. */
5589 ARMul_Icycles (state
, 1, 0L);
5593 if (BIT (21) && LHSReg
!= 15)
5599 /* This function does the work of loading the registers listed in an LDM
5600 instruction, when the S bit is set. The code here is always increment
5601 after, it's up to the caller to get the input address correct and to
5602 handle base register modification. */
5605 LoadSMult (ARMul_State
* state
,
5614 UNDEF_LSMBaseInListWb
;
5619 if (ADDREXCEPT (address
))
5620 INTERNALABORT (address
);
5623 if (BIT (21) && LHSReg
!= 15)
5626 if (!BIT (15) && state
->Bank
!= USERBANK
)
5628 /* Temporary reg bank switch. */
5629 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5630 UNDEF_LSMUserBankWb
;
5633 /* N cycle first. */
5634 for (temp
= 0; !BIT (temp
); temp
++)
5637 dest
= ARMul_LoadWordN (state
, address
);
5639 if (!state
->abortSig
)
5640 state
->Reg
[temp
++] = dest
;
5641 else if (!state
->Aborted
)
5643 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5644 state
->Aborted
= ARMul_DataAbortV
;
5647 /* S cycles from here on. */
5648 for (; temp
< 16; temp
++)
5651 /* Load this register. */
5653 dest
= ARMul_LoadWordS (state
, address
);
5655 if (!state
->abortSig
&& !state
->Aborted
)
5656 state
->Reg
[temp
] = dest
;
5657 else if (!state
->Aborted
)
5659 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5660 state
->Aborted
= ARMul_DataAbortV
;
5664 if (BIT (15) && !state
->Aborted
)
5666 /* PC is in the reg list. */
5668 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5670 state
->Cpsr
= GETSPSR (state
->Bank
);
5671 ARMul_CPSRAltered (state
);
5674 WriteR15 (state
, PC
);
5676 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
5678 /* Protect bits in user mode. */
5679 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
5680 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
5681 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
5682 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
5685 ARMul_R15Altered (state
);
5691 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5692 /* Restore the correct bank. */
5693 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5695 /* To write back the final register. */
5696 ARMul_Icycles (state
, 1, 0L);
5700 if (BIT (21) && LHSReg
!= 15)
5707 /* This function does the work of storing the registers listed in an STM
5708 instruction, when the S bit is clear. The code here is always increment
5709 after, it's up to the caller to get the input address correct and to
5710 handle base register modification. */
5713 StoreMult (ARMul_State
* state
,
5722 UNDEF_LSMBaseInListWb
;
5725 /* N-cycle, increment the PC and update the NextInstr state. */
5729 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5730 INTERNALABORT (address
);
5736 /* N cycle first. */
5737 for (temp
= 0; !BIT (temp
); temp
++)
5741 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5745 (void) ARMul_LoadWordN (state
, address
);
5747 /* Fake the Stores as Loads. */
5748 for (; temp
< 16; temp
++)
5751 /* Save this register. */
5753 (void) ARMul_LoadWordS (state
, address
);
5756 if (BIT (21) && LHSReg
!= 15)
5762 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5765 if (state
->abortSig
&& !state
->Aborted
)
5767 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5768 state
->Aborted
= ARMul_DataAbortV
;
5771 if (BIT (21) && LHSReg
!= 15)
5774 /* S cycles from here on. */
5775 for (; temp
< 16; temp
++)
5778 /* Save this register. */
5781 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5783 if (state
->abortSig
&& !state
->Aborted
)
5785 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5786 state
->Aborted
= ARMul_DataAbortV
;
5794 /* This function does the work of storing the registers listed in an STM
5795 instruction when the S bit is set. The code here is always increment
5796 after, it's up to the caller to get the input address correct and to
5797 handle base register modification. */
5800 StoreSMult (ARMul_State
* state
,
5809 UNDEF_LSMBaseInListWb
;
5814 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5815 INTERNALABORT (address
);
5821 if (state
->Bank
!= USERBANK
)
5823 /* Force User Bank. */
5824 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5825 UNDEF_LSMUserBankWb
;
5828 for (temp
= 0; !BIT (temp
); temp
++)
5829 ; /* N cycle first. */
5832 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5836 (void) ARMul_LoadWordN (state
, address
);
5838 for (; temp
< 16; temp
++)
5839 /* Fake the Stores as Loads. */
5842 /* Save this register. */
5845 (void) ARMul_LoadWordS (state
, address
);
5848 if (BIT (21) && LHSReg
!= 15)
5855 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5858 if (state
->abortSig
&& !state
->Aborted
)
5860 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5861 state
->Aborted
= ARMul_DataAbortV
;
5864 /* S cycles from here on. */
5865 for (; temp
< 16; temp
++)
5868 /* Save this register. */
5871 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5873 if (state
->abortSig
&& !state
->Aborted
)
5875 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5876 state
->Aborted
= ARMul_DataAbortV
;
5880 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5881 /* Restore the correct bank. */
5882 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5884 if (BIT (21) && LHSReg
!= 15)
5891 /* This function does the work of adding two 32bit values
5892 together, and calculating if a carry has occurred. */
5895 Add32 (ARMword a1
, ARMword a2
, int *carry
)
5897 ARMword result
= (a1
+ a2
);
5898 unsigned int uresult
= (unsigned int) result
;
5899 unsigned int ua1
= (unsigned int) a1
;
5901 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5902 or (result > RdLo) then we have no carry. */
5903 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
5911 /* This function does the work of multiplying
5912 two 32bit values to give a 64bit result. */
5915 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5917 /* Operand register numbers. */
5918 int nRdHi
, nRdLo
, nRs
, nRm
;
5919 ARMword RdHi
= 0, RdLo
= 0, Rm
;
5923 nRdHi
= BITS (16, 19);
5924 nRdLo
= BITS (12, 15);
5928 /* Needed to calculate the cycle count. */
5929 Rm
= state
->Reg
[nRm
];
5931 /* Check for illegal operand combinations first. */
5938 /* Intermediate results. */
5939 ARMword lo
, mid1
, mid2
, hi
;
5941 ARMword Rs
= state
->Reg
[nRs
];
5949 /* BAD code can trigger this result. So only complain if debugging. */
5950 if (state
->Debug
&& (nRdHi
== nRm
|| nRdLo
== nRm
))
5951 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS: %d %d %d\n",
5955 /* Compute sign of result and adjust operands if necessary. */
5956 sign
= (Rm
^ Rs
) & 0x80000000;
5958 if (((ARMsword
) Rm
) < 0)
5961 if (((ARMsword
) Rs
) < 0)
5965 /* We can split the 32x32 into four 16x16 operations. This
5966 ensures that we do not lose precision on 32bit only hosts. */
5967 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
5968 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5969 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
5970 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5972 /* We now need to add all of these results together, taking
5973 care to propogate the carries from the additions. */
5974 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
5976 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
5978 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
5982 /* Negate result if necessary. */
5985 if (RdLo
== 0xFFFFFFFF)
5994 state
->Reg
[nRdLo
] = RdLo
;
5995 state
->Reg
[nRdHi
] = RdHi
;
5997 else if (state
->Debug
)
5998 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
6001 /* Ensure that both RdHi and RdLo are used to compute Z,
6002 but don't let RdLo's sign bit make it to N. */
6003 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6005 /* The cycle count depends on whether the instruction is a signed or
6006 unsigned multiply, and what bits are clear in the multiplier. */
6007 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
6008 /* Invert the bits to make the check against zero. */
6011 if ((Rm
& 0xFFFFFF00) == 0)
6013 else if ((Rm
& 0xFFFF0000) == 0)
6015 else if ((Rm
& 0xFF000000) == 0)
6023 /* This function does the work of multiplying two 32bit
6024 values and adding a 64bit value to give a 64bit result. */
6027 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
6034 nRdHi
= BITS (16, 19);
6035 nRdLo
= BITS (12, 15);
6037 RdHi
= state
->Reg
[nRdHi
];
6038 RdLo
= state
->Reg
[nRdLo
];
6040 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
6042 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
6043 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
6045 state
->Reg
[nRdLo
] = RdLo
;
6046 state
->Reg
[nRdHi
] = RdHi
;
6049 /* Ensure that both RdHi and RdLo are used to compute Z,
6050 but don't let RdLo's sign bit make it to N. */
6051 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6053 /* Extra cycle for addition. */
This page took 0.15951 seconds and 4 git commands to generate.