1 /* thumbemu.c -- Thumb instruction emulation.
2 Copyright (C) 1996, Cygnus Software Technologies Ltd.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>. */
17 /* We can provide simple Thumb simulation by decoding the Thumb
18 instruction into its corresponding ARM instruction, and using the
19 existing ARM simulator. */
21 /* This must come before any other includes. */
24 #ifndef MODET /* required for the Thumb instruction support */
26 #error "MODET needs to be defined for the Thumb world to work"
36 #define tBIT(n) ( (ARMword)(tinstr >> (n)) & 1)
37 #define tBITS(m,n) ( (ARMword)(tinstr << (31 - (n))) >> ((31 - (n)) + (m)) )
39 #define ntBIT(n) ( (ARMword)(next_instr >> (n)) & 1)
40 #define ntBITS(m,n) ( (ARMword)(next_instr << (31 - (n))) >> ((31 - (n)) + (m)) )
43 test_cond (int cond
, ARMul_State
* state
)
47 case EQ
: return ZFLAG
;
48 case NE
: return !ZFLAG
;
49 case VS
: return VFLAG
;
50 case VC
: return !VFLAG
;
51 case MI
: return NFLAG
;
52 case PL
: return !NFLAG
;
53 case CS
: return CFLAG
;
54 case CC
: return !CFLAG
;
55 case HI
: return (CFLAG
&& !ZFLAG
);
56 case LS
: return (!CFLAG
|| ZFLAG
);
57 case GE
: return ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
58 case LT
: return ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
59 case GT
: return ((!NFLAG
&& !VFLAG
&& !ZFLAG
)
60 || (NFLAG
&& VFLAG
&& !ZFLAG
));
61 case LE
: return ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
64 default: return FALSE
;
68 static ARMword skipping_32bit_thumb
= 0;
70 static int IT_block_cond
= AL
;
71 static ARMword IT_block_mask
= 0;
72 static int IT_block_first
= FALSE
;
75 handle_IT_block (ARMul_State
* state
,
80 IT_block_mask
= tBITS (0, 3);
82 if (IT_block_mask
== 0)
86 IT_block_cond
= tBITS (4, 7);
87 IT_block_first
= TRUE
;
93 return IT_block_mask
!= 0;
97 IT_block_allow (ARMul_State
* state
)
101 if (IT_block_mask
== 0)
104 cond
= IT_block_cond
;
107 IT_block_first
= FALSE
;
110 if ((IT_block_mask
& 8) == 0)
115 IT_block_mask
&= 0xF;
118 if (IT_block_mask
== 0x8)
121 return test_cond (cond
, state
);
125 ThumbExpandImm (ARMword tinstr
)
129 if (tBITS (10, 11) == 0)
131 switch (tBITS (8, 9))
133 case 0: val
= tBITS (0, 7); break;
134 case 1: val
= tBITS (0, 7) << 8; break;
135 case 2: val
= (tBITS (0, 7) << 8) | (tBITS (0, 7) << 24); break;
136 case 3: val
= tBITS (0, 7) * 0x01010101; break;
142 int ror
= tBITS (7, 11);
144 val
= (1 << 7) | tBITS (0, 6);
145 val
= (val
>> ror
) | (val
<< (32 - ror
));
151 #define tASSERT(truth) \
156 fprintf (stderr, "unhandled T2 insn %04x|%04x detected at thumbemu.c:%d\n", \
157 tinstr, next_instr, __LINE__); \
164 /* Attempt to emulate a 32-bit ARMv7 Thumb instruction.
165 Stores t_branch into PVALUE upon success or t_undefined otherwise. */
168 handle_T2_insn (ARMul_State
* state
,
175 * pvalid
= t_undefined
;
181 fprintf (stderr
, "|%04x ", next_instr
);
183 if (tBITS (11, 15) == 0x1E && ntBIT (15) == 1)
189 switch ((ntBIT (14) << 1) | ntBIT (12))
193 ARMword cond
= tBITS (6, 9);
199 tASSERT (cond
!= AL
&& cond
!= NV
);
200 if (! test_cond (cond
, state
))
204 imm11
= ntBITS (0, 10);
208 simm32
= (J1
<< 19) | (J2
<< 18) | (imm6
<< 12) | (imm11
<< 1);
210 simm32
|= -(1 << 20);
216 ARMword imm10
= tBITS (0, 9);
217 ARMword imm11
= ntBITS (0, 10);
218 ARMword I1
= (ntBIT (13) ^ S
) ? 0 : 1;
219 ARMword I2
= (ntBIT (11) ^ S
) ? 0 : 1;
221 simm32
= (I1
<< 23) | (I2
<< 22) | (imm10
<< 12) | (imm11
<< 1);
223 simm32
|= -(1 << 24);
227 case 2: /* BLX <label> */
229 ARMword imm10h
= tBITS (0, 9);
230 ARMword imm10l
= ntBITS (1, 10);
231 ARMword I1
= (ntBIT (13) ^ S
) ? 0 : 1;
232 ARMword I2
= (ntBIT (11) ^ S
) ? 0 : 1;
234 simm32
= (I1
<< 23) | (I2
<< 22) | (imm10h
<< 12) | (imm10l
<< 2);
236 simm32
|= -(1 << 24);
239 state
->Reg
[14] = (pc
+ 4) | 1;
243 case 3: /* BL <label> */
245 ARMword imm10
= tBITS (0, 9);
246 ARMword imm11
= ntBITS (0, 10);
247 ARMword I1
= (ntBIT (13) ^ S
) ? 0 : 1;
248 ARMword I2
= (ntBIT (11) ^ S
) ? 0 : 1;
250 simm32
= (I1
<< 23) | (I2
<< 22) | (imm10
<< 12) | (imm11
<< 1);
252 simm32
|= -(1 << 24);
253 state
->Reg
[14] = (pc
+ 4) | 1;
258 state
->Reg
[15] = (pc
+ 4 + simm32
);
261 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
265 switch (tBITS (5,12))
267 case 0x29: // TST<c>.W <Rn>,<Rm>{,<shift>}
269 ARMword Rn
= tBITS (0, 3);
270 ARMword Rm
= ntBITS (0, 3);
271 ARMword type
= ntBITS (4, 5);
272 ARMword imm5
= (ntBITS (12, 14) << 2) | ntBITS (6, 7);
274 tASSERT (ntBITS (8, 11) == 0xF);
276 * ainstr
= 0xE1100000;
277 * ainstr
|= (Rn
<< 16);
279 * ainstr
|= (type
<< 5);
280 * ainstr
|= (imm5
<< 7);
281 * pvalid
= t_decoded
;
286 if (tBIT (4) && ntBITS (5, 15) == 0x780)
289 ARMword Rn
= tBITS (0, 3);
290 ARMword Rm
= ntBITS (0, 3);
291 ARMword address
, dest
;
296 address
= state
->Reg
[Rn
] + state
->Reg
[Rm
] * 2;
297 dest
= ARMul_LoadHalfWord (state
, address
);
302 address
= state
->Reg
[Rn
] + state
->Reg
[Rm
];
303 dest
= ARMul_LoadByte (state
, address
);
306 state
->Reg
[15] = (pc
+ 4 + dest
* 2);
311 ATTRIBUTE_FALLTHROUGH
;
320 ARMword Rn
= tBITS (0, 3);
321 ARMword Rt
= ntBITS (12, 15);
322 ARMword Rt2
= ntBITS (8, 11);
323 ARMword imm8
= ntBITS (0, 7);
324 ARMword P
= tBIT (8);
325 ARMword U
= tBIT (7);
326 ARMword W
= tBIT (5);
328 tASSERT (Rt2
== Rt
+ 1);
330 tASSERT (imm8
<= 255);
331 tASSERT (P
!= 0 || W
!= 0);
333 // Convert into an ARM A1 encoding.
336 tASSERT (tBIT (4) == 1);
338 // Ignore W even if 1.
339 * ainstr
= 0xE14F00D0;
345 * ainstr
= 0xE04000D0;
348 // STRD<c> <Rt>,<Rt2>,[<Rn>{,#+/-<imm8>}]
349 // STRD<c> <Rt>,<Rt2>,[<Rn>],#+/-<imm8>
350 // STRD<c> <Rt>,<Rt2>,[<Rn>,#+/-<imm8>]!
351 * ainstr
= 0xE04000F0;
353 * ainstr
|= (Rn
<< 16);
354 * ainstr
|= (P
<< 24);
355 * ainstr
|= (W
<< 21);
358 * ainstr
|= (U
<< 23);
359 * ainstr
|= (Rt
<< 12);
360 * ainstr
|= ((imm8
<< 4) & 0xF00);
361 * ainstr
|= (imm8
& 0xF);
362 * pvalid
= t_decoded
;
369 ARMword Rn
= tBITS (0, 3);
371 ARMword list
= (ntBIT (15) << 15) | (ntBIT (14) << 14) | ntBITS (0, 12);
374 * ainstr
= 0xE8BD0000;
377 * ainstr
= 0xE8900000;
378 * ainstr
|= (W
<< 21);
379 * ainstr
|= (Rn
<< 16);
382 * pvalid
= t_decoded
;
389 ARMword Rn
= tBITS (0, 3);
391 ARMword list
= (ntBIT (14) << 14) | ntBITS (0, 12);
394 * ainstr
= 0xE92D0000;
397 * ainstr
= 0xE9000000;
398 * ainstr
|= (W
<< 21);
399 * ainstr
|= (Rn
<< 16);
402 * pvalid
= t_decoded
;
408 ARMword Rd
= ntBITS (8, 11);
409 ARMword Rn
= tBITS (0, 3);
410 ARMword Rm
= ntBITS (0, 3);
411 ARMword imm5
= (ntBITS (12, 14) << 2) | ntBITS (6, 7);
412 ARMword type
= ntBITS (4, 5);
414 tASSERT (ntBIT (15) == 0);
418 tASSERT (tBIT (4) == 1);
420 // TST<c>.W <Rn>,<Rm>{,<shift>}
421 * ainstr
= 0xE1100000;
425 // AND{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
428 * ainstr
= 0xE0000000;
432 * ainstr
|= (S
<< 20);
435 * ainstr
|= (Rn
<< 16);
436 * ainstr
|= (imm5
<< 7);
437 * ainstr
|= (type
<< 5);
438 * ainstr
|= (Rm
<< 0);
439 * pvalid
= t_decoded
;
443 case 0x51: // BIC{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
445 ARMword Rn
= tBITS (0, 3);
447 ARMword Rm
= ntBITS (0, 3);
448 ARMword Rd
= ntBITS (8, 11);
449 ARMword imm5
= (ntBITS (12, 14) << 2) | ntBITS (6, 7);
450 ARMword type
= ntBITS (4, 5);
452 tASSERT (ntBIT (15) == 0);
454 * ainstr
= 0xE1C00000;
455 * ainstr
|= (S
<< 20);
456 * ainstr
|= (Rn
<< 16);
457 * ainstr
|= (Rd
<< 12);
458 * ainstr
|= (imm5
<< 7);
459 * ainstr
|= (type
<< 5);
460 * ainstr
|= (Rm
<< 0);
461 * pvalid
= t_decoded
;
467 ARMword Rn
= tBITS (0, 3);
468 ARMword Rd
= ntBITS (8, 11);
469 ARMword Rm
= ntBITS (0, 3);
471 ARMword imm5
= (ntBITS (12, 14) << 2) | ntBITS (6, 7);
472 ARMword type
= ntBITS (4, 5);
481 tASSERT (ntBIT (15) == 0);
483 switch (ntBITS (4, 5))
486 // LSL{S}<c>.W <Rd>,<Rm>,#<imm5>
487 * ainstr
= 0xE1A00000;
490 // LSR{S}<c>.W <Rd>,<Rm>,#<imm>
491 * ainstr
= 0xE1A00020;
494 // ASR{S}<c>.W <Rd>,<Rm>,#<imm>
495 * ainstr
= 0xE1A00040;
498 // ROR{S}<c> <Rd>,<Rm>,#<imm>
499 * ainstr
= 0xE1A00060;
508 // ORR{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
509 * ainstr
= 0xE1800000;
510 * ainstr
|= (Rn
<< 16);
511 * ainstr
|= (type
<< 5);
514 * ainstr
|= (Rd
<< 12);
515 * ainstr
|= (S
<< 20);
516 * ainstr
|= (imm5
<< 7);
517 * ainstr
|= (Rm
<< 0);
518 * pvalid
= t_decoded
;
522 case 0x53: // MVN{S}<c>.W <Rd>,<Rm>{,<shift>}
524 ARMword Rd
= ntBITS (8, 11);
525 ARMword Rm
= ntBITS (0, 3);
527 ARMword imm5
= (ntBITS (12, 14) << 2) | ntBITS (6, 7);
528 ARMword type
= ntBITS (4, 5);
530 tASSERT (ntBIT (15) == 0);
535 * ainstr
= 0xE1E00000;
536 * ainstr
|= (S
<< 20);
537 * ainstr
|= (Rd
<< 12);
538 * ainstr
|= (imm5
<< 7);
539 * ainstr
|= (type
<< 5);
540 * ainstr
|= (Rm
<< 0);
541 * pvalid
= t_decoded
;
547 ARMword Rn
= tBITS (0, 3);
548 ARMword Rd
= ntBITS (8, 11);
549 ARMword Rm
= ntBITS (0, 3);
551 ARMword imm5
= (ntBITS (12, 14) << 2) | ntBITS (6, 7);
552 ARMword type
= ntBITS (4, 5);
556 // TEQ<c> <Rn>,<Rm>{,<shift>}
557 tASSERT (ntBIT (15) == 0);
559 * ainstr
= 0xE1300000;
563 // EOR{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
567 * ainstr
= 0xE0200000;
568 * ainstr
|= (S
<< 20);
569 * ainstr
|= (Rd
<< 8);
572 * ainstr
|= (Rn
<< 16);
573 * ainstr
|= (imm5
<< 7);
574 * ainstr
|= (type
<< 5);
575 * ainstr
|= (Rm
<< 0);
576 * pvalid
= t_decoded
;
580 case 0x58: // ADD{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
582 ARMword Rn
= tBITS (0, 3);
583 ARMword Rd
= ntBITS (8, 11);
584 ARMword Rm
= ntBITS (0, 3);
586 ARMword imm5
= (ntBITS (12, 14) << 2) | ntBITS (6, 7);
587 ARMword type
= ntBITS (4, 5);
589 tASSERT (! (Rd
== 15 && S
));
594 * ainstr
= 0xE0800000;
595 * ainstr
|= (S
<< 20);
596 * ainstr
|= (Rn
<< 16);
597 * ainstr
|= (Rd
<< 12);
598 * ainstr
|= (imm5
<< 7);
599 * ainstr
|= (type
<< 5);
601 * pvalid
= t_decoded
;
605 case 0x5A: // ADC{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
606 tASSERT (ntBIT (15) == 0);
607 * ainstr
= 0xE0A00000;
608 if (! in_IT_block ())
609 * ainstr
|= (tBIT (4) << 20); // S
610 * ainstr
|= (tBITS (0, 3) << 16); // Rn
611 * ainstr
|= (ntBITS (8, 11) << 12); // Rd
612 * ainstr
|= ((ntBITS (12, 14) << 2) | ntBITS (6, 7)) << 7; // imm5
613 * ainstr
|= (ntBITS (4, 5) << 5); // type
614 * ainstr
|= ntBITS (0, 3); // Rm
615 * pvalid
= t_decoded
;
618 case 0x5B: // SBC{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
620 ARMword Rn
= tBITS (0, 3);
621 ARMword Rd
= ntBITS (8, 11);
622 ARMword Rm
= ntBITS (0, 3);
624 ARMword imm5
= (ntBITS (12, 14) << 2) | ntBITS (6, 7);
625 ARMword type
= ntBITS (4, 5);
627 tASSERT (ntBIT (15) == 0);
632 * ainstr
= 0xE0C00000;
633 * ainstr
|= (S
<< 20);
634 * ainstr
|= (Rn
<< 16);
635 * ainstr
|= (Rd
<< 12);
636 * ainstr
|= (imm5
<< 7);
637 * ainstr
|= (type
<< 5);
639 * pvalid
= t_decoded
;
643 case 0x5E: // RSB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}
644 case 0x5D: // SUB{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
646 ARMword Rn
= tBITS (0, 3);
647 ARMword Rd
= ntBITS (8, 11);
648 ARMword Rm
= ntBITS (0, 3);
649 ARMword S
= tBIT (4);
650 ARMword type
= ntBITS (4, 5);
651 ARMword imm5
= (ntBITS (12, 14) << 2) | ntBITS (6, 7);
653 tASSERT (ntBIT(15) == 0);
657 // CMP<c>.W <Rn>, <Rm> {,<shift>}
658 * ainstr
= 0xE1500000;
662 * ainstr
= 0xE0400000;
664 * ainstr
= 0xE0600000;
666 * ainstr
|= (S
<< 20);
667 * ainstr
|= (Rn
<< 16);
668 * ainstr
|= (Rd
<< 12);
669 * ainstr
|= (imm5
<< 7);
670 * ainstr
|= (type
<< 5);
671 * ainstr
|= (Rm
<< 0);
672 * pvalid
= t_decoded
;
677 tASSERT (tBITS (0, 15) == 0xF3AF);
678 tASSERT (ntBITS (0, 15) == 0x8000);
685 ARMword Rn
= tBITS (0, 3);
686 ARMword imm12
= (tBIT(10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
687 ARMword Rd
= ntBITS (8, 11);
691 imm12
= ThumbExpandImm (imm12
);
692 val
= state
->Reg
[Rn
] & imm12
;
696 // TST<c> <Rn>,#<const>
701 // AND{S}<c> <Rd>,<Rn>,#<const>
705 state
->Reg
[Rd
] = val
;
709 ARMul_NegZero (state
, val
);
717 ARMword Rn
= tBITS (0, 3);
718 ARMword Rd
= ntBITS (8, 11);
719 ARMword S
= tBIT (4);
720 ARMword imm8
= (ntBITS (12, 14) << 8) | ntBITS (0, 7);
722 tASSERT (ntBIT (15) == 0);
724 imm8
= ThumbExpandImm (imm8
);
725 state
->Reg
[Rd
] = state
->Reg
[Rn
] & ~ imm8
;
727 if (S
&& ! in_IT_block ())
728 ARMul_NegZero (state
, state
->Reg
[Rd
]);
729 * pvalid
= t_resolved
;
734 case 0x82: // MOV{S}<c>.W <Rd>,#<const>
736 ARMword val
= (tBIT(10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
737 ARMword Rd
= ntBITS (8, 11);
739 val
= ThumbExpandImm (val
);
740 state
->Reg
[Rd
] = val
;
742 if (tBIT (4) && ! in_IT_block ())
743 ARMul_NegZero (state
, val
);
744 /* Indicate that the instruction has been processed. */
750 case 0x83: // MVN{S}<c> <Rd>,#<const>
752 ARMword val
= (tBIT(10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
753 ARMword Rd
= ntBITS (8, 11);
755 val
= ThumbExpandImm (val
);
757 state
->Reg
[Rd
] = val
;
759 if (tBIT (4) && ! in_IT_block ())
760 ARMul_NegZero (state
, val
);
761 * pvalid
= t_resolved
;
768 ARMword Rn
= tBITS (0, 3);
769 ARMword Rd
= ntBITS (8, 11);
770 ARMword S
= tBIT (4);
771 ARMword imm12
= ((tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7));
774 imm12
= ThumbExpandImm (imm12
);
776 result
= state
->Reg
[Rn
] ^ imm12
;
779 // TEQ<c> <Rn>,#<const>
783 // EOR{S}<c> <Rd>,<Rn>,#<const>
784 state
->Reg
[Rd
] = result
;
791 ARMul_NegZero (state
, result
);
792 * pvalid
= t_resolved
;
799 ARMword Rd
= ntBITS (8, 11);
801 ARMword Rn
= tBITS (0, 3);
802 ARMword lhs
= state
->Reg
[Rn
];
803 ARMword imm12
= (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
804 ARMword rhs
= ThumbExpandImm (imm12
);
805 ARMword res
= lhs
+ rhs
;
809 // CMN<c> <Rn>,#<const>
814 // ADD{S}<c>.W <Rd>,<Rn>,#<const>
820 state
->Reg
[Rd
] = res
;
825 ARMul_NegZero (state
, res
);
827 if ((lhs
| rhs
) >> 30)
829 /* Possible C,V,N to set. */
830 ARMul_AddCarry (state
, lhs
, rhs
, res
);
831 ARMul_AddOverflow (state
, lhs
, rhs
, res
);
845 case 0x8A: // ADC{S}<c> <Rd>,<Rn>,#<const>
847 ARMword Rn
= tBITS (0, 3);
848 ARMword Rd
= ntBITS (8, 11);
850 ARMword imm12
= (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
851 ARMword lhs
= state
->Reg
[Rn
];
852 ARMword rhs
= ThumbExpandImm (imm12
);
855 tASSERT (ntBIT (15) == 0);
861 state
->Reg
[Rd
] = res
;
868 ARMul_NegZero (state
, res
);
870 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
872 ARMul_AddCarry (state
, lhs
, rhs
, res
);
873 ARMul_AddOverflow (state
, lhs
, rhs
, res
);
887 case 0x8B: // SBC{S}<c> <Rd>,<Rn>,#<const>
889 ARMword Rn
= tBITS (0, 3);
890 ARMword Rd
= ntBITS (8, 11);
892 ARMword imm12
= (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
893 ARMword lhs
= state
->Reg
[Rn
];
894 ARMword rhs
= ThumbExpandImm (imm12
);
897 tASSERT (ntBIT (15) == 0);
903 state
->Reg
[Rd
] = res
;
910 ARMul_NegZero (state
, res
);
912 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
914 ARMul_SubCarry (state
, lhs
, rhs
, res
);
915 ARMul_SubOverflow (state
, lhs
, rhs
, res
);
931 ARMword Rn
= tBITS (0, 3);
932 ARMword Rd
= ntBITS (8, 11);
934 ARMword imm12
= (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
935 ARMword lhs
= state
->Reg
[Rn
];
936 ARMword rhs
= ThumbExpandImm (imm12
);
937 ARMword res
= lhs
- rhs
;
941 // CMP<c>.W <Rn>,#<const>
946 // SUB{S}<c>.W <Rd>,<Rn>,#<const>
950 state
->Reg
[Rd
] = res
;
955 ARMul_NegZero (state
, res
);
957 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
959 ARMul_SubCarry (state
, lhs
, rhs
, res
);
960 ARMul_SubOverflow (state
, lhs
, rhs
, res
);
974 case 0x8E: // RSB{S}<c>.W <Rd>,<Rn>,#<const>
976 ARMword Rn
= tBITS (0, 3);
977 ARMword Rd
= ntBITS (8, 11);
978 ARMword imm12
= (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
981 ARMword rhs
= state
->Reg
[Rn
];
982 ARMword res
= lhs
- rhs
;
984 tASSERT (ntBIT (15) == 0);
986 state
->Reg
[Rd
] = res
;
990 ARMul_NegZero (state
, res
);
992 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
994 ARMul_SubCarry (state
, lhs
, rhs
, res
);
995 ARMul_SubOverflow (state
, lhs
, rhs
, res
);
1004 * pvalid
= t_branch
;
1009 case 0x90: // ADDW<c> <Rd>,<Rn>,#<imm12>
1011 ARMword Rn
= tBITS (0, 3);
1012 ARMword Rd
= ntBITS (8, 11);
1013 ARMword imm12
= (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
1015 tASSERT (tBIT (4) == 0);
1016 tASSERT (ntBIT (15) == 0);
1018 state
->Reg
[Rd
] = state
->Reg
[Rn
] + imm12
;
1019 * pvalid
= t_branch
;
1024 case 0x92: // MOVW<c> <Rd>,#<imm16>
1026 ARMword Rd
= ntBITS (8, 11);
1027 ARMword imm
= (tBITS (0, 3) << 12) | (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
1029 state
->Reg
[Rd
] = imm
;
1030 /* Indicate that the instruction has been processed. */
1031 * pvalid
= t_branch
;
1036 case 0x95:// SUBW<c> <Rd>,<Rn>,#<imm12>
1038 ARMword Rd
= ntBITS (8, 11);
1039 ARMword Rn
= tBITS (0, 3);
1040 ARMword imm12
= (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
1042 tASSERT (tBIT (4) == 0);
1043 tASSERT (ntBIT (15) == 0);
1045 /* Note the ARM ARM indicates special cases for Rn == 15 (ADR)
1046 and Rn == 13 (SUB SP minus immediate), but these are implemented
1047 in exactly the same way as the normal SUBW insn. */
1048 state
->Reg
[Rd
] = state
->Reg
[Rn
] - imm12
;
1050 * pvalid
= t_resolved
;
1055 case 0x96: // MOVT<c> <Rd>,#<imm16>
1057 ARMword Rd
= ntBITS (8, 11);
1058 ARMword imm
= (tBITS (0, 3) << 12) | (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
1060 state
->Reg
[Rd
] &= 0xFFFF;
1061 state
->Reg
[Rd
] |= (imm
<< 16);
1062 * pvalid
= t_resolved
;
1066 case 0x9A: // SBFXc> <Rd>,<Rn>,#<lsb>,#<width>
1067 tASSERT (tBIT (4) == 0);
1068 tASSERT (ntBIT (15) == 0);
1069 tASSERT (ntBIT (5) == 0);
1070 * ainstr
= 0xE7A00050;
1071 * ainstr
|= (ntBITS (0, 4) << 16); // widthm1
1072 * ainstr
|= (ntBITS (8, 11) << 12); // Rd
1073 * ainstr
|= (((ntBITS (12, 14) << 2) | ntBITS (6, 7)) << 7); // lsb
1074 * ainstr
|= tBITS (0, 3); // Rn
1075 * pvalid
= t_decoded
;
1080 ARMword Rd
= ntBITS (8, 11);
1081 ARMword Rn
= tBITS (0, 3);
1082 ARMword msbit
= ntBITS (0, 5);
1083 ARMword lsbit
= (ntBITS (12, 14) << 2) | ntBITS (6, 7);
1084 ARMword mask
= -(1 << lsbit
);
1086 tASSERT (tBIT (4) == 0);
1087 tASSERT (ntBIT (15) == 0);
1088 tASSERT (ntBIT (5) == 0);
1090 mask
&= ((1 << (msbit
+ 1)) - 1);
1096 // BFC<c> <Rd>,#<lsb>,#<width>
1097 state
->Reg
[Rd
] &= ~ mask
;
1101 // BFI<c> <Rd>,<Rn>,#<lsb>,#<width>
1102 ARMword val
= state
->Reg
[Rn
] & (mask
>> lsbit
);
1105 state
->Reg
[Rd
] &= ~ mask
;
1106 state
->Reg
[Rd
] |= val
;
1109 * pvalid
= t_resolved
;
1113 case 0x9E: // UBFXc> <Rd>,<Rn>,#<lsb>,#<width>
1114 tASSERT (tBIT (4) == 0);
1115 tASSERT (ntBIT (15) == 0);
1116 tASSERT (ntBIT (5) == 0);
1117 * ainstr
= 0xE7E00050;
1118 * ainstr
|= (ntBITS (0, 4) << 16); // widthm1
1119 * ainstr
|= (ntBITS (8, 11) << 12); // Rd
1120 * ainstr
|= (((ntBITS (12, 14) << 2) | ntBITS (6, 7)) << 7); // lsb
1121 * ainstr
|= tBITS (0, 3); // Rn
1122 * pvalid
= t_decoded
;
1128 ARMword Rn
= tBITS (0, 3);
1129 ARMword Rt
= ntBITS (12, 15);
1137 /* LDRB<c> <Rt>,<label> => 1111 1000 U001 1111 */
1138 * ainstr
= 0xE55F0000;
1139 * ainstr
|= (tBIT (7) << 23);
1140 * ainstr
|= ntBITS (0, 11);
1144 /* LDRB<c>.W <Rt>,[<Rn>{,#<imm12>}] => 1111 1000 1001 rrrr */
1145 * ainstr
= 0xE5D00000;
1146 * ainstr
|= ntBITS (0, 11);
1148 else if (ntBIT (11) == 0)
1150 /* LDRB<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}] => 1111 1000 0001 rrrr */
1151 * ainstr
= 0xE7D00000;
1152 * ainstr
|= (ntBITS (4, 5) << 7);
1153 * ainstr
|= ntBITS (0, 3);
1161 tASSERT (! (Rt
== 15 && P
&& !U
&& !W
));
1162 tASSERT (! (P
&& U
&& !W
));
1164 /* LDRB<c> <Rt>,[<Rn>,#-<imm8>] => 1111 1000 0001 rrrr
1165 LDRB<c> <Rt>,[<Rn>],#+/-<imm8> => 1111 1000 0001 rrrr
1166 LDRB<c> <Rt>,[<Rn>,#+/-<imm8>]! => 1111 1000 0001 rrrr */
1167 * ainstr
= 0xE4500000;
1168 * ainstr
|= (P
<< 24);
1169 * ainstr
|= (U
<< 23);
1170 * ainstr
|= (W
<< 21);
1171 * ainstr
|= ntBITS (0, 7);
1178 // STRB<c>.W <Rt>,[<Rn>,#<imm12>]
1179 ARMword imm12
= ntBITS (0, 11);
1181 ARMul_StoreByte (state
, state
->Reg
[Rn
] + imm12
, state
->Reg
[Rt
]);
1182 * pvalid
= t_branch
;
1185 else if (ntBIT (11))
1187 // STRB<c> <Rt>,[<Rn>,#-<imm8>]
1188 // STRB<c> <Rt>,[<Rn>],#+/-<imm8>
1189 // STRB<c> <Rt>,[<Rn>,#+/-<imm8>]!
1193 ARMword imm8
= ntBITS (0, 7);
1195 tASSERT (! (P
&& U
&& !W
));
1196 tASSERT (! (Rn
== 13 && P
&& !U
&& W
&& imm8
== 4));
1198 * ainstr
= 0xE4000000;
1199 * ainstr
|= (P
<< 24);
1200 * ainstr
|= (U
<< 23);
1201 * ainstr
|= (W
<< 21);
1206 // STRB<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1207 tASSERT (ntBITS (6, 11) == 0);
1209 * ainstr
= 0xE7C00000;
1210 * ainstr
|= (ntBITS (4, 5) << 7);
1211 * ainstr
|= ntBITS (0, 3);
1215 * ainstr
|= (Rn
<< 16);
1216 * ainstr
|= (Rt
<< 12);
1217 * pvalid
= t_decoded
;
1221 case 0xC2: // LDR, STR
1223 ARMword Rn
= tBITS (0, 3);
1224 ARMword Rt
= ntBITS (12, 15);
1225 ARMword imm8
= ntBITS (0, 7);
1226 ARMword P
= ntBIT (10);
1227 ARMword U
= ntBIT (9);
1228 ARMword W
= ntBIT (8);
1236 // LDR<c>.W <Rt>,<label>
1237 * ainstr
= 0xE51F0000;
1238 * ainstr
|= ntBITS (0, 11);
1240 else if (ntBIT (11))
1242 tASSERT (! (P
&& U
&& ! W
));
1243 tASSERT (! (!P
&& U
&& W
&& Rn
== 13 && imm8
== 4 && ntBIT (11) == 0));
1244 tASSERT (! (P
&& !U
&& W
&& Rn
== 13 && imm8
== 4 && ntBIT (11)));
1246 // LDR<c> <Rt>,[<Rn>,#-<imm8>]
1247 // LDR<c> <Rt>,[<Rn>],#+/-<imm8>
1248 // LDR<c> <Rt>,[<Rn>,#+/-<imm8>]!
1251 * ainstr
= 0xE4100000;
1252 * ainstr
|= (P
<< 24);
1253 * ainstr
|= (U
<< 23);
1254 * ainstr
|= (W
<< 21);
1259 // LDR<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1261 tASSERT (ntBITS (6, 11) == 0);
1263 * ainstr
= 0xE7900000;
1264 * ainstr
|= ntBITS (4, 5) << 7;
1265 * ainstr
|= ntBITS (0, 3);
1272 tASSERT (! (P
&& U
&& ! W
));
1273 if (Rn
== 13 && P
&& !U
&& W
&& imm8
== 4)
1275 // PUSH<c>.W <register>
1276 tASSERT (ntBITS (0, 11) == 0xD04);
1277 tASSERT (tBITS (0, 4) == 0x0D);
1279 * ainstr
= 0xE92D0000;
1280 * ainstr
|= (1 << Rt
);
1286 tASSERT (! (P
&& U
&& !W
));
1289 // STR<c> <Rt>,[<Rn>,#-<imm8>]
1290 // STR<c> <Rt>,[<Rn>],#+/-<imm8>
1291 // STR<c> <Rt>,[<Rn>,#+/-<imm8>]!
1292 * ainstr
= 0xE4000000;
1293 * ainstr
|= (P
<< 24);
1294 * ainstr
|= (U
<< 23);
1295 * ainstr
|= (W
<< 21);
1301 // STR<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1302 tASSERT (ntBITS (6, 11) == 0);
1304 * ainstr
= 0xE7800000;
1305 * ainstr
|= ntBITS (4, 5) << 7;
1306 * ainstr
|= ntBITS (0, 3);
1310 * ainstr
|= (Rn
<< 16);
1311 * ainstr
|= (Rt
<< 12);
1312 * pvalid
= t_decoded
;
1319 ARMword Rn
= tBITS (0, 3);
1320 ARMword Rt
= ntBITS (12, 15);
1329 // LDRH<c>.W <Rt>,[<Rn>{,#<imm12>}]
1330 ARMword imm12
= ntBITS (0, 11);
1331 address
= state
->Reg
[Rn
] + imm12
;
1333 else if (ntBIT (11))
1335 // LDRH<c> <Rt>,[<Rn>,#-<imm8>]
1336 // LDRH<c> <Rt>,[<Rn>],#+/-<imm8>
1337 // LDRH<c> <Rt>,[<Rn>,#+/-<imm8>]!
1338 ARMword P
= ntBIT (10);
1339 ARMword U
= ntBIT (9);
1340 ARMword W
= ntBIT (8);
1341 ARMword imm8
= ntBITS (0, 7);
1344 tASSERT (! (P
&& U
&& !W
));
1346 * ainstr
= 0xE05000B0;
1347 * ainstr
|= (P
<< 24);
1348 * ainstr
|= (U
<< 23);
1349 * ainstr
|= (W
<< 21);
1350 * ainstr
|= (Rn
<< 16);
1351 * ainstr
|= (Rt
<< 12);
1352 * ainstr
|= ((imm8
& 0xF0) << 4);
1353 * ainstr
|= (imm8
& 0xF);
1354 * pvalid
= t_decoded
;
1359 // LDRH<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1360 ARMword Rm
= ntBITS (0, 3);
1361 ARMword imm2
= ntBITS (4, 5);
1363 tASSERT (ntBITS (6, 10) == 0);
1365 address
= state
->Reg
[Rn
] + (state
->Reg
[Rm
] << imm2
);
1368 state
->Reg
[Rt
] = ARMul_LoadHalfWord (state
, address
);
1374 // STRH<c>.W <Rt>,[<Rn>{,#<imm12>}]
1375 ARMword imm12
= ntBITS (0, 11);
1377 address
= state
->Reg
[Rn
] + imm12
;
1379 else if (ntBIT (11))
1381 // STRH<c> <Rt>,[<Rn>,#-<imm8>]
1382 // STRH<c> <Rt>,[<Rn>],#+/-<imm8>
1383 // STRH<c> <Rt>,[<Rn>,#+/-<imm8>]!
1384 ARMword P
= ntBIT (10);
1385 ARMword U
= ntBIT (9);
1386 ARMword W
= ntBIT (8);
1387 ARMword imm8
= ntBITS (0, 7);
1389 tASSERT (! (P
&& U
&& !W
));
1391 * ainstr
= 0xE04000B0;
1392 * ainstr
|= (P
<< 24);
1393 * ainstr
|= (U
<< 23);
1394 * ainstr
|= (W
<< 21);
1395 * ainstr
|= (Rn
<< 16);
1396 * ainstr
|= (Rt
<< 12);
1397 * ainstr
|= ((imm8
& 0xF0) << 4);
1398 * ainstr
|= (imm8
& 0xF);
1399 * pvalid
= t_decoded
;
1404 // STRH<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1405 ARMword Rm
= ntBITS (0, 3);
1406 ARMword imm2
= ntBITS (4, 5);
1408 tASSERT (ntBITS (6, 10) == 0);
1410 address
= state
->Reg
[Rn
] + (state
->Reg
[Rm
] << imm2
);
1413 ARMul_StoreHalfWord (state
, address
, state
->Reg
[Rt
]);
1415 * pvalid
= t_branch
;
1419 case 0xC6: // LDR.W/STR.W
1421 ARMword Rn
= tBITS (0, 3);
1422 ARMword Rt
= ntBITS (12, 15);
1423 ARMword imm12
= ntBITS (0, 11);
1424 ARMword address
= state
->Reg
[Rn
];
1428 // LDR<c>.W <Rt>,<label>
1429 tASSERT (tBIT (4) == 1);
1430 // tASSERT (tBIT (7) == 1)
1435 state
->Reg
[Rt
] = ARMul_LoadWordN (state
, address
);
1437 ARMul_StoreWordN (state
, address
, state
->Reg
[Rt
]);
1439 * pvalid
= t_resolved
;
1446 ARMword Rt
= ntBITS (12, 15);
1447 ARMword Rn
= tBITS (0, 3);
1448 ARMword U
= tBIT (7);
1449 ARMword address
= state
->Reg
[Rn
];
1451 tASSERT (tBIT (4) == 1);
1452 tASSERT (Rt
!= 15); // PLI
1456 // LDRSB<c> <Rt>,<label>
1457 ARMword imm12
= ntBITS (0, 11);
1458 address
+= (U
? imm12
: - imm12
);
1462 // LDRSB<c> <Rt>,[<Rn>,#<imm12>]
1463 ARMword imm12
= ntBITS (0, 11);
1466 else if (ntBIT (11))
1468 // LDRSB<c> <Rt>,[<Rn>,#-<imm8>]
1469 // LDRSB<c> <Rt>,[<Rn>],#+/-<imm8>
1470 // LDRSB<c> <Rt>,[<Rn>,#+/-<imm8>]!
1471 * ainstr
= 0xE05000D0;
1472 * ainstr
|= ntBIT (10) << 24; // P
1473 * ainstr
|= ntBIT (9) << 23; // U
1474 * ainstr
|= ntBIT (8) << 21; // W
1475 * ainstr
|= Rn
<< 16;
1476 * ainstr
|= Rt
<< 12;
1477 * ainstr
|= ntBITS (4, 7) << 8;
1478 * ainstr
|= ntBITS (0, 3);
1479 * pvalid
= t_decoded
;
1484 // LDRSB<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1485 ARMword Rm
= ntBITS (0, 3);
1486 ARMword imm2
= ntBITS (4,5);
1488 tASSERT (ntBITS (6, 11) == 0);
1490 address
+= (state
->Reg
[Rm
] << imm2
);
1493 state
->Reg
[Rt
] = ARMul_LoadByte (state
, address
);
1494 if (state
->Reg
[Rt
] & 0x80)
1495 state
->Reg
[Rt
] |= -(1 << 8);
1497 * pvalid
= t_resolved
;
1504 ARMword Rt
= ntBITS (12, 15);
1505 ARMword Rn
= tBITS (0, 3);
1506 ARMword U
= tBIT (7);
1507 ARMword address
= state
->Reg
[Rn
];
1509 tASSERT (tBIT (4) == 1);
1511 if (Rn
== 15 || U
== 1)
1513 // Rn==15 => LDRSH<c> <Rt>,<label>
1514 // Rn!=15 => LDRSH<c> <Rt>,[<Rn>,#<imm12>]
1515 ARMword imm12
= ntBITS (0, 11);
1517 address
+= (U
? imm12
: - imm12
);
1519 else if (ntBIT (11))
1521 // LDRSH<c> <Rt>,[<Rn>,#-<imm8>]
1522 // LDRSH<c> <Rt>,[<Rn>],#+/-<imm8>
1523 // LDRSH<c> <Rt>,[<Rn>,#+/-<imm8>]!
1524 * ainstr
= 0xE05000F0;
1525 * ainstr
|= ntBIT (10) << 24; // P
1526 * ainstr
|= ntBIT (9) << 23; // U
1527 * ainstr
|= ntBIT (8) << 21; // W
1528 * ainstr
|= Rn
<< 16;
1529 * ainstr
|= Rt
<< 12;
1530 * ainstr
|= ntBITS (4, 7) << 8;
1531 * ainstr
|= ntBITS (0, 3);
1532 * pvalid
= t_decoded
;
1537 // LDRSH<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1538 ARMword Rm
= ntBITS (0, 3);
1539 ARMword imm2
= ntBITS (4,5);
1541 tASSERT (ntBITS (6, 11) == 0);
1543 address
+= (state
->Reg
[Rm
] << imm2
);
1546 state
->Reg
[Rt
] = ARMul_LoadHalfWord (state
, address
);
1547 if (state
->Reg
[Rt
] & 0x8000)
1548 state
->Reg
[Rt
] |= -(1 << 16);
1550 * pvalid
= t_branch
;
1556 ARMword Rm
= ntBITS (0, 3);
1557 ARMword Rd
= ntBITS (8, 11);
1559 tASSERT (ntBITS (12, 15) == 15);
1563 // SXTH<c>.W <Rd>,<Rm>{,<rotation>}
1564 ARMword ror
= ntBITS (4, 5) << 3;
1567 val
= state
->Reg
[Rm
];
1568 val
= (val
>> ror
) | (val
<< (32 - ror
));
1571 state
->Reg
[Rd
] = val
;
1575 // LSL{S}<c>.W <Rd>,<Rn>,<Rm>
1576 ARMword Rn
= tBITS (0, 3);
1578 tASSERT (ntBITS (4, 6) == 0);
1580 state
->Reg
[Rd
] = state
->Reg
[Rn
] << (state
->Reg
[Rm
] & 0xFF);
1582 ARMul_NegZero (state
, state
->Reg
[Rd
]);
1584 * pvalid
= t_branch
;
1588 case 0x0D1: // LSR{S}<c>.W <Rd>,<Rn>,<Rm>
1590 ARMword Rd
= ntBITS (8, 11);
1591 ARMword Rn
= tBITS (0, 3);
1592 ARMword Rm
= ntBITS (0, 3);
1594 tASSERT (ntBITS (12, 15) == 15);
1595 tASSERT (ntBITS (4, 7) == 0);
1597 state
->Reg
[Rd
] = state
->Reg
[Rn
] >> (state
->Reg
[Rm
] & 0xFF);
1599 ARMul_NegZero (state
, state
->Reg
[Rd
]);
1600 * pvalid
= t_resolved
;
1605 tASSERT (ntBITS (12, 15) == 15);
1608 tASSERT (ntBIT (6) == 0);
1609 // UXTB<c>.W <Rd>,<Rm>{,<rotation>}
1610 * ainstr
= 0xE6EF0070;
1611 * ainstr
|= (ntBITS (4, 5) << 10); // rotate
1612 * ainstr
|= ntBITS (0, 3); // Rm
1616 // ASR{S}<c>.W <Rd>,<Rn>,<Rm>
1617 tASSERT (ntBITS (4, 7) == 0);
1618 * ainstr
= 0xE1A00050;
1619 if (! in_IT_block ())
1620 * ainstr
|= (tBIT (4) << 20);
1621 * ainstr
|= (ntBITS (0, 3) << 8); // Rm
1622 * ainstr
|= tBITS (0, 3); // Rn
1625 * ainstr
|= (ntBITS (8, 11) << 12); // Rd
1626 * pvalid
= t_decoded
;
1629 case 0xD3: // ROR{S}<c>.W <Rd>,<Rn>,<Rm>
1630 tASSERT (ntBITS (12, 15) == 15);
1631 tASSERT (ntBITS (4, 7) == 0);
1632 * ainstr
= 0xE1A00070;
1633 if (! in_IT_block ())
1634 * ainstr
|= (tBIT (4) << 20);
1635 * ainstr
|= (ntBITS (8, 11) << 12); // Rd
1636 * ainstr
|= (ntBITS (0, 3) << 8); // Rm
1637 * ainstr
|= (tBITS (0, 3) << 0); // Rn
1638 * pvalid
= t_decoded
;
1643 ARMword Rn
= tBITS (0, 3);
1644 ARMword Rd
= ntBITS (8, 11);
1645 ARMword Rm
= ntBITS (0, 3);
1647 tASSERT (ntBITS (12, 15) == 15);
1649 if (ntBITS (4, 7) == 8)
1651 // REV<c>.W <Rd>,<Rm>
1652 ARMword val
= state
->Reg
[Rm
];
1658 | ((val
>> 8) & 0xFF00)
1659 | ((val
<< 8) & 0xFF0000)
1661 * pvalid
= t_resolved
;
1665 tASSERT (ntBITS (4, 7) == 4);
1668 // UADD8<c> <Rd>,<Rn>,<Rm>
1669 * ainstr
= 0xE6500F10;
1671 // UADD16<c> <Rd>,<Rn>,<Rm>
1672 * ainstr
= 0xE6500F90;
1674 * ainstr
|= (Rn
<< 16);
1675 * ainstr
|= (Rd
<< 12);
1676 * ainstr
|= (Rm
<< 0);
1677 * pvalid
= t_decoded
;
1684 ARMword Rn
= tBITS (0, 3);
1685 ARMword Rd
= ntBITS (8, 11);
1686 ARMword Rm
= ntBITS (0, 3);
1688 tASSERT (ntBITS (12, 15) == 15);
1689 tASSERT (ntBITS (4, 7) == 8);
1695 * ainstr
= 0xE16F0F10;
1699 // SEL<c> <Rd>,<Rn>,<Rm>
1700 * ainstr
= 0xE6800FB0;
1701 * ainstr
|= (Rn
<< 16);
1704 * ainstr
|= (Rd
<< 12);
1705 * ainstr
|= (Rm
<< 0);
1706 * pvalid
= t_decoded
;
1712 ARMword Rn
= tBITS (0, 3);
1713 ARMword Rm
= ntBITS (0, 3);
1714 ARMword Rd
= ntBITS (8, 11);
1715 ARMword Ra
= ntBITS (12, 15);
1719 // SMLA<x><y><c> <Rd>,<Rn>,<Rm>,<Ra>
1720 ARMword nval
= state
->Reg
[Rn
];
1721 ARMword mval
= state
->Reg
[Rm
];
1724 tASSERT (ntBITS (6, 7) == 0);
1738 res
+= state
->Reg
[Ra
];
1739 // FIXME: Test and clear/set the Q bit.
1740 state
->Reg
[Rd
] = res
;
1744 if (ntBITS (4, 7) == 1)
1746 // MLS<c> <Rd>,<Rn>,<Rm>,<Ra>
1747 state
->Reg
[Rd
] = state
->Reg
[Ra
] - (state
->Reg
[Rn
] * state
->Reg
[Rm
]);
1751 tASSERT (ntBITS (4, 7) == 0);
1754 // MUL<c> <Rd>,<Rn>,<Rm>
1755 state
->Reg
[Rd
] = state
->Reg
[Rn
] * state
->Reg
[Rm
];
1757 // MLA<c> <Rd>,<Rn>,<Rm>,<Ra>
1758 state
->Reg
[Rd
] = state
->Reg
[Rn
] * state
->Reg
[Rm
] + state
->Reg
[Ra
];
1761 * pvalid
= t_resolved
;
1766 if (tBIT (4) == 0 && ntBITS (4, 7) == 0)
1769 * ainstr
= 0xE0C00090;
1770 * ainstr
|= (ntBITS (8, 11) << 16); // RdHi
1771 * ainstr
|= (ntBITS (12, 15) << 12); // RdLo
1772 * ainstr
|= (ntBITS (0, 3) << 8); // Rm
1773 * ainstr
|= tBITS (0, 3); // Rn
1774 * pvalid
= t_decoded
;
1776 else if (tBIT (4) == 1 && ntBITS (4, 7) == 0xF)
1779 * ainstr
= 0xE710F010;
1780 * ainstr
|= (ntBITS (8, 11) << 16); // Rd
1781 * ainstr
|= (ntBITS (0, 3) << 8); // Rm
1782 * ainstr
|= tBITS (0, 3); // Rn
1783 * pvalid
= t_decoded
;
1787 fprintf (stderr
, "(op = %x) ", tBITS (5,12));
1794 if (tBIT (4) == 0 && ntBITS (4, 7) == 0)
1797 * ainstr
= 0xE0800090;
1798 * ainstr
|= (ntBITS (8, 11) << 16); // RdHi
1799 * ainstr
|= (ntBITS (12, 15) << 12); // RdLo
1800 * ainstr
|= (ntBITS (0, 3) << 8); // Rm
1801 * ainstr
|= tBITS (0, 3); // Rn
1802 * pvalid
= t_decoded
;
1804 else if (tBIT (4) == 1 && ntBITS (4, 7) == 0xF)
1807 * ainstr
= 0xE730F010;
1808 * ainstr
|= (ntBITS (8, 11) << 16); // Rd
1809 * ainstr
|= (ntBITS (0, 3) << 8); // Rm
1810 * ainstr
|= tBITS (0, 3); // Rn
1811 * pvalid
= t_decoded
;
1815 fprintf (stderr
, "(op = %x) ", tBITS (5,12));
1822 tASSERT (tBIT (4) == 0);
1823 tASSERT (ntBITS (4, 7) == 0);
1824 * ainstr
= 0xE0A00090;
1825 * ainstr
|= (ntBITS (8, 11) << 16); // RdHi
1826 * ainstr
|= (ntBITS (12, 15) << 12); // RdLo
1827 * ainstr
|= (ntBITS (0, 3) << 8); // Rm
1828 * ainstr
|= tBITS (0, 3); // Rn
1829 * pvalid
= t_decoded
;
1833 fprintf (stderr
, "(op = %x) ", tBITS (5,12));
1838 /* Tell the Thumb decoder to skip the next 16-bit insn - it was
1839 part of this insn - unless this insn has changed the PC. */
1840 skipping_32bit_thumb
= pc
+ 2;
1843 /* Attempt to emulate an ARMv6 instruction.
1844 Stores t_branch into PVALUE upon success or t_undefined otherwise. */
1847 handle_v6_thumb_insn (ARMul_State
* state
,
1856 * pvalid
= t_undefined
;
1860 if (tBITS (12, 15) == 0xB
1864 // Conditional branch forwards.
1865 ARMword Rn
= tBITS (0, 2);
1866 ARMword imm5
= tBIT (9) << 5 | tBITS (3, 7);
1870 if (state
->Reg
[Rn
] != 0)
1872 state
->Reg
[15] = (pc
+ 4 + imm5
* 2);
1878 if (state
->Reg
[Rn
] == 0)
1880 state
->Reg
[15] = (pc
+ 4 + imm5
* 2);
1884 * pvalid
= t_branch
;
1888 switch (tinstr
& 0xFFC0)
1895 ARMword Rd
= (tBIT (7) << 3) | tBITS (0, 2);
1896 ARMword Rm
= tBITS (3, 6);
1897 state
->Reg
[Rd
] += state
->Reg
[Rm
];
1901 case 0x4600: // MOV<c> <Rd>,<Rm>
1903 // instr [15, 8] = 0100 0110
1904 // instr [7] = Rd<high>
1906 // instr [2,0] = Rd<low>
1907 ARMword Rd
= (tBIT(7) << 3) | tBITS (0, 2);
1908 // FIXME: Check for Rd == 15 and ITblock.
1909 state
->Reg
[Rd
] = state
->Reg
[tBITS (3, 6)];
1917 handle_IT_block (state
, tinstr
, pvalid
);
1921 case 0xE880: // LDMIA
1926 case 0xE9C0: // LDRD
1935 case 0xFA80: // UADD, SEL
1936 case 0xFBC0: // UMULL, SMULL, SDIV, UDIV
1937 handle_T2_insn (state
, tinstr
, next_instr
, pc
, ainstr
, pvalid
);
1940 case 0xba00: /* rev */
1942 ARMword val
= state
->Reg
[tBITS (3, 5)];
1943 state
->Reg
[tBITS (0, 2)] =
1945 | ((val
>> 8) & 0xFF00)
1946 | ((val
<< 8) & 0xFF0000)
1951 case 0xba40: /* rev16 */
1953 ARMword val
= state
->Reg
[tBITS (3, 5)];
1954 state
->Reg
[tBITS (0, 2)] = (val
>> 16) | (val
<< 16);
1958 case 0xb660: /* cpsie */
1959 case 0xb670: /* cpsid */
1960 case 0xbac0: /* revsh */
1961 case 0xb650: /* setend */
1963 printf ("Unhandled v6 thumb insn: %04x\n", tinstr
);
1964 * pvalid
= t_undefined
;
1967 case 0xb200: /* sxth */
1969 ARMword Rm
= state
->Reg
[(tinstr
& 0x38) >> 3];
1972 state
->Reg
[(tinstr
& 0x7)] = (Rm
& 0xffff) | 0xffff0000;
1974 state
->Reg
[(tinstr
& 0x7)] = Rm
& 0xffff;
1978 case 0xb240: /* sxtb */
1980 ARMword Rm
= state
->Reg
[(tinstr
& 0x38) >> 3];
1983 state
->Reg
[(tinstr
& 0x7)] = (Rm
& 0xff) | 0xffffff00;
1985 state
->Reg
[(tinstr
& 0x7)] = Rm
& 0xff;
1989 case 0xb280: /* uxth */
1991 ARMword Rm
= state
->Reg
[(tinstr
& 0x38) >> 3];
1993 state
->Reg
[(tinstr
& 0x7)] = Rm
& 0xffff;
1997 case 0xb2c0: /* uxtb */
1999 ARMword Rm
= state
->Reg
[(tinstr
& 0x38) >> 3];
2001 state
->Reg
[(tinstr
& 0x7)] = Rm
& 0xff;
2005 /* Indicate that the instruction has been processed. */
2006 * pvalid
= t_branch
;
2009 /* Decode a 16bit Thumb instruction. The instruction is in the low
2010 16-bits of the tinstr field, with the following Thumb instruction
2011 held in the high 16-bits. Passing in two Thumb instructions allows
2012 easier simulation of the special dual BL instruction. */
2015 ARMul_ThumbDecode (ARMul_State
* state
,
2020 tdstate valid
= t_decoded
; /* default assumes a valid instruction */
2022 ARMword old_tinstr
= tinstr
;
2024 if (skipping_32bit_thumb
== pc
)
2026 skipping_32bit_thumb
= 0;
2029 skipping_32bit_thumb
= 0;
2031 if (state
->bigendSig
)
2033 next_instr
= tinstr
& 0xFFFF;
2038 next_instr
= tinstr
>> 16;
2042 if (! IT_block_allow (state
))
2044 if ( tBITS (11, 15) == 0x1F
2045 || tBITS (11, 15) == 0x1E
2046 || tBITS (11, 15) == 0x1D)
2049 fprintf (stderr
, "pc: %x, SKIP instr: %04x|%04x\n",
2050 pc
& ~1, tinstr
, next_instr
);
2051 skipping_32bit_thumb
= pc
+ 2;
2054 fprintf (stderr
, "pc: %x, SKIP instr: %04x\n", pc
& ~1, tinstr
);
2059 old_tinstr
= tinstr
;
2061 fprintf (stderr
, "pc: %x, Thumb instr: %x", pc
& ~1, tinstr
);
2063 #if 1 /* debugging to catch non updates */
2064 *ainstr
= 0xDEADC0DE;
2067 switch ((tinstr
& 0xF800) >> 11)
2073 *ainstr
= 0xE1B00000 /* base opcode */
2074 | ((tinstr
& 0x1800) >> (11 - 5)) /* shift type */
2075 | ((tinstr
& 0x07C0) << (7 - 6)) /* imm5 */
2076 | ((tinstr
& 0x0038) >> 3) /* Rs */
2077 | ((tinstr
& 0x0007) << 12); /* Rd */
2079 case 3: /* ADD/SUB */
2084 0xE0900000, /* ADDS Rd,Rs,Rn */
2085 0xE0500000, /* SUBS Rd,Rs,Rn */
2086 0xE2900000, /* ADDS Rd,Rs,#imm3 */
2087 0xE2500000 /* SUBS Rd,Rs,#imm3 */
2089 /* It is quicker indexing into a table, than performing switch
2091 *ainstr
= subset
[(tinstr
& 0x0600) >> 9] /* base opcode */
2092 | ((tinstr
& 0x01C0) >> 6) /* Rn or imm3 */
2093 | ((tinstr
& 0x0038) << (16 - 3)) /* Rs */
2094 | ((tinstr
& 0x0007) << (12 - 0)); /* Rd */
2097 *ainstr
&= ~ (1 << 20);
2101 * ainstr
= 0xE3A00000; /* MOV Rd,#imm8 */
2102 if (! in_IT_block ())
2103 * ainstr
|= (1 << 20);
2104 * ainstr
|= tBITS (8, 10) << 12;
2105 * ainstr
|= tBITS (0, 7);
2109 * ainstr
= 0xE3500000; /* CMP Rd,#imm8 */
2110 * ainstr
|= tBITS (8, 10) << 16;
2111 * ainstr
|= tBITS (0, 7);
2116 * ainstr
= tBIT (11)
2117 ? 0xE2400000 /* SUB Rd,Rd,#imm8 */
2118 : 0xE2800000; /* ADD Rd,Rd,#imm8 */
2119 if (! in_IT_block ())
2120 * ainstr
|= (1 << 20);
2121 * ainstr
|= tBITS (8, 10) << 12;
2122 * ainstr
|= tBITS (8, 10) << 16;
2123 * ainstr
|= tBITS (0, 7);
2126 case 8: /* Arithmetic and high register transfers */
2127 /* TODO: Since the subsets for both Format 4 and Format 5
2128 instructions are made up of different ARM encodings, we could
2129 save the following conditional, and just have one large
2131 if ((tinstr
& (1 << 10)) == 0)
2134 struct insn_format
{
2136 enum { t_norm
, t_shift
, t_neg
, t_mul
} otype
;
2138 static const struct insn_format subset
[16] =
2140 { 0xE0100000, t_norm
}, /* ANDS Rd,Rd,Rs */
2141 { 0xE0300000, t_norm
}, /* EORS Rd,Rd,Rs */
2142 { 0xE1B00010, t_shift
}, /* MOVS Rd,Rd,LSL Rs */
2143 { 0xE1B00030, t_shift
}, /* MOVS Rd,Rd,LSR Rs */
2144 { 0xE1B00050, t_shift
}, /* MOVS Rd,Rd,ASR Rs */
2145 { 0xE0B00000, t_norm
}, /* ADCS Rd,Rd,Rs */
2146 { 0xE0D00000, t_norm
}, /* SBCS Rd,Rd,Rs */
2147 { 0xE1B00070, t_shift
}, /* MOVS Rd,Rd,ROR Rs */
2148 { 0xE1100000, t_norm
}, /* TST Rd,Rs */
2149 { 0xE2700000, t_neg
}, /* RSBS Rd,Rs,#0 */
2150 { 0xE1500000, t_norm
}, /* CMP Rd,Rs */
2151 { 0xE1700000, t_norm
}, /* CMN Rd,Rs */
2152 { 0xE1900000, t_norm
}, /* ORRS Rd,Rd,Rs */
2153 { 0xE0100090, t_mul
} , /* MULS Rd,Rd,Rs */
2154 { 0xE1D00000, t_norm
}, /* BICS Rd,Rd,Rs */
2155 { 0xE1F00000, t_norm
} /* MVNS Rd,Rs */
2157 *ainstr
= subset
[(tinstr
& 0x03C0) >> 6].opcode
; /* base */
2161 static const struct insn_format it_subset
[16] =
2163 { 0xE0000000, t_norm
}, /* AND Rd,Rd,Rs */
2164 { 0xE0200000, t_norm
}, /* EOR Rd,Rd,Rs */
2165 { 0xE1A00010, t_shift
}, /* MOV Rd,Rd,LSL Rs */
2166 { 0xE1A00030, t_shift
}, /* MOV Rd,Rd,LSR Rs */
2167 { 0xE1A00050, t_shift
}, /* MOV Rd,Rd,ASR Rs */
2168 { 0xE0A00000, t_norm
}, /* ADC Rd,Rd,Rs */
2169 { 0xE0C00000, t_norm
}, /* SBC Rd,Rd,Rs */
2170 { 0xE1A00070, t_shift
}, /* MOV Rd,Rd,ROR Rs */
2171 { 0xE1100000, t_norm
}, /* TST Rd,Rs */
2172 { 0xE2600000, t_neg
}, /* RSB Rd,Rs,#0 */
2173 { 0xE1500000, t_norm
}, /* CMP Rd,Rs */
2174 { 0xE1700000, t_norm
}, /* CMN Rd,Rs */
2175 { 0xE1800000, t_norm
}, /* ORR Rd,Rd,Rs */
2176 { 0xE0000090, t_mul
} , /* MUL Rd,Rd,Rs */
2177 { 0xE1C00000, t_norm
}, /* BIC Rd,Rd,Rs */
2178 { 0xE1E00000, t_norm
} /* MVN Rd,Rs */
2180 *ainstr
= it_subset
[(tinstr
& 0x03C0) >> 6].opcode
; /* base */
2183 switch (subset
[(tinstr
& 0x03C0) >> 6].otype
)
2186 *ainstr
|= ((tinstr
& 0x0007) << 16) /* Rn */
2187 | ((tinstr
& 0x0007) << 12) /* Rd */
2188 | ((tinstr
& 0x0038) >> 3); /* Rs */
2191 *ainstr
|= ((tinstr
& 0x0007) << 12) /* Rd */
2192 | ((tinstr
& 0x0007) >> 0) /* Rm */
2193 | ((tinstr
& 0x0038) << (8 - 3)); /* Rs */
2196 *ainstr
|= ((tinstr
& 0x0007) << 12) /* Rd */
2197 | ((tinstr
& 0x0038) << (16 - 3)); /* Rn */
2200 *ainstr
|= ((tinstr
& 0x0007) << 16) /* Rd */
2201 | ((tinstr
& 0x0007) << 8) /* Rs */
2202 | ((tinstr
& 0x0038) >> 3); /* Rm */
2209 ARMword Rd
= ((tinstr
& 0x0007) >> 0);
2210 ARMword Rs
= ((tinstr
& 0x0038) >> 3);
2211 if (tinstr
& (1 << 7))
2213 if (tinstr
& (1 << 6))
2215 switch ((tinstr
& 0x03C0) >> 6)
2217 case 0x1: /* ADD Rd,Rd,Hs */
2218 case 0x2: /* ADD Hd,Hd,Rs */
2219 case 0x3: /* ADD Hd,Hd,Hs */
2220 *ainstr
= 0xE0800000 /* base */
2221 | (Rd
<< 16) /* Rn */
2222 | (Rd
<< 12) /* Rd */
2223 | (Rs
<< 0); /* Rm */
2225 case 0x5: /* CMP Rd,Hs */
2226 case 0x6: /* CMP Hd,Rs */
2227 case 0x7: /* CMP Hd,Hs */
2228 *ainstr
= 0xE1500000 /* base */
2229 | (Rd
<< 16) /* Rn */
2230 | (Rd
<< 12) /* Rd */
2231 | (Rs
<< 0); /* Rm */
2233 case 0x9: /* MOV Rd,Hs */
2234 case 0xA: /* MOV Hd,Rs */
2235 case 0xB: /* MOV Hd,Hs */
2236 *ainstr
= 0xE1A00000 /* base */
2237 | (Rd
<< 12) /* Rd */
2238 | (Rs
<< 0); /* Rm */
2240 case 0xC: /* BX Rs */
2241 case 0xD: /* BX Hs */
2242 *ainstr
= 0xE12FFF10 /* base */
2243 | ((tinstr
& 0x0078) >> 3); /* Rd */
2245 case 0xE: /* UNDEFINED */
2246 case 0xF: /* UNDEFINED */
2249 /* BLX Rs; BLX Hs */
2250 *ainstr
= 0xE12FFF30 /* base */
2251 | ((tinstr
& 0x0078) >> 3); /* Rd */
2254 ATTRIBUTE_FALLTHROUGH
;
2256 case 0x0: /* UNDEFINED */
2257 case 0x4: /* UNDEFINED */
2258 case 0x8: /* UNDEFINED */
2259 handle_v6_thumb_insn (state
, tinstr
, next_instr
, pc
, ainstr
, & valid
);
2264 case 9: /* LDR Rd,[PC,#imm8] */
2266 *ainstr
= 0xE59F0000 /* base */
2267 | ((tinstr
& 0x0700) << (12 - 8)) /* Rd */
2268 | ((tinstr
& 0x00FF) << (2 - 0)); /* off8 */
2272 /* TODO: Format 7 and Format 8 perform the same ARM encoding, so
2273 the following could be merged into a single subset, saving on
2274 the following boolean: */
2275 if ((tinstr
& (1 << 9)) == 0)
2278 ARMword subset
[4] = {
2279 0xE7800000, /* STR Rd,[Rb,Ro] */
2280 0xE7C00000, /* STRB Rd,[Rb,Ro] */
2281 0xE7900000, /* LDR Rd,[Rb,Ro] */
2282 0xE7D00000 /* LDRB Rd,[Rb,Ro] */
2284 *ainstr
= subset
[(tinstr
& 0x0C00) >> 10] /* base */
2285 | ((tinstr
& 0x0007) << (12 - 0)) /* Rd */
2286 | ((tinstr
& 0x0038) << (16 - 3)) /* Rb */
2287 | ((tinstr
& 0x01C0) >> 6); /* Ro */
2292 ARMword subset
[4] = {
2293 0xE18000B0, /* STRH Rd,[Rb,Ro] */
2294 0xE19000D0, /* LDRSB Rd,[Rb,Ro] */
2295 0xE19000B0, /* LDRH Rd,[Rb,Ro] */
2296 0xE19000F0 /* LDRSH Rd,[Rb,Ro] */
2298 *ainstr
= subset
[(tinstr
& 0x0C00) >> 10] /* base */
2299 | ((tinstr
& 0x0007) << (12 - 0)) /* Rd */
2300 | ((tinstr
& 0x0038) << (16 - 3)) /* Rb */
2301 | ((tinstr
& 0x01C0) >> 6); /* Ro */
2304 case 12: /* STR Rd,[Rb,#imm5] */
2305 case 13: /* LDR Rd,[Rb,#imm5] */
2306 case 14: /* STRB Rd,[Rb,#imm5] */
2307 case 15: /* LDRB Rd,[Rb,#imm5] */
2310 ARMword subset
[4] = {
2311 0xE5800000, /* STR Rd,[Rb,#imm5] */
2312 0xE5900000, /* LDR Rd,[Rb,#imm5] */
2313 0xE5C00000, /* STRB Rd,[Rb,#imm5] */
2314 0xE5D00000 /* LDRB Rd,[Rb,#imm5] */
2316 /* The offset range defends on whether we are transferring a
2317 byte or word value: */
2318 *ainstr
= subset
[(tinstr
& 0x1800) >> 11] /* base */
2319 | ((tinstr
& 0x0007) << (12 - 0)) /* Rd */
2320 | ((tinstr
& 0x0038) << (16 - 3)) /* Rb */
2321 | ((tinstr
& 0x07C0) >> (6 - ((tinstr
& (1 << 12)) ? 0 : 2))); /* off5 */
2324 case 16: /* STRH Rd,[Rb,#imm5] */
2325 case 17: /* LDRH Rd,[Rb,#imm5] */
2327 *ainstr
= ((tinstr
& (1 << 11)) /* base */
2328 ? 0xE1D000B0 /* LDRH */
2329 : 0xE1C000B0) /* STRH */
2330 | ((tinstr
& 0x0007) << (12 - 0)) /* Rd */
2331 | ((tinstr
& 0x0038) << (16 - 3)) /* Rb */
2332 | ((tinstr
& 0x01C0) >> (6 - 1)) /* off5, low nibble */
2333 | ((tinstr
& 0x0600) >> (9 - 8)); /* off5, high nibble */
2335 case 18: /* STR Rd,[SP,#imm8] */
2336 case 19: /* LDR Rd,[SP,#imm8] */
2338 *ainstr
= ((tinstr
& (1 << 11)) /* base */
2339 ? 0xE59D0000 /* LDR */
2340 : 0xE58D0000) /* STR */
2341 | ((tinstr
& 0x0700) << (12 - 8)) /* Rd */
2342 | ((tinstr
& 0x00FF) << 2); /* off8 */
2344 case 20: /* ADD Rd,PC,#imm8 */
2345 case 21: /* ADD Rd,SP,#imm8 */
2347 if ((tinstr
& (1 << 11)) == 0)
2349 /* NOTE: The PC value used here should by word aligned */
2350 /* We encode shift-left-by-2 in the rotate immediate field,
2351 so no shift of off8 is needed. */
2352 *ainstr
= 0xE28F0F00 /* base */
2353 | ((tinstr
& 0x0700) << (12 - 8)) /* Rd */
2354 | (tinstr
& 0x00FF); /* off8 */
2358 /* We encode shift-left-by-2 in the rotate immediate field,
2359 so no shift of off8 is needed. */
2360 *ainstr
= 0xE28D0F00 /* base */
2361 | ((tinstr
& 0x0700) << (12 - 8)) /* Rd */
2362 | (tinstr
& 0x00FF); /* off8 */
2367 switch (tinstr
& 0x0F00)
2371 /* NOTE: The instruction contains a shift left of 2
2372 equivalent (implemented as ROR #30): */
2373 *ainstr
= ((tinstr
& (1 << 7)) /* base */
2374 ? 0xE24DDF00 /* SUB */
2375 : 0xE28DDF00) /* ADD */
2376 | (tinstr
& 0x007F); /* off7 */
2379 /* Format 14 - Push */
2380 * ainstr
= 0xE92D0000 | (tinstr
& 0x00FF);
2383 /* Format 14 - Push + LR */
2384 * ainstr
= 0xE92D4000 | (tinstr
& 0x00FF);
2387 /* Format 14 - Pop */
2388 * ainstr
= 0xE8BD0000 | (tinstr
& 0x00FF);
2391 /* Format 14 - Pop + PC */
2392 * ainstr
= 0xE8BD8000 | (tinstr
& 0x00FF);
2397 /* This is normally an undefined instruction. The v5t architecture
2398 defines this particular pattern as a BKPT instruction, for
2399 hardware assisted debugging. We map onto the arm BKPT
2402 // Map to the SVC instruction instead of the BKPT instruction.
2403 * ainstr
= 0xEF000000 | tBITS (0, 7);
2405 * ainstr
= 0xE1200070 | ((tinstr
& 0xf0) << 4) | (tinstr
& 0xf);
2408 ATTRIBUTE_FALLTHROUGH
;
2410 /* Everything else is an undefined instruction. */
2411 handle_v6_thumb_insn (state
, tinstr
, next_instr
, pc
, ainstr
, & valid
);
2415 case 24: /* STMIA */
2416 case 25: /* LDMIA */
2418 *ainstr
= ((tinstr
& (1 << 11)) /* base */
2419 ? 0xE8B00000 /* LDMIA */
2420 : 0xE8A00000) /* STMIA */
2421 | ((tinstr
& 0x0700) << (16 - 8)) /* Rb */
2422 | (tinstr
& 0x00FF); /* mask8 */
2425 case 27: /* Bcc/SWI */
2426 if ((tinstr
& 0x0F00) == 0x0F00)
2428 /* Format 17 : SWI */
2429 *ainstr
= 0xEF000000;
2430 /* Breakpoint must be handled specially. */
2431 if ((tinstr
& 0x00FF) == 0x18)
2432 *ainstr
|= ((tinstr
& 0x00FF) << 16);
2433 /* New breakpoint value. See gdb/arm-tdep.c */
2434 else if ((tinstr
& 0x00FF) == 0xFE)
2435 *ainstr
|= SWI_Breakpoint
;
2437 *ainstr
|= (tinstr
& 0x00FF);
2439 else if ((tinstr
& 0x0F00) != 0x0E00)
2443 /* TODO: Since we are doing a switch here, we could just add
2444 the SWI and undefined instruction checks into this
2445 switch to same on a couple of conditionals: */
2446 switch ((tinstr
& 0x0F00) >> 8)
2473 doit
= (CFLAG
&& !ZFLAG
);
2476 doit
= (!CFLAG
|| ZFLAG
);
2479 doit
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
2482 doit
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
2485 doit
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
)
2486 || (NFLAG
&& VFLAG
&& !ZFLAG
));
2489 doit
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
2494 state
->Reg
[15] = (pc
+ 4
2495 + (((tinstr
& 0x7F) << 1)
2496 | ((tinstr
& (1 << 7)) ? 0xFFFFFF00 : 0)));
2502 /* UNDEFINED : cc=1110(AL) uses different format. */
2503 handle_v6_thumb_insn (state
, tinstr
, next_instr
, pc
, ainstr
, & valid
);
2507 state
->Reg
[15] = (pc
+ 4
2508 + (((tinstr
& 0x3FF) << 1)
2509 | ((tinstr
& (1 << 10)) ? 0xFFFFF800 : 0)));
2513 case 29: /* UNDEFINED */
2516 handle_v6_thumb_insn (state
, tinstr
, next_instr
, pc
, ainstr
, & valid
);
2524 handle_v6_thumb_insn (state
, tinstr
, next_instr
, pc
, ainstr
, & valid
);
2530 /* There is no single ARM instruction equivalent for this
2531 instruction. Also, it should only ever be matched with the
2532 fmt19 "BL/BLX instruction 1" instruction. However, we do
2533 allow the simulation of it on its own, with undefined results
2534 if r14 is not suitably initialised. */
2536 ARMword tmp
= (pc
+ 2);
2538 state
->Reg
[15] = ((state
->Reg
[14] + ((tinstr
& 0x07FF) << 1))
2541 state
->Reg
[14] = (tmp
| 1);
2545 fprintf (stderr
, " pc changed to %x\n", state
->Reg
[15]);
2550 handle_v6_thumb_insn (state
, tinstr
, next_instr
, pc
, ainstr
, & valid
);
2553 case 30: /* BL instruction 1 */
2556 handle_T2_insn (state
, tinstr
, next_instr
, pc
, ainstr
, & valid
);
2561 /* There is no single ARM instruction equivalent for this Thumb
2562 instruction. To keep the simulation simple (from the user
2563 perspective) we check if the following instruction is the
2564 second half of this BL, and if it is we simulate it
2566 state
->Reg
[14] = state
->Reg
[15] \
2567 + (((tinstr
& 0x07FF) << 12) \
2568 | ((tinstr
& (1 << 10)) ? 0xFF800000 : 0));
2570 valid
= t_branch
; /* in-case we don't have the 2nd half */
2571 tinstr
= next_instr
; /* move the instruction down */
2572 pc
+= 2; /* point the pc at the 2nd half */
2573 if (((tinstr
& 0xF800) >> 11) != 31)
2575 if (((tinstr
& 0xF800) >> 11) == 29)
2577 ARMword tmp
= (pc
+ 2);
2579 state
->Reg
[15] = ((state
->Reg
[14]
2580 + ((tinstr
& 0x07FE) << 1))
2583 state
->Reg
[14] = (tmp
| 1);
2588 /* Exit, since not correct instruction. */
2592 /* else we fall through to process the second half of the BL */
2593 pc
+= 2; /* point the pc at the 2nd half */
2594 ATTRIBUTE_FALLTHROUGH
;
2595 case 31: /* BL instruction 2 */
2598 handle_T2_insn (state
, old_tinstr
, next_instr
, pc
, ainstr
, & valid
);
2603 /* There is no single ARM instruction equivalent for this
2604 instruction. Also, it should only ever be matched with the
2605 fmt19 "BL instruction 1" instruction. However, we do allow
2606 the simulation of it on its own, with undefined results if
2607 r14 is not suitably initialised. */
2611 state
->Reg
[15] = (state
->Reg
[14] + ((tinstr
& 0x07FF) << 1));
2612 state
->Reg
[14] = (tmp
| 1);
2619 if (trace
&& valid
!= t_decoded
)
2620 fprintf (stderr
, "\n");