Print this page
libdisasm: print push/pop register list in a more human readable form
Instead of just blindly dumping a list of registers, we detect ranges and
print a list of ranges.
libdisasm: print r9 as "fp"
libdisasm: use "push" and "pop" when appropriate
While there is nothing technically wrong with printing the actual
instruction, it is easier on the eyes to just use these common aliases.
libdisasm: remove shouting
There's no need to print everything upper case.


   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 {