[BACK]Return to disassem.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / arm

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