]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/arm/armemu.c
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 ARMword 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) */
1439 state
->Reg
[14] = pc
+ 4;
1441 /* Force entry into Thumb mode. */
1444 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
1446 dest
+= POSBRANCH
+ (BIT (24) << 1);
1448 WriteR15Branch (state
, dest
);
1451 else if ((instr
& 0xFC70F000) == 0xF450F000)
1452 /* The PLD instruction. Ignored. */
1454 else if ( ((instr
& 0xfe500f00) == 0xfc100100)
1455 || ((instr
& 0xfe500f00) == 0xfc000100))
1456 /* wldrw and wstrw are unconditional. */
1459 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
1460 ARMul_UndefInstr (state
, instr
);
1489 temp
= (CFLAG
&& !ZFLAG
);
1492 temp
= (!CFLAG
|| ZFLAG
);
1495 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
1498 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
1501 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
1504 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
1508 /* Handle the Clock counter here. */
1509 if (state
->is_XScale
)
1514 ok
= state
->CPRead
[14] (state
, 0, & cp14r0
);
1516 if (ok
&& (cp14r0
& ARMul_CP14_R0_ENABLE
))
1518 unsigned long newcycles
, nowtime
= ARMul_Time (state
);
1520 newcycles
= nowtime
- state
->LastTime
;
1521 state
->LastTime
= nowtime
;
1523 if (cp14r0
& ARMul_CP14_R0_CCD
)
1525 if (state
->CP14R0_CCD
== -1)
1526 state
->CP14R0_CCD
= newcycles
;
1528 state
->CP14R0_CCD
+= newcycles
;
1530 if (state
->CP14R0_CCD
>= 64)
1534 while (state
->CP14R0_CCD
>= 64)
1535 state
->CP14R0_CCD
-= 64, newcycles
++;
1545 state
->CP14R0_CCD
= -1;
1548 cp14r0
|= ARMul_CP14_R0_FLAG2
;
1549 (void) state
->CPWrite
[14] (state
, 0, cp14r0
);
1551 ok
= state
->CPRead
[14] (state
, 1, & cp14r1
);
1553 /* Coded like this for portability. */
1554 while (ok
&& newcycles
)
1556 if (cp14r1
== 0xffffffff)
1567 (void) state
->CPWrite
[14] (state
, 1, cp14r1
);
1569 if (do_int
&& (cp14r0
& ARMul_CP14_R0_INTEN2
))
1573 if (state
->CPRead
[13] (state
, 8, & temp
)
1574 && (temp
& ARMul_CP13_R8_PMUS
))
1575 ARMul_Abort (state
, ARMul_FIQV
);
1577 ARMul_Abort (state
, ARMul_IRQV
);
1583 /* Handle hardware instructions breakpoints here. */
1584 if (state
->is_XScale
)
1586 if ( (pc
| 3) == (read_cp15_reg (14, 0, 8) | 2)
1587 || (pc
| 3) == (read_cp15_reg (14, 0, 9) | 2))
1589 if (XScale_debug_moe (state
, ARMul_CP14_R10_MOE_IB
))
1590 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1594 /* Actual execution of instructions begins here. */
1595 /* If the condition codes don't match, stop here. */
1600 if (state
->is_XScale
)
1602 if (BIT (20) == 0 && BITS (25, 27) == 0)
1604 if (BITS (4, 7) == 0xD)
1606 /* XScale Load Consecutive insn. */
1607 ARMword temp
= GetLS7RHS (state
, instr
);
1608 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
1609 ARMword addr
= BIT (24) ? temp2
: LHS
;
1612 ARMul_UndefInstr (state
, instr
);
1614 /* Alignment violation. */
1615 ARMul_Abort (state
, ARMul_DataAbortV
);
1618 int wb
= BIT (21) || (! BIT (24));
1620 state
->Reg
[BITS (12, 15)] =
1621 ARMul_LoadWordN (state
, addr
);
1622 state
->Reg
[BITS (12, 15) + 1] =
1623 ARMul_LoadWordN (state
, addr
+ 4);
1630 else if (BITS (4, 7) == 0xF)
1632 /* XScale Store Consecutive insn. */
1633 ARMword temp
= GetLS7RHS (state
, instr
);
1634 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
1635 ARMword addr
= BIT (24) ? temp2
: LHS
;
1638 ARMul_UndefInstr (state
, instr
);
1640 /* Alignment violation. */
1641 ARMul_Abort (state
, ARMul_DataAbortV
);
1644 ARMul_StoreWordN (state
, addr
,
1645 state
->Reg
[BITS (12, 15)]);
1646 ARMul_StoreWordN (state
, addr
+ 4,
1647 state
->Reg
[BITS (12, 15) + 1]);
1649 if (BIT (21)|| ! BIT (24))
1657 if (ARMul_HandleIwmmxt (state
, instr
))
1661 switch ((int) BITS (20, 27))
1663 /* Data Processing Register RHS Instructions. */
1665 case 0x00: /* AND reg and MUL */
1667 if (BITS (4, 11) == 0xB)
1669 /* STRH register offset, no write-back, down, post indexed. */
1673 if (BITS (4, 7) == 0xD)
1675 Handle_Load_Double (state
, instr
);
1678 if (BITS (4, 7) == 0xF)
1680 Handle_Store_Double (state
, instr
);
1684 if (BITS (4, 7) == 9)
1687 rhs
= state
->Reg
[MULRHSReg
];
1688 if (MULLHSReg
== MULDESTReg
)
1691 state
->Reg
[MULDESTReg
] = 0;
1693 else if (MULDESTReg
!= 15)
1694 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
1698 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1699 if (rhs
& (1L << dest
))
1702 /* Mult takes this many/2 I cycles. */
1703 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1714 case 0x01: /* ANDS reg and MULS */
1716 if ((BITS (4, 11) & 0xF9) == 0x9)
1717 /* LDR register offset, no write-back, down, post indexed. */
1719 /* Fall through to rest of decoding. */
1721 if (BITS (4, 7) == 9)
1724 rhs
= state
->Reg
[MULRHSReg
];
1726 if (MULLHSReg
== MULDESTReg
)
1729 state
->Reg
[MULDESTReg
] = 0;
1733 else if (MULDESTReg
!= 15)
1735 dest
= state
->Reg
[MULLHSReg
] * rhs
;
1736 ARMul_NegZero (state
, dest
);
1737 state
->Reg
[MULDESTReg
] = dest
;
1742 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1743 if (rhs
& (1L << dest
))
1746 /* Mult takes this many/2 I cycles. */
1747 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1758 case 0x02: /* EOR reg and MLA */
1760 if (BITS (4, 11) == 0xB)
1762 /* STRH register offset, write-back, down, post indexed. */
1767 if (BITS (4, 7) == 9)
1769 rhs
= state
->Reg
[MULRHSReg
];
1770 if (MULLHSReg
== MULDESTReg
)
1773 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
1775 else if (MULDESTReg
!= 15)
1776 state
->Reg
[MULDESTReg
] =
1777 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1781 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1782 if (rhs
& (1L << dest
))
1785 /* Mult takes this many/2 I cycles. */
1786 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1796 case 0x03: /* EORS reg and MLAS */
1798 if ((BITS (4, 11) & 0xF9) == 0x9)
1799 /* LDR register offset, write-back, down, post-indexed. */
1801 /* Fall through to rest of the decoding. */
1803 if (BITS (4, 7) == 9)
1806 rhs
= state
->Reg
[MULRHSReg
];
1808 if (MULLHSReg
== MULDESTReg
)
1811 dest
= state
->Reg
[MULACCReg
];
1812 ARMul_NegZero (state
, dest
);
1813 state
->Reg
[MULDESTReg
] = dest
;
1815 else if (MULDESTReg
!= 15)
1818 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
1819 ARMul_NegZero (state
, dest
);
1820 state
->Reg
[MULDESTReg
] = dest
;
1825 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
1826 if (rhs
& (1L << dest
))
1829 /* Mult takes this many/2 I cycles. */
1830 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
1841 case 0x04: /* SUB reg */
1843 if (BITS (4, 7) == 0xB)
1845 /* STRH immediate offset, no write-back, down, post indexed. */
1849 if (BITS (4, 7) == 0xD)
1851 Handle_Load_Double (state
, instr
);
1854 if (BITS (4, 7) == 0xF)
1856 Handle_Store_Double (state
, instr
);
1865 case 0x05: /* SUBS reg */
1867 if ((BITS (4, 7) & 0x9) == 0x9)
1868 /* LDR immediate offset, no write-back, down, post indexed. */
1870 /* Fall through to the rest of the instruction decoding. */
1876 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1878 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1879 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1889 case 0x06: /* RSB reg */
1891 if (BITS (4, 7) == 0xB)
1893 /* STRH immediate offset, write-back, down, post indexed. */
1903 case 0x07: /* RSBS reg */
1905 if ((BITS (4, 7) & 0x9) == 0x9)
1906 /* LDR immediate offset, write-back, down, post indexed. */
1908 /* Fall through to remainder of instruction decoding. */
1914 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1916 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1917 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1927 case 0x08: /* ADD reg */
1929 if (BITS (4, 11) == 0xB)
1931 /* STRH register offset, no write-back, up, post indexed. */
1935 if (BITS (4, 7) == 0xD)
1937 Handle_Load_Double (state
, instr
);
1940 if (BITS (4, 7) == 0xF)
1942 Handle_Store_Double (state
, instr
);
1947 if (BITS (4, 7) == 0x9)
1951 ARMul_Icycles (state
,
1952 Multiply64 (state
, instr
, LUNSIGNED
,
1962 case 0x09: /* ADDS reg */
1964 if ((BITS (4, 11) & 0xF9) == 0x9)
1965 /* LDR register offset, no write-back, up, post indexed. */
1967 /* Fall through to remaining instruction decoding. */
1970 if (BITS (4, 7) == 0x9)
1974 ARMul_Icycles (state
,
1975 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
1983 ASSIGNZ (dest
== 0);
1984 if ((lhs
| rhs
) >> 30)
1986 /* Possible C,V,N to set. */
1987 ASSIGNN (NEG (dest
));
1988 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1989 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2000 case 0x0a: /* ADC reg */
2002 if (BITS (4, 11) == 0xB)
2004 /* STRH register offset, write-back, up, post-indexed. */
2008 if (BITS (4, 7) == 0x9)
2012 ARMul_Icycles (state
,
2013 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
2019 dest
= LHS
+ rhs
+ CFLAG
;
2023 case 0x0b: /* ADCS reg */
2025 if ((BITS (4, 11) & 0xF9) == 0x9)
2026 /* LDR register offset, write-back, up, post indexed. */
2028 /* Fall through to remaining instruction decoding. */
2029 if (BITS (4, 7) == 0x9)
2033 ARMul_Icycles (state
,
2034 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
2041 dest
= lhs
+ rhs
+ CFLAG
;
2042 ASSIGNZ (dest
== 0);
2043 if ((lhs
| rhs
) >> 30)
2045 /* Possible C,V,N to set. */
2046 ASSIGNN (NEG (dest
));
2047 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2048 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2059 case 0x0c: /* SBC reg */
2061 if (BITS (4, 7) == 0xB)
2063 /* STRH immediate offset, no write-back, up post indexed. */
2067 if (BITS (4, 7) == 0xD)
2069 Handle_Load_Double (state
, instr
);
2072 if (BITS (4, 7) == 0xF)
2074 Handle_Store_Double (state
, instr
);
2077 if (BITS (4, 7) == 0x9)
2081 ARMul_Icycles (state
,
2082 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
2088 dest
= LHS
- rhs
- !CFLAG
;
2092 case 0x0d: /* SBCS reg */
2094 if ((BITS (4, 7) & 0x9) == 0x9)
2095 /* LDR immediate offset, no write-back, up, post indexed. */
2098 if (BITS (4, 7) == 0x9)
2102 ARMul_Icycles (state
,
2103 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
2110 dest
= lhs
- rhs
- !CFLAG
;
2111 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2113 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2114 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2124 case 0x0e: /* RSC reg */
2126 if (BITS (4, 7) == 0xB)
2128 /* STRH immediate offset, write-back, up, post indexed. */
2133 if (BITS (4, 7) == 0x9)
2137 ARMul_Icycles (state
,
2138 MultiplyAdd64 (state
, instr
, LSIGNED
,
2144 dest
= rhs
- LHS
- !CFLAG
;
2148 case 0x0f: /* RSCS reg */
2150 if ((BITS (4, 7) & 0x9) == 0x9)
2151 /* LDR immediate offset, write-back, up, post indexed. */
2153 /* Fall through to remaining instruction decoding. */
2155 if (BITS (4, 7) == 0x9)
2159 ARMul_Icycles (state
,
2160 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
2167 dest
= rhs
- lhs
- !CFLAG
;
2169 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2171 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2172 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2182 case 0x10: /* TST reg and MRS CPSR and SWP word. */
2185 if (BIT (4) == 0 && BIT (7) == 1)
2187 /* ElSegundo SMLAxy insn. */
2188 ARMword op1
= state
->Reg
[BITS (0, 3)];
2189 ARMword op2
= state
->Reg
[BITS (8, 11)];
2190 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2204 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
2206 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
2210 if (BITS (4, 11) == 5)
2212 /* ElSegundo QADD insn. */
2213 ARMword op1
= state
->Reg
[BITS (0, 3)];
2214 ARMword op2
= state
->Reg
[BITS (16, 19)];
2215 ARMword result
= op1
+ op2
;
2216 if (AddOverflow (op1
, op2
, result
))
2218 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2221 state
->Reg
[BITS (12, 15)] = result
;
2226 if (BITS (4, 11) == 0xB)
2228 /* STRH register offset, no write-back, down, pre indexed. */
2232 if (BITS (4, 7) == 0xD)
2234 Handle_Load_Double (state
, instr
);
2237 if (BITS (4, 7) == 0xF)
2239 Handle_Store_Double (state
, instr
);
2243 if (BITS (4, 11) == 9)
2250 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2252 INTERNALABORT (temp
);
2253 (void) ARMul_LoadWordN (state
, temp
);
2254 (void) ARMul_LoadWordN (state
, temp
);
2258 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
2260 DEST
= ARMul_Align (state
, temp
, dest
);
2263 if (state
->abortSig
|| state
->Aborted
)
2266 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2269 DEST
= ECC
| EINT
| EMODE
;
2275 && handle_v6_insn (state
, instr
))
2282 case 0x11: /* TSTP reg */
2284 if ((BITS (4, 11) & 0xF9) == 0x9)
2285 /* LDR register offset, no write-back, down, pre indexed. */
2287 /* Continue with remaining instruction decode. */
2293 state
->Cpsr
= GETSPSR (state
->Bank
);
2294 ARMul_CPSRAltered (state
);
2306 ARMul_NegZero (state
, dest
);
2310 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
2313 if (BITS (4, 7) == 3)
2319 temp
= (pc
+ 2) | 1;
2323 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2324 state
->Reg
[14] = temp
;
2331 if (BIT (4) == 0 && BIT (7) == 1
2332 && (BIT (5) == 0 || BITS (12, 15) == 0))
2334 /* ElSegundo SMLAWy/SMULWy insn. */
2335 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2336 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2341 if (op1
& 0x80000000)
2346 result
= (op1
* op2
) >> 16;
2350 ARMword Rn
= state
->Reg
[BITS (12, 15)];
2352 if (AddOverflow (result
, Rn
, result
+ Rn
))
2356 state
->Reg
[BITS (16, 19)] = result
;
2360 if (BITS (4, 11) == 5)
2362 /* ElSegundo QSUB insn. */
2363 ARMword op1
= state
->Reg
[BITS (0, 3)];
2364 ARMword op2
= state
->Reg
[BITS (16, 19)];
2365 ARMword result
= op1
- op2
;
2367 if (SubOverflow (op1
, op2
, result
))
2369 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2373 state
->Reg
[BITS (12, 15)] = result
;
2378 if (BITS (4, 11) == 0xB)
2380 /* STRH register offset, write-back, down, pre indexed. */
2384 if (BITS (4, 27) == 0x12FFF1)
2387 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
2390 if (BITS (4, 7) == 0xD)
2392 Handle_Load_Double (state
, instr
);
2395 if (BITS (4, 7) == 0xF)
2397 Handle_Store_Double (state
, instr
);
2403 if (BITS (4, 7) == 0x7)
2405 extern int SWI_vector_installed
;
2407 /* Hardware is allowed to optionally override this
2408 instruction and treat it as a breakpoint. Since
2409 this is a simulator not hardware, we take the position
2410 that if a SWI vector was not installed, then an Abort
2411 vector was probably not installed either, and so
2412 normally this instruction would be ignored, even if an
2413 Abort is generated. This is a bad thing, since GDB
2414 uses this instruction for its breakpoints (at least in
2415 Thumb mode it does). So intercept the instruction here
2416 and generate a breakpoint SWI instead. */
2417 if (! SWI_vector_installed
)
2418 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
2421 /* BKPT - normally this will cause an abort, but on the
2422 XScale we must check the DCSR. */
2423 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
2424 if (!XScale_debug_moe (state
, ARMul_CP14_R10_MOE_BT
))
2428 /* Force the next instruction to be refetched. */
2429 state
->NextInstr
= RESUME
;
2435 /* MSR reg to CPSR. */
2439 /* Don't allow TBIT to be set by MSR. */
2442 ARMul_FixCPSR (state
, instr
, temp
);
2445 else if (state
->is_v6
2446 && handle_v6_insn (state
, instr
))
2454 case 0x13: /* TEQP reg */
2456 if ((BITS (4, 11) & 0xF9) == 0x9)
2457 /* LDR register offset, write-back, down, pre indexed. */
2459 /* Continue with remaining instruction decode. */
2465 state
->Cpsr
= GETSPSR (state
->Bank
);
2466 ARMul_CPSRAltered (state
);
2478 ARMul_NegZero (state
, dest
);
2482 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
2485 if (BIT (4) == 0 && BIT (7) == 1)
2487 /* ElSegundo SMLALxy insn. */
2488 ARMdword op1
= state
->Reg
[BITS (0, 3)];
2489 ARMdword op2
= state
->Reg
[BITS (8, 11)];
2503 dest
= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
2504 dest
|= state
->Reg
[BITS (12, 15)];
2506 state
->Reg
[BITS (12, 15)] = dest
;
2507 state
->Reg
[BITS (16, 19)] = dest
>> 32;
2511 if (BITS (4, 11) == 5)
2513 /* ElSegundo QDADD insn. */
2514 ARMword op1
= state
->Reg
[BITS (0, 3)];
2515 ARMword op2
= state
->Reg
[BITS (16, 19)];
2516 ARMword op2d
= op2
+ op2
;
2519 if (AddOverflow (op2
, op2
, op2d
))
2522 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2525 result
= op1
+ op2d
;
2526 if (AddOverflow (op1
, op2d
, result
))
2529 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2532 state
->Reg
[BITS (12, 15)] = result
;
2537 if (BITS (4, 7) == 0xB)
2539 /* STRH immediate offset, no write-back, down, pre indexed. */
2543 if (BITS (4, 7) == 0xD)
2545 Handle_Load_Double (state
, instr
);
2548 if (BITS (4, 7) == 0xF)
2550 Handle_Store_Double (state
, instr
);
2554 if (BITS (4, 11) == 9)
2561 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
2563 INTERNALABORT (temp
);
2564 (void) ARMul_LoadByte (state
, temp
);
2565 (void) ARMul_LoadByte (state
, temp
);
2569 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
2570 if (state
->abortSig
|| state
->Aborted
)
2573 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
2577 DEST
= GETSPSR (state
->Bank
);
2580 else if (state
->is_v6
2581 && handle_v6_insn (state
, instr
))
2589 case 0x15: /* CMPP reg. */
2591 if ((BITS (4, 7) & 0x9) == 0x9)
2592 /* LDR immediate offset, no write-back, down, pre indexed. */
2594 /* Continue with remaining instruction decode. */
2600 state
->Cpsr
= GETSPSR (state
->Bank
);
2601 ARMul_CPSRAltered (state
);
2614 ARMul_NegZero (state
, dest
);
2615 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2617 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2618 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2628 case 0x16: /* CMN reg and MSR reg to SPSR */
2631 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
2633 /* ElSegundo SMULxy insn. */
2634 ARMword op1
= state
->Reg
[BITS (0, 3)];
2635 ARMword op2
= state
->Reg
[BITS (8, 11)];
2648 state
->Reg
[BITS (16, 19)] = op1
* op2
;
2652 if (BITS (4, 11) == 5)
2654 /* ElSegundo QDSUB insn. */
2655 ARMword op1
= state
->Reg
[BITS (0, 3)];
2656 ARMword op2
= state
->Reg
[BITS (16, 19)];
2657 ARMword op2d
= op2
+ op2
;
2660 if (AddOverflow (op2
, op2
, op2d
))
2663 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
2666 result
= op1
- op2d
;
2667 if (SubOverflow (op1
, op2d
, result
))
2670 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
2673 state
->Reg
[BITS (12, 15)] = result
;
2680 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
2682 /* ARM5 CLZ insn. */
2683 ARMword op1
= state
->Reg
[BITS (0, 3)];
2687 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
2690 state
->Reg
[BITS (12, 15)] = result
;
2695 if (BITS (4, 7) == 0xB)
2697 /* STRH immediate offset, write-back, down, pre indexed. */
2701 if (BITS (4, 7) == 0xD)
2703 Handle_Load_Double (state
, instr
);
2706 if (BITS (4, 7) == 0xF)
2708 Handle_Store_Double (state
, instr
);
2716 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
2722 && handle_v6_insn (state
, instr
))
2729 case 0x17: /* CMNP reg */
2731 if ((BITS (4, 7) & 0x9) == 0x9)
2732 /* LDR immediate offset, write-back, down, pre indexed. */
2734 /* Continue with remaining instruction decoding. */
2739 state
->Cpsr
= GETSPSR (state
->Bank
);
2740 ARMul_CPSRAltered (state
);
2754 ASSIGNZ (dest
== 0);
2755 if ((lhs
| rhs
) >> 30)
2757 /* Possible C,V,N to set. */
2758 ASSIGNN (NEG (dest
));
2759 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2760 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2771 case 0x18: /* ORR reg */
2773 if (BITS (4, 11) == 0xB)
2775 /* STRH register offset, no write-back, up, pre indexed. */
2779 if (BITS (4, 7) == 0xD)
2781 Handle_Load_Double (state
, instr
);
2784 if (BITS (4, 7) == 0xF)
2786 Handle_Store_Double (state
, instr
);
2795 case 0x19: /* ORRS reg */
2797 if ((BITS (4, 11) & 0xF9) == 0x9)
2798 /* LDR register offset, no write-back, up, pre indexed. */
2800 /* Continue with remaining instruction decoding. */
2807 case 0x1a: /* MOV reg */
2809 if (BITS (4, 11) == 0xB)
2811 /* STRH register offset, write-back, up, pre indexed. */
2815 if (BITS (4, 7) == 0xD)
2817 Handle_Load_Double (state
, instr
);
2820 if (BITS (4, 7) == 0xF)
2822 Handle_Store_Double (state
, instr
);
2830 case 0x1b: /* MOVS reg */
2832 if ((BITS (4, 11) & 0xF9) == 0x9)
2833 /* LDR register offset, write-back, up, pre indexed. */
2835 /* Continue with remaining instruction decoding. */
2841 case 0x1c: /* BIC reg */
2843 if (BITS (4, 7) == 0xB)
2845 /* STRH immediate offset, no write-back, up, pre indexed. */
2849 if (BITS (4, 7) == 0xD)
2851 Handle_Load_Double (state
, instr
);
2854 else if (BITS (4, 7) == 0xF)
2856 Handle_Store_Double (state
, instr
);
2865 case 0x1d: /* BICS reg */
2867 if ((BITS (4, 7) & 0x9) == 0x9)
2868 /* LDR immediate offset, no write-back, up, pre indexed. */
2870 /* Continue with instruction decoding. */
2877 case 0x1e: /* MVN reg */
2879 if (BITS (4, 7) == 0xB)
2881 /* STRH immediate offset, write-back, up, pre indexed. */
2885 if (BITS (4, 7) == 0xD)
2887 Handle_Load_Double (state
, instr
);
2890 if (BITS (4, 7) == 0xF)
2892 Handle_Store_Double (state
, instr
);
2900 case 0x1f: /* MVNS reg */
2902 if ((BITS (4, 7) & 0x9) == 0x9)
2903 /* LDR immediate offset, write-back, up, pre indexed. */
2905 /* Continue instruction decoding. */
2912 /* Data Processing Immediate RHS Instructions. */
2914 case 0x20: /* AND immed */
2915 dest
= LHS
& DPImmRHS
;
2919 case 0x21: /* ANDS immed */
2925 case 0x22: /* EOR immed */
2926 dest
= LHS
^ DPImmRHS
;
2930 case 0x23: /* EORS immed */
2936 case 0x24: /* SUB immed */
2937 dest
= LHS
- DPImmRHS
;
2941 case 0x25: /* SUBS immed */
2946 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
2948 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
2949 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
2959 case 0x26: /* RSB immed */
2960 dest
= DPImmRHS
- LHS
;
2964 case 0x27: /* RSBS immed */
2969 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
2971 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
2972 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
2982 case 0x28: /* ADD immed */
2983 dest
= LHS
+ DPImmRHS
;
2987 case 0x29: /* ADDS immed */
2991 ASSIGNZ (dest
== 0);
2993 if ((lhs
| rhs
) >> 30)
2995 /* Possible C,V,N to set. */
2996 ASSIGNN (NEG (dest
));
2997 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2998 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3009 case 0x2a: /* ADC immed */
3010 dest
= LHS
+ DPImmRHS
+ CFLAG
;
3014 case 0x2b: /* ADCS immed */
3017 dest
= lhs
+ rhs
+ CFLAG
;
3018 ASSIGNZ (dest
== 0);
3019 if ((lhs
| rhs
) >> 30)
3021 /* Possible C,V,N to set. */
3022 ASSIGNN (NEG (dest
));
3023 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
3024 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3035 case 0x2c: /* SBC immed */
3036 dest
= LHS
- DPImmRHS
- !CFLAG
;
3040 case 0x2d: /* SBCS immed */
3043 dest
= lhs
- rhs
- !CFLAG
;
3044 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
3046 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
3047 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
3057 case 0x2e: /* RSC immed */
3058 dest
= DPImmRHS
- LHS
- !CFLAG
;
3062 case 0x2f: /* RSCS immed */
3065 dest
= rhs
- lhs
- !CFLAG
;
3066 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
3068 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
3069 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
3079 case 0x30: /* MOVW immed */
3082 && handle_v6_insn (state
, instr
))
3085 dest
= BITS (0, 11);
3086 dest
|= (BITS (16, 19) << 12);
3090 case 0x31: /* TSTP immed */
3095 state
->Cpsr
= GETSPSR (state
->Bank
);
3096 ARMul_CPSRAltered (state
);
3098 temp
= LHS
& DPImmRHS
;
3107 ARMul_NegZero (state
, dest
);
3111 case 0x32: /* TEQ immed and MSR immed to CPSR */
3113 /* MSR immed to CPSR. */
3114 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
3116 else if (state
->is_v6
3117 && handle_v6_insn (state
, instr
))
3124 case 0x33: /* TEQP immed */
3129 state
->Cpsr
= GETSPSR (state
->Bank
);
3130 ARMul_CPSRAltered (state
);
3132 temp
= LHS
^ DPImmRHS
;
3138 DPSImmRHS
; /* TEQ immed */
3140 ARMul_NegZero (state
, dest
);
3144 case 0x34: /* MOVT immed */
3147 && handle_v6_insn (state
, instr
))
3151 dest
= BITS (0, 11);
3152 dest
|= (BITS (16, 19) << 12);
3153 DEST
|= (dest
<< 16);
3156 case 0x35: /* CMPP immed */
3161 state
->Cpsr
= GETSPSR (state
->Bank
);
3162 ARMul_CPSRAltered (state
);
3164 temp
= LHS
- DPImmRHS
;
3175 ARMul_NegZero (state
, dest
);
3177 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
3179 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
3180 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
3190 case 0x36: /* CMN immed and MSR immed to SPSR */
3192 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
3194 else if (state
->is_v6
3195 && handle_v6_insn (state
, instr
))
3202 case 0x37: /* CMNP immed. */
3207 state
->Cpsr
= GETSPSR (state
->Bank
);
3208 ARMul_CPSRAltered (state
);
3210 temp
= LHS
+ DPImmRHS
;
3221 ASSIGNZ (dest
== 0);
3222 if ((lhs
| rhs
) >> 30)
3224 /* Possible C,V,N to set. */
3225 ASSIGNN (NEG (dest
));
3226 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
3227 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
3238 case 0x38: /* ORR immed. */
3239 dest
= LHS
| DPImmRHS
;
3243 case 0x39: /* ORRS immed. */
3249 case 0x3a: /* MOV immed. */
3254 case 0x3b: /* MOVS immed. */
3259 case 0x3c: /* BIC immed. */
3260 dest
= LHS
& ~DPImmRHS
;
3264 case 0x3d: /* BICS immed. */
3270 case 0x3e: /* MVN immed. */
3275 case 0x3f: /* MVNS immed. */
3281 /* Single Data Transfer Immediate RHS Instructions. */
3283 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
3285 if (StoreWord (state
, instr
, lhs
))
3286 LSBase
= lhs
- LSImmRHS
;
3289 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
3291 if (LoadWord (state
, instr
, lhs
))
3292 LSBase
= lhs
- LSImmRHS
;
3295 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
3296 UNDEF_LSRBaseEQDestWb
;
3299 temp
= lhs
- LSImmRHS
;
3300 state
->NtransSig
= LOW
;
3301 if (StoreWord (state
, instr
, lhs
))
3303 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3306 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
3307 UNDEF_LSRBaseEQDestWb
;
3310 state
->NtransSig
= LOW
;
3311 if (LoadWord (state
, instr
, lhs
))
3312 LSBase
= lhs
- LSImmRHS
;
3313 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3316 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
3318 if (StoreByte (state
, instr
, lhs
))
3319 LSBase
= lhs
- LSImmRHS
;
3322 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
3324 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3325 LSBase
= lhs
- LSImmRHS
;
3328 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
3329 UNDEF_LSRBaseEQDestWb
;
3332 state
->NtransSig
= LOW
;
3333 if (StoreByte (state
, instr
, lhs
))
3334 LSBase
= lhs
- LSImmRHS
;
3335 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3338 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
3339 UNDEF_LSRBaseEQDestWb
;
3342 state
->NtransSig
= LOW
;
3343 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3344 LSBase
= lhs
- LSImmRHS
;
3345 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3348 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
3350 if (StoreWord (state
, instr
, lhs
))
3351 LSBase
= lhs
+ LSImmRHS
;
3354 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
3356 if (LoadWord (state
, instr
, lhs
))
3357 LSBase
= lhs
+ LSImmRHS
;
3360 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
3361 UNDEF_LSRBaseEQDestWb
;
3364 state
->NtransSig
= LOW
;
3365 if (StoreWord (state
, instr
, lhs
))
3366 LSBase
= lhs
+ LSImmRHS
;
3367 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3370 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
3371 UNDEF_LSRBaseEQDestWb
;
3374 state
->NtransSig
= LOW
;
3375 if (LoadWord (state
, instr
, lhs
))
3376 LSBase
= lhs
+ LSImmRHS
;
3377 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3380 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
3382 if (StoreByte (state
, instr
, lhs
))
3383 LSBase
= lhs
+ LSImmRHS
;
3386 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
3388 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3389 LSBase
= lhs
+ LSImmRHS
;
3392 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
3393 UNDEF_LSRBaseEQDestWb
;
3396 state
->NtransSig
= LOW
;
3397 if (StoreByte (state
, instr
, lhs
))
3398 LSBase
= lhs
+ LSImmRHS
;
3399 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3402 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
3403 UNDEF_LSRBaseEQDestWb
;
3406 state
->NtransSig
= LOW
;
3407 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3408 LSBase
= lhs
+ LSImmRHS
;
3409 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3413 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
3414 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
3417 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
3418 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
3421 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
3422 UNDEF_LSRBaseEQDestWb
;
3424 temp
= LHS
- LSImmRHS
;
3425 if (StoreWord (state
, instr
, temp
))
3429 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
3430 UNDEF_LSRBaseEQDestWb
;
3432 temp
= LHS
- LSImmRHS
;
3433 if (LoadWord (state
, instr
, temp
))
3437 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
3438 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
3441 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
3442 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
3445 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
3446 UNDEF_LSRBaseEQDestWb
;
3448 temp
= LHS
- LSImmRHS
;
3449 if (StoreByte (state
, instr
, temp
))
3453 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
3454 UNDEF_LSRBaseEQDestWb
;
3456 temp
= LHS
- LSImmRHS
;
3457 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3461 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
3462 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
3465 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
3466 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
3469 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
3470 UNDEF_LSRBaseEQDestWb
;
3472 temp
= LHS
+ LSImmRHS
;
3473 if (StoreWord (state
, instr
, temp
))
3477 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
3478 UNDEF_LSRBaseEQDestWb
;
3480 temp
= LHS
+ LSImmRHS
;
3481 if (LoadWord (state
, instr
, temp
))
3485 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
3486 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
3489 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
3490 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
3493 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
3494 UNDEF_LSRBaseEQDestWb
;
3496 temp
= LHS
+ LSImmRHS
;
3497 if (StoreByte (state
, instr
, temp
))
3501 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
3502 UNDEF_LSRBaseEQDestWb
;
3504 temp
= LHS
+ LSImmRHS
;
3505 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3510 /* Single Data Transfer Register RHS Instructions. */
3512 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
3517 && handle_v6_insn (state
, instr
))
3520 ARMul_UndefInstr (state
, instr
);
3523 UNDEF_LSRBaseEQOffWb
;
3524 UNDEF_LSRBaseEQDestWb
;
3528 if (StoreWord (state
, instr
, lhs
))
3529 LSBase
= lhs
- LSRegRHS
;
3532 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
3537 && handle_v6_insn (state
, instr
))
3540 ARMul_UndefInstr (state
, instr
);
3543 UNDEF_LSRBaseEQOffWb
;
3544 UNDEF_LSRBaseEQDestWb
;
3548 temp
= lhs
- LSRegRHS
;
3549 if (LoadWord (state
, instr
, lhs
))
3553 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
3558 && handle_v6_insn (state
, instr
))
3561 ARMul_UndefInstr (state
, instr
);
3564 UNDEF_LSRBaseEQOffWb
;
3565 UNDEF_LSRBaseEQDestWb
;
3569 state
->NtransSig
= LOW
;
3570 if (StoreWord (state
, instr
, lhs
))
3571 LSBase
= lhs
- LSRegRHS
;
3572 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3575 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
3580 && handle_v6_insn (state
, instr
))
3583 ARMul_UndefInstr (state
, instr
);
3586 UNDEF_LSRBaseEQOffWb
;
3587 UNDEF_LSRBaseEQDestWb
;
3591 temp
= lhs
- LSRegRHS
;
3592 state
->NtransSig
= LOW
;
3593 if (LoadWord (state
, instr
, lhs
))
3595 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3598 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
3603 && handle_v6_insn (state
, instr
))
3606 ARMul_UndefInstr (state
, instr
);
3609 UNDEF_LSRBaseEQOffWb
;
3610 UNDEF_LSRBaseEQDestWb
;
3614 if (StoreByte (state
, instr
, lhs
))
3615 LSBase
= lhs
- LSRegRHS
;
3618 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
3623 && handle_v6_insn (state
, instr
))
3626 ARMul_UndefInstr (state
, instr
);
3629 UNDEF_LSRBaseEQOffWb
;
3630 UNDEF_LSRBaseEQDestWb
;
3634 temp
= lhs
- LSRegRHS
;
3635 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3639 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
3644 && handle_v6_insn (state
, instr
))
3647 ARMul_UndefInstr (state
, instr
);
3650 UNDEF_LSRBaseEQOffWb
;
3651 UNDEF_LSRBaseEQDestWb
;
3655 state
->NtransSig
= LOW
;
3656 if (StoreByte (state
, instr
, lhs
))
3657 LSBase
= lhs
- LSRegRHS
;
3658 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3661 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
3666 && handle_v6_insn (state
, instr
))
3669 ARMul_UndefInstr (state
, instr
);
3672 UNDEF_LSRBaseEQOffWb
;
3673 UNDEF_LSRBaseEQDestWb
;
3677 temp
= lhs
- LSRegRHS
;
3678 state
->NtransSig
= LOW
;
3679 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3681 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3684 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
3689 && handle_v6_insn (state
, instr
))
3692 ARMul_UndefInstr (state
, instr
);
3695 UNDEF_LSRBaseEQOffWb
;
3696 UNDEF_LSRBaseEQDestWb
;
3700 if (StoreWord (state
, instr
, lhs
))
3701 LSBase
= lhs
+ LSRegRHS
;
3704 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
3709 && handle_v6_insn (state
, instr
))
3712 ARMul_UndefInstr (state
, instr
);
3715 UNDEF_LSRBaseEQOffWb
;
3716 UNDEF_LSRBaseEQDestWb
;
3720 temp
= lhs
+ LSRegRHS
;
3721 if (LoadWord (state
, instr
, lhs
))
3725 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
3730 && handle_v6_insn (state
, instr
))
3733 ARMul_UndefInstr (state
, instr
);
3736 UNDEF_LSRBaseEQOffWb
;
3737 UNDEF_LSRBaseEQDestWb
;
3741 state
->NtransSig
= LOW
;
3742 if (StoreWord (state
, instr
, lhs
))
3743 LSBase
= lhs
+ LSRegRHS
;
3744 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3747 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
3752 && handle_v6_insn (state
, instr
))
3755 ARMul_UndefInstr (state
, instr
);
3758 UNDEF_LSRBaseEQOffWb
;
3759 UNDEF_LSRBaseEQDestWb
;
3763 temp
= lhs
+ LSRegRHS
;
3764 state
->NtransSig
= LOW
;
3765 if (LoadWord (state
, instr
, lhs
))
3767 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3770 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
3775 && handle_v6_insn (state
, instr
))
3778 ARMul_UndefInstr (state
, instr
);
3781 UNDEF_LSRBaseEQOffWb
;
3782 UNDEF_LSRBaseEQDestWb
;
3786 if (StoreByte (state
, instr
, lhs
))
3787 LSBase
= lhs
+ LSRegRHS
;
3790 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
3795 && handle_v6_insn (state
, instr
))
3798 ARMul_UndefInstr (state
, instr
);
3801 UNDEF_LSRBaseEQOffWb
;
3802 UNDEF_LSRBaseEQDestWb
;
3806 temp
= lhs
+ LSRegRHS
;
3807 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3811 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
3816 && handle_v6_insn (state
, instr
))
3819 ARMul_UndefInstr (state
, instr
);
3822 UNDEF_LSRBaseEQOffWb
;
3823 UNDEF_LSRBaseEQDestWb
;
3827 state
->NtransSig
= LOW
;
3828 if (StoreByte (state
, instr
, lhs
))
3829 LSBase
= lhs
+ LSRegRHS
;
3830 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3833 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
3838 && handle_v6_insn (state
, instr
))
3841 ARMul_UndefInstr (state
, instr
);
3844 UNDEF_LSRBaseEQOffWb
;
3845 UNDEF_LSRBaseEQDestWb
;
3849 temp
= lhs
+ LSRegRHS
;
3850 state
->NtransSig
= LOW
;
3851 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
3853 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
3857 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
3862 && handle_v6_insn (state
, instr
))
3865 ARMul_UndefInstr (state
, instr
);
3868 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
3871 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
3876 && handle_v6_insn (state
, instr
))
3879 ARMul_UndefInstr (state
, instr
);
3882 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
3885 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
3890 && handle_v6_insn (state
, instr
))
3893 ARMul_UndefInstr (state
, instr
);
3896 UNDEF_LSRBaseEQOffWb
;
3897 UNDEF_LSRBaseEQDestWb
;
3900 temp
= LHS
- LSRegRHS
;
3901 if (StoreWord (state
, instr
, temp
))
3905 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
3910 && handle_v6_insn (state
, instr
))
3913 ARMul_UndefInstr (state
, instr
);
3916 UNDEF_LSRBaseEQOffWb
;
3917 UNDEF_LSRBaseEQDestWb
;
3920 temp
= LHS
- LSRegRHS
;
3921 if (LoadWord (state
, instr
, temp
))
3925 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
3930 && handle_v6_insn (state
, instr
))
3933 ARMul_UndefInstr (state
, instr
);
3936 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
3939 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
3944 && handle_v6_insn (state
, instr
))
3947 ARMul_UndefInstr (state
, instr
);
3950 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
3953 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
3958 && handle_v6_insn (state
, instr
))
3961 ARMul_UndefInstr (state
, instr
);
3964 UNDEF_LSRBaseEQOffWb
;
3965 UNDEF_LSRBaseEQDestWb
;
3968 temp
= LHS
- LSRegRHS
;
3969 if (StoreByte (state
, instr
, temp
))
3973 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
3978 && handle_v6_insn (state
, instr
))
3981 ARMul_UndefInstr (state
, instr
);
3984 UNDEF_LSRBaseEQOffWb
;
3985 UNDEF_LSRBaseEQDestWb
;
3988 temp
= LHS
- LSRegRHS
;
3989 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
3993 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
3998 && handle_v6_insn (state
, instr
))
4001 ARMul_UndefInstr (state
, instr
);
4004 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
4007 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
4012 && handle_v6_insn (state
, instr
))
4015 ARMul_UndefInstr (state
, instr
);
4018 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
4021 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
4026 && handle_v6_insn (state
, instr
))
4029 ARMul_UndefInstr (state
, instr
);
4032 UNDEF_LSRBaseEQOffWb
;
4033 UNDEF_LSRBaseEQDestWb
;
4036 temp
= LHS
+ LSRegRHS
;
4037 if (StoreWord (state
, instr
, temp
))
4041 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
4046 && handle_v6_insn (state
, instr
))
4049 ARMul_UndefInstr (state
, instr
);
4052 UNDEF_LSRBaseEQOffWb
;
4053 UNDEF_LSRBaseEQDestWb
;
4056 temp
= LHS
+ LSRegRHS
;
4057 if (LoadWord (state
, instr
, temp
))
4061 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
4066 && handle_v6_insn (state
, instr
))
4069 ARMul_UndefInstr (state
, instr
);
4072 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
4075 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
4080 && handle_v6_insn (state
, instr
))
4083 ARMul_UndefInstr (state
, instr
);
4086 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
4089 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
4094 && handle_v6_insn (state
, instr
))
4097 ARMul_UndefInstr (state
, instr
);
4100 UNDEF_LSRBaseEQOffWb
;
4101 UNDEF_LSRBaseEQDestWb
;
4104 temp
= LHS
+ LSRegRHS
;
4105 if (StoreByte (state
, instr
, temp
))
4109 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
4112 /* Check for the special breakpoint opcode.
4113 This value should correspond to the value defined
4114 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
4115 if (BITS (0, 19) == 0xfdefe)
4117 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
4118 ARMul_Abort (state
, ARMul_SWIV
);
4121 else if (state
->is_v6
4122 && handle_v6_insn (state
, instr
))
4126 ARMul_UndefInstr (state
, instr
);
4129 UNDEF_LSRBaseEQOffWb
;
4130 UNDEF_LSRBaseEQDestWb
;
4133 temp
= LHS
+ LSRegRHS
;
4134 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
4139 /* Multiple Data Transfer Instructions. */
4141 case 0x80: /* Store, No WriteBack, Post Dec. */
4142 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4145 case 0x81: /* Load, No WriteBack, Post Dec. */
4146 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4149 case 0x82: /* Store, WriteBack, Post Dec. */
4150 temp
= LSBase
- LSMNumRegs
;
4151 STOREMULT (instr
, temp
+ 4L, temp
);
4154 case 0x83: /* Load, WriteBack, Post Dec. */
4155 temp
= LSBase
- LSMNumRegs
;
4156 LOADMULT (instr
, temp
+ 4L, temp
);
4159 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
4160 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4163 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
4164 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
4167 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
4168 temp
= LSBase
- LSMNumRegs
;
4169 STORESMULT (instr
, temp
+ 4L, temp
);
4172 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
4173 temp
= LSBase
- LSMNumRegs
;
4174 LOADSMULT (instr
, temp
+ 4L, temp
);
4177 case 0x88: /* Store, No WriteBack, Post Inc. */
4178 STOREMULT (instr
, LSBase
, 0L);
4181 case 0x89: /* Load, No WriteBack, Post Inc. */
4182 LOADMULT (instr
, LSBase
, 0L);
4185 case 0x8a: /* Store, WriteBack, Post Inc. */
4187 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
4190 case 0x8b: /* Load, WriteBack, Post Inc. */
4192 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
4195 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
4196 STORESMULT (instr
, LSBase
, 0L);
4199 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
4200 LOADSMULT (instr
, LSBase
, 0L);
4203 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
4205 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
4208 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
4210 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
4213 case 0x90: /* Store, No WriteBack, Pre Dec. */
4214 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4217 case 0x91: /* Load, No WriteBack, Pre Dec. */
4218 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4221 case 0x92: /* Store, WriteBack, Pre Dec. */
4222 temp
= LSBase
- LSMNumRegs
;
4223 STOREMULT (instr
, temp
, temp
);
4226 case 0x93: /* Load, WriteBack, Pre Dec. */
4227 temp
= LSBase
- LSMNumRegs
;
4228 LOADMULT (instr
, temp
, temp
);
4231 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
4232 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4235 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
4236 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
4239 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
4240 temp
= LSBase
- LSMNumRegs
;
4241 STORESMULT (instr
, temp
, temp
);
4244 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
4245 temp
= LSBase
- LSMNumRegs
;
4246 LOADSMULT (instr
, temp
, temp
);
4249 case 0x98: /* Store, No WriteBack, Pre Inc. */
4250 STOREMULT (instr
, LSBase
+ 4L, 0L);
4253 case 0x99: /* Load, No WriteBack, Pre Inc. */
4254 LOADMULT (instr
, LSBase
+ 4L, 0L);
4257 case 0x9a: /* Store, WriteBack, Pre Inc. */
4259 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4262 case 0x9b: /* Load, WriteBack, Pre Inc. */
4264 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4267 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
4268 STORESMULT (instr
, LSBase
+ 4L, 0L);
4271 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
4272 LOADSMULT (instr
, LSBase
+ 4L, 0L);
4275 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
4277 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4280 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
4282 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
4286 /* Branch forward. */
4295 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4300 /* Branch backward. */
4309 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4313 /* Branch and Link forward. */
4322 /* Put PC into Link. */
4324 state
->Reg
[14] = pc
+ 4;
4326 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4328 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
4331 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4334 /* Branch and Link backward. */
4343 /* Put PC into Link. */
4345 state
->Reg
[14] = pc
+ 4;
4347 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
;
4349 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
4352 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
4355 /* Co-Processor Data Transfers. */
4359 if (CPNum
== 10 || CPNum
== 11)
4360 handle_VFP_move (state
, instr
);
4361 /* Reading from R15 is UNPREDICTABLE. */
4362 else if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
4363 ARMul_UndefInstr (state
, instr
);
4364 /* Is access to coprocessor 0 allowed ? */
4365 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4366 ARMul_UndefInstr (state
, instr
);
4367 /* Special treatment for XScale coprocessors. */
4368 else if (state
->is_XScale
)
4370 /* Only opcode 0 is supported. */
4371 if (BITS (4, 7) != 0x00)
4372 ARMul_UndefInstr (state
, instr
);
4373 /* Only coporcessor 0 is supported. */
4374 else if (CPNum
!= 0x00)
4375 ARMul_UndefInstr (state
, instr
);
4376 /* Only accumulator 0 is supported. */
4377 else if (BITS (0, 3) != 0x00)
4378 ARMul_UndefInstr (state
, instr
);
4381 /* XScale MAR insn. Move two registers into accumulator. */
4382 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
4383 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
4387 /* FIXME: Not sure what to do for other v5 processors. */
4388 ARMul_UndefInstr (state
, instr
);
4393 case 0xc0: /* Store , No WriteBack , Post Dec. */
4394 ARMul_STC (state
, instr
, LHS
);
4400 if (CPNum
== 10 || CPNum
== 11)
4401 handle_VFP_move (state
, instr
);
4402 /* Writes to R15 are UNPREDICATABLE. */
4403 else if (DESTReg
== 15 || LHSReg
== 15)
4404 ARMul_UndefInstr (state
, instr
);
4405 /* Is access to the coprocessor allowed ? */
4406 else if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4407 ARMul_UndefInstr (state
, instr
);
4408 /* Special handling for XScale coprcoessors. */
4409 else if (state
->is_XScale
)
4411 /* Only opcode 0 is supported. */
4412 if (BITS (4, 7) != 0x00)
4413 ARMul_UndefInstr (state
, instr
);
4414 /* Only coprocessor 0 is supported. */
4415 else if (CPNum
!= 0x00)
4416 ARMul_UndefInstr (state
, instr
);
4417 /* Only accumulator 0 is supported. */
4418 else if (BITS (0, 3) != 0x00)
4419 ARMul_UndefInstr (state
, instr
);
4422 /* XScale MRA insn. Move accumulator into two registers. */
4423 ARMword t1
= (state
->Accumulator
>> 32) & 255;
4428 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
4429 state
->Reg
[BITS (16, 19)] = t1
;
4434 /* FIXME: Not sure what to do for other v5 processors. */
4435 ARMul_UndefInstr (state
, instr
);
4440 case 0xc1: /* Load , No WriteBack , Post Dec. */
4441 ARMul_LDC (state
, instr
, LHS
);
4445 case 0xc6: /* Store , WriteBack , Post Dec. */
4447 state
->Base
= lhs
- LSCOff
;
4448 ARMul_STC (state
, instr
, lhs
);
4452 case 0xc7: /* Load , WriteBack , Post Dec. */
4454 state
->Base
= lhs
- LSCOff
;
4455 ARMul_LDC (state
, instr
, lhs
);
4459 case 0xcc: /* Store , No WriteBack , Post Inc. */
4460 ARMul_STC (state
, instr
, LHS
);
4464 case 0xcd: /* Load , No WriteBack , Post Inc. */
4465 ARMul_LDC (state
, instr
, LHS
);
4469 case 0xce: /* Store , WriteBack , Post Inc. */
4471 state
->Base
= lhs
+ LSCOff
;
4472 ARMul_STC (state
, instr
, LHS
);
4476 case 0xcf: /* Load , WriteBack , Post Inc. */
4478 state
->Base
= lhs
+ LSCOff
;
4479 ARMul_LDC (state
, instr
, LHS
);
4483 case 0xd4: /* Store , No WriteBack , Pre Dec. */
4484 ARMul_STC (state
, instr
, LHS
- LSCOff
);
4488 case 0xd5: /* Load , No WriteBack , Pre Dec. */
4489 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
4493 case 0xd6: /* Store , WriteBack , Pre Dec. */
4496 ARMul_STC (state
, instr
, lhs
);
4500 case 0xd7: /* Load , WriteBack , Pre Dec. */
4503 ARMul_LDC (state
, instr
, lhs
);
4507 case 0xdc: /* Store , No WriteBack , Pre Inc. */
4508 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
4512 case 0xdd: /* Load , No WriteBack , Pre Inc. */
4513 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
4517 case 0xde: /* Store , WriteBack , Pre Inc. */
4520 ARMul_STC (state
, instr
, lhs
);
4524 case 0xdf: /* Load , WriteBack , Pre Inc. */
4527 ARMul_LDC (state
, instr
, lhs
);
4531 /* Co-Processor Register Transfers (MCR) and Data Ops. */
4534 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
4536 ARMul_UndefInstr (state
, instr
);
4539 if (state
->is_XScale
)
4540 switch (BITS (18, 19))
4543 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4545 /* XScale MIA instruction. Signed multiplication of
4546 two 32 bit values and addition to 40 bit accumulator. */
4547 ARMsdword Rm
= state
->Reg
[MULLHSReg
];
4548 ARMsdword Rs
= state
->Reg
[MULACCReg
];
4554 state
->Accumulator
+= Rm
* Rs
;
4560 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
4562 /* XScale MIAPH instruction. */
4563 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
4564 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
4565 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
4566 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
4581 state
->Accumulator
+= t5
;
4586 state
->Accumulator
+= t5
;
4592 if (BITS (4, 11) == 1)
4594 /* XScale MIAxy instruction. */
4600 t1
= state
->Reg
[MULLHSReg
] >> 16;
4602 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
4605 t2
= state
->Reg
[MULACCReg
] >> 16;
4607 t2
= state
->Reg
[MULACCReg
] & 0xffff;
4617 state
->Accumulator
+= t5
;
4636 if (CPNum
== 10 || CPNum
== 11)
4637 handle_VFP_move (state
, instr
);
4639 else if (DESTReg
== 15)
4643 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
4645 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
4646 ((state
->Reg
[15] + isize
) & R15PCBITS
));
4650 ARMul_MCR (state
, instr
, DEST
);
4654 ARMul_CDP (state
, instr
);
4658 /* Co-Processor Register Transfers (MRC) and Data Ops. */
4669 if (CPNum
== 10 || CPNum
== 11)
4671 switch (BITS (20, 27))
4674 if (BITS (16, 19) == 0x1
4675 && BITS (0, 11) == 0xA10)
4680 ARMul_SetCPSR (state
, (state
->FPSCR
& 0xF0000000)
4681 | (ARMul_GetCPSR (state
) & 0x0FFFFFFF));
4684 fprintf (stderr
, " VFP: VMRS: set flags to %c%c%c%c\n",
4685 ARMul_GetCPSR (state
) & NBIT
? 'N' : '-',
4686 ARMul_GetCPSR (state
) & ZBIT
? 'Z' : '-',
4687 ARMul_GetCPSR (state
) & CBIT
? 'C' : '-',
4688 ARMul_GetCPSR (state
) & VBIT
? 'V' : '-');
4692 state
->Reg
[DESTReg
] = state
->FPSCR
;
4695 fprintf (stderr
, " VFP: VMRS: r%d = %x\n", DESTReg
, state
->Reg
[DESTReg
]);
4699 fprintf (stderr
, "SIM: VFP: Unimplemented: Compare op\n");
4704 /* VMOV reg <-> single precision. */
4705 if (BITS (0,6) != 0x10 || BITS (8,11) != 0xA)
4706 fprintf (stderr
, "SIM: VFP: Unimplemented: move op\n");
4708 state
->Reg
[BITS (12, 15)] = VFP_uword (BITS (16, 19) << 1 | BIT (7));
4710 VFP_uword (BITS (16, 19) << 1 | BIT (7)) = state
->Reg
[BITS (12, 15)];
4714 fprintf (stderr
, "SIM: VFP: Unimplemented: CDP op\n");
4721 temp
= ARMul_MRC (state
, instr
);
4724 ASSIGNN ((temp
& NBIT
) != 0);
4725 ASSIGNZ ((temp
& ZBIT
) != 0);
4726 ASSIGNC ((temp
& CBIT
) != 0);
4727 ASSIGNV ((temp
& VBIT
) != 0);
4735 ARMul_CDP (state
, instr
);
4739 /* SWI instruction. */
4756 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
4758 /* A prefetch abort. */
4759 XScale_set_fsr_far (state
, ARMul_CP15_R5_MMU_EXCPT
, pc
);
4760 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
4764 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
4765 ARMul_Abort (state
, ARMul_SWIV
);
4775 if (state
->Emulate
== ONCE
)
4776 state
->Emulate
= STOP
;
4777 /* If we have changed mode, allow the PC to advance before stopping. */
4778 else if (state
->Emulate
== CHANGEMODE
)
4780 else if (state
->Emulate
!= RUN
)
4783 while (!stop_simulator
);
4785 state
->decoded
= decoded
;
4786 state
->loaded
= loaded
;
4792 /* This routine evaluates most Data Processing register RHS's with the S
4793 bit clear. It is intended to be called from the macro DPRegRHS, which
4794 filters the common case of an unshifted register with in line code. */
4797 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
4799 ARMword shamt
, base
;
4804 /* Shift amount in a register. */
4809 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4812 base
= state
->Reg
[base
];
4813 ARMul_Icycles (state
, 1, 0L);
4814 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4815 switch ((int) BITS (5, 6))
4820 else if (shamt
>= 32)
4823 return (base
<< shamt
);
4827 else if (shamt
>= 32)
4830 return (base
>> shamt
);
4834 else if (shamt
>= 32)
4835 return ((ARMword
) ((ARMsword
) base
>> 31L));
4837 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4843 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4848 /* Shift amount is a constant. */
4851 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4854 base
= state
->Reg
[base
];
4855 shamt
= BITS (7, 11);
4856 switch ((int) BITS (5, 6))
4859 return (base
<< shamt
);
4864 return (base
>> shamt
);
4867 return ((ARMword
) ((ARMsword
) base
>> 31L));
4869 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4873 return ((base
>> 1) | (CFLAG
<< 31));
4875 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4882 /* This routine evaluates most Logical Data Processing register RHS's
4883 with the S bit set. It is intended to be called from the macro
4884 DPSRegRHS, which filters the common case of an unshifted register
4885 with in line code. */
4888 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
4890 ARMword shamt
, base
;
4895 /* Shift amount in a register. */
4900 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4903 base
= state
->Reg
[base
];
4904 ARMul_Icycles (state
, 1, 0L);
4905 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
4906 switch ((int) BITS (5, 6))
4911 else if (shamt
== 32)
4916 else if (shamt
> 32)
4923 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4924 return (base
<< shamt
);
4929 else if (shamt
== 32)
4931 ASSIGNC (base
>> 31);
4934 else if (shamt
> 32)
4941 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4942 return (base
>> shamt
);
4947 else if (shamt
>= 32)
4949 ASSIGNC (base
>> 31L);
4950 return ((ARMword
) ((ARMsword
) base
>> 31L));
4954 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
4955 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
4963 ASSIGNC (base
>> 31);
4968 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4969 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
4975 /* Shift amount is a constant. */
4978 base
= ECC
| ER15INT
| R15PC
| EMODE
;
4981 base
= state
->Reg
[base
];
4982 shamt
= BITS (7, 11);
4984 switch ((int) BITS (5, 6))
4987 ASSIGNC ((base
>> (32 - shamt
)) & 1);
4988 return (base
<< shamt
);
4992 ASSIGNC (base
>> 31);
4997 ASSIGNC ((base
>> (shamt
- 1)) & 1);
4998 return (base
>> shamt
);
5003 ASSIGNC (base
>> 31L);
5004 return ((ARMword
) ((ARMsword
) base
>> 31L));
5008 ASSIGNC ((ARMword
) ((ARMsword
) base
>> (int) (shamt
- 1)) & 1);
5009 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
5017 return ((base
>> 1) | (shamt
<< 31));
5021 ASSIGNC ((base
>> (shamt
- 1)) & 1);
5022 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
5030 /* This routine handles writes to register 15 when the S bit is not set. */
5033 WriteR15 (ARMul_State
* state
, ARMword src
)
5035 /* The ARM documentation states that the two least significant bits
5036 are discarded when setting PC, except in the cases handled by
5037 WriteR15Branch() below. It's probably an oversight: in THUMB
5038 mode, the second least significant bit should probably not be
5048 state
->Reg
[15] = src
& PCBITS
;
5050 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
5051 ARMul_R15Altered (state
);
5056 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5059 /* This routine handles writes to register 15 when the S bit is set. */
5062 WriteSR15 (ARMul_State
* state
, ARMword src
)
5065 if (state
->Bank
> 0)
5067 state
->Cpsr
= state
->Spsr
[state
->Bank
];
5068 ARMul_CPSRAltered (state
);
5076 state
->Reg
[15] = src
& PCBITS
;
5080 /* ARMul_R15Altered would have to support it. */
5086 if (state
->Bank
== USERBANK
)
5087 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
5089 state
->Reg
[15] = src
;
5091 ARMul_R15Altered (state
);
5095 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5098 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
5099 will switch to Thumb mode if the least significant bit is set. */
5102 WriteR15Branch (ARMul_State
* state
, ARMword src
)
5109 state
->Reg
[15] = src
& 0xfffffffe;
5114 state
->Reg
[15] = src
& 0xfffffffc;
5118 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
5120 WriteR15 (state
, src
);
5124 /* Before ARM_v5 LDR and LDM of pc did not change mode. */
5127 WriteR15Load (ARMul_State
* state
, ARMword src
)
5130 WriteR15Branch (state
, src
);
5132 WriteR15 (state
, src
);
5135 /* This routine evaluates most Load and Store register RHS's. It is
5136 intended to be called from the macro LSRegRHS, which filters the
5137 common case of an unshifted register with in line code. */
5140 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
5142 ARMword shamt
, base
;
5147 /* Now forbidden, but ... */
5148 base
= ECC
| ER15INT
| R15PC
| EMODE
;
5151 base
= state
->Reg
[base
];
5153 shamt
= BITS (7, 11);
5154 switch ((int) BITS (5, 6))
5157 return (base
<< shamt
);
5162 return (base
>> shamt
);
5165 return ((ARMword
) ((ARMsword
) base
>> 31L));
5167 return ((ARMword
) ((ARMsword
) base
>> (int) shamt
));
5171 return ((base
>> 1) | (CFLAG
<< 31));
5173 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
5180 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
5183 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
5190 /* Now forbidden, but ... */
5191 return ECC
| ER15INT
| R15PC
| EMODE
;
5193 return state
->Reg
[RHSReg
];
5197 return BITS (0, 3) | (BITS (8, 11) << 4);
5200 /* This function does the work of loading a word for a LDR instruction. */
5203 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5209 if (ADDREXCEPT (address
))
5210 INTERNALABORT (address
);
5213 dest
= ARMul_LoadWordN (state
, address
);
5218 return state
->lateabtSig
;
5221 dest
= ARMul_Align (state
, address
, dest
);
5223 ARMul_Icycles (state
, 1, 0L);
5225 return (DESTReg
!= LHSReg
);
5229 /* This function does the work of loading a halfword. */
5232 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
5239 if (ADDREXCEPT (address
))
5240 INTERNALABORT (address
);
5242 dest
= ARMul_LoadHalfWord (state
, address
);
5246 return state
->lateabtSig
;
5250 if (dest
& 1 << (16 - 1))
5251 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
5254 ARMul_Icycles (state
, 1, 0L);
5255 return (DESTReg
!= LHSReg
);
5260 /* This function does the work of loading a byte for a LDRB instruction. */
5263 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
5269 if (ADDREXCEPT (address
))
5270 INTERNALABORT (address
);
5272 dest
= ARMul_LoadByte (state
, address
);
5276 return state
->lateabtSig
;
5280 if (dest
& 1 << (8 - 1))
5281 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
5284 ARMul_Icycles (state
, 1, 0L);
5286 return (DESTReg
!= LHSReg
);
5289 /* This function does the work of loading two words for a LDRD instruction. */
5292 Handle_Load_Double (ARMul_State
* state
, ARMword instr
)
5296 ARMword write_back
= BIT (21);
5297 ARMword immediate
= BIT (22);
5298 ARMword add_to_base
= BIT (23);
5299 ARMword pre_indexed
= BIT (24);
5309 /* If the writeback bit is set, the pre-index bit must be clear. */
5310 if (write_back
&& ! pre_indexed
)
5312 ARMul_UndefInstr (state
, instr
);
5316 /* Extract the base address register. */
5319 /* Extract the destination register and check it. */
5322 /* Destination register must be even. */
5324 /* Destination register cannot be LR. */
5325 || (dest_reg
== 14))
5327 ARMul_UndefInstr (state
, instr
);
5331 /* Compute the base address. */
5332 base
= state
->Reg
[addr_reg
];
5334 /* Compute the offset. */
5335 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5337 /* Compute the sum of the two. */
5339 sum
= base
+ offset
;
5341 sum
= base
- offset
;
5343 /* If this is a pre-indexed mode use the sum. */
5349 if (state
->is_v6
&& (addr
& 0x3) == 0)
5350 /* Word alignment is enough for v6. */
5352 /* The address must be aligned on a 8 byte boundary. */
5353 else if (addr
& 0x7)
5356 ARMul_DATAABORT (addr
);
5358 ARMul_UndefInstr (state
, instr
);
5363 /* For pre indexed or post indexed addressing modes,
5364 check that the destination registers do not overlap
5365 the address registers. */
5366 if ((! pre_indexed
|| write_back
)
5367 && ( addr_reg
== dest_reg
5368 || addr_reg
== dest_reg
+ 1))
5370 ARMul_UndefInstr (state
, instr
);
5374 /* Load the words. */
5375 value1
= ARMul_LoadWordN (state
, addr
);
5376 value2
= ARMul_LoadWordN (state
, addr
+ 4);
5378 /* Check for data aborts. */
5385 ARMul_Icycles (state
, 2, 0L);
5387 /* Store the values. */
5388 state
->Reg
[dest_reg
] = value1
;
5389 state
->Reg
[dest_reg
+ 1] = value2
;
5391 /* Do the post addressing and writeback. */
5395 if (! pre_indexed
|| write_back
)
5396 state
->Reg
[addr_reg
] = addr
;
5399 /* This function does the work of storing two words for a STRD instruction. */
5402 Handle_Store_Double (ARMul_State
* state
, ARMword instr
)
5406 ARMword write_back
= BIT (21);
5407 ARMword immediate
= BIT (22);
5408 ARMword add_to_base
= BIT (23);
5409 ARMword pre_indexed
= BIT (24);
5417 /* If the writeback bit is set, the pre-index bit must be clear. */
5418 if (write_back
&& ! pre_indexed
)
5420 ARMul_UndefInstr (state
, instr
);
5424 /* Extract the base address register. */
5427 /* Base register cannot be PC. */
5430 ARMul_UndefInstr (state
, instr
);
5434 /* Extract the source register. */
5437 /* Source register must be even. */
5440 ARMul_UndefInstr (state
, instr
);
5444 /* Compute the base address. */
5445 base
= state
->Reg
[addr_reg
];
5447 /* Compute the offset. */
5448 offset
= immediate
? ((BITS (8, 11) << 4) | BITS (0, 3)) : state
->Reg
[RHSReg
];
5450 /* Compute the sum of the two. */
5452 sum
= base
+ offset
;
5454 sum
= base
- offset
;
5456 /* If this is a pre-indexed mode use the sum. */
5462 /* The address must be aligned on a 8 byte boundary. */
5463 if (state
->is_v6
&& (addr
& 0x3) == 0)
5464 /* Word alignment is enough for v6. */
5466 else if (addr
& 0x7)
5469 ARMul_DATAABORT (addr
);
5471 ARMul_UndefInstr (state
, instr
);
5476 /* For pre indexed or post indexed addressing modes,
5477 check that the destination registers do not overlap
5478 the address registers. */
5479 if ((! pre_indexed
|| write_back
)
5480 && ( addr_reg
== src_reg
5481 || addr_reg
== src_reg
+ 1))
5483 ARMul_UndefInstr (state
, instr
);
5487 /* Load the words. */
5488 ARMul_StoreWordN (state
, addr
, state
->Reg
[src_reg
]);
5489 ARMul_StoreWordN (state
, addr
+ 4, state
->Reg
[src_reg
+ 1]);
5497 /* Do the post addressing and writeback. */
5501 if (! pre_indexed
|| write_back
)
5502 state
->Reg
[addr_reg
] = addr
;
5505 /* This function does the work of storing a word from a STR instruction. */
5508 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5513 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5516 ARMul_StoreWordN (state
, address
, DEST
);
5518 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5520 INTERNALABORT (address
);
5521 (void) ARMul_LoadWordN (state
, address
);
5524 ARMul_StoreWordN (state
, address
, DEST
);
5529 return state
->lateabtSig
;
5535 /* This function does the work of storing a byte for a STRH instruction. */
5538 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
5544 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5548 ARMul_StoreHalfWord (state
, address
, DEST
);
5550 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5552 INTERNALABORT (address
);
5553 (void) ARMul_LoadHalfWord (state
, address
);
5556 ARMul_StoreHalfWord (state
, address
, DEST
);
5562 return state
->lateabtSig
;
5569 /* This function does the work of storing a byte for a STRB instruction. */
5572 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
5577 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
5580 ARMul_StoreByte (state
, address
, DEST
);
5582 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5584 INTERNALABORT (address
);
5585 (void) ARMul_LoadByte (state
, address
);
5588 ARMul_StoreByte (state
, address
, DEST
);
5593 return state
->lateabtSig
;
5599 /* This function does the work of loading the registers listed in an LDM
5600 instruction, when the S bit is clear. The code here is always increment
5601 after, it's up to the caller to get the input address correct and to
5602 handle base register modification. */
5605 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
5611 UNDEF_LSMBaseInListWb
;
5614 if (ADDREXCEPT (address
))
5615 INTERNALABORT (address
);
5617 if (BIT (21) && LHSReg
!= 15)
5620 /* N cycle first. */
5621 for (temp
= 0; !BIT (temp
); temp
++)
5624 dest
= ARMul_LoadWordN (state
, address
);
5626 if (!state
->abortSig
&& !state
->Aborted
)
5627 state
->Reg
[temp
++] = dest
;
5628 else if (!state
->Aborted
)
5630 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5631 state
->Aborted
= ARMul_DataAbortV
;
5634 /* S cycles from here on. */
5635 for (; temp
< 16; temp
++)
5638 /* Load this register. */
5640 dest
= ARMul_LoadWordS (state
, address
);
5642 if (!state
->abortSig
&& !state
->Aborted
)
5643 state
->Reg
[temp
] = dest
;
5644 else if (!state
->Aborted
)
5646 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5647 state
->Aborted
= ARMul_DataAbortV
;
5651 if (BIT (15) && !state
->Aborted
)
5652 /* PC is in the reg list. */
5653 WriteR15Load (state
, PC
);
5655 /* To write back the final register. */
5656 ARMul_Icycles (state
, 1, 0L);
5660 if (BIT (21) && LHSReg
!= 15)
5666 /* This function does the work of loading the registers listed in an LDM
5667 instruction, when the S bit is set. The code here is always increment
5668 after, it's up to the caller to get the input address correct and to
5669 handle base register modification. */
5672 LoadSMult (ARMul_State
* state
,
5681 UNDEF_LSMBaseInListWb
;
5686 if (ADDREXCEPT (address
))
5687 INTERNALABORT (address
);
5690 if (BIT (21) && LHSReg
!= 15)
5693 if (!BIT (15) && state
->Bank
!= USERBANK
)
5695 /* Temporary reg bank switch. */
5696 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5697 UNDEF_LSMUserBankWb
;
5700 /* N cycle first. */
5701 for (temp
= 0; !BIT (temp
); temp
++)
5704 dest
= ARMul_LoadWordN (state
, address
);
5706 if (!state
->abortSig
)
5707 state
->Reg
[temp
++] = dest
;
5708 else if (!state
->Aborted
)
5710 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5711 state
->Aborted
= ARMul_DataAbortV
;
5714 /* S cycles from here on. */
5715 for (; temp
< 16; temp
++)
5718 /* Load this register. */
5720 dest
= ARMul_LoadWordS (state
, address
);
5722 if (!state
->abortSig
&& !state
->Aborted
)
5723 state
->Reg
[temp
] = dest
;
5724 else if (!state
->Aborted
)
5726 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5727 state
->Aborted
= ARMul_DataAbortV
;
5731 if (BIT (15) && !state
->Aborted
)
5733 /* PC is in the reg list. */
5735 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5737 state
->Cpsr
= GETSPSR (state
->Bank
);
5738 ARMul_CPSRAltered (state
);
5741 WriteR15 (state
, PC
);
5743 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
5745 /* Protect bits in user mode. */
5746 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
5747 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
5748 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
5749 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
5752 ARMul_R15Altered (state
);
5758 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5759 /* Restore the correct bank. */
5760 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5762 /* To write back the final register. */
5763 ARMul_Icycles (state
, 1, 0L);
5767 if (BIT (21) && LHSReg
!= 15)
5774 /* This function does the work of storing the registers listed in an STM
5775 instruction, when the S bit is clear. The code here is always increment
5776 after, it's up to the caller to get the input address correct and to
5777 handle base register modification. */
5780 StoreMult (ARMul_State
* state
,
5789 UNDEF_LSMBaseInListWb
;
5792 /* N-cycle, increment the PC and update the NextInstr state. */
5796 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5797 INTERNALABORT (address
);
5803 /* N cycle first. */
5804 for (temp
= 0; !BIT (temp
); temp
++)
5808 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5812 (void) ARMul_LoadWordN (state
, address
);
5814 /* Fake the Stores as Loads. */
5815 for (; temp
< 16; temp
++)
5818 /* Save this register. */
5820 (void) ARMul_LoadWordS (state
, address
);
5823 if (BIT (21) && LHSReg
!= 15)
5829 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5832 if (state
->abortSig
&& !state
->Aborted
)
5834 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5835 state
->Aborted
= ARMul_DataAbortV
;
5838 if (BIT (21) && LHSReg
!= 15)
5841 /* S cycles from here on. */
5842 for (; temp
< 16; temp
++)
5845 /* Save this register. */
5848 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5850 if (state
->abortSig
&& !state
->Aborted
)
5852 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5853 state
->Aborted
= ARMul_DataAbortV
;
5861 /* This function does the work of storing the registers listed in an STM
5862 instruction when the S bit is set. The code here is always increment
5863 after, it's up to the caller to get the input address correct and to
5864 handle base register modification. */
5867 StoreSMult (ARMul_State
* state
,
5876 UNDEF_LSMBaseInListWb
;
5881 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
5882 INTERNALABORT (address
);
5888 if (state
->Bank
!= USERBANK
)
5890 /* Force User Bank. */
5891 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
);
5892 UNDEF_LSMUserBankWb
;
5895 for (temp
= 0; !BIT (temp
); temp
++)
5896 ; /* N cycle first. */
5899 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5903 (void) ARMul_LoadWordN (state
, address
);
5905 for (; temp
< 16; temp
++)
5906 /* Fake the Stores as Loads. */
5909 /* Save this register. */
5912 (void) ARMul_LoadWordS (state
, address
);
5915 if (BIT (21) && LHSReg
!= 15)
5922 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
5925 if (state
->abortSig
&& !state
->Aborted
)
5927 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5928 state
->Aborted
= ARMul_DataAbortV
;
5931 /* S cycles from here on. */
5932 for (; temp
< 16; temp
++)
5935 /* Save this register. */
5938 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
5940 if (state
->abortSig
&& !state
->Aborted
)
5942 XScale_set_fsr_far (state
, ARMul_CP15_R5_ST_ALIGN
, address
);
5943 state
->Aborted
= ARMul_DataAbortV
;
5947 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
5948 /* Restore the correct bank. */
5949 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
);
5951 if (BIT (21) && LHSReg
!= 15)
5958 /* This function does the work of adding two 32bit values
5959 together, and calculating if a carry has occurred. */
5962 Add32 (ARMword a1
, ARMword a2
, int *carry
)
5964 ARMword result
= (a1
+ a2
);
5965 unsigned int uresult
= (unsigned int) result
;
5966 unsigned int ua1
= (unsigned int) a1
;
5968 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
5969 or (result > RdLo) then we have no carry. */
5970 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
5978 /* This function does the work of multiplying
5979 two 32bit values to give a 64bit result. */
5982 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
5984 /* Operand register numbers. */
5985 int nRdHi
, nRdLo
, nRs
, nRm
;
5986 ARMword RdHi
= 0, RdLo
= 0, Rm
;
5990 nRdHi
= BITS (16, 19);
5991 nRdLo
= BITS (12, 15);
5995 /* Needed to calculate the cycle count. */
5996 Rm
= state
->Reg
[nRm
];
5998 /* Check for illegal operand combinations first. */
6005 /* Intermediate results. */
6006 ARMword lo
, mid1
, mid2
, hi
;
6008 ARMword Rs
= state
->Reg
[nRs
];
6016 /* BAD code can trigger this result. So only complain if debugging. */
6017 if (state
->Debug
&& (nRdHi
== nRm
|| nRdLo
== nRm
))
6018 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS: %d %d %d\n",
6022 /* Compute sign of result and adjust operands if necessary. */
6023 sign
= (Rm
^ Rs
) & 0x80000000;
6025 if (((ARMsword
) Rm
) < 0)
6028 if (((ARMsword
) Rs
) < 0)
6032 /* We can split the 32x32 into four 16x16 operations. This
6033 ensures that we do not lose precision on 32bit only hosts. */
6034 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
6035 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
6036 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
6037 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
6039 /* We now need to add all of these results together, taking
6040 care to propogate the carries from the additions. */
6041 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
6043 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
6045 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
6049 /* Negate result if necessary. */
6052 if (RdLo
== 0xFFFFFFFF)
6061 state
->Reg
[nRdLo
] = RdLo
;
6062 state
->Reg
[nRdHi
] = RdHi
;
6064 else if (state
->Debug
)
6065 fprintf (stderr
, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
6068 /* Ensure that both RdHi and RdLo are used to compute Z,
6069 but don't let RdLo's sign bit make it to N. */
6070 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6072 /* The cycle count depends on whether the instruction is a signed or
6073 unsigned multiply, and what bits are clear in the multiplier. */
6074 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
6075 /* Invert the bits to make the check against zero. */
6078 if ((Rm
& 0xFFFFFF00) == 0)
6080 else if ((Rm
& 0xFFFF0000) == 0)
6082 else if ((Rm
& 0xFF000000) == 0)
6090 /* This function does the work of multiplying two 32bit
6091 values and adding a 64bit value to give a 64bit result. */
6094 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
6101 nRdHi
= BITS (16, 19);
6102 nRdLo
= BITS (12, 15);
6104 RdHi
= state
->Reg
[nRdHi
];
6105 RdLo
= state
->Reg
[nRdLo
];
6107 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
6109 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
6110 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
6112 state
->Reg
[nRdLo
] = RdLo
;
6113 state
->Reg
[nRdHi
] = RdHi
;
6116 /* Ensure that both RdHi and RdLo are used to compute Z,
6117 but don't let RdLo's sign bit make it to N. */
6118 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
6120 /* Extra cycle for addition. */