8 * http://www.illumos.org/license/CDDL.
9 */
10 /*
11 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
12 * Copyright (c) 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
13 */
14
15 /*
16 * This provides basic support for disassembling arm instructions. This is
17 * derived from the arm reference manual (generic), chapter A3 (ARM DDI 0100l).
18 * All instructions come in as uint32_t's.
19 */
20
21 #include <libdisasm.h>
22 #include <stdint.h>
23 #include <stdio.h>
24 #include <sys/byteorder.h>
25
26 #include "libdisasm_impl.h"
27
28 extern size_t strlcat(char *, const char *, size_t);
29
30 /*
31 * Condition code mask and shift, aka bits 28-31.
32 */
33 #define ARM_CC_MASK 0xf0000000
34 #define ARM_CC_SHIFT 28
35
36 /*
37 * First level of decoding, aka bits 25-27.
38 */
39 #define ARM_L1_DEC_MASK 0x0e000000
40 #define ARM_L1_DEC_SHIFT 25
41
42 /*
43 * Masks and values for the 0b000 l1 group
44 */
45 #define ARM_L1_0_B4_MASK 0x00000010
46 #define ARM_L1_0_B7_MASK 0x00000080
47 #define ARM_L1_0_OPMASK 0x01800000
376 #define ARM_COPROC_DRT_OP_MASK 0x000000f0
377 #define ARM_COPROC_DRT_OP_SHIFT 4
378 #define ARM_COPROC_DRT_DIR_MASK 0x00100000 /* MCRR or MRRC */
379
380 #define ARM_COPROC_LS_P_MASK 0x01000000
381 #define ARM_COPROC_LS_U_MASK 0x00800000
382 #define ARM_COPROC_LS_N_MASK 0x00400000
383 #define ARM_COPROC_LS_W_MASK 0x00200000
384 #define ARM_COPROC_LS_L_MASK 0x00100000
385 #define ARM_COPROC_LS_IMM_MASK 0x000000ff
386
387 /*
388 * This is the table of condition codes that instructions might have. Every
389 * instruction starts with a four bit code. The last two codes are special.
390 * 0b1110 is the always condition. Therefore we leave off its mneomic extension
391 * and treat it as the empty string. The condition code 0b1111 takes us to a
392 * separate series of encoded instructions and therefore we go elsewhere with
393 * them.
394 */
395 static const char *arm_cond_names[] = {
396 "EQ", /* Equal */
397 "NE", /* Not Equal */
398 "CS/HS", /* Carry set/unsigned higher or same */
399 "CC/LO", /* Carry clear/unsigned lower */
400 "MI", /* Minus/negative */
401 "PL", /* Plus/positive or zero */
402 "VS", /* Overflow */
403 "VC", /* No overflow */
404 "HI", /* Unsigned higher */
405 "LS", /* Unsigned lower or same */
406 "GE", /* Signed greater than or equal */
407 "LT", /* Signed less than */
408 "GT", /* Signed greater than */
409 "LE", /* Signed less than or equal */
410 "", /* AL - Always (unconditional) */
411 NULL /* Not a condition code */
412 };
413
414 typedef enum arm_cond_code {
415 ARM_COND_EQ, /* Equal */
416 ARM_COND_NE, /* Not Equal */
417 ARM_COND_CSHS, /* Carry set/unsigned higher or same */
418 ARM_COND_CCLO, /* Carry clear/unsigned lower */
419 ARM_COND_MI, /* Minus/negative */
420 ARM_COND_PL, /* Plus/positive or zero */
421 ARM_COND_VS, /* Overflow */
422 ARM_COND_VC, /* No overflow */
423 ARM_COND_HI, /* Unsigned higher */
424 ARM_COND_LS, /* Unsigned lower or same */
425 ARM_COND_GE, /* Signed greater than or equal */
426 ARM_COND_LT, /* Signed less than */
427 ARM_COND_GT, /* Signed greater than */
428 ARM_COND_LE, /* Signed less than or equal */
429 ARM_COND_AL, /* AL - Always (unconditional) */
430 ARM_COND_NACC /* Not a condition code */
431 } arm_cond_code_t;
432
433 /*
434 * Registers are encoded surprisingly sanely. It's a 4-bit value that indicates
435 * which register in question we're working with.
436 */
437 static const char *arm_reg_names[] = {
438 "R0",
439 "R1",
440 "R2",
441 "R3",
442 "R4",
443 "R5",
444 "R6",
445 "R7",
446 "R8",
447 "R9",
448 "R10",
449 "R11",
450 "IP", /* Alt for R12 */
451 "SP", /* Alt for R13 */
452 "LR", /* Alt for R14 */
453 "PC" /* Alt for R15 */
454 };
455
456 typedef enum arm_reg {
457 ARM_REG_R0,
458 ARM_REG_R1,
459 ARM_REG_R2,
460 ARM_REG_R3,
461 ARM_REG_R4,
462 ARM_REG_R5,
463 ARM_REG_R6,
464 ARM_REG_R7,
465 ARM_REG_R8,
466 ARM_REG_R9,
467 ARM_REG_R10,
468 ARM_REG_R11,
469 ARM_REG_R12,
470 ARM_REG_R13,
471 ARM_REG_R14,
472 ARM_REG_R15
473 } arm_reg_t;
482 "p3",
483 "p4",
484 "p5",
485 "p6",
486 "p7",
487 "p8",
488 "p9",
489 "p10",
490 "p11",
491 "p12",
492 "p13",
493 "p14",
494 "p15"
495 };
496
497 /*
498 * These are the opcodes for the instructions which are considered data
499 * processing instructions.
500 */
501 static const char *arm_dpi_opnames[] = {
502 "AND", /* Logical AND */
503 "EOR", /* Logical Exclusive OR */
504 "SUB", /* Subtract */
505 "RSB", /* Reverse Subtract */
506 "ADD", /* Add */
507 "ADC", /* Add with Carry */
508 "SBC", /* Subtract with Carry */
509 "RSC", /* Reverse Subtract with Carry */
510 "TST", /* Test */
511 "TEQ", /* Test Equivalence */
512 "CMP", /* Compare */
513 "CMN", /* Compare negated */
514 "ORR", /* Logical (inclusive) OR */
515 "MOV", /* Move */
516 "BIC", /* Bit clear */
517 "MVN" /* Move not */
518 };
519
520 typedef enum arm_dpi_opcode {
521 DPI_OP_AND, /* Logical AND */
522 DPI_OP_EOR, /* Logical Exclusive OR */
523 DPI_OP_SUB, /* Subtract */
524 DPI_OP_RSB, /* Reverse Subtract */
525 DPI_OP_ADD, /* Add */
526 DPI_OP_ADC, /* Add with Carry */
527 DPI_OP_SBC, /* Subtract with Carry */
528 DPI_OP_RSC, /* Reverse Subtract with Carry */
529 DPI_OP_TST, /* Test */
530 DPI_OP_TEQ, /* Test Equivalence */
531 DPI_OP_CMP, /* Compare */
532 DPI_OP_CMN, /* Compare negated */
533 DPI_OP_ORR, /* Logical (inclusive) OR */
534 DPI_OP_MOV, /* Move */
535 DPI_OP_BIC, /* Bit clear */
536 DPI_OP_MVN /* Move not */
537 } arm_dpi_opcode_t;
538
539 const char *arm_dpi_shifts[] = {
540 "LSL", /* Logical shift left */
541 "LSR", /* Logical shift right */
542 "ASR", /* Arithmetic shift right */
543 "ROR", /* Rotate right */
544 "RRX" /* Rotate right with extend. This is a special case of ROR */
545 };
546
547 typedef enum arm_dpi_shift_code {
548 DPI_S_LSL, /* Logical shift left */
549 DPI_S_LSR, /* Logical shift right */
550 DPI_S_ASR, /* Arithmetic shift right */
551 DPI_S_ROR, /* Rotate right */
552 DPI_S_RRX, /* Rotate right with extend. Special case of ROR */
553 DPI_S_NONE /* No shift code */
554 } arm_dpi_shift_code_t;
555
556 #define ARM_DPI_SHIFTER_IMM32 0x00
557 #define ARM_DPI_SHIFTER_SIMM 0x01
558 #define ARM_DPI_SHIFTER_SREG 0x02
559
560 typedef struct arm_dpi_shifter_imm {
561 uint8_t dpisi_rot; /* Rotation amount */
562 uint8_t dpisi_imm; /* Immediate value */
563 } arm_dpi_shifter_imm_t;
564
565 typedef struct arm_dpi_shifter_simm {
566 uint8_t dpiss_imm; /* Shift value */
567 arm_dpi_shift_code_t dpiss_code; /* Shift type */
568 arm_reg_t dpiss_targ; /* Target register */
569 } arm_dpi_shifter_simm_t;
570
571 typedef struct arm_dpi_shifter_sreg {
572 arm_reg_t dpisr_val; /* reg with shift value */
577 typedef struct arm_dpi_inst {
578 arm_dpi_opcode_t dpii_op; /* dpi opcode */
579 arm_cond_code_t dpii_cond; /* condition code */
580 int dpii_sbit; /* value of S bit */
581 arm_reg_t dpii_rn; /* first operand */
582 arm_reg_t dpii_rd; /* destination operand */
583 int dpii_stype; /* type of shifter */
584 union { /* shifter values */
585 arm_dpi_shifter_imm_t dpii_im;
586 arm_dpi_shifter_simm_t dpii_si;
587 arm_dpi_shifter_sreg_t dpii_ri;
588 } dpii_un;
589 } arm_dpi_inst_t;
590
591 /*
592 * This table contains the names of the load store multiple addressing modes.
593 * The P and U bits are supposed to be combined to index into this. You should
594 * do this by doing P << 1 | U.
595 */
596 static const char *arm_lsm_mode_names[] = {
597 "DA",
598 "IA",
599 "DB",
600 "IB"
601 };
602
603 /*
604 * The MSR field has a four bit field mask. Each bit correspons to a letter.
605 * From high to low, f, s, x, c. At least one must be specified, hence 0 is
606 * NULL. The preferred manual ordering of these is csxf.
607 */
608 static const char *arm_cdsp_msr_field_names[] = {
609 NULL,
610 "c", /* 0001 */
611 "x", /* 0010 */
612 "cx", /* 0011 */
613 "s", /* 0100 */
614 "cs", /* 0101 */
615 "sx", /* 0110 */
616 "csx", /* 0111 */
617 "f", /* 1000 */
618 "cf", /* 1001 */
619 "xf", /* 1010 */
620 "cxf", /* 1011 */
621 "sf", /* 1100 */
622 "csf", /* 1101 */
623 "sxf", /* 1110 */
624 "csxf" /* 1111 */
625 };
626
627 /*
628 * Names for specific saturating add and subtraction instructions from the
629 * extended control and dsp instructino section.
630 */
631 static const char *arm_cdsp_sat_opnames[] = {
632 "ADD",
633 "SUB",
634 "DADD",
635 "DSUB"
636 };
637
638 static const char *arm_padd_p_names[] = {
639 NULL, /* 000 */
640 "S", /* 001 */
641 "Q", /* 010 */
642 "SH", /* 011 */
643 NULL, /* 100 */
644 "U", /* 101 */
645 "UQ", /* 110 */
646 "UH", /* 111 */
647 };
648
649 static const char *arm_padd_i_names[] = {
650 "ADD16", /* 000 */
651 "ADDSUBX", /* 001 */
652 "SUBADDX", /* 010 */
653 "SUB16", /* 011 */
654 "ADD8", /* 100 */
655 NULL, /* 101 */
656 NULL, /* 110 */
657 "SUB8", /* 111 */
658 };
659
660 static const char *arm_extend_rot_names[] = {
661 "", /* 0b00, ROR #0 */
662 ", ROR #8", /* 0b01 */
663 ", ROR #16", /* 0b10 */
664 ", ROR #24" /* 0b11 */
665 };
666
667 /*
668 * There are sixteen data processing instructions (dpi). They come in a few
669 * different forms which are based on whether immediate values are used and
670 * whether or not some special purpose shifting is done. We use this one entry
671 * point to cover all the different types.
672 *
673 * From the ARM arch manual:
674 *
675 * <opcode1>{<cond>}{S} <Rd>,<shifter>
676 * <opcode1> := MOV | MVN
677 * <opcode2>{<cond>} <Rn>,<shifter>
678 * <opcode2> := CMP, CMN, TST, TEQ
679 * <opcode3>{<cond>{S} <Rd>,<Rn>, <shifter>
680 * <opcode3> := ADD | SUB | RSB | ADC | SBC | RSC | AND | BIC | EOR | ORR
681 *
682 * 31 - 28|27 26 |25 | 24-21 |20 | 19-16 | 15-12 | 11 - 0
683 * [ cond | 0 0 | I | opcode | S | Rn | Rd | shifter ]
684 *
761 ARM_DPI_IMS_SHIFT_MASK) >> ARM_DPI_IMS_SHIFT_SHIFT;
762 dpi_inst.dpii_un.dpii_si.dpiss_targ = in & ARM_DPI_IMS_RM_MASK;
763 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_ROR &&
764 dpi_inst.dpii_un.dpii_si.dpiss_imm == 0)
765 dpi_inst.dpii_un.dpii_si.dpiss_code = DPI_S_RRX;
766
767 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_LSL &&
768 dpi_inst.dpii_un.dpii_si.dpiss_imm == 0)
769 dpi_inst.dpii_un.dpii_si.dpiss_code = DPI_S_NONE;
770 }
771
772 /*
773 * Print everything before the shifter based on the instruction
774 */
775 switch (dpi_inst.dpii_op) {
776 case DPI_OP_MOV:
777 case DPI_OP_MVN:
778 len = snprintf(buf, buflen, "%s%s%s %s",
779 arm_dpi_opnames[dpi_inst.dpii_op],
780 arm_cond_names[dpi_inst.dpii_cond],
781 dpi_inst.dpii_sbit != 0 ? "S" : "",
782 arm_reg_names[dpi_inst.dpii_rd]);
783 break;
784 case DPI_OP_CMP:
785 case DPI_OP_CMN:
786 case DPI_OP_TST:
787 case DPI_OP_TEQ:
788 len = snprintf(buf, buflen, "%s%s %s",
789 arm_dpi_opnames[dpi_inst.dpii_op],
790 arm_cond_names[dpi_inst.dpii_cond],
791 arm_reg_names[dpi_inst.dpii_rn]);
792 break;
793 default:
794 len = snprintf(buf, buflen,
795 "%s%s%s %s, %s", arm_dpi_opnames[dpi_inst.dpii_op],
796 arm_cond_names[dpi_inst.dpii_cond],
797 dpi_inst.dpii_sbit != 0 ? "S" : "",
798 arm_reg_names[dpi_inst.dpii_rd],
799 arm_reg_names[dpi_inst.dpii_rn]);
800 break;
801 }
802
803 if (len >= buflen)
804 return (-1);
805 buflen -= len;
806 buf += len;
807
808 /*
809 * Print the shifter as appropriate
810 */
811 switch (dpi_inst.dpii_stype) {
812 case ARM_DPI_SHIFTER_IMM32: {
813 uint32_t rawimm, imm;
814 int rawrot, rot;
815
816 rawimm = dpi_inst.dpii_un.dpii_im.dpisi_imm;
817 rawrot = dpi_inst.dpii_un.dpii_im.dpisi_rot;
818
819 rot = rawrot * 2;
820 imm = (rawimm << (32 - rot)) | (rawimm >> rot);
821
822 len = snprintf(buf, buflen, ", #%u, %d ; 0x%08x", rawimm,
823 rawrot, imm);
824 break;
825 }
826 case ARM_DPI_SHIFTER_SIMM:
827 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_NONE) {
828 len = snprintf(buf, buflen, ", %s",
829 arm_reg_names[dpi_inst.dpii_un.dpii_si.dpiss_targ]);
830 break;
831 }
832 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_RRX) {
833 len = snprintf(buf, buflen, ", %s RRX",
834 arm_reg_names[dpi_inst.dpii_un.dpii_si.dpiss_targ]);
835 break;
836 }
837 len = snprintf(buf, buflen, ", %s, %s #%d",
838 arm_reg_names[dpi_inst.dpii_un.dpii_si.dpiss_targ],
839 arm_dpi_shifts[dpi_inst.dpii_un.dpii_si.dpiss_code],
840 dpi_inst.dpii_un.dpii_si.dpiss_imm);
841 break;
842 case ARM_DPI_SHIFTER_SREG:
843 len = snprintf(buf, buflen, ", %s, %s %s",
844 arm_reg_names[dpi_inst.dpii_un.dpii_ri.dpisr_targ],
845 arm_dpi_shifts[dpi_inst.dpii_un.dpii_ri.dpisr_code],
846 arm_reg_names[dpi_inst.dpii_un.dpii_ri.dpisr_val]);
847 break;
848 }
849
850 return (len < buflen ? 0 : -1);
851 }
852
853 /*
883 static int
884 arm_dis_ldstr(uint32_t in, char *buf, size_t buflen)
885 {
886 arm_cond_code_t cc;
887 arm_reg_t rd, rn, rm;
888 int ibit, pbit, ubit, bbit, wbit, lbit;
889 arm_dpi_shift_code_t sc;
890 uint8_t simm;
891 size_t len;
892
893 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
894 ibit = in & ARM_LS_IBIT_MASK;
895 pbit = in & ARM_LS_PBIT_MASK;
896 ubit = in & ARM_LS_UBIT_MASK;
897 bbit = in & ARM_LS_BBIT_MASK;
898 wbit = in & ARM_LS_WBIT_MASK;
899 lbit = in & ARM_LS_LBIT_MASK;
900 rd = (in & ARM_LS_RD_MASK) >> ARM_LS_RD_SHIFT;
901 rn = (in & ARM_LS_RN_MASK) >> ARM_LS_RN_SHIFT;
902
903 len = snprintf(buf, buflen, "%s%s%s%s %s, ", lbit != 0 ? "LDR" : "STR",
904 arm_cond_names[cc], bbit != 0 ? "B" : "",
905 (pbit == 0 && wbit != 0) ? "T" : "",
906 arm_reg_names[rd]);
907 if (len >= buflen)
908 return (-1);
909
910 /* Figure out the specifics of the encoding for the rest */
911 if (ibit == 0 && pbit != 0) {
912 /*
913 * This is the immediate offset mode (A5.2.2). That means that
914 * we have something of the form [ <Rn>, #+/-<offset_12> ]. All
915 * of the mode specific bits contribute to offset_12. We also
916 * handle the pre-indexed version (A5.2.5) which depends on the
917 * wbit being set.
918 */
919 len += snprintf(buf + len, buflen - len, "[%s, #%s%d]%s",
920 arm_reg_names[rn], ubit != 0 ? "" : "-",
921 in & ARM_LS_IMM_MASK, wbit != 0 ? "!" : "");
922 } else if (ibit != 0 && pbit != 0) {
923 /*
924 * This handles A5.2.2, A5.2.3, A5.2.6, and A5.2.7. We can have
925 * one of two options. If the non-rm bits (11-4) are all zeros
971 ARM_LS_SCR_SIMM_SHIFT;
972 sc = (in & ARM_LS_SCR_SCODE_MASK) >>
973 ARM_LS_SCR_SCODE_SHIFT;
974
975 if (simm == 0 && sc == DPI_S_ROR)
976 sc = DPI_S_RRX;
977
978 len += snprintf(buf + len, buflen - len, "%s",
979 arm_dpi_shifts[sc]);
980 if (len >= buflen)
981 return (-1);
982 if (sc != DPI_S_RRX)
983 len += snprintf(buf + len, buflen - len,
984 " #%d", simm);
985 }
986 }
987
988 return (len < buflen ? 0 : -1);
989 }
990
991 /*
992 * This handles load and store multiple instructions. The general format is as
993 * follows:
994 *
995 * 31 - 28|27 26 25|24|23|22|21|20|19-16|15-0
996 * [ cond | 1 0 0 |P |U |S |W |L | Rn | register set
997 *
998 * The register set has one bit per register. If a bit is set it indicates that
999 * register and if it is not set then it indicates that the register is not
1000 * included in this.
1001 *
1002 * S bit: If the instruction is a LDM and we load the PC, the S == 1 tells us to
1003 * load the CPSR from SPSR after the other regs are loaded. If the instruction
1004 * is a STM or LDM without touching the PC it indicates that if we are
1005 * privileged we should send the banked registers.
1006 *
1007 * L bit: Where this is a load or store. Load is active high.
1008 *
1009 * P bit: If P == 0 then Rn is included in the memory region transfers and its
1010 * location is dependent on the U bit. It is at the top (U == 0) or bottom (U ==
1020 *
1021 * The overal layout for this is
1022 * (LDM|STM){<cond>}<addressing mode> Rn{!}, <registers>{^}. Here the ! is based
1023 * on having the W bit set. The ^ bit depends on whether S is set or not.
1024 *
1025 * There are four normal addressing modes: IA, IB, DA, DB. There are also
1026 * corresponding stack addressing modes that exist. However we have no way of
1027 * knowing which are the ones being used, therefore we are going to default to
1028 * the non-stack versions which are listed as the primary.
1029 *
1030 * Finally the last useful bit is how the registers list is specified. It is a
1031 * comma separated list inside of { }. However, a user may separate a contiguous
1032 * range by the use of a -, eg. R0 - R4. However, it is impossible for us to map
1033 * back directly to what the user did. So for now, we punt on second down and
1034 * instead just list each indidvidual register rather than attempt a joining
1035 * routine.
1036 */
1037 static int
1038 arm_dis_ldstr_multi(uint32_t in, char *buf, size_t buflen)
1039 {
1040 int sbit, wbit, lbit, ii, cont;
1041 uint16_t regs, addr_mode;
1042 arm_reg_t rn;
1043 arm_cond_code_t cc;
1044 size_t len;
1045
1046 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1047 sbit = in & ARM_LSM_SBIT_MASK;
1048 wbit = in & ARM_LSM_WBIT_MASK;
1049 lbit = in & ARM_LSM_LBIT_MASK;
1050 rn = (in & ARM_LSM_RN_MASK) >> ARM_LSM_RN_SHIFT;
1051 regs = in & ARM_LSM_RLIST_MASK;
1052 addr_mode = (in & ARM_LSM_ADDR_MASK) >> ARM_LSM_ADDR_SHIFT;
1053
1054 len = snprintf(buf, buflen, "%s%s%s %s%s, { ",
1055 lbit != 0 ? "LDM" : "STM",
1056 arm_cond_names[cc],
1057 arm_lsm_mode_names[addr_mode],
1058 arm_reg_names[rn],
1059 wbit != 0 ? "!" : "");
1060
1061 cont = 0;
1062 for (ii = 0; ii < 16; ii++) {
1063 if (!(regs & (1 << ii)))
1064 continue;
1065
1066 len += snprintf(buf + len, buflen - len, "%s%s",
1067 cont > 0 ? ", " : "", arm_reg_names[ii]);
1068 if (len >= buflen)
1069 return (-1);
1070 cont++;
1071 }
1072
1073 len += snprintf(buf + len, buflen - len, " }%s", sbit != 0 ? "^" : "");
1074 return (len >= buflen ? -1 : 0);
1075 }
1076
1077 /*
1078 * Here we need to handle miscillaneous loads and stores. This is used to load
1079 * and store signed and unsigned half words. To load a signed byte. And to load
1080 * and store double words. There is no specific store routines for signed bytes
1081 * and halfwords as they are supposed to use the SRB and STRH. There are two
1082 * primary encodings this time. The general case looks like:
1083 *
1084 * 31 - 28|27 - 25|24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1085 * [ cond | 0 |P |U |I |W |L | Rn | Rd |amode|1|S|H|1|amode ]
1086 *
1087 * The I, P, U, and W bits specify the addressing mode.
1088 * The L, S, and H bits describe the type and size.
1089 * Rn: The base register used by the addressing mode
1090 * Rd: The register to load to or store from
1091 *
1092 * The other bits specifically mean:
1093 * I bit: If set to one the address specific pieces are immediate. Otherwise
1094 * they aren't.
1095 * P bit: If P is 0 used post-indexed addressing. If P is 1 its behavior is
1096 * based on the value of W.
1097 * U bit: If U is one the offset is added to the base otherwise subtracted
1098 * W bit: When P is one a value of W == 1 says that the resulting memory address
1111 * 1 | 1 | 1 | load signed halfword
1112 *
1113 * The final format of this is:
1114 * LDR|STR{<cond>}H|SH|SB|D <rd>, address_mode
1115 */
1116 static int
1117 arm_dis_els(uint32_t in, char *buf, size_t buflen)
1118 {
1119 arm_cond_code_t cc;
1120 arm_reg_t rn, rd;
1121 const char *iname, *suffix;
1122 int lbit, sbit, hbit, pbit, ubit, ibit, wbit;
1123 uint8_t imm;
1124 size_t len;
1125
1126 lbit = in & ARM_ELS_LBIT_MASK;
1127 sbit = in & ARM_ELS_SBIT_MASK;
1128 hbit = in & ARM_ELS_SBIT_MASK;
1129
1130 if (lbit || (sbit && hbit == 0))
1131 iname = "LDR";
1132 else
1133 iname = "STR";
1134
1135 if (sbit == 0 && hbit)
1136 suffix = "H";
1137 else if (lbit == 0)
1138 suffix = "D";
1139 else if (sbit && hbit == 0)
1140 suffix = "SB";
1141 else if (sbit && hbit)
1142 suffix = "SH";
1143
1144 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1145 rn = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
1146 rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1147
1148 len = snprintf(buf, buflen, "%s%s%s %s, ", iname, arm_cond_names[cc],
1149 suffix, arm_reg_names[rd]);
1150 if (len >= buflen)
1151 return (-1);
1152
1153 pbit = in & ARM_ELS_PBIT_MASK;
1154 ubit = in & ARM_ELS_UBIT_MASK;
1155 ibit = in & ARM_ELS_IBIT_MASK;
1156 wbit = in & ARM_ELS_WBIT_MASK;
1157
1158 if (pbit && ibit) {
1159 /* Handle A5.3.2 and A5.3.4 immediate offset and pre-indexed */
1160 /* Bits 11-8 form the upper 4 bits of imm */
1161 imm = (in & ARM_ELS_UP_AM_MASK) >> (ARM_ELS_UP_AM_SHIFT - 4);
1162 imm |= in & ARM_ELS_LOW_AM_MASK;
1185 arm_reg_names[in & ARM_ELS_LOW_AM_MASK]);
1186 }
1187
1188 return (len >= buflen ? -1 : 0);
1189 }
1190
1191 /*
1192 * Handle SWP and SWPB out of the extra loads/stores extensions.
1193 */
1194 static int
1195 arm_dis_swap(uint32_t in, char *buf, size_t buflen)
1196 {
1197 arm_cond_code_t cc;
1198 arm_reg_t rn, rd, rm;
1199
1200 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1201 rn = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
1202 rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1203 rm = in & ARM_ELS_RN_MASK;
1204
1205 if (snprintf(buf, buflen, "SWP%s%s %s, %s, [%s]",
1206 arm_cond_names[cc],
1207 (in & ARM_ELS_SWAP_BYTE_MASK) ? "B" : "",
1208 arm_reg_names[rd], arm_reg_names[rm], arm_reg_names[rn]) >=
1209 buflen)
1210 return (-1);
1211
1212 return (0);
1213 }
1214
1215 /*
1216 * Handle LDREX and STREX out of the extra loads/stores extensions.
1217 */
1218 static int
1219 arm_dis_lsexcl(uint32_t in, char *buf, size_t buflen)
1220 {
1221 arm_cond_code_t cc;
1222 arm_reg_t rn, rd, rm;
1223 int lbit;
1224 size_t len;
1225
1226 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1227 rn = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
1228 rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1229 rm = in & ARM_ELS_RN_MASK;
1230 lbit = in & ARM_ELS_LBIT_MASK;
1231
1232 len = snprintf(buf, buflen, "%s%sEX %s, ",
1233 lbit != 0 ? "LDR" : "STR",
1234 arm_cond_names[cc], arm_reg_names[rd]);
1235 if (len >= buflen)
1236 return (-1);
1237
1238 if (lbit)
1239 len += snprintf(buf + len, buflen - len, "[%s]",
1240 arm_reg_names[rn]);
1241 else
1242 len += snprintf(buf + len, buflen - len, "%s, [%s]",
1243 arm_reg_names[rm], arm_reg_names[rn]);
1244 return (len >= buflen ? -1 : 0);
1245 }
1246
1247 /*
1248 * This is designed to handle the multiplication instruction extension space.
1249 * Note that this doesn't actually cover all of the multiplication instructions
1250 * available in ARM, but all of the ones that are in this space. This includes
1251 * the following instructions:
1252 *
1253 *
1275 */
1276 static int
1277 arm_dis_extmul(uint32_t in, char *buf, size_t buflen)
1278 {
1279 arm_cond_code_t cc;
1280 arm_reg_t rd, rn, rs, rm;
1281 size_t len;
1282
1283 /*
1284 * RdHi is equal to rd here. RdLo is equal to Rn here.
1285 */
1286 rd = (in & ARM_EMULT_RD_MASK) >> ARM_EMULT_RD_SHIFT;
1287 rn = (in & ARM_EMULT_RN_MASK) >> ARM_EMULT_RN_SHIFT;
1288 rs = (in & ARM_EMULT_RS_MASK) >> ARM_EMULT_RS_SHIFT;
1289 rm = in & ARM_EMULT_RM_MASK;
1290
1291 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1292
1293 if ((in & ARM_EMULT_MA_MASK) == 0) {
1294 if (in & ARM_EMULT_ABIT_MASK) {
1295 len = snprintf(buf, buflen, "MLA%s%s %s, %s, %s, %s",
1296 arm_cond_names[cc],
1297 (in & ARM_EMULT_SBIT_MASK) ? "S" : "",
1298 arm_reg_names[rd], arm_reg_names[rm],
1299 arm_reg_names[rs], arm_reg_names[rs]);
1300 } else {
1301 len = snprintf(buf, buflen, "MUL%s%s %s, %s, %s",
1302 arm_cond_names[cc],
1303 (in & ARM_EMULT_SBIT_MASK) ? "S" : "",
1304 arm_reg_names[rd], arm_reg_names[rm],
1305 arm_reg_names[rs]);
1306
1307 }
1308 } else if ((in & ARM_EMULT_UMA_MASK) == ARM_EMULT_UMA_TARG) {
1309 len = snprintf(buf, buflen, "UMAAL%s %s, %s, %s, %s",
1310 arm_cond_names[cc], arm_reg_names[rn], arm_reg_names[rd],
1311 arm_reg_names[rm], arm_reg_names[rs]);
1312 } else if ((in & ARM_EMULT_MAL_MASK) == ARM_EMULT_MAL_TARG) {
1313 len = snprintf(buf, buflen, "%s%s%s%s %s, %s, %s, %s",
1314 (in & ARM_EMULT_UNBIT_MASK) ? "S" : "U",
1315 (in & ARM_EMULT_ABIT_MASK) ? "MLAL" : "MULL",
1316 arm_cond_names[cc],
1317 (in & ARM_EMULT_SBIT_MASK) ? "S" : "",
1318 arm_reg_names[rn], arm_reg_names[rd], arm_reg_names[rm],
1319 arm_reg_names[rs]);
1320 } else {
1321 /* Not a supported instruction in this space */
1322 return (-1);
1323 }
1324 return (len >= buflen ? -1 : 0);
1325 }
1326
1327 /*
1328 * Here we handle the three different cases of moving to and from the various
1329 * status registers in both register mode and in immediate mode.
1330 */
1331 static int
1332 arm_dis_status_regs(uint32_t in, char *buf, size_t buflen)
1333 {
1334 arm_cond_code_t cc;
1335 arm_reg_t rd, rm;
1336 uint8_t field;
1337 int imm;
1338 size_t len;
1339
1340 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1341
1342 if ((in & ARM_CDSP_MRS_MASK) == ARM_CDSP_MRS_TARG) {
1343 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1344 if (snprintf(buf, buflen, "MRS%s %s, %s", arm_cond_names[cc],
1345 arm_reg_names[rd],
1346 (in & ARM_CDSP_STATUS_RBIT) != 0 ? "SPSR" : "CPSR") >=
1347 buflen)
1348 return (-1);
1349 return (0);
1350 }
1351
1352 field = (in & ARM_CDSP_MSR_F_MASK) >> ARM_CDSP_MSR_F_SHIFT;
1353 len = snprintf(buf, buflen, "MSR%s %s_%s, ", arm_cond_names[cc],
1354 (in & ARM_CDSP_STATUS_RBIT) != 0 ? "SPSR" : "CPSR",
1355 arm_cdsp_msr_field_names[field]);
1356 if (len >= buflen)
1357 return (-1);
1358
1359 if (in & ARM_CDSP_MSR_ISIMM_MASK) {
1360 imm = in & ARM_CDSP_MSR_IMM_MASK;
1361 imm <<= (in & ARM_CDSP_MSR_RI_MASK) >> ARM_CDSP_MSR_RI_SHIFT;
1362 len += snprintf(buf + len, buflen - len, "#%d", imm);
1363 } else {
1364 rm = in & ARM_CDSP_RM_MASK;
1365 len += snprintf(buf + len, buflen - len, "%s",
1366 arm_reg_names[rm]);
1367 }
1368
1369 return (len >= buflen ? -1 : 0);
1370 }
1371
1372 /*
1373 * Here we need to handle the Control And DSP instruction extension space. This
1374 * consists of several different instructions. Unlike other extension spaces
1385 uint16_t imm, op;
1386 arm_cond_code_t cc;
1387 arm_reg_t rd, rm, rn, rs;
1388 size_t len;
1389
1390 if ((in & ARM_CDSP_STATUS_MASK) == ARM_CDSP_STATUS_TARG)
1391 return (arm_dis_status_regs(in, buf, buflen));
1392
1393 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1394
1395 /*
1396 * This gets the Branch/exchange as well as the Branch and link/exchange
1397 * pieces. These generally also transform the instruction set into
1398 * something we can't actually disassemble. Here the lower mask and
1399 * target is the opposite. eg. the target bits are not what we want.
1400 */
1401 if ((in & ARM_CDSP_BEX_UP_MASK) == ARM_CDSP_BEX_UP_TARG &&
1402 (in & ARM_CDSP_BEX_LOW_MASK) != ARM_CDSP_BEX_NLOW_TARG) {
1403 rm = in & ARM_CDSP_RM_MASK;
1404 imm = (in & ARM_CDSP_BEX_TYPE_MASK) >> ARM_CDSP_BEX_TYPE_SHIFT;
1405 if (snprintf(buf, buflen, "B%s%s %s",
1406 imm == ARM_CDSP_BEX_TYPE_X ? "X" :
1407 imm == ARM_CDSP_BEX_TYPE_J ? "XJ" : "LX",
1408 arm_cond_names[cc], arm_reg_names[rm]) >= buflen)
1409 return (-1);
1410 return (0);
1411 }
1412
1413 /* Count leading zeros */
1414 if ((in & ARM_CDSP_CLZ_MASK) == ARM_CDSP_CLZ_TARG) {
1415 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1416 rm = in & ARM_CDSP_RM_MASK;
1417 if (snprintf(buf, buflen, "CLZ%s %s, %s", arm_cond_names[cc],
1418 arm_reg_names[rd], arm_reg_names[rm]) >= buflen)
1419 return (-1);
1420 return (0);
1421 }
1422
1423 if ((in & ARM_CDSP_SAT_MASK) == ARM_CDSP_SAT_TARG) {
1424 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1425 rn = (in & ARM_CDSP_RN_MASK) >> ARM_CDSP_RN_SHIFT;
1426 rm = in & ARM_CDSP_RM_MASK;
1427 imm = (in & ARM_CDSP_SAT_OP_MASK) >> ARM_CDSP_SAT_OP_SHIFT;
1428 if (snprintf(buf, buflen, "Q%s%s %s, %s, %s",
1429 arm_cdsp_sat_opnames[imm], arm_cond_names[cc],
1430 arm_reg_names[rd], arm_reg_names[rm],
1431 arm_reg_names[rn]) >= buflen)
1432 return (-1);
1433 return (0);
1434 }
1435
1436 /*
1437 * Breakpoint instructions are a bit different. While they are in the
1438 * conditional instruction namespace, they actually aren't defined to
1439 * take a condition. That's just how it rolls. The breakpoint is a
1440 * 16-bit value. The upper 12 bits are stored together and the lower
1441 * four together.
1442 */
1443 if ((in & ARM_CDSP_BKPT_MASK) == ARM_CDSP_BKPT_TARG) {
1444 if (cc != ARM_COND_NACC)
1445 return (-1);
1446 imm = (in & ARM_CDSP_BKPT_UIMM_MASK) >>
1447 ARM_CDSP_BKPT_UIMM_SHIFT;
1448 imm <<= 4;
1449 imm |= (in & ARM_CDSP_BKPT_LIMM_MASK);
1450 if (snprintf(buf, buflen, "BKPT %d", imm) >= buflen)
1451 return (1);
1452 return (0);
1453 }
1454
1455 /*
1456 * Here we need to handle another set of multiplies. Specifically the
1457 * Signed multiplies. This is SMLA<x><y>, SMLAW<y>, SMULW<y>,
1458 * SMLAL<x><y>, SMUL<x><y>. These instructions all follow the form:
1459 *
1460 * 31 - 28|27-25|24|23|22-21|20|19-16|15-12|11 - 8|7|6|5|4|3-0
1461 * [ cond | 0 | 1| 0| op. | 0|Rn |Rd |Rs |1|y|x|0|Rm ]
1462 *
1463 * If x is one a T is used for that part of the name. Otherwise a B is.
1464 * The same holds true for y.
1465 *
1466 * These instructions map to the following opcodes:
1467 * SMLA<x><y>: 00,
1468 * SMLAW<y>: 01 and x is zero,
1469 * SMULW<y>: 01 and x is one ,
1470 * SMLAL<x><y>: 10,
1471 * SMUL<xy><y>: 11
1472 */
1473 if ((in & ARM_CDSP_SMUL_MASK) == ARM_CDSP_SMUL_TARG) {
1474 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1475 rn = (in & ARM_CDSP_RN_MASK) >> ARM_CDSP_RN_SHIFT;
1476 rs = (in & ARM_CDSP_RS_MASK) >> ARM_CDSP_RS_SHIFT;
1477 rm = in & ARM_CDSP_RM_MASK;
1478 op = (in & ARM_CDSP_SMUL_OP_MASK) >> ARM_CDSP_SMUL_OP_SHIFT;
1479
1480 switch (op) {
1481 case 0:
1482 len = snprintf(buf, buflen, "SMLA%s%s%s %s, %s, %s, %s",
1483 (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "T" : "B",
1484 (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "T" : "B",
1485 arm_cond_names[cc], arm_reg_names[rd],
1486 arm_reg_names[rm], arm_reg_names[rs],
1487 arm_reg_names[rn]);
1488 break;
1489 case 1:
1490 if (in & ARM_CDSP_SMUL_X_MASK) {
1491 len = snprintf(buf, buflen,
1492 "SMULW%s%s %s, %s, %s",
1493 (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "T" :
1494 "B", arm_cond_names[cc], arm_reg_names[rd],
1495 arm_reg_names[rm], arm_reg_names[rs]);
1496 } else {
1497 len = snprintf(buf, buflen,
1498 "SMLAW%s%s %s, %s, %s %s",
1499 (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "T" :
1500 "B", arm_cond_names[cc], arm_reg_names[rd],
1501 arm_reg_names[rm], arm_reg_names[rs],
1502 arm_reg_names[rn]);
1503 }
1504 break;
1505 case 2:
1506 len = snprintf(buf, buflen,
1507 "SMLAL%s%s%s %s, %s, %s, %s",
1508 (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "T" : "B",
1509 (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "T" : "B",
1510 arm_cond_names[cc], arm_reg_names[rd],
1511 arm_reg_names[rn], arm_reg_names[rm],
1512 arm_reg_names[rs]);
1513 break;
1514 case 3:
1515 len = snprintf(buf, buflen, "SMUL%s%s%s %s, %s, %s",
1516 (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "T" : "B",
1517 (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "T" : "B",
1518 arm_cond_names[cc], arm_reg_names[rd],
1519 arm_reg_names[rm], arm_reg_names[rs]);
1520 break;
1521 default:
1522 return (-1);
1523 }
1524 return (len >= buflen ? -1 : 0);
1525 }
1526
1527 /*
1528 * If we got here then this is some other instructin we don't know
1529 * about in the instruction extensino space.
1530 */
1531 return (-1);
1532 }
1533
1534 /*
1535 * Coprocessor double register transfers
1536 *
1537 * MCRR:
1547 arm_dis_coproc_drt(uint32_t in, char *buf, size_t buflen)
1548 {
1549 arm_cond_code_t cc;
1550 arm_reg_t rd, rn, rm;
1551 uint8_t coproc, op;
1552 const char *ccn;
1553 size_t len;
1554
1555 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1556 coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1557 rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1558 rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1559 rm = in & ARM_COPROC_RM_MASK;
1560 op = (in & ARM_COPROC_DRT_OP_MASK) >> ARM_COPROC_DRT_OP_SHIFT;
1561
1562 if (cc == ARM_COND_NACC)
1563 ccn = "2";
1564 else
1565 ccn = arm_cond_names[cc];
1566
1567 len = snprintf(buf, buflen, "%s%s %s, #%d, %s, %s, C%s",
1568 (in & ARM_COPROC_DRT_DIR_MASK) != 0 ? "MRRC" : "MCRR",
1569 ccn, arm_coproc_names[coproc], op, arm_reg_names[rd],
1570 arm_reg_names[rn], arm_reg_names[rm]);
1571 return (len >= buflen ? -1 : 0);
1572 }
1573
1574 /*
1575 * This serves as both the entry point for the normal load and stores as well as
1576 * the double register transfers (MCRR and MRCC). If it is a register transfer
1577 * then we quickly send it off.
1578 * LDC:
1579 * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11 - 8|7 - 0
1580 * [ cond |1 1 0| P| U| N| W| L| Rn | CRd | cp # | off ]
1581 *
1582 * STC:
1583 * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11 - 8|7 - 0
1584 * [ cond |1 1 0| P| U| N| W| L| Rn | CRd | cp # | off ]
1585 *
1586 * Here the bits mean:
1587 *
1588 * P bit: If P is zero, it is post-indexed or unindexed based on W. If P is 1
1613 if ((in & ARM_COPROC_DRT_MASK) == ARM_COPROC_DRT_TARG)
1614 return (arm_dis_coproc_drt(in, buf, buflen));
1615
1616 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1617 coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1618 rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1619 rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1620 imm = in & ARM_COPROC_LS_IMM_MASK;
1621
1622 pbit = in & ARM_COPROC_LS_P_MASK;
1623 ubit = in & ARM_COPROC_LS_U_MASK;
1624 nbit = in & ARM_COPROC_LS_N_MASK;
1625 wbit = in & ARM_COPROC_LS_W_MASK;
1626 lbit = in & ARM_COPROC_LS_L_MASK;
1627
1628 if (cc == ARM_COND_NACC)
1629 ccn = "2";
1630 else
1631 ccn = arm_cond_names[cc];
1632
1633 len = snprintf(buf, buflen, "%s%s%s %s, C%s, ",
1634 lbit != 0 ? "LDC" : "STC", ccn, nbit != 0 ? "L" : "",
1635 arm_coproc_names[coproc], arm_reg_names[rd]);
1636 if (len >= buflen)
1637 return (-1);
1638
1639 if (pbit != 0) {
1640 imm *= 4;
1641 len += snprintf(buf + len, buflen - len, "[%s, #%s%d]%s",
1642 arm_reg_names[rn],
1643 ubit != 0 ? "" : "-", imm,
1644 wbit != 0 ? "!" : "");
1645 } else if (wbit != 0) {
1646 imm *= 4;
1647 len += snprintf(buf + len, buflen - len, "[%s], #%s%d",
1648 arm_reg_names[rn], ubit != 0 ? "" : "-", imm);
1649 } else {
1650 len += snprintf(buf + len, buflen - len, "[%s], { %d }",
1651 arm_reg_names[rn], imm);
1652 }
1653 return (len >= buflen ? -1 : 0);
1654 }
1668 uint8_t op1, op2, coproc;
1669 const char *ccn;
1670
1671 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1672 coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1673 rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1674 rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1675 rm = in & ARM_COPROC_RM_MASK;
1676 op1 = (in & ARM_COPROC_CDP_OP1_MASK) >> ARM_COPROC_CDP_OP1_SHIFT;
1677 op2 = (in & ARM_COPROC_CDP_OP2_MASK) >> ARM_COPROC_CDP_OP2_SHIFT;
1678
1679 /*
1680 * This instruction is valid with the undefined condition code. When it
1681 * does that, the instruction is intead CDP2 as opposed to CDP.
1682 */
1683 if (cc == ARM_COND_NACC)
1684 ccn = "2";
1685 else
1686 ccn = arm_cond_names[cc];
1687
1688 if (snprintf(buf, buflen, "CDP%s %s, #%d, C%s, C%s, C%s, #%d", ccn,
1689 arm_coproc_names[coproc], op1, arm_reg_names[rd],
1690 arm_reg_names[rn], arm_reg_names[rm], op2) >= buflen)
1691 return (-1);
1692
1693 return (0);
1694 }
1695
1696 /*
1697 * Here we handle coprocesser single register transfers.
1698 *
1699 * MCR:
1700 * 31 - 28|27 - 24|23-21|20|19-16|15-12|11 - 8|7 - 5|4|3-0
1701 * [ cond |1 1 1 0| op_1| 0| CRn | Rd | cp # | op_2|1|CRm ]
1702 *
1703 * MRC:
1704 * 31 - 28|27 - 24|23-21|20|19-16|15-12|11 - 8|7 - 5|4|3-0
1705 * [ cond |1 1 1 0| op_1| 1| CRn | Rd | cp # | op_2|1|CRm ]
1706 */
1707 static int
1708 arm_dis_coproc_rt(uint32_t in, char *buf, size_t buflen)
1709 {
1710 arm_cond_code_t cc;
1711 arm_reg_t rn, rd, rm;
1712 uint8_t op1, op2, coproc;
1713 const char *ccn;
1714 size_t len;
1715
1716 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1717 coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1718 rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1719 rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1720 rm = in & ARM_COPROC_RM_MASK;
1721 op1 = (in & ARM_COPROC_CRT_OP1_MASK) >> ARM_COPROC_CRT_OP1_SHIFT;
1722 op2 = (in & ARM_COPROC_CRT_OP2_MASK) >> ARM_COPROC_CRT_OP2_SHIFT;
1723
1724 if (cc == ARM_COND_NACC)
1725 ccn = "2";
1726 else
1727 ccn = arm_cond_names[cc];
1728
1729 len = snprintf(buf, buflen, "%s%s %s, #%d, %s, C%s, C%s",
1730 (in & ARM_COPROC_CRT_DIR_MASK) != 0 ? "MRC" : "MCR", ccn,
1731 arm_coproc_names[coproc], op1, arm_reg_names[rd],
1732 arm_reg_names[rn], arm_reg_names[rm]);
1733 if (len >= buflen)
1734 return (-1);
1735
1736 if (op2 != 0)
1737 if (snprintf(buf + len, buflen - len, ", #%d", op2) >=
1738 buflen - len)
1739 return (-1);
1740 return (0);
1741 }
1742
1743 /*
1744 * Here we handle the set of unconditional instructions.
1745 */
1746 static int
1747 arm_dis_uncond_insn(uint32_t in, char *buf, size_t buflen)
1748 {
1749 int imm, sc;
1750 arm_reg_t rn, rm;
1764 * effect: determines what to do with the A, I, F interrupt bits in the
1765 * CPSR. effect is encoded in the imod field. It is either enable
1766 * interrupts 0b10 or disable interrupts 0b11. Recall that interrupts
1767 * are active low in the CPSR. If effect is not specified then this is
1768 * strictly a mode change which is required.
1769 *
1770 * A, I, F: If effect is specified then the bits which are high are
1771 * modified by the instruction.
1772 *
1773 * mode: Specifies a mode to change to. mmod will be 1 if mode is set.
1774 *
1775 */
1776 if ((in & ARM_UNI_CPS_MASK) == ARM_UNI_CPS_TARG) {
1777 imm = (in & ARM_UNI_CPS_IMOD_MASK) > ARM_UNI_CPS_IMOD_SHIFT;
1778
1779 /* Ob01 is not a valid value for the imod */
1780 if (imm == 1)
1781 return (-1);
1782
1783 if (imm != 0)
1784 len = snprintf(buf, buflen, "CPS%s %s%s%s%s",
1785 imm == 2 ? "IE" : "ID",
1786 (in & ARM_UNI_CPS_A_MASK) ? "a" : "",
1787 (in & ARM_UNI_CPS_I_MASK) ? "i" : "",
1788 (in & ARM_UNI_CPS_F_MASK) ? "f" : "",
1789 (in & ARM_UNI_CPS_MMOD_MASK) ? " ," : "");
1790 else
1791 len = snprintf(buf, buflen, "CPS ");
1792 if (len >= buflen)
1793 return (-1);
1794
1795 if (in & ARM_UNI_CPS_MMOD_MASK)
1796 if (snprintf(buf + len, buflen - len, "#%d",
1797 in & ARM_UNI_CPS_MODE_MASK) >= buflen - len)
1798 return (-1);
1799 return (0);
1800 }
1801
1802 if ((in & ARM_UNI_SE_MASK) == ARM_UNI_SE_TARG) {
1803 if (snprintf(buf, buflen, "SETEND %s",
1804 (in & ARM_UNI_SE_BE_MASK) ? "BE" : "LE") >= buflen)
1805 return (-1);
1806 return (0);
1807 }
1808
1809 /*
1810 * The cache preload is like a load, but it has a much simpler set of
1811 * constraints. The only valid bits that you can transform are the I and
1812 * the U bits. We have to use pre-indexed addressing. This means that we
1813 * only have the U bit and the I bit. See arm_dis_ldstr for a full
1814 * explanation of what's happening here.
1815 */
1816 if ((in & ARM_UNI_PLD_MASK) == ARM_UNI_PLD_TARG) {
1817 rn = (in & ARM_LS_RN_MASK) >> ARM_LS_RN_SHIFT;
1818 if ((in & ARM_LS_IBIT_MASK) == 0) {
1819 if (snprintf(buf, buflen, "PLD [%s, #%s%d",
1820 arm_reg_names[rn],
1821 (in & ARM_LS_UBIT_MASK) != 0 ? "" : "-",
1822 in & ARM_LS_IMM_MASK) >= buflen)
1823 return (-1);
1824 return (0);
1825 }
1826
1827 rm = in & ARM_LS_REG_RM_MASK;
1828 len = snprintf(buf, buflen, "PLD [%s, %s%s", arm_reg_names[rn],
1829 (in & ARM_LS_UBIT_MASK) != 0 ? "" : "-",
1830 arm_reg_names[rm]);
1831 if (len >= buflen)
1832 return (-1);
1833
1834 if ((in & ARM_LS_REG_NRM_MASK) != 0) {
1835 imm = (in & ARM_LS_SCR_SIMM_MASK) >>
1836 ARM_LS_SCR_SIMM_SHIFT;
1837 sc = (in & ARM_LS_SCR_SCODE_MASK) >>
1838 ARM_LS_SCR_SCODE_SHIFT;
1839
1840 if (imm == 0 && sc == DPI_S_ROR)
1841 sc = DPI_S_RRX;
1842
1843 len += snprintf(buf + len, buflen - len, "%s",
1844 arm_dpi_shifts[sc]);
1845 if (len >= buflen)
1846 return (-1);
1847 if (sc != DPI_S_RRX) {
1848 len += snprintf(buf + len, buflen - len,
1849 " #%d", imm);
1850 if (len >= buflen)
1851 return (-1);
1852 }
1853 }
1854 if (snprintf(buf + len, buflen - len, "]") >= buflen - len)
1855 return (-1);
1856 return (0);
1857 }
1858
1859 /*
1860 * This is a special case of STM, but it works across chip modes.
1861 */
1862 if ((in & ARM_UNI_SRS_MASK) == ARM_UNI_SRS_TARG) {
1863 imm = (in & ARM_LSM_ADDR_MASK) >> ARM_LSM_ADDR_SHIFT;
1864 if (snprintf(buf, buflen, "SRS%s #%d%s",
1865 arm_lsm_mode_names[imm],
1866 in & ARM_UNI_SRS_MODE_MASK,
1867 (in & ARM_UNI_SRS_WBIT_MASK) != 0 ? "!" : "") >= buflen)
1868 return (-1);
1869 return (0);
1870 }
1871
1872 /*
1873 * RFE is a return from exception instruction that is similar to the LDM
1874 * and STM, but a bit different.
1875 */
1876 if ((in & ARM_UNI_RFE_MASK) == ARM_UNI_RFE_TARG) {
1877 imm = (in & ARM_LSM_ADDR_MASK) >> ARM_LSM_ADDR_SHIFT;
1878 rn = (in & ARM_LS_RN_MASK) >> ARM_LS_RN_SHIFT;
1879 if (snprintf(buf, buflen, "RFE%s %s%s", arm_lsm_mode_names[imm],
1880 arm_reg_names[rn],
1881 (in & ARM_UNI_RFE_WBIT_MASK) != 0 ? "!" : "") >= buflen)
1882 return (-1);
1883 return (0);
1884 }
1885
1886 if ((in & ARM_UNI_BLX_MASK) == ARM_UNI_BLX_TARG) {
1887 if (snprintf(buf, buflen, "BLX %d",
1888 in & ARM_UNI_BLX_IMM_MASK) >= buflen)
1889 return (-1);
1890 return (0);
1891 }
1892
1893 if ((in & ARM_UNI_CODRT_MASK) == ARM_UNI_CODRT_TARG) {
1894 return (arm_dis_coproc_lsdrt(in, buf, buflen));
1895 }
1896
1897 if ((in & ARM_UNI_CORT_MASK) == ARM_UNI_CORT_TARG) {
1898 return (arm_dis_coproc_rt(in, buf, buflen));
1899 }
1900
1901 if ((in & ARM_UNI_CODP_MASK) == ARM_UNI_CORT_TARG) {
1902 return (arm_dis_coproc_dp(in, buf, buflen));
1903 }
1904
1905 /*
1906 * An undefined or illegal instruction
1907 */
1912 * Disassemble B and BL instructions. The instruction is given a 24-bit two's
1913 * complement value as an offset address. This value gets sign extended to 30
1914 * bits and then shifted over two bits. This is then added to the PC + 8. So,
1915 * instead of dispalying an absolute address, we're going to display the delta
1916 * that the instruction has instead.
1917 */
1918 static int
1919 arm_dis_branch(dis_handle_t *dhp, uint32_t in, char *buf, size_t buflen)
1920 {
1921 uint32_t addr;
1922 arm_cond_code_t cc;
1923 size_t len;
1924
1925 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1926 addr = in & ARM_BRANCH_IMM_MASK;
1927 if (in & ARM_BRANCH_SIGN_MASK)
1928 addr |= ARM_BRANCH_NEG_SIGN;
1929 else
1930 addr &= ARM_BRANCH_POS_SIGN;
1931 addr <<= 2;
1932 if ((len = snprintf(buf, buflen, "B%s%s %d",
1933 (in & ARM_BRANCH_LBIT_MASK) != 0 ? "L" : "",
1934 arm_cond_names[cc], (int)addr)) >= buflen)
1935 return (-1);
1936
1937 /* Per the ARM manuals, we have to account for the extra 8 bytes here */
1938 if (dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int)addr + 8, NULL, 0,
1939 NULL, NULL) == 0) {
1940 len += snprintf(buf + len, buflen - len, "\t<");
1941 if (len >= buflen)
1942 return (-1);
1943 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int)addr + 8,
1944 buf + len, buflen - len, NULL, NULL);
1945 strlcat(buf, ">", buflen);
1946 }
1947
1948 return (0);
1949 }
1950
1951 /*
1952 * There are six instructions that are covered here: ADD16, ADDSUBX, SUBADDX,
1953 * SUB16, ADD8, and SUB8. They can hae the following variations: S, Q, SH, U,
2014 arm_dis_extend(uint32_t in, char *buf, size_t buflen)
2015 {
2016 uint8_t op, rot;
2017 int sbit;
2018 arm_cond_code_t cc;
2019 arm_reg_t rn, rm, rd;
2020 const char *opn;
2021 size_t len;
2022
2023
2024 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2025 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2026 rm = in & ARM_MEDIA_RM_MASK;
2027 op = (in & ARM_MEDIA_SZE_OP_MASK) >> ARM_MEDIA_SZE_OP_SHIFT;
2028 rot = (in & ARM_MEDIA_SZE_ROT_MASK) >> ARM_MEDIA_SZE_ROT_SHIFT;
2029 sbit = in & ARM_MEDIA_SZE_S_MASK;
2030 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2031
2032 switch (op) {
2033 case 0x0:
2034 opn = rn == ARM_REG_R15 ? "XTAB16" : "XTB16";
2035 break;
2036 case 0x2:
2037 opn = rn == ARM_REG_R15 ? "XTAB" : "XTB";
2038 break;
2039 case 0x3:
2040 opn = rn == ARM_REG_R15 ? "XTAH" : "XTH";
2041 break;
2042 default:
2043 return (-1);
2044 break;
2045 }
2046
2047 if (rn == ARM_REG_R15) {
2048 len = snprintf(buf, buflen, "%s%s%s %s, %s",
2049 sbit != 0 ? "U" : "S",
2050 opn, arm_cond_names[cc], arm_reg_names[rd],
2051 arm_reg_names[rn]);
2052 } else {
2053 len = snprintf(buf, buflen, "%s%s%s %s, %s, %s",
2054 sbit != 0 ? "U" : "S",
2055 opn, arm_cond_names[cc], arm_reg_names[rd],
2056 arm_reg_names[rn], arm_reg_names[rm]);
2057 }
2058
2059 if (len >= buflen)
2060 return (-1);
2061
2062 if (snprintf(buf + len, buflen - len, "%s",
2063 arm_extend_rot_names[rot]) >= buflen - len)
2064 return (-1);
2065 return (0);
2066 }
2067
2068 /*
2069 * The media instructions and extensions can be divided into different groups of
2070 * instructions. We first use bits 23 and 24 to figure out where to send it. We
2071 * call this group of bits the l1 mask.
2072 */
2073 static int
2074 arm_dis_media(uint32_t in, char *buf, size_t buflen)
2077 arm_cond_code_t cc;
2078 arm_reg_t rd, rn, rs, rm;
2079 int xbit;
2080 size_t len;
2081
2082 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2083 l1 = (in & ARM_MEDIA_L1_MASK) >> ARM_MEDIA_L1_SHIFT;
2084 switch (l1) {
2085 case 0x0:
2086 return (arm_dis_padd(in, buf, buflen));
2087 break;
2088 case 0x1:
2089 if ((in & ARM_MEDIA_HPACK_MASK) == ARM_MEDIA_HPACK_TARG) {
2090 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2091 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2092 rm = in & ARM_MEDIA_RM_MASK;
2093 op1 = (in & ARM_MEDIA_HPACK_SHIFT_MASK) >>
2094 ARM_MEDIA_HPACK_SHIFT_IMM;
2095 len = snprintf(buf, buflen, "%s%s %s, %s, %s",
2096 (in & ARM_MEDIA_HPACK_OP_MASK) != 0 ?
2097 "PKHTB" : "PKHBT", arm_cond_names[cc],
2098 arm_reg_names[rd], arm_reg_names[rn],
2099 arm_reg_names[rd]);
2100 if (len >= buflen)
2101 return (-1);
2102
2103 if (op1 != 0) {
2104 if (in & ARM_MEDIA_HPACK_OP_MASK)
2105 len += snprintf(buf + len, buflen - len,
2106 ", ASR %d", op1);
2107 else
2108 len += snprintf(buf + len, buflen - len,
2109 ", LSL %d", op1);
2110 }
2111 return (len >= buflen ? -1 : 0);
2112 }
2113
2114 if ((in & ARM_MEDIA_WSAT_MASK) == ARM_MEDIA_WSAT_TARG) {
2115 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2116 rm = in & ARM_MEDIA_RM_MASK;
2117 op1 = (in & ARM_MEDIA_SAT_IMM_MASK) >>
2118 ARM_MEDIA_SAT_IMM_SHIFT;
2119 op2 = (in & ARM_MEDIA_SAT_SHI_MASK) >>
2120 ARM_MEDIA_SAT_SHI_SHIFT;
2121 len = snprintf(buf, buflen, "%s%s %s, #%d, %s",
2122 (in & ARM_MEDIA_SAT_U_MASK) != 0 ? "USAT" : "SSAT",
2123 arm_cond_names[cc], arm_reg_names[rd], op1,
2124 arm_reg_names[rm]);
2125
2126 if (len >= buflen)
2127 return (-1);
2128
2129 /*
2130 * The shift is optional in the assembler and encoded as
2131 * LSL 0. However if we get ASR 0, that means ASR #32.
2132 * An ARM_MEDIA_SAT_STYPE_MASK of 0 is LSL, 1 is ASR.
2133 */
2134 if (op2 != 0 || (in & ARM_MEDIA_SAT_STYPE_MASK) == 1) {
2135 if (op2 == 0)
2136 op2 = 32;
2137 if (snprintf(buf + len, buflen - len,
2138 ", %s #%d",
2139 (in & ARM_MEDIA_SAT_STYPE_MASK) != 0 ?
2140 "ASR" : "LSL", op2) >= buflen - len)
2141 return (-1);
2142 }
2143 return (0);
2144 }
2145
2146 if ((in & ARM_MEDIA_PHSAT_MASK) == ARM_MEDIA_PHSAT_TARG) {
2147 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2148 rm = in & ARM_MEDIA_RM_MASK;
2149 op1 = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2150 if (snprintf(buf, buflen, "%s%s %s, #%d, %s",
2151 (in & ARM_MEDIA_SAT_U_MASK) != 0 ?
2152 "USAT16" : "SSAT16",
2153 arm_cond_names[cc], arm_reg_names[rd], op1,
2154 arm_reg_names[rm]) >= buflen)
2155 return (-1);
2156 return (0);
2157 }
2158
2159 if ((in & ARM_MEDIA_REV_MASK) == ARM_MEDIA_REV_TARG) {
2160 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2161 rm = in & ARM_MEDIA_RM_MASK;
2162 if (snprintf(buf, buflen, "REV%s %s, %s",
2163 arm_cond_names[cc], arm_reg_names[rd],
2164 arm_reg_names[rd]) >= buflen)
2165 return (-1);
2166 return (0);
2167 }
2168
2169 if ((in & ARM_MEDIA_BRPH_MASK) == ARM_MEDIA_BRPH_TARG) {
2170 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2171 rm = in & ARM_MEDIA_RM_MASK;
2172 if (snprintf(buf, buflen, "REV16%s %s, %s",
2173 arm_cond_names[cc], arm_reg_names[rd],
2174 arm_reg_names[rd]) >= buflen)
2175 return (-1);
2176 return (0);
2177 }
2178
2179 if ((in & ARM_MEDIA_BRSH_MASK) == ARM_MEDIA_BRSH_TARG) {
2180 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2181 rm = in & ARM_MEDIA_RM_MASK;
2182 if (snprintf(buf, buflen, "REVSH%s %s, %s",
2183 arm_cond_names[cc], arm_reg_names[rd],
2184 arm_reg_names[rd]) >= buflen)
2185 return (-1);
2186 return (0);
2187 }
2188
2189 if ((in & ARM_MEDIA_SEL_MASK) == ARM_MEDIA_SEL_TARG) {
2190 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2191 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2192 rm = in & ARM_MEDIA_RM_MASK;
2193 if (snprintf(buf, buflen, "SEL%s %s, %s, %s",
2194 arm_cond_names[cc], arm_reg_names[rd],
2195 arm_reg_names[rn], arm_reg_names[rm]) >= buflen)
2196 return (-1);
2197 return (0);
2198 }
2199
2200 if ((in & ARM_MEDIA_SZE_MASK) == ARM_MEDIA_SZE_TARG)
2201 return (arm_dis_extend(in, buf, buflen));
2202 /* Unknown instruction */
2203 return (-1);
2204 break;
2205 case 0x2:
2206 /*
2207 * This consists of the following multiply instructions:
2208 * SMLAD, SMLSD, SMLALD, SMUAD, and SMUSD.
2209 *
2210 * SMLAD and SMUAD encoding are the same, switch on Rn == R15
2211 * 22-20 are 000 7-6 are 00
2212 * SMLSD and SMUSD encoding are the same, switch on Rn == R15
2213 * 22-20 are 000 7-6 are 01
2214 * SMLALD: 22-20 are 100 7-6 are 00
2215 */
2216 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2217 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2218 rs = (in & ARM_MEDIA_RS_MASK) >> ARM_MEDIA_RS_SHIFT;
2219 rm = in & ARM_MEDIA_RM_MASK;
2220 op1 = (in & ARM_MEDIA_OP1_MASK) >> ARM_MEDIA_OP1_SHIFT;
2221 op2 = (in & ARM_MEDIA_OP2_MASK) >> ARM_MEDIA_OP2_SHIFT;
2222 xbit = in & ARM_MEDIA_MULT_X_MASK;
2223
2224 if (op1 == 0x0) {
2225 if (op2 != 0x0 && op2 != 0x1)
2226 return (-1);
2227 if (rn == ARM_REG_R15) {
2228 len = snprintf(buf, buflen, "%s%s%s %s, %s, %s",
2229 op2 != 0 ? "SMUSD" : "SMUAD",
2230 xbit != 0 ? "X" : "X",
2231 arm_cond_names[cc], arm_reg_names[rd],
2232 arm_reg_names[rm], arm_reg_names[rs]);
2233 } else {
2234 len = snprintf(buf, buflen,
2235 "%s%s%s %s, %s, %s, %s",
2236 op2 != 0 ? "SMLSD" : "SMLAD",
2237 xbit != 0 ? "X" : "",
2238 arm_cond_names[cc], arm_reg_names[rd],
2239 arm_reg_names[rm], arm_reg_names[rs],
2240 arm_reg_names[rn]);
2241
2242 }
2243 } else if (op1 == 0x8) {
2244 if (op2 != 0x0)
2245 return (-1);
2246 len = snprintf(buf, buflen, "SMLALD%s%s %s, %s, %s, %s",
2247 xbit != 0 ? "X" : "",
2248 arm_cond_names[cc], arm_reg_names[rn],
2249 arm_reg_names[rd], arm_reg_names[rm],
2250 arm_reg_names[rs]);
2251 } else
2252 return (-1);
2253
2254 return (len >= buflen ? -1 : 0);
2255 break;
2256 case 0x3:
2257 /*
2258 * Here we handle USAD8 and USADA8. The main difference is the
2259 * presence of RN. USAD8 is defined as having a value of rn that
2260 * is not r15. If it is r15, then instead it is USADA8.
2261 */
2262 if ((in & ARM_MEDIA_OP1_MASK) != 0)
2263 return (-1);
2264 if ((in & ARM_MEDIA_OP2_MASK) != 0)
2265 return (-1);
2266
2267 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2268 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2269 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2270 rs = (in & ARM_MEDIA_RS_MASK) >> ARM_MEDIA_RS_SHIFT;
2271 rm = in & ARM_MEDIA_RM_MASK;
2272
2273 if (rn != ARM_REG_R15)
2274 len = snprintf(buf, buflen, "USADA8%s %s, %s, %s, %s",
2275 arm_cond_names[cc], arm_reg_names[rd],
2276 arm_reg_names[rm], arm_reg_names[rs],
2277 arm_reg_names[rn]);
2278 else
2279 len = snprintf(buf, buflen, "USAD8%s %s, %s, %s",
2280 arm_cond_names[cc], arm_reg_names[rd],
2281 arm_reg_names[rm], arm_reg_names[rs]);
2282 return (len >= buflen ? -1 : 0);
2283 break;
2284 default:
2285 return (-1);
2286 }
2287 }
2288
2289 /*
2290 * Each instruction in the ARM instruction set is a uint32_t and in our case is
2291 * LE. The upper four bits determine the condition code. If the conditoin code
2292 * is undefined then we know to immediately jump there. Otherwise we go use the
2293 * next three bits to determine where we should go next and how to further
2294 * process the instruction in question. The ARM instruction manual doesn't
2295 * define this field so we're going to call it the L1_DEC or level 1 decoding
2296 * from which it will have to be further subdivided into the specific
2297 * instruction groupings that we care about.
2298 */
2299 static int
2432 /* coprocessor load/store && double register transfers */
2433 return (arm_dis_coproc_lsdrt(in, buf, buflen));
2434 break;
2435 case 0x7:
2436 /*
2437 * In l1 group 0b111 you can determine the three groups using
2438 * the following logic. If the next bit after the l1 group (bit
2439 * 24) is one than you know that it is a software interrupt.
2440 * Otherwise it is one of the coprocessor instructions.
2441 * Furthermore you can tell apart the data processing from the
2442 * register transfers based on bit 4. If it is zero then it is
2443 * a data processing instruction, otherwise it is a register
2444 * transfer.
2445 */
2446 if (in & ARM_L1_7_SWINTMASK) {
2447 /*
2448 * The software interrupt is pretty straightforward. The
2449 * lower 24 bits are the interrupt number. It's also
2450 * valid for it to run with a condition code.
2451 */
2452 if (snprintf(buf, buflen, "SWI%s %d",
2453 arm_cond_names[cc],
2454 in & ARM_SWI_IMM_MASK) >= buflen)
2455 return (-1);
2456 return (0);
2457 } else if (in & ARM_L1_7_COPROCMASK) {
2458 /* coprocessor register transfers */
2459 return (arm_dis_coproc_rt(in, buf, buflen));
2460 } else {
2461 /* coprocessor data processing */
2462 return (arm_dis_coproc_dp(in, buf, buflen));
2463 }
2464 break;
2465 }
2466
2467 return (-1);
2468 }
2469
2470 static int
2471 dis_arm_supports_flags(int flags)
2472 {
|
8 * http://www.illumos.org/license/CDDL.
9 */
10 /*
11 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
12 * Copyright (c) 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
13 */
14
15 /*
16 * This provides basic support for disassembling arm instructions. This is
17 * derived from the arm reference manual (generic), chapter A3 (ARM DDI 0100l).
18 * All instructions come in as uint32_t's.
19 */
20
21 #include <libdisasm.h>
22 #include <stdint.h>
23 #include <stdio.h>
24 #include <sys/byteorder.h>
25
26 #include "libdisasm_impl.h"
27
28 extern size_t strlen(const char *);
29 extern size_t strlcat(char *, const char *, size_t);
30
31 /*
32 * Condition code mask and shift, aka bits 28-31.
33 */
34 #define ARM_CC_MASK 0xf0000000
35 #define ARM_CC_SHIFT 28
36
37 /*
38 * First level of decoding, aka bits 25-27.
39 */
40 #define ARM_L1_DEC_MASK 0x0e000000
41 #define ARM_L1_DEC_SHIFT 25
42
43 /*
44 * Masks and values for the 0b000 l1 group
45 */
46 #define ARM_L1_0_B4_MASK 0x00000010
47 #define ARM_L1_0_B7_MASK 0x00000080
48 #define ARM_L1_0_OPMASK 0x01800000
377 #define ARM_COPROC_DRT_OP_MASK 0x000000f0
378 #define ARM_COPROC_DRT_OP_SHIFT 4
379 #define ARM_COPROC_DRT_DIR_MASK 0x00100000 /* MCRR or MRRC */
380
381 #define ARM_COPROC_LS_P_MASK 0x01000000
382 #define ARM_COPROC_LS_U_MASK 0x00800000
383 #define ARM_COPROC_LS_N_MASK 0x00400000
384 #define ARM_COPROC_LS_W_MASK 0x00200000
385 #define ARM_COPROC_LS_L_MASK 0x00100000
386 #define ARM_COPROC_LS_IMM_MASK 0x000000ff
387
388 /*
389 * This is the table of condition codes that instructions might have. Every
390 * instruction starts with a four bit code. The last two codes are special.
391 * 0b1110 is the always condition. Therefore we leave off its mneomic extension
392 * and treat it as the empty string. The condition code 0b1111 takes us to a
393 * separate series of encoded instructions and therefore we go elsewhere with
394 * them.
395 */
396 static const char *arm_cond_names[] = {
397 "eq", /* Equal */
398 "ne", /* Not Equal */
399 "cs/hs", /* Carry set/unsigned higher or same */
400 "cc/lo", /* Carry clear/unsigned lower */
401 "mi", /* Minus/negative */
402 "pl", /* Plus/positive or zero */
403 "vs", /* Overflow */
404 "vc", /* No overflow */
405 "hi", /* Unsigned higher */
406 "ls", /* Unsigned lower or same */
407 "ge", /* Signed greater than or equal */
408 "lt", /* Signed less than */
409 "gt", /* Signed greater than */
410 "le", /* Signed less than or equal */
411 "", /* AL - Always (unconditional) */
412 NULL /* Not a condition code */
413 };
414
415 typedef enum arm_cond_code {
416 ARM_COND_EQ, /* Equal */
417 ARM_COND_NE, /* Not Equal */
418 ARM_COND_CSHS, /* Carry set/unsigned higher or same */
419 ARM_COND_CCLO, /* Carry clear/unsigned lower */
420 ARM_COND_MI, /* Minus/negative */
421 ARM_COND_PL, /* Plus/positive or zero */
422 ARM_COND_VS, /* Overflow */
423 ARM_COND_VC, /* No overflow */
424 ARM_COND_HI, /* Unsigned higher */
425 ARM_COND_LS, /* Unsigned lower or same */
426 ARM_COND_GE, /* Signed greater than or equal */
427 ARM_COND_LT, /* Signed less than */
428 ARM_COND_GT, /* Signed greater than */
429 ARM_COND_LE, /* Signed less than or equal */
430 ARM_COND_AL, /* AL - Always (unconditional) */
431 ARM_COND_NACC /* Not a condition code */
432 } arm_cond_code_t;
433
434 /*
435 * Registers are encoded surprisingly sanely. It's a 4-bit value that indicates
436 * which register in question we're working with.
437 */
438 static const char *arm_reg_names[] = {
439 "r0",
440 "r1",
441 "r2",
442 "r3",
443 "r4",
444 "r5",
445 "r6",
446 "r7",
447 "r8",
448 "fp", /* Alt for r9 */
449 "r10",
450 "r11",
451 "ip", /* Alt for r12 */
452 "sp", /* Alt for r13 */
453 "lr", /* Alt for r14 */
454 "pc" /* Alt for r15 */
455 };
456
457 typedef enum arm_reg {
458 ARM_REG_R0,
459 ARM_REG_R1,
460 ARM_REG_R2,
461 ARM_REG_R3,
462 ARM_REG_R4,
463 ARM_REG_R5,
464 ARM_REG_R6,
465 ARM_REG_R7,
466 ARM_REG_R8,
467 ARM_REG_R9,
468 ARM_REG_R10,
469 ARM_REG_R11,
470 ARM_REG_R12,
471 ARM_REG_R13,
472 ARM_REG_R14,
473 ARM_REG_R15
474 } arm_reg_t;
483 "p3",
484 "p4",
485 "p5",
486 "p6",
487 "p7",
488 "p8",
489 "p9",
490 "p10",
491 "p11",
492 "p12",
493 "p13",
494 "p14",
495 "p15"
496 };
497
498 /*
499 * These are the opcodes for the instructions which are considered data
500 * processing instructions.
501 */
502 static const char *arm_dpi_opnames[] = {
503 "and", /* Logical AND */
504 "eor", /* Logical Exclusive OR */
505 "sub", /* Subtract */
506 "rsb", /* Reverse Subtract */
507 "add", /* Add */
508 "adc", /* Add with Carry */
509 "sbc", /* Subtract with Carry */
510 "rsc", /* Reverse Subtract with Carry */
511 "tst", /* Test */
512 "teq", /* Test Equivalence */
513 "cmp", /* Compare */
514 "cmn", /* Compare negated */
515 "orr", /* Logical (inclusive) OR */
516 "mov", /* Move */
517 "bic", /* Bit clear */
518 "mvn" /* Move not */
519 };
520
521 typedef enum arm_dpi_opcode {
522 DPI_OP_AND, /* Logical AND */
523 DPI_OP_EOR, /* Logical Exclusive OR */
524 DPI_OP_SUB, /* Subtract */
525 DPI_OP_RSB, /* Reverse Subtract */
526 DPI_OP_ADD, /* Add */
527 DPI_OP_ADC, /* Add with Carry */
528 DPI_OP_SBC, /* Subtract with Carry */
529 DPI_OP_RSC, /* Reverse Subtract with Carry */
530 DPI_OP_TST, /* Test */
531 DPI_OP_TEQ, /* Test Equivalence */
532 DPI_OP_CMP, /* Compare */
533 DPI_OP_CMN, /* Compare negated */
534 DPI_OP_ORR, /* Logical (inclusive) OR */
535 DPI_OP_MOV, /* Move */
536 DPI_OP_BIC, /* Bit clear */
537 DPI_OP_MVN /* Move not */
538 } arm_dpi_opcode_t;
539
540 const char *arm_dpi_shifts[] = {
541 "lsl", /* Logical shift left */
542 "lsr", /* Logical shift right */
543 "asr", /* Arithmetic shift right */
544 "ror", /* Rotate right */
545 "rrx" /* Rotate right with extend. This is a special case of ror */
546 };
547
548 typedef enum arm_dpi_shift_code {
549 DPI_S_LSL, /* Logical shift left */
550 DPI_S_LSR, /* Logical shift right */
551 DPI_S_ASR, /* Arithmetic shift right */
552 DPI_S_ROR, /* Rotate right */
553 DPI_S_RRX, /* Rotate right with extend. Special case of ror */
554 DPI_S_NONE /* No shift code */
555 } arm_dpi_shift_code_t;
556
557 #define ARM_DPI_SHIFTER_IMM32 0x00
558 #define ARM_DPI_SHIFTER_SIMM 0x01
559 #define ARM_DPI_SHIFTER_SREG 0x02
560
561 typedef struct arm_dpi_shifter_imm {
562 uint8_t dpisi_rot; /* Rotation amount */
563 uint8_t dpisi_imm; /* Immediate value */
564 } arm_dpi_shifter_imm_t;
565
566 typedef struct arm_dpi_shifter_simm {
567 uint8_t dpiss_imm; /* Shift value */
568 arm_dpi_shift_code_t dpiss_code; /* Shift type */
569 arm_reg_t dpiss_targ; /* Target register */
570 } arm_dpi_shifter_simm_t;
571
572 typedef struct arm_dpi_shifter_sreg {
573 arm_reg_t dpisr_val; /* reg with shift value */
578 typedef struct arm_dpi_inst {
579 arm_dpi_opcode_t dpii_op; /* dpi opcode */
580 arm_cond_code_t dpii_cond; /* condition code */
581 int dpii_sbit; /* value of S bit */
582 arm_reg_t dpii_rn; /* first operand */
583 arm_reg_t dpii_rd; /* destination operand */
584 int dpii_stype; /* type of shifter */
585 union { /* shifter values */
586 arm_dpi_shifter_imm_t dpii_im;
587 arm_dpi_shifter_simm_t dpii_si;
588 arm_dpi_shifter_sreg_t dpii_ri;
589 } dpii_un;
590 } arm_dpi_inst_t;
591
592 /*
593 * This table contains the names of the load store multiple addressing modes.
594 * The P and U bits are supposed to be combined to index into this. You should
595 * do this by doing P << 1 | U.
596 */
597 static const char *arm_lsm_mode_names[] = {
598 "da",
599 "ia",
600 "db",
601 "ib"
602 };
603
604 /*
605 * The MSR field has a four bit field mask. Each bit correspons to a letter.
606 * From high to low, f, s, x, c. At least one must be specified, hence 0 is
607 * NULL. The preferred manual ordering of these is csxf.
608 */
609 static const char *arm_cdsp_msr_field_names[] = {
610 NULL,
611 "c", /* 0001 */
612 "x", /* 0010 */
613 "cx", /* 0011 */
614 "s", /* 0100 */
615 "cs", /* 0101 */
616 "sx", /* 0110 */
617 "csx", /* 0111 */
618 "f", /* 1000 */
619 "cf", /* 1001 */
620 "xf", /* 1010 */
621 "cxf", /* 1011 */
622 "sf", /* 1100 */
623 "csf", /* 1101 */
624 "sxf", /* 1110 */
625 "csxf" /* 1111 */
626 };
627
628 /*
629 * Names for specific saturating add and subtraction instructions from the
630 * extended control and dsp instructino section.
631 */
632 static const char *arm_cdsp_sat_opnames[] = {
633 "add",
634 "sub",
635 "dadd",
636 "dsub"
637 };
638
639 static const char *arm_padd_p_names[] = {
640 NULL, /* 000 */
641 "s", /* 001 */
642 "q", /* 010 */
643 "sh", /* 011 */
644 NULL, /* 100 */
645 "u", /* 101 */
646 "uq", /* 110 */
647 "uh", /* 111 */
648 };
649
650 static const char *arm_padd_i_names[] = {
651 "add16", /* 000 */
652 "addsubx", /* 001 */
653 "subaddx", /* 010 */
654 "sub16", /* 011 */
655 "add8", /* 100 */
656 NULL, /* 101 */
657 NULL, /* 110 */
658 "sub8", /* 111 */
659 };
660
661 static const char *arm_extend_rot_names[] = {
662 "", /* 0b00, ROR #0 */
663 ", ror #8", /* 0b01 */
664 ", ror #16", /* 0b10 */
665 ", ror #24" /* 0b11 */
666 };
667
668 /*
669 * There are sixteen data processing instructions (dpi). They come in a few
670 * different forms which are based on whether immediate values are used and
671 * whether or not some special purpose shifting is done. We use this one entry
672 * point to cover all the different types.
673 *
674 * From the ARM arch manual:
675 *
676 * <opcode1>{<cond>}{S} <Rd>,<shifter>
677 * <opcode1> := MOV | MVN
678 * <opcode2>{<cond>} <Rn>,<shifter>
679 * <opcode2> := CMP, CMN, TST, TEQ
680 * <opcode3>{<cond>{S} <Rd>,<Rn>, <shifter>
681 * <opcode3> := ADD | SUB | RSB | ADC | SBC | RSC | AND | BIC | EOR | ORR
682 *
683 * 31 - 28|27 26 |25 | 24-21 |20 | 19-16 | 15-12 | 11 - 0
684 * [ cond | 0 0 | I | opcode | S | Rn | Rd | shifter ]
685 *
762 ARM_DPI_IMS_SHIFT_MASK) >> ARM_DPI_IMS_SHIFT_SHIFT;
763 dpi_inst.dpii_un.dpii_si.dpiss_targ = in & ARM_DPI_IMS_RM_MASK;
764 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_ROR &&
765 dpi_inst.dpii_un.dpii_si.dpiss_imm == 0)
766 dpi_inst.dpii_un.dpii_si.dpiss_code = DPI_S_RRX;
767
768 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_LSL &&
769 dpi_inst.dpii_un.dpii_si.dpiss_imm == 0)
770 dpi_inst.dpii_un.dpii_si.dpiss_code = DPI_S_NONE;
771 }
772
773 /*
774 * Print everything before the shifter based on the instruction
775 */
776 switch (dpi_inst.dpii_op) {
777 case DPI_OP_MOV:
778 case DPI_OP_MVN:
779 len = snprintf(buf, buflen, "%s%s%s %s",
780 arm_dpi_opnames[dpi_inst.dpii_op],
781 arm_cond_names[dpi_inst.dpii_cond],
782 dpi_inst.dpii_sbit != 0 ? "s" : "",
783 arm_reg_names[dpi_inst.dpii_rd]);
784 break;
785 case DPI_OP_CMP:
786 case DPI_OP_CMN:
787 case DPI_OP_TST:
788 case DPI_OP_TEQ:
789 len = snprintf(buf, buflen, "%s%s %s",
790 arm_dpi_opnames[dpi_inst.dpii_op],
791 arm_cond_names[dpi_inst.dpii_cond],
792 arm_reg_names[dpi_inst.dpii_rn]);
793 break;
794 default:
795 len = snprintf(buf, buflen,
796 "%s%s%s %s, %s", arm_dpi_opnames[dpi_inst.dpii_op],
797 arm_cond_names[dpi_inst.dpii_cond],
798 dpi_inst.dpii_sbit != 0 ? "s" : "",
799 arm_reg_names[dpi_inst.dpii_rd],
800 arm_reg_names[dpi_inst.dpii_rn]);
801 break;
802 }
803
804 if (len >= buflen)
805 return (-1);
806 buflen -= len;
807 buf += len;
808
809 /*
810 * Print the shifter as appropriate
811 */
812 switch (dpi_inst.dpii_stype) {
813 case ARM_DPI_SHIFTER_IMM32: {
814 uint32_t rawimm, imm;
815 int rawrot, rot;
816
817 rawimm = dpi_inst.dpii_un.dpii_im.dpisi_imm;
818 rawrot = dpi_inst.dpii_un.dpii_im.dpisi_rot;
819
820 rot = rawrot * 2;
821 imm = (rawimm << (32 - rot)) | (rawimm >> rot);
822
823 len = snprintf(buf, buflen, ", #%u, %d ; 0x%08x", rawimm,
824 rawrot, imm);
825 break;
826 }
827 case ARM_DPI_SHIFTER_SIMM:
828 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_NONE) {
829 len = snprintf(buf, buflen, ", %s",
830 arm_reg_names[dpi_inst.dpii_un.dpii_si.dpiss_targ]);
831 break;
832 }
833 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_RRX) {
834 len = snprintf(buf, buflen, ", %s rrx",
835 arm_reg_names[dpi_inst.dpii_un.dpii_si.dpiss_targ]);
836 break;
837 }
838 len = snprintf(buf, buflen, ", %s, %s #%d",
839 arm_reg_names[dpi_inst.dpii_un.dpii_si.dpiss_targ],
840 arm_dpi_shifts[dpi_inst.dpii_un.dpii_si.dpiss_code],
841 dpi_inst.dpii_un.dpii_si.dpiss_imm);
842 break;
843 case ARM_DPI_SHIFTER_SREG:
844 len = snprintf(buf, buflen, ", %s, %s %s",
845 arm_reg_names[dpi_inst.dpii_un.dpii_ri.dpisr_targ],
846 arm_dpi_shifts[dpi_inst.dpii_un.dpii_ri.dpisr_code],
847 arm_reg_names[dpi_inst.dpii_un.dpii_ri.dpisr_val]);
848 break;
849 }
850
851 return (len < buflen ? 0 : -1);
852 }
853
854 /*
884 static int
885 arm_dis_ldstr(uint32_t in, char *buf, size_t buflen)
886 {
887 arm_cond_code_t cc;
888 arm_reg_t rd, rn, rm;
889 int ibit, pbit, ubit, bbit, wbit, lbit;
890 arm_dpi_shift_code_t sc;
891 uint8_t simm;
892 size_t len;
893
894 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
895 ibit = in & ARM_LS_IBIT_MASK;
896 pbit = in & ARM_LS_PBIT_MASK;
897 ubit = in & ARM_LS_UBIT_MASK;
898 bbit = in & ARM_LS_BBIT_MASK;
899 wbit = in & ARM_LS_WBIT_MASK;
900 lbit = in & ARM_LS_LBIT_MASK;
901 rd = (in & ARM_LS_RD_MASK) >> ARM_LS_RD_SHIFT;
902 rn = (in & ARM_LS_RN_MASK) >> ARM_LS_RN_SHIFT;
903
904 len = snprintf(buf, buflen, "%s%s%s%s %s, ", lbit != 0 ? "ldr" : "str",
905 arm_cond_names[cc], bbit != 0 ? "b" : "",
906 (pbit == 0 && wbit != 0) ? "t" : "",
907 arm_reg_names[rd]);
908 if (len >= buflen)
909 return (-1);
910
911 /* Figure out the specifics of the encoding for the rest */
912 if (ibit == 0 && pbit != 0) {
913 /*
914 * This is the immediate offset mode (A5.2.2). That means that
915 * we have something of the form [ <Rn>, #+/-<offset_12> ]. All
916 * of the mode specific bits contribute to offset_12. We also
917 * handle the pre-indexed version (A5.2.5) which depends on the
918 * wbit being set.
919 */
920 len += snprintf(buf + len, buflen - len, "[%s, #%s%d]%s",
921 arm_reg_names[rn], ubit != 0 ? "" : "-",
922 in & ARM_LS_IMM_MASK, wbit != 0 ? "!" : "");
923 } else if (ibit != 0 && pbit != 0) {
924 /*
925 * This handles A5.2.2, A5.2.3, A5.2.6, and A5.2.7. We can have
926 * one of two options. If the non-rm bits (11-4) are all zeros
972 ARM_LS_SCR_SIMM_SHIFT;
973 sc = (in & ARM_LS_SCR_SCODE_MASK) >>
974 ARM_LS_SCR_SCODE_SHIFT;
975
976 if (simm == 0 && sc == DPI_S_ROR)
977 sc = DPI_S_RRX;
978
979 len += snprintf(buf + len, buflen - len, "%s",
980 arm_dpi_shifts[sc]);
981 if (len >= buflen)
982 return (-1);
983 if (sc != DPI_S_RRX)
984 len += snprintf(buf + len, buflen - len,
985 " #%d", simm);
986 }
987 }
988
989 return (len < buflen ? 0 : -1);
990 }
991
992 static void
993 print_range(char **bufp, size_t *buflenp, uint16_t regs, uint16_t precede)
994 {
995 char *buf = *bufp;
996 size_t buflen = *buflenp;
997 boolean_t cont = B_FALSE;
998 int minreg = -1;
999 int i;
1000
1001 *buf = '\0';
1002
1003 if (precede && regs)
1004 strlcat(buf, ", ", buflen);
1005
1006 for (i = 0; i < 16; i++) {
1007 boolean_t present = (regs & (1 << i)) != 0;
1008 boolean_t lastreg = (regs & (2 << i)) == 0;
1009
1010 if (!present)
1011 continue;
1012
1013 if (minreg == -1) {
1014 if (cont)
1015 strlcat(buf, ", ", buflen);
1016
1017 strlcat(buf, arm_reg_names[i], buflen);
1018
1019 if (!lastreg)
1020 minreg = i;
1021 } else {
1022 if (lastreg) {
1023 strlcat(buf, "-", buflen);
1024 strlcat(buf, arm_reg_names[i], buflen);
1025 minreg = -1;
1026 }
1027 }
1028
1029 cont = B_TRUE;
1030 }
1031
1032 *bufp += strlen(buf);
1033 *buflenp -= strlen(buf);
1034 }
1035
1036 static size_t
1037 print_reg_list(char *buf, size_t buflen, uint16_t regs)
1038 {
1039 char *save = buf;
1040
1041 print_range(&buf, &buflen, regs & 0x01ff, 0);
1042 print_range(&buf, &buflen, regs & 0x0200, regs & 0x01ff); /* fp */
1043 print_range(&buf, &buflen, regs & 0x0c00, regs & 0x03ff);
1044 print_range(&buf, &buflen, regs & 0x1000, regs & 0x0fff); /* ip */
1045 print_range(&buf, &buflen, regs & 0x2000, regs & 0x1fff); /* sp */
1046 print_range(&buf, &buflen, regs & 0x4000, regs & 0x3fff); /* lr */
1047 print_range(&buf, &buflen, regs & 0x8000, regs & 0x7fff); /* pc */
1048
1049 return (strlen(save));
1050 }
1051
1052 /*
1053 * This handles load and store multiple instructions. The general format is as
1054 * follows:
1055 *
1056 * 31 - 28|27 26 25|24|23|22|21|20|19-16|15-0
1057 * [ cond | 1 0 0 |P |U |S |W |L | Rn | register set
1058 *
1059 * The register set has one bit per register. If a bit is set it indicates that
1060 * register and if it is not set then it indicates that the register is not
1061 * included in this.
1062 *
1063 * S bit: If the instruction is a LDM and we load the PC, the S == 1 tells us to
1064 * load the CPSR from SPSR after the other regs are loaded. If the instruction
1065 * is a STM or LDM without touching the PC it indicates that if we are
1066 * privileged we should send the banked registers.
1067 *
1068 * L bit: Where this is a load or store. Load is active high.
1069 *
1070 * P bit: If P == 0 then Rn is included in the memory region transfers and its
1071 * location is dependent on the U bit. It is at the top (U == 0) or bottom (U ==
1081 *
1082 * The overal layout for this is
1083 * (LDM|STM){<cond>}<addressing mode> Rn{!}, <registers>{^}. Here the ! is based
1084 * on having the W bit set. The ^ bit depends on whether S is set or not.
1085 *
1086 * There are four normal addressing modes: IA, IB, DA, DB. There are also
1087 * corresponding stack addressing modes that exist. However we have no way of
1088 * knowing which are the ones being used, therefore we are going to default to
1089 * the non-stack versions which are listed as the primary.
1090 *
1091 * Finally the last useful bit is how the registers list is specified. It is a
1092 * comma separated list inside of { }. However, a user may separate a contiguous
1093 * range by the use of a -, eg. R0 - R4. However, it is impossible for us to map
1094 * back directly to what the user did. So for now, we punt on second down and
1095 * instead just list each indidvidual register rather than attempt a joining
1096 * routine.
1097 */
1098 static int
1099 arm_dis_ldstr_multi(uint32_t in, char *buf, size_t buflen)
1100 {
1101 int sbit, wbit, lbit;
1102 uint16_t regs, addr_mode;
1103 arm_reg_t rn;
1104 arm_cond_code_t cc;
1105 size_t len;
1106
1107 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1108 sbit = in & ARM_LSM_SBIT_MASK;
1109 wbit = in & ARM_LSM_WBIT_MASK;
1110 lbit = in & ARM_LSM_LBIT_MASK;
1111 rn = (in & ARM_LSM_RN_MASK) >> ARM_LSM_RN_SHIFT;
1112 regs = in & ARM_LSM_RLIST_MASK;
1113 addr_mode = (in & ARM_LSM_ADDR_MASK) >> ARM_LSM_ADDR_SHIFT;
1114
1115 if ((lbit == 0 && addr_mode == 2 && rn == ARM_REG_R13 && wbit != 0) ||
1116 (lbit != 0 && addr_mode == 1 && rn == ARM_REG_R13 && wbit != 0))
1117 len = snprintf(buf, buflen, "%s%s { ",
1118 lbit != 0 ? "pop" : "push",
1119 arm_cond_names[cc]);
1120 else
1121 len = snprintf(buf, buflen, "%s%s%s %s%s, { ",
1122 lbit != 0 ? "ldm" : "stm",
1123 arm_cond_names[cc],
1124 arm_lsm_mode_names[addr_mode],
1125 arm_reg_names[rn],
1126 wbit != 0 ? "!" : "");
1127
1128 len += print_reg_list(buf + len, buflen - len, regs);
1129
1130 len += snprintf(buf + len, buflen - len, " }%s", sbit != 0 ? "^" : "");
1131 return (len >= buflen ? -1 : 0);
1132 }
1133
1134 /*
1135 * Here we need to handle miscellaneous loads and stores. This is used to load
1136 * and store signed and unsigned half words. To load a signed byte. And to load
1137 * and store double words. There is no specific store routines for signed bytes
1138 * and halfwords as they are supposed to use the SRB and STRH. There are two
1139 * primary encodings this time. The general case looks like:
1140 *
1141 * 31 - 28|27 - 25|24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1142 * [ cond | 0 |P |U |I |W |L | Rn | Rd |amode|1|S|H|1|amode ]
1143 *
1144 * The I, P, U, and W bits specify the addressing mode.
1145 * The L, S, and H bits describe the type and size.
1146 * Rn: The base register used by the addressing mode
1147 * Rd: The register to load to or store from
1148 *
1149 * The other bits specifically mean:
1150 * I bit: If set to one the address specific pieces are immediate. Otherwise
1151 * they aren't.
1152 * P bit: If P is 0 used post-indexed addressing. If P is 1 its behavior is
1153 * based on the value of W.
1154 * U bit: If U is one the offset is added to the base otherwise subtracted
1155 * W bit: When P is one a value of W == 1 says that the resulting memory address
1168 * 1 | 1 | 1 | load signed halfword
1169 *
1170 * The final format of this is:
1171 * LDR|STR{<cond>}H|SH|SB|D <rd>, address_mode
1172 */
1173 static int
1174 arm_dis_els(uint32_t in, char *buf, size_t buflen)
1175 {
1176 arm_cond_code_t cc;
1177 arm_reg_t rn, rd;
1178 const char *iname, *suffix;
1179 int lbit, sbit, hbit, pbit, ubit, ibit, wbit;
1180 uint8_t imm;
1181 size_t len;
1182
1183 lbit = in & ARM_ELS_LBIT_MASK;
1184 sbit = in & ARM_ELS_SBIT_MASK;
1185 hbit = in & ARM_ELS_SBIT_MASK;
1186
1187 if (lbit || (sbit && hbit == 0))
1188 iname = "ldr";
1189 else
1190 iname = "str";
1191
1192 if (sbit == 0 && hbit)
1193 suffix = "h";
1194 else if (lbit == 0)
1195 suffix = "d";
1196 else if (sbit && hbit == 0)
1197 suffix = "sb";
1198 else if (sbit && hbit)
1199 suffix = "sh";
1200
1201 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1202 rn = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
1203 rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1204
1205 len = snprintf(buf, buflen, "%s%s%s %s, ", iname, arm_cond_names[cc],
1206 suffix, arm_reg_names[rd]);
1207 if (len >= buflen)
1208 return (-1);
1209
1210 pbit = in & ARM_ELS_PBIT_MASK;
1211 ubit = in & ARM_ELS_UBIT_MASK;
1212 ibit = in & ARM_ELS_IBIT_MASK;
1213 wbit = in & ARM_ELS_WBIT_MASK;
1214
1215 if (pbit && ibit) {
1216 /* Handle A5.3.2 and A5.3.4 immediate offset and pre-indexed */
1217 /* Bits 11-8 form the upper 4 bits of imm */
1218 imm = (in & ARM_ELS_UP_AM_MASK) >> (ARM_ELS_UP_AM_SHIFT - 4);
1219 imm |= in & ARM_ELS_LOW_AM_MASK;
1242 arm_reg_names[in & ARM_ELS_LOW_AM_MASK]);
1243 }
1244
1245 return (len >= buflen ? -1 : 0);
1246 }
1247
1248 /*
1249 * Handle SWP and SWPB out of the extra loads/stores extensions.
1250 */
1251 static int
1252 arm_dis_swap(uint32_t in, char *buf, size_t buflen)
1253 {
1254 arm_cond_code_t cc;
1255 arm_reg_t rn, rd, rm;
1256
1257 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1258 rn = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
1259 rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1260 rm = in & ARM_ELS_RN_MASK;
1261
1262 if (snprintf(buf, buflen, "swp%s%s %s, %s, [%s]",
1263 arm_cond_names[cc],
1264 (in & ARM_ELS_SWAP_BYTE_MASK) ? "b" : "",
1265 arm_reg_names[rd], arm_reg_names[rm], arm_reg_names[rn]) >=
1266 buflen)
1267 return (-1);
1268
1269 return (0);
1270 }
1271
1272 /*
1273 * Handle LDREX and STREX out of the extra loads/stores extensions.
1274 */
1275 static int
1276 arm_dis_lsexcl(uint32_t in, char *buf, size_t buflen)
1277 {
1278 arm_cond_code_t cc;
1279 arm_reg_t rn, rd, rm;
1280 int lbit;
1281 size_t len;
1282
1283 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1284 rn = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
1285 rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1286 rm = in & ARM_ELS_RN_MASK;
1287 lbit = in & ARM_ELS_LBIT_MASK;
1288
1289 len = snprintf(buf, buflen, "%s%sex %s, ",
1290 lbit != 0 ? "ldr" : "str",
1291 arm_cond_names[cc], arm_reg_names[rd]);
1292 if (len >= buflen)
1293 return (-1);
1294
1295 if (lbit)
1296 len += snprintf(buf + len, buflen - len, "[%s]",
1297 arm_reg_names[rn]);
1298 else
1299 len += snprintf(buf + len, buflen - len, "%s, [%s]",
1300 arm_reg_names[rm], arm_reg_names[rn]);
1301 return (len >= buflen ? -1 : 0);
1302 }
1303
1304 /*
1305 * This is designed to handle the multiplication instruction extension space.
1306 * Note that this doesn't actually cover all of the multiplication instructions
1307 * available in ARM, but all of the ones that are in this space. This includes
1308 * the following instructions:
1309 *
1310 *
1332 */
1333 static int
1334 arm_dis_extmul(uint32_t in, char *buf, size_t buflen)
1335 {
1336 arm_cond_code_t cc;
1337 arm_reg_t rd, rn, rs, rm;
1338 size_t len;
1339
1340 /*
1341 * RdHi is equal to rd here. RdLo is equal to Rn here.
1342 */
1343 rd = (in & ARM_EMULT_RD_MASK) >> ARM_EMULT_RD_SHIFT;
1344 rn = (in & ARM_EMULT_RN_MASK) >> ARM_EMULT_RN_SHIFT;
1345 rs = (in & ARM_EMULT_RS_MASK) >> ARM_EMULT_RS_SHIFT;
1346 rm = in & ARM_EMULT_RM_MASK;
1347
1348 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1349
1350 if ((in & ARM_EMULT_MA_MASK) == 0) {
1351 if (in & ARM_EMULT_ABIT_MASK) {
1352 len = snprintf(buf, buflen, "mla%s%s %s, %s, %s, %s",
1353 arm_cond_names[cc],
1354 (in & ARM_EMULT_SBIT_MASK) ? "s" : "",
1355 arm_reg_names[rd], arm_reg_names[rm],
1356 arm_reg_names[rs], arm_reg_names[rs]);
1357 } else {
1358 len = snprintf(buf, buflen, "mul%s%s %s, %s, %s",
1359 arm_cond_names[cc],
1360 (in & ARM_EMULT_SBIT_MASK) ? "s" : "",
1361 arm_reg_names[rd], arm_reg_names[rm],
1362 arm_reg_names[rs]);
1363
1364 }
1365 } else if ((in & ARM_EMULT_UMA_MASK) == ARM_EMULT_UMA_TARG) {
1366 len = snprintf(buf, buflen, "umaal%s %s, %s, %s, %s",
1367 arm_cond_names[cc], arm_reg_names[rn], arm_reg_names[rd],
1368 arm_reg_names[rm], arm_reg_names[rs]);
1369 } else if ((in & ARM_EMULT_MAL_MASK) == ARM_EMULT_MAL_TARG) {
1370 len = snprintf(buf, buflen, "%s%s%s%s %s, %s, %s, %s",
1371 (in & ARM_EMULT_UNBIT_MASK) ? "s" : "u",
1372 (in & ARM_EMULT_ABIT_MASK) ? "mlal" : "mull",
1373 arm_cond_names[cc],
1374 (in & ARM_EMULT_SBIT_MASK) ? "s" : "",
1375 arm_reg_names[rn], arm_reg_names[rd], arm_reg_names[rm],
1376 arm_reg_names[rs]);
1377 } else {
1378 /* Not a supported instruction in this space */
1379 return (-1);
1380 }
1381 return (len >= buflen ? -1 : 0);
1382 }
1383
1384 /*
1385 * Here we handle the three different cases of moving to and from the various
1386 * status registers in both register mode and in immediate mode.
1387 */
1388 static int
1389 arm_dis_status_regs(uint32_t in, char *buf, size_t buflen)
1390 {
1391 arm_cond_code_t cc;
1392 arm_reg_t rd, rm;
1393 uint8_t field;
1394 int imm;
1395 size_t len;
1396
1397 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1398
1399 if ((in & ARM_CDSP_MRS_MASK) == ARM_CDSP_MRS_TARG) {
1400 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1401 if (snprintf(buf, buflen, "mrs%s %s, %s", arm_cond_names[cc],
1402 arm_reg_names[rd],
1403 (in & ARM_CDSP_STATUS_RBIT) != 0 ? "spsr" : "cpsr") >=
1404 buflen)
1405 return (-1);
1406 return (0);
1407 }
1408
1409 field = (in & ARM_CDSP_MSR_F_MASK) >> ARM_CDSP_MSR_F_SHIFT;
1410 len = snprintf(buf, buflen, "msr%s %s_%s, ", arm_cond_names[cc],
1411 (in & ARM_CDSP_STATUS_RBIT) != 0 ? "spsr" : "cpsr",
1412 arm_cdsp_msr_field_names[field]);
1413 if (len >= buflen)
1414 return (-1);
1415
1416 if (in & ARM_CDSP_MSR_ISIMM_MASK) {
1417 imm = in & ARM_CDSP_MSR_IMM_MASK;
1418 imm <<= (in & ARM_CDSP_MSR_RI_MASK) >> ARM_CDSP_MSR_RI_SHIFT;
1419 len += snprintf(buf + len, buflen - len, "#%d", imm);
1420 } else {
1421 rm = in & ARM_CDSP_RM_MASK;
1422 len += snprintf(buf + len, buflen - len, "%s",
1423 arm_reg_names[rm]);
1424 }
1425
1426 return (len >= buflen ? -1 : 0);
1427 }
1428
1429 /*
1430 * Here we need to handle the Control And DSP instruction extension space. This
1431 * consists of several different instructions. Unlike other extension spaces
1442 uint16_t imm, op;
1443 arm_cond_code_t cc;
1444 arm_reg_t rd, rm, rn, rs;
1445 size_t len;
1446
1447 if ((in & ARM_CDSP_STATUS_MASK) == ARM_CDSP_STATUS_TARG)
1448 return (arm_dis_status_regs(in, buf, buflen));
1449
1450 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1451
1452 /*
1453 * This gets the Branch/exchange as well as the Branch and link/exchange
1454 * pieces. These generally also transform the instruction set into
1455 * something we can't actually disassemble. Here the lower mask and
1456 * target is the opposite. eg. the target bits are not what we want.
1457 */
1458 if ((in & ARM_CDSP_BEX_UP_MASK) == ARM_CDSP_BEX_UP_TARG &&
1459 (in & ARM_CDSP_BEX_LOW_MASK) != ARM_CDSP_BEX_NLOW_TARG) {
1460 rm = in & ARM_CDSP_RM_MASK;
1461 imm = (in & ARM_CDSP_BEX_TYPE_MASK) >> ARM_CDSP_BEX_TYPE_SHIFT;
1462 if (snprintf(buf, buflen, "b%s%s %s",
1463 imm == ARM_CDSP_BEX_TYPE_X ? "x" :
1464 imm == ARM_CDSP_BEX_TYPE_J ? "xj" : "lx",
1465 arm_cond_names[cc], arm_reg_names[rm]) >= buflen)
1466 return (-1);
1467 return (0);
1468 }
1469
1470 /* Count leading zeros */
1471 if ((in & ARM_CDSP_CLZ_MASK) == ARM_CDSP_CLZ_TARG) {
1472 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1473 rm = in & ARM_CDSP_RM_MASK;
1474 if (snprintf(buf, buflen, "clz%s %s, %s", arm_cond_names[cc],
1475 arm_reg_names[rd], arm_reg_names[rm]) >= buflen)
1476 return (-1);
1477 return (0);
1478 }
1479
1480 if ((in & ARM_CDSP_SAT_MASK) == ARM_CDSP_SAT_TARG) {
1481 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1482 rn = (in & ARM_CDSP_RN_MASK) >> ARM_CDSP_RN_SHIFT;
1483 rm = in & ARM_CDSP_RM_MASK;
1484 imm = (in & ARM_CDSP_SAT_OP_MASK) >> ARM_CDSP_SAT_OP_SHIFT;
1485 if (snprintf(buf, buflen, "q%s%s %s, %s, %s",
1486 arm_cdsp_sat_opnames[imm], arm_cond_names[cc],
1487 arm_reg_names[rd], arm_reg_names[rm],
1488 arm_reg_names[rn]) >= buflen)
1489 return (-1);
1490 return (0);
1491 }
1492
1493 /*
1494 * Breakpoint instructions are a bit different. While they are in the
1495 * conditional instruction namespace, they actually aren't defined to
1496 * take a condition. That's just how it rolls. The breakpoint is a
1497 * 16-bit value. The upper 12 bits are stored together and the lower
1498 * four together.
1499 */
1500 if ((in & ARM_CDSP_BKPT_MASK) == ARM_CDSP_BKPT_TARG) {
1501 if (cc != ARM_COND_NACC)
1502 return (-1);
1503 imm = (in & ARM_CDSP_BKPT_UIMM_MASK) >>
1504 ARM_CDSP_BKPT_UIMM_SHIFT;
1505 imm <<= 4;
1506 imm |= (in & ARM_CDSP_BKPT_LIMM_MASK);
1507 if (snprintf(buf, buflen, "bkpt %d", imm) >= buflen)
1508 return (1);
1509 return (0);
1510 }
1511
1512 /*
1513 * Here we need to handle another set of multiplies. Specifically the
1514 * Signed multiplies. This is SMLA<x><y>, SMLAW<y>, SMULW<y>,
1515 * SMLAL<x><y>, SMUL<x><y>. These instructions all follow the form:
1516 *
1517 * 31 - 28|27-25|24|23|22-21|20|19-16|15-12|11 - 8|7|6|5|4|3-0
1518 * [ cond | 0 | 1| 0| op. | 0|Rn |Rd |Rs |1|y|x|0|Rm ]
1519 *
1520 * If x is one a T is used for that part of the name. Otherwise a B is.
1521 * The same holds true for y.
1522 *
1523 * These instructions map to the following opcodes:
1524 * SMLA<x><y>: 00,
1525 * SMLAW<y>: 01 and x is zero,
1526 * SMULW<y>: 01 and x is one ,
1527 * SMLAL<x><y>: 10,
1528 * SMUL<xy><y>: 11
1529 */
1530 if ((in & ARM_CDSP_SMUL_MASK) == ARM_CDSP_SMUL_TARG) {
1531 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1532 rn = (in & ARM_CDSP_RN_MASK) >> ARM_CDSP_RN_SHIFT;
1533 rs = (in & ARM_CDSP_RS_MASK) >> ARM_CDSP_RS_SHIFT;
1534 rm = in & ARM_CDSP_RM_MASK;
1535 op = (in & ARM_CDSP_SMUL_OP_MASK) >> ARM_CDSP_SMUL_OP_SHIFT;
1536
1537 switch (op) {
1538 case 0:
1539 len = snprintf(buf, buflen, "smla%s%s%s %s, %s, %s, %s",
1540 (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "t" : "b",
1541 (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" : "b",
1542 arm_cond_names[cc], arm_reg_names[rd],
1543 arm_reg_names[rm], arm_reg_names[rs],
1544 arm_reg_names[rn]);
1545 break;
1546 case 1:
1547 if (in & ARM_CDSP_SMUL_X_MASK) {
1548 len = snprintf(buf, buflen,
1549 "smulw%s%s %s, %s, %s",
1550 (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" :
1551 "b", arm_cond_names[cc], arm_reg_names[rd],
1552 arm_reg_names[rm], arm_reg_names[rs]);
1553 } else {
1554 len = snprintf(buf, buflen,
1555 "smlaw%s%s %s, %s, %s %s",
1556 (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" :
1557 "b", arm_cond_names[cc], arm_reg_names[rd],
1558 arm_reg_names[rm], arm_reg_names[rs],
1559 arm_reg_names[rn]);
1560 }
1561 break;
1562 case 2:
1563 len = snprintf(buf, buflen,
1564 "smlal%s%s%s %s, %s, %s, %s",
1565 (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "t" : "b",
1566 (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" : "b",
1567 arm_cond_names[cc], arm_reg_names[rd],
1568 arm_reg_names[rn], arm_reg_names[rm],
1569 arm_reg_names[rs]);
1570 break;
1571 case 3:
1572 len = snprintf(buf, buflen, "smul%s%s%s %s, %s, %s",
1573 (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "t" : "b",
1574 (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" : "b",
1575 arm_cond_names[cc], arm_reg_names[rd],
1576 arm_reg_names[rm], arm_reg_names[rs]);
1577 break;
1578 default:
1579 return (-1);
1580 }
1581 return (len >= buflen ? -1 : 0);
1582 }
1583
1584 /*
1585 * If we got here then this is some other instructin we don't know
1586 * about in the instruction extensino space.
1587 */
1588 return (-1);
1589 }
1590
1591 /*
1592 * Coprocessor double register transfers
1593 *
1594 * MCRR:
1604 arm_dis_coproc_drt(uint32_t in, char *buf, size_t buflen)
1605 {
1606 arm_cond_code_t cc;
1607 arm_reg_t rd, rn, rm;
1608 uint8_t coproc, op;
1609 const char *ccn;
1610 size_t len;
1611
1612 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1613 coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1614 rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1615 rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1616 rm = in & ARM_COPROC_RM_MASK;
1617 op = (in & ARM_COPROC_DRT_OP_MASK) >> ARM_COPROC_DRT_OP_SHIFT;
1618
1619 if (cc == ARM_COND_NACC)
1620 ccn = "2";
1621 else
1622 ccn = arm_cond_names[cc];
1623
1624 len = snprintf(buf, buflen, "%s%s %s, #%d, %s, %s, c%s",
1625 (in & ARM_COPROC_DRT_DIR_MASK) != 0 ? "mrrc" : "mcrr",
1626 ccn, arm_coproc_names[coproc], op, arm_reg_names[rd],
1627 arm_reg_names[rn], arm_reg_names[rm]);
1628 return (len >= buflen ? -1 : 0);
1629 }
1630
1631 /*
1632 * This serves as both the entry point for the normal load and stores as well as
1633 * the double register transfers (MCRR and MRCC). If it is a register transfer
1634 * then we quickly send it off.
1635 * LDC:
1636 * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11 - 8|7 - 0
1637 * [ cond |1 1 0| P| U| N| W| L| Rn | CRd | cp # | off ]
1638 *
1639 * STC:
1640 * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11 - 8|7 - 0
1641 * [ cond |1 1 0| P| U| N| W| L| Rn | CRd | cp # | off ]
1642 *
1643 * Here the bits mean:
1644 *
1645 * P bit: If P is zero, it is post-indexed or unindexed based on W. If P is 1
1670 if ((in & ARM_COPROC_DRT_MASK) == ARM_COPROC_DRT_TARG)
1671 return (arm_dis_coproc_drt(in, buf, buflen));
1672
1673 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1674 coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1675 rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1676 rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1677 imm = in & ARM_COPROC_LS_IMM_MASK;
1678
1679 pbit = in & ARM_COPROC_LS_P_MASK;
1680 ubit = in & ARM_COPROC_LS_U_MASK;
1681 nbit = in & ARM_COPROC_LS_N_MASK;
1682 wbit = in & ARM_COPROC_LS_W_MASK;
1683 lbit = in & ARM_COPROC_LS_L_MASK;
1684
1685 if (cc == ARM_COND_NACC)
1686 ccn = "2";
1687 else
1688 ccn = arm_cond_names[cc];
1689
1690 len = snprintf(buf, buflen, "%s%s%s %s, c%s, ",
1691 lbit != 0 ? "ldc" : "stc", ccn, nbit != 0 ? "l" : "",
1692 arm_coproc_names[coproc], arm_reg_names[rd]);
1693 if (len >= buflen)
1694 return (-1);
1695
1696 if (pbit != 0) {
1697 imm *= 4;
1698 len += snprintf(buf + len, buflen - len, "[%s, #%s%d]%s",
1699 arm_reg_names[rn],
1700 ubit != 0 ? "" : "-", imm,
1701 wbit != 0 ? "!" : "");
1702 } else if (wbit != 0) {
1703 imm *= 4;
1704 len += snprintf(buf + len, buflen - len, "[%s], #%s%d",
1705 arm_reg_names[rn], ubit != 0 ? "" : "-", imm);
1706 } else {
1707 len += snprintf(buf + len, buflen - len, "[%s], { %d }",
1708 arm_reg_names[rn], imm);
1709 }
1710 return (len >= buflen ? -1 : 0);
1711 }
1725 uint8_t op1, op2, coproc;
1726 const char *ccn;
1727
1728 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1729 coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1730 rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1731 rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1732 rm = in & ARM_COPROC_RM_MASK;
1733 op1 = (in & ARM_COPROC_CDP_OP1_MASK) >> ARM_COPROC_CDP_OP1_SHIFT;
1734 op2 = (in & ARM_COPROC_CDP_OP2_MASK) >> ARM_COPROC_CDP_OP2_SHIFT;
1735
1736 /*
1737 * This instruction is valid with the undefined condition code. When it
1738 * does that, the instruction is intead CDP2 as opposed to CDP.
1739 */
1740 if (cc == ARM_COND_NACC)
1741 ccn = "2";
1742 else
1743 ccn = arm_cond_names[cc];
1744
1745 if (snprintf(buf, buflen, "cdp%s %s, #%d, c%s, c%s, c%s, #%d", ccn,
1746 arm_coproc_names[coproc], op1, arm_reg_names[rd],
1747 arm_reg_names[rn], arm_reg_names[rm], op2) >= buflen)
1748 return (-1);
1749
1750 return (0);
1751 }
1752
1753 /*
1754 * Here we handle coprocesser single register transfers.
1755 *
1756 * MCR:
1757 * 31 - 28|27 - 24|23-21|20|19-16|15-12|11 - 8|7 - 5|4|3-0
1758 * [ cond |1 1 1 0| op_1| 0| CRn | Rd | cp # | op_2|1|CRm ]
1759 *
1760 * MRC:
1761 * 31 - 28|27 - 24|23-21|20|19-16|15-12|11 - 8|7 - 5|4|3-0
1762 * [ cond |1 1 1 0| op_1| 1| CRn | Rd | cp # | op_2|1|CRm ]
1763 */
1764 static int
1765 arm_dis_coproc_rt(uint32_t in, char *buf, size_t buflen)
1766 {
1767 arm_cond_code_t cc;
1768 arm_reg_t rn, rd, rm;
1769 uint8_t op1, op2, coproc;
1770 const char *ccn;
1771 size_t len;
1772
1773 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1774 coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1775 rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1776 rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1777 rm = in & ARM_COPROC_RM_MASK;
1778 op1 = (in & ARM_COPROC_CRT_OP1_MASK) >> ARM_COPROC_CRT_OP1_SHIFT;
1779 op2 = (in & ARM_COPROC_CRT_OP2_MASK) >> ARM_COPROC_CRT_OP2_SHIFT;
1780
1781 if (cc == ARM_COND_NACC)
1782 ccn = "2";
1783 else
1784 ccn = arm_cond_names[cc];
1785
1786 len = snprintf(buf, buflen, "%s%s %s, #%d, %s, c%s, c%s",
1787 (in & ARM_COPROC_CRT_DIR_MASK) != 0 ? "mrc" : "mcr", ccn,
1788 arm_coproc_names[coproc], op1, arm_reg_names[rd],
1789 arm_reg_names[rn], arm_reg_names[rm]);
1790 if (len >= buflen)
1791 return (-1);
1792
1793 if (op2 != 0)
1794 if (snprintf(buf + len, buflen - len, ", #%d", op2) >=
1795 buflen - len)
1796 return (-1);
1797 return (0);
1798 }
1799
1800 /*
1801 * Here we handle the set of unconditional instructions.
1802 */
1803 static int
1804 arm_dis_uncond_insn(uint32_t in, char *buf, size_t buflen)
1805 {
1806 int imm, sc;
1807 arm_reg_t rn, rm;
1821 * effect: determines what to do with the A, I, F interrupt bits in the
1822 * CPSR. effect is encoded in the imod field. It is either enable
1823 * interrupts 0b10 or disable interrupts 0b11. Recall that interrupts
1824 * are active low in the CPSR. If effect is not specified then this is
1825 * strictly a mode change which is required.
1826 *
1827 * A, I, F: If effect is specified then the bits which are high are
1828 * modified by the instruction.
1829 *
1830 * mode: Specifies a mode to change to. mmod will be 1 if mode is set.
1831 *
1832 */
1833 if ((in & ARM_UNI_CPS_MASK) == ARM_UNI_CPS_TARG) {
1834 imm = (in & ARM_UNI_CPS_IMOD_MASK) > ARM_UNI_CPS_IMOD_SHIFT;
1835
1836 /* Ob01 is not a valid value for the imod */
1837 if (imm == 1)
1838 return (-1);
1839
1840 if (imm != 0)
1841 len = snprintf(buf, buflen, "cps%s %s%s%s%s",
1842 imm == 2 ? "ie" : "id",
1843 (in & ARM_UNI_CPS_A_MASK) ? "a" : "",
1844 (in & ARM_UNI_CPS_I_MASK) ? "i" : "",
1845 (in & ARM_UNI_CPS_F_MASK) ? "f" : "",
1846 (in & ARM_UNI_CPS_MMOD_MASK) ? " ," : "");
1847 else
1848 len = snprintf(buf, buflen, "cps ");
1849 if (len >= buflen)
1850 return (-1);
1851
1852 if (in & ARM_UNI_CPS_MMOD_MASK)
1853 if (snprintf(buf + len, buflen - len, "#%d",
1854 in & ARM_UNI_CPS_MODE_MASK) >= buflen - len)
1855 return (-1);
1856 return (0);
1857 }
1858
1859 if ((in & ARM_UNI_SE_MASK) == ARM_UNI_SE_TARG) {
1860 if (snprintf(buf, buflen, "SETEND %s",
1861 (in & ARM_UNI_SE_BE_MASK) ? "be" : "le") >= buflen)
1862 return (-1);
1863 return (0);
1864 }
1865
1866 /*
1867 * The cache preload is like a load, but it has a much simpler set of
1868 * constraints. The only valid bits that you can transform are the I and
1869 * the U bits. We have to use pre-indexed addressing. This means that we
1870 * only have the U bit and the I bit. See arm_dis_ldstr for a full
1871 * explanation of what's happening here.
1872 */
1873 if ((in & ARM_UNI_PLD_MASK) == ARM_UNI_PLD_TARG) {
1874 rn = (in & ARM_LS_RN_MASK) >> ARM_LS_RN_SHIFT;
1875 if ((in & ARM_LS_IBIT_MASK) == 0) {
1876 if (snprintf(buf, buflen, "pld [%s, #%s%d",
1877 arm_reg_names[rn],
1878 (in & ARM_LS_UBIT_MASK) != 0 ? "" : "-",
1879 in & ARM_LS_IMM_MASK) >= buflen)
1880 return (-1);
1881 return (0);
1882 }
1883
1884 rm = in & ARM_LS_REG_RM_MASK;
1885 len = snprintf(buf, buflen, "pld [%s, %s%s", arm_reg_names[rn],
1886 (in & ARM_LS_UBIT_MASK) != 0 ? "" : "-",
1887 arm_reg_names[rm]);
1888 if (len >= buflen)
1889 return (-1);
1890
1891 if ((in & ARM_LS_REG_NRM_MASK) != 0) {
1892 imm = (in & ARM_LS_SCR_SIMM_MASK) >>
1893 ARM_LS_SCR_SIMM_SHIFT;
1894 sc = (in & ARM_LS_SCR_SCODE_MASK) >>
1895 ARM_LS_SCR_SCODE_SHIFT;
1896
1897 if (imm == 0 && sc == DPI_S_ROR)
1898 sc = DPI_S_RRX;
1899
1900 len += snprintf(buf + len, buflen - len, "%s",
1901 arm_dpi_shifts[sc]);
1902 if (len >= buflen)
1903 return (-1);
1904 if (sc != DPI_S_RRX) {
1905 len += snprintf(buf + len, buflen - len,
1906 " #%d", imm);
1907 if (len >= buflen)
1908 return (-1);
1909 }
1910 }
1911 if (snprintf(buf + len, buflen - len, "]") >= buflen - len)
1912 return (-1);
1913 return (0);
1914 }
1915
1916 /*
1917 * This is a special case of STM, but it works across chip modes.
1918 */
1919 if ((in & ARM_UNI_SRS_MASK) == ARM_UNI_SRS_TARG) {
1920 imm = (in & ARM_LSM_ADDR_MASK) >> ARM_LSM_ADDR_SHIFT;
1921 if (snprintf(buf, buflen, "srs%s #%d%s",
1922 arm_lsm_mode_names[imm],
1923 in & ARM_UNI_SRS_MODE_MASK,
1924 (in & ARM_UNI_SRS_WBIT_MASK) != 0 ? "!" : "") >= buflen)
1925 return (-1);
1926 return (0);
1927 }
1928
1929 /*
1930 * RFE is a return from exception instruction that is similar to the LDM
1931 * and STM, but a bit different.
1932 */
1933 if ((in & ARM_UNI_RFE_MASK) == ARM_UNI_RFE_TARG) {
1934 imm = (in & ARM_LSM_ADDR_MASK) >> ARM_LSM_ADDR_SHIFT;
1935 rn = (in & ARM_LS_RN_MASK) >> ARM_LS_RN_SHIFT;
1936 if (snprintf(buf, buflen, "rfe%s %s%s", arm_lsm_mode_names[imm],
1937 arm_reg_names[rn],
1938 (in & ARM_UNI_RFE_WBIT_MASK) != 0 ? "!" : "") >= buflen)
1939 return (-1);
1940 return (0);
1941 }
1942
1943 if ((in & ARM_UNI_BLX_MASK) == ARM_UNI_BLX_TARG) {
1944 if (snprintf(buf, buflen, "blx %d",
1945 in & ARM_UNI_BLX_IMM_MASK) >= buflen)
1946 return (-1);
1947 return (0);
1948 }
1949
1950 if ((in & ARM_UNI_CODRT_MASK) == ARM_UNI_CODRT_TARG) {
1951 return (arm_dis_coproc_lsdrt(in, buf, buflen));
1952 }
1953
1954 if ((in & ARM_UNI_CORT_MASK) == ARM_UNI_CORT_TARG) {
1955 return (arm_dis_coproc_rt(in, buf, buflen));
1956 }
1957
1958 if ((in & ARM_UNI_CODP_MASK) == ARM_UNI_CORT_TARG) {
1959 return (arm_dis_coproc_dp(in, buf, buflen));
1960 }
1961
1962 /*
1963 * An undefined or illegal instruction
1964 */
1969 * Disassemble B and BL instructions. The instruction is given a 24-bit two's
1970 * complement value as an offset address. This value gets sign extended to 30
1971 * bits and then shifted over two bits. This is then added to the PC + 8. So,
1972 * instead of dispalying an absolute address, we're going to display the delta
1973 * that the instruction has instead.
1974 */
1975 static int
1976 arm_dis_branch(dis_handle_t *dhp, uint32_t in, char *buf, size_t buflen)
1977 {
1978 uint32_t addr;
1979 arm_cond_code_t cc;
1980 size_t len;
1981
1982 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1983 addr = in & ARM_BRANCH_IMM_MASK;
1984 if (in & ARM_BRANCH_SIGN_MASK)
1985 addr |= ARM_BRANCH_NEG_SIGN;
1986 else
1987 addr &= ARM_BRANCH_POS_SIGN;
1988 addr <<= 2;
1989 if ((len = snprintf(buf, buflen, "b%s%s %d",
1990 (in & ARM_BRANCH_LBIT_MASK) != 0 ? "l" : "",
1991 arm_cond_names[cc], (int)addr)) >= buflen)
1992 return (-1);
1993
1994 /* Per the ARM manuals, we have to account for the extra 8 bytes here */
1995 if (dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int)addr + 8, NULL, 0,
1996 NULL, NULL) == 0) {
1997 len += snprintf(buf + len, buflen - len, "\t<");
1998 if (len >= buflen)
1999 return (-1);
2000 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int)addr + 8,
2001 buf + len, buflen - len, NULL, NULL);
2002 strlcat(buf, ">", buflen);
2003 }
2004
2005 return (0);
2006 }
2007
2008 /*
2009 * There are six instructions that are covered here: ADD16, ADDSUBX, SUBADDX,
2010 * SUB16, ADD8, and SUB8. They can hae the following variations: S, Q, SH, U,
2071 arm_dis_extend(uint32_t in, char *buf, size_t buflen)
2072 {
2073 uint8_t op, rot;
2074 int sbit;
2075 arm_cond_code_t cc;
2076 arm_reg_t rn, rm, rd;
2077 const char *opn;
2078 size_t len;
2079
2080
2081 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2082 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2083 rm = in & ARM_MEDIA_RM_MASK;
2084 op = (in & ARM_MEDIA_SZE_OP_MASK) >> ARM_MEDIA_SZE_OP_SHIFT;
2085 rot = (in & ARM_MEDIA_SZE_ROT_MASK) >> ARM_MEDIA_SZE_ROT_SHIFT;
2086 sbit = in & ARM_MEDIA_SZE_S_MASK;
2087 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2088
2089 switch (op) {
2090 case 0x0:
2091 opn = rn == ARM_REG_R15 ? "xtab16" : "xtb16";
2092 break;
2093 case 0x2:
2094 opn = rn == ARM_REG_R15 ? "xtab" : "xtb";
2095 break;
2096 case 0x3:
2097 opn = rn == ARM_REG_R15 ? "xtah" : "xth";
2098 break;
2099 default:
2100 return (-1);
2101 break;
2102 }
2103
2104 if (rn == ARM_REG_R15) {
2105 len = snprintf(buf, buflen, "%s%s%s %s, %s",
2106 sbit != 0 ? "u" : "s",
2107 opn, arm_cond_names[cc], arm_reg_names[rd],
2108 arm_reg_names[rn]);
2109 } else {
2110 len = snprintf(buf, buflen, "%s%s%s %s, %s, %s",
2111 sbit != 0 ? "u" : "s",
2112 opn, arm_cond_names[cc], arm_reg_names[rd],
2113 arm_reg_names[rn], arm_reg_names[rm]);
2114 }
2115
2116 if (len >= buflen)
2117 return (-1);
2118
2119 if (snprintf(buf + len, buflen - len, "%s",
2120 arm_extend_rot_names[rot]) >= buflen - len)
2121 return (-1);
2122 return (0);
2123 }
2124
2125 /*
2126 * The media instructions and extensions can be divided into different groups of
2127 * instructions. We first use bits 23 and 24 to figure out where to send it. We
2128 * call this group of bits the l1 mask.
2129 */
2130 static int
2131 arm_dis_media(uint32_t in, char *buf, size_t buflen)
2134 arm_cond_code_t cc;
2135 arm_reg_t rd, rn, rs, rm;
2136 int xbit;
2137 size_t len;
2138
2139 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2140 l1 = (in & ARM_MEDIA_L1_MASK) >> ARM_MEDIA_L1_SHIFT;
2141 switch (l1) {
2142 case 0x0:
2143 return (arm_dis_padd(in, buf, buflen));
2144 break;
2145 case 0x1:
2146 if ((in & ARM_MEDIA_HPACK_MASK) == ARM_MEDIA_HPACK_TARG) {
2147 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2148 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2149 rm = in & ARM_MEDIA_RM_MASK;
2150 op1 = (in & ARM_MEDIA_HPACK_SHIFT_MASK) >>
2151 ARM_MEDIA_HPACK_SHIFT_IMM;
2152 len = snprintf(buf, buflen, "%s%s %s, %s, %s",
2153 (in & ARM_MEDIA_HPACK_OP_MASK) != 0 ?
2154 "pkhtb" : "pkhbt", arm_cond_names[cc],
2155 arm_reg_names[rd], arm_reg_names[rn],
2156 arm_reg_names[rd]);
2157 if (len >= buflen)
2158 return (-1);
2159
2160 if (op1 != 0) {
2161 if (in & ARM_MEDIA_HPACK_OP_MASK)
2162 len += snprintf(buf + len, buflen - len,
2163 ", asr %d", op1);
2164 else
2165 len += snprintf(buf + len, buflen - len,
2166 ", lsl %d", op1);
2167 }
2168 return (len >= buflen ? -1 : 0);
2169 }
2170
2171 if ((in & ARM_MEDIA_WSAT_MASK) == ARM_MEDIA_WSAT_TARG) {
2172 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2173 rm = in & ARM_MEDIA_RM_MASK;
2174 op1 = (in & ARM_MEDIA_SAT_IMM_MASK) >>
2175 ARM_MEDIA_SAT_IMM_SHIFT;
2176 op2 = (in & ARM_MEDIA_SAT_SHI_MASK) >>
2177 ARM_MEDIA_SAT_SHI_SHIFT;
2178 len = snprintf(buf, buflen, "%s%s %s, #%d, %s",
2179 (in & ARM_MEDIA_SAT_U_MASK) != 0 ? "usat" : "ssat",
2180 arm_cond_names[cc], arm_reg_names[rd], op1,
2181 arm_reg_names[rm]);
2182
2183 if (len >= buflen)
2184 return (-1);
2185
2186 /*
2187 * The shift is optional in the assembler and encoded as
2188 * LSL 0. However if we get ASR 0, that means ASR #32.
2189 * An ARM_MEDIA_SAT_STYPE_MASK of 0 is LSL, 1 is ASR.
2190 */
2191 if (op2 != 0 || (in & ARM_MEDIA_SAT_STYPE_MASK) == 1) {
2192 if (op2 == 0)
2193 op2 = 32;
2194 if (snprintf(buf + len, buflen - len,
2195 ", %s #%d",
2196 (in & ARM_MEDIA_SAT_STYPE_MASK) != 0 ?
2197 "asr" : "lsl", op2) >= buflen - len)
2198 return (-1);
2199 }
2200 return (0);
2201 }
2202
2203 if ((in & ARM_MEDIA_PHSAT_MASK) == ARM_MEDIA_PHSAT_TARG) {
2204 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2205 rm = in & ARM_MEDIA_RM_MASK;
2206 op1 = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2207 if (snprintf(buf, buflen, "%s%s %s, #%d, %s",
2208 (in & ARM_MEDIA_SAT_U_MASK) != 0 ?
2209 "usat16" : "ssat16",
2210 arm_cond_names[cc], arm_reg_names[rd], op1,
2211 arm_reg_names[rm]) >= buflen)
2212 return (-1);
2213 return (0);
2214 }
2215
2216 if ((in & ARM_MEDIA_REV_MASK) == ARM_MEDIA_REV_TARG) {
2217 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2218 rm = in & ARM_MEDIA_RM_MASK;
2219 if (snprintf(buf, buflen, "rev%s %s, %s",
2220 arm_cond_names[cc], arm_reg_names[rd],
2221 arm_reg_names[rd]) >= buflen)
2222 return (-1);
2223 return (0);
2224 }
2225
2226 if ((in & ARM_MEDIA_BRPH_MASK) == ARM_MEDIA_BRPH_TARG) {
2227 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2228 rm = in & ARM_MEDIA_RM_MASK;
2229 if (snprintf(buf, buflen, "rev16%s %s, %s",
2230 arm_cond_names[cc], arm_reg_names[rd],
2231 arm_reg_names[rd]) >= buflen)
2232 return (-1);
2233 return (0);
2234 }
2235
2236 if ((in & ARM_MEDIA_BRSH_MASK) == ARM_MEDIA_BRSH_TARG) {
2237 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2238 rm = in & ARM_MEDIA_RM_MASK;
2239 if (snprintf(buf, buflen, "revsh%s %s, %s",
2240 arm_cond_names[cc], arm_reg_names[rd],
2241 arm_reg_names[rd]) >= buflen)
2242 return (-1);
2243 return (0);
2244 }
2245
2246 if ((in & ARM_MEDIA_SEL_MASK) == ARM_MEDIA_SEL_TARG) {
2247 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2248 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2249 rm = in & ARM_MEDIA_RM_MASK;
2250 if (snprintf(buf, buflen, "sel%s %s, %s, %s",
2251 arm_cond_names[cc], arm_reg_names[rd],
2252 arm_reg_names[rn], arm_reg_names[rm]) >= buflen)
2253 return (-1);
2254 return (0);
2255 }
2256
2257 if ((in & ARM_MEDIA_SZE_MASK) == ARM_MEDIA_SZE_TARG)
2258 return (arm_dis_extend(in, buf, buflen));
2259 /* Unknown instruction */
2260 return (-1);
2261 break;
2262 case 0x2:
2263 /*
2264 * This consists of the following multiply instructions:
2265 * SMLAD, SMLSD, SMLALD, SMUAD, and SMUSD.
2266 *
2267 * SMLAD and SMUAD encoding are the same, switch on Rn == R15
2268 * 22-20 are 000 7-6 are 00
2269 * SMLSD and SMUSD encoding are the same, switch on Rn == R15
2270 * 22-20 are 000 7-6 are 01
2271 * SMLALD: 22-20 are 100 7-6 are 00
2272 */
2273 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2274 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2275 rs = (in & ARM_MEDIA_RS_MASK) >> ARM_MEDIA_RS_SHIFT;
2276 rm = in & ARM_MEDIA_RM_MASK;
2277 op1 = (in & ARM_MEDIA_OP1_MASK) >> ARM_MEDIA_OP1_SHIFT;
2278 op2 = (in & ARM_MEDIA_OP2_MASK) >> ARM_MEDIA_OP2_SHIFT;
2279 xbit = in & ARM_MEDIA_MULT_X_MASK;
2280
2281 if (op1 == 0x0) {
2282 if (op2 != 0x0 && op2 != 0x1)
2283 return (-1);
2284 if (rn == ARM_REG_R15) {
2285 len = snprintf(buf, buflen, "%s%s%s %s, %s, %s",
2286 op2 != 0 ? "smusd" : "smuad",
2287 xbit != 0 ? "x" : "x",
2288 arm_cond_names[cc], arm_reg_names[rd],
2289 arm_reg_names[rm], arm_reg_names[rs]);
2290 } else {
2291 len = snprintf(buf, buflen,
2292 "%s%s%s %s, %s, %s, %s",
2293 op2 != 0 ? "smlsd" : "smlad",
2294 xbit != 0 ? "x" : "",
2295 arm_cond_names[cc], arm_reg_names[rd],
2296 arm_reg_names[rm], arm_reg_names[rs],
2297 arm_reg_names[rn]);
2298
2299 }
2300 } else if (op1 == 0x8) {
2301 if (op2 != 0x0)
2302 return (-1);
2303 len = snprintf(buf, buflen, "smlald%s%s %s, %s, %s, %s",
2304 xbit != 0 ? "x" : "",
2305 arm_cond_names[cc], arm_reg_names[rn],
2306 arm_reg_names[rd], arm_reg_names[rm],
2307 arm_reg_names[rs]);
2308 } else
2309 return (-1);
2310
2311 return (len >= buflen ? -1 : 0);
2312 break;
2313 case 0x3:
2314 /*
2315 * Here we handle USAD8 and USADA8. The main difference is the
2316 * presence of RN. USAD8 is defined as having a value of rn that
2317 * is not r15. If it is r15, then instead it is USADA8.
2318 */
2319 if ((in & ARM_MEDIA_OP1_MASK) != 0)
2320 return (-1);
2321 if ((in & ARM_MEDIA_OP2_MASK) != 0)
2322 return (-1);
2323
2324 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2325 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2326 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2327 rs = (in & ARM_MEDIA_RS_MASK) >> ARM_MEDIA_RS_SHIFT;
2328 rm = in & ARM_MEDIA_RM_MASK;
2329
2330 if (rn != ARM_REG_R15)
2331 len = snprintf(buf, buflen, "usada8%s %s, %s, %s, %s",
2332 arm_cond_names[cc], arm_reg_names[rd],
2333 arm_reg_names[rm], arm_reg_names[rs],
2334 arm_reg_names[rn]);
2335 else
2336 len = snprintf(buf, buflen, "usad8%s %s, %s, %s",
2337 arm_cond_names[cc], arm_reg_names[rd],
2338 arm_reg_names[rm], arm_reg_names[rs]);
2339 return (len >= buflen ? -1 : 0);
2340 break;
2341 default:
2342 return (-1);
2343 }
2344 }
2345
2346 /*
2347 * Each instruction in the ARM instruction set is a uint32_t and in our case is
2348 * LE. The upper four bits determine the condition code. If the conditoin code
2349 * is undefined then we know to immediately jump there. Otherwise we go use the
2350 * next three bits to determine where we should go next and how to further
2351 * process the instruction in question. The ARM instruction manual doesn't
2352 * define this field so we're going to call it the L1_DEC or level 1 decoding
2353 * from which it will have to be further subdivided into the specific
2354 * instruction groupings that we care about.
2355 */
2356 static int
2489 /* coprocessor load/store && double register transfers */
2490 return (arm_dis_coproc_lsdrt(in, buf, buflen));
2491 break;
2492 case 0x7:
2493 /*
2494 * In l1 group 0b111 you can determine the three groups using
2495 * the following logic. If the next bit after the l1 group (bit
2496 * 24) is one than you know that it is a software interrupt.
2497 * Otherwise it is one of the coprocessor instructions.
2498 * Furthermore you can tell apart the data processing from the
2499 * register transfers based on bit 4. If it is zero then it is
2500 * a data processing instruction, otherwise it is a register
2501 * transfer.
2502 */
2503 if (in & ARM_L1_7_SWINTMASK) {
2504 /*
2505 * The software interrupt is pretty straightforward. The
2506 * lower 24 bits are the interrupt number. It's also
2507 * valid for it to run with a condition code.
2508 */
2509 if (snprintf(buf, buflen, "swi%s %d",
2510 arm_cond_names[cc],
2511 in & ARM_SWI_IMM_MASK) >= buflen)
2512 return (-1);
2513 return (0);
2514 } else if (in & ARM_L1_7_COPROCMASK) {
2515 /* coprocessor register transfers */
2516 return (arm_dis_coproc_rt(in, buf, buflen));
2517 } else {
2518 /* coprocessor data processing */
2519 return (arm_dis_coproc_dp(in, buf, buflen));
2520 }
2521 break;
2522 }
2523
2524 return (-1);
2525 }
2526
2527 static int
2528 dis_arm_supports_flags(int flags)
2529 {
|