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
;
922 /* SDIV<c> <Rd>,<Rn>,<Rm>
923 UDIV<c> <Rd>,<Rn>,<Rm>
925 instr[27,20] = 0111 0001 (SDIV), 0111 0011 (UDIV)
932 /* These bit-positions are confusing!
934 instr[11, 8] = 1111 */
936 #if 0 /* This is what I would expect: */
940 #else /* This seem to work: */
945 if (Rn
== 15 || Rd
== 15 || Rm
== 15
946 || Rn
== 13 || Rd
== 13 || Rm
== 13)
948 ARMul_UndefInstr (state
, instr
);
949 state
->Emulate
= FALSE
;
953 valn
= state
->Reg
[Rn
];
954 valm
= state
->Reg
[Rm
];
959 /* Exceptions: UsageFault, address 20
960 Note: UsageFault is for Cortex-M; I don't know what it would be on non-Cortex-M. */
961 ARMul_Abort (state
, address
);
963 printf ("Unhandled v6 insn: %cDIV divide by zero exception\n", "SU"[BIT(21)]);
973 val
= ((ARMsword
)valn
/ (ARMsword
)valm
);
975 state
->Reg
[Rd
] = val
;
987 /* BFC<c> <Rd>,#<lsb>,#<width>
988 BFI<c> <Rd>,<Rn>,#<lsb>,#<width>
991 instr[27,21] = 0111 110
995 instr[ 6, 4] = 001 1111
996 instr[ 3, 0] = Rn (BFI) / 1111 (BFC). */
998 if (BITS (4, 6) != 0x1)
1004 ARMul_UndefInstr (state
, instr
);
1005 state
->Emulate
= FALSE
;
1009 msb
= BITS (16, 20);
1012 ARMul_UndefInstr (state
, instr
);
1013 state
->Emulate
= FALSE
;
1017 mask
&= ~(-(1 << (msb
+ 1)));
1018 state
->Reg
[Rd
] &= ~ mask
;
1023 ARMword val
= state
->Reg
[Rn
] & ~(-(1 << ((msb
+ 1) - lsb
)));
1024 state
->Reg
[Rd
] |= val
<< lsb
;
1029 case 0x7a: /* SBFX<c> <Rd>,<Rn>,#<lsb>,#<width>. */
1035 if (BITS (4, 6) != 0x5)
1041 ARMul_UndefInstr (state
, instr
);
1042 state
->Emulate
= FALSE
;
1048 ARMul_UndefInstr (state
, instr
);
1049 state
->Emulate
= FALSE
;
1053 widthm1
= BITS (16, 20);
1055 sval
= state
->Reg
[Rn
];
1056 sval
<<= (31 - (lsb
+ widthm1
));
1057 sval
>>= (31 - widthm1
);
1058 state
->Reg
[Rd
] = sval
;
1069 /* UBFX<c> <Rd>,<Rn>,#<lsb>,#<width>
1071 instr[27,21] = 0111 111
1072 instr[20,16] = widthm1
1076 instr[ 3, 0] = Rn. */
1078 if (BITS (4, 6) != 0x5)
1084 ARMul_UndefInstr (state
, instr
);
1085 state
->Emulate
= FALSE
;
1091 ARMul_UndefInstr (state
, instr
);
1092 state
->Emulate
= FALSE
;
1096 widthm1
= BITS (16, 20);
1098 val
= state
->Reg
[Rn
];
1100 val
&= ~(-(1 << (widthm1
+ 1)));
1102 state
->Reg
[Rd
] = val
;
1107 case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
1112 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr
);
1118 handle_VFP_move (ARMul_State
* state
, ARMword instr
)
1120 switch (BITS (20, 27))
1124 switch (BITS (4, 11))
1129 /* VMOV two core <-> two VFP single precision. */
1130 int sreg
= (BITS (0, 3) << 1) | BIT (5);
1134 state
->Reg
[BITS (12, 15)] = VFP_uword (sreg
);
1135 state
->Reg
[BITS (16, 19)] = VFP_uword (sreg
+ 1);
1139 VFP_uword (sreg
) = state
->Reg
[BITS (12, 15)];
1140 VFP_uword (sreg
+ 1) = state
->Reg
[BITS (16, 19)];
1148 /* VMOV two core <-> VFP double precision. */
1149 int dreg
= BITS (0, 3) | (BIT (5) << 4);
1154 fprintf (stderr
, " VFP: VMOV: r%d r%d <= d%d\n",
1155 BITS (12, 15), BITS (16, 19), dreg
);
1157 state
->Reg
[BITS (12, 15)] = VFP_dword (dreg
);
1158 state
->Reg
[BITS (16, 19)] = VFP_dword (dreg
) >> 32;
1162 VFP_dword (dreg
) = state
->Reg
[BITS (16, 19)];
1163 VFP_dword (dreg
) <<= 32;
1164 VFP_dword (dreg
) |= state
->Reg
[BITS (12, 15)];
1167 fprintf (stderr
, " VFP: VMOV: d%d <= r%d r%d : %g\n",
1168 dreg
, BITS (16, 19), BITS (12, 15),
1175 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1182 /* VMOV single core <-> VFP single precision. */
1183 if (BITS (0, 6) != 0x10 || BITS (8, 11) != 0xA)
1184 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1187 int sreg
= (BITS (16, 19) << 1) | BIT (7);
1190 state
->Reg
[DESTReg
] = VFP_uword (sreg
);
1192 VFP_uword (sreg
) = state
->Reg
[DESTReg
];
1197 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1202 /* EMULATION of ARM6. */
1206 ARMul_Emulate32 (ARMul_State
* state
)
1208 ARMul_Emulate26 (ARMul_State
* state
)
1211 ARMword instr
; /* The current instruction. */
1212 ARMword dest
= 0; /* Almost the DestBus. */
1213 ARMword temp
; /* Ubiquitous third hand. */
1214 ARMword pc
= 0; /* The address of the current instruction. */
1215 ARMword lhs
; /* Almost the ABus and BBus. */
1217 ARMword decoded
= 0; /* Instruction pipeline. */
1220 /* Execute the next instruction. */
1222 if (state
->NextInstr
< PRIMEPIPE
)
1224 decoded
= state
->decoded
;
1225 loaded
= state
->loaded
;
1231 /* Just keep going. */
1234 switch (state
->NextInstr
)
1237 /* Advance the pipeline, and an S cycle. */
1238 state
->Reg
[15] += isize
;
1242 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1246 /* Advance the pipeline, and an N cycle. */
1247 state
->Reg
[15] += isize
;
1251 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
1256 /* Program counter advanced, and an S cycle. */
1260 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1265 /* Program counter advanced, and an N cycle. */
1269 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
1274 /* The program counter has been changed. */
1275 pc
= state
->Reg
[15];
1277 pc
= pc
& R15PCBITS
;
1279 state
->Reg
[15] = pc
+ (isize
* 2);
1281 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
1282 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
1283 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
1288 /* The program counter has been changed. */
1289 pc
= state
->Reg
[15];
1291 pc
= pc
& R15PCBITS
;
1293 state
->Reg
[15] = pc
+ (isize
* 2);
1295 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
1296 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
1297 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1302 if (state
->EventSet
)
1303 ARMul_EnvokeEvent (state
);
1305 if (! TFLAG
&& trace
)
1307 fprintf (stderr
, "pc: %x, ", pc
& ~1);
1309 fprintf (stderr
, "instr: %x\n", instr
);
1312 if (instr
== 0 || pc
< 0x10)
1314 ARMul_Abort (state
, ARMUndefinedInstrV
);
1315 state
->Emulate
= FALSE
;
1318 #if 0 /* Enable this code to help track down stack alignment bugs. */
1320 static ARMword old_sp
= -1;
1322 if (old_sp
!= state
->Reg
[13])
1324 old_sp
= state
->Reg
[13];
1325 fprintf (stderr
, "pc: %08x: SP set to %08x%s\n",
1326 pc
& ~1, old_sp
, (old_sp
% 8) ? " [UNALIGNED!]" : "");
1331 if (state
->Exception
)
1333 /* Any exceptions ? */
1334 if (state
->NresetSig
== LOW
)
1336 ARMul_Abort (state
, ARMul_ResetV
);
1339 else if (!state
->NfiqSig
&& !FFLAG
)
1341 ARMul_Abort (state
, ARMul_FIQV
);
1344 else if (!state
->NirqSig
&& !IFLAG
)
1346 ARMul_Abort (state
, ARMul_IRQV
);
1351 if (state
->CallDebug
> 0)
1353 if (state
->Emulate
< ONCE
)
1355 state
->NextInstr
= RESUME
;
1360 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n",
1361 (long) pc
, (long) instr
, (long) state
->Mode
);
1362 (void) fgetc (stdin
);
1365 else if (state
->Emulate
< ONCE
)
1367 state
->NextInstr
= RESUME
;
1374 /* Provide Thumb instruction decoding. If the processor is in Thumb
1375 mode, then we can simply decode the Thumb instruction, and map it
1376 to the corresponding ARM instruction (by directly loading the
1377 instr variable, and letting the normal ARM simulator
1378 execute). There are some caveats to ensure that the correct
1379 pipelined PC value is used when executing Thumb code, and also for
1380 dealing with the BL instruction. */
1385 /* Check if in Thumb mode. */
1386 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
1389 /* This is a Thumb instruction. */
1390 ARMul_UndefInstr (state
, instr
);
1394 /* Already processed. */
1398 /* ARM instruction available. */
1401 fprintf (stderr
, " emulate as: ");
1403 fprintf (stderr
, "%08x ", new);
1405 fprintf (stderr
, "\n");
1408 /* So continue instruction decoding. */
1418 /* Check the condition codes. */
1419 if ((temp
= TOPBITS (28)) == AL
)
1420 /* Vile deed in the need for speed. */
1423 /* Check the condition code. */
1424 switch ((int) TOPBITS (28))
1432 if (BITS (25, 27) == 5) /* BLX(1) */
1436 state
->Reg
[14] = pc
+ 4;
1438 /* Force entry into Thumb mode. */
1441 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
1443 dest
+= POSBRANCH
+ (BIT (24) << 1);
1445 WriteR15Branch (state
, dest
);
1448 else if ((instr
& 0xFC70F000) == 0xF450F000)
1449 /* The PLD instruction. Ignored. */
1451 else if ( ((instr
& 0xfe500f00) == 0xfc100100)
1452 || ((instr
& 0xfe500f00) == 0xfc000100))
1453 /* wldrw and wstrw are unconditional. */
1456 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
1457 ARMul_UndefInstr (state
, instr
);
1486 temp
= (CFLAG
&& !ZFLAG
);
1489 temp
= (!CFLAG
|| ZFLAG
);
1492 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
1495 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
1498 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
1501 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
1505 /* Handle the Clock counter here. */
1506 if (state
->is_XScale
)
1511 ok
= state
->CPRead
[14] (state
, 0, & cp14r0
);
1513 if (ok
&& (cp14r0
& ARMul_CP14_R0_ENABLE
))
1515 unsigned long newcycles
, nowtime
= ARMul_Time (state
);
1517 newcycles
= nowtime
- state
->LastTime
;
1518 state
->LastTime
= nowtime
;
1520 if (cp14r0
& ARMul_CP14_R0_CCD
)
1522 if (state
->CP14R0_CCD
== -1)
1523 state
->CP14R0_CCD
= newcycles
;
1525 state
->CP14R0_CCD
+= newcycles
;
1527 if (state
->CP14R0_CCD
>= 64)
1531 while (state
->CP14R0_CCD
>= 64)
1532 state
->CP14R0_CCD
-= 64, newcycles
++;
1542 state
->CP14R0_CCD
= -1;
1545 cp14r0
|= ARMul_CP14_R0_FLAG2
;
1546 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
1548 ok
= state
->CPRead
[14] (state
, 1, & cp14r1
);
1550 /* Coded like this for portability. */
1551 while (ok
&& newcycles
)
1553 if (cp14r1
== 0xffffffff)
1564 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
1566 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
1570 if (state
->CPRead
[13] (state
, 8, & temp
)
1571 && (temp
& ARMul_CP13_R8_PMUS
))
1572 ARMul_Abort (state
, ARMul_FIQV
);
1574 ARMul_Abort (state
, ARMul_IRQV
);
1580 /* Handle hardware instructions breakpoints here. */
1581 if (state
->is_XScale
)
1583 if ( (pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
1584 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
1586 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
1587 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1591 /* Actual execution of instructions begins here. */
1592 /* If the condition codes don't match, stop here. */
1597 if (state
->is_XScale
)
1599 if (BIT (20) == 0 && BITS (25, 27) == 0)
1601 if (BITS (4, 7) == 0xD)
1603 /* XScale Load Consecutive insn. */
1604 ARMword temp
= GetLS7RHS (state
, instr
);
1605 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
1606 ARMword addr
= BIT (24) ? temp2
: LHS
;
1609 ARMul_UndefInstr (state
, instr
);
1611 /* Alignment violation. */
1612 ARMul_Abort (state
, ARMul_DataAbortV
);
1615 int wb
= BIT (21) || (! BIT (24));
1617 state
->Reg
[BITS (12, 15)] =
1618 ARMul_LoadWordN (state
, addr
);
1619 state
->Reg
[BITS (12, 15) + 1] =
1620 ARMul_LoadWordN (state
, addr
+ 4);
1627 else if (BITS (4, 7) == 0xF)
1629 /* XScale Store Consecutive insn. */
1630 ARMword temp
= GetLS7RHS (state
, instr
);
1631 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
1632 ARMword addr
= BIT (24) ? temp2
: LHS
;
1635 ARMul_UndefInstr (state
, instr
);
1637 /* Alignment violation. */
1638 ARMul_Abort (state
, ARMul_DataAbortV
);
1641 ARMul_StoreWordN (state
, addr
,
1642 state
->Reg
[BITS (12, 15)]);
1643 ARMul_StoreWordN (state
, addr
+ 4,
1644 state
->Reg
[BITS (12, 15) + 1]);
1646 if (BIT (21)|| ! BIT (24))
1654 if (ARMul_HandleIwmmxt (state
, instr
))
1658 switch ((int) BITS (20, 27))
1660 /* Data Processing Register RHS Instructions. */
1662 case 0x00: /* AND reg and MUL */
1664 if (BITS (4, 11) == 0xB)
1666 /* STRH register offset, no write-back, down, post indexed. */
1670 if (BITS (4, 7) == 0xD)
1672 Handle_Load_Double (state
, instr
);
1675 if (BITS (4, 7) == 0xF)
1677 Handle_Store_Double (state
, instr
);
1681 if (BITS (4, 7) == 9)
1684 rhs
= state
->Reg
[MULRHSReg
];
1685 if (MULLHSReg
== MULDESTReg
)
1688 state
->Reg
[MULDESTReg
] = 0;
1690 else if (MULDESTReg
!= 15)
1691 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
1695 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1696 if (rhs
& (1L << dest
))
1699 /* Mult takes this many/2 I cycles. */
1700 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1711 case 0x01: /* ANDS reg and MULS */
1713 if ((BITS (4, 11) & 0xF9) == 0x9)
1714 /* LDR register offset, no write-back, down, post indexed. */
1716 /* Fall through to rest of decoding. */
1718 if (BITS (4, 7) == 9)
1721 rhs
= state
->Reg
[MULRHSReg
];
1723 if (MULLHSReg
== MULDESTReg
)
1726 state
->Reg
[MULDESTReg
] = 0;
1730 else if (MULDESTReg
!= 15)
1732 dest
= state
->Reg
[MULLHSReg
] * rhs
;
1733 ARMul_NegZero (state
, dest
);
1734 state
->Reg
[MULDESTReg
] = dest
;
1739 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1740 if (rhs
& (1L << dest
))
1743 /* Mult takes this many/2 I cycles. */
1744 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1755 case 0x02: /* EOR reg and MLA */
1757 if (BITS (4, 11) == 0xB)
1759 /* STRH register offset, write-back, down, post indexed. */
1764 if (BITS (4, 7) == 9)
1766 rhs
= state
->Reg
[MULRHSReg
];
1767 if (MULLHSReg
== MULDESTReg
)
1770 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
1772 else if (MULDESTReg
!= 15)
1773 state
->Reg
[MULDESTReg
] =
1774 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1778 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1779 if (rhs
& (1L << dest
))
1782 /* Mult takes this many/2 I cycles. */
1783 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1793 case 0x03: /* EORS reg and MLAS */
1795 if ((BITS (4, 11) & 0xF9) == 0x9)
1796 /* LDR register offset, write-back, down, post-indexed. */
1798 /* Fall through to rest of the decoding. */
1800 if (BITS (4, 7) == 9)
1803 rhs
= state
->Reg
[MULRHSReg
];
1805 if (MULLHSReg
== MULDESTReg
)
1808 dest
= state
->Reg
[MULACCReg
];
1809 ARMul_NegZero (state
, dest
);
1810 state
->Reg
[MULDESTReg
] = dest
;
1812 else if (MULDESTReg
!= 15)
1815 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1816 ARMul_NegZero (state
, dest
);
1817 state
->Reg
[MULDESTReg
] = dest
;
1822 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1823 if (rhs
& (1L << dest
))
1826 /* Mult takes this many/2 I cycles. */
1827 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1838 case 0x04: /* SUB reg */
1840 if (BITS (4, 7) == 0xB)
1842 /* STRH immediate offset, no write-back, down, post indexed. */
1846 if (BITS (4, 7) == 0xD)
1848 Handle_Load_Double (state
, instr
);
1851 if (BITS (4, 7) == 0xF)
1853 Handle_Store_Double (state
, instr
);
1862 case 0x05: /* SUBS reg */
1864 if ((BITS (4, 7) & 0x9) == 0x9)
1865 /* LDR immediate offset, no write-back, down, post indexed. */
1867 /* Fall through to the rest of the instruction decoding. */
1873 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1875 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1876 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1886 case 0x06: /* RSB reg */
1888 if (BITS (4, 7) == 0xB)
1890 /* STRH immediate offset, write-back, down, post indexed. */
1900 case 0x07: /* RSBS reg */
1902 if ((BITS (4, 7) & 0x9) == 0x9)
1903 /* LDR immediate offset, write-back, down, post indexed. */
1905 /* Fall through to remainder of instruction decoding. */
1911 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1913 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1914 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1924 case 0x08: /* ADD reg */
1926 if (BITS (4, 11) == 0xB)
1928 /* STRH register offset, no write-back, up, post indexed. */
1932 if (BITS (4, 7) == 0xD)
1934 Handle_Load_Double (state
, instr
);
1937 if (BITS (4, 7) == 0xF)
1939 Handle_Store_Double (state
, instr
);
1944 if (BITS (4, 7) == 0x9)
1948 ARMul_Icycles (state
,
1949 Multiply64 (state
, instr
, LUNSIGNED
,
1959 case 0x09: /* ADDS reg */
1961 if ((BITS (4, 11) & 0xF9) == 0x9)
1962 /* LDR register offset, no write-back, up, post indexed. */
1964 /* Fall through to remaining instruction decoding. */
1967 if (BITS (4, 7) == 0x9)
1971 ARMul_Icycles (state
,
1972 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
1980 ASSIGNZ (dest
== 0);
1981 if ((lhs
| rhs
) >> 30)
1983 /* Possible C,V,N to set. */
1984 ASSIGNN (NEG (dest
));
1985 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1986 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1997 case 0x0a: /* ADC reg */
1999 if (BITS (4, 11) == 0xB)
2001 /* STRH register offset, write-back, up, post-indexed. */
2005 if (BITS (4, 7) == 0x9)
2009 ARMul_Icycles (state
,
2010 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
2016 dest
= LHS
+ rhs
+ CFLAG
;
2020 case 0x0b: /* ADCS reg */
2022 if ((BITS (4, 11) & 0xF9) == 0x9)
2023 /* LDR register offset, write-back, up, post indexed. */
2025 /* Fall through to remaining instruction decoding. */
2026 if (BITS (4, 7) == 0x9)
2030 ARMul_Icycles (state
,
2031 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
2038 dest
= lhs
+ rhs
+ CFLAG
;
2039 ASSIGNZ (dest
== 0);
2040 if ((lhs
| rhs
) >> 30)
2042 /* Possible C,V,N to set. */
2043 ASSIGNN (NEG (dest
));
2044 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2045 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2056 case 0x0c: /* SBC reg */
2058 if (BITS (4, 7) == 0xB)
2060 /* STRH immediate offset, no write-back, up post indexed. */
2064 if (BITS (4, 7) == 0xD)
2066 Handle_Load_Double (state
, instr
);
2069 if (BITS (4, 7) == 0xF)
2071 Handle_Store_Double (state
, instr
);
2074 if (BITS (4, 7) == 0x9)
2078 ARMul_Icycles (state
,
2079 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
2085 dest
= LHS
- rhs
- !CFLAG
;
2089 case 0x0d: /* SBCS reg */
2091 if ((BITS (4, 7) & 0x9) == 0x9)
2092 /* LDR immediate offset, no write-back, up, post indexed. */
2095 if (BITS (4, 7) == 0x9)
2099 ARMul_Icycles (state
,
2100 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
2107 dest
= lhs
- rhs
- !CFLAG
;
2108 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2110 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2111 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2121 case 0x0e: /* RSC reg */
2123 if (BITS (4, 7) == 0xB)
2125 /* STRH immediate offset, write-back, up, post indexed. */
2130 if (BITS (4, 7) == 0x9)
2134 ARMul_Icycles (state
,
2135 MultiplyAdd64 (state
, instr
, LSIGNED
,
2141 dest
= rhs
- LHS
- !CFLAG
;
2145 case 0x0f: /* RSCS reg */
2147 if ((BITS (4, 7) & 0x9) == 0x9)
2148 /* LDR immediate offset, write-back, up, post indexed. */
2150 /* Fall through to remaining instruction decoding. */
2152 if (BITS (4, 7) == 0x9)
2156 ARMul_Icycles (state
,
2157 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
2164 dest
= rhs
- lhs
- !CFLAG
;
2166 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2168 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2169 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2179 case 0x10: /* TST reg and MRS CPSR and SWP word. */
2182 if (BIT (4) == 0 && BIT (7) == 1)
2184 /* ElSegundo SMLAxy insn. */
2185 ARMword op1
= state
->Reg
[BITS (0, 3)];
2186 ARMword op2
= state
->Reg
[BITS (8, 11)];
2187 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2201 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
2203 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
2207 if (BITS (4, 11) == 5)
2209 /* ElSegundo QADD insn. */
2210 ARMword op1
= state
->Reg
[BITS (0, 3)];
2211 ARMword op2
= state
->Reg
[BITS (16, 19)];
2212 ARMword result
= op1
+ op2
;
2213 if (AddOverflow (op1
, op2
, result
))
2215 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2218 state
->Reg
[BITS (12, 15)] = result
;
2223 if (BITS (4, 11) == 0xB)
2225 /* STRH register offset, no write-back, down, pre indexed. */
2229 if (BITS (4, 7) == 0xD)
2231 Handle_Load_Double (state
, instr
);
2234 if (BITS (4, 7) == 0xF)
2236 Handle_Store_Double (state
, instr
);
2240 if (BITS (4, 11) == 9)
2247 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2249 INTERNALABORT (temp
);
2250 (void) ARMul_LoadWordN (state
, temp
);
2251 (void) ARMul_LoadWordN (state
, temp
);
2255 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
2257 DEST
= ARMul_Align (state
, temp
, dest
);
2260 if (state
->abortSig
|| state
->Aborted
)
2263 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2266 DEST
= ECC
| EINT
| EMODE
;
2272 && handle_v6_insn (state
, instr
))
2279 case 0x11: /* TSTP reg */
2281 if ((BITS (4, 11) & 0xF9) == 0x9)
2282 /* LDR register offset, no write-back, down, pre indexed. */
2284 /* Continue with remaining instruction decode. */
2290 state
->Cpsr
= GETSPSR (state
->Bank
);
2291 ARMul_CPSRAltered (state
);
2303 ARMul_NegZero (state
, dest
);
2307 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
2310 if (BITS (4, 7) == 3)
2316 temp
= (pc
+ 2) | 1;
2320 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2321 state
->Reg
[14] = temp
;
2328 if (BIT (4) == 0 && BIT (7) == 1
2329 && (BIT (5) == 0 || BITS (12, 15) == 0))
2331 /* ElSegundo SMLAWy/SMULWy insn. */
2332 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2333 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2338 if (op1
& 0x80000000)
2343 result
= (op1
* op2
) >> 16;
2347 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2349 if (AddOverflow (result
, Rn
, result
+ Rn
))
2353 state
->Reg
[BITS (16, 19)] = result
;
2357 if (BITS (4, 11) == 5)
2359 /* ElSegundo QSUB insn. */
2360 ARMword op1
= state
->Reg
[BITS (0, 3)];
2361 ARMword op2
= state
->Reg
[BITS (16, 19)];
2362 ARMword result
= op1
- op2
;
2364 if (SubOverflow (op1
, op2
, result
))
2366 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2370 state
->Reg
[BITS (12, 15)] = result
;
2375 if (BITS (4, 11) == 0xB)
2377 /* STRH register offset, write-back, down, pre indexed. */
2381 if (BITS (4, 27) == 0x12FFF1)
2384 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2387 if (BITS (4, 7) == 0xD)
2389 Handle_Load_Double (state
, instr
);
2392 if (BITS (4, 7) == 0xF)
2394 Handle_Store_Double (state
, instr
);
2400 if (BITS (4, 7) == 0x7)
2402 extern int SWI_vector_installed
;
2404 /* Hardware is allowed to optionally override this
2405 instruction and treat it as a breakpoint. Since
2406 this is a simulator not hardware, we take the position
2407 that if a SWI vector was not installed, then an Abort
2408 vector was probably not installed either, and so
2409 normally this instruction would be ignored, even if an
2410 Abort is generated. This is a bad thing, since GDB
2411 uses this instruction for its breakpoints (at least in
2412 Thumb mode it does). So intercept the instruction here
2413 and generate a breakpoint SWI instead. */
2414 if (! SWI_vector_installed
)
2415 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
2418 /* BKPT - normally this will cause an abort, but on the
2419 XScale we must check the DCSR. */
2420 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
2421 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
2425 /* Force the next instruction to be refetched. */
2426 state
->NextInstr
= RESUME
;
2432 /* MSR reg to CPSR. */
2436 /* Don't allow TBIT to be set by MSR. */
2439 ARMul_FixCPSR (state
, instr
, temp
);
2442 else if (state
->is_v6
2443 && handle_v6_insn (state
, instr
))
2451 case 0x13: /* TEQP reg */
2453 if ((BITS (4, 11) & 0xF9) == 0x9)
2454 /* LDR register offset, write-back, down, pre indexed. */
2456 /* Continue with remaining instruction decode. */
2462 state
->Cpsr
= GETSPSR (state
->Bank
);
2463 ARMul_CPSRAltered (state
);
2475 ARMul_NegZero (state
, dest
);
2479 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
2482 if (BIT (4) == 0 && BIT (7) == 1)
2484 /* ElSegundo SMLALxy insn. */
2485 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2486 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2500 dest
= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
2501 dest
|= state
->Reg
[BITS (12, 15)];
2503 state
->Reg
[BITS (12, 15)] = dest
;
2504 state
->Reg
[BITS (16, 19)] = dest
>> 32;
2508 if (BITS (4, 11) == 5)
2510 /* ElSegundo QDADD insn. */
2511 ARMword op1
= state
->Reg
[BITS (0, 3)];
2512 ARMword op2
= state
->Reg
[BITS (16, 19)];
2513 ARMword op2d
= op2
+ op2
;
2516 if (AddOverflow (op2
, op2
, op2d
))
2519 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2522 result
= op1
+ op2d
;
2523 if (AddOverflow (op1
, op2d
, result
))
2526 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2529 state
->Reg
[BITS (12, 15)] = result
;
2534 if (BITS (4, 7) == 0xB)
2536 /* STRH immediate offset, no write-back, down, pre indexed. */
2540 if (BITS (4, 7) == 0xD)
2542 Handle_Load_Double (state
, instr
);
2545 if (BITS (4, 7) == 0xF)
2547 Handle_Store_Double (state
, instr
);
2551 if (BITS (4, 11) == 9)
2558 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2560 INTERNALABORT (temp
);
2561 (void) ARMul_LoadByte (state
, temp
);
2562 (void) ARMul_LoadByte (state
, temp
);
2566 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
2567 if (state
->abortSig
|| state
->Aborted
)
2570 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2574 DEST
= GETSPSR (state
->Bank
);
2577 else if (state
->is_v6
2578 && handle_v6_insn (state
, instr
))
2586 case 0x15: /* CMPP reg. */
2588 if ((BITS (4, 7) & 0x9) == 0x9)
2589 /* LDR immediate offset, no write-back, down, pre indexed. */
2591 /* Continue with remaining instruction decode. */
2597 state
->Cpsr
= GETSPSR (state
->Bank
);
2598 ARMul_CPSRAltered (state
);
2611 ARMul_NegZero (state
, dest
);
2612 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2614 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2615 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2625 case 0x16: /* CMN reg and MSR reg to SPSR */
2628 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
2630 /* ElSegundo SMULxy insn. */
2631 ARMword op1
= state
->Reg
[BITS (0, 3)];
2632 ARMword op2
= state
->Reg
[BITS (8, 11)];
2645 state
->Reg
[BITS (16, 19)] = op1
* op2
;
2649 if (BITS (4, 11) == 5)
2651 /* ElSegundo QDSUB insn. */
2652 ARMword op1
= state
->Reg
[BITS (0, 3)];
2653 ARMword op2
= state
->Reg
[BITS (16, 19)];
2654 ARMword op2d
= op2
+ op2
;
2657 if (AddOverflow (op2
, op2
, op2d
))
2660 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2663 result
= op1
- op2d
;
2664 if (SubOverflow (op1
, op2d
, result
))
2667 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2670 state
->Reg
[BITS (12, 15)] = result
;
2677 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
2679 /* ARM5 CLZ insn. */
2680 ARMword op1
= state
->Reg
[BITS (0, 3)];
2684 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
2687 state
->Reg
[BITS (12, 15)] = result
;
2692 if (BITS (4, 7) == 0xB)
2694 /* STRH immediate offset, write-back, down, pre indexed. */
2698 if (BITS (4, 7) == 0xD)
2700 Handle_Load_Double (state
, instr
);
2703 if (BITS (4, 7) == 0xF)
2705 Handle_Store_Double (state
, instr
);
2713 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
2719 && handle_v6_insn (state
, instr
))
2726 case 0x17: /* CMNP reg */
2728 if ((BITS (4, 7) & 0x9) == 0x9)
2729 /* LDR immediate offset, write-back, down, pre indexed. */
2731 /* Continue with remaining instruction decoding. */
2736 state
->Cpsr
= GETSPSR (state
->Bank
);
2737 ARMul_CPSRAltered (state
);
2751 ASSIGNZ (dest
== 0);
2752 if ((lhs
| rhs
) >> 30)
2754 /* Possible C,V,N to set. */
2755 ASSIGNN (NEG (dest
));
2756 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2757 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2768 case 0x18: /* ORR reg */
2770 if (BITS (4, 11) == 0xB)
2772 /* STRH register offset, no write-back, up, pre indexed. */
2776 if (BITS (4, 7) == 0xD)
2778 Handle_Load_Double (state
, instr
);
2781 if (BITS (4, 7) == 0xF)
2783 Handle_Store_Double (state
, instr
);
2792 case 0x19: /* ORRS reg */
2794 if ((BITS (4, 11) & 0xF9) == 0x9)
2795 /* LDR register offset, no write-back, up, pre indexed. */
2797 /* Continue with remaining instruction decoding. */
2804 case 0x1a: /* MOV reg */
2806 if (BITS (4, 11) == 0xB)
2808 /* STRH register offset, write-back, up, pre indexed. */
2812 if (BITS (4, 7) == 0xD)
2814 Handle_Load_Double (state
, instr
);
2817 if (BITS (4, 7) == 0xF)
2819 Handle_Store_Double (state
, instr
);
2827 case 0x1b: /* MOVS reg */
2829 if ((BITS (4, 11) & 0xF9) == 0x9)
2830 /* LDR register offset, write-back, up, pre indexed. */
2832 /* Continue with remaining instruction decoding. */
2838 case 0x1c: /* BIC reg */
2840 if (BITS (4, 7) == 0xB)
2842 /* STRH immediate offset, no write-back, up, pre indexed. */
2846 if (BITS (4, 7) == 0xD)
2848 Handle_Load_Double (state
, instr
);
2851 else if (BITS (4, 7) == 0xF)
2853 Handle_Store_Double (state
, instr
);
2862 case 0x1d: /* BICS reg */
2864 if ((BITS (4, 7) & 0x9) == 0x9)
2865 /* LDR immediate offset, no write-back, up, pre indexed. */
2867 /* Continue with instruction decoding. */
2874 case 0x1e: /* MVN reg */
2876 if (BITS (4, 7) == 0xB)
2878 /* STRH immediate offset, write-back, up, pre indexed. */
2882 if (BITS (4, 7) == 0xD)
2884 Handle_Load_Double (state
, instr
);
2887 if (BITS (4, 7) == 0xF)
2889 Handle_Store_Double (state
, instr
);
2897 case 0x1f: /* MVNS reg */
2899 if ((BITS (4, 7) & 0x9) == 0x9)
2900 /* LDR immediate offset, write-back, up, pre indexed. */
2902 /* Continue instruction decoding. */
2909 /* Data Processing Immediate RHS Instructions. */
2911 case 0x20: /* AND immed */
2912 dest
= LHS
& DPImmRHS
;
2916 case 0x21: /* ANDS immed */
2922 case 0x22: /* EOR immed */
2923 dest
= LHS
^ DPImmRHS
;
2927 case 0x23: /* EORS immed */
2933 case 0x24: /* SUB immed */
2934 dest
= LHS
- DPImmRHS
;
2938 case 0x25: /* SUBS immed */
2943 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2945 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2946 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2956 case 0x26: /* RSB immed */
2957 dest
= DPImmRHS
- LHS
;
2961 case 0x27: /* RSBS immed */
2966 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2968 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2969 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2979 case 0x28: /* ADD immed */
2980 dest
= LHS
+ DPImmRHS
;
2984 case 0x29: /* ADDS immed */
2988 ASSIGNZ (dest
== 0);
2990 if ((lhs
| rhs
) >> 30)
2992 /* Possible C,V,N to set. */
2993 ASSIGNN (NEG (dest
));
2994 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2995 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3006 case 0x2a: /* ADC immed */
3007 dest
= LHS
+ DPImmRHS
+ CFLAG
;
3011 case 0x2b: /* ADCS immed */
3014 dest
= lhs
+ rhs
+ CFLAG
;
3015 ASSIGNZ (dest
== 0);
3016 if ((lhs
| rhs
) >> 30)
3018 /* Possible C,V,N to set. */
3019 ASSIGNN (NEG (dest
));
3020 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
3021 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3032 case 0x2c: /* SBC immed */
3033 dest
= LHS
- DPImmRHS
- !CFLAG
;
3037 case 0x2d: /* SBCS immed */
3040 dest
= lhs
- rhs
- !CFLAG
;
3041 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
3043 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
3044 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
3054 case 0x2e: /* RSC immed */
3055 dest
= DPImmRHS
- LHS
- !CFLAG
;
3059 case 0x2f: /* RSCS immed */
3062 dest
= rhs
- lhs
- !CFLAG
;
3063 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
3065 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
3066 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
3076 case 0x30: /* MOVW immed */
3079 && handle_v6_insn (state
, instr
))
3082 dest
= BITS (0, 11);
3083 dest
|= (BITS (16, 19) << 12);
3087 case 0x31: /* TSTP immed */
3092 state
->Cpsr
= GETSPSR (state
->Bank
);
3093 ARMul_CPSRAltered (state
);
3095 temp
= LHS
& DPImmRHS
;
3104 ARMul_NegZero (state
, dest
);
3108 case 0x32: /* TEQ immed and MSR immed to CPSR */
3110 /* MSR immed to CPSR. */
3111 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
3113 else if (state
->is_v6
3114 && handle_v6_insn (state
, instr
))
3121 case 0x33: /* TEQP immed */
3126 state
->Cpsr
= GETSPSR (state
->Bank
);
3127 ARMul_CPSRAltered (state
);
3129 temp
= LHS
^ DPImmRHS
;
3135 DPSImmRHS
; /* TEQ immed */
3137 ARMul_NegZero (state
, dest
);
3141 case 0x34: /* MOVT immed */
3144 && handle_v6_insn (state
, instr
))
3148 dest
= BITS (0, 11);
3149 dest
|= (BITS (16, 19) << 12);
3150 DEST
|= (dest
<< 16);
3153 case 0x35: /* CMPP immed */
3158 state
->Cpsr
= GETSPSR (state
->Bank
);
3159 ARMul_CPSRAltered (state
);
3161 temp
= LHS
- DPImmRHS
;
3172 ARMul_NegZero (state
, dest
);
3174 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
3176 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
3177 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
3187 case 0x36: /* CMN immed and MSR immed to SPSR */
3189 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
3191 else if (state
->is_v6
3192 && handle_v6_insn (state
, instr
))
3199 case 0x37: /* CMNP immed. */
3204 state
->Cpsr
= GETSPSR (state
->Bank
);
3205 ARMul_CPSRAltered (state
);
3207 temp
= LHS
+ DPImmRHS
;
3218 ASSIGNZ (dest
== 0);
3219 if ((lhs
| rhs
) >> 30)
3221 /* Possible C,V,N to set. */
3222 ASSIGNN (NEG (dest
));
3223 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
3224 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3235 case 0x38: /* ORR immed. */
3236 dest
= LHS
| DPImmRHS
;
3240 case 0x39: /* ORRS immed. */
3246 case 0x3a: /* MOV immed. */
3251 case 0x3b: /* MOVS immed. */
3256 case 0x3c: /* BIC immed. */
3257 dest
= LHS
& ~DPImmRHS
;
3261 case 0x3d: /* BICS immed. */
3267 case 0x3e: /* MVN immed. */
3272 case 0x3f: /* MVNS immed. */
3278 /* Single Data Transfer Immediate RHS Instructions. */
3280 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
3282 if (StoreWord (state
, instr
, lhs
))
3283 LSBase
= lhs
- LSImmRHS
;
3286 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
3288 if (LoadWord (state
, instr
, lhs
))
3289 LSBase
= lhs
- LSImmRHS
;
3292 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
3293 UNDEF_LSRBaseEQDestWb
;
3296 temp
= lhs
- LSImmRHS
;
3297 state
->NtransSig
= LOW
;
3298 if (StoreWord (state
, instr
, lhs
))
3300 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3303 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
3304 UNDEF_LSRBaseEQDestWb
;
3307 state
->NtransSig
= LOW
;
3308 if (LoadWord (state
, instr
, lhs
))
3309 LSBase
= lhs
- LSImmRHS
;
3310 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3313 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
3315 if (StoreByte (state
, instr
, lhs
))
3316 LSBase
= lhs
- LSImmRHS
;
3319 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
3321 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3322 LSBase
= lhs
- LSImmRHS
;
3325 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
3326 UNDEF_LSRBaseEQDestWb
;
3329 state
->NtransSig
= LOW
;
3330 if (StoreByte (state
, instr
, lhs
))
3331 LSBase
= lhs
- LSImmRHS
;
3332 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3335 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
3336 UNDEF_LSRBaseEQDestWb
;
3339 state
->NtransSig
= LOW
;
3340 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3341 LSBase
= lhs
- LSImmRHS
;
3342 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3345 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
3347 if (StoreWord (state
, instr
, lhs
))
3348 LSBase
= lhs
+ LSImmRHS
;
3351 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
3353 if (LoadWord (state
, instr
, lhs
))
3354 LSBase
= lhs
+ LSImmRHS
;
3357 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
3358 UNDEF_LSRBaseEQDestWb
;
3361 state
->NtransSig
= LOW
;
3362 if (StoreWord (state
, instr
, lhs
))
3363 LSBase
= lhs
+ LSImmRHS
;
3364 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3367 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
3368 UNDEF_LSRBaseEQDestWb
;
3371 state
->NtransSig
= LOW
;
3372 if (LoadWord (state
, instr
, lhs
))
3373 LSBase
= lhs
+ LSImmRHS
;
3374 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3377 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
3379 if (StoreByte (state
, instr
, lhs
))
3380 LSBase
= lhs
+ LSImmRHS
;
3383 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
3385 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3386 LSBase
= lhs
+ LSImmRHS
;
3389 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
3390 UNDEF_LSRBaseEQDestWb
;
3393 state
->NtransSig
= LOW
;
3394 if (StoreByte (state
, instr
, lhs
))
3395 LSBase
= lhs
+ LSImmRHS
;
3396 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3399 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
3400 UNDEF_LSRBaseEQDestWb
;
3403 state
->NtransSig
= LOW
;
3404 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3405 LSBase
= lhs
+ LSImmRHS
;
3406 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3410 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
3411 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
3414 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
3415 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
3418 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
3419 UNDEF_LSRBaseEQDestWb
;
3421 temp
= LHS
- LSImmRHS
;
3422 if (StoreWord (state
, instr
, temp
))
3426 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
3427 UNDEF_LSRBaseEQDestWb
;
3429 temp
= LHS
- LSImmRHS
;
3430 if (LoadWord (state
, instr
, temp
))
3434 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
3435 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
3438 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
3439 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
3442 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
3443 UNDEF_LSRBaseEQDestWb
;
3445 temp
= LHS
- LSImmRHS
;
3446 if (StoreByte (state
, instr
, temp
))
3450 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
3451 UNDEF_LSRBaseEQDestWb
;
3453 temp
= LHS
- LSImmRHS
;
3454 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3458 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
3459 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
3462 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
3463 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
3466 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
3467 UNDEF_LSRBaseEQDestWb
;
3469 temp
= LHS
+ LSImmRHS
;
3470 if (StoreWord (state
, instr
, temp
))
3474 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
3475 UNDEF_LSRBaseEQDestWb
;
3477 temp
= LHS
+ LSImmRHS
;
3478 if (LoadWord (state
, instr
, temp
))
3482 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
3483 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
3486 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
3487 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
3490 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
3491 UNDEF_LSRBaseEQDestWb
;
3493 temp
= LHS
+ LSImmRHS
;
3494 if (StoreByte (state
, instr
, temp
))
3498 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
3499 UNDEF_LSRBaseEQDestWb
;
3501 temp
= LHS
+ LSImmRHS
;
3502 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3507 /* Single Data Transfer Register RHS Instructions. */
3509 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
3514 && handle_v6_insn (state
, instr
))
3517 ARMul_UndefInstr (state
, instr
);
3520 UNDEF_LSRBaseEQOffWb
;
3521 UNDEF_LSRBaseEQDestWb
;
3525 if (StoreWord (state
, instr
, lhs
))
3526 LSBase
= lhs
- LSRegRHS
;
3529 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
3534 && handle_v6_insn (state
, instr
))
3537 ARMul_UndefInstr (state
, instr
);
3540 UNDEF_LSRBaseEQOffWb
;
3541 UNDEF_LSRBaseEQDestWb
;
3545 temp
= lhs
- LSRegRHS
;
3546 if (LoadWord (state
, instr
, lhs
))
3550 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
3555 && handle_v6_insn (state
, instr
))
3558 ARMul_UndefInstr (state
, instr
);
3561 UNDEF_LSRBaseEQOffWb
;
3562 UNDEF_LSRBaseEQDestWb
;
3566 state
->NtransSig
= LOW
;
3567 if (StoreWord (state
, instr
, lhs
))
3568 LSBase
= lhs
- LSRegRHS
;
3569 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3572 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
3577 && handle_v6_insn (state
, instr
))
3580 ARMul_UndefInstr (state
, instr
);
3583 UNDEF_LSRBaseEQOffWb
;
3584 UNDEF_LSRBaseEQDestWb
;
3588 temp
= lhs
- LSRegRHS
;
3589 state
->NtransSig
= LOW
;
3590 if (LoadWord (state
, instr
, lhs
))
3592 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3595 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
3600 && handle_v6_insn (state
, instr
))
3603 ARMul_UndefInstr (state
, instr
);
3606 UNDEF_LSRBaseEQOffWb
;
3607 UNDEF_LSRBaseEQDestWb
;
3611 if (StoreByte (state
, instr
, lhs
))
3612 LSBase
= lhs
- LSRegRHS
;
3615 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
3620 && handle_v6_insn (state
, instr
))
3623 ARMul_UndefInstr (state
, instr
);
3626 UNDEF_LSRBaseEQOffWb
;
3627 UNDEF_LSRBaseEQDestWb
;
3631 temp
= lhs
- LSRegRHS
;
3632 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3636 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
3641 && handle_v6_insn (state
, instr
))
3644 ARMul_UndefInstr (state
, instr
);
3647 UNDEF_LSRBaseEQOffWb
;
3648 UNDEF_LSRBaseEQDestWb
;
3652 state
->NtransSig
= LOW
;
3653 if (StoreByte (state
, instr
, lhs
))
3654 LSBase
= lhs
- LSRegRHS
;
3655 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3658 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
3663 && handle_v6_insn (state
, instr
))
3666 ARMul_UndefInstr (state
, instr
);
3669 UNDEF_LSRBaseEQOffWb
;
3670 UNDEF_LSRBaseEQDestWb
;
3674 temp
= lhs
- LSRegRHS
;
3675 state
->NtransSig
= LOW
;
3676 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3678 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3681 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
3686 && handle_v6_insn (state
, instr
))
3689 ARMul_UndefInstr (state
, instr
);
3692 UNDEF_LSRBaseEQOffWb
;
3693 UNDEF_LSRBaseEQDestWb
;
3697 if (StoreWord (state
, instr
, lhs
))
3698 LSBase
= lhs
+ LSRegRHS
;
3701 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
3706 && handle_v6_insn (state
, instr
))
3709 ARMul_UndefInstr (state
, instr
);
3712 UNDEF_LSRBaseEQOffWb
;
3713 UNDEF_LSRBaseEQDestWb
;
3717 temp
= lhs
+ LSRegRHS
;
3718 if (LoadWord (state
, instr
, lhs
))
3722 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
3727 && handle_v6_insn (state
, instr
))
3730 ARMul_UndefInstr (state
, instr
);
3733 UNDEF_LSRBaseEQOffWb
;
3734 UNDEF_LSRBaseEQDestWb
;
3738 state
->NtransSig
= LOW
;
3739 if (StoreWord (state
, instr
, lhs
))
3740 LSBase
= lhs
+ LSRegRHS
;
3741 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3744 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
3749 && handle_v6_insn (state
, instr
))
3752 ARMul_UndefInstr (state
, instr
);
3755 UNDEF_LSRBaseEQOffWb
;
3756 UNDEF_LSRBaseEQDestWb
;
3760 temp
= lhs
+ LSRegRHS
;
3761 state
->NtransSig
= LOW
;
3762 if (LoadWord (state
, instr
, lhs
))
3764 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3767 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
3772 && handle_v6_insn (state
, instr
))
3775 ARMul_UndefInstr (state
, instr
);
3778 UNDEF_LSRBaseEQOffWb
;
3779 UNDEF_LSRBaseEQDestWb
;
3783 if (StoreByte (state
, instr
, lhs
))
3784 LSBase
= lhs
+ LSRegRHS
;
3787 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
3792 && handle_v6_insn (state
, instr
))
3795 ARMul_UndefInstr (state
, instr
);
3798 UNDEF_LSRBaseEQOffWb
;
3799 UNDEF_LSRBaseEQDestWb
;
3803 temp
= lhs
+ LSRegRHS
;
3804 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3808 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3813 && handle_v6_insn (state
, instr
))
3816 ARMul_UndefInstr (state
, instr
);
3819 UNDEF_LSRBaseEQOffWb
;
3820 UNDEF_LSRBaseEQDestWb
;
3824 state
->NtransSig
= LOW
;
3825 if (StoreByte (state
, instr
, lhs
))
3826 LSBase
= lhs
+ LSRegRHS
;
3827 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3830 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3835 && handle_v6_insn (state
, instr
))
3838 ARMul_UndefInstr (state
, instr
);
3841 UNDEF_LSRBaseEQOffWb
;
3842 UNDEF_LSRBaseEQDestWb
;
3846 temp
= lhs
+ LSRegRHS
;
3847 state
->NtransSig
= LOW
;
3848 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3850 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3854 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3859 && handle_v6_insn (state
, instr
))
3862 ARMul_UndefInstr (state
, instr
);
3865 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
3868 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3873 && handle_v6_insn (state
, instr
))
3876 ARMul_UndefInstr (state
, instr
);
3879 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
3882 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3887 && handle_v6_insn (state
, instr
))
3890 ARMul_UndefInstr (state
, instr
);
3893 UNDEF_LSRBaseEQOffWb
;
3894 UNDEF_LSRBaseEQDestWb
;
3897 temp
= LHS
- LSRegRHS
;
3898 if (StoreWord (state
, instr
, temp
))
3902 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3907 && handle_v6_insn (state
, instr
))
3910 ARMul_UndefInstr (state
, instr
);
3913 UNDEF_LSRBaseEQOffWb
;
3914 UNDEF_LSRBaseEQDestWb
;
3917 temp
= LHS
- LSRegRHS
;
3918 if (LoadWord (state
, instr
, temp
))
3922 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3927 && handle_v6_insn (state
, instr
))
3930 ARMul_UndefInstr (state
, instr
);
3933 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
3936 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3941 && handle_v6_insn (state
, instr
))
3944 ARMul_UndefInstr (state
, instr
);
3947 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
3950 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3955 && handle_v6_insn (state
, instr
))
3958 ARMul_UndefInstr (state
, instr
);
3961 UNDEF_LSRBaseEQOffWb
;
3962 UNDEF_LSRBaseEQDestWb
;
3965 temp
= LHS
- LSRegRHS
;
3966 if (StoreByte (state
, instr
, temp
))
3970 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3975 && handle_v6_insn (state
, instr
))
3978 ARMul_UndefInstr (state
, instr
);
3981 UNDEF_LSRBaseEQOffWb
;
3982 UNDEF_LSRBaseEQDestWb
;
3985 temp
= LHS
- LSRegRHS
;
3986 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3990 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3995 && handle_v6_insn (state
, instr
))
3998 ARMul_UndefInstr (state
, instr
);
4001 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
4004 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
4009 && handle_v6_insn (state
, instr
))
4012 ARMul_UndefInstr (state
, instr
);
4015 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
4018 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
4023 && handle_v6_insn (state
, instr
))
4026 ARMul_UndefInstr (state
, instr
);
4029 UNDEF_LSRBaseEQOffWb
;
4030 UNDEF_LSRBaseEQDestWb
;
4033 temp
= LHS
+ LSRegRHS
;
4034 if (StoreWord (state
, instr
, temp
))
4038 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
4043 && handle_v6_insn (state
, instr
))
4046 ARMul_UndefInstr (state
, instr
);
4049 UNDEF_LSRBaseEQOffWb
;
4050 UNDEF_LSRBaseEQDestWb
;
4053 temp
= LHS
+ LSRegRHS
;
4054 if (LoadWord (state
, instr
, temp
))
4058 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
4063 && handle_v6_insn (state
, instr
))
4066 ARMul_UndefInstr (state
, instr
);
4069 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
4072 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
4077 && handle_v6_insn (state
, instr
))
4080 ARMul_UndefInstr (state
, instr
);
4083 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
4086 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
4091 && handle_v6_insn (state
, instr
))
4094 ARMul_UndefInstr (state
, instr
);
4097 UNDEF_LSRBaseEQOffWb
;
4098 UNDEF_LSRBaseEQDestWb
;
4101 temp
= LHS
+ LSRegRHS
;
4102 if (StoreByte (state
, instr
, temp
))
4106 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
4109 /* Check for the special breakpoint opcode.
4110 This value should correspond to the value defined
4111 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
4112 if (BITS (0, 19) == 0xfdefe)
4114 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
4115 ARMul_Abort (state
, ARMul_SWIV
);
4118 else if (state
->is_v6
4119 && handle_v6_insn (state
, instr
))
4123 ARMul_UndefInstr (state
, instr
);
4126 UNDEF_LSRBaseEQOffWb
;
4127 UNDEF_LSRBaseEQDestWb
;
4130 temp
= LHS
+ LSRegRHS
;
4131 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
4136 /* Multiple Data Transfer Instructions. */
4138 case 0x80: /* Store, No WriteBack, Post Dec. */
4139 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4142 case 0x81: /* Load, No WriteBack, Post Dec. */
4143 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4146 case 0x82: /* Store, WriteBack, Post Dec. */
4147 temp
= LSBase
- LSMNumRegs
;
4148 STOREMULT (instr
, temp
+ 4L, temp
);
4151 case 0x83: /* Load, WriteBack, Post Dec. */
4152 temp
= LSBase
- LSMNumRegs
;
4153 LOADMULT (instr
, temp
+ 4L, temp
);
4156 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
4157 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4160 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
4161 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4164 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
4165 temp
= LSBase
- LSMNumRegs
;
4166 STORESMULT (instr
, temp
+ 4L, temp
);
4169 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
4170 temp
= LSBase
- LSMNumRegs
;
4171 LOADSMULT (instr
, temp
+ 4L, temp
);
4174 case 0x88: /* Store, No WriteBack, Post Inc. */
4175 STOREMULT (instr
, LSBase
, 0L);
4178 case 0x89: /* Load, No WriteBack, Post Inc. */
4179 LOADMULT (instr
, LSBase
, 0L);
4182 case 0x8a: /* Store, WriteBack, Post Inc. */
4184 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
4187 case 0x8b: /* Load, WriteBack, Post Inc. */
4189 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
4192 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
4193 STORESMULT (instr
, LSBase
, 0L);
4196 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
4197 LOADSMULT (instr
, LSBase
, 0L);
4200 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
4202 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
4205 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
4207 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
4210 case 0x90: /* Store, No WriteBack, Pre Dec. */
4211 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4214 case 0x91: /* Load, No WriteBack, Pre Dec. */
4215 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4218 case 0x92: /* Store, WriteBack, Pre Dec. */
4219 temp
= LSBase
- LSMNumRegs
;
4220 STOREMULT (instr
, temp
, temp
);
4223 case 0x93: /* Load, WriteBack, Pre Dec. */
4224 temp
= LSBase
- LSMNumRegs
;
4225 LOADMULT (instr
, temp
, temp
);
4228 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
4229 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4232 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
4233 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4236 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
4237 temp
= LSBase
- LSMNumRegs
;
4238 STORESMULT (instr
, temp
, temp
);
4241 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
4242 temp
= LSBase
- LSMNumRegs
;
4243 LOADSMULT (instr
, temp
, temp
);
4246 case 0x98: /* Store, No WriteBack, Pre Inc. */
4247 STOREMULT (instr
, LSBase
+ 4L, 0L);
4250 case 0x99: /* Load, No WriteBack, Pre Inc. */
4251 LOADMULT (instr
, LSBase
+ 4L, 0L);
4254 case 0x9a: /* Store, WriteBack, Pre Inc. */
4256 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4259 case 0x9b: /* Load, WriteBack, Pre Inc. */
4261 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4264 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
4265 STORESMULT (instr
, LSBase
+ 4L, 0L);
4268 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
4269 LOADSMULT (instr
, LSBase
+ 4L, 0L);
4272 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
4274 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4277 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
4279 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4283 /* Branch forward. */
4292 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4297 /* Branch backward. */
4306 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4310 /* Branch and Link forward. */
4319 /* Put PC into Link. */
4321 state
->Reg
[14] = pc
+ 4;
4323 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4325 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4328 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4331 /* Branch and Link backward. */
4340 /* Put PC into Link. */
4342 state
->Reg
[14] = pc
+ 4;
4344 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4346 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4349 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4352 /* Co-Processor Data Transfers. */
4356 if (CPNum
== 10 || CPNum
== 11)
4357 handle_VFP_move (state
, instr
);
4358 /* Reading from R15 is UNPREDICTABLE. */
4359 else if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
4360 ARMul_UndefInstr (state
, instr
);
4361 /* Is access to coprocessor 0 allowed ? */
4362 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4363 ARMul_UndefInstr (state
, instr
);
4364 /* Special treatment for XScale coprocessors. */
4365 else if (state
->is_XScale
)
4367 /* Only opcode 0 is supported. */
4368 if (BITS (4, 7) != 0x00)
4369 ARMul_UndefInstr (state
, instr
);
4370 /* Only coporcessor 0 is supported. */
4371 else if (CPNum
!= 0x00)
4372 ARMul_UndefInstr (state
, instr
);
4373 /* Only accumulator 0 is supported. */
4374 else if (BITS (0, 3) != 0x00)
4375 ARMul_UndefInstr (state
, instr
);
4378 /* XScale MAR insn. Move two registers into accumulator. */
4379 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
4380 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
4384 /* FIXME: Not sure what to do for other v5 processors. */
4385 ARMul_UndefInstr (state
, instr
);
4390 case 0xc0: /* Store , No WriteBack , Post Dec. */
4391 ARMul_STC (state
, instr
, LHS
);
4397 if (CPNum
== 10 || CPNum
== 11)
4398 handle_VFP_move (state
, instr
);
4399 /* Writes to R15 are UNPREDICATABLE. */
4400 else if (DESTReg
== 15 || LHSReg
== 15)
4401 ARMul_UndefInstr (state
, instr
);
4402 /* Is access to the coprocessor allowed ? */
4403 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4404 ARMul_UndefInstr (state
, instr
);
4405 /* Special handling for XScale coprcoessors. */
4406 else if (state
->is_XScale
)
4408 /* Only opcode 0 is supported. */
4409 if (BITS (4, 7) != 0x00)
4410 ARMul_UndefInstr (state
, instr
);
4411 /* Only coprocessor 0 is supported. */
4412 else if (CPNum
!= 0x00)
4413 ARMul_UndefInstr (state
, instr
);
4414 /* Only accumulator 0 is supported. */
4415 else if (BITS (0, 3) != 0x00)
4416 ARMul_UndefInstr (state
, instr
);
4419 /* XScale MRA insn. Move accumulator into two registers. */
4420 ARMword t1
= (state
->Accumulator
>> 32) & 255;
4425 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
4426 state
->Reg
[BITS (16, 19)] = t1
;
4431 /* FIXME: Not sure what to do for other v5 processors. */
4432 ARMul_UndefInstr (state
, instr
);
4437 case 0xc1: /* Load , No WriteBack , Post Dec. */
4438 ARMul_LDC (state
, instr
, LHS
);
4442 case 0xc6: /* Store , WriteBack , Post Dec. */
4444 state
->Base
= lhs
- LSCOff
;
4445 ARMul_STC (state
, instr
, lhs
);
4449 case 0xc7: /* Load , WriteBack , Post Dec. */
4451 state
->Base
= lhs
- LSCOff
;
4452 ARMul_LDC (state
, instr
, lhs
);
4456 case 0xcc: /* Store , No WriteBack , Post Inc. */
4457 ARMul_STC (state
, instr
, LHS
);
4461 case 0xcd: /* Load , No WriteBack , Post Inc. */
4462 ARMul_LDC (state
, instr
, LHS
);
4466 case 0xce: /* Store , WriteBack , Post Inc. */
4468 state
->Base
= lhs
+ LSCOff
;
4469 ARMul_STC (state
, instr
, LHS
);
4473 case 0xcf: /* Load , WriteBack , Post Inc. */
4475 state
->Base
= lhs
+ LSCOff
;
4476 ARMul_LDC (state
, instr
, LHS
);
4480 case 0xd4: /* Store , No WriteBack , Pre Dec. */
4481 ARMul_STC (state
, instr
, LHS
- LSCOff
);
4485 case 0xd5: /* Load , No WriteBack , Pre Dec. */
4486 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
4490 case 0xd6: /* Store , WriteBack , Pre Dec. */
4493 ARMul_STC (state
, instr
, lhs
);
4497 case 0xd7: /* Load , WriteBack , Pre Dec. */
4500 ARMul_LDC (state
, instr
, lhs
);
4504 case 0xdc: /* Store , No WriteBack , Pre Inc. */
4505 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
4509 case 0xdd: /* Load , No WriteBack , Pre Inc. */
4510 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
4514 case 0xde: /* Store , WriteBack , Pre Inc. */
4517 ARMul_STC (state
, instr
, lhs
);
4521 case 0xdf: /* Load , WriteBack , Pre Inc. */
4524 ARMul_LDC (state
, instr
, lhs
);
4528 /* Co-Processor Register Transfers (MCR) and Data Ops. */
4531 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4533 ARMul_UndefInstr (state
, instr
);
4536 if (state
->is_XScale
)
4537 switch (BITS (18, 19))
4540 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4542 /* XScale MIA instruction. Signed multiplication of
4543 two 32 bit values and addition to 40 bit accumulator. */
4544 ARMsdword Rm
= state
->Reg
[MULLHSReg
];
4545 ARMsdword Rs
= state
->Reg
[MULACCReg
];
4551 state
->Accumulator
+= Rm
* Rs
;
4557 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4559 /* XScale MIAPH instruction. */
4560 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
4561 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
4562 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
4563 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
4578 state
->Accumulator
+= t5
;
4583 state
->Accumulator
+= t5
;
4589 if (BITS (4, 11) == 1)
4591 /* XScale MIAxy instruction. */
4597 t1
= state
->Reg
[MULLHSReg
] >> 16;
4599 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
4602 t2
= state
->Reg
[MULACCReg
] >> 16;
4604 t2
= state
->Reg
[MULACCReg
] & 0xffff;
4614 state
->Accumulator
+= t5
;
4633 if (CPNum
== 10 || CPNum
== 11)
4634 handle_VFP_move (state
, instr
);
4636 else if (DESTReg
== 15)
4640 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
4642 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
4643 ((state
->Reg
[15] + isize
) & R15PCBITS
));
4647 ARMul_MCR (state
, instr
, DEST
);
4651 ARMul_CDP (state
, instr
);
4655 /* Co-Processor Register Transfers (MRC) and Data Ops. */
4666 if (CPNum
== 10 || CPNum
== 11)
4668 switch (BITS (20, 27))
4671 if (BITS (16, 19) == 0x1
4672 && BITS (0, 11) == 0xA10)
4677 ARMul_SetCPSR (state
, (state
->FPSCR
& 0xF0000000)
4678 | (ARMul_GetCPSR (state
) & 0x0FFFFFFF));
4681 fprintf (stderr
, " VFP: VMRS: set flags to %c%c%c%c\n",
4682 ARMul_GetCPSR (state
) & NBIT
? 'N' : '-',
4683 ARMul_GetCPSR (state
) & ZBIT
? 'Z' : '-',
4684 ARMul_GetCPSR (state
) & CBIT
? 'C' : '-',
4685 ARMul_GetCPSR (state
) & VBIT
? 'V' : '-');
4689 state
->Reg
[DESTReg
] = state
->FPSCR
;
4692 fprintf (stderr
, " VFP: VMRS: r%d = %x\n", DESTReg
, state
->Reg
[DESTReg
]);
4696 fprintf (stderr
, "SIM: VFP: Unimplemented: Compare op\n");
4701 /* VMOV reg <-> single precision. */
4702 if (BITS (0,6) != 0x10 || BITS (8,11) != 0xA)
4703 fprintf (stderr
, "SIM: VFP: Unimplemented: move op\n");
4705 state
->Reg
[BITS (12, 15)] = VFP_uword (BITS (16, 19) << 1 | BIT (7));
4707 VFP_uword (BITS (16, 19) << 1 | BIT (7)) = state
->Reg
[BITS (12, 15)];
4711 fprintf (stderr
, "SIM: VFP: Unimplemented: CDP op\n");
4718 temp
= ARMul_MRC (state
, instr
);
4721 ASSIGNN ((temp
& NBIT
) != 0);
4722 ASSIGNZ ((temp
& ZBIT
) != 0);
4723 ASSIGNC ((temp
& CBIT
) != 0);
4724 ASSIGNV ((temp
& VBIT
) != 0);
4732 ARMul_CDP (state
, instr
);
4736 /* SWI instruction. */
4753 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
4755 /* A prefetch abort. */
4756 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
4757 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
4761 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
4762 ARMul_Abort (state
, ARMul_SWIV
);
4772 if (state
->Emulate
== ONCE
)
4773 state
->Emulate
= STOP
;
4774 /* If we have changed mode, allow the PC to advance before stopping. */
4775 else if (state
->Emulate
== CHANGEMODE
)
4777 else if (state
->Emulate
!= RUN
)
4780 while (!stop_simulator
);
4782 state
->decoded
= decoded
;
4783 state
->loaded
= loaded
;
4789 /* This routine evaluates most Data Processing register RHS's with the S
4790 bit clear. It is intended to be called from the macro DPRegRHS, which
4791 filters the common case of an unshifted register with in line code. */
4794 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
4796 ARMword shamt
, base
;
4801 /* Shift amount in a register. */
4806 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4809 base
= state
->Reg
[base
];
4810 ARMul_Icycles (state
, 1, 0L);
4811 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4812 switch ((int) BITS (5, 6))
4817 else if (shamt
>= 32)
4820 return (base
<< shamt
);
4824 else if (shamt
>= 32)
4827 return (base
>> shamt
);
4831 else if (shamt
>= 32)
4832 return ((ARMword
) ((ARMsword
) base
>> 31L));
4834 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4840 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4845 /* Shift amount is a constant. */
4848 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4851 base
= state
->Reg
[base
];
4852 shamt
= BITS (7, 11);
4853 switch ((int) BITS (5, 6))
4856 return (base
<< shamt
);
4861 return (base
>> shamt
);
4864 return ((ARMword
) ((ARMsword
) base
>> 31L));
4866 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4870 return ((base
>> 1) | (CFLAG
<< 31));
4872 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4879 /* This routine evaluates most Logical Data Processing register RHS's
4880 with the S bit set. It is intended to be called from the macro
4881 DPSRegRHS, which filters the common case of an unshifted register
4882 with in line code. */
4885 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
4887 ARMword shamt
, base
;
4892 /* Shift amount in a register. */
4897 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4900 base
= state
->Reg
[base
];
4901 ARMul_Icycles (state
, 1, 0L);
4902 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4903 switch ((int) BITS (5, 6))
4908 else if (shamt
== 32)
4913 else if (shamt
> 32)
4920 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4921 return (base
<< shamt
);
4926 else if (shamt
== 32)
4928 ASSIGNC (base
>> 31);
4931 else if (shamt
> 32)
4938 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4939 return (base
>> shamt
);
4944 else if (shamt
>= 32)
4946 ASSIGNC (base
>> 31L);
4947 return ((ARMword
) ((ARMsword
) base
>> 31L));
4951 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4952 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4960 ASSIGNC (base
>> 31);
4965 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4966 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4972 /* Shift amount is a constant. */
4975 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4978 base
= state
->Reg
[base
];
4979 shamt
= BITS (7, 11);
4981 switch ((int) BITS (5, 6))
4984 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4985 return (base
<< shamt
);
4989 ASSIGNC (base
>> 31);
4994 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4995 return (base
>> shamt
);
5000 ASSIGNC (base
>> 31L);
5001 return ((ARMword
) ((ARMsword
) base
>> 31L));
5005 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
5006 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
5014 return ((base
>> 1) | (shamt
<< 31));
5018 ASSIGNC ((base
>> (shamt
- 1)) & 1);
5019 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
5027 /* This routine handles writes to register 15 when the S bit is not set. */
5030 WriteR15 (ARMul_State
* state
, ARMword src
)
5032 /* The ARM documentation states that the two least significant bits
5033 are discarded when setting PC, except in the cases handled by
5034 WriteR15Branch() below. It's probably an oversight: in THUMB
5035 mode, the second least significant bit should probably not be
5045 state
->Reg
[15] = src
& PCBITS
;
5047 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
5048 ARMul_R15Altered (state
);
5053 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5056 /* This routine handles writes to register 15 when the S bit is set. */
5059 WriteSR15 (ARMul_State
* state
, ARMword src
)
5062 if (state
->Bank
> 0)
5064 state
->Cpsr
= state
->Spsr
[state
->Bank
];
5065 ARMul_CPSRAltered (state
);
5073 state
->Reg
[15] = src
& PCBITS
;
5077 /* ARMul_R15Altered would have to support it. */
5083 if (state
->Bank
== USERBANK
)
5084 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
5086 state
->Reg
[15] = src
;
5088 ARMul_R15Altered (state
);
5092 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5095 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
5096 will switch to Thumb mode if the least significant bit is set. */
5099 WriteR15Branch (ARMul_State
* state
, ARMword src
)
5106 state
->Reg
[15] = src
& 0xfffffffe;
5111 state
->Reg
[15] = src
& 0xfffffffc;
5115 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5117 WriteR15 (state
, src
);
5121 /* Before ARM_v5 LDR and LDM of pc did not change mode. */
5124 WriteR15Load (ARMul_State
* state
, ARMword src
)
5127 WriteR15Branch (state
, src
);
5129 WriteR15 (state
, src
);
5132 /* This routine evaluates most Load and Store register RHS's. It is
5133 intended to be called from the macro LSRegRHS, which filters the
5134 common case of an unshifted register with in line code. */
5137 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
5139 ARMword shamt
, base
;
5144 /* Now forbidden, but ... */
5145 base
= ECC
| ER15INT
| R15PC
| EMODE
;
5148 base
= state
->Reg
[base
];
5150 shamt
= BITS (7, 11);
5151 switch ((int) BITS (5, 6))
5154 return (base
<< shamt
);
5159 return (base
>> shamt
);
5162 return ((ARMword
) ((ARMsword
) base
>> 31L));
5164 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
5168 return ((base
>> 1) | (CFLAG
<< 31));
5170 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
5177 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
5180 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
5187 /* Now forbidden, but ... */
5188 return ECC
| ER15INT
| R15PC
| EMODE
;
5190 return state
->Reg
[RHSReg
];
5194 return BITS (0, 3) | (BITS (8, 11) << 4);
5197 /* This function does the work of loading a word for a LDR instruction. */
5200 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5206 if (ADDREXCEPT (address
))
5207 INTERNALABORT (address
);
5210 dest
= ARMul_LoadWordN (state
, address
);
5215 return state
->lateabtSig
;
5218 dest
= ARMul_Align (state
, address
, dest
);
5220 ARMul_Icycles (state
, 1, 0L);
5222 return (DESTReg
!= LHSReg
);
5226 /* This function does the work of loading a halfword. */
5229 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
5236 if (ADDREXCEPT (address
))
5237 INTERNALABORT (address
);
5239 dest
= ARMul_LoadHalfWord (state
, address
);
5243 return state
->lateabtSig
;
5247 if (dest
& 1 << (16 - 1))
5248 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
5251 ARMul_Icycles (state
, 1, 0L);
5252 return (DESTReg
!= LHSReg
);
5257 /* This function does the work of loading a byte for a LDRB instruction. */
5260 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
5266 if (ADDREXCEPT (address
))
5267 INTERNALABORT (address
);
5269 dest
= ARMul_LoadByte (state
, address
);
5273 return state
->lateabtSig
;
5277 if (dest
& 1 << (8 - 1))
5278 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
5281 ARMul_Icycles (state
, 1, 0L);
5283 return (DESTReg
!= LHSReg
);
5286 /* This function does the work of loading two words for a LDRD instruction. */
5289 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
5293 ARMword write_back
= BIT (21);
5294 ARMword immediate
= BIT (22);
5295 ARMword add_to_base
= BIT (23);
5296 ARMword pre_indexed
= BIT (24);
5306 /* If the writeback bit is set, the pre-index bit must be clear. */
5307 if (write_back
&& ! pre_indexed
)
5309 ARMul_UndefInstr (state
, instr
);
5313 /* Extract the base address register. */
5316 /* Extract the destination register and check it. */
5319 /* Destination register must be even. */
5321 /* Destination register cannot be LR. */
5322 || (dest_reg
== 14))
5324 ARMul_UndefInstr (state
, instr
);
5328 /* Compute the base address. */
5329 base
= state
->Reg
[addr_reg
];
5331 /* Compute the offset. */
5332 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5334 /* Compute the sum of the two. */
5336 sum
= base
+ offset
;
5338 sum
= base
- offset
;
5340 /* If this is a pre-indexed mode use the sum. */
5346 if (state
->is_v6
&& (addr
& 0x3) == 0)
5347 /* Word alignment is enough for v6. */
5349 /* The address must be aligned on a 8 byte boundary. */
5350 else if (addr
& 0x7)
5353 ARMul_DATAABORT (addr
);
5355 ARMul_UndefInstr (state
, instr
);
5360 /* For pre indexed or post indexed addressing modes,
5361 check that the destination registers do not overlap
5362 the address registers. */
5363 if ((! pre_indexed
|| write_back
)
5364 && ( addr_reg
== dest_reg
5365 || addr_reg
== dest_reg
+ 1))
5367 ARMul_UndefInstr (state
, instr
);
5371 /* Load the words. */
5372 value1
= ARMul_LoadWordN (state
, addr
);
5373 value2
= ARMul_LoadWordN (state
, addr
+ 4);
5375 /* Check for data aborts. */
5382 ARMul_Icycles (state
, 2, 0L);
5384 /* Store the values. */
5385 state
->Reg
[dest_reg
] = value1
;
5386 state
->Reg
[dest_reg
+ 1] = value2
;
5388 /* Do the post addressing and writeback. */
5392 if (! pre_indexed
|| write_back
)
5393 state
->Reg
[addr_reg
] = addr
;
5396 /* This function does the work of storing two words for a STRD instruction. */
5399 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
5403 ARMword write_back
= BIT (21);
5404 ARMword immediate
= BIT (22);
5405 ARMword add_to_base
= BIT (23);
5406 ARMword pre_indexed
= BIT (24);
5414 /* If the writeback bit is set, the pre-index bit must be clear. */
5415 if (write_back
&& ! pre_indexed
)
5417 ARMul_UndefInstr (state
, instr
);
5421 /* Extract the base address register. */
5424 /* Base register cannot be PC. */
5427 ARMul_UndefInstr (state
, instr
);
5431 /* Extract the source register. */
5434 /* Source register must be even. */
5437 ARMul_UndefInstr (state
, instr
);
5441 /* Compute the base address. */
5442 base
= state
->Reg
[addr_reg
];
5444 /* Compute the offset. */
5445 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5447 /* Compute the sum of the two. */
5449 sum
= base
+ offset
;
5451 sum
= base
- offset
;
5453 /* If this is a pre-indexed mode use the sum. */
5459 /* The address must be aligned on a 8 byte boundary. */
5463 ARMul_DATAABORT (addr
);
5465 ARMul_UndefInstr (state
, instr
);
5470 /* For pre indexed or post indexed addressing modes,
5471 check that the destination registers do not overlap
5472 the address registers. */
5473 if ((! pre_indexed
|| write_back
)
5474 && ( addr_reg
== src_reg
5475 || addr_reg
== src_reg
+ 1))
5477 ARMul_UndefInstr (state
, instr
);
5481 /* Load the words. */
5482 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
5483 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
5491 /* Do the post addressing and writeback. */
5495 if (! pre_indexed
|| write_back
)
5496 state
->Reg
[addr_reg
] = addr
;
5499 /* This function does the work of storing a word from a STR instruction. */
5502 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5507 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5510 ARMul_StoreWordN (state
, address
, DEST
);
5512 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5514 INTERNALABORT (address
);
5515 (void) ARMul_LoadWordN (state
, address
);
5518 ARMul_StoreWordN (state
, address
, DEST
);
5523 return state
->lateabtSig
;
5529 /* This function does the work of storing a byte for a STRH instruction. */
5532 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5538 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5542 ARMul_StoreHalfWord (state
, address
, DEST
);
5544 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5546 INTERNALABORT (address
);
5547 (void) ARMul_LoadHalfWord (state
, address
);
5550 ARMul_StoreHalfWord (state
, address
, DEST
);
5556 return state
->lateabtSig
;
5563 /* This function does the work of storing a byte for a STRB instruction. */
5566 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
5571 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5574 ARMul_StoreByte (state
, address
, DEST
);
5576 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5578 INTERNALABORT (address
);
5579 (void) ARMul_LoadByte (state
, address
);
5582 ARMul_StoreByte (state
, address
, DEST
);
5587 return state
->lateabtSig
;
5593 /* This function does the work of loading the registers listed in an LDM
5594 instruction, when the S bit is clear. The code here is always increment
5595 after, it's up to the caller to get the input address correct and to
5596 handle base register modification. */
5599 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
5605 UNDEF_LSMBaseInListWb
;
5608 if (ADDREXCEPT (address
))
5609 INTERNALABORT (address
);
5611 if (BIT (21) && LHSReg
!= 15)
5614 /* N cycle first. */
5615 for (temp
= 0; !BIT (temp
); temp
++)
5618 dest
= ARMul_LoadWordN (state
, address
);
5620 if (!state
->abortSig
&& !state
->Aborted
)
5621 state
->Reg
[temp
++] = dest
;
5622 else if (!state
->Aborted
)
5624 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5625 state
->Aborted
= ARMul_DataAbortV
;
5628 /* S cycles from here on. */
5629 for (; temp
< 16; temp
++)
5632 /* Load this register. */
5634 dest
= ARMul_LoadWordS (state
, address
);
5636 if (!state
->abortSig
&& !state
->Aborted
)
5637 state
->Reg
[temp
] = dest
;
5638 else if (!state
->Aborted
)
5640 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5641 state
->Aborted
= ARMul_DataAbortV
;
5645 if (BIT (15) && !state
->Aborted
)
5646 /* PC is in the reg list. */
5647 WriteR15Load (state
, PC
);
5649 /* To write back the final register. */
5650 ARMul_Icycles (state
, 1, 0L);
5654 if (BIT (21) && LHSReg
!= 15)
5660 /* This function does the work of loading the registers listed in an LDM
5661 instruction, when the S bit is set. The code here is always increment
5662 after, it's up to the caller to get the input address correct and to
5663 handle base register modification. */
5666 LoadSMult (ARMul_State
* state
,
5675 UNDEF_LSMBaseInListWb
;
5680 if (ADDREXCEPT (address
))
5681 INTERNALABORT (address
);
5684 if (BIT (21) && LHSReg
!= 15)
5687 if (!BIT (15) && state
->Bank
!= USERBANK
)
5689 /* Temporary reg bank switch. */
5690 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5691 UNDEF_LSMUserBankWb
;
5694 /* N cycle first. */
5695 for (temp
= 0; !BIT (temp
); temp
++)
5698 dest
= ARMul_LoadWordN (state
, address
);
5700 if (!state
->abortSig
)
5701 state
->Reg
[temp
++] = dest
;
5702 else if (!state
->Aborted
)
5704 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5705 state
->Aborted
= ARMul_DataAbortV
;
5708 /* S cycles from here on. */
5709 for (; temp
< 16; temp
++)
5712 /* Load this register. */
5714 dest
= ARMul_LoadWordS (state
, address
);
5716 if (!state
->abortSig
&& !state
->Aborted
)
5717 state
->Reg
[temp
] = dest
;
5718 else if (!state
->Aborted
)
5720 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5721 state
->Aborted
= ARMul_DataAbortV
;
5725 if (BIT (15) && !state
->Aborted
)
5727 /* PC is in the reg list. */
5729 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5731 state
->Cpsr
= GETSPSR (state
->Bank
);
5732 ARMul_CPSRAltered (state
);
5735 WriteR15 (state
, PC
);
5737 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
5739 /* Protect bits in user mode. */
5740 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
5741 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
5742 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
5743 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
5746 ARMul_R15Altered (state
);
5752 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5753 /* Restore the correct bank. */
5754 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5756 /* To write back the final register. */
5757 ARMul_Icycles (state
, 1, 0L);
5761 if (BIT (21) && LHSReg
!= 15)
5768 /* This function does the work of storing the registers listed in an STM
5769 instruction, when the S bit is clear. The code here is always increment
5770 after, it's up to the caller to get the input address correct and to
5771 handle base register modification. */
5774 StoreMult (ARMul_State
* state
,
5783 UNDEF_LSMBaseInListWb
;
5786 /* N-cycle, increment the PC and update the NextInstr state. */
5790 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5791 INTERNALABORT (address
);
5797 /* N cycle first. */
5798 for (temp
= 0; !BIT (temp
); temp
++)
5802 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5806 (void) ARMul_LoadWordN (state
, address
);
5808 /* Fake the Stores as Loads. */
5809 for (; temp
< 16; temp
++)
5812 /* Save this register. */
5814 (void) ARMul_LoadWordS (state
, address
);
5817 if (BIT (21) && LHSReg
!= 15)
5823 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5826 if (state
->abortSig
&& !state
->Aborted
)
5828 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5829 state
->Aborted
= ARMul_DataAbortV
;
5832 if (BIT (21) && LHSReg
!= 15)
5835 /* S cycles from here on. */
5836 for (; temp
< 16; temp
++)
5839 /* Save this register. */
5842 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5844 if (state
->abortSig
&& !state
->Aborted
)
5846 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5847 state
->Aborted
= ARMul_DataAbortV
;
5855 /* This function does the work of storing the registers listed in an STM
5856 instruction when the S bit is set. The code here is always increment
5857 after, it's up to the caller to get the input address correct and to
5858 handle base register modification. */
5861 StoreSMult (ARMul_State
* state
,
5870 UNDEF_LSMBaseInListWb
;
5875 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5876 INTERNALABORT (address
);
5882 if (state
->Bank
!= USERBANK
)
5884 /* Force User Bank. */
5885 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5886 UNDEF_LSMUserBankWb
;
5889 for (temp
= 0; !BIT (temp
); temp
++)
5890 ; /* N cycle first. */
5893 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5897 (void) ARMul_LoadWordN (state
, address
);
5899 for (; temp
< 16; temp
++)
5900 /* Fake the Stores as Loads. */
5903 /* Save this register. */
5906 (void) ARMul_LoadWordS (state
, address
);
5909 if (BIT (21) && LHSReg
!= 15)
5916 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5919 if (state
->abortSig
&& !state
->Aborted
)
5921 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5922 state
->Aborted
= ARMul_DataAbortV
;
5925 /* S cycles from here on. */
5926 for (; temp
< 16; temp
++)
5929 /* Save this register. */
5932 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5934 if (state
->abortSig
&& !state
->Aborted
)
5936 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5937 state
->Aborted
= ARMul_DataAbortV
;
5941 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5942 /* Restore the correct bank. */
5943 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5945 if (BIT (21) && LHSReg
!= 15)
5952 /* This function does the work of adding two 32bit values
5953 together, and calculating if a carry has occurred. */
5956 Add32 (ARMword a1
, ARMword a2
, int *carry
)
5958 ARMword result
= (a1
+ a2
);
5959 unsigned int uresult
= (unsigned int) result
;
5960 unsigned int ua1
= (unsigned int) a1
;
5962 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5963 or (result > RdLo) then we have no carry. */
5964 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
5972 /* This function does the work of multiplying
5973 two 32bit values to give a 64bit result. */
5976 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5978 /* Operand register numbers. */
5979 int nRdHi
, nRdLo
, nRs
, nRm
;
5980 ARMword RdHi
= 0, RdLo
= 0, Rm
;
5984 nRdHi
= BITS (16, 19);
5985 nRdLo
= BITS (12, 15);
5989 /* Needed to calculate the cycle count. */
5990 Rm
= state
->Reg
[nRm
];
5992 /* Check for illegal operand combinations first. */
5999 /* Intermediate results. */
6000 ARMword lo
, mid1
, mid2
, hi
;
6002 ARMword Rs
= state
->Reg
[nRs
];
6010 /* BAD code can trigger this result. So only complain if debugging. */
6011 if (state
->Debug
&& (nRdHi
== nRm
|| nRdLo
== nRm
))
6012 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS: %d %d %d\n",
6016 /* Compute sign of result and adjust operands if necessary. */
6017 sign
= (Rm
^ Rs
) & 0x80000000;
6019 if (((ARMsword
) Rm
) < 0)
6022 if (((ARMsword
) Rs
) < 0)
6026 /* We can split the 32x32 into four 16x16 operations. This
6027 ensures that we do not lose precision on 32bit only hosts. */
6028 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
6029 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
6030 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
6031 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
6033 /* We now need to add all of these results together, taking
6034 care to propogate the carries from the additions. */
6035 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
6037 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
6039 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
6043 /* Negate result if necessary. */
6046 if (RdLo
== 0xFFFFFFFF)
6055 state
->Reg
[nRdLo
] = RdLo
;
6056 state
->Reg
[nRdHi
] = RdHi
;
6058 else if (state
->Debug
)
6059 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
6062 /* Ensure that both RdHi and RdLo are used to compute Z,
6063 but don't let RdLo's sign bit make it to N. */
6064 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6066 /* The cycle count depends on whether the instruction is a signed or
6067 unsigned multiply, and what bits are clear in the multiplier. */
6068 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
6069 /* Invert the bits to make the check against zero. */
6072 if ((Rm
& 0xFFFFFF00) == 0)
6074 else if ((Rm
& 0xFFFF0000) == 0)
6076 else if ((Rm
& 0xFF000000) == 0)
6084 /* This function does the work of multiplying two 32bit
6085 values and adding a 64bit value to give a 64bit result. */
6088 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
6095 nRdHi
= BITS (16, 19);
6096 nRdLo
= BITS (12, 15);
6098 RdHi
= state
->Reg
[nRdHi
];
6099 RdLo
= state
->Reg
[nRdLo
];
6101 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
6103 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
6104 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
6106 state
->Reg
[nRdLo
] = RdLo
;
6107 state
->Reg
[nRdHi
] = RdHi
;
6110 /* Ensure that both RdHi and RdLo are used to compute Z,
6111 but don't let RdLo's sign bit make it to N. */
6112 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6114 /* Extra cycle for addition. */