[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

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