Annotation of sys/arch/arm/arm/disassem.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: disassem.c,v 1.1 2004/02/01 05:09:48 drahn Exp $ */
! 2: /* $NetBSD: disassem.c,v 1.14 2003/03/27 16:58:36 mycroft Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1996 Mark Brinicombe.
! 6: * Copyright (c) 1996 Brini.
! 7: *
! 8: * All rights reserved.
! 9: *
! 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice, this list of conditions and the following disclaimer.
! 15: * 2. Redistributions in binary form must reproduce the above copyright
! 16: * notice, this list of conditions and the following disclaimer in the
! 17: * documentation and/or other materials provided with the distribution.
! 18: * 3. All advertising materials mentioning features or use of this software
! 19: * must display the following acknowledgement:
! 20: * This product includes software developed by Brini.
! 21: * 4. The name of the company nor the name of the author may be used to
! 22: * endorse or promote products derived from this software without specific
! 23: * prior written permission.
! 24: *
! 25: * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
! 26: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
! 27: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 28: * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
! 29: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 30: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 31: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 35: * SUCH DAMAGE.
! 36: *
! 37: * RiscBSD kernel project
! 38: *
! 39: * db_disasm.c
! 40: *
! 41: * Kernel disassembler
! 42: *
! 43: * Created : 10/02/96
! 44: *
! 45: * Structured after the sparc/sparc/db_disasm.c by David S. Miller &
! 46: * Paul Kranenburg
! 47: *
! 48: * This code is not complete. Not all instructions are disassembled.
! 49: */
! 50:
! 51: #include <sys/param.h>
! 52:
! 53: #include <sys/systm.h>
! 54: #include <machine/db_machdep.h>
! 55: #include <ddb/db_access.h>
! 56: #include <ddb/db_sym.h>
! 57: #include <ddb/db_variables.h>
! 58: #include <ddb/db_interface.h>
! 59: #include <arch/arm/arm/disassem.h>
! 60:
! 61: /*
! 62: * General instruction format
! 63: *
! 64: * insn[cc][mod] [operands]
! 65: *
! 66: * Those fields with an uppercase format code indicate that the field
! 67: * follows directly after the instruction before the separator i.e.
! 68: * they modify the instruction rather than just being an operand to
! 69: * the instruction. The only exception is the writeback flag which
! 70: * follows a operand.
! 71: *
! 72: *
! 73: * 2 - print Operand 2 of a data processing instruction
! 74: * d - destination register (bits 12-15)
! 75: * n - n register (bits 16-19)
! 76: * s - s register (bits 8-11)
! 77: * o - indirect register rn (bits 16-19) (used by swap)
! 78: * m - m register (bits 0-3)
! 79: * a - address operand of ldr/str instruction
! 80: * l - register list for ldm/stm instruction
! 81: * f - 1st fp operand (register) (bits 12-14)
! 82: * g - 2nd fp operand (register) (bits 16-18)
! 83: * h - 3rd fp operand (register/immediate) (bits 0-4)
! 84: * b - branch address
! 85: * t - thumb branch address (bits 24, 0-23)
! 86: * k - breakpoint comment (bits 0-3, 8-19)
! 87: * X - block transfer type
! 88: * Y - block transfer type (r13 base)
! 89: * c - comment field bits(0-23)
! 90: * p - saved or current status register
! 91: * F - PSR transfer fields
! 92: * D - destination-is-r15 (P) flag on TST, TEQ, CMP, CMN
! 93: * L - co-processor transfer size
! 94: * S - set status flag
! 95: * P - fp precision
! 96: * Q - fp precision (for ldf/stf)
! 97: * R - fp rounding
! 98: * v - co-processor data transfer registers + addressing mode
! 99: * W - writeback flag
! 100: * x - instruction in hex
! 101: * # - co-processor number
! 102: * y - co-processor data processing registers
! 103: * z - co-processor register transfer registers
! 104: */
! 105:
! 106: struct arm32_insn {
! 107: u_int mask;
! 108: u_int pattern;
! 109: char* name;
! 110: char* format;
! 111: };
! 112:
! 113: static const struct arm32_insn arm32_i[] = {
! 114: { 0x0fffffff, 0x0ff00000, "imb", "c" }, /* Before swi */
! 115: { 0x0fffffff, 0x0ff00001, "imbrange", "c" }, /* Before swi */
! 116: { 0x0f000000, 0x0f000000, "swi", "c" },
! 117: { 0xfe000000, 0xfa000000, "blx", "t" }, /* Before b and bl */
! 118: { 0x0f000000, 0x0a000000, "b", "b" },
! 119: { 0x0f000000, 0x0b000000, "bl", "b" },
! 120: { 0x0fe000f0, 0x00000090, "mul", "Snms" },
! 121: { 0x0fe000f0, 0x00200090, "mla", "Snmsd" },
! 122: { 0x0fe000f0, 0x00800090, "umull", "Sdnms" },
! 123: { 0x0fe000f0, 0x00c00090, "smull", "Sdnms" },
! 124: { 0x0fe000f0, 0x00a00090, "umlal", "Sdnms" },
! 125: { 0x0fe000f0, 0x00e00090, "smlal", "Sdnms" },
! 126: { 0x0d700000, 0x04200000, "strt", "daW" },
! 127: { 0x0d700000, 0x04300000, "ldrt", "daW" },
! 128: { 0x0d700000, 0x04600000, "strbt", "daW" },
! 129: { 0x0d700000, 0x04700000, "ldrbt", "daW" },
! 130: { 0x0c500000, 0x04000000, "str", "daW" },
! 131: { 0x0c500000, 0x04100000, "ldr", "daW" },
! 132: { 0x0c500000, 0x04400000, "strb", "daW" },
! 133: { 0x0c500000, 0x04500000, "ldrb", "daW" },
! 134: { 0x0e1f0000, 0x080d0000, "stm", "YnWl" },/* separate out r13 base */
! 135: { 0x0e1f0000, 0x081d0000, "ldm", "YnWl" },/* separate out r13 base */
! 136: { 0x0e100000, 0x08000000, "stm", "XnWl" },
! 137: { 0x0e100000, 0x08100000, "ldm", "XnWl" },
! 138: { 0x0e1000f0, 0x00100090, "ldrb", "de" },
! 139: { 0x0e1000f0, 0x00000090, "strb", "de" },
! 140: { 0x0e1000f0, 0x001000d0, "ldrsb", "de" },
! 141: { 0x0e1000f0, 0x001000b0, "ldrh", "de" },
! 142: { 0x0e1000f0, 0x000000b0, "strh", "de" },
! 143: { 0x0e1000f0, 0x001000f0, "ldrsh", "de" },
! 144: { 0x0f200090, 0x00200090, "und", "x" }, /* Before data processing */
! 145: { 0x0e1000d0, 0x000000d0, "und", "x" }, /* Before data processing */
! 146: { 0x0ff00ff0, 0x01000090, "swp", "dmo" },
! 147: { 0x0ff00ff0, 0x01400090, "swpb", "dmo" },
! 148: { 0x0fbf0fff, 0x010f0000, "mrs", "dp" }, /* Before data processing */
! 149: { 0x0fb0fff0, 0x0120f000, "msr", "pFm" },/* Before data processing */
! 150: { 0x0fb0f000, 0x0320f000, "msr", "pF2" },/* Before data processing */
! 151: { 0x0ffffff0, 0x012fff10, "bx", "m" },
! 152: { 0x0fff0ff0, 0x016f0f10, "clz", "dm" },
! 153: { 0x0ffffff0, 0x012fff30, "blx", "m" },
! 154: { 0xfff000f0, 0xe1200070, "bkpt", "k" },
! 155: { 0x0de00000, 0x00000000, "and", "Sdn2" },
! 156: { 0x0de00000, 0x00200000, "eor", "Sdn2" },
! 157: { 0x0de00000, 0x00400000, "sub", "Sdn2" },
! 158: { 0x0de00000, 0x00600000, "rsb", "Sdn2" },
! 159: { 0x0de00000, 0x00800000, "add", "Sdn2" },
! 160: { 0x0de00000, 0x00a00000, "adc", "Sdn2" },
! 161: { 0x0de00000, 0x00c00000, "sbc", "Sdn2" },
! 162: { 0x0de00000, 0x00e00000, "rsc", "Sdn2" },
! 163: { 0x0df00000, 0x01100000, "tst", "Dn2" },
! 164: { 0x0df00000, 0x01300000, "teq", "Dn2" },
! 165: { 0x0de00000, 0x01400000, "cmp", "Dn2" },
! 166: { 0x0de00000, 0x01600000, "cmn", "Dn2" },
! 167: { 0x0de00000, 0x01800000, "orr", "Sdn2" },
! 168: { 0x0de00000, 0x01a00000, "mov", "Sd2" },
! 169: { 0x0de00000, 0x01c00000, "bic", "Sdn2" },
! 170: { 0x0de00000, 0x01e00000, "mvn", "Sd2" },
! 171: { 0x0ff08f10, 0x0e000100, "adf", "PRfgh" },
! 172: { 0x0ff08f10, 0x0e100100, "muf", "PRfgh" },
! 173: { 0x0ff08f10, 0x0e200100, "suf", "PRfgh" },
! 174: { 0x0ff08f10, 0x0e300100, "rsf", "PRfgh" },
! 175: { 0x0ff08f10, 0x0e400100, "dvf", "PRfgh" },
! 176: { 0x0ff08f10, 0x0e500100, "rdf", "PRfgh" },
! 177: { 0x0ff08f10, 0x0e600100, "pow", "PRfgh" },
! 178: { 0x0ff08f10, 0x0e700100, "rpw", "PRfgh" },
! 179: { 0x0ff08f10, 0x0e800100, "rmf", "PRfgh" },
! 180: { 0x0ff08f10, 0x0e900100, "fml", "PRfgh" },
! 181: { 0x0ff08f10, 0x0ea00100, "fdv", "PRfgh" },
! 182: { 0x0ff08f10, 0x0eb00100, "frd", "PRfgh" },
! 183: { 0x0ff08f10, 0x0ec00100, "pol", "PRfgh" },
! 184: { 0x0f008f10, 0x0e000100, "fpbop", "PRfgh" },
! 185: { 0x0ff08f10, 0x0e008100, "mvf", "PRfh" },
! 186: { 0x0ff08f10, 0x0e108100, "mnf", "PRfh" },
! 187: { 0x0ff08f10, 0x0e208100, "abs", "PRfh" },
! 188: { 0x0ff08f10, 0x0e308100, "rnd", "PRfh" },
! 189: { 0x0ff08f10, 0x0e408100, "sqt", "PRfh" },
! 190: { 0x0ff08f10, 0x0e508100, "log", "PRfh" },
! 191: { 0x0ff08f10, 0x0e608100, "lgn", "PRfh" },
! 192: { 0x0ff08f10, 0x0e708100, "exp", "PRfh" },
! 193: { 0x0ff08f10, 0x0e808100, "sin", "PRfh" },
! 194: { 0x0ff08f10, 0x0e908100, "cos", "PRfh" },
! 195: { 0x0ff08f10, 0x0ea08100, "tan", "PRfh" },
! 196: { 0x0ff08f10, 0x0eb08100, "asn", "PRfh" },
! 197: { 0x0ff08f10, 0x0ec08100, "acs", "PRfh" },
! 198: { 0x0ff08f10, 0x0ed08100, "atn", "PRfh" },
! 199: { 0x0f008f10, 0x0e008100, "fpuop", "PRfh" },
! 200: { 0x0e100f00, 0x0c000100, "stf", "QLv" },
! 201: { 0x0e100f00, 0x0c100100, "ldf", "QLv" },
! 202: { 0x0ff00f10, 0x0e000110, "flt", "PRgd" },
! 203: { 0x0ff00f10, 0x0e100110, "fix", "PRdh" },
! 204: { 0x0ff00f10, 0x0e200110, "wfs", "d" },
! 205: { 0x0ff00f10, 0x0e300110, "rfs", "d" },
! 206: { 0x0ff00f10, 0x0e400110, "wfc", "d" },
! 207: { 0x0ff00f10, 0x0e500110, "rfc", "d" },
! 208: { 0x0ff0ff10, 0x0e90f110, "cmf", "PRgh" },
! 209: { 0x0ff0ff10, 0x0eb0f110, "cnf", "PRgh" },
! 210: { 0x0ff0ff10, 0x0ed0f110, "cmfe", "PRgh" },
! 211: { 0x0ff0ff10, 0x0ef0f110, "cnfe", "PRgh" },
! 212: { 0xff100010, 0xfe000010, "mcr2", "#z" },
! 213: { 0x0f100010, 0x0e000010, "mcr", "#z" },
! 214: { 0xff100010, 0xfe100010, "mrc2", "#z" },
! 215: { 0x0f100010, 0x0e100010, "mrc", "#z" },
! 216: { 0xff000010, 0xfe000000, "cdp2", "#y" },
! 217: { 0x0f000010, 0x0e000000, "cdp", "#y" },
! 218: { 0xfe100090, 0xfc100000, "ldc2", "L#v" },
! 219: { 0x0e100090, 0x0c100000, "ldc", "L#v" },
! 220: { 0xfe100090, 0xfc000000, "stc2", "L#v" },
! 221: { 0x0e100090, 0x0c000000, "stc", "L#v" },
! 222: { 0x00000000, 0x00000000, NULL, NULL }
! 223: };
! 224:
! 225: static char const arm32_insn_conditions[][4] = {
! 226: "eq", "ne", "cs", "cc",
! 227: "mi", "pl", "vs", "vc",
! 228: "hi", "ls", "ge", "lt",
! 229: "gt", "le", "", "nv"
! 230: };
! 231:
! 232: static char const insn_block_transfers[][4] = {
! 233: "da", "ia", "db", "ib"
! 234: };
! 235:
! 236: static char const insn_stack_block_transfers[][4] = {
! 237: "ed", "ea", "fd", "fa"
! 238: };
! 239:
! 240: static char const op_shifts[][4] = {
! 241: "lsl", "lsr", "asr", "ror"
! 242: };
! 243:
! 244: static char const insn_fpa_rounding[][2] = {
! 245: "", "p", "m", "z"
! 246: };
! 247:
! 248: static char const insn_fpa_precision[][2] = {
! 249: "s", "d", "e", "p"
! 250: };
! 251:
! 252: static char const insn_fpaconstants[][8] = {
! 253: "0.0", "1.0", "2.0", "3.0",
! 254: "4.0", "5.0", "0.5", "10.0"
! 255: };
! 256:
! 257: #define insn_condition(x) arm32_insn_conditions[(x >> 28) & 0x0f]
! 258: #define insn_blktrans(x) insn_block_transfers[(x >> 23) & 3]
! 259: #define insn_stkblktrans(x) insn_stack_block_transfers[(x >> 23) & 3]
! 260: #define op2_shift(x) op_shifts[(x >> 5) & 3]
! 261: #define insn_fparnd(x) insn_fpa_rounding[(x >> 5) & 0x03]
! 262: #define insn_fpaprec(x) insn_fpa_precision[(((x >> 18) & 2)|(x >> 7)) & 1]
! 263: #define insn_fpaprect(x) insn_fpa_precision[(((x >> 21) & 2)|(x >> 15)) & 1]
! 264: #define insn_fpaimm(x) insn_fpaconstants[x & 0x07]
! 265:
! 266: /* Local prototypes */
! 267: static void disasm_register_shift(const disasm_interface_t *di, u_int insn);
! 268: static void disasm_print_reglist(const disasm_interface_t *di, u_int insn);
! 269: static void disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn,
! 270: u_int loc);
! 271: static void disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn,
! 272: u_int loc);
! 273: static void disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn,
! 274: u_int loc);
! 275: static db_expr_t disassemble_readword(db_expr_t address);
! 276: static void disassemble_printaddr(db_expr_t address);
! 277:
! 278: vaddr_t
! 279: disasm(const disasm_interface_t *di, vaddr_t loc, int altfmt)
! 280: {
! 281: struct arm32_insn *i_ptr = (struct arm32_insn *)&arm32_i;
! 282:
! 283: u_int insn;
! 284: int matchp;
! 285: int branch;
! 286: char* f_ptr;
! 287: int fmt;
! 288:
! 289: fmt = 0;
! 290: matchp = 0;
! 291: insn = di->di_readword(loc);
! 292:
! 293: /* di->di_printf("loc=%08x insn=%08x : ", loc, insn);*/
! 294:
! 295: while (i_ptr->name) {
! 296: if ((insn & i_ptr->mask) == i_ptr->pattern) {
! 297: matchp = 1;
! 298: break;
! 299: }
! 300: i_ptr++;
! 301: }
! 302:
! 303: if (!matchp) {
! 304: di->di_printf("und%s\t%08x\n", insn_condition(insn), insn);
! 305: return(loc + INSN_SIZE);
! 306: }
! 307:
! 308: /* If instruction forces condition code, don't print it. */
! 309: if ((i_ptr->mask & 0xf0000000) == 0xf0000000)
! 310: di->di_printf("%s", i_ptr->name);
! 311: else
! 312: di->di_printf("%s%s", i_ptr->name, insn_condition(insn));
! 313:
! 314: f_ptr = i_ptr->format;
! 315:
! 316: /* Insert tab if there are no instruction modifiers */
! 317:
! 318: if (*(f_ptr) < 'A' || *(f_ptr) > 'Z') {
! 319: ++fmt;
! 320: di->di_printf("\t");
! 321: }
! 322:
! 323: while (*f_ptr) {
! 324: switch (*f_ptr) {
! 325: /* 2 - print Operand 2 of a data processing instruction */
! 326: case '2':
! 327: if (insn & 0x02000000) {
! 328: int rotate= ((insn >> 7) & 0x1e);
! 329:
! 330: di->di_printf("#0x%08x",
! 331: (insn & 0xff) << (32 - rotate) |
! 332: (insn & 0xff) >> rotate);
! 333: } else {
! 334: disasm_register_shift(di, insn);
! 335: }
! 336: break;
! 337: /* d - destination register (bits 12-15) */
! 338: case 'd':
! 339: di->di_printf("r%d", ((insn >> 12) & 0x0f));
! 340: break;
! 341: /* D - insert 'p' if Rd is R15 */
! 342: case 'D':
! 343: if (((insn >> 12) & 0x0f) == 15)
! 344: di->di_printf("p");
! 345: break;
! 346: /* n - n register (bits 16-19) */
! 347: case 'n':
! 348: di->di_printf("r%d", ((insn >> 16) & 0x0f));
! 349: break;
! 350: /* s - s register (bits 8-11) */
! 351: case 's':
! 352: di->di_printf("r%d", ((insn >> 8) & 0x0f));
! 353: break;
! 354: /* o - indirect register rn (bits 16-19) (used by swap) */
! 355: case 'o':
! 356: di->di_printf("[r%d]", ((insn >> 16) & 0x0f));
! 357: break;
! 358: /* m - m register (bits 0-4) */
! 359: case 'm':
! 360: di->di_printf("r%d", ((insn >> 0) & 0x0f));
! 361: break;
! 362: /* a - address operand of ldr/str instruction */
! 363: case 'a':
! 364: disasm_insn_ldrstr(di, insn, loc);
! 365: break;
! 366: /* e - address operand of ldrh/strh instruction */
! 367: case 'e':
! 368: disasm_insn_ldrhstrh(di, insn, loc);
! 369: break;
! 370: /* l - register list for ldm/stm instruction */
! 371: case 'l':
! 372: disasm_print_reglist(di, insn);
! 373: break;
! 374: /* f - 1st fp operand (register) (bits 12-14) */
! 375: case 'f':
! 376: di->di_printf("f%d", (insn >> 12) & 7);
! 377: break;
! 378: /* g - 2nd fp operand (register) (bits 16-18) */
! 379: case 'g':
! 380: di->di_printf("f%d", (insn >> 16) & 7);
! 381: break;
! 382: /* h - 3rd fp operand (register/immediate) (bits 0-4) */
! 383: case 'h':
! 384: if (insn & (1 << 3))
! 385: di->di_printf("#%s", insn_fpaimm(insn));
! 386: else
! 387: di->di_printf("f%d", insn & 7);
! 388: break;
! 389: /* b - branch address */
! 390: case 'b':
! 391: branch = ((insn << 2) & 0x03ffffff);
! 392: if (branch & 0x02000000)
! 393: branch |= 0xfc000000;
! 394: di->di_printaddr(loc + 8 + branch);
! 395: break;
! 396: /* t - blx address */
! 397: case 't':
! 398: branch = ((insn << 2) & 0x03ffffff) |
! 399: (insn >> 23 & 0x00000002);
! 400: if (branch & 0x02000000)
! 401: branch |= 0xfc000000;
! 402: di->di_printaddr(loc + 8 + branch);
! 403: break;
! 404: /* X - block transfer type */
! 405: case 'X':
! 406: di->di_printf("%s", insn_blktrans(insn));
! 407: break;
! 408: /* Y - block transfer type (r13 base) */
! 409: case 'Y':
! 410: di->di_printf("%s", insn_stkblktrans(insn));
! 411: break;
! 412: /* c - comment field bits(0-23) */
! 413: case 'c':
! 414: di->di_printf("0x%08x", (insn & 0x00ffffff));
! 415: break;
! 416: /* k - breakpoint comment (bits 0-3, 8-19) */
! 417: case 'k':
! 418: di->di_printf("0x%04x",
! 419: (insn & 0x000fff00) >> 4 | (insn & 0x0000000f));
! 420: break;
! 421: /* p - saved or current status register */
! 422: case 'p':
! 423: if (insn & 0x00400000)
! 424: di->di_printf("spsr");
! 425: else
! 426: di->di_printf("cpsr");
! 427: break;
! 428: /* F - PSR transfer fields */
! 429: case 'F':
! 430: di->di_printf("_");
! 431: if (insn & (1 << 16))
! 432: di->di_printf("c");
! 433: if (insn & (1 << 17))
! 434: di->di_printf("x");
! 435: if (insn & (1 << 18))
! 436: di->di_printf("s");
! 437: if (insn & (1 << 19))
! 438: di->di_printf("f");
! 439: break;
! 440: /* B - byte transfer flag */
! 441: case 'B':
! 442: if (insn & 0x00400000)
! 443: di->di_printf("b");
! 444: break;
! 445: /* L - co-processor transfer size */
! 446: case 'L':
! 447: if (insn & (1 << 22))
! 448: di->di_printf("l");
! 449: break;
! 450: /* S - set status flag */
! 451: case 'S':
! 452: if (insn & 0x00100000)
! 453: di->di_printf("s");
! 454: break;
! 455: /* P - fp precision */
! 456: case 'P':
! 457: di->di_printf("%s", insn_fpaprec(insn));
! 458: break;
! 459: /* Q - fp precision (for ldf/stf) */
! 460: case 'Q':
! 461: break;
! 462: /* R - fp rounding */
! 463: case 'R':
! 464: di->di_printf("%s", insn_fparnd(insn));
! 465: break;
! 466: /* W - writeback flag */
! 467: case 'W':
! 468: if (insn & (1 << 21))
! 469: di->di_printf("!");
! 470: break;
! 471: /* # - co-processor number */
! 472: case '#':
! 473: di->di_printf("p%d", (insn >> 8) & 0x0f);
! 474: break;
! 475: /* v - co-processor data transfer registers+addressing mode */
! 476: case 'v':
! 477: disasm_insn_ldcstc(di, insn, loc);
! 478: break;
! 479: /* x - instruction in hex */
! 480: case 'x':
! 481: di->di_printf("0x%08x", insn);
! 482: break;
! 483: /* y - co-processor data processing registers */
! 484: case 'y':
! 485: di->di_printf("%d, ", (insn >> 20) & 0x0f);
! 486:
! 487: di->di_printf("c%d, c%d, c%d", (insn >> 12) & 0x0f,
! 488: (insn >> 16) & 0x0f, insn & 0x0f);
! 489:
! 490: di->di_printf(", %d", (insn >> 5) & 0x07);
! 491: break;
! 492: /* z - co-processor register transfer registers */
! 493: case 'z':
! 494: di->di_printf("%d, ", (insn >> 21) & 0x07);
! 495: di->di_printf("r%d, c%d, c%d, %d",
! 496: (insn >> 12) & 0x0f, (insn >> 16) & 0x0f,
! 497: insn & 0x0f, (insn >> 5) & 0x07);
! 498:
! 499: /* if (((insn >> 5) & 0x07) != 0)
! 500: di->di_printf(", %d", (insn >> 5) & 0x07);*/
! 501: break;
! 502: default:
! 503: di->di_printf("[%c - unknown]", *f_ptr);
! 504: break;
! 505: }
! 506: if (*(f_ptr+1) >= 'A' && *(f_ptr+1) <= 'Z')
! 507: ++f_ptr;
! 508: else if (*(++f_ptr)) {
! 509: ++fmt;
! 510: if (fmt == 1)
! 511: di->di_printf("\t");
! 512: else
! 513: di->di_printf(", ");
! 514: }
! 515: };
! 516:
! 517: di->di_printf("\n");
! 518:
! 519: return(loc + INSN_SIZE);
! 520: }
! 521:
! 522:
! 523: static void
! 524: disasm_register_shift(const disasm_interface_t *di, u_int insn)
! 525: {
! 526: di->di_printf("r%d", (insn & 0x0f));
! 527: if ((insn & 0x00000ff0) == 0)
! 528: ;
! 529: else if ((insn & 0x00000ff0) == 0x00000060)
! 530: di->di_printf(", rrx");
! 531: else {
! 532: if (insn & 0x10)
! 533: di->di_printf(", %s r%d", op2_shift(insn),
! 534: (insn >> 8) & 0x0f);
! 535: else
! 536: di->di_printf(", %s #%d", op2_shift(insn),
! 537: (insn >> 7) & 0x1f);
! 538: }
! 539: }
! 540:
! 541:
! 542: static void
! 543: disasm_print_reglist(const disasm_interface_t *di, u_int insn)
! 544: {
! 545: int loop;
! 546: int start;
! 547: int comma;
! 548:
! 549: di->di_printf("{");
! 550: start = -1;
! 551: comma = 0;
! 552:
! 553: for (loop = 0; loop < 17; ++loop) {
! 554: if (start != -1) {
! 555: if (loop == 16 || !(insn & (1 << loop))) {
! 556: if (comma)
! 557: di->di_printf(", ");
! 558: else
! 559: comma = 1;
! 560: if (start == loop - 1)
! 561: di->di_printf("r%d", start);
! 562: else
! 563: di->di_printf("r%d-r%d", start, loop - 1);
! 564: start = -1;
! 565: }
! 566: } else {
! 567: if (insn & (1 << loop))
! 568: start = loop;
! 569: }
! 570: }
! 571: di->di_printf("}");
! 572:
! 573: if (insn & (1 << 22))
! 574: di->di_printf("^");
! 575: }
! 576:
! 577: static void
! 578: disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn, u_int loc)
! 579: {
! 580: int offset;
! 581:
! 582: offset = insn & 0xfff;
! 583: if ((insn & 0x032f0000) == 0x010f0000) {
! 584: /* rA = pc, immediate index */
! 585: if (insn & 0x00800000)
! 586: loc += offset;
! 587: else
! 588: loc -= offset;
! 589: di->di_printaddr(loc + 8);
! 590: } else {
! 591: di->di_printf("[r%d", (insn >> 16) & 0x0f);
! 592: if ((insn & 0x03000fff) != 0x01000000) {
! 593: di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
! 594: if (!(insn & 0x00800000))
! 595: di->di_printf("-");
! 596: if (insn & (1 << 25))
! 597: disasm_register_shift(di, insn);
! 598: else
! 599: di->di_printf("#0x%03x", offset);
! 600: }
! 601: if (insn & (1 << 24))
! 602: di->di_printf("]");
! 603: }
! 604: }
! 605:
! 606: static void
! 607: disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn, u_int loc)
! 608: {
! 609: int offset;
! 610:
! 611: offset = ((insn & 0xf00) >> 4) | (insn & 0xf);
! 612: if ((insn & 0x004f0000) == 0x004f0000) {
! 613: /* rA = pc, immediate index */
! 614: if (insn & 0x00800000)
! 615: loc += offset;
! 616: else
! 617: loc -= offset;
! 618: di->di_printaddr(loc + 8);
! 619: } else {
! 620: di->di_printf("[r%d", (insn >> 16) & 0x0f);
! 621: if ((insn & 0x01400f0f) != 0x01400000) {
! 622: di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
! 623: if (!(insn & 0x00800000))
! 624: di->di_printf("-");
! 625: if (insn & (1 << 22))
! 626: di->di_printf("#0x%02x", offset);
! 627: else
! 628: di->di_printf("r%d", (insn & 0x0f));
! 629: }
! 630: if (insn & (1 << 24))
! 631: di->di_printf("]");
! 632: }
! 633: }
! 634:
! 635: static void
! 636: disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn, u_int loc)
! 637: {
! 638: if (((insn >> 8) & 0xf) == 1)
! 639: di->di_printf("f%d, ", (insn >> 12) & 0x07);
! 640: else
! 641: di->di_printf("c%d, ", (insn >> 12) & 0x0f);
! 642:
! 643: di->di_printf("[r%d", (insn >> 16) & 0x0f);
! 644:
! 645: di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
! 646:
! 647: if (!(insn & (1 << 23)))
! 648: di->di_printf("-");
! 649:
! 650: di->di_printf("#0x%03x", (insn & 0xff) << 2);
! 651:
! 652: if (insn & (1 << 24))
! 653: di->di_printf("]");
! 654:
! 655: if (insn & (1 << 21))
! 656: di->di_printf("!");
! 657: }
! 658:
! 659: static db_expr_t
! 660: disassemble_readword(db_expr_t address)
! 661: {
! 662: return(*((u_int *)address));
! 663: }
! 664:
! 665: static void
! 666: disassemble_printaddr(db_expr_t address)
! 667: {
! 668: printf("0x%08x", address);
! 669: }
! 670:
! 671: static const disasm_interface_t disassemble_di = {
! 672: disassemble_readword, disassemble_printaddr, printf
! 673: };
! 674:
! 675: void
! 676: disassemble(u_int address)
! 677: {
! 678:
! 679: (void)disasm(&disassemble_di, address, 0);
! 680: }
! 681:
! 682: /* End of disassem.c */
CVSweb