1 /* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3 Modifications to add arch. v4 support by <jsmith@cygnus.com>.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>. */
23 static ARMword
GetDPRegRHS (ARMul_State
*, ARMword
);
24 static ARMword
GetDPSRegRHS (ARMul_State
*, ARMword
);
25 static void WriteR15 (ARMul_State
*, ARMword
);
26 static void WriteSR15 (ARMul_State
*, ARMword
);
27 static void WriteR15Branch (ARMul_State
*, ARMword
);
28 static void WriteR15Load (ARMul_State
*, ARMword
);
29 static ARMword
GetLSRegRHS (ARMul_State
*, ARMword
);
30 static ARMword
GetLS7RHS (ARMul_State
*, ARMword
);
31 static unsigned LoadWord (ARMul_State
*, ARMword
, ARMword
);
32 static unsigned LoadHalfWord (ARMul_State
*, ARMword
, ARMword
, int);
33 static unsigned LoadByte (ARMul_State
*, ARMword
, ARMword
, int);
34 static unsigned StoreWord (ARMul_State
*, ARMword
, ARMword
);
35 static unsigned StoreHalfWord (ARMul_State
*, ARMword
, ARMword
);
36 static unsigned StoreByte (ARMul_State
*, ARMword
, ARMword
);
37 static void LoadMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
38 static void StoreMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
39 static void LoadSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
40 static void StoreSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
41 static unsigned Multiply64 (ARMul_State
*, ARMword
, int, int);
42 static unsigned MultiplyAdd64 (ARMul_State
*, ARMword
, int, int);
43 static void Handle_Load_Double (ARMul_State
*, ARMword
);
44 static void Handle_Store_Double (ARMul_State
*, ARMword
);
46 #define LUNSIGNED (0) /* unsigned operation */
47 #define LSIGNED (1) /* signed operation */
48 #define LDEFAULT (0) /* default : do nothing */
49 #define LSCC (1) /* set condition codes on result */
51 extern int stop_simulator
;
53 /* Short-hand macros for LDR/STR. */
55 /* Store post decrement writeback. */
58 if (StoreHalfWord (state, instr, lhs)) \
59 LSBase = lhs - GetLS7RHS (state, instr);
61 /* Store post increment writeback. */
64 if (StoreHalfWord (state, instr, lhs)) \
65 LSBase = lhs + GetLS7RHS (state, instr);
67 /* Store pre decrement. */
69 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
71 /* Store pre decrement writeback. */
72 #define SHPREDOWNWB() \
73 temp = LHS - GetLS7RHS (state, instr); \
74 if (StoreHalfWord (state, instr, temp)) \
77 /* Store pre increment. */
79 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
81 /* Store pre increment writeback. */
83 temp = LHS + GetLS7RHS (state, instr); \
84 if (StoreHalfWord (state, instr, temp)) \
87 /* Load post decrement writeback. */
88 #define LHPOSTDOWN() \
92 temp = lhs - GetLS7RHS (state, instr); \
94 switch (BITS (5, 6)) \
97 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
101 if (LoadByte (state, instr, lhs, LSIGNED)) \
105 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
108 case 0: /* SWP handled elsewhere. */ \
117 /* Load post increment writeback. */
122 temp = lhs + GetLS7RHS (state, instr); \
124 switch (BITS (5, 6)) \
127 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
131 if (LoadByte (state, instr, lhs, LSIGNED)) \
135 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
138 case 0: /* SWP handled elsewhere. */ \
147 /* Load pre decrement. */
148 #define LHPREDOWN() \
152 temp = LHS - GetLS7RHS (state, instr); \
153 switch (BITS (5, 6)) \
156 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
159 (void) LoadByte (state, instr, temp, LSIGNED); \
162 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
165 /* SWP handled elsewhere. */ \
174 /* Load pre decrement writeback. */
175 #define LHPREDOWNWB() \
179 temp = LHS - GetLS7RHS (state, instr); \
180 switch (BITS (5, 6)) \
183 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
187 if (LoadByte (state, instr, temp, LSIGNED)) \
191 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
195 /* SWP handled elsewhere. */ \
204 /* Load pre increment. */
209 temp = LHS + GetLS7RHS (state, instr); \
210 switch (BITS (5, 6)) \
213 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
216 (void) LoadByte (state, instr, temp, LSIGNED); \
219 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
222 /* SWP handled elsewhere. */ \
231 /* Load pre increment writeback. */
232 #define LHPREUPWB() \
236 temp = LHS + GetLS7RHS (state, instr); \
237 switch (BITS (5, 6)) \
240 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
244 if (LoadByte (state, instr, temp, LSIGNED)) \
248 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
252 /* SWP handled elsewhere. */ \
261 /* Attempt to emulate an ARMv6 instruction.
262 Returns non-zero upon success. */
266 handle_v6_insn (ARMul_State
* state
, ARMword instr
)
273 switch (BITS (20, 27))
276 case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
277 case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
278 case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
279 case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
280 case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
281 case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
282 case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
283 case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
284 case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
285 case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
286 case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
287 case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
288 case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
289 case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
291 case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
292 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
293 case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
294 case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
295 case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
296 case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
297 case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
301 /* MOVW<c> <Rd>,#<imm16>
303 instr[27,20] = 0011 0000
306 instr[11, 0] = imm12. */
308 val
= (BITS (16, 19) << 12) | BITS (0, 11);
309 state
->Reg
[Rd
] = val
;
315 /* MOVT<c> <Rd>,#<imm16>
317 instr[27,20] = 0011 0100
320 instr[11, 0] = imm12. */
322 val
= (BITS (16, 19) << 12) | BITS (0, 11);
323 state
->Reg
[Rd
] &= 0xFFFF;
324 state
->Reg
[Rd
] |= val
<< 16;
339 if (Rd
== 15 || Rn
== 15 || Rm
== 15)
342 val1
= state
->Reg
[Rn
];
343 val2
= state
->Reg
[Rm
];
345 switch (BITS (4, 11))
347 case 0xF1: /* QADD16<c> <Rd>,<Rn>,<Rm>. */
350 for (i
= 0; i
< 32; i
+= 16)
352 n
= (val1
>> i
) & 0xFFFF;
356 m
= (val2
>> i
) & 0xFFFF;
364 else if (r
< -(0x8000))
367 state
->Reg
[Rd
] |= (r
& 0xFFFF) << i
;
371 case 0xF3: /* QASX<c> <Rd>,<Rn>,<Rm>. */
376 m
= (val2
>> 16) & 0xFFFF;
384 else if (r
< -(0x8000))
387 state
->Reg
[Rd
] = (r
& 0xFFFF);
389 n
= (val1
>> 16) & 0xFFFF;
401 else if (r
< -(0x8000))
404 state
->Reg
[Rd
] |= (r
& 0xFFFF) << 16;
407 case 0xF5: /* QSAX<c> <Rd>,<Rn>,<Rm>. */
412 m
= (val2
>> 16) & 0xFFFF;
420 else if (r
< -(0x8000))
423 state
->Reg
[Rd
] = (r
& 0xFFFF);
425 n
= (val1
>> 16) & 0xFFFF;
437 else if (r
< -(0x8000))
440 state
->Reg
[Rd
] |= (r
& 0xFFFF) << 16;
443 case 0xF7: /* QSUB16<c> <Rd>,<Rn>,<Rm>. */
446 for (i
= 0; i
< 32; i
+= 16)
448 n
= (val1
>> i
) & 0xFFFF;
452 m
= (val2
>> i
) & 0xFFFF;
460 else if (r
< -(0x8000))
463 state
->Reg
[Rd
] |= (r
& 0xFFFF) << i
;
467 case 0xF9: /* QADD8<c> <Rd>,<Rn>,<Rm>. */
470 for (i
= 0; i
< 32; i
+= 8)
472 n
= (val1
>> i
) & 0xFF;
476 m
= (val2
>> i
) & 0xFF;
487 state
->Reg
[Rd
] |= (r
& 0xFF) << i
;
491 case 0xFF: /* QSUB8<c> <Rd>,<Rn>,<Rm>. */
494 for (i
= 0; i
< 32; i
+= 8)
496 n
= (val1
>> i
) & 0xFF;
500 m
= (val2
>> i
) & 0xFF;
511 state
->Reg
[Rd
] |= (r
& 0xFF) << i
;
525 ARMword res1
, res2
, res3
, res4
;
527 /* U{ADD|SUB}{8|16}<c> <Rd>, <Rn>, <Rm>
529 instr[27,20] = 0110 0101
533 instr[ 7, 4] = opcode: UADD8 (1001), UADD16 (0001), USUB8 (1111), USUB16 (0111)
534 instr[ 3, 0] = Rm. */
535 if (BITS (8, 11) != 0xF)
542 if (Rn
== 15 || Rd
== 15 || Rm
== 15)
544 ARMul_UndefInstr (state
, instr
);
545 state
->Emulate
= FALSE
;
549 valn
= state
->Reg
[Rn
];
550 valm
= state
->Reg
[Rm
];
554 case 1: /* UADD16. */
555 res1
= (valn
& 0xFFFF) + (valm
& 0xFFFF);
557 state
->Cpsr
|= (GE0
| GE1
);
559 state
->Cpsr
&= ~ (GE0
| GE1
);
561 res2
= (valn
>> 16) + (valm
>> 16);
563 state
->Cpsr
|= (GE2
| GE3
);
565 state
->Cpsr
&= ~ (GE2
| GE3
);
567 state
->Reg
[Rd
] = (res1
& 0xFFFF) | (res2
<< 16);
570 case 7: /* USUB16. */
571 res1
= (valn
& 0xFFFF) - (valm
& 0xFFFF);
573 state
->Cpsr
|= (GE0
| GE1
);
575 state
->Cpsr
&= ~ (GE0
| GE1
);
577 res2
= (valn
>> 16) - (valm
>> 16);
579 state
->Cpsr
|= (GE2
| GE3
);
581 state
->Cpsr
&= ~ (GE2
| GE3
);
583 state
->Reg
[Rd
] = (res1
& 0xFFFF) | (res2
<< 16);
587 res1
= (valn
& 0xFF) + (valm
& 0xFF);
591 state
->Cpsr
&= ~ GE0
;
593 res2
= ((valn
>> 8) & 0xFF) + ((valm
>> 8) & 0xFF);
597 state
->Cpsr
&= ~ GE1
;
599 res3
= ((valn
>> 16) & 0xFF) + ((valm
>> 16) & 0xFF);
603 state
->Cpsr
&= ~ GE2
;
605 res4
= (valn
>> 24) + (valm
>> 24);
609 state
->Cpsr
&= ~ GE3
;
611 state
->Reg
[Rd
] = (res1
& 0xFF) | ((res2
<< 8) & 0xFF00)
612 | ((res3
<< 16) & 0xFF0000) | (res4
<< 24);
615 case 15: /* USUB8. */
616 res1
= (valn
& 0xFF) - (valm
& 0xFF);
620 state
->Cpsr
&= ~ GE0
;
622 res2
= ((valn
>> 8) & 0XFF) - ((valm
>> 8) & 0xFF);
626 state
->Cpsr
&= ~ GE1
;
628 res3
= ((valn
>> 16) & 0XFF) - ((valm
>> 16) & 0xFF);
632 state
->Cpsr
&= ~ GE2
;
634 res4
= (valn
>> 24) - (valm
>> 24) ;
638 state
->Cpsr
&= ~ GE3
;
640 state
->Reg
[Rd
] = (res1
& 0xFF) | ((res2
<< 8) & 0xFF00)
641 | ((res3
<< 16) & 0xFF0000) | (res4
<< 24);
654 /* PKHBT<c> <Rd>,<Rn>,<Rm>{,LSL #<imm>}
655 PKHTB<c> <Rd>,<Rn>,<Rm>{,ASR #<imm>}
656 SXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>}
657 SXTB16<c> <Rd>,<Rm>{,<rotation>}
658 SEL<c> <Rd>,<Rn>,<Rm>
661 instr[27,20] = 0110 1000
664 instr[11, 7] = imm5 (PKH), 11111 (SEL), rr000 (SXTAB16 & SXTB16),
665 instr[6] = tb (PKH), 0 (SEL), 1 (SXT)
666 instr[5] = opcode: PKH (0), SEL/SXT (1)
668 instr[ 3, 0] = Rm. */
675 /* FIXME: Add implementation of PKH. */
676 fprintf (stderr
, "PKH: NOT YET IMPLEMENTED\n");
677 ARMul_UndefInstr (state
, instr
);
683 /* FIXME: Add implementation of SXT. */
684 fprintf (stderr
, "SXT: NOT YET IMPLEMENTED\n");
685 ARMul_UndefInstr (state
, instr
);
692 if (Rn
== 15 || Rm
== 15 || Rd
== 15)
694 ARMul_UndefInstr (state
, instr
);
695 state
->Emulate
= FALSE
;
699 res
= (state
->Reg
[(state
->Cpsr
& GE0
) ? Rn
: Rm
]) & 0xFF;
700 res
|= (state
->Reg
[(state
->Cpsr
& GE1
) ? Rn
: Rm
]) & 0xFF00;
701 res
|= (state
->Reg
[(state
->Cpsr
& GE2
) ? Rn
: Rm
]) & 0xFF0000;
702 res
|= (state
->Reg
[(state
->Cpsr
& GE3
) ? Rn
: Rm
]) & 0xFF000000;
703 state
->Reg
[Rd
] = res
;
711 switch (BITS (4, 11))
713 case 0x07: ror
= 0; break;
714 case 0x47: ror
= 8; break;
715 case 0x87: ror
= 16; break;
716 case 0xc7: ror
= 24; break;
720 printf ("Unhandled v6 insn: ssat\n");
729 if (BITS (4, 6) == 0x7)
731 printf ("Unhandled v6 insn: ssat\n");
737 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
741 if (BITS (16, 19) == 0xf)
743 state
->Reg
[BITS (12, 15)] = Rm
;
746 state
->Reg
[BITS (12, 15)] += Rm
;
754 switch (BITS (4, 11))
756 case 0x07: ror
= 0; break;
757 case 0x47: ror
= 8; break;
758 case 0x87: ror
= 16; break;
759 case 0xc7: ror
= 24; break;
765 instr[27,20] = 0110 1011
768 instr[11, 4] = 1111 0011
769 instr[ 3, 0] = Rm. */
770 if (BITS (16, 19) != 0xF)
775 if (Rd
== 15 || Rm
== 15)
777 ARMul_UndefInstr (state
, instr
);
778 state
->Emulate
= FALSE
;
782 val
= state
->Reg
[Rm
] << 24;
783 val
|= ((state
->Reg
[Rm
] << 8) & 0xFF0000);
784 val
|= ((state
->Reg
[Rm
] >> 8) & 0xFF00);
785 val
|= ((state
->Reg
[Rm
] >> 24));
786 state
->Reg
[Rd
] = val
;
792 /* REV16<c> <Rd>,<Rm>. */
793 if (BITS (16, 19) != 0xF)
798 if (Rd
== 15 || Rm
== 15)
800 ARMul_UndefInstr (state
, instr
);
801 state
->Emulate
= FALSE
;
806 val
|= ((state
->Reg
[Rm
] >> 8) & 0x00FF00FF);
807 val
|= ((state
->Reg
[Rm
] << 8) & 0xFF00FF00);
808 state
->Reg
[Rd
] = val
;
819 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
823 if (BITS (16, 19) == 0xf)
825 state
->Reg
[BITS (12, 15)] = Rm
;
828 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
836 switch (BITS (4, 11))
838 case 0x07: ror
= 0; break;
839 case 0x47: ror
= 8; break;
840 case 0x87: ror
= 16; break;
841 case 0xc7: ror
= 24; break;
845 printf ("Unhandled v6 insn: usat\n");
854 if (BITS (4, 6) == 0x7)
856 printf ("Unhandled v6 insn: usat\n");
862 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
864 if (BITS (16, 19) == 0xf)
866 state
->Reg
[BITS (12, 15)] = Rm
;
869 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
878 switch (BITS (4, 11))
880 case 0x07: ror
= 0; break;
881 case 0x47: ror
= 8; break;
882 case 0x87: ror
= 16; break;
883 case 0xc7: ror
= 24; break;
885 case 0xf3: /* RBIT */
886 if (BITS (16, 19) != 0xF)
890 Rm
= state
->Reg
[BITS (0, 3)];
891 for (i
= 0; i
< 32; i
++)
893 state
->Reg
[Rd
] |= (1 << (31 - i
));
897 printf ("Unhandled v6 insn: revsh\n");
907 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
909 if (BITS (16, 19) == 0xf)
911 state
->Reg
[BITS (12, 15)] = Rm
;
914 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
925 /* BFC<c> <Rd>,#<lsb>,#<width>
926 BFI<c> <Rd>,<Rn>,#<lsb>,#<width>
929 instr[27,21] = 0111 110
933 instr[ 6, 4] = 001 1111
934 instr[ 3, 0] = Rn (BFI) / 1111 (BFC). */
936 if (BITS (4, 6) != 0x1)
942 ARMul_UndefInstr (state
, instr
);
943 state
->Emulate
= FALSE
;
950 ARMul_UndefInstr (state
, instr
);
951 state
->Emulate
= FALSE
;
955 mask
&= ~(-(1 << (msb
+ 1)));
956 state
->Reg
[Rd
] &= ~ mask
;
961 ARMword val
= state
->Reg
[Rn
] & ~(-(1 << ((msb
+ 1) - lsb
)));
962 state
->Reg
[Rd
] |= val
<< lsb
;
968 case 0x7a: /* SBFX<c> <Rd>,<Rn>,#<lsb>,#<width>. */
974 if (BITS (4, 6) != 0x5)
980 ARMul_UndefInstr (state
, instr
);
981 state
->Emulate
= FALSE
;
987 ARMul_UndefInstr (state
, instr
);
988 state
->Emulate
= FALSE
;
992 widthm1
= BITS (16, 20);
994 sval
= state
->Reg
[Rn
];
995 sval
<<= (31 - (lsb
+ widthm1
));
996 sval
>>= (31 - widthm1
);
997 state
->Reg
[Rd
] = sval
;
1008 /* UBFX<c> <Rd>,<Rn>,#<lsb>,#<width>
1010 instr[27,21] = 0111 111
1011 instr[20,16] = widthm1
1015 instr[ 3, 0] = Rn. */
1017 if (BITS (4, 6) != 0x5)
1023 ARMul_UndefInstr (state
, instr
);
1024 state
->Emulate
= FALSE
;
1030 ARMul_UndefInstr (state
, instr
);
1031 state
->Emulate
= FALSE
;
1035 widthm1
= BITS (16, 20);
1037 val
= state
->Reg
[Rn
];
1039 val
&= ~(-(1 << (widthm1
+ 1)));
1041 state
->Reg
[Rd
] = val
;
1046 case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
1051 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr
);
1057 handle_VFP_move (ARMul_State
* state
, ARMword instr
)
1059 switch (BITS (20, 27))
1063 switch (BITS (4, 11))
1068 /* VMOV two core <-> two VFP single precision. */
1069 int sreg
= (BITS (0, 3) << 1) | BIT (5);
1073 state
->Reg
[BITS (12, 15)] = VFP_uword (sreg
);
1074 state
->Reg
[BITS (16, 19)] = VFP_uword (sreg
+ 1);
1078 VFP_uword (sreg
) = state
->Reg
[BITS (12, 15)];
1079 VFP_uword (sreg
+ 1) = state
->Reg
[BITS (16, 19)];
1087 /* VMOV two core <-> VFP double precision. */
1088 int dreg
= BITS (0, 3) | (BIT (5) << 4);
1093 fprintf (stderr
, " VFP: VMOV: r%d r%d <= d%d\n",
1094 BITS (12, 15), BITS (16, 19), dreg
);
1096 state
->Reg
[BITS (12, 15)] = VFP_dword (dreg
);
1097 state
->Reg
[BITS (16, 19)] = VFP_dword (dreg
) >> 32;
1101 VFP_dword (dreg
) = state
->Reg
[BITS (16, 19)];
1102 VFP_dword (dreg
) <<= 32;
1103 VFP_dword (dreg
) |= state
->Reg
[BITS (12, 15)];
1106 fprintf (stderr
, " VFP: VMOV: d%d <= r%d r%d : %g\n",
1107 dreg
, BITS (16, 19), BITS (12, 15),
1114 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1121 /* VMOV single core <-> VFP single precision. */
1122 if (BITS (0, 6) != 0x10 || BITS (8, 11) != 0xA)
1123 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1126 int sreg
= (BITS (16, 19) << 1) | BIT (7);
1129 state
->Reg
[DESTReg
] = VFP_uword (sreg
);
1131 VFP_uword (sreg
) = state
->Reg
[DESTReg
];
1136 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1141 /* EMULATION of ARM6. */
1143 /* The PC pipeline value depends on whether ARM
1144 or Thumb instructions are being executed. */
1149 ARMul_Emulate32 (ARMul_State
* state
)
1151 ARMul_Emulate26 (ARMul_State
* state
)
1154 ARMword instr
; /* The current instruction. */
1155 ARMword dest
= 0; /* Almost the DestBus. */
1156 ARMword temp
; /* Ubiquitous third hand. */
1157 ARMword pc
= 0; /* The address of the current instruction. */
1158 ARMword lhs
; /* Almost the ABus and BBus. */
1160 ARMword decoded
= 0; /* Instruction pipeline. */
1163 /* Execute the next instruction. */
1165 if (state
->NextInstr
< PRIMEPIPE
)
1167 decoded
= state
->decoded
;
1168 loaded
= state
->loaded
;
1174 /* Just keep going. */
1177 switch (state
->NextInstr
)
1180 /* Advance the pipeline, and an S cycle. */
1181 state
->Reg
[15] += isize
;
1185 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1189 /* Advance the pipeline, and an N cycle. */
1190 state
->Reg
[15] += isize
;
1194 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
1199 /* Program counter advanced, and an S cycle. */
1203 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1208 /* Program counter advanced, and an N cycle. */
1212 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
1217 /* The program counter has been changed. */
1218 pc
= state
->Reg
[15];
1220 pc
= pc
& R15PCBITS
;
1222 state
->Reg
[15] = pc
+ (isize
* 2);
1224 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
1225 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
1226 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
1231 /* The program counter has been changed. */
1232 pc
= state
->Reg
[15];
1234 pc
= pc
& R15PCBITS
;
1236 state
->Reg
[15] = pc
+ (isize
* 2);
1238 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
1239 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
1240 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1245 if (state
->EventSet
)
1246 ARMul_EnvokeEvent (state
);
1248 if (! TFLAG
&& trace
)
1250 fprintf (stderr
, "pc: %x, ", pc
& ~1);
1252 fprintf (stderr
, "instr: %x\n", instr
);
1255 if (instr
== 0 || pc
< 0x10)
1257 ARMul_Abort (state
, ARMUndefinedInstrV
);
1258 state
->Emulate
= FALSE
;
1261 #if 0 /* Enable this code to help track down stack alignment bugs. */
1263 static ARMword old_sp
= -1;
1265 if (old_sp
!= state
->Reg
[13])
1267 old_sp
= state
->Reg
[13];
1268 fprintf (stderr
, "pc: %08x: SP set to %08x%s\n",
1269 pc
& ~1, old_sp
, (old_sp
% 8) ? " [UNALIGNED!]" : "");
1274 if (state
->Exception
)
1276 /* Any exceptions ? */
1277 if (state
->NresetSig
== LOW
)
1279 ARMul_Abort (state
, ARMul_ResetV
);
1282 else if (!state
->NfiqSig
&& !FFLAG
)
1284 ARMul_Abort (state
, ARMul_FIQV
);
1287 else if (!state
->NirqSig
&& !IFLAG
)
1289 ARMul_Abort (state
, ARMul_IRQV
);
1294 if (state
->CallDebug
> 0)
1296 instr
= ARMul_Debug (state
, pc
, instr
);
1297 if (state
->Emulate
< ONCE
)
1299 state
->NextInstr
= RESUME
;
1304 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n",
1305 (long) pc
, (long) instr
, (long) state
->Mode
);
1306 (void) fgetc (stdin
);
1309 else if (state
->Emulate
< ONCE
)
1311 state
->NextInstr
= RESUME
;
1318 /* Provide Thumb instruction decoding. If the processor is in Thumb
1319 mode, then we can simply decode the Thumb instruction, and map it
1320 to the corresponding ARM instruction (by directly loading the
1321 instr variable, and letting the normal ARM simulator
1322 execute). There are some caveats to ensure that the correct
1323 pipelined PC value is used when executing Thumb code, and also for
1324 dealing with the BL instruction. */
1329 /* Check if in Thumb mode. */
1330 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
1333 /* This is a Thumb instruction. */
1334 ARMul_UndefInstr (state
, instr
);
1338 /* Already processed. */
1342 /* ARM instruction available. */
1345 fprintf (stderr
, " emulate as: ");
1347 fprintf (stderr
, "%08x ", new);
1349 fprintf (stderr
, "\n");
1352 /* So continue instruction decoding. */
1362 /* Check the condition codes. */
1363 if ((temp
= TOPBITS (28)) == AL
)
1364 /* Vile deed in the need for speed. */
1367 /* Check the condition code. */
1368 switch ((int) TOPBITS (28))
1376 if (BITS (25, 27) == 5) /* BLX(1) */
1380 state
->Reg
[14] = pc
+ 4;
1382 /* Force entry into Thumb mode. */
1385 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
1387 dest
+= POSBRANCH
+ (BIT (24) << 1);
1389 WriteR15Branch (state
, dest
);
1392 else if ((instr
& 0xFC70F000) == 0xF450F000)
1393 /* The PLD instruction. Ignored. */
1395 else if ( ((instr
& 0xfe500f00) == 0xfc100100)
1396 || ((instr
& 0xfe500f00) == 0xfc000100))
1397 /* wldrw and wstrw are unconditional. */
1400 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
1401 ARMul_UndefInstr (state
, instr
);
1430 temp
= (CFLAG
&& !ZFLAG
);
1433 temp
= (!CFLAG
|| ZFLAG
);
1436 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
1439 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
1442 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
1445 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
1449 /* Handle the Clock counter here. */
1450 if (state
->is_XScale
)
1455 ok
= state
->CPRead
[14] (state
, 0, & cp14r0
);
1457 if (ok
&& (cp14r0
& ARMul_CP14_R0_ENABLE
))
1459 unsigned long newcycles
, nowtime
= ARMul_Time (state
);
1461 newcycles
= nowtime
- state
->LastTime
;
1462 state
->LastTime
= nowtime
;
1464 if (cp14r0
& ARMul_CP14_R0_CCD
)
1466 if (state
->CP14R0_CCD
== -1)
1467 state
->CP14R0_CCD
= newcycles
;
1469 state
->CP14R0_CCD
+= newcycles
;
1471 if (state
->CP14R0_CCD
>= 64)
1475 while (state
->CP14R0_CCD
>= 64)
1476 state
->CP14R0_CCD
-= 64, newcycles
++;
1486 state
->CP14R0_CCD
= -1;
1489 cp14r0
|= ARMul_CP14_R0_FLAG2
;
1490 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
1492 ok
= state
->CPRead
[14] (state
, 1, & cp14r1
);
1494 /* Coded like this for portability. */
1495 while (ok
&& newcycles
)
1497 if (cp14r1
== 0xffffffff)
1508 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
1510 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
1514 if (state
->CPRead
[13] (state
, 8, & temp
)
1515 && (temp
& ARMul_CP13_R8_PMUS
))
1516 ARMul_Abort (state
, ARMul_FIQV
);
1518 ARMul_Abort (state
, ARMul_IRQV
);
1524 /* Handle hardware instructions breakpoints here. */
1525 if (state
->is_XScale
)
1527 if ( (pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
1528 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
1530 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
1531 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1535 /* Actual execution of instructions begins here. */
1536 /* If the condition codes don't match, stop here. */
1541 if (state
->is_XScale
)
1543 if (BIT (20) == 0 && BITS (25, 27) == 0)
1545 if (BITS (4, 7) == 0xD)
1547 /* XScale Load Consecutive insn. */
1548 ARMword temp
= GetLS7RHS (state
, instr
);
1549 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
1550 ARMword addr
= BIT (24) ? temp2
: LHS
;
1553 ARMul_UndefInstr (state
, instr
);
1555 /* Alignment violation. */
1556 ARMul_Abort (state
, ARMul_DataAbortV
);
1559 int wb
= BIT (21) || (! BIT (24));
1561 state
->Reg
[BITS (12, 15)] =
1562 ARMul_LoadWordN (state
, addr
);
1563 state
->Reg
[BITS (12, 15) + 1] =
1564 ARMul_LoadWordN (state
, addr
+ 4);
1571 else if (BITS (4, 7) == 0xF)
1573 /* XScale Store Consecutive insn. */
1574 ARMword temp
= GetLS7RHS (state
, instr
);
1575 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
1576 ARMword addr
= BIT (24) ? temp2
: LHS
;
1579 ARMul_UndefInstr (state
, instr
);
1581 /* Alignment violation. */
1582 ARMul_Abort (state
, ARMul_DataAbortV
);
1585 ARMul_StoreWordN (state
, addr
,
1586 state
->Reg
[BITS (12, 15)]);
1587 ARMul_StoreWordN (state
, addr
+ 4,
1588 state
->Reg
[BITS (12, 15) + 1]);
1590 if (BIT (21)|| ! BIT (24))
1598 if (ARMul_HandleIwmmxt (state
, instr
))
1602 switch ((int) BITS (20, 27))
1604 /* Data Processing Register RHS Instructions. */
1606 case 0x00: /* AND reg and MUL */
1608 if (BITS (4, 11) == 0xB)
1610 /* STRH register offset, no write-back, down, post indexed. */
1614 if (BITS (4, 7) == 0xD)
1616 Handle_Load_Double (state
, instr
);
1619 if (BITS (4, 7) == 0xF)
1621 Handle_Store_Double (state
, instr
);
1625 if (BITS (4, 7) == 9)
1628 rhs
= state
->Reg
[MULRHSReg
];
1629 if (MULLHSReg
== MULDESTReg
)
1632 state
->Reg
[MULDESTReg
] = 0;
1634 else if (MULDESTReg
!= 15)
1635 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
1639 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1640 if (rhs
& (1L << dest
))
1643 /* Mult takes this many/2 I cycles. */
1644 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1655 case 0x01: /* ANDS reg and MULS */
1657 if ((BITS (4, 11) & 0xF9) == 0x9)
1658 /* LDR register offset, no write-back, down, post indexed. */
1660 /* Fall through to rest of decoding. */
1662 if (BITS (4, 7) == 9)
1665 rhs
= state
->Reg
[MULRHSReg
];
1667 if (MULLHSReg
== MULDESTReg
)
1670 state
->Reg
[MULDESTReg
] = 0;
1674 else if (MULDESTReg
!= 15)
1676 dest
= state
->Reg
[MULLHSReg
] * rhs
;
1677 ARMul_NegZero (state
, dest
);
1678 state
->Reg
[MULDESTReg
] = dest
;
1683 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1684 if (rhs
& (1L << dest
))
1687 /* Mult takes this many/2 I cycles. */
1688 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1699 case 0x02: /* EOR reg and MLA */
1701 if (BITS (4, 11) == 0xB)
1703 /* STRH register offset, write-back, down, post indexed. */
1708 if (BITS (4, 7) == 9)
1710 rhs
= state
->Reg
[MULRHSReg
];
1711 if (MULLHSReg
== MULDESTReg
)
1714 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
1716 else if (MULDESTReg
!= 15)
1717 state
->Reg
[MULDESTReg
] =
1718 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1722 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1723 if (rhs
& (1L << dest
))
1726 /* Mult takes this many/2 I cycles. */
1727 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1737 case 0x03: /* EORS reg and MLAS */
1739 if ((BITS (4, 11) & 0xF9) == 0x9)
1740 /* LDR register offset, write-back, down, post-indexed. */
1742 /* Fall through to rest of the decoding. */
1744 if (BITS (4, 7) == 9)
1747 rhs
= state
->Reg
[MULRHSReg
];
1749 if (MULLHSReg
== MULDESTReg
)
1752 dest
= state
->Reg
[MULACCReg
];
1753 ARMul_NegZero (state
, dest
);
1754 state
->Reg
[MULDESTReg
] = dest
;
1756 else if (MULDESTReg
!= 15)
1759 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1760 ARMul_NegZero (state
, dest
);
1761 state
->Reg
[MULDESTReg
] = dest
;
1766 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1767 if (rhs
& (1L << dest
))
1770 /* Mult takes this many/2 I cycles. */
1771 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1782 case 0x04: /* SUB reg */
1784 if (BITS (4, 7) == 0xB)
1786 /* STRH immediate offset, no write-back, down, post indexed. */
1790 if (BITS (4, 7) == 0xD)
1792 Handle_Load_Double (state
, instr
);
1795 if (BITS (4, 7) == 0xF)
1797 Handle_Store_Double (state
, instr
);
1806 case 0x05: /* SUBS reg */
1808 if ((BITS (4, 7) & 0x9) == 0x9)
1809 /* LDR immediate offset, no write-back, down, post indexed. */
1811 /* Fall through to the rest of the instruction decoding. */
1817 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1819 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1820 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1830 case 0x06: /* RSB reg */
1832 if (BITS (4, 7) == 0xB)
1834 /* STRH immediate offset, write-back, down, post indexed. */
1844 case 0x07: /* RSBS reg */
1846 if ((BITS (4, 7) & 0x9) == 0x9)
1847 /* LDR immediate offset, write-back, down, post indexed. */
1849 /* Fall through to remainder of instruction decoding. */
1855 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1857 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1858 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1868 case 0x08: /* ADD reg */
1870 if (BITS (4, 11) == 0xB)
1872 /* STRH register offset, no write-back, up, post indexed. */
1876 if (BITS (4, 7) == 0xD)
1878 Handle_Load_Double (state
, instr
);
1881 if (BITS (4, 7) == 0xF)
1883 Handle_Store_Double (state
, instr
);
1888 if (BITS (4, 7) == 0x9)
1892 ARMul_Icycles (state
,
1893 Multiply64 (state
, instr
, LUNSIGNED
,
1903 case 0x09: /* ADDS reg */
1905 if ((BITS (4, 11) & 0xF9) == 0x9)
1906 /* LDR register offset, no write-back, up, post indexed. */
1908 /* Fall through to remaining instruction decoding. */
1911 if (BITS (4, 7) == 0x9)
1915 ARMul_Icycles (state
,
1916 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
1924 ASSIGNZ (dest
== 0);
1925 if ((lhs
| rhs
) >> 30)
1927 /* Possible C,V,N to set. */
1928 ASSIGNN (NEG (dest
));
1929 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1930 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1941 case 0x0a: /* ADC reg */
1943 if (BITS (4, 11) == 0xB)
1945 /* STRH register offset, write-back, up, post-indexed. */
1949 if (BITS (4, 7) == 0x9)
1953 ARMul_Icycles (state
,
1954 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1960 dest
= LHS
+ rhs
+ CFLAG
;
1964 case 0x0b: /* ADCS reg */
1966 if ((BITS (4, 11) & 0xF9) == 0x9)
1967 /* LDR register offset, write-back, up, post indexed. */
1969 /* Fall through to remaining instruction decoding. */
1970 if (BITS (4, 7) == 0x9)
1974 ARMul_Icycles (state
,
1975 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
1982 dest
= lhs
+ rhs
+ CFLAG
;
1983 ASSIGNZ (dest
== 0);
1984 if ((lhs
| rhs
) >> 30)
1986 /* Possible C,V,N to set. */
1987 ASSIGNN (NEG (dest
));
1988 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1989 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2000 case 0x0c: /* SBC reg */
2002 if (BITS (4, 7) == 0xB)
2004 /* STRH immediate offset, no write-back, up post indexed. */
2008 if (BITS (4, 7) == 0xD)
2010 Handle_Load_Double (state
, instr
);
2013 if (BITS (4, 7) == 0xF)
2015 Handle_Store_Double (state
, instr
);
2018 if (BITS (4, 7) == 0x9)
2022 ARMul_Icycles (state
,
2023 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
2029 dest
= LHS
- rhs
- !CFLAG
;
2033 case 0x0d: /* SBCS reg */
2035 if ((BITS (4, 7) & 0x9) == 0x9)
2036 /* LDR immediate offset, no write-back, up, post indexed. */
2039 if (BITS (4, 7) == 0x9)
2043 ARMul_Icycles (state
,
2044 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
2051 dest
= lhs
- rhs
- !CFLAG
;
2052 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2054 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2055 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2065 case 0x0e: /* RSC reg */
2067 if (BITS (4, 7) == 0xB)
2069 /* STRH immediate offset, write-back, up, post indexed. */
2074 if (BITS (4, 7) == 0x9)
2078 ARMul_Icycles (state
,
2079 MultiplyAdd64 (state
, instr
, LSIGNED
,
2085 dest
= rhs
- LHS
- !CFLAG
;
2089 case 0x0f: /* RSCS reg */
2091 if ((BITS (4, 7) & 0x9) == 0x9)
2092 /* LDR immediate offset, write-back, up, post indexed. */
2094 /* Fall through to remaining instruction decoding. */
2096 if (BITS (4, 7) == 0x9)
2100 ARMul_Icycles (state
,
2101 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
2108 dest
= rhs
- lhs
- !CFLAG
;
2110 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2112 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2113 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2123 case 0x10: /* TST reg and MRS CPSR and SWP word. */
2126 if (BIT (4) == 0 && BIT (7) == 1)
2128 /* ElSegundo SMLAxy insn. */
2129 ARMword op1
= state
->Reg
[BITS (0, 3)];
2130 ARMword op2
= state
->Reg
[BITS (8, 11)];
2131 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2145 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
2147 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
2151 if (BITS (4, 11) == 5)
2153 /* ElSegundo QADD insn. */
2154 ARMword op1
= state
->Reg
[BITS (0, 3)];
2155 ARMword op2
= state
->Reg
[BITS (16, 19)];
2156 ARMword result
= op1
+ op2
;
2157 if (AddOverflow (op1
, op2
, result
))
2159 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2162 state
->Reg
[BITS (12, 15)] = result
;
2167 if (BITS (4, 11) == 0xB)
2169 /* STRH register offset, no write-back, down, pre indexed. */
2173 if (BITS (4, 7) == 0xD)
2175 Handle_Load_Double (state
, instr
);
2178 if (BITS (4, 7) == 0xF)
2180 Handle_Store_Double (state
, instr
);
2184 if (BITS (4, 11) == 9)
2191 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2193 INTERNALABORT (temp
);
2194 (void) ARMul_LoadWordN (state
, temp
);
2195 (void) ARMul_LoadWordN (state
, temp
);
2199 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
2201 DEST
= ARMul_Align (state
, temp
, dest
);
2204 if (state
->abortSig
|| state
->Aborted
)
2207 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2210 DEST
= ECC
| EINT
| EMODE
;
2216 && handle_v6_insn (state
, instr
))
2223 case 0x11: /* TSTP reg */
2225 if ((BITS (4, 11) & 0xF9) == 0x9)
2226 /* LDR register offset, no write-back, down, pre indexed. */
2228 /* Continue with remaining instruction decode. */
2234 state
->Cpsr
= GETSPSR (state
->Bank
);
2235 ARMul_CPSRAltered (state
);
2247 ARMul_NegZero (state
, dest
);
2251 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
2254 if (BITS (4, 7) == 3)
2260 temp
= (pc
+ 2) | 1;
2264 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2265 state
->Reg
[14] = temp
;
2272 if (BIT (4) == 0 && BIT (7) == 1
2273 && (BIT (5) == 0 || BITS (12, 15) == 0))
2275 /* ElSegundo SMLAWy/SMULWy insn. */
2276 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2277 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2282 if (op1
& 0x80000000)
2287 result
= (op1
* op2
) >> 16;
2291 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2293 if (AddOverflow (result
, Rn
, result
+ Rn
))
2297 state
->Reg
[BITS (16, 19)] = result
;
2301 if (BITS (4, 11) == 5)
2303 /* ElSegundo QSUB insn. */
2304 ARMword op1
= state
->Reg
[BITS (0, 3)];
2305 ARMword op2
= state
->Reg
[BITS (16, 19)];
2306 ARMword result
= op1
- op2
;
2308 if (SubOverflow (op1
, op2
, result
))
2310 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2314 state
->Reg
[BITS (12, 15)] = result
;
2319 if (BITS (4, 11) == 0xB)
2321 /* STRH register offset, write-back, down, pre indexed. */
2325 if (BITS (4, 27) == 0x12FFF1)
2328 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2331 if (BITS (4, 7) == 0xD)
2333 Handle_Load_Double (state
, instr
);
2336 if (BITS (4, 7) == 0xF)
2338 Handle_Store_Double (state
, instr
);
2344 if (BITS (4, 7) == 0x7)
2346 extern int SWI_vector_installed
;
2348 /* Hardware is allowed to optionally override this
2349 instruction and treat it as a breakpoint. Since
2350 this is a simulator not hardware, we take the position
2351 that if a SWI vector was not installed, then an Abort
2352 vector was probably not installed either, and so
2353 normally this instruction would be ignored, even if an
2354 Abort is generated. This is a bad thing, since GDB
2355 uses this instruction for its breakpoints (at least in
2356 Thumb mode it does). So intercept the instruction here
2357 and generate a breakpoint SWI instead. */
2358 if (! SWI_vector_installed
)
2359 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
2362 /* BKPT - normally this will cause an abort, but on the
2363 XScale we must check the DCSR. */
2364 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
2365 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
2369 /* Force the next instruction to be refetched. */
2370 state
->NextInstr
= RESUME
;
2376 /* MSR reg to CPSR. */
2380 /* Don't allow TBIT to be set by MSR. */
2383 ARMul_FixCPSR (state
, instr
, temp
);
2386 else if (state
->is_v6
2387 && handle_v6_insn (state
, instr
))
2395 case 0x13: /* TEQP reg */
2397 if ((BITS (4, 11) & 0xF9) == 0x9)
2398 /* LDR register offset, write-back, down, pre indexed. */
2400 /* Continue with remaining instruction decode. */
2406 state
->Cpsr
= GETSPSR (state
->Bank
);
2407 ARMul_CPSRAltered (state
);
2419 ARMul_NegZero (state
, dest
);
2423 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
2426 if (BIT (4) == 0 && BIT (7) == 1)
2428 /* ElSegundo SMLALxy insn. */
2429 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2430 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2444 dest
= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
2445 dest
|= state
->Reg
[BITS (12, 15)];
2447 state
->Reg
[BITS (12, 15)] = dest
;
2448 state
->Reg
[BITS (16, 19)] = dest
>> 32;
2452 if (BITS (4, 11) == 5)
2454 /* ElSegundo QDADD insn. */
2455 ARMword op1
= state
->Reg
[BITS (0, 3)];
2456 ARMword op2
= state
->Reg
[BITS (16, 19)];
2457 ARMword op2d
= op2
+ op2
;
2460 if (AddOverflow (op2
, op2
, op2d
))
2463 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2466 result
= op1
+ op2d
;
2467 if (AddOverflow (op1
, op2d
, result
))
2470 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2473 state
->Reg
[BITS (12, 15)] = result
;
2478 if (BITS (4, 7) == 0xB)
2480 /* STRH immediate offset, no write-back, down, pre indexed. */
2484 if (BITS (4, 7) == 0xD)
2486 Handle_Load_Double (state
, instr
);
2489 if (BITS (4, 7) == 0xF)
2491 Handle_Store_Double (state
, instr
);
2495 if (BITS (4, 11) == 9)
2502 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2504 INTERNALABORT (temp
);
2505 (void) ARMul_LoadByte (state
, temp
);
2506 (void) ARMul_LoadByte (state
, temp
);
2510 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
2511 if (state
->abortSig
|| state
->Aborted
)
2514 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2518 DEST
= GETSPSR (state
->Bank
);
2521 else if (state
->is_v6
2522 && handle_v6_insn (state
, instr
))
2530 case 0x15: /* CMPP reg. */
2532 if ((BITS (4, 7) & 0x9) == 0x9)
2533 /* LDR immediate offset, no write-back, down, pre indexed. */
2535 /* Continue with remaining instruction decode. */
2541 state
->Cpsr
= GETSPSR (state
->Bank
);
2542 ARMul_CPSRAltered (state
);
2555 ARMul_NegZero (state
, dest
);
2556 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2558 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2559 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2569 case 0x16: /* CMN reg and MSR reg to SPSR */
2572 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
2574 /* ElSegundo SMULxy insn. */
2575 ARMword op1
= state
->Reg
[BITS (0, 3)];
2576 ARMword op2
= state
->Reg
[BITS (8, 11)];
2589 state
->Reg
[BITS (16, 19)] = op1
* op2
;
2593 if (BITS (4, 11) == 5)
2595 /* ElSegundo QDSUB insn. */
2596 ARMword op1
= state
->Reg
[BITS (0, 3)];
2597 ARMword op2
= state
->Reg
[BITS (16, 19)];
2598 ARMword op2d
= op2
+ op2
;
2601 if (AddOverflow (op2
, op2
, op2d
))
2604 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2607 result
= op1
- op2d
;
2608 if (SubOverflow (op1
, op2d
, result
))
2611 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2614 state
->Reg
[BITS (12, 15)] = result
;
2621 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
2623 /* ARM5 CLZ insn. */
2624 ARMword op1
= state
->Reg
[BITS (0, 3)];
2628 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
2631 state
->Reg
[BITS (12, 15)] = result
;
2636 if (BITS (4, 7) == 0xB)
2638 /* STRH immediate offset, write-back, down, pre indexed. */
2642 if (BITS (4, 7) == 0xD)
2644 Handle_Load_Double (state
, instr
);
2647 if (BITS (4, 7) == 0xF)
2649 Handle_Store_Double (state
, instr
);
2657 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
2663 && handle_v6_insn (state
, instr
))
2670 case 0x17: /* CMNP reg */
2672 if ((BITS (4, 7) & 0x9) == 0x9)
2673 /* LDR immediate offset, write-back, down, pre indexed. */
2675 /* Continue with remaining instruction decoding. */
2680 state
->Cpsr
= GETSPSR (state
->Bank
);
2681 ARMul_CPSRAltered (state
);
2695 ASSIGNZ (dest
== 0);
2696 if ((lhs
| rhs
) >> 30)
2698 /* Possible C,V,N to set. */
2699 ASSIGNN (NEG (dest
));
2700 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2701 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2712 case 0x18: /* ORR reg */
2714 if (BITS (4, 11) == 0xB)
2716 /* STRH register offset, no write-back, up, pre indexed. */
2720 if (BITS (4, 7) == 0xD)
2722 Handle_Load_Double (state
, instr
);
2725 if (BITS (4, 7) == 0xF)
2727 Handle_Store_Double (state
, instr
);
2736 case 0x19: /* ORRS reg */
2738 if ((BITS (4, 11) & 0xF9) == 0x9)
2739 /* LDR register offset, no write-back, up, pre indexed. */
2741 /* Continue with remaining instruction decoding. */
2748 case 0x1a: /* MOV reg */
2750 if (BITS (4, 11) == 0xB)
2752 /* STRH register offset, write-back, up, pre indexed. */
2756 if (BITS (4, 7) == 0xD)
2758 Handle_Load_Double (state
, instr
);
2761 if (BITS (4, 7) == 0xF)
2763 Handle_Store_Double (state
, instr
);
2771 case 0x1b: /* MOVS reg */
2773 if ((BITS (4, 11) & 0xF9) == 0x9)
2774 /* LDR register offset, write-back, up, pre indexed. */
2776 /* Continue with remaining instruction decoding. */
2782 case 0x1c: /* BIC reg */
2784 if (BITS (4, 7) == 0xB)
2786 /* STRH immediate offset, no write-back, up, pre indexed. */
2790 if (BITS (4, 7) == 0xD)
2792 Handle_Load_Double (state
, instr
);
2795 else if (BITS (4, 7) == 0xF)
2797 Handle_Store_Double (state
, instr
);
2806 case 0x1d: /* BICS reg */
2808 if ((BITS (4, 7) & 0x9) == 0x9)
2809 /* LDR immediate offset, no write-back, up, pre indexed. */
2811 /* Continue with instruction decoding. */
2818 case 0x1e: /* MVN reg */
2820 if (BITS (4, 7) == 0xB)
2822 /* STRH immediate offset, write-back, up, pre indexed. */
2826 if (BITS (4, 7) == 0xD)
2828 Handle_Load_Double (state
, instr
);
2831 if (BITS (4, 7) == 0xF)
2833 Handle_Store_Double (state
, instr
);
2841 case 0x1f: /* MVNS reg */
2843 if ((BITS (4, 7) & 0x9) == 0x9)
2844 /* LDR immediate offset, write-back, up, pre indexed. */
2846 /* Continue instruction decoding. */
2853 /* Data Processing Immediate RHS Instructions. */
2855 case 0x20: /* AND immed */
2856 dest
= LHS
& DPImmRHS
;
2860 case 0x21: /* ANDS immed */
2866 case 0x22: /* EOR immed */
2867 dest
= LHS
^ DPImmRHS
;
2871 case 0x23: /* EORS immed */
2877 case 0x24: /* SUB immed */
2878 dest
= LHS
- DPImmRHS
;
2882 case 0x25: /* SUBS immed */
2887 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2889 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2890 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2900 case 0x26: /* RSB immed */
2901 dest
= DPImmRHS
- LHS
;
2905 case 0x27: /* RSBS immed */
2910 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2912 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2913 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2923 case 0x28: /* ADD immed */
2924 dest
= LHS
+ DPImmRHS
;
2928 case 0x29: /* ADDS immed */
2932 ASSIGNZ (dest
== 0);
2934 if ((lhs
| rhs
) >> 30)
2936 /* Possible C,V,N to set. */
2937 ASSIGNN (NEG (dest
));
2938 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2939 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2950 case 0x2a: /* ADC immed */
2951 dest
= LHS
+ DPImmRHS
+ CFLAG
;
2955 case 0x2b: /* ADCS immed */
2958 dest
= lhs
+ rhs
+ CFLAG
;
2959 ASSIGNZ (dest
== 0);
2960 if ((lhs
| rhs
) >> 30)
2962 /* Possible C,V,N to set. */
2963 ASSIGNN (NEG (dest
));
2964 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2965 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2976 case 0x2c: /* SBC immed */
2977 dest
= LHS
- DPImmRHS
- !CFLAG
;
2981 case 0x2d: /* SBCS immed */
2984 dest
= lhs
- rhs
- !CFLAG
;
2985 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2987 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2988 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2998 case 0x2e: /* RSC immed */
2999 dest
= DPImmRHS
- LHS
- !CFLAG
;
3003 case 0x2f: /* RSCS immed */
3006 dest
= rhs
- lhs
- !CFLAG
;
3007 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
3009 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
3010 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
3020 case 0x30: /* MOVW immed */
3023 && handle_v6_insn (state
, instr
))
3026 dest
= BITS (0, 11);
3027 dest
|= (BITS (16, 19) << 12);
3031 case 0x31: /* TSTP immed */
3036 state
->Cpsr
= GETSPSR (state
->Bank
);
3037 ARMul_CPSRAltered (state
);
3039 temp
= LHS
& DPImmRHS
;
3048 ARMul_NegZero (state
, dest
);
3052 case 0x32: /* TEQ immed and MSR immed to CPSR */
3054 /* MSR immed to CPSR. */
3055 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
3057 else if (state
->is_v6
3058 && handle_v6_insn (state
, instr
))
3065 case 0x33: /* TEQP immed */
3070 state
->Cpsr
= GETSPSR (state
->Bank
);
3071 ARMul_CPSRAltered (state
);
3073 temp
= LHS
^ DPImmRHS
;
3079 DPSImmRHS
; /* TEQ immed */
3081 ARMul_NegZero (state
, dest
);
3085 case 0x34: /* MOVT immed */
3088 && handle_v6_insn (state
, instr
))
3092 dest
= BITS (0, 11);
3093 dest
|= (BITS (16, 19) << 12);
3094 DEST
|= (dest
<< 16);
3097 case 0x35: /* CMPP immed */
3102 state
->Cpsr
= GETSPSR (state
->Bank
);
3103 ARMul_CPSRAltered (state
);
3105 temp
= LHS
- DPImmRHS
;
3116 ARMul_NegZero (state
, dest
);
3118 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
3120 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
3121 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
3131 case 0x36: /* CMN immed and MSR immed to SPSR */
3133 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
3135 else if (state
->is_v6
3136 && handle_v6_insn (state
, instr
))
3143 case 0x37: /* CMNP immed. */
3148 state
->Cpsr
= GETSPSR (state
->Bank
);
3149 ARMul_CPSRAltered (state
);
3151 temp
= LHS
+ DPImmRHS
;
3162 ASSIGNZ (dest
== 0);
3163 if ((lhs
| rhs
) >> 30)
3165 /* Possible C,V,N to set. */
3166 ASSIGNN (NEG (dest
));
3167 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
3168 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3179 case 0x38: /* ORR immed. */
3180 dest
= LHS
| DPImmRHS
;
3184 case 0x39: /* ORRS immed. */
3190 case 0x3a: /* MOV immed. */
3195 case 0x3b: /* MOVS immed. */
3200 case 0x3c: /* BIC immed. */
3201 dest
= LHS
& ~DPImmRHS
;
3205 case 0x3d: /* BICS immed. */
3211 case 0x3e: /* MVN immed. */
3216 case 0x3f: /* MVNS immed. */
3222 /* Single Data Transfer Immediate RHS Instructions. */
3224 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
3226 if (StoreWord (state
, instr
, lhs
))
3227 LSBase
= lhs
- LSImmRHS
;
3230 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
3232 if (LoadWord (state
, instr
, lhs
))
3233 LSBase
= lhs
- LSImmRHS
;
3236 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
3237 UNDEF_LSRBaseEQDestWb
;
3240 temp
= lhs
- LSImmRHS
;
3241 state
->NtransSig
= LOW
;
3242 if (StoreWord (state
, instr
, lhs
))
3244 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3247 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
3248 UNDEF_LSRBaseEQDestWb
;
3251 state
->NtransSig
= LOW
;
3252 if (LoadWord (state
, instr
, lhs
))
3253 LSBase
= lhs
- LSImmRHS
;
3254 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3257 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
3259 if (StoreByte (state
, instr
, lhs
))
3260 LSBase
= lhs
- LSImmRHS
;
3263 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
3265 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3266 LSBase
= lhs
- LSImmRHS
;
3269 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
3270 UNDEF_LSRBaseEQDestWb
;
3273 state
->NtransSig
= LOW
;
3274 if (StoreByte (state
, instr
, lhs
))
3275 LSBase
= lhs
- LSImmRHS
;
3276 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3279 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
3280 UNDEF_LSRBaseEQDestWb
;
3283 state
->NtransSig
= LOW
;
3284 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3285 LSBase
= lhs
- LSImmRHS
;
3286 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3289 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
3291 if (StoreWord (state
, instr
, lhs
))
3292 LSBase
= lhs
+ LSImmRHS
;
3295 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
3297 if (LoadWord (state
, instr
, lhs
))
3298 LSBase
= lhs
+ LSImmRHS
;
3301 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
3302 UNDEF_LSRBaseEQDestWb
;
3305 state
->NtransSig
= LOW
;
3306 if (StoreWord (state
, instr
, lhs
))
3307 LSBase
= lhs
+ LSImmRHS
;
3308 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3311 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
3312 UNDEF_LSRBaseEQDestWb
;
3315 state
->NtransSig
= LOW
;
3316 if (LoadWord (state
, instr
, lhs
))
3317 LSBase
= lhs
+ LSImmRHS
;
3318 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3321 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
3323 if (StoreByte (state
, instr
, lhs
))
3324 LSBase
= lhs
+ LSImmRHS
;
3327 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
3329 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3330 LSBase
= lhs
+ LSImmRHS
;
3333 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
3334 UNDEF_LSRBaseEQDestWb
;
3337 state
->NtransSig
= LOW
;
3338 if (StoreByte (state
, instr
, lhs
))
3339 LSBase
= lhs
+ LSImmRHS
;
3340 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3343 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
3344 UNDEF_LSRBaseEQDestWb
;
3347 state
->NtransSig
= LOW
;
3348 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3349 LSBase
= lhs
+ LSImmRHS
;
3350 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3354 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
3355 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
3358 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
3359 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
3362 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
3363 UNDEF_LSRBaseEQDestWb
;
3365 temp
= LHS
- LSImmRHS
;
3366 if (StoreWord (state
, instr
, temp
))
3370 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
3371 UNDEF_LSRBaseEQDestWb
;
3373 temp
= LHS
- LSImmRHS
;
3374 if (LoadWord (state
, instr
, temp
))
3378 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
3379 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
3382 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
3383 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
3386 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
3387 UNDEF_LSRBaseEQDestWb
;
3389 temp
= LHS
- LSImmRHS
;
3390 if (StoreByte (state
, instr
, temp
))
3394 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
3395 UNDEF_LSRBaseEQDestWb
;
3397 temp
= LHS
- LSImmRHS
;
3398 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3402 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
3403 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
3406 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
3407 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
3410 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
3411 UNDEF_LSRBaseEQDestWb
;
3413 temp
= LHS
+ LSImmRHS
;
3414 if (StoreWord (state
, instr
, temp
))
3418 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
3419 UNDEF_LSRBaseEQDestWb
;
3421 temp
= LHS
+ LSImmRHS
;
3422 if (LoadWord (state
, instr
, temp
))
3426 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
3427 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
3430 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
3431 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
3434 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
3435 UNDEF_LSRBaseEQDestWb
;
3437 temp
= LHS
+ LSImmRHS
;
3438 if (StoreByte (state
, instr
, temp
))
3442 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
3443 UNDEF_LSRBaseEQDestWb
;
3445 temp
= LHS
+ LSImmRHS
;
3446 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3451 /* Single Data Transfer Register RHS Instructions. */
3453 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
3458 && handle_v6_insn (state
, instr
))
3461 ARMul_UndefInstr (state
, instr
);
3464 UNDEF_LSRBaseEQOffWb
;
3465 UNDEF_LSRBaseEQDestWb
;
3469 if (StoreWord (state
, instr
, lhs
))
3470 LSBase
= lhs
- LSRegRHS
;
3473 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
3478 && handle_v6_insn (state
, instr
))
3481 ARMul_UndefInstr (state
, instr
);
3484 UNDEF_LSRBaseEQOffWb
;
3485 UNDEF_LSRBaseEQDestWb
;
3489 temp
= lhs
- LSRegRHS
;
3490 if (LoadWord (state
, instr
, lhs
))
3494 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
3499 && handle_v6_insn (state
, instr
))
3502 ARMul_UndefInstr (state
, instr
);
3505 UNDEF_LSRBaseEQOffWb
;
3506 UNDEF_LSRBaseEQDestWb
;
3510 state
->NtransSig
= LOW
;
3511 if (StoreWord (state
, instr
, lhs
))
3512 LSBase
= lhs
- LSRegRHS
;
3513 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3516 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
3521 && handle_v6_insn (state
, instr
))
3524 ARMul_UndefInstr (state
, instr
);
3527 UNDEF_LSRBaseEQOffWb
;
3528 UNDEF_LSRBaseEQDestWb
;
3532 temp
= lhs
- LSRegRHS
;
3533 state
->NtransSig
= LOW
;
3534 if (LoadWord (state
, instr
, lhs
))
3536 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3539 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
3544 && handle_v6_insn (state
, instr
))
3547 ARMul_UndefInstr (state
, instr
);
3550 UNDEF_LSRBaseEQOffWb
;
3551 UNDEF_LSRBaseEQDestWb
;
3555 if (StoreByte (state
, instr
, lhs
))
3556 LSBase
= lhs
- LSRegRHS
;
3559 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
3564 && handle_v6_insn (state
, instr
))
3567 ARMul_UndefInstr (state
, instr
);
3570 UNDEF_LSRBaseEQOffWb
;
3571 UNDEF_LSRBaseEQDestWb
;
3575 temp
= lhs
- LSRegRHS
;
3576 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3580 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
3585 && handle_v6_insn (state
, instr
))
3588 ARMul_UndefInstr (state
, instr
);
3591 UNDEF_LSRBaseEQOffWb
;
3592 UNDEF_LSRBaseEQDestWb
;
3596 state
->NtransSig
= LOW
;
3597 if (StoreByte (state
, instr
, lhs
))
3598 LSBase
= lhs
- LSRegRHS
;
3599 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3602 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
3607 && handle_v6_insn (state
, instr
))
3610 ARMul_UndefInstr (state
, instr
);
3613 UNDEF_LSRBaseEQOffWb
;
3614 UNDEF_LSRBaseEQDestWb
;
3618 temp
= lhs
- LSRegRHS
;
3619 state
->NtransSig
= LOW
;
3620 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3622 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3625 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
3630 && handle_v6_insn (state
, instr
))
3633 ARMul_UndefInstr (state
, instr
);
3636 UNDEF_LSRBaseEQOffWb
;
3637 UNDEF_LSRBaseEQDestWb
;
3641 if (StoreWord (state
, instr
, lhs
))
3642 LSBase
= lhs
+ LSRegRHS
;
3645 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
3650 && handle_v6_insn (state
, instr
))
3653 ARMul_UndefInstr (state
, instr
);
3656 UNDEF_LSRBaseEQOffWb
;
3657 UNDEF_LSRBaseEQDestWb
;
3661 temp
= lhs
+ LSRegRHS
;
3662 if (LoadWord (state
, instr
, lhs
))
3666 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
3671 && handle_v6_insn (state
, instr
))
3674 ARMul_UndefInstr (state
, instr
);
3677 UNDEF_LSRBaseEQOffWb
;
3678 UNDEF_LSRBaseEQDestWb
;
3682 state
->NtransSig
= LOW
;
3683 if (StoreWord (state
, instr
, lhs
))
3684 LSBase
= lhs
+ LSRegRHS
;
3685 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3688 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
3693 && handle_v6_insn (state
, instr
))
3696 ARMul_UndefInstr (state
, instr
);
3699 UNDEF_LSRBaseEQOffWb
;
3700 UNDEF_LSRBaseEQDestWb
;
3704 temp
= lhs
+ LSRegRHS
;
3705 state
->NtransSig
= LOW
;
3706 if (LoadWord (state
, instr
, lhs
))
3708 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3711 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
3716 && handle_v6_insn (state
, instr
))
3719 ARMul_UndefInstr (state
, instr
);
3722 UNDEF_LSRBaseEQOffWb
;
3723 UNDEF_LSRBaseEQDestWb
;
3727 if (StoreByte (state
, instr
, lhs
))
3728 LSBase
= lhs
+ LSRegRHS
;
3731 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
3736 && handle_v6_insn (state
, instr
))
3739 ARMul_UndefInstr (state
, instr
);
3742 UNDEF_LSRBaseEQOffWb
;
3743 UNDEF_LSRBaseEQDestWb
;
3747 temp
= lhs
+ LSRegRHS
;
3748 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3752 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3757 && handle_v6_insn (state
, instr
))
3760 ARMul_UndefInstr (state
, instr
);
3763 UNDEF_LSRBaseEQOffWb
;
3764 UNDEF_LSRBaseEQDestWb
;
3768 state
->NtransSig
= LOW
;
3769 if (StoreByte (state
, instr
, lhs
))
3770 LSBase
= lhs
+ LSRegRHS
;
3771 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3774 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3779 && handle_v6_insn (state
, instr
))
3782 ARMul_UndefInstr (state
, instr
);
3785 UNDEF_LSRBaseEQOffWb
;
3786 UNDEF_LSRBaseEQDestWb
;
3790 temp
= lhs
+ LSRegRHS
;
3791 state
->NtransSig
= LOW
;
3792 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3794 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3798 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3803 && handle_v6_insn (state
, instr
))
3806 ARMul_UndefInstr (state
, instr
);
3809 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
3812 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3817 && handle_v6_insn (state
, instr
))
3820 ARMul_UndefInstr (state
, instr
);
3823 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
3826 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3831 && handle_v6_insn (state
, instr
))
3834 ARMul_UndefInstr (state
, instr
);
3837 UNDEF_LSRBaseEQOffWb
;
3838 UNDEF_LSRBaseEQDestWb
;
3841 temp
= LHS
- LSRegRHS
;
3842 if (StoreWord (state
, instr
, temp
))
3846 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3851 && handle_v6_insn (state
, instr
))
3854 ARMul_UndefInstr (state
, instr
);
3857 UNDEF_LSRBaseEQOffWb
;
3858 UNDEF_LSRBaseEQDestWb
;
3861 temp
= LHS
- LSRegRHS
;
3862 if (LoadWord (state
, instr
, temp
))
3866 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3871 && handle_v6_insn (state
, instr
))
3874 ARMul_UndefInstr (state
, instr
);
3877 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
3880 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3885 && handle_v6_insn (state
, instr
))
3888 ARMul_UndefInstr (state
, instr
);
3891 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
3894 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3899 && handle_v6_insn (state
, instr
))
3902 ARMul_UndefInstr (state
, instr
);
3905 UNDEF_LSRBaseEQOffWb
;
3906 UNDEF_LSRBaseEQDestWb
;
3909 temp
= LHS
- LSRegRHS
;
3910 if (StoreByte (state
, instr
, temp
))
3914 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3919 && handle_v6_insn (state
, instr
))
3922 ARMul_UndefInstr (state
, instr
);
3925 UNDEF_LSRBaseEQOffWb
;
3926 UNDEF_LSRBaseEQDestWb
;
3929 temp
= LHS
- LSRegRHS
;
3930 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3934 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3939 && handle_v6_insn (state
, instr
))
3942 ARMul_UndefInstr (state
, instr
);
3945 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
3948 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
3953 && handle_v6_insn (state
, instr
))
3956 ARMul_UndefInstr (state
, instr
);
3959 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
3962 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
3967 && handle_v6_insn (state
, instr
))
3970 ARMul_UndefInstr (state
, instr
);
3973 UNDEF_LSRBaseEQOffWb
;
3974 UNDEF_LSRBaseEQDestWb
;
3977 temp
= LHS
+ LSRegRHS
;
3978 if (StoreWord (state
, instr
, temp
))
3982 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
3987 && handle_v6_insn (state
, instr
))
3990 ARMul_UndefInstr (state
, instr
);
3993 UNDEF_LSRBaseEQOffWb
;
3994 UNDEF_LSRBaseEQDestWb
;
3997 temp
= LHS
+ LSRegRHS
;
3998 if (LoadWord (state
, instr
, temp
))
4002 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
4007 && handle_v6_insn (state
, instr
))
4010 ARMul_UndefInstr (state
, instr
);
4013 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
4016 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
4021 && handle_v6_insn (state
, instr
))
4024 ARMul_UndefInstr (state
, instr
);
4027 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
4030 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
4035 && handle_v6_insn (state
, instr
))
4038 ARMul_UndefInstr (state
, instr
);
4041 UNDEF_LSRBaseEQOffWb
;
4042 UNDEF_LSRBaseEQDestWb
;
4045 temp
= LHS
+ LSRegRHS
;
4046 if (StoreByte (state
, instr
, temp
))
4050 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
4053 /* Check for the special breakpoint opcode.
4054 This value should correspond to the value defined
4055 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
4056 if (BITS (0, 19) == 0xfdefe)
4058 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
4059 ARMul_Abort (state
, ARMul_SWIV
);
4062 else if (state
->is_v6
4063 && handle_v6_insn (state
, instr
))
4067 ARMul_UndefInstr (state
, instr
);
4070 UNDEF_LSRBaseEQOffWb
;
4071 UNDEF_LSRBaseEQDestWb
;
4074 temp
= LHS
+ LSRegRHS
;
4075 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
4080 /* Multiple Data Transfer Instructions. */
4082 case 0x80: /* Store, No WriteBack, Post Dec. */
4083 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4086 case 0x81: /* Load, No WriteBack, Post Dec. */
4087 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4090 case 0x82: /* Store, WriteBack, Post Dec. */
4091 temp
= LSBase
- LSMNumRegs
;
4092 STOREMULT (instr
, temp
+ 4L, temp
);
4095 case 0x83: /* Load, WriteBack, Post Dec. */
4096 temp
= LSBase
- LSMNumRegs
;
4097 LOADMULT (instr
, temp
+ 4L, temp
);
4100 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
4101 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4104 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
4105 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4108 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
4109 temp
= LSBase
- LSMNumRegs
;
4110 STORESMULT (instr
, temp
+ 4L, temp
);
4113 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
4114 temp
= LSBase
- LSMNumRegs
;
4115 LOADSMULT (instr
, temp
+ 4L, temp
);
4118 case 0x88: /* Store, No WriteBack, Post Inc. */
4119 STOREMULT (instr
, LSBase
, 0L);
4122 case 0x89: /* Load, No WriteBack, Post Inc. */
4123 LOADMULT (instr
, LSBase
, 0L);
4126 case 0x8a: /* Store, WriteBack, Post Inc. */
4128 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
4131 case 0x8b: /* Load, WriteBack, Post Inc. */
4133 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
4136 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
4137 STORESMULT (instr
, LSBase
, 0L);
4140 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
4141 LOADSMULT (instr
, LSBase
, 0L);
4144 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
4146 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
4149 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
4151 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
4154 case 0x90: /* Store, No WriteBack, Pre Dec. */
4155 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4158 case 0x91: /* Load, No WriteBack, Pre Dec. */
4159 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4162 case 0x92: /* Store, WriteBack, Pre Dec. */
4163 temp
= LSBase
- LSMNumRegs
;
4164 STOREMULT (instr
, temp
, temp
);
4167 case 0x93: /* Load, WriteBack, Pre Dec. */
4168 temp
= LSBase
- LSMNumRegs
;
4169 LOADMULT (instr
, temp
, temp
);
4172 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
4173 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4176 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
4177 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4180 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
4181 temp
= LSBase
- LSMNumRegs
;
4182 STORESMULT (instr
, temp
, temp
);
4185 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
4186 temp
= LSBase
- LSMNumRegs
;
4187 LOADSMULT (instr
, temp
, temp
);
4190 case 0x98: /* Store, No WriteBack, Pre Inc. */
4191 STOREMULT (instr
, LSBase
+ 4L, 0L);
4194 case 0x99: /* Load, No WriteBack, Pre Inc. */
4195 LOADMULT (instr
, LSBase
+ 4L, 0L);
4198 case 0x9a: /* Store, WriteBack, Pre Inc. */
4200 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4203 case 0x9b: /* Load, WriteBack, Pre Inc. */
4205 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4208 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
4209 STORESMULT (instr
, LSBase
+ 4L, 0L);
4212 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
4213 LOADSMULT (instr
, LSBase
+ 4L, 0L);
4216 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
4218 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4221 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
4223 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4227 /* Branch forward. */
4236 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4241 /* Branch backward. */
4250 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4254 /* Branch and Link forward. */
4263 /* Put PC into Link. */
4265 state
->Reg
[14] = pc
+ 4;
4267 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4269 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4272 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4275 /* Branch and Link backward. */
4284 /* Put PC into Link. */
4286 state
->Reg
[14] = pc
+ 4;
4288 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4290 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4293 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4296 /* Co-Processor Data Transfers. */
4300 if (CPNum
== 10 || CPNum
== 11)
4301 handle_VFP_move (state
, instr
);
4302 /* Reading from R15 is UNPREDICTABLE. */
4303 else if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
4304 ARMul_UndefInstr (state
, instr
);
4305 /* Is access to coprocessor 0 allowed ? */
4306 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4307 ARMul_UndefInstr (state
, instr
);
4308 /* Special treatment for XScale coprocessors. */
4309 else if (state
->is_XScale
)
4311 /* Only opcode 0 is supported. */
4312 if (BITS (4, 7) != 0x00)
4313 ARMul_UndefInstr (state
, instr
);
4314 /* Only coporcessor 0 is supported. */
4315 else if (CPNum
!= 0x00)
4316 ARMul_UndefInstr (state
, instr
);
4317 /* Only accumulator 0 is supported. */
4318 else if (BITS (0, 3) != 0x00)
4319 ARMul_UndefInstr (state
, instr
);
4322 /* XScale MAR insn. Move two registers into accumulator. */
4323 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
4324 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
4328 /* FIXME: Not sure what to do for other v5 processors. */
4329 ARMul_UndefInstr (state
, instr
);
4334 case 0xc0: /* Store , No WriteBack , Post Dec. */
4335 ARMul_STC (state
, instr
, LHS
);
4341 if (CPNum
== 10 || CPNum
== 11)
4342 handle_VFP_move (state
, instr
);
4343 /* Writes to R15 are UNPREDICATABLE. */
4344 else if (DESTReg
== 15 || LHSReg
== 15)
4345 ARMul_UndefInstr (state
, instr
);
4346 /* Is access to the coprocessor allowed ? */
4347 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4348 ARMul_UndefInstr (state
, instr
);
4349 /* Special handling for XScale coprcoessors. */
4350 else if (state
->is_XScale
)
4352 /* Only opcode 0 is supported. */
4353 if (BITS (4, 7) != 0x00)
4354 ARMul_UndefInstr (state
, instr
);
4355 /* Only coprocessor 0 is supported. */
4356 else if (CPNum
!= 0x00)
4357 ARMul_UndefInstr (state
, instr
);
4358 /* Only accumulator 0 is supported. */
4359 else if (BITS (0, 3) != 0x00)
4360 ARMul_UndefInstr (state
, instr
);
4363 /* XScale MRA insn. Move accumulator into two registers. */
4364 ARMword t1
= (state
->Accumulator
>> 32) & 255;
4369 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
4370 state
->Reg
[BITS (16, 19)] = t1
;
4375 /* FIXME: Not sure what to do for other v5 processors. */
4376 ARMul_UndefInstr (state
, instr
);
4381 case 0xc1: /* Load , No WriteBack , Post Dec. */
4382 ARMul_LDC (state
, instr
, LHS
);
4386 case 0xc6: /* Store , WriteBack , Post Dec. */
4388 state
->Base
= lhs
- LSCOff
;
4389 ARMul_STC (state
, instr
, lhs
);
4393 case 0xc7: /* Load , WriteBack , Post Dec. */
4395 state
->Base
= lhs
- LSCOff
;
4396 ARMul_LDC (state
, instr
, lhs
);
4400 case 0xcc: /* Store , No WriteBack , Post Inc. */
4401 ARMul_STC (state
, instr
, LHS
);
4405 case 0xcd: /* Load , No WriteBack , Post Inc. */
4406 ARMul_LDC (state
, instr
, LHS
);
4410 case 0xce: /* Store , WriteBack , Post Inc. */
4412 state
->Base
= lhs
+ LSCOff
;
4413 ARMul_STC (state
, instr
, LHS
);
4417 case 0xcf: /* Load , WriteBack , Post Inc. */
4419 state
->Base
= lhs
+ LSCOff
;
4420 ARMul_LDC (state
, instr
, LHS
);
4424 case 0xd4: /* Store , No WriteBack , Pre Dec. */
4425 ARMul_STC (state
, instr
, LHS
- LSCOff
);
4429 case 0xd5: /* Load , No WriteBack , Pre Dec. */
4430 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
4434 case 0xd6: /* Store , WriteBack , Pre Dec. */
4437 ARMul_STC (state
, instr
, lhs
);
4441 case 0xd7: /* Load , WriteBack , Pre Dec. */
4444 ARMul_LDC (state
, instr
, lhs
);
4448 case 0xdc: /* Store , No WriteBack , Pre Inc. */
4449 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
4453 case 0xdd: /* Load , No WriteBack , Pre Inc. */
4454 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
4458 case 0xde: /* Store , WriteBack , Pre Inc. */
4461 ARMul_STC (state
, instr
, lhs
);
4465 case 0xdf: /* Load , WriteBack , Pre Inc. */
4468 ARMul_LDC (state
, instr
, lhs
);
4472 /* Co-Processor Register Transfers (MCR) and Data Ops. */
4475 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4477 ARMul_UndefInstr (state
, instr
);
4480 if (state
->is_XScale
)
4481 switch (BITS (18, 19))
4484 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4486 /* XScale MIA instruction. Signed multiplication of
4487 two 32 bit values and addition to 40 bit accumulator. */
4488 ARMsdword Rm
= state
->Reg
[MULLHSReg
];
4489 ARMsdword Rs
= state
->Reg
[MULACCReg
];
4495 state
->Accumulator
+= Rm
* Rs
;
4501 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4503 /* XScale MIAPH instruction. */
4504 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
4505 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
4506 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
4507 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
4522 state
->Accumulator
+= t5
;
4527 state
->Accumulator
+= t5
;
4533 if (BITS (4, 11) == 1)
4535 /* XScale MIAxy instruction. */
4541 t1
= state
->Reg
[MULLHSReg
] >> 16;
4543 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
4546 t2
= state
->Reg
[MULACCReg
] >> 16;
4548 t2
= state
->Reg
[MULACCReg
] & 0xffff;
4558 state
->Accumulator
+= t5
;
4577 if (CPNum
== 10 || CPNum
== 11)
4578 handle_VFP_move (state
, instr
);
4580 else if (DESTReg
== 15)
4584 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
4586 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
4587 ((state
->Reg
[15] + isize
) & R15PCBITS
));
4591 ARMul_MCR (state
, instr
, DEST
);
4595 ARMul_CDP (state
, instr
);
4599 /* Co-Processor Register Transfers (MRC) and Data Ops. */
4610 if (CPNum
== 10 || CPNum
== 11)
4612 switch (BITS (20, 27))
4615 if (BITS (16, 19) == 0x1
4616 && BITS (0, 11) == 0xA10)
4621 ARMul_SetCPSR (state
, (state
->FPSCR
& 0xF0000000)
4622 | (ARMul_GetCPSR (state
) & 0x0FFFFFFF));
4625 fprintf (stderr
, " VFP: VMRS: set flags to %c%c%c%c\n",
4626 ARMul_GetCPSR (state
) & NBIT
? 'N' : '-',
4627 ARMul_GetCPSR (state
) & ZBIT
? 'Z' : '-',
4628 ARMul_GetCPSR (state
) & CBIT
? 'C' : '-',
4629 ARMul_GetCPSR (state
) & VBIT
? 'V' : '-');
4633 state
->Reg
[DESTReg
] = state
->FPSCR
;
4636 fprintf (stderr
, " VFP: VMRS: r%d = %x\n", DESTReg
, state
->Reg
[DESTReg
]);
4640 fprintf (stderr
, "SIM: VFP: Unimplemented: Compare op\n");
4645 /* VMOV reg <-> single precision. */
4646 if (BITS (0,6) != 0x10 || BITS (8,11) != 0xA)
4647 fprintf (stderr
, "SIM: VFP: Unimplemented: move op\n");
4649 state
->Reg
[BITS (12, 15)] = VFP_uword (BITS (16, 19) << 1 | BIT (7));
4651 VFP_uword (BITS (16, 19) << 1 | BIT (7)) = state
->Reg
[BITS (12, 15)];
4655 fprintf (stderr
, "SIM: VFP: Unimplemented: CDP op\n");
4662 temp
= ARMul_MRC (state
, instr
);
4665 ASSIGNN ((temp
& NBIT
) != 0);
4666 ASSIGNZ ((temp
& ZBIT
) != 0);
4667 ASSIGNC ((temp
& CBIT
) != 0);
4668 ASSIGNV ((temp
& VBIT
) != 0);
4676 ARMul_CDP (state
, instr
);
4680 /* SWI instruction. */
4697 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
4699 /* A prefetch abort. */
4700 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
4701 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
4705 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
4706 ARMul_Abort (state
, ARMul_SWIV
);
4716 if (state
->Emulate
== ONCE
)
4717 state
->Emulate
= STOP
;
4718 /* If we have changed mode, allow the PC to advance before stopping. */
4719 else if (state
->Emulate
== CHANGEMODE
)
4721 else if (state
->Emulate
!= RUN
)
4724 while (!stop_simulator
);
4726 state
->decoded
= decoded
;
4727 state
->loaded
= loaded
;
4733 /* This routine evaluates most Data Processing register RHS's with the S
4734 bit clear. It is intended to be called from the macro DPRegRHS, which
4735 filters the common case of an unshifted register with in line code. */
4738 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
4740 ARMword shamt
, base
;
4745 /* Shift amount in a register. */
4750 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4753 base
= state
->Reg
[base
];
4754 ARMul_Icycles (state
, 1, 0L);
4755 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4756 switch ((int) BITS (5, 6))
4761 else if (shamt
>= 32)
4764 return (base
<< shamt
);
4768 else if (shamt
>= 32)
4771 return (base
>> shamt
);
4775 else if (shamt
>= 32)
4776 return ((ARMword
) ((ARMsword
) base
>> 31L));
4778 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4784 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4789 /* Shift amount is a constant. */
4792 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4795 base
= state
->Reg
[base
];
4796 shamt
= BITS (7, 11);
4797 switch ((int) BITS (5, 6))
4800 return (base
<< shamt
);
4805 return (base
>> shamt
);
4808 return ((ARMword
) ((ARMsword
) base
>> 31L));
4810 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4814 return ((base
>> 1) | (CFLAG
<< 31));
4816 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4823 /* This routine evaluates most Logical Data Processing register RHS's
4824 with the S bit set. It is intended to be called from the macro
4825 DPSRegRHS, which filters the common case of an unshifted register
4826 with in line code. */
4829 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
4831 ARMword shamt
, base
;
4836 /* Shift amount in a register. */
4841 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4844 base
= state
->Reg
[base
];
4845 ARMul_Icycles (state
, 1, 0L);
4846 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4847 switch ((int) BITS (5, 6))
4852 else if (shamt
== 32)
4857 else if (shamt
> 32)
4864 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4865 return (base
<< shamt
);
4870 else if (shamt
== 32)
4872 ASSIGNC (base
>> 31);
4875 else if (shamt
> 32)
4882 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4883 return (base
>> shamt
);
4888 else if (shamt
>= 32)
4890 ASSIGNC (base
>> 31L);
4891 return ((ARMword
) ((ARMsword
) base
>> 31L));
4895 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4896 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4904 ASSIGNC (base
>> 31);
4909 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4910 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4916 /* Shift amount is a constant. */
4919 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4922 base
= state
->Reg
[base
];
4923 shamt
= BITS (7, 11);
4925 switch ((int) BITS (5, 6))
4928 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4929 return (base
<< shamt
);
4933 ASSIGNC (base
>> 31);
4938 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4939 return (base
>> shamt
);
4944 ASSIGNC (base
>> 31L);
4945 return ((ARMword
) ((ARMsword
) base
>> 31L));
4949 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4950 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4958 return ((base
>> 1) | (shamt
<< 31));
4962 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4963 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4971 /* This routine handles writes to register 15 when the S bit is not set. */
4974 WriteR15 (ARMul_State
* state
, ARMword src
)
4976 /* The ARM documentation states that the two least significant bits
4977 are discarded when setting PC, except in the cases handled by
4978 WriteR15Branch() below. It's probably an oversight: in THUMB
4979 mode, the second least significant bit should probably not be
4989 state
->Reg
[15] = src
& PCBITS
;
4991 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
4992 ARMul_R15Altered (state
);
4997 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5000 /* This routine handles writes to register 15 when the S bit is set. */
5003 WriteSR15 (ARMul_State
* state
, ARMword src
)
5006 if (state
->Bank
> 0)
5008 state
->Cpsr
= state
->Spsr
[state
->Bank
];
5009 ARMul_CPSRAltered (state
);
5017 state
->Reg
[15] = src
& PCBITS
;
5021 /* ARMul_R15Altered would have to support it. */
5027 if (state
->Bank
== USERBANK
)
5028 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
5030 state
->Reg
[15] = src
;
5032 ARMul_R15Altered (state
);
5036 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5039 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
5040 will switch to Thumb mode if the least significant bit is set. */
5043 WriteR15Branch (ARMul_State
* state
, ARMword src
)
5050 state
->Reg
[15] = src
& 0xfffffffe;
5055 state
->Reg
[15] = src
& 0xfffffffc;
5059 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5061 WriteR15 (state
, src
);
5065 /* Before ARM_v5 LDR and LDM of pc did not change mode. */
5068 WriteR15Load (ARMul_State
* state
, ARMword src
)
5071 WriteR15Branch (state
, src
);
5073 WriteR15 (state
, src
);
5076 /* This routine evaluates most Load and Store register RHS's. It is
5077 intended to be called from the macro LSRegRHS, which filters the
5078 common case of an unshifted register with in line code. */
5081 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
5083 ARMword shamt
, base
;
5088 /* Now forbidden, but ... */
5089 base
= ECC
| ER15INT
| R15PC
| EMODE
;
5092 base
= state
->Reg
[base
];
5094 shamt
= BITS (7, 11);
5095 switch ((int) BITS (5, 6))
5098 return (base
<< shamt
);
5103 return (base
>> shamt
);
5106 return ((ARMword
) ((ARMsword
) base
>> 31L));
5108 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
5112 return ((base
>> 1) | (CFLAG
<< 31));
5114 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
5121 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
5124 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
5131 /* Now forbidden, but ... */
5132 return ECC
| ER15INT
| R15PC
| EMODE
;
5134 return state
->Reg
[RHSReg
];
5138 return BITS (0, 3) | (BITS (8, 11) << 4);
5141 /* This function does the work of loading a word for a LDR instruction. */
5144 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5150 if (ADDREXCEPT (address
))
5151 INTERNALABORT (address
);
5154 dest
= ARMul_LoadWordN (state
, address
);
5159 return state
->lateabtSig
;
5162 dest
= ARMul_Align (state
, address
, dest
);
5164 ARMul_Icycles (state
, 1, 0L);
5166 return (DESTReg
!= LHSReg
);
5170 /* This function does the work of loading a halfword. */
5173 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
5180 if (ADDREXCEPT (address
))
5181 INTERNALABORT (address
);
5183 dest
= ARMul_LoadHalfWord (state
, address
);
5187 return state
->lateabtSig
;
5191 if (dest
& 1 << (16 - 1))
5192 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
5195 ARMul_Icycles (state
, 1, 0L);
5196 return (DESTReg
!= LHSReg
);
5201 /* This function does the work of loading a byte for a LDRB instruction. */
5204 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
5210 if (ADDREXCEPT (address
))
5211 INTERNALABORT (address
);
5213 dest
= ARMul_LoadByte (state
, address
);
5217 return state
->lateabtSig
;
5221 if (dest
& 1 << (8 - 1))
5222 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
5225 ARMul_Icycles (state
, 1, 0L);
5227 return (DESTReg
!= LHSReg
);
5230 /* This function does the work of loading two words for a LDRD instruction. */
5233 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
5237 ARMword write_back
= BIT (21);
5238 ARMword immediate
= BIT (22);
5239 ARMword add_to_base
= BIT (23);
5240 ARMword pre_indexed
= BIT (24);
5250 /* If the writeback bit is set, the pre-index bit must be clear. */
5251 if (write_back
&& ! pre_indexed
)
5253 ARMul_UndefInstr (state
, instr
);
5257 /* Extract the base address register. */
5260 /* Extract the destination register and check it. */
5263 /* Destination register must be even. */
5265 /* Destination register cannot be LR. */
5266 || (dest_reg
== 14))
5268 ARMul_UndefInstr (state
, instr
);
5272 /* Compute the base address. */
5273 base
= state
->Reg
[addr_reg
];
5275 /* Compute the offset. */
5276 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5278 /* Compute the sum of the two. */
5280 sum
= base
+ offset
;
5282 sum
= base
- offset
;
5284 /* If this is a pre-indexed mode use the sum. */
5290 if (state
->is_v6
&& (addr
& 0x3) == 0)
5291 /* Word alignment is enough for v6. */
5293 /* The address must be aligned on a 8 byte boundary. */
5294 else if (addr
& 0x7)
5297 ARMul_DATAABORT (addr
);
5299 ARMul_UndefInstr (state
, instr
);
5304 /* For pre indexed or post indexed addressing modes,
5305 check that the destination registers do not overlap
5306 the address registers. */
5307 if ((! pre_indexed
|| write_back
)
5308 && ( addr_reg
== dest_reg
5309 || addr_reg
== dest_reg
+ 1))
5311 ARMul_UndefInstr (state
, instr
);
5315 /* Load the words. */
5316 value1
= ARMul_LoadWordN (state
, addr
);
5317 value2
= ARMul_LoadWordN (state
, addr
+ 4);
5319 /* Check for data aborts. */
5326 ARMul_Icycles (state
, 2, 0L);
5328 /* Store the values. */
5329 state
->Reg
[dest_reg
] = value1
;
5330 state
->Reg
[dest_reg
+ 1] = value2
;
5332 /* Do the post addressing and writeback. */
5336 if (! pre_indexed
|| write_back
)
5337 state
->Reg
[addr_reg
] = addr
;
5340 /* This function does the work of storing two words for a STRD instruction. */
5343 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
5347 ARMword write_back
= BIT (21);
5348 ARMword immediate
= BIT (22);
5349 ARMword add_to_base
= BIT (23);
5350 ARMword pre_indexed
= BIT (24);
5358 /* If the writeback bit is set, the pre-index bit must be clear. */
5359 if (write_back
&& ! pre_indexed
)
5361 ARMul_UndefInstr (state
, instr
);
5365 /* Extract the base address register. */
5368 /* Base register cannot be PC. */
5371 ARMul_UndefInstr (state
, instr
);
5375 /* Extract the source register. */
5378 /* Source register must be even. */
5381 ARMul_UndefInstr (state
, instr
);
5385 /* Compute the base address. */
5386 base
= state
->Reg
[addr_reg
];
5388 /* Compute the offset. */
5389 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5391 /* Compute the sum of the two. */
5393 sum
= base
+ offset
;
5395 sum
= base
- offset
;
5397 /* If this is a pre-indexed mode use the sum. */
5403 /* The address must be aligned on a 8 byte boundary. */
5407 ARMul_DATAABORT (addr
);
5409 ARMul_UndefInstr (state
, instr
);
5414 /* For pre indexed or post indexed addressing modes,
5415 check that the destination registers do not overlap
5416 the address registers. */
5417 if ((! pre_indexed
|| write_back
)
5418 && ( addr_reg
== src_reg
5419 || addr_reg
== src_reg
+ 1))
5421 ARMul_UndefInstr (state
, instr
);
5425 /* Load the words. */
5426 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
5427 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
5435 /* Do the post addressing and writeback. */
5439 if (! pre_indexed
|| write_back
)
5440 state
->Reg
[addr_reg
] = addr
;
5443 /* This function does the work of storing a word from a STR instruction. */
5446 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5451 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5454 ARMul_StoreWordN (state
, address
, DEST
);
5456 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5458 INTERNALABORT (address
);
5459 (void) ARMul_LoadWordN (state
, address
);
5462 ARMul_StoreWordN (state
, address
, DEST
);
5467 return state
->lateabtSig
;
5473 /* This function does the work of storing a byte for a STRH instruction. */
5476 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5482 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5486 ARMul_StoreHalfWord (state
, address
, DEST
);
5488 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5490 INTERNALABORT (address
);
5491 (void) ARMul_LoadHalfWord (state
, address
);
5494 ARMul_StoreHalfWord (state
, address
, DEST
);
5500 return state
->lateabtSig
;
5507 /* This function does the work of storing a byte for a STRB instruction. */
5510 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
5515 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5518 ARMul_StoreByte (state
, address
, DEST
);
5520 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5522 INTERNALABORT (address
);
5523 (void) ARMul_LoadByte (state
, address
);
5526 ARMul_StoreByte (state
, address
, DEST
);
5531 return state
->lateabtSig
;
5537 /* This function does the work of loading the registers listed in an LDM
5538 instruction, when the S bit is clear. The code here is always increment
5539 after, it's up to the caller to get the input address correct and to
5540 handle base register modification. */
5543 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
5549 UNDEF_LSMBaseInListWb
;
5552 if (ADDREXCEPT (address
))
5553 INTERNALABORT (address
);
5555 if (BIT (21) && LHSReg
!= 15)
5558 /* N cycle first. */
5559 for (temp
= 0; !BIT (temp
); temp
++)
5562 dest
= ARMul_LoadWordN (state
, address
);
5564 if (!state
->abortSig
&& !state
->Aborted
)
5565 state
->Reg
[temp
++] = dest
;
5566 else if (!state
->Aborted
)
5568 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5569 state
->Aborted
= ARMul_DataAbortV
;
5572 /* S cycles from here on. */
5573 for (; temp
< 16; temp
++)
5576 /* Load this register. */
5578 dest
= ARMul_LoadWordS (state
, address
);
5580 if (!state
->abortSig
&& !state
->Aborted
)
5581 state
->Reg
[temp
] = dest
;
5582 else if (!state
->Aborted
)
5584 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5585 state
->Aborted
= ARMul_DataAbortV
;
5589 if (BIT (15) && !state
->Aborted
)
5590 /* PC is in the reg list. */
5591 WriteR15Load (state
, PC
);
5593 /* To write back the final register. */
5594 ARMul_Icycles (state
, 1, 0L);
5598 if (BIT (21) && LHSReg
!= 15)
5604 /* This function does the work of loading the registers listed in an LDM
5605 instruction, when the S bit is set. The code here is always increment
5606 after, it's up to the caller to get the input address correct and to
5607 handle base register modification. */
5610 LoadSMult (ARMul_State
* state
,
5619 UNDEF_LSMBaseInListWb
;
5624 if (ADDREXCEPT (address
))
5625 INTERNALABORT (address
);
5628 if (BIT (21) && LHSReg
!= 15)
5631 if (!BIT (15) && state
->Bank
!= USERBANK
)
5633 /* Temporary reg bank switch. */
5634 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5635 UNDEF_LSMUserBankWb
;
5638 /* N cycle first. */
5639 for (temp
= 0; !BIT (temp
); temp
++)
5642 dest
= ARMul_LoadWordN (state
, address
);
5644 if (!state
->abortSig
)
5645 state
->Reg
[temp
++] = dest
;
5646 else if (!state
->Aborted
)
5648 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5649 state
->Aborted
= ARMul_DataAbortV
;
5652 /* S cycles from here on. */
5653 for (; temp
< 16; temp
++)
5656 /* Load this register. */
5658 dest
= ARMul_LoadWordS (state
, address
);
5660 if (!state
->abortSig
&& !state
->Aborted
)
5661 state
->Reg
[temp
] = dest
;
5662 else if (!state
->Aborted
)
5664 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5665 state
->Aborted
= ARMul_DataAbortV
;
5669 if (BIT (15) && !state
->Aborted
)
5671 /* PC is in the reg list. */
5673 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5675 state
->Cpsr
= GETSPSR (state
->Bank
);
5676 ARMul_CPSRAltered (state
);
5679 WriteR15 (state
, PC
);
5681 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
5683 /* Protect bits in user mode. */
5684 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
5685 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
5686 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
5687 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
5690 ARMul_R15Altered (state
);
5696 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5697 /* Restore the correct bank. */
5698 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5700 /* To write back the final register. */
5701 ARMul_Icycles (state
, 1, 0L);
5705 if (BIT (21) && LHSReg
!= 15)
5712 /* This function does the work of storing the registers listed in an STM
5713 instruction, when the S bit is clear. The code here is always increment
5714 after, it's up to the caller to get the input address correct and to
5715 handle base register modification. */
5718 StoreMult (ARMul_State
* state
,
5727 UNDEF_LSMBaseInListWb
;
5730 /* N-cycle, increment the PC and update the NextInstr state. */
5734 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5735 INTERNALABORT (address
);
5741 /* N cycle first. */
5742 for (temp
= 0; !BIT (temp
); temp
++)
5746 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5750 (void) ARMul_LoadWordN (state
, address
);
5752 /* Fake the Stores as Loads. */
5753 for (; temp
< 16; temp
++)
5756 /* Save this register. */
5758 (void) ARMul_LoadWordS (state
, address
);
5761 if (BIT (21) && LHSReg
!= 15)
5767 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5770 if (state
->abortSig
&& !state
->Aborted
)
5772 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5773 state
->Aborted
= ARMul_DataAbortV
;
5776 if (BIT (21) && LHSReg
!= 15)
5779 /* S cycles from here on. */
5780 for (; temp
< 16; temp
++)
5783 /* Save this register. */
5786 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5788 if (state
->abortSig
&& !state
->Aborted
)
5790 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5791 state
->Aborted
= ARMul_DataAbortV
;
5799 /* This function does the work of storing the registers listed in an STM
5800 instruction when the S bit is set. The code here is always increment
5801 after, it's up to the caller to get the input address correct and to
5802 handle base register modification. */
5805 StoreSMult (ARMul_State
* state
,
5814 UNDEF_LSMBaseInListWb
;
5819 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5820 INTERNALABORT (address
);
5826 if (state
->Bank
!= USERBANK
)
5828 /* Force User Bank. */
5829 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5830 UNDEF_LSMUserBankWb
;
5833 for (temp
= 0; !BIT (temp
); temp
++)
5834 ; /* N cycle first. */
5837 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5841 (void) ARMul_LoadWordN (state
, address
);
5843 for (; temp
< 16; temp
++)
5844 /* Fake the Stores as Loads. */
5847 /* Save this register. */
5850 (void) ARMul_LoadWordS (state
, address
);
5853 if (BIT (21) && LHSReg
!= 15)
5860 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5863 if (state
->abortSig
&& !state
->Aborted
)
5865 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5866 state
->Aborted
= ARMul_DataAbortV
;
5869 /* S cycles from here on. */
5870 for (; temp
< 16; temp
++)
5873 /* Save this register. */
5876 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5878 if (state
->abortSig
&& !state
->Aborted
)
5880 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5881 state
->Aborted
= ARMul_DataAbortV
;
5885 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5886 /* Restore the correct bank. */
5887 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5889 if (BIT (21) && LHSReg
!= 15)
5896 /* This function does the work of adding two 32bit values
5897 together, and calculating if a carry has occurred. */
5900 Add32 (ARMword a1
, ARMword a2
, int *carry
)
5902 ARMword result
= (a1
+ a2
);
5903 unsigned int uresult
= (unsigned int) result
;
5904 unsigned int ua1
= (unsigned int) a1
;
5906 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5907 or (result > RdLo) then we have no carry. */
5908 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
5916 /* This function does the work of multiplying
5917 two 32bit values to give a 64bit result. */
5920 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5922 /* Operand register numbers. */
5923 int nRdHi
, nRdLo
, nRs
, nRm
;
5924 ARMword RdHi
= 0, RdLo
= 0, Rm
;
5928 nRdHi
= BITS (16, 19);
5929 nRdLo
= BITS (12, 15);
5933 /* Needed to calculate the cycle count. */
5934 Rm
= state
->Reg
[nRm
];
5936 /* Check for illegal operand combinations first. */
5943 /* Intermediate results. */
5944 ARMword lo
, mid1
, mid2
, hi
;
5946 ARMword Rs
= state
->Reg
[nRs
];
5954 if (nRdHi
== nRm
|| nRdLo
== nRm
)
5955 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS: %d %d %d\n",
5960 /* Compute sign of result and adjust operands if necessary. */
5961 sign
= (Rm
^ Rs
) & 0x80000000;
5963 if (((ARMsword
) Rm
) < 0)
5966 if (((ARMsword
) Rs
) < 0)
5970 /* We can split the 32x32 into four 16x16 operations. This
5971 ensures that we do not lose precision on 32bit only hosts. */
5972 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
5973 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5974 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
5975 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
5977 /* We now need to add all of these results together, taking
5978 care to propogate the carries from the additions. */
5979 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
5981 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
5983 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
5987 /* Negate result if necessary. */
5990 if (RdLo
== 0xFFFFFFFF)
5999 state
->Reg
[nRdLo
] = RdLo
;
6000 state
->Reg
[nRdHi
] = RdHi
;
6003 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
6006 /* Ensure that both RdHi and RdLo are used to compute Z,
6007 but don't let RdLo's sign bit make it to N. */
6008 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6010 /* The cycle count depends on whether the instruction is a signed or
6011 unsigned multiply, and what bits are clear in the multiplier. */
6012 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
6013 /* Invert the bits to make the check against zero. */
6016 if ((Rm
& 0xFFFFFF00) == 0)
6018 else if ((Rm
& 0xFFFF0000) == 0)
6020 else if ((Rm
& 0xFF000000) == 0)
6028 /* This function does the work of multiplying two 32bit
6029 values and adding a 64bit value to give a 64bit result. */
6032 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
6039 nRdHi
= BITS (16, 19);
6040 nRdLo
= BITS (12, 15);
6042 RdHi
= state
->Reg
[nRdHi
];
6043 RdLo
= state
->Reg
[nRdLo
];
6045 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
6047 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
6048 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
6050 state
->Reg
[nRdLo
] = RdLo
;
6051 state
->Reg
[nRdHi
] = RdHi
;
6054 /* Ensure that both RdHi and RdLo are used to compute Z,
6055 but don't let RdLo's sign bit make it to N. */
6056 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6058 /* Extra cycle for addition. */
This page took 0.241999 seconds and 4 git commands to generate.