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/>. */
18 /* This must come before any other includes. */
26 static ARMword
GetDPRegRHS (ARMul_State
*, ARMword
);
27 static ARMword
GetDPSRegRHS (ARMul_State
*, ARMword
);
28 static void WriteR15 (ARMul_State
*, ARMword
);
29 static void WriteSR15 (ARMul_State
*, ARMword
);
30 static void WriteR15Branch (ARMul_State
*, ARMword
);
31 static void WriteR15Load (ARMul_State
*, ARMword
);
32 static ARMword
GetLSRegRHS (ARMul_State
*, ARMword
);
33 static ARMword
GetLS7RHS (ARMul_State
*, ARMword
);
34 static unsigned LoadWord (ARMul_State
*, ARMword
, ARMword
);
35 static unsigned LoadHalfWord (ARMul_State
*, ARMword
, ARMword
, int);
36 static unsigned LoadByte (ARMul_State
*, ARMword
, ARMword
, int);
37 static unsigned StoreWord (ARMul_State
*, ARMword
, ARMword
);
38 static unsigned StoreHalfWord (ARMul_State
*, ARMword
, ARMword
);
39 static unsigned StoreByte (ARMul_State
*, ARMword
, ARMword
);
40 static void LoadMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
41 static void StoreMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
42 static void LoadSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
43 static void StoreSMult (ARMul_State
*, ARMword
, ARMword
, ARMword
);
44 static unsigned Multiply64 (ARMul_State
*, ARMword
, int, int);
45 static unsigned MultiplyAdd64 (ARMul_State
*, ARMword
, int, int);
46 static void Handle_Load_Double (ARMul_State
*, ARMword
);
47 static void Handle_Store_Double (ARMul_State
*, ARMword
);
49 #define LUNSIGNED (0) /* unsigned operation */
50 #define LSIGNED (1) /* signed operation */
51 #define LDEFAULT (0) /* default : do nothing */
52 #define LSCC (1) /* set condition codes on result */
54 extern int stop_simulator
;
56 /* Short-hand macros for LDR/STR. */
58 /* Store post decrement writeback. */
61 if (StoreHalfWord (state, instr, lhs)) \
62 LSBase = lhs - GetLS7RHS (state, instr);
64 /* Store post increment writeback. */
67 if (StoreHalfWord (state, instr, lhs)) \
68 LSBase = lhs + GetLS7RHS (state, instr);
70 /* Store pre decrement. */
72 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
74 /* Store pre decrement writeback. */
75 #define SHPREDOWNWB() \
76 temp = LHS - GetLS7RHS (state, instr); \
77 if (StoreHalfWord (state, instr, temp)) \
80 /* Store pre increment. */
82 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
84 /* Store pre increment writeback. */
86 temp = LHS + GetLS7RHS (state, instr); \
87 if (StoreHalfWord (state, instr, temp)) \
90 /* Load post decrement writeback. */
91 #define LHPOSTDOWN() \
95 temp = lhs - GetLS7RHS (state, instr); \
97 switch (BITS (5, 6)) \
100 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
104 if (LoadByte (state, instr, lhs, LSIGNED)) \
108 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
111 case 0: /* SWP handled elsewhere. */ \
120 /* Load post increment writeback. */
125 temp = lhs + GetLS7RHS (state, instr); \
127 switch (BITS (5, 6)) \
130 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
134 if (LoadByte (state, instr, lhs, LSIGNED)) \
138 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
141 case 0: /* SWP handled elsewhere. */ \
150 /* Load pre decrement. */
151 #define LHPREDOWN() \
155 temp = LHS - GetLS7RHS (state, instr); \
156 switch (BITS (5, 6)) \
159 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
162 (void) LoadByte (state, instr, temp, LSIGNED); \
165 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
168 /* SWP handled elsewhere. */ \
177 /* Load pre decrement writeback. */
178 #define LHPREDOWNWB() \
182 temp = LHS - GetLS7RHS (state, instr); \
183 switch (BITS (5, 6)) \
186 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
190 if (LoadByte (state, instr, temp, LSIGNED)) \
194 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
198 /* SWP handled elsewhere. */ \
207 /* Load pre increment. */
212 temp = LHS + GetLS7RHS (state, instr); \
213 switch (BITS (5, 6)) \
216 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
219 (void) LoadByte (state, instr, temp, LSIGNED); \
222 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
225 /* SWP handled elsewhere. */ \
234 /* Load pre increment writeback. */
235 #define LHPREUPWB() \
239 temp = LHS + GetLS7RHS (state, instr); \
240 switch (BITS (5, 6)) \
243 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
247 if (LoadByte (state, instr, temp, LSIGNED)) \
251 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
255 /* SWP handled elsewhere. */ \
264 /* Attempt to emulate an ARMv6 instruction.
265 Returns non-zero upon success. */
269 handle_v6_insn (ARMul_State
* state
, ARMword instr
)
276 switch (BITS (20, 27))
279 case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
280 case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
281 case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
282 case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
283 case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
284 case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
285 case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
286 case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
287 case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
288 case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
289 case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
290 case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
291 case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
292 case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
294 case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
295 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
296 case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
297 case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
298 case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
299 case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
300 case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
304 /* MOVW<c> <Rd>,#<imm16>
306 instr[27,20] = 0011 0000
309 instr[11, 0] = imm12. */
311 val
= (BITS (16, 19) << 12) | BITS (0, 11);
312 state
->Reg
[Rd
] = val
;
318 /* MOVT<c> <Rd>,#<imm16>
320 instr[27,20] = 0011 0100
323 instr[11, 0] = imm12. */
325 val
= (BITS (16, 19) << 12) | BITS (0, 11);
326 state
->Reg
[Rd
] &= 0xFFFF;
327 state
->Reg
[Rd
] |= val
<< 16;
342 if (Rd
== 15 || Rn
== 15 || Rm
== 15)
345 val1
= state
->Reg
[Rn
];
346 val2
= state
->Reg
[Rm
];
348 switch (BITS (4, 11))
350 case 0xF1: /* QADD16<c> <Rd>,<Rn>,<Rm>. */
353 for (i
= 0; i
< 32; i
+= 16)
355 n
= (val1
>> i
) & 0xFFFF;
359 m
= (val2
>> i
) & 0xFFFF;
367 else if (r
< -(0x8000))
370 state
->Reg
[Rd
] |= (r
& 0xFFFF) << i
;
374 case 0xF3: /* QASX<c> <Rd>,<Rn>,<Rm>. */
379 m
= (val2
>> 16) & 0xFFFF;
387 else if (r
< -(0x8000))
390 state
->Reg
[Rd
] = (r
& 0xFFFF);
392 n
= (val1
>> 16) & 0xFFFF;
404 else if (r
< -(0x8000))
407 state
->Reg
[Rd
] |= (r
& 0xFFFF) << 16;
410 case 0xF5: /* QSAX<c> <Rd>,<Rn>,<Rm>. */
415 m
= (val2
>> 16) & 0xFFFF;
423 else if (r
< -(0x8000))
426 state
->Reg
[Rd
] = (r
& 0xFFFF);
428 n
= (val1
>> 16) & 0xFFFF;
440 else if (r
< -(0x8000))
443 state
->Reg
[Rd
] |= (r
& 0xFFFF) << 16;
446 case 0xF7: /* QSUB16<c> <Rd>,<Rn>,<Rm>. */
449 for (i
= 0; i
< 32; i
+= 16)
451 n
= (val1
>> i
) & 0xFFFF;
455 m
= (val2
>> i
) & 0xFFFF;
463 else if (r
< -(0x8000))
466 state
->Reg
[Rd
] |= (r
& 0xFFFF) << i
;
470 case 0xF9: /* QADD8<c> <Rd>,<Rn>,<Rm>. */
473 for (i
= 0; i
< 32; i
+= 8)
475 n
= (val1
>> i
) & 0xFF;
479 m
= (val2
>> i
) & 0xFF;
490 state
->Reg
[Rd
] |= (r
& 0xFF) << i
;
494 case 0xFF: /* QSUB8<c> <Rd>,<Rn>,<Rm>. */
497 for (i
= 0; i
< 32; i
+= 8)
499 n
= (val1
>> i
) & 0xFF;
503 m
= (val2
>> i
) & 0xFF;
514 state
->Reg
[Rd
] |= (r
& 0xFF) << i
;
528 ARMword res1
, res2
, res3
, res4
;
530 /* U{ADD|SUB}{8|16}<c> <Rd>, <Rn>, <Rm>
532 instr[27,20] = 0110 0101
536 instr[ 7, 4] = opcode: UADD8 (1001), UADD16 (0001), USUB8 (1111), USUB16 (0111)
537 instr[ 3, 0] = Rm. */
538 if (BITS (8, 11) != 0xF)
545 if (Rn
== 15 || Rd
== 15 || Rm
== 15)
547 ARMul_UndefInstr (state
, instr
);
548 state
->Emulate
= FALSE
;
552 valn
= state
->Reg
[Rn
];
553 valm
= state
->Reg
[Rm
];
557 case 1: /* UADD16. */
558 res1
= (valn
& 0xFFFF) + (valm
& 0xFFFF);
560 state
->Cpsr
|= (GE0
| GE1
);
562 state
->Cpsr
&= ~ (GE0
| GE1
);
564 res2
= (valn
>> 16) + (valm
>> 16);
566 state
->Cpsr
|= (GE2
| GE3
);
568 state
->Cpsr
&= ~ (GE2
| GE3
);
570 state
->Reg
[Rd
] = (res1
& 0xFFFF) | (res2
<< 16);
573 case 7: /* USUB16. */
574 res1
= (valn
& 0xFFFF) - (valm
& 0xFFFF);
576 state
->Cpsr
|= (GE0
| GE1
);
578 state
->Cpsr
&= ~ (GE0
| GE1
);
580 res2
= (valn
>> 16) - (valm
>> 16);
582 state
->Cpsr
|= (GE2
| GE3
);
584 state
->Cpsr
&= ~ (GE2
| GE3
);
586 state
->Reg
[Rd
] = (res1
& 0xFFFF) | (res2
<< 16);
590 res1
= (valn
& 0xFF) + (valm
& 0xFF);
594 state
->Cpsr
&= ~ GE0
;
596 res2
= ((valn
>> 8) & 0xFF) + ((valm
>> 8) & 0xFF);
600 state
->Cpsr
&= ~ GE1
;
602 res3
= ((valn
>> 16) & 0xFF) + ((valm
>> 16) & 0xFF);
606 state
->Cpsr
&= ~ GE2
;
608 res4
= (valn
>> 24) + (valm
>> 24);
612 state
->Cpsr
&= ~ GE3
;
614 state
->Reg
[Rd
] = (res1
& 0xFF) | ((res2
<< 8) & 0xFF00)
615 | ((res3
<< 16) & 0xFF0000) | (res4
<< 24);
618 case 15: /* USUB8. */
619 res1
= (valn
& 0xFF) - (valm
& 0xFF);
623 state
->Cpsr
&= ~ GE0
;
625 res2
= ((valn
>> 8) & 0XFF) - ((valm
>> 8) & 0xFF);
629 state
->Cpsr
&= ~ GE1
;
631 res3
= ((valn
>> 16) & 0XFF) - ((valm
>> 16) & 0xFF);
635 state
->Cpsr
&= ~ GE2
;
637 res4
= (valn
>> 24) - (valm
>> 24) ;
641 state
->Cpsr
&= ~ GE3
;
643 state
->Reg
[Rd
] = (res1
& 0xFF) | ((res2
<< 8) & 0xFF00)
644 | ((res3
<< 16) & 0xFF0000) | (res4
<< 24);
657 /* PKHBT<c> <Rd>,<Rn>,<Rm>{,LSL #<imm>}
658 PKHTB<c> <Rd>,<Rn>,<Rm>{,ASR #<imm>}
659 SXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>}
660 SXTB16<c> <Rd>,<Rm>{,<rotation>}
661 SEL<c> <Rd>,<Rn>,<Rm>
664 instr[27,20] = 0110 1000
667 instr[11, 7] = imm5 (PKH), 11111 (SEL), rr000 (SXTAB16 & SXTB16),
668 instr[6] = tb (PKH), 0 (SEL), 1 (SXT)
669 instr[5] = opcode: PKH (0), SEL/SXT (1)
671 instr[ 3, 0] = Rm. */
678 /* FIXME: Add implementation of PKH. */
679 fprintf (stderr
, "PKH: NOT YET IMPLEMENTED\n");
680 ARMul_UndefInstr (state
, instr
);
686 /* FIXME: Add implementation of SXT. */
687 fprintf (stderr
, "SXT: NOT YET IMPLEMENTED\n");
688 ARMul_UndefInstr (state
, instr
);
695 if (Rn
== 15 || Rm
== 15 || Rd
== 15)
697 ARMul_UndefInstr (state
, instr
);
698 state
->Emulate
= FALSE
;
702 res
= (state
->Reg
[(state
->Cpsr
& GE0
) ? Rn
: Rm
]) & 0xFF;
703 res
|= (state
->Reg
[(state
->Cpsr
& GE1
) ? Rn
: Rm
]) & 0xFF00;
704 res
|= (state
->Reg
[(state
->Cpsr
& GE2
) ? Rn
: Rm
]) & 0xFF0000;
705 res
|= (state
->Reg
[(state
->Cpsr
& GE3
) ? Rn
: Rm
]) & 0xFF000000;
706 state
->Reg
[Rd
] = res
;
714 switch (BITS (4, 11))
716 case 0x07: ror
= 0; break;
717 case 0x47: ror
= 8; break;
718 case 0x87: ror
= 16; break;
719 case 0xc7: ror
= 24; break;
723 printf ("Unhandled v6 insn: ssat\n");
732 if (BITS (4, 6) == 0x7)
734 printf ("Unhandled v6 insn: ssat\n");
740 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
744 if (BITS (16, 19) == 0xf)
746 state
->Reg
[BITS (12, 15)] = Rm
;
749 state
->Reg
[BITS (12, 15)] += Rm
;
757 switch (BITS (4, 11))
759 case 0x07: ror
= 0; break;
760 case 0x47: ror
= 8; break;
761 case 0x87: ror
= 16; break;
762 case 0xc7: ror
= 24; break;
768 instr[27,20] = 0110 1011
771 instr[11, 4] = 1111 0011
772 instr[ 3, 0] = Rm. */
773 if (BITS (16, 19) != 0xF)
778 if (Rd
== 15 || Rm
== 15)
780 ARMul_UndefInstr (state
, instr
);
781 state
->Emulate
= FALSE
;
785 val
= state
->Reg
[Rm
] << 24;
786 val
|= ((state
->Reg
[Rm
] << 8) & 0xFF0000);
787 val
|= ((state
->Reg
[Rm
] >> 8) & 0xFF00);
788 val
|= ((state
->Reg
[Rm
] >> 24));
789 state
->Reg
[Rd
] = val
;
795 /* REV16<c> <Rd>,<Rm>. */
796 if (BITS (16, 19) != 0xF)
801 if (Rd
== 15 || Rm
== 15)
803 ARMul_UndefInstr (state
, instr
);
804 state
->Emulate
= FALSE
;
809 val
|= ((state
->Reg
[Rm
] >> 8) & 0x00FF00FF);
810 val
|= ((state
->Reg
[Rm
] << 8) & 0xFF00FF00);
811 state
->Reg
[Rd
] = val
;
822 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
826 if (BITS (16, 19) == 0xf)
828 state
->Reg
[BITS (12, 15)] = Rm
;
831 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
839 switch (BITS (4, 11))
841 case 0x07: ror
= 0; break;
842 case 0x47: ror
= 8; break;
843 case 0x87: ror
= 16; break;
844 case 0xc7: ror
= 24; break;
848 printf ("Unhandled v6 insn: usat\n");
857 if (BITS (4, 6) == 0x7)
859 printf ("Unhandled v6 insn: usat\n");
865 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFF);
867 if (BITS (16, 19) == 0xf)
869 state
->Reg
[BITS (12, 15)] = Rm
;
872 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
881 switch (BITS (4, 11))
883 case 0x07: ror
= 0; break;
884 case 0x47: ror
= 8; break;
885 case 0x87: ror
= 16; break;
886 case 0xc7: ror
= 24; break;
888 case 0xf3: /* RBIT */
889 if (BITS (16, 19) != 0xF)
893 Rm
= state
->Reg
[BITS (0, 3)];
894 for (i
= 0; i
< 32; i
++)
896 state
->Reg
[Rd
] |= (1 << (31 - i
));
900 printf ("Unhandled v6 insn: revsh\n");
910 Rm
= ((state
->Reg
[BITS (0, 3)] >> ror
) & 0xFFFF);
912 if (BITS (16, 19) == 0xf)
914 state
->Reg
[BITS (12, 15)] = Rm
;
917 state
->Reg
[BITS (12, 15)] = state
->Reg
[BITS (16, 19)] + Rm
;
925 /* SDIV<c> <Rd>,<Rn>,<Rm>
926 UDIV<c> <Rd>,<Rn>,<Rm>
928 instr[27,20] = 0111 0001 (SDIV), 0111 0011 (UDIV)
935 /* These bit-positions are confusing!
937 instr[11, 8] = 1111 */
939 #if 0 /* This is what I would expect: */
943 #else /* This seem to work: */
948 if (Rn
== 15 || Rd
== 15 || Rm
== 15
949 || Rn
== 13 || Rd
== 13 || Rm
== 13)
951 ARMul_UndefInstr (state
, instr
);
952 state
->Emulate
= FALSE
;
956 valn
= state
->Reg
[Rn
];
957 valm
= state
->Reg
[Rm
];
962 /* Exceptions: UsageFault, address 20
963 Note: UsageFault is for Cortex-M; I don't know what it would be on non-Cortex-M. */
964 ARMul_Abort (state
, address
);
966 printf ("Unhandled v6 insn: %cDIV divide by zero exception\n", "SU"[BIT(21)]);
976 val
= ((ARMsword
)valn
/ (ARMsword
)valm
);
978 state
->Reg
[Rd
] = val
;
990 /* BFC<c> <Rd>,#<lsb>,#<width>
991 BFI<c> <Rd>,<Rn>,#<lsb>,#<width>
994 instr[27,21] = 0111 110
998 instr[ 6, 4] = 001 1111
999 instr[ 3, 0] = Rn (BFI) / 1111 (BFC). */
1001 if (BITS (4, 6) != 0x1)
1007 ARMul_UndefInstr (state
, instr
);
1008 state
->Emulate
= FALSE
;
1012 msb
= BITS (16, 20);
1015 ARMul_UndefInstr (state
, instr
);
1016 state
->Emulate
= FALSE
;
1020 mask
&= ~(-(1 << (msb
+ 1)));
1021 state
->Reg
[Rd
] &= ~ mask
;
1026 val
= state
->Reg
[Rn
] & ~(-(1 << ((msb
+ 1) - lsb
)));
1027 state
->Reg
[Rd
] |= val
<< lsb
;
1032 case 0x7a: /* SBFX<c> <Rd>,<Rn>,#<lsb>,#<width>. */
1038 if (BITS (4, 6) != 0x5)
1044 ARMul_UndefInstr (state
, instr
);
1045 state
->Emulate
= FALSE
;
1051 ARMul_UndefInstr (state
, instr
);
1052 state
->Emulate
= FALSE
;
1056 widthm1
= BITS (16, 20);
1058 sval
= state
->Reg
[Rn
];
1059 sval
<<= (31 - (lsb
+ widthm1
));
1060 sval
>>= (31 - widthm1
);
1061 state
->Reg
[Rd
] = sval
;
1072 /* UBFX<c> <Rd>,<Rn>,#<lsb>,#<width>
1074 instr[27,21] = 0111 111
1075 instr[20,16] = widthm1
1079 instr[ 3, 0] = Rn. */
1081 if (BITS (4, 6) != 0x5)
1087 ARMul_UndefInstr (state
, instr
);
1088 state
->Emulate
= FALSE
;
1094 ARMul_UndefInstr (state
, instr
);
1095 state
->Emulate
= FALSE
;
1099 widthm1
= BITS (16, 20);
1101 val
= state
->Reg
[Rn
];
1103 val
&= ~(-(1 << (widthm1
+ 1)));
1105 state
->Reg
[Rd
] = val
;
1110 case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
1115 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr
);
1121 handle_VFP_move (ARMul_State
* state
, ARMword instr
)
1123 switch (BITS (20, 27))
1127 switch (BITS (4, 11))
1132 /* VMOV two core <-> two VFP single precision. */
1133 int sreg
= (BITS (0, 3) << 1) | BIT (5);
1137 state
->Reg
[BITS (12, 15)] = VFP_uword (sreg
);
1138 state
->Reg
[BITS (16, 19)] = VFP_uword (sreg
+ 1);
1142 VFP_uword (sreg
) = state
->Reg
[BITS (12, 15)];
1143 VFP_uword (sreg
+ 1) = state
->Reg
[BITS (16, 19)];
1151 /* VMOV two core <-> VFP double precision. */
1152 int dreg
= BITS (0, 3) | (BIT (5) << 4);
1157 fprintf (stderr
, " VFP: VMOV: r%d r%d <= d%d\n",
1158 BITS (12, 15), BITS (16, 19), dreg
);
1160 state
->Reg
[BITS (12, 15)] = VFP_dword (dreg
);
1161 state
->Reg
[BITS (16, 19)] = VFP_dword (dreg
) >> 32;
1165 VFP_dword (dreg
) = state
->Reg
[BITS (16, 19)];
1166 VFP_dword (dreg
) <<= 32;
1167 VFP_dword (dreg
) |= state
->Reg
[BITS (12, 15)];
1170 fprintf (stderr
, " VFP: VMOV: d%d <= r%d r%d : %g\n",
1171 dreg
, BITS (16, 19), BITS (12, 15),
1178 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1185 /* VMOV single core <-> VFP single precision. */
1186 if (BITS (0, 6) != 0x10 || BITS (8, 11) != 0xA)
1187 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1190 int sreg
= (BITS (16, 19) << 1) | BIT (7);
1193 state
->Reg
[DESTReg
] = VFP_uword (sreg
);
1195 VFP_uword (sreg
) = state
->Reg
[DESTReg
];
1200 fprintf (stderr
, "SIM: VFP: Unimplemented move insn %x\n", BITS (20, 27));
1205 /* EMULATION of ARM6. */
1209 ARMul_Emulate32 (ARMul_State
* state
)
1211 ARMul_Emulate26 (ARMul_State
* state
)
1214 ARMword instr
; /* The current instruction. */
1215 ARMword dest
= 0; /* Almost the DestBus. */
1216 ARMword temp
; /* Ubiquitous third hand. */
1217 ARMword pc
= 0; /* The address of the current instruction. */
1218 ARMword lhs
; /* Almost the ABus and BBus. */
1220 ARMword decoded
= 0; /* Instruction pipeline. */
1223 /* Execute the next instruction. */
1225 if (state
->NextInstr
< PRIMEPIPE
)
1227 decoded
= state
->decoded
;
1228 loaded
= state
->loaded
;
1234 /* Just keep going. */
1237 switch (state
->NextInstr
)
1240 /* Advance the pipeline, and an S cycle. */
1241 state
->Reg
[15] += isize
;
1245 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1249 /* Advance the pipeline, and an N cycle. */
1250 state
->Reg
[15] += isize
;
1254 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
1259 /* Program counter advanced, and an S cycle. */
1263 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1268 /* Program counter advanced, and an N cycle. */
1272 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
1277 /* The program counter has been changed. */
1278 pc
= state
->Reg
[15];
1280 pc
= pc
& R15PCBITS
;
1282 state
->Reg
[15] = pc
+ (isize
* 2);
1284 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
1285 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
1286 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
1291 /* The program counter has been changed. */
1292 pc
= state
->Reg
[15];
1294 pc
= pc
& R15PCBITS
;
1296 state
->Reg
[15] = pc
+ (isize
* 2);
1298 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
1299 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
1300 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
1305 if (state
->EventSet
)
1306 ARMul_EnvokeEvent (state
);
1308 if (! TFLAG
&& trace
)
1310 fprintf (stderr
, "pc: %x, ", pc
& ~1);
1312 fprintf (stderr
, "instr: %x\n", instr
);
1315 if (instr
== 0 || pc
< 0x10)
1317 ARMul_Abort (state
, ARMUndefinedInstrV
);
1318 state
->Emulate
= FALSE
;
1321 #if 0 /* Enable this code to help track down stack alignment bugs. */
1323 static ARMword old_sp
= -1;
1325 if (old_sp
!= state
->Reg
[13])
1327 old_sp
= state
->Reg
[13];
1328 fprintf (stderr
, "pc: %08x: SP set to %08x%s\n",
1329 pc
& ~1, old_sp
, (old_sp
% 8) ? " [UNALIGNED!]" : "");
1334 if (state
->Exception
)
1336 /* Any exceptions ? */
1337 if (state
->NresetSig
== LOW
)
1339 ARMul_Abort (state
, ARMul_ResetV
);
1342 else if (!state
->NfiqSig
&& !FFLAG
)
1344 ARMul_Abort (state
, ARMul_FIQV
);
1347 else if (!state
->NirqSig
&& !IFLAG
)
1349 ARMul_Abort (state
, ARMul_IRQV
);
1354 if (state
->CallDebug
> 0)
1356 if (state
->Emulate
< ONCE
)
1358 state
->NextInstr
= RESUME
;
1363 fprintf (stderr
, "sim: At %08lx Instr %08lx Mode %02lx\n",
1364 (long) pc
, (long) instr
, (long) state
->Mode
);
1365 (void) fgetc (stdin
);
1368 else if (state
->Emulate
< ONCE
)
1370 state
->NextInstr
= RESUME
;
1377 /* Provide Thumb instruction decoding. If the processor is in Thumb
1378 mode, then we can simply decode the Thumb instruction, and map it
1379 to the corresponding ARM instruction (by directly loading the
1380 instr variable, and letting the normal ARM simulator
1381 execute). There are some caveats to ensure that the correct
1382 pipelined PC value is used when executing Thumb code, and also for
1383 dealing with the BL instruction. */
1388 /* Check if in Thumb mode. */
1389 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
1392 /* This is a Thumb instruction. */
1393 ARMul_UndefInstr (state
, instr
);
1397 /* Already processed. */
1401 /* ARM instruction available. */
1404 fprintf (stderr
, " emulate as: ");
1406 fprintf (stderr
, "%08x ", new);
1408 fprintf (stderr
, "\n");
1411 /* So continue instruction decoding. */
1421 /* Check the condition codes. */
1422 if ((temp
= TOPBITS (28)) == AL
)
1423 /* Vile deed in the need for speed. */
1426 /* Check the condition code. */
1427 switch ((int) TOPBITS (28))
1435 if (BITS (25, 27) == 5) /* BLX(1) */
1437 state
->Reg
[14] = pc
+ 4;
1439 /* Force entry into Thumb mode. */
1442 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
1444 dest
+= POSBRANCH
+ (BIT (24) << 1);
1446 WriteR15Branch (state
, dest
);
1449 else if ((instr
& 0xFC70F000) == 0xF450F000)
1450 /* The PLD instruction. Ignored. */
1452 else if ( ((instr
& 0xfe500f00) == 0xfc100100)
1453 || ((instr
& 0xfe500f00) == 0xfc000100))
1454 /* wldrw and wstrw are unconditional. */
1457 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
1458 ARMul_UndefInstr (state
, instr
);
1487 temp
= (CFLAG
&& !ZFLAG
);
1490 temp
= (!CFLAG
|| ZFLAG
);
1493 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
1496 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
1499 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
1502 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
1506 /* Handle the Clock counter here. */
1507 if (state
->is_XScale
)
1512 ok
= state
->CPRead
[14] (state
, 0, & cp14r0
);
1514 if (ok
&& (cp14r0
& ARMul_CP14_R0_ENABLE
))
1516 unsigned long newcycles
, nowtime
= ARMul_Time (state
);
1518 newcycles
= nowtime
- state
->LastTime
;
1519 state
->LastTime
= nowtime
;
1521 if (cp14r0
& ARMul_CP14_R0_CCD
)
1523 if (state
->CP14R0_CCD
== -1)
1524 state
->CP14R0_CCD
= newcycles
;
1526 state
->CP14R0_CCD
+= newcycles
;
1528 if (state
->CP14R0_CCD
>= 64)
1532 while (state
->CP14R0_CCD
>= 64)
1533 state
->CP14R0_CCD
-= 64, newcycles
++;
1543 state
->CP14R0_CCD
= -1;
1546 cp14r0
|= ARMul_CP14_R0_FLAG2
;
1547 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
1549 ok
= state
->CPRead
[14] (state
, 1, & cp14r1
);
1551 /* Coded like this for portability. */
1552 while (ok
&& newcycles
)
1554 if (cp14r1
== 0xffffffff)
1565 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
1567 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
1571 if (state
->CPRead
[13] (state
, 8, & cp
)
1572 && (cp
& ARMul_CP13_R8_PMUS
))
1573 ARMul_Abort (state
, ARMul_FIQV
);
1575 ARMul_Abort (state
, ARMul_IRQV
);
1581 /* Handle hardware instructions breakpoints here. */
1582 if (state
->is_XScale
)
1584 if ( (pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
1585 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
1587 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
1588 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1592 /* Actual execution of instructions begins here. */
1593 /* If the condition codes don't match, stop here. */
1598 if (state
->is_XScale
)
1600 if (BIT (20) == 0 && BITS (25, 27) == 0)
1602 if (BITS (4, 7) == 0xD)
1604 /* XScale Load Consecutive insn. */
1605 ARMword temp1
= GetLS7RHS (state
, instr
);
1606 ARMword temp2
= BIT (23) ? LHS
+ temp1
: LHS
- temp1
;
1607 ARMword addr
= BIT (24) ? temp2
: LHS
;
1610 ARMul_UndefInstr (state
, instr
);
1612 /* Alignment violation. */
1613 ARMul_Abort (state
, ARMul_DataAbortV
);
1616 int wb
= BIT (21) || (! BIT (24));
1618 state
->Reg
[BITS (12, 15)] =
1619 ARMul_LoadWordN (state
, addr
);
1620 state
->Reg
[BITS (12, 15) + 1] =
1621 ARMul_LoadWordN (state
, addr
+ 4);
1628 else if (BITS (4, 7) == 0xF)
1630 /* XScale Store Consecutive insn. */
1631 ARMword temp1
= GetLS7RHS (state
, instr
);
1632 ARMword temp2
= BIT (23) ? LHS
+ temp1
: LHS
- temp1
;
1633 ARMword addr
= BIT (24) ? temp2
: LHS
;
1636 ARMul_UndefInstr (state
, instr
);
1638 /* Alignment violation. */
1639 ARMul_Abort (state
, ARMul_DataAbortV
);
1642 ARMul_StoreWordN (state
, addr
,
1643 state
->Reg
[BITS (12, 15)]);
1644 ARMul_StoreWordN (state
, addr
+ 4,
1645 state
->Reg
[BITS (12, 15) + 1]);
1647 if (BIT (21)|| ! BIT (24))
1655 if (ARMul_HandleIwmmxt (state
, instr
))
1659 switch ((int) BITS (20, 27))
1661 /* Data Processing Register RHS Instructions. */
1663 case 0x00: /* AND reg and MUL */
1665 if (BITS (4, 11) == 0xB)
1667 /* STRH register offset, no write-back, down, post indexed. */
1671 if (BITS (4, 7) == 0xD)
1673 Handle_Load_Double (state
, instr
);
1676 if (BITS (4, 7) == 0xF)
1678 Handle_Store_Double (state
, instr
);
1682 if (BITS (4, 7) == 9)
1685 rhs
= state
->Reg
[MULRHSReg
];
1686 if (MULLHSReg
== MULDESTReg
)
1689 state
->Reg
[MULDESTReg
] = 0;
1691 else if (MULDESTReg
!= 15)
1692 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
1696 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1697 if (rhs
& (1L << dest
))
1700 /* Mult takes this many/2 I cycles. */
1701 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1712 case 0x01: /* ANDS reg and MULS */
1714 if ((BITS (4, 11) & 0xF9) == 0x9)
1715 /* LDR register offset, no write-back, down, post indexed. */
1717 /* Fall through to rest of decoding. */
1719 if (BITS (4, 7) == 9)
1722 rhs
= state
->Reg
[MULRHSReg
];
1724 if (MULLHSReg
== MULDESTReg
)
1727 state
->Reg
[MULDESTReg
] = 0;
1731 else if (MULDESTReg
!= 15)
1733 dest
= state
->Reg
[MULLHSReg
] * rhs
;
1734 ARMul_NegZero (state
, dest
);
1735 state
->Reg
[MULDESTReg
] = dest
;
1740 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1741 if (rhs
& (1L << dest
))
1744 /* Mult takes this many/2 I cycles. */
1745 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1756 case 0x02: /* EOR reg and MLA */
1758 if (BITS (4, 11) == 0xB)
1760 /* STRH register offset, write-back, down, post indexed. */
1765 if (BITS (4, 7) == 9)
1767 rhs
= state
->Reg
[MULRHSReg
];
1768 if (MULLHSReg
== MULDESTReg
)
1771 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
1773 else if (MULDESTReg
!= 15)
1774 state
->Reg
[MULDESTReg
] =
1775 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1779 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1780 if (rhs
& (1L << dest
))
1783 /* Mult takes this many/2 I cycles. */
1784 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1794 case 0x03: /* EORS reg and MLAS */
1796 if ((BITS (4, 11) & 0xF9) == 0x9)
1797 /* LDR register offset, write-back, down, post-indexed. */
1799 /* Fall through to rest of the decoding. */
1801 if (BITS (4, 7) == 9)
1804 rhs
= state
->Reg
[MULRHSReg
];
1806 if (MULLHSReg
== MULDESTReg
)
1809 dest
= state
->Reg
[MULACCReg
];
1810 ARMul_NegZero (state
, dest
);
1811 state
->Reg
[MULDESTReg
] = dest
;
1813 else if (MULDESTReg
!= 15)
1816 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1817 ARMul_NegZero (state
, dest
);
1818 state
->Reg
[MULDESTReg
] = dest
;
1823 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1824 if (rhs
& (1L << dest
))
1827 /* Mult takes this many/2 I cycles. */
1828 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1839 case 0x04: /* SUB reg */
1841 if (BITS (4, 7) == 0xB)
1843 /* STRH immediate offset, no write-back, down, post indexed. */
1847 if (BITS (4, 7) == 0xD)
1849 Handle_Load_Double (state
, instr
);
1852 if (BITS (4, 7) == 0xF)
1854 Handle_Store_Double (state
, instr
);
1863 case 0x05: /* SUBS reg */
1865 if ((BITS (4, 7) & 0x9) == 0x9)
1866 /* LDR immediate offset, no write-back, down, post indexed. */
1868 /* Fall through to the rest of the instruction decoding. */
1874 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1876 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1877 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1887 case 0x06: /* RSB reg */
1889 if (BITS (4, 7) == 0xB)
1891 /* STRH immediate offset, write-back, down, post indexed. */
1901 case 0x07: /* RSBS reg */
1903 if ((BITS (4, 7) & 0x9) == 0x9)
1904 /* LDR immediate offset, write-back, down, post indexed. */
1906 /* Fall through to remainder of instruction decoding. */
1912 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1914 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1915 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1925 case 0x08: /* ADD reg */
1927 if (BITS (4, 11) == 0xB)
1929 /* STRH register offset, no write-back, up, post indexed. */
1933 if (BITS (4, 7) == 0xD)
1935 Handle_Load_Double (state
, instr
);
1938 if (BITS (4, 7) == 0xF)
1940 Handle_Store_Double (state
, instr
);
1945 if (BITS (4, 7) == 0x9)
1949 ARMul_Icycles (state
,
1950 Multiply64 (state
, instr
, LUNSIGNED
,
1960 case 0x09: /* ADDS reg */
1962 if ((BITS (4, 11) & 0xF9) == 0x9)
1963 /* LDR register offset, no write-back, up, post indexed. */
1965 /* Fall through to remaining instruction decoding. */
1968 if (BITS (4, 7) == 0x9)
1972 ARMul_Icycles (state
,
1973 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
1981 ASSIGNZ (dest
== 0);
1982 if ((lhs
| rhs
) >> 30)
1984 /* Possible C,V,N to set. */
1985 ASSIGNN (NEG (dest
));
1986 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1987 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1998 case 0x0a: /* ADC reg */
2000 if (BITS (4, 11) == 0xB)
2002 /* STRH register offset, write-back, up, post-indexed. */
2006 if (BITS (4, 7) == 0x9)
2010 ARMul_Icycles (state
,
2011 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
2017 dest
= LHS
+ rhs
+ CFLAG
;
2021 case 0x0b: /* ADCS reg */
2023 if ((BITS (4, 11) & 0xF9) == 0x9)
2024 /* LDR register offset, write-back, up, post indexed. */
2026 /* Fall through to remaining instruction decoding. */
2027 if (BITS (4, 7) == 0x9)
2031 ARMul_Icycles (state
,
2032 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
2039 dest
= lhs
+ rhs
+ CFLAG
;
2040 ASSIGNZ (dest
== 0);
2041 if ((lhs
| rhs
) >> 30)
2043 /* Possible C,V,N to set. */
2044 ASSIGNN (NEG (dest
));
2045 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2046 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2057 case 0x0c: /* SBC reg */
2059 if (BITS (4, 7) == 0xB)
2061 /* STRH immediate offset, no write-back, up post indexed. */
2065 if (BITS (4, 7) == 0xD)
2067 Handle_Load_Double (state
, instr
);
2070 if (BITS (4, 7) == 0xF)
2072 Handle_Store_Double (state
, instr
);
2075 if (BITS (4, 7) == 0x9)
2079 ARMul_Icycles (state
,
2080 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
2086 dest
= LHS
- rhs
- !CFLAG
;
2090 case 0x0d: /* SBCS reg */
2092 if ((BITS (4, 7) & 0x9) == 0x9)
2093 /* LDR immediate offset, no write-back, up, post indexed. */
2096 if (BITS (4, 7) == 0x9)
2100 ARMul_Icycles (state
,
2101 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
2108 dest
= lhs
- rhs
- !CFLAG
;
2109 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2111 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2112 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2122 case 0x0e: /* RSC reg */
2124 if (BITS (4, 7) == 0xB)
2126 /* STRH immediate offset, write-back, up, post indexed. */
2131 if (BITS (4, 7) == 0x9)
2135 ARMul_Icycles (state
,
2136 MultiplyAdd64 (state
, instr
, LSIGNED
,
2142 dest
= rhs
- LHS
- !CFLAG
;
2146 case 0x0f: /* RSCS reg */
2148 if ((BITS (4, 7) & 0x9) == 0x9)
2149 /* LDR immediate offset, write-back, up, post indexed. */
2151 /* Fall through to remaining instruction decoding. */
2153 if (BITS (4, 7) == 0x9)
2157 ARMul_Icycles (state
,
2158 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
2165 dest
= rhs
- lhs
- !CFLAG
;
2167 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2169 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2170 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2180 case 0x10: /* TST reg and MRS CPSR and SWP word. */
2183 if (BIT (4) == 0 && BIT (7) == 1)
2185 /* ElSegundo SMLAxy insn. */
2186 ARMword op1
= state
->Reg
[BITS (0, 3)];
2187 ARMword op2
= state
->Reg
[BITS (8, 11)];
2188 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2202 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
2204 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
2208 if (BITS (4, 11) == 5)
2210 /* ElSegundo QADD insn. */
2211 ARMword op1
= state
->Reg
[BITS (0, 3)];
2212 ARMword op2
= state
->Reg
[BITS (16, 19)];
2213 ARMword result
= op1
+ op2
;
2214 if (AddOverflow (op1
, op2
, result
))
2216 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2219 state
->Reg
[BITS (12, 15)] = result
;
2224 if (BITS (4, 11) == 0xB)
2226 /* STRH register offset, no write-back, down, pre indexed. */
2230 if (BITS (4, 7) == 0xD)
2232 Handle_Load_Double (state
, instr
);
2235 if (BITS (4, 7) == 0xF)
2237 Handle_Store_Double (state
, instr
);
2241 if (BITS (4, 11) == 9)
2248 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2250 INTERNALABORT (temp
);
2251 (void) ARMul_LoadWordN (state
, temp
);
2252 (void) ARMul_LoadWordN (state
, temp
);
2256 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
2258 DEST
= ARMul_Align (state
, temp
, dest
);
2261 if (state
->abortSig
|| state
->Aborted
)
2264 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2267 DEST
= ECC
| EINT
| EMODE
;
2273 && handle_v6_insn (state
, instr
))
2280 case 0x11: /* TSTP reg */
2282 if ((BITS (4, 11) & 0xF9) == 0x9)
2283 /* LDR register offset, no write-back, down, pre indexed. */
2285 /* Continue with remaining instruction decode. */
2291 state
->Cpsr
= GETSPSR (state
->Bank
);
2292 ARMul_CPSRAltered (state
);
2304 ARMul_NegZero (state
, dest
);
2308 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
2311 if (BITS (4, 7) == 3)
2315 dest
= (pc
+ 2) | 1;
2319 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2320 state
->Reg
[14] = dest
;
2327 if (BIT (4) == 0 && BIT (7) == 1
2328 && (BIT (5) == 0 || BITS (12, 15) == 0))
2330 /* ElSegundo SMLAWy/SMULWy insn. */
2331 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2332 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2337 if (op1
& 0x80000000)
2342 result
= (op1
* op2
) >> 16;
2346 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2348 if (AddOverflow (result
, Rn
, result
+ Rn
))
2352 state
->Reg
[BITS (16, 19)] = result
;
2356 if (BITS (4, 11) == 5)
2358 /* ElSegundo QSUB insn. */
2359 ARMword op1
= state
->Reg
[BITS (0, 3)];
2360 ARMword op2
= state
->Reg
[BITS (16, 19)];
2361 ARMword result
= op1
- op2
;
2363 if (SubOverflow (op1
, op2
, result
))
2365 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2369 state
->Reg
[BITS (12, 15)] = result
;
2374 if (BITS (4, 11) == 0xB)
2376 /* STRH register offset, write-back, down, pre indexed. */
2380 if (BITS (4, 27) == 0x12FFF1)
2383 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2386 if (BITS (4, 7) == 0xD)
2388 Handle_Load_Double (state
, instr
);
2391 if (BITS (4, 7) == 0xF)
2393 Handle_Store_Double (state
, instr
);
2399 if (BITS (4, 7) == 0x7)
2401 extern int SWI_vector_installed
;
2403 /* Hardware is allowed to optionally override this
2404 instruction and treat it as a breakpoint. Since
2405 this is a simulator not hardware, we take the position
2406 that if a SWI vector was not installed, then an Abort
2407 vector was probably not installed either, and so
2408 normally this instruction would be ignored, even if an
2409 Abort is generated. This is a bad thing, since GDB
2410 uses this instruction for its breakpoints (at least in
2411 Thumb mode it does). So intercept the instruction here
2412 and generate a breakpoint SWI instead. */
2413 if (! SWI_vector_installed
)
2414 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
2417 /* BKPT - normally this will cause an abort, but on the
2418 XScale we must check the DCSR. */
2419 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
2420 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
2424 /* Force the next instruction to be refetched. */
2425 state
->NextInstr
= RESUME
;
2431 /* MSR reg to CPSR. */
2435 /* Don't allow TBIT to be set by MSR. */
2438 ARMul_FixCPSR (state
, instr
, temp
);
2441 else if (state
->is_v6
2442 && handle_v6_insn (state
, instr
))
2450 case 0x13: /* TEQP reg */
2452 if ((BITS (4, 11) & 0xF9) == 0x9)
2453 /* LDR register offset, write-back, down, pre indexed. */
2455 /* Continue with remaining instruction decode. */
2461 state
->Cpsr
= GETSPSR (state
->Bank
);
2462 ARMul_CPSRAltered (state
);
2474 ARMul_NegZero (state
, dest
);
2478 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
2481 if (BIT (4) == 0 && BIT (7) == 1)
2483 /* ElSegundo SMLALxy insn. */
2484 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2485 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2499 result
= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
2500 result
|= state
->Reg
[BITS (12, 15)];
2501 result
+= op1
* op2
;
2502 state
->Reg
[BITS (12, 15)] = result
;
2503 state
->Reg
[BITS (16, 19)] = result
>> 32;
2507 if (BITS (4, 11) == 5)
2509 /* ElSegundo QDADD insn. */
2510 ARMword op1
= state
->Reg
[BITS (0, 3)];
2511 ARMword op2
= state
->Reg
[BITS (16, 19)];
2512 ARMword op2d
= op2
+ op2
;
2515 if (AddOverflow (op2
, op2
, op2d
))
2518 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2521 result
= op1
+ op2d
;
2522 if (AddOverflow (op1
, op2d
, result
))
2525 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2528 state
->Reg
[BITS (12, 15)] = result
;
2533 if (BITS (4, 7) == 0xB)
2535 /* STRH immediate offset, no write-back, down, pre indexed. */
2539 if (BITS (4, 7) == 0xD)
2541 Handle_Load_Double (state
, instr
);
2544 if (BITS (4, 7) == 0xF)
2546 Handle_Store_Double (state
, instr
);
2550 if (BITS (4, 11) == 9)
2557 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2559 INTERNALABORT (temp
);
2560 (void) ARMul_LoadByte (state
, temp
);
2561 (void) ARMul_LoadByte (state
, temp
);
2565 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
2566 if (state
->abortSig
|| state
->Aborted
)
2569 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2573 DEST
= GETSPSR (state
->Bank
);
2576 else if (state
->is_v6
2577 && handle_v6_insn (state
, instr
))
2585 case 0x15: /* CMPP reg. */
2587 if ((BITS (4, 7) & 0x9) == 0x9)
2588 /* LDR immediate offset, no write-back, down, pre indexed. */
2590 /* Continue with remaining instruction decode. */
2596 state
->Cpsr
= GETSPSR (state
->Bank
);
2597 ARMul_CPSRAltered (state
);
2610 ARMul_NegZero (state
, dest
);
2611 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2613 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2614 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2624 case 0x16: /* CMN reg and MSR reg to SPSR */
2627 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
2629 /* ElSegundo SMULxy insn. */
2630 ARMword op1
= state
->Reg
[BITS (0, 3)];
2631 ARMword op2
= state
->Reg
[BITS (8, 11)];
2644 state
->Reg
[BITS (16, 19)] = op1
* op2
;
2648 if (BITS (4, 11) == 5)
2650 /* ElSegundo QDSUB insn. */
2651 ARMword op1
= state
->Reg
[BITS (0, 3)];
2652 ARMword op2
= state
->Reg
[BITS (16, 19)];
2653 ARMword op2d
= op2
+ op2
;
2656 if (AddOverflow (op2
, op2
, op2d
))
2659 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2662 result
= op1
- op2d
;
2663 if (SubOverflow (op1
, op2d
, result
))
2666 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2669 state
->Reg
[BITS (12, 15)] = result
;
2676 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
2678 /* ARM5 CLZ insn. */
2679 ARMword op1
= state
->Reg
[BITS (0, 3)];
2683 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
2686 state
->Reg
[BITS (12, 15)] = result
;
2691 if (BITS (4, 7) == 0xB)
2693 /* STRH immediate offset, write-back, down, pre indexed. */
2697 if (BITS (4, 7) == 0xD)
2699 Handle_Load_Double (state
, instr
);
2702 if (BITS (4, 7) == 0xF)
2704 Handle_Store_Double (state
, instr
);
2712 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
2718 && handle_v6_insn (state
, instr
))
2725 case 0x17: /* CMNP reg */
2727 if ((BITS (4, 7) & 0x9) == 0x9)
2728 /* LDR immediate offset, write-back, down, pre indexed. */
2730 /* Continue with remaining instruction decoding. */
2735 state
->Cpsr
= GETSPSR (state
->Bank
);
2736 ARMul_CPSRAltered (state
);
2750 ASSIGNZ (dest
== 0);
2751 if ((lhs
| rhs
) >> 30)
2753 /* Possible C,V,N to set. */
2754 ASSIGNN (NEG (dest
));
2755 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2756 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2767 case 0x18: /* ORR reg */
2769 if (BITS (4, 11) == 0xB)
2771 /* STRH register offset, no write-back, up, pre indexed. */
2775 if (BITS (4, 7) == 0xD)
2777 Handle_Load_Double (state
, instr
);
2780 if (BITS (4, 7) == 0xF)
2782 Handle_Store_Double (state
, instr
);
2791 case 0x19: /* ORRS reg */
2793 if ((BITS (4, 11) & 0xF9) == 0x9)
2794 /* LDR register offset, no write-back, up, pre indexed. */
2796 /* Continue with remaining instruction decoding. */
2803 case 0x1a: /* MOV reg */
2805 if (BITS (4, 11) == 0xB)
2807 /* STRH register offset, write-back, up, pre indexed. */
2811 if (BITS (4, 7) == 0xD)
2813 Handle_Load_Double (state
, instr
);
2816 if (BITS (4, 7) == 0xF)
2818 Handle_Store_Double (state
, instr
);
2826 case 0x1b: /* MOVS reg */
2828 if ((BITS (4, 11) & 0xF9) == 0x9)
2829 /* LDR register offset, write-back, up, pre indexed. */
2831 /* Continue with remaining instruction decoding. */
2837 case 0x1c: /* BIC reg */
2839 if (BITS (4, 7) == 0xB)
2841 /* STRH immediate offset, no write-back, up, pre indexed. */
2845 if (BITS (4, 7) == 0xD)
2847 Handle_Load_Double (state
, instr
);
2850 else if (BITS (4, 7) == 0xF)
2852 Handle_Store_Double (state
, instr
);
2861 case 0x1d: /* BICS reg */
2863 if ((BITS (4, 7) & 0x9) == 0x9)
2864 /* LDR immediate offset, no write-back, up, pre indexed. */
2866 /* Continue with instruction decoding. */
2873 case 0x1e: /* MVN reg */
2875 if (BITS (4, 7) == 0xB)
2877 /* STRH immediate offset, write-back, up, pre indexed. */
2881 if (BITS (4, 7) == 0xD)
2883 Handle_Load_Double (state
, instr
);
2886 if (BITS (4, 7) == 0xF)
2888 Handle_Store_Double (state
, instr
);
2896 case 0x1f: /* MVNS reg */
2898 if ((BITS (4, 7) & 0x9) == 0x9)
2899 /* LDR immediate offset, write-back, up, pre indexed. */
2901 /* Continue instruction decoding. */
2908 /* Data Processing Immediate RHS Instructions. */
2910 case 0x20: /* AND immed */
2911 dest
= LHS
& DPImmRHS
;
2915 case 0x21: /* ANDS immed */
2921 case 0x22: /* EOR immed */
2922 dest
= LHS
^ DPImmRHS
;
2926 case 0x23: /* EORS immed */
2932 case 0x24: /* SUB immed */
2933 dest
= LHS
- DPImmRHS
;
2937 case 0x25: /* SUBS immed */
2942 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2944 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2945 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2955 case 0x26: /* RSB immed */
2956 dest
= DPImmRHS
- LHS
;
2960 case 0x27: /* RSBS immed */
2965 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2967 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2968 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2978 case 0x28: /* ADD immed */
2979 dest
= LHS
+ DPImmRHS
;
2983 case 0x29: /* ADDS immed */
2987 ASSIGNZ (dest
== 0);
2989 if ((lhs
| rhs
) >> 30)
2991 /* Possible C,V,N to set. */
2992 ASSIGNN (NEG (dest
));
2993 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2994 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3005 case 0x2a: /* ADC immed */
3006 dest
= LHS
+ DPImmRHS
+ CFLAG
;
3010 case 0x2b: /* ADCS immed */
3013 dest
= lhs
+ rhs
+ CFLAG
;
3014 ASSIGNZ (dest
== 0);
3015 if ((lhs
| rhs
) >> 30)
3017 /* Possible C,V,N to set. */
3018 ASSIGNN (NEG (dest
));
3019 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
3020 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3031 case 0x2c: /* SBC immed */
3032 dest
= LHS
- DPImmRHS
- !CFLAG
;
3036 case 0x2d: /* SBCS immed */
3039 dest
= lhs
- rhs
- !CFLAG
;
3040 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
3042 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
3043 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
3053 case 0x2e: /* RSC immed */
3054 dest
= DPImmRHS
- LHS
- !CFLAG
;
3058 case 0x2f: /* RSCS immed */
3061 dest
= rhs
- lhs
- !CFLAG
;
3062 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
3064 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
3065 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
3075 case 0x30: /* MOVW immed */
3078 && handle_v6_insn (state
, instr
))
3081 dest
= BITS (0, 11);
3082 dest
|= (BITS (16, 19) << 12);
3086 case 0x31: /* TSTP immed */
3091 state
->Cpsr
= GETSPSR (state
->Bank
);
3092 ARMul_CPSRAltered (state
);
3094 temp
= LHS
& DPImmRHS
;
3103 ARMul_NegZero (state
, dest
);
3107 case 0x32: /* TEQ immed and MSR immed to CPSR */
3109 /* MSR immed to CPSR. */
3110 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
3112 else if (state
->is_v6
3113 && handle_v6_insn (state
, instr
))
3120 case 0x33: /* TEQP immed */
3125 state
->Cpsr
= GETSPSR (state
->Bank
);
3126 ARMul_CPSRAltered (state
);
3128 temp
= LHS
^ DPImmRHS
;
3134 DPSImmRHS
; /* TEQ immed */
3136 ARMul_NegZero (state
, dest
);
3140 case 0x34: /* MOVT immed */
3143 && handle_v6_insn (state
, instr
))
3147 dest
= BITS (0, 11);
3148 dest
|= (BITS (16, 19) << 12);
3149 DEST
|= (dest
<< 16);
3152 case 0x35: /* CMPP immed */
3157 state
->Cpsr
= GETSPSR (state
->Bank
);
3158 ARMul_CPSRAltered (state
);
3160 temp
= LHS
- DPImmRHS
;
3171 ARMul_NegZero (state
, dest
);
3173 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
3175 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
3176 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
3186 case 0x36: /* CMN immed and MSR immed to SPSR */
3188 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
3190 else if (state
->is_v6
3191 && handle_v6_insn (state
, instr
))
3198 case 0x37: /* CMNP immed. */
3203 state
->Cpsr
= GETSPSR (state
->Bank
);
3204 ARMul_CPSRAltered (state
);
3206 temp
= LHS
+ DPImmRHS
;
3217 ASSIGNZ (dest
== 0);
3218 if ((lhs
| rhs
) >> 30)
3220 /* Possible C,V,N to set. */
3221 ASSIGNN (NEG (dest
));
3222 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
3223 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3234 case 0x38: /* ORR immed. */
3235 dest
= LHS
| DPImmRHS
;
3239 case 0x39: /* ORRS immed. */
3245 case 0x3a: /* MOV immed. */
3250 case 0x3b: /* MOVS immed. */
3255 case 0x3c: /* BIC immed. */
3256 dest
= LHS
& ~DPImmRHS
;
3260 case 0x3d: /* BICS immed. */
3266 case 0x3e: /* MVN immed. */
3271 case 0x3f: /* MVNS immed. */
3277 /* Single Data Transfer Immediate RHS Instructions. */
3279 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
3281 if (StoreWord (state
, instr
, lhs
))
3282 LSBase
= lhs
- LSImmRHS
;
3285 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
3287 if (LoadWord (state
, instr
, lhs
))
3288 LSBase
= lhs
- LSImmRHS
;
3291 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
3292 UNDEF_LSRBaseEQDestWb
;
3295 temp
= lhs
- LSImmRHS
;
3296 state
->NtransSig
= LOW
;
3297 if (StoreWord (state
, instr
, lhs
))
3299 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3302 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
3303 UNDEF_LSRBaseEQDestWb
;
3306 state
->NtransSig
= LOW
;
3307 if (LoadWord (state
, instr
, lhs
))
3308 LSBase
= lhs
- LSImmRHS
;
3309 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3312 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
3314 if (StoreByte (state
, instr
, lhs
))
3315 LSBase
= lhs
- LSImmRHS
;
3318 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
3320 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3321 LSBase
= lhs
- LSImmRHS
;
3324 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
3325 UNDEF_LSRBaseEQDestWb
;
3328 state
->NtransSig
= LOW
;
3329 if (StoreByte (state
, instr
, lhs
))
3330 LSBase
= lhs
- LSImmRHS
;
3331 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3334 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
3335 UNDEF_LSRBaseEQDestWb
;
3338 state
->NtransSig
= LOW
;
3339 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3340 LSBase
= lhs
- LSImmRHS
;
3341 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3344 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
3346 if (StoreWord (state
, instr
, lhs
))
3347 LSBase
= lhs
+ LSImmRHS
;
3350 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
3352 if (LoadWord (state
, instr
, lhs
))
3353 LSBase
= lhs
+ LSImmRHS
;
3356 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
3357 UNDEF_LSRBaseEQDestWb
;
3360 state
->NtransSig
= LOW
;
3361 if (StoreWord (state
, instr
, lhs
))
3362 LSBase
= lhs
+ LSImmRHS
;
3363 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3366 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
3367 UNDEF_LSRBaseEQDestWb
;
3370 state
->NtransSig
= LOW
;
3371 if (LoadWord (state
, instr
, lhs
))
3372 LSBase
= lhs
+ LSImmRHS
;
3373 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3376 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
3378 if (StoreByte (state
, instr
, lhs
))
3379 LSBase
= lhs
+ LSImmRHS
;
3382 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
3384 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3385 LSBase
= lhs
+ LSImmRHS
;
3388 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
3389 UNDEF_LSRBaseEQDestWb
;
3392 state
->NtransSig
= LOW
;
3393 if (StoreByte (state
, instr
, lhs
))
3394 LSBase
= lhs
+ LSImmRHS
;
3395 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3398 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
3399 UNDEF_LSRBaseEQDestWb
;
3402 state
->NtransSig
= LOW
;
3403 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3404 LSBase
= lhs
+ LSImmRHS
;
3405 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3409 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
3410 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
3413 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
3414 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
3417 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
3418 UNDEF_LSRBaseEQDestWb
;
3420 temp
= LHS
- LSImmRHS
;
3421 if (StoreWord (state
, instr
, temp
))
3425 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
3426 UNDEF_LSRBaseEQDestWb
;
3428 temp
= LHS
- LSImmRHS
;
3429 if (LoadWord (state
, instr
, temp
))
3433 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
3434 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
3437 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
3438 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
3441 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
3442 UNDEF_LSRBaseEQDestWb
;
3444 temp
= LHS
- LSImmRHS
;
3445 if (StoreByte (state
, instr
, temp
))
3449 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
3450 UNDEF_LSRBaseEQDestWb
;
3452 temp
= LHS
- LSImmRHS
;
3453 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3457 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
3458 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
3461 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
3462 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
3465 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
3466 UNDEF_LSRBaseEQDestWb
;
3468 temp
= LHS
+ LSImmRHS
;
3469 if (StoreWord (state
, instr
, temp
))
3473 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
3474 UNDEF_LSRBaseEQDestWb
;
3476 temp
= LHS
+ LSImmRHS
;
3477 if (LoadWord (state
, instr
, temp
))
3481 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
3482 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
3485 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
3486 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
3489 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
3490 UNDEF_LSRBaseEQDestWb
;
3492 temp
= LHS
+ LSImmRHS
;
3493 if (StoreByte (state
, instr
, temp
))
3497 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
3498 UNDEF_LSRBaseEQDestWb
;
3500 temp
= LHS
+ LSImmRHS
;
3501 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3506 /* Single Data Transfer Register RHS Instructions. */
3508 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
3513 && handle_v6_insn (state
, instr
))
3516 ARMul_UndefInstr (state
, instr
);
3519 UNDEF_LSRBaseEQOffWb
;
3520 UNDEF_LSRBaseEQDestWb
;
3524 if (StoreWord (state
, instr
, lhs
))
3525 LSBase
= lhs
- LSRegRHS
;
3528 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
3533 && handle_v6_insn (state
, instr
))
3536 ARMul_UndefInstr (state
, instr
);
3539 UNDEF_LSRBaseEQOffWb
;
3540 UNDEF_LSRBaseEQDestWb
;
3544 temp
= lhs
- LSRegRHS
;
3545 if (LoadWord (state
, instr
, lhs
))
3549 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
3554 && handle_v6_insn (state
, instr
))
3557 ARMul_UndefInstr (state
, instr
);
3560 UNDEF_LSRBaseEQOffWb
;
3561 UNDEF_LSRBaseEQDestWb
;
3565 state
->NtransSig
= LOW
;
3566 if (StoreWord (state
, instr
, lhs
))
3567 LSBase
= lhs
- LSRegRHS
;
3568 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3571 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
3576 && handle_v6_insn (state
, instr
))
3579 ARMul_UndefInstr (state
, instr
);
3582 UNDEF_LSRBaseEQOffWb
;
3583 UNDEF_LSRBaseEQDestWb
;
3587 temp
= lhs
- LSRegRHS
;
3588 state
->NtransSig
= LOW
;
3589 if (LoadWord (state
, instr
, lhs
))
3591 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3594 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
3599 && handle_v6_insn (state
, instr
))
3602 ARMul_UndefInstr (state
, instr
);
3605 UNDEF_LSRBaseEQOffWb
;
3606 UNDEF_LSRBaseEQDestWb
;
3610 if (StoreByte (state
, instr
, lhs
))
3611 LSBase
= lhs
- LSRegRHS
;
3614 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
3619 && handle_v6_insn (state
, instr
))
3622 ARMul_UndefInstr (state
, instr
);
3625 UNDEF_LSRBaseEQOffWb
;
3626 UNDEF_LSRBaseEQDestWb
;
3630 temp
= lhs
- LSRegRHS
;
3631 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3635 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
3640 && handle_v6_insn (state
, instr
))
3643 ARMul_UndefInstr (state
, instr
);
3646 UNDEF_LSRBaseEQOffWb
;
3647 UNDEF_LSRBaseEQDestWb
;
3651 state
->NtransSig
= LOW
;
3652 if (StoreByte (state
, instr
, lhs
))
3653 LSBase
= lhs
- LSRegRHS
;
3654 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3657 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
3662 && handle_v6_insn (state
, instr
))
3665 ARMul_UndefInstr (state
, instr
);
3668 UNDEF_LSRBaseEQOffWb
;
3669 UNDEF_LSRBaseEQDestWb
;
3673 temp
= lhs
- LSRegRHS
;
3674 state
->NtransSig
= LOW
;
3675 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3677 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3680 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
3685 && handle_v6_insn (state
, instr
))
3688 ARMul_UndefInstr (state
, instr
);
3691 UNDEF_LSRBaseEQOffWb
;
3692 UNDEF_LSRBaseEQDestWb
;
3696 if (StoreWord (state
, instr
, lhs
))
3697 LSBase
= lhs
+ LSRegRHS
;
3700 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
3705 && handle_v6_insn (state
, instr
))
3708 ARMul_UndefInstr (state
, instr
);
3711 UNDEF_LSRBaseEQOffWb
;
3712 UNDEF_LSRBaseEQDestWb
;
3716 temp
= lhs
+ LSRegRHS
;
3717 if (LoadWord (state
, instr
, lhs
))
3721 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
3726 && handle_v6_insn (state
, instr
))
3729 ARMul_UndefInstr (state
, instr
);
3732 UNDEF_LSRBaseEQOffWb
;
3733 UNDEF_LSRBaseEQDestWb
;
3737 state
->NtransSig
= LOW
;
3738 if (StoreWord (state
, instr
, lhs
))
3739 LSBase
= lhs
+ LSRegRHS
;
3740 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3743 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
3748 && handle_v6_insn (state
, instr
))
3751 ARMul_UndefInstr (state
, instr
);
3754 UNDEF_LSRBaseEQOffWb
;
3755 UNDEF_LSRBaseEQDestWb
;
3759 temp
= lhs
+ LSRegRHS
;
3760 state
->NtransSig
= LOW
;
3761 if (LoadWord (state
, instr
, lhs
))
3763 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3766 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
3771 && handle_v6_insn (state
, instr
))
3774 ARMul_UndefInstr (state
, instr
);
3777 UNDEF_LSRBaseEQOffWb
;
3778 UNDEF_LSRBaseEQDestWb
;
3782 if (StoreByte (state
, instr
, lhs
))
3783 LSBase
= lhs
+ LSRegRHS
;
3786 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
3791 && handle_v6_insn (state
, instr
))
3794 ARMul_UndefInstr (state
, instr
);
3797 UNDEF_LSRBaseEQOffWb
;
3798 UNDEF_LSRBaseEQDestWb
;
3802 temp
= lhs
+ LSRegRHS
;
3803 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3807 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3812 && handle_v6_insn (state
, instr
))
3815 ARMul_UndefInstr (state
, instr
);
3818 UNDEF_LSRBaseEQOffWb
;
3819 UNDEF_LSRBaseEQDestWb
;
3823 state
->NtransSig
= LOW
;
3824 if (StoreByte (state
, instr
, lhs
))
3825 LSBase
= lhs
+ LSRegRHS
;
3826 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3829 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3834 && handle_v6_insn (state
, instr
))
3837 ARMul_UndefInstr (state
, instr
);
3840 UNDEF_LSRBaseEQOffWb
;
3841 UNDEF_LSRBaseEQDestWb
;
3845 temp
= lhs
+ LSRegRHS
;
3846 state
->NtransSig
= LOW
;
3847 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3849 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3853 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3858 && handle_v6_insn (state
, instr
))
3861 ARMul_UndefInstr (state
, instr
);
3864 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
3867 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3872 && handle_v6_insn (state
, instr
))
3875 ARMul_UndefInstr (state
, instr
);
3878 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
3881 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3886 && handle_v6_insn (state
, instr
))
3889 ARMul_UndefInstr (state
, instr
);
3892 UNDEF_LSRBaseEQOffWb
;
3893 UNDEF_LSRBaseEQDestWb
;
3896 temp
= LHS
- LSRegRHS
;
3897 if (StoreWord (state
, instr
, temp
))
3901 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3906 && handle_v6_insn (state
, instr
))
3909 ARMul_UndefInstr (state
, instr
);
3912 UNDEF_LSRBaseEQOffWb
;
3913 UNDEF_LSRBaseEQDestWb
;
3916 temp
= LHS
- LSRegRHS
;
3917 if (LoadWord (state
, instr
, temp
))
3921 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3926 && handle_v6_insn (state
, instr
))
3929 ARMul_UndefInstr (state
, instr
);
3932 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
3935 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3940 && handle_v6_insn (state
, instr
))
3943 ARMul_UndefInstr (state
, instr
);
3946 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
3949 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3954 && handle_v6_insn (state
, instr
))
3957 ARMul_UndefInstr (state
, instr
);
3960 UNDEF_LSRBaseEQOffWb
;
3961 UNDEF_LSRBaseEQDestWb
;
3964 temp
= LHS
- LSRegRHS
;
3965 if (StoreByte (state
, instr
, temp
))
3969 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3974 && handle_v6_insn (state
, instr
))
3977 ARMul_UndefInstr (state
, instr
);
3980 UNDEF_LSRBaseEQOffWb
;
3981 UNDEF_LSRBaseEQDestWb
;
3984 temp
= LHS
- LSRegRHS
;
3985 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3989 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3994 && handle_v6_insn (state
, instr
))
3997 ARMul_UndefInstr (state
, instr
);
4000 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
4003 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
4008 && handle_v6_insn (state
, instr
))
4011 ARMul_UndefInstr (state
, instr
);
4014 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
4017 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
4022 && handle_v6_insn (state
, instr
))
4025 ARMul_UndefInstr (state
, instr
);
4028 UNDEF_LSRBaseEQOffWb
;
4029 UNDEF_LSRBaseEQDestWb
;
4032 temp
= LHS
+ LSRegRHS
;
4033 if (StoreWord (state
, instr
, temp
))
4037 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
4042 && handle_v6_insn (state
, instr
))
4045 ARMul_UndefInstr (state
, instr
);
4048 UNDEF_LSRBaseEQOffWb
;
4049 UNDEF_LSRBaseEQDestWb
;
4052 temp
= LHS
+ LSRegRHS
;
4053 if (LoadWord (state
, instr
, temp
))
4057 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
4062 && handle_v6_insn (state
, instr
))
4065 ARMul_UndefInstr (state
, instr
);
4068 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
4071 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
4076 && handle_v6_insn (state
, instr
))
4079 ARMul_UndefInstr (state
, instr
);
4082 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
4085 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
4090 && handle_v6_insn (state
, instr
))
4093 ARMul_UndefInstr (state
, instr
);
4096 UNDEF_LSRBaseEQOffWb
;
4097 UNDEF_LSRBaseEQDestWb
;
4100 temp
= LHS
+ LSRegRHS
;
4101 if (StoreByte (state
, instr
, temp
))
4105 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
4108 /* Check for the special breakpoint opcode.
4109 This value should correspond to the value defined
4110 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
4111 if (BITS (0, 19) == 0xfdefe)
4113 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
4114 ARMul_Abort (state
, ARMul_SWIV
);
4117 else if (state
->is_v6
4118 && handle_v6_insn (state
, instr
))
4122 ARMul_UndefInstr (state
, instr
);
4125 UNDEF_LSRBaseEQOffWb
;
4126 UNDEF_LSRBaseEQDestWb
;
4129 temp
= LHS
+ LSRegRHS
;
4130 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
4135 /* Multiple Data Transfer Instructions. */
4137 case 0x80: /* Store, No WriteBack, Post Dec. */
4138 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4141 case 0x81: /* Load, No WriteBack, Post Dec. */
4142 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4145 case 0x82: /* Store, WriteBack, Post Dec. */
4146 temp
= LSBase
- LSMNumRegs
;
4147 STOREMULT (instr
, temp
+ 4L, temp
);
4150 case 0x83: /* Load, WriteBack, Post Dec. */
4151 temp
= LSBase
- LSMNumRegs
;
4152 LOADMULT (instr
, temp
+ 4L, temp
);
4155 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
4156 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4159 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
4160 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4163 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
4164 temp
= LSBase
- LSMNumRegs
;
4165 STORESMULT (instr
, temp
+ 4L, temp
);
4168 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
4169 temp
= LSBase
- LSMNumRegs
;
4170 LOADSMULT (instr
, temp
+ 4L, temp
);
4173 case 0x88: /* Store, No WriteBack, Post Inc. */
4174 STOREMULT (instr
, LSBase
, 0L);
4177 case 0x89: /* Load, No WriteBack, Post Inc. */
4178 LOADMULT (instr
, LSBase
, 0L);
4181 case 0x8a: /* Store, WriteBack, Post Inc. */
4183 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
4186 case 0x8b: /* Load, WriteBack, Post Inc. */
4188 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
4191 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
4192 STORESMULT (instr
, LSBase
, 0L);
4195 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
4196 LOADSMULT (instr
, LSBase
, 0L);
4199 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
4201 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
4204 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
4206 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
4209 case 0x90: /* Store, No WriteBack, Pre Dec. */
4210 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4213 case 0x91: /* Load, No WriteBack, Pre Dec. */
4214 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4217 case 0x92: /* Store, WriteBack, Pre Dec. */
4218 temp
= LSBase
- LSMNumRegs
;
4219 STOREMULT (instr
, temp
, temp
);
4222 case 0x93: /* Load, WriteBack, Pre Dec. */
4223 temp
= LSBase
- LSMNumRegs
;
4224 LOADMULT (instr
, temp
, temp
);
4227 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
4228 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4231 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
4232 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4235 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
4236 temp
= LSBase
- LSMNumRegs
;
4237 STORESMULT (instr
, temp
, temp
);
4240 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
4241 temp
= LSBase
- LSMNumRegs
;
4242 LOADSMULT (instr
, temp
, temp
);
4245 case 0x98: /* Store, No WriteBack, Pre Inc. */
4246 STOREMULT (instr
, LSBase
+ 4L, 0L);
4249 case 0x99: /* Load, No WriteBack, Pre Inc. */
4250 LOADMULT (instr
, LSBase
+ 4L, 0L);
4253 case 0x9a: /* Store, WriteBack, Pre Inc. */
4255 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4258 case 0x9b: /* Load, WriteBack, Pre Inc. */
4260 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4263 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
4264 STORESMULT (instr
, LSBase
+ 4L, 0L);
4267 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
4268 LOADSMULT (instr
, LSBase
+ 4L, 0L);
4271 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
4273 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4276 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
4278 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4282 /* Branch forward. */
4291 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4296 /* Branch backward. */
4305 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4309 /* Branch and Link forward. */
4318 /* Put PC into Link. */
4320 state
->Reg
[14] = pc
+ 4;
4322 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4324 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4327 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4330 /* Branch and Link backward. */
4339 /* Put PC into Link. */
4341 state
->Reg
[14] = pc
+ 4;
4343 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4345 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4348 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4351 /* Co-Processor Data Transfers. */
4355 if (CPNum
== 10 || CPNum
== 11)
4356 handle_VFP_move (state
, instr
);
4357 /* Reading from R15 is UNPREDICTABLE. */
4358 else if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
4359 ARMul_UndefInstr (state
, instr
);
4360 /* Is access to coprocessor 0 allowed ? */
4361 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4362 ARMul_UndefInstr (state
, instr
);
4363 /* Special treatment for XScale coprocessors. */
4364 else if (state
->is_XScale
)
4366 /* Only opcode 0 is supported. */
4367 if (BITS (4, 7) != 0x00)
4368 ARMul_UndefInstr (state
, instr
);
4369 /* Only coporcessor 0 is supported. */
4370 else if (CPNum
!= 0x00)
4371 ARMul_UndefInstr (state
, instr
);
4372 /* Only accumulator 0 is supported. */
4373 else if (BITS (0, 3) != 0x00)
4374 ARMul_UndefInstr (state
, instr
);
4377 /* XScale MAR insn. Move two registers into accumulator. */
4378 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
4379 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
4383 /* FIXME: Not sure what to do for other v5 processors. */
4384 ARMul_UndefInstr (state
, instr
);
4387 ATTRIBUTE_FALLTHROUGH
;
4389 case 0xc0: /* Store , No WriteBack , Post Dec. */
4390 ARMul_STC (state
, instr
, LHS
);
4396 if (CPNum
== 10 || CPNum
== 11)
4397 handle_VFP_move (state
, instr
);
4398 /* Writes to R15 are UNPREDICATABLE. */
4399 else if (DESTReg
== 15 || LHSReg
== 15)
4400 ARMul_UndefInstr (state
, instr
);
4401 /* Is access to the coprocessor allowed ? */
4402 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4403 ARMul_UndefInstr (state
, instr
);
4404 /* Special handling for XScale coprcoessors. */
4405 else if (state
->is_XScale
)
4407 /* Only opcode 0 is supported. */
4408 if (BITS (4, 7) != 0x00)
4409 ARMul_UndefInstr (state
, instr
);
4410 /* Only coprocessor 0 is supported. */
4411 else if (CPNum
!= 0x00)
4412 ARMul_UndefInstr (state
, instr
);
4413 /* Only accumulator 0 is supported. */
4414 else if (BITS (0, 3) != 0x00)
4415 ARMul_UndefInstr (state
, instr
);
4418 /* XScale MRA insn. Move accumulator into two registers. */
4419 ARMword t1
= (state
->Accumulator
>> 32) & 255;
4424 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
4425 state
->Reg
[BITS (16, 19)] = t1
;
4430 /* FIXME: Not sure what to do for other v5 processors. */
4431 ARMul_UndefInstr (state
, instr
);
4434 ATTRIBUTE_FALLTHROUGH
;
4436 case 0xc1: /* Load , No WriteBack , Post Dec. */
4437 ARMul_LDC (state
, instr
, LHS
);
4441 case 0xc6: /* Store , WriteBack , Post Dec. */
4443 state
->Base
= lhs
- LSCOff
;
4444 ARMul_STC (state
, instr
, lhs
);
4448 case 0xc7: /* Load , WriteBack , Post Dec. */
4450 state
->Base
= lhs
- LSCOff
;
4451 ARMul_LDC (state
, instr
, lhs
);
4455 case 0xcc: /* Store , No WriteBack , Post Inc. */
4456 ARMul_STC (state
, instr
, LHS
);
4460 case 0xcd: /* Load , No WriteBack , Post Inc. */
4461 ARMul_LDC (state
, instr
, LHS
);
4465 case 0xce: /* Store , WriteBack , Post Inc. */
4467 state
->Base
= lhs
+ LSCOff
;
4468 ARMul_STC (state
, instr
, LHS
);
4472 case 0xcf: /* Load , WriteBack , Post Inc. */
4474 state
->Base
= lhs
+ LSCOff
;
4475 ARMul_LDC (state
, instr
, LHS
);
4479 case 0xd4: /* Store , No WriteBack , Pre Dec. */
4480 ARMul_STC (state
, instr
, LHS
- LSCOff
);
4484 case 0xd5: /* Load , No WriteBack , Pre Dec. */
4485 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
4489 case 0xd6: /* Store , WriteBack , Pre Dec. */
4492 ARMul_STC (state
, instr
, lhs
);
4496 case 0xd7: /* Load , WriteBack , Pre Dec. */
4499 ARMul_LDC (state
, instr
, lhs
);
4503 case 0xdc: /* Store , No WriteBack , Pre Inc. */
4504 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
4508 case 0xdd: /* Load , No WriteBack , Pre Inc. */
4509 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
4513 case 0xde: /* Store , WriteBack , Pre Inc. */
4516 ARMul_STC (state
, instr
, lhs
);
4520 case 0xdf: /* Load , WriteBack , Pre Inc. */
4523 ARMul_LDC (state
, instr
, lhs
);
4527 /* Co-Processor Register Transfers (MCR) and Data Ops. */
4530 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4532 ARMul_UndefInstr (state
, instr
);
4535 if (state
->is_XScale
)
4536 switch (BITS (18, 19))
4539 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4541 /* XScale MIA instruction. Signed multiplication of
4542 two 32 bit values and addition to 40 bit accumulator. */
4543 ARMsdword Rm
= state
->Reg
[MULLHSReg
];
4544 ARMsdword Rs
= state
->Reg
[MULACCReg
];
4550 state
->Accumulator
+= Rm
* Rs
;
4556 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4558 /* XScale MIAPH instruction. */
4559 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
4560 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
4561 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
4562 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
4577 state
->Accumulator
+= t5
;
4582 state
->Accumulator
+= t5
;
4588 if (BITS (4, 11) == 1)
4590 /* XScale MIAxy instruction. */
4596 t1
= state
->Reg
[MULLHSReg
] >> 16;
4598 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
4601 t2
= state
->Reg
[MULACCReg
] >> 16;
4603 t2
= state
->Reg
[MULACCReg
] & 0xffff;
4613 state
->Accumulator
+= t5
;
4621 ATTRIBUTE_FALLTHROUGH
;
4632 if (CPNum
== 10 || CPNum
== 11)
4633 handle_VFP_move (state
, instr
);
4635 else if (DESTReg
== 15)
4639 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
4641 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
4642 ((state
->Reg
[15] + isize
) & R15PCBITS
));
4646 ARMul_MCR (state
, instr
, DEST
);
4650 ARMul_CDP (state
, instr
);
4654 /* Co-Processor Register Transfers (MRC) and Data Ops. */
4665 if (CPNum
== 10 || CPNum
== 11)
4667 switch (BITS (20, 27))
4670 if (BITS (16, 19) == 0x1
4671 && BITS (0, 11) == 0xA10)
4676 ARMul_SetCPSR (state
, (state
->FPSCR
& 0xF0000000)
4677 | (ARMul_GetCPSR (state
) & 0x0FFFFFFF));
4680 fprintf (stderr
, " VFP: VMRS: set flags to %c%c%c%c\n",
4681 ARMul_GetCPSR (state
) & NBIT
? 'N' : '-',
4682 ARMul_GetCPSR (state
) & ZBIT
? 'Z' : '-',
4683 ARMul_GetCPSR (state
) & CBIT
? 'C' : '-',
4684 ARMul_GetCPSR (state
) & VBIT
? 'V' : '-');
4688 state
->Reg
[DESTReg
] = state
->FPSCR
;
4691 fprintf (stderr
, " VFP: VMRS: r%d = %x\n", DESTReg
, state
->Reg
[DESTReg
]);
4695 fprintf (stderr
, "SIM: VFP: Unimplemented: Compare op\n");
4700 /* VMOV reg <-> single precision. */
4701 if (BITS (0,6) != 0x10 || BITS (8,11) != 0xA)
4702 fprintf (stderr
, "SIM: VFP: Unimplemented: move op\n");
4704 state
->Reg
[BITS (12, 15)] = VFP_uword (BITS (16, 19) << 1 | BIT (7));
4706 VFP_uword (BITS (16, 19) << 1 | BIT (7)) = state
->Reg
[BITS (12, 15)];
4710 fprintf (stderr
, "SIM: VFP: Unimplemented: CDP op\n");
4717 temp
= ARMul_MRC (state
, instr
);
4720 ASSIGNN ((temp
& NBIT
) != 0);
4721 ASSIGNZ ((temp
& ZBIT
) != 0);
4722 ASSIGNC ((temp
& CBIT
) != 0);
4723 ASSIGNV ((temp
& VBIT
) != 0);
4731 ARMul_CDP (state
, instr
);
4735 /* SWI instruction. */
4752 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
4754 /* A prefetch abort. */
4755 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
4756 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
4760 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
4761 ARMul_Abort (state
, ARMul_SWIV
);
4771 if (state
->Emulate
== ONCE
)
4772 state
->Emulate
= STOP
;
4773 /* If we have changed mode, allow the PC to advance before stopping. */
4774 else if (state
->Emulate
== CHANGEMODE
)
4776 else if (state
->Emulate
!= RUN
)
4779 while (!stop_simulator
);
4781 state
->decoded
= decoded
;
4782 state
->loaded
= loaded
;
4788 /* This routine evaluates most Data Processing register RHS's with the S
4789 bit clear. It is intended to be called from the macro DPRegRHS, which
4790 filters the common case of an unshifted register with in line code. */
4793 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
4795 ARMword shamt
, base
;
4800 /* Shift amount in a register. */
4805 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4808 base
= state
->Reg
[base
];
4809 ARMul_Icycles (state
, 1, 0L);
4810 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4811 switch ((int) BITS (5, 6))
4816 else if (shamt
>= 32)
4819 return (base
<< shamt
);
4823 else if (shamt
>= 32)
4826 return (base
>> shamt
);
4830 else if (shamt
>= 32)
4831 return ((ARMword
) ((ARMsword
) base
>> 31L));
4833 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4839 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4844 /* Shift amount is a constant. */
4847 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4850 base
= state
->Reg
[base
];
4851 shamt
= BITS (7, 11);
4852 switch ((int) BITS (5, 6))
4855 return (base
<< shamt
);
4860 return (base
>> shamt
);
4863 return ((ARMword
) ((ARMsword
) base
>> 31L));
4865 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4869 return ((base
>> 1) | (CFLAG
<< 31));
4871 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4878 /* This routine evaluates most Logical Data Processing register RHS's
4879 with the S bit set. It is intended to be called from the macro
4880 DPSRegRHS, which filters the common case of an unshifted register
4881 with in line code. */
4884 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
4886 ARMword shamt
, base
;
4891 /* Shift amount in a register. */
4896 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4899 base
= state
->Reg
[base
];
4900 ARMul_Icycles (state
, 1, 0L);
4901 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4902 switch ((int) BITS (5, 6))
4907 else if (shamt
== 32)
4912 else if (shamt
> 32)
4919 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4920 return (base
<< shamt
);
4925 else if (shamt
== 32)
4927 ASSIGNC (base
>> 31);
4930 else if (shamt
> 32)
4937 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4938 return (base
>> shamt
);
4943 else if (shamt
>= 32)
4945 ASSIGNC (base
>> 31L);
4946 return ((ARMword
) ((ARMsword
) base
>> 31L));
4950 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4951 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4959 ASSIGNC (base
>> 31);
4964 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4965 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4971 /* Shift amount is a constant. */
4974 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4977 base
= state
->Reg
[base
];
4978 shamt
= BITS (7, 11);
4980 switch ((int) BITS (5, 6))
4983 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4984 return (base
<< shamt
);
4988 ASSIGNC (base
>> 31);
4993 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4994 return (base
>> shamt
);
4999 ASSIGNC (base
>> 31L);
5000 return ((ARMword
) ((ARMsword
) base
>> 31L));
5004 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
5005 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
5013 return ((base
>> 1) | (shamt
<< 31));
5017 ASSIGNC ((base
>> (shamt
- 1)) & 1);
5018 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
5026 /* This routine handles writes to register 15 when the S bit is not set. */
5029 WriteR15 (ARMul_State
* state
, ARMword src
)
5031 /* The ARM documentation states that the two least significant bits
5032 are discarded when setting PC, except in the cases handled by
5033 WriteR15Branch() below. It's probably an oversight: in THUMB
5034 mode, the second least significant bit should probably not be
5044 state
->Reg
[15] = src
& PCBITS
;
5046 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
5047 ARMul_R15Altered (state
);
5052 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5055 /* This routine handles writes to register 15 when the S bit is set. */
5058 WriteSR15 (ARMul_State
* state
, ARMword src
)
5061 if (state
->Bank
> 0)
5063 state
->Cpsr
= state
->Spsr
[state
->Bank
];
5064 ARMul_CPSRAltered (state
);
5072 state
->Reg
[15] = src
& PCBITS
;
5076 /* ARMul_R15Altered would have to support it. */
5082 if (state
->Bank
== USERBANK
)
5083 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
5085 state
->Reg
[15] = src
;
5087 ARMul_R15Altered (state
);
5091 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5094 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
5095 will switch to Thumb mode if the least significant bit is set. */
5098 WriteR15Branch (ARMul_State
* state
, ARMword src
)
5105 state
->Reg
[15] = src
& 0xfffffffe;
5110 state
->Reg
[15] = src
& 0xfffffffc;
5114 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5116 WriteR15 (state
, src
);
5120 /* Before ARM_v5 LDR and LDM of pc did not change mode. */
5123 WriteR15Load (ARMul_State
* state
, ARMword src
)
5126 WriteR15Branch (state
, src
);
5128 WriteR15 (state
, src
);
5131 /* This routine evaluates most Load and Store register RHS's. It is
5132 intended to be called from the macro LSRegRHS, which filters the
5133 common case of an unshifted register with in line code. */
5136 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
5138 ARMword shamt
, base
;
5143 /* Now forbidden, but ... */
5144 base
= ECC
| ER15INT
| R15PC
| EMODE
;
5147 base
= state
->Reg
[base
];
5149 shamt
= BITS (7, 11);
5150 switch ((int) BITS (5, 6))
5153 return (base
<< shamt
);
5158 return (base
>> shamt
);
5161 return ((ARMword
) ((ARMsword
) base
>> 31L));
5163 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
5167 return ((base
>> 1) | (CFLAG
<< 31));
5169 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
5176 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
5179 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
5186 /* Now forbidden, but ... */
5187 return ECC
| ER15INT
| R15PC
| EMODE
;
5189 return state
->Reg
[RHSReg
];
5193 return BITS (0, 3) | (BITS (8, 11) << 4);
5196 /* This function does the work of loading a word for a LDR instruction. */
5199 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5205 if (ADDREXCEPT (address
))
5206 INTERNALABORT (address
);
5209 dest
= ARMul_LoadWordN (state
, address
);
5214 return state
->lateabtSig
;
5217 dest
= ARMul_Align (state
, address
, dest
);
5219 ARMul_Icycles (state
, 1, 0L);
5221 return (DESTReg
!= LHSReg
);
5225 /* This function does the work of loading a halfword. */
5228 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
5235 if (ADDREXCEPT (address
))
5236 INTERNALABORT (address
);
5238 dest
= ARMul_LoadHalfWord (state
, address
);
5242 return state
->lateabtSig
;
5246 if (dest
& 1 << (16 - 1))
5247 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
5250 ARMul_Icycles (state
, 1, 0L);
5251 return (DESTReg
!= LHSReg
);
5256 /* This function does the work of loading a byte for a LDRB instruction. */
5259 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
5265 if (ADDREXCEPT (address
))
5266 INTERNALABORT (address
);
5268 dest
= ARMul_LoadByte (state
, address
);
5272 return state
->lateabtSig
;
5276 if (dest
& 1 << (8 - 1))
5277 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
5280 ARMul_Icycles (state
, 1, 0L);
5282 return (DESTReg
!= LHSReg
);
5285 /* This function does the work of loading two words for a LDRD instruction. */
5288 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
5292 ARMword write_back
= BIT (21);
5293 ARMword immediate
= BIT (22);
5294 ARMword add_to_base
= BIT (23);
5295 ARMword pre_indexed
= BIT (24);
5305 /* If the writeback bit is set, the pre-index bit must be clear. */
5306 if (write_back
&& ! pre_indexed
)
5308 ARMul_UndefInstr (state
, instr
);
5312 /* Extract the base address register. */
5315 /* Extract the destination register and check it. */
5318 /* Destination register must be even. */
5320 /* Destination register cannot be LR. */
5321 || (dest_reg
== 14))
5323 ARMul_UndefInstr (state
, instr
);
5327 /* Compute the base address. */
5328 base
= state
->Reg
[addr_reg
];
5330 /* Compute the offset. */
5331 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5333 /* Compute the sum of the two. */
5335 sum
= base
+ offset
;
5337 sum
= base
- offset
;
5339 /* If this is a pre-indexed mode use the sum. */
5345 if (state
->is_v6
&& (addr
& 0x3) == 0)
5346 /* Word alignment is enough for v6. */
5348 /* The address must be aligned on a 8 byte boundary. */
5349 else if (addr
& 0x7)
5352 ARMul_DATAABORT (addr
);
5354 ARMul_UndefInstr (state
, instr
);
5359 /* For pre indexed or post indexed addressing modes,
5360 check that the destination registers do not overlap
5361 the address registers. */
5362 if ((! pre_indexed
|| write_back
)
5363 && ( addr_reg
== dest_reg
5364 || addr_reg
== dest_reg
+ 1))
5366 ARMul_UndefInstr (state
, instr
);
5370 /* Load the words. */
5371 value1
= ARMul_LoadWordN (state
, addr
);
5372 value2
= ARMul_LoadWordN (state
, addr
+ 4);
5374 /* Check for data aborts. */
5381 ARMul_Icycles (state
, 2, 0L);
5383 /* Store the values. */
5384 state
->Reg
[dest_reg
] = value1
;
5385 state
->Reg
[dest_reg
+ 1] = value2
;
5387 /* Do the post addressing and writeback. */
5391 if (! pre_indexed
|| write_back
)
5392 state
->Reg
[addr_reg
] = addr
;
5395 /* This function does the work of storing two words for a STRD instruction. */
5398 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
5402 ARMword write_back
= BIT (21);
5403 ARMword immediate
= BIT (22);
5404 ARMword add_to_base
= BIT (23);
5405 ARMword pre_indexed
= BIT (24);
5413 /* If the writeback bit is set, the pre-index bit must be clear. */
5414 if (write_back
&& ! pre_indexed
)
5416 ARMul_UndefInstr (state
, instr
);
5420 /* Extract the base address register. */
5423 /* Base register cannot be PC. */
5426 ARMul_UndefInstr (state
, instr
);
5430 /* Extract the source register. */
5433 /* Source register must be even. */
5436 ARMul_UndefInstr (state
, instr
);
5440 /* Compute the base address. */
5441 base
= state
->Reg
[addr_reg
];
5443 /* Compute the offset. */
5444 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5446 /* Compute the sum of the two. */
5448 sum
= base
+ offset
;
5450 sum
= base
- offset
;
5452 /* If this is a pre-indexed mode use the sum. */
5458 /* The address must be aligned on a 8 byte boundary. */
5459 if (state
->is_v6
&& (addr
& 0x3) == 0)
5460 /* Word alignment is enough for v6. */
5462 else if (addr
& 0x7)
5465 ARMul_DATAABORT (addr
);
5467 ARMul_UndefInstr (state
, instr
);
5472 /* For pre indexed or post indexed addressing modes,
5473 check that the destination registers do not overlap
5474 the address registers. */
5475 if ((! pre_indexed
|| write_back
)
5476 && ( addr_reg
== src_reg
5477 || addr_reg
== src_reg
+ 1))
5479 ARMul_UndefInstr (state
, instr
);
5483 /* Load the words. */
5484 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
5485 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
5493 /* Do the post addressing and writeback. */
5497 if (! pre_indexed
|| write_back
)
5498 state
->Reg
[addr_reg
] = addr
;
5501 /* This function does the work of storing a word from a STR instruction. */
5504 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5509 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5512 ARMul_StoreWordN (state
, address
, DEST
);
5514 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5516 INTERNALABORT (address
);
5517 (void) ARMul_LoadWordN (state
, address
);
5520 ARMul_StoreWordN (state
, address
, DEST
);
5525 return state
->lateabtSig
;
5531 /* This function does the work of storing a byte for a STRH instruction. */
5534 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5540 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5544 ARMul_StoreHalfWord (state
, address
, DEST
);
5546 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5548 INTERNALABORT (address
);
5549 (void) ARMul_LoadHalfWord (state
, address
);
5552 ARMul_StoreHalfWord (state
, address
, DEST
);
5558 return state
->lateabtSig
;
5565 /* This function does the work of storing a byte for a STRB instruction. */
5568 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
5573 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5576 ARMul_StoreByte (state
, address
, DEST
);
5578 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5580 INTERNALABORT (address
);
5581 (void) ARMul_LoadByte (state
, address
);
5584 ARMul_StoreByte (state
, address
, DEST
);
5589 return state
->lateabtSig
;
5595 /* This function does the work of loading the registers listed in an LDM
5596 instruction, when the S bit is clear. The code here is always increment
5597 after, it's up to the caller to get the input address correct and to
5598 handle base register modification. */
5601 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
5607 UNDEF_LSMBaseInListWb
;
5610 if (ADDREXCEPT (address
))
5611 INTERNALABORT (address
);
5613 if (BIT (21) && LHSReg
!= 15)
5616 /* N cycle first. */
5617 for (temp
= 0; !BIT (temp
); temp
++)
5620 dest
= ARMul_LoadWordN (state
, address
);
5622 if (!state
->abortSig
&& !state
->Aborted
)
5623 state
->Reg
[temp
++] = dest
;
5624 else if (!state
->Aborted
)
5626 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5627 state
->Aborted
= ARMul_DataAbortV
;
5630 /* S cycles from here on. */
5631 for (; temp
< 16; temp
++)
5634 /* Load this register. */
5636 dest
= ARMul_LoadWordS (state
, address
);
5638 if (!state
->abortSig
&& !state
->Aborted
)
5639 state
->Reg
[temp
] = dest
;
5640 else if (!state
->Aborted
)
5642 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5643 state
->Aborted
= ARMul_DataAbortV
;
5647 if (BIT (15) && !state
->Aborted
)
5648 /* PC is in the reg list. */
5649 WriteR15Load (state
, PC
);
5651 /* To write back the final register. */
5652 ARMul_Icycles (state
, 1, 0L);
5656 if (BIT (21) && LHSReg
!= 15)
5662 /* This function does the work of loading the registers listed in an LDM
5663 instruction, when the S bit is set. The code here is always increment
5664 after, it's up to the caller to get the input address correct and to
5665 handle base register modification. */
5668 LoadSMult (ARMul_State
* state
,
5677 UNDEF_LSMBaseInListWb
;
5682 if (ADDREXCEPT (address
))
5683 INTERNALABORT (address
);
5686 if (BIT (21) && LHSReg
!= 15)
5689 if (!BIT (15) && state
->Bank
!= USERBANK
)
5691 /* Temporary reg bank switch. */
5692 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5693 UNDEF_LSMUserBankWb
;
5696 /* N cycle first. */
5697 for (temp
= 0; !BIT (temp
); temp
++)
5700 dest
= ARMul_LoadWordN (state
, address
);
5702 if (!state
->abortSig
)
5703 state
->Reg
[temp
++] = dest
;
5704 else if (!state
->Aborted
)
5706 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5707 state
->Aborted
= ARMul_DataAbortV
;
5710 /* S cycles from here on. */
5711 for (; temp
< 16; temp
++)
5714 /* Load this register. */
5716 dest
= ARMul_LoadWordS (state
, address
);
5718 if (!state
->abortSig
&& !state
->Aborted
)
5719 state
->Reg
[temp
] = dest
;
5720 else if (!state
->Aborted
)
5722 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5723 state
->Aborted
= ARMul_DataAbortV
;
5727 if (BIT (15) && !state
->Aborted
)
5729 /* PC is in the reg list. */
5731 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5733 state
->Cpsr
= GETSPSR (state
->Bank
);
5734 ARMul_CPSRAltered (state
);
5737 WriteR15 (state
, PC
);
5739 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
5741 /* Protect bits in user mode. */
5742 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
5743 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
5744 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
5745 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
5748 ARMul_R15Altered (state
);
5754 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5755 /* Restore the correct bank. */
5756 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5758 /* To write back the final register. */
5759 ARMul_Icycles (state
, 1, 0L);
5763 if (BIT (21) && LHSReg
!= 15)
5770 /* This function does the work of storing the registers listed in an STM
5771 instruction, when the S bit is clear. The code here is always increment
5772 after, it's up to the caller to get the input address correct and to
5773 handle base register modification. */
5776 StoreMult (ARMul_State
* state
,
5785 UNDEF_LSMBaseInListWb
;
5788 /* N-cycle, increment the PC and update the NextInstr state. */
5792 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5793 INTERNALABORT (address
);
5799 /* N cycle first. */
5800 for (temp
= 0; !BIT (temp
); temp
++)
5804 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5808 (void) ARMul_LoadWordN (state
, address
);
5810 /* Fake the Stores as Loads. */
5811 for (; temp
< 16; temp
++)
5814 /* Save this register. */
5816 (void) ARMul_LoadWordS (state
, address
);
5819 if (BIT (21) && LHSReg
!= 15)
5825 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5828 if (state
->abortSig
&& !state
->Aborted
)
5830 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5831 state
->Aborted
= ARMul_DataAbortV
;
5834 if (BIT (21) && LHSReg
!= 15)
5837 /* S cycles from here on. */
5838 for (; temp
< 16; temp
++)
5841 /* Save this register. */
5844 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5846 if (state
->abortSig
&& !state
->Aborted
)
5848 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5849 state
->Aborted
= ARMul_DataAbortV
;
5857 /* This function does the work of storing the registers listed in an STM
5858 instruction when the S bit is set. The code here is always increment
5859 after, it's up to the caller to get the input address correct and to
5860 handle base register modification. */
5863 StoreSMult (ARMul_State
* state
,
5872 UNDEF_LSMBaseInListWb
;
5877 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5878 INTERNALABORT (address
);
5884 if (state
->Bank
!= USERBANK
)
5886 /* Force User Bank. */
5887 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5888 UNDEF_LSMUserBankWb
;
5891 for (temp
= 0; !BIT (temp
); temp
++)
5892 ; /* N cycle first. */
5895 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5899 (void) ARMul_LoadWordN (state
, address
);
5901 for (; temp
< 16; temp
++)
5902 /* Fake the Stores as Loads. */
5905 /* Save this register. */
5908 (void) ARMul_LoadWordS (state
, address
);
5911 if (BIT (21) && LHSReg
!= 15)
5918 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5921 if (state
->abortSig
&& !state
->Aborted
)
5923 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5924 state
->Aborted
= ARMul_DataAbortV
;
5927 /* S cycles from here on. */
5928 for (; temp
< 16; temp
++)
5931 /* Save this register. */
5934 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5936 if (state
->abortSig
&& !state
->Aborted
)
5938 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5939 state
->Aborted
= ARMul_DataAbortV
;
5943 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5944 /* Restore the correct bank. */
5945 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5947 if (BIT (21) && LHSReg
!= 15)
5954 /* This function does the work of adding two 32bit values
5955 together, and calculating if a carry has occurred. */
5958 Add32 (ARMword a1
, ARMword a2
, int *carry
)
5960 ARMword result
= (a1
+ a2
);
5961 unsigned int uresult
= (unsigned int) result
;
5962 unsigned int ua1
= (unsigned int) a1
;
5964 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5965 or (result > RdLo) then we have no carry. */
5966 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
5974 /* This function does the work of multiplying
5975 two 32bit values to give a 64bit result. */
5978 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5980 /* Operand register numbers. */
5981 int nRdHi
, nRdLo
, nRs
, nRm
;
5982 ARMword RdHi
= 0, RdLo
= 0, Rm
;
5986 nRdHi
= BITS (16, 19);
5987 nRdLo
= BITS (12, 15);
5991 /* Needed to calculate the cycle count. */
5992 Rm
= state
->Reg
[nRm
];
5994 /* Check for illegal operand combinations first. */
6001 /* Intermediate results. */
6002 ARMword lo
, mid1
, mid2
, hi
;
6004 ARMword Rs
= state
->Reg
[nRs
];
6012 /* BAD code can trigger this result. So only complain if debugging. */
6013 if (state
->Debug
&& (nRdHi
== nRm
|| nRdLo
== nRm
))
6014 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS: %d %d %d\n",
6018 /* Compute sign of result and adjust operands if necessary. */
6019 sign
= (Rm
^ Rs
) & 0x80000000;
6021 if (((ARMsword
) Rm
) < 0)
6024 if (((ARMsword
) Rs
) < 0)
6028 /* We can split the 32x32 into four 16x16 operations. This
6029 ensures that we do not lose precision on 32bit only hosts. */
6030 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
6031 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
6032 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
6033 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
6035 /* We now need to add all of these results together, taking
6036 care to propagate the carries from the additions. */
6037 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
6039 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
6041 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
6045 /* Negate result if necessary. */
6048 if (RdLo
== 0xFFFFFFFF)
6057 state
->Reg
[nRdLo
] = RdLo
;
6058 state
->Reg
[nRdHi
] = RdHi
;
6060 else if (state
->Debug
)
6061 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
6064 /* Ensure that both RdHi and RdLo are used to compute Z,
6065 but don't let RdLo's sign bit make it to N. */
6066 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6068 /* The cycle count depends on whether the instruction is a signed or
6069 unsigned multiply, and what bits are clear in the multiplier. */
6070 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
6071 /* Invert the bits to make the check against zero. */
6074 if ((Rm
& 0xFFFFFF00) == 0)
6076 else if ((Rm
& 0xFFFF0000) == 0)
6078 else if ((Rm
& 0xFF000000) == 0)
6086 /* This function does the work of multiplying two 32bit
6087 values and adding a 64bit value to give a 64bit result. */
6090 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
6097 nRdHi
= BITS (16, 19);
6098 nRdLo
= BITS (12, 15);
6100 RdHi
= state
->Reg
[nRdHi
];
6101 RdLo
= state
->Reg
[nRdLo
];
6103 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
6105 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
6106 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
6108 state
->Reg
[nRdLo
] = RdLo
;
6109 state
->Reg
[nRdHi
] = RdHi
;
6112 /* Ensure that both RdHi and RdLo are used to compute Z,
6113 but don't let RdLo's sign bit make it to N. */
6114 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6116 /* Extra cycle for addition. */