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

Annotation of sys/arch/alpha/alpha/db_disasm.c, Revision 1.1.1.1

1.1       nbrk        1: /* $OpenBSD: db_disasm.c,v 1.19 2007/02/14 00:53:47 jsg Exp $ */
                      2: /* $NetBSD: db_disasm.c,v 1.8 2000/05/25 19:57:30 jhawk Exp $ */
                      3:
                      4: /*
                      5:  * Mach Operating System
                      6:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
                      7:  * All Rights Reserved.
                      8:  *
                      9:  * Permission to use, copy, modify and distribute this software and its
                     10:  * documentation is hereby granted, provided that both the copyright
                     11:  * notice and this permission notice appear in all copies of the
                     12:  * software, derivative works or modified versions, and any portions
                     13:  * thereof, and that both notices appear in supporting documentation.
                     14:  *
                     15:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     16:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     17:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     18:  *
                     19:  * Carnegie Mellon requests users of this software to return to
                     20:  *
                     21:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     22:  *  School of Computer Science
                     23:  *  Carnegie Mellon University
                     24:  *  Pittsburgh PA 15213-3890
                     25:  *
                     26:  * any improvements or extensions that they make and grant Carnegie Mellon
                     27:  * the rights to redistribute these changes.
                     28:  */
                     29:
                     30: /*
                     31:  *     File: db_disasm.c
                     32:  *     Author: Alessandro Forin, Carnegie Mellon University
                     33:  *     Date:   11/91
                     34:  *
                     35:  *     Disassembler for Alpha
                     36:  *
                     37:  *     Modified for NetBSD/alpha by:
                     38:  *
                     39:  *     Christopher G. Demetriou, Carnegie Mellon University
                     40:  *
                     41:  *     Jason R. Thorpe, Numerical Aerospace Simulation Facility,
                     42:  *     NASA Ames Research Center
                     43:  *
                     44:  *     This code was derived exclusively from information available in
                     45:  *     "Alpha Architecture Reference Manual", Richard L. Sites ed.
                     46:  *     Digital Press, Burlington, MA 01803
                     47:  *     ISBN 1-55558-098-X, Order no. EY-L520E-DP
                     48:  */
                     49:
                     50: #include <sys/param.h>
                     51: #include <sys/systm.h>
                     52: #include <sys/proc.h>
                     53: #include <machine/db_machdep.h>
                     54: #include <alpha/alpha/db_instruction.h>
                     55:
                     56: #include <machine/pal.h>
                     57:
                     58: #include <ddb/db_access.h>
                     59: #include <ddb/db_sym.h>
                     60: #include <ddb/db_output.h>
                     61: #include <ddb/db_interface.h>
                     62:
                     63: /*
                     64:  * This would belong in a header file, except noone else needs it
                     65:  *
                     66:  * XXX THESE SHOULD BE CONVERTED TO ra, rb, rc FORMAT.
                     67:  */
                     68: typedef union {
                     69:        /*
                     70:         *      All instructions are 32 bits wide, PAL included
                     71:         */
                     72:        unsigned int    bits;
                     73:
                     74:        /*
                     75:         *      Internal processor register access instrs
                     76:         *      specify the IPR index, doubly specify the
                     77:         *      (same) GP register as src/dest, and qualifiers
                     78:         *      for the IPR set involved (abox/ibox/tmp)
                     79:         */
                     80:        struct {
                     81:                unsigned        index : 5,
                     82:                                regset : 3, /* a,i,p */
                     83:                                xxx : 8,
                     84:                                rs : 5,
                     85:                                rd : 5,
                     86:                                opcode : 6;
                     87:        } mXpr_format;
                     88:
                     89:        /*
                     90:         *      Load/store instructions have a 12 bit displacement,
                     91:         *      and two register specifiers just as normal ld/st.
                     92:         *      Four bits have special meanings:
                     93:         *              phy: bypass the MMU (physical access)
                     94:         *              alt: use mode in ALT register for checks,
                     95:         *                   or if PHY is also on locked/linked access
                     96:         *              rwc: read-with-write-check (probew)
                     97:         *              qw:  quadword access
                     98:         */
                     99:        struct {
                    100:                signed int      displacement : 12;
                    101:                unsigned        qw : 1,
                    102:                                qualif : 3,
                    103:                                rs : 5,
                    104:                                rd : 5,
                    105:                                opcode : 6;
                    106:        } mem_format;
                    107:
                    108:        /*
                    109:         *      Return from exception or interrupt has
                    110:         *      a branch-like encoding, but only one
                    111:         *      instantiation is actually usable.
                    112:         */
                    113:        struct {
                    114:                unsigned        xxx : 14,
                    115:                                zero : 1,       /* branch prediction! */
                    116:                                one : 1,
                    117:                                rb : 5,         /* r31 or stall */
                    118:                                ra : 5,         /* r31 or stall */
                    119:                                opcode : 6;
                    120:        } rei_format;
                    121:
                    122: } pal_instruction;
                    123:
                    124:
                    125: /*
                    126:  * Major opcodes
                    127:  */
                    128: static char *op_name[64] = {
                    129: /* 0 */        "call_pal", "op1", "op2", "op3", "op4", "op5",  "op6",  "op7",
                    130: /* 8 */        "lda",  "ldah", "ldbu", "ldq_u","ldwu", "stw",  "stb",  "stq_u",
                    131: /*16 */        "arit", "logical","bit","mul",  "op20", "vaxf", "ieeef","anyf",
                    132: /*24 */        "spec", "hw_mfpr","jump","hw_ld","intmisc","hw_mtpr","hw_rei","hw_st",
                    133: /*32 */        "ldf",  "ldg",  "lds",  "ldt",  "stf",  "stg",  "sts",  "stt",
                    134: /*40 */        "ldl",  "ldq",  "ldl_l","ldq_l","stl",  "stq",  "stl_c","stq_c",
                    135: /*48 */        "br",   "fbeq", "fblt", "fble", "bsr",  "fbne", "fbge", "fbgt",
                    136: /*56 */        "blbc", "beq",  "blt",  "ble",  "blbs", "bne",  "bge",  "bgt"
                    137: };
                    138:
                    139: /*
                    140:  * The function field is too big (7 or 11 bits), so the sub-tables
                    141:  * are addressed in a somewhat complicated manner to save
                    142:  * space.  After all, alu operations is what RISCs are good at.
                    143:  */
                    144:
                    145: struct tbl {
                    146:        const char      *name;
                    147:        int             code;
                    148: };
                    149:
                    150: static const struct tbl pal_op_tbl[] = {
                    151:        /* Common PAL function codes. */
                    152:        { "halt",               PAL_halt },
                    153:        { "cflush",             PAL_cflush },
                    154:        { "draina",             PAL_draina },
                    155:        { "cserve",             PAL_cserve, },
                    156:        { "swppal",             PAL_swppal },
                    157:        { "ipir",               PAL_ipir },
                    158:        { "bpt",                PAL_bpt },
                    159:        { "bugchk",             PAL_bugchk },
                    160:        { "imb",                PAL_imb },
                    161:        { "rdunique",           PAL_rdunique },
                    162:        { "wrunique",           PAL_wrunique },
                    163:        { "gentrap",            PAL_gentrap },
                    164:
                    165:        /* OSF/1 PAL function codes. */
                    166:        { "osf1_rdmces",        PAL_OSF1_rdmces },
                    167:        { "osf1_wrmces",        PAL_OSF1_wrmces },
                    168:        { "osf1_wrfen",         PAL_OSF1_wrfen },
                    169:        { "osf1_wrvptptr",      PAL_OSF1_wrvptptr },
                    170:        { "osf1_swpctx",        PAL_OSF1_swpctx },
                    171:        { "osf1_wrval",         PAL_OSF1_wrval },
                    172:        { "osf1_rdval",         PAL_OSF1_rdval },
                    173:        { "osf1_tbi",           PAL_OSF1_tbi },
                    174:        { "osf1_wrent",         PAL_OSF1_wrent },
                    175:        { "osf1_swpipl",        PAL_OSF1_swpipl },
                    176:        { "osf1_rdps",          PAL_OSF1_rdps },
                    177:        { "osf1_wrkgp",         PAL_OSF1_wrkgp },
                    178:        { "osf1_wrusp",         PAL_OSF1_wrusp },
                    179:        { "osf1_wrperfmon",     PAL_OSF1_wrperfmon },
                    180:        { "osf1_rdusp",         PAL_OSF1_rdusp },
                    181:        { "osf1_whami",         PAL_OSF1_whami },
                    182:        { "osf1_retsys",        PAL_OSF1_retsys },
                    183:        { "osf1_rti",           PAL_OSF1_rti },
                    184:        { "osf1_callsys",       PAL_OSF1_callsys },
                    185:
                    186:        { NULL,                 -1 },
                    187: };
                    188:
                    189: static const char *pal_opname(int);
                    190:
                    191: static const char *
                    192: pal_opname(op)
                    193:        int op;
                    194: {
                    195:        static char unk[11];
                    196:        int i;
                    197:
                    198:        for (i = 0; pal_op_tbl[i].name != NULL; i++) {
                    199:                if (pal_op_tbl[i].code == op)
                    200:                        return (pal_op_tbl[i].name);
                    201:        }
                    202:
                    203:        snprintf(unk, sizeof unk, "0x%x", op);
                    204:        return (unk);
                    205: }
                    206:
                    207: /* HW (PAL) instruction qualifiers, stright tables */
                    208: static const char *mXpr_name[8] = {
                    209:        "", "/i", "/a", "/ai", "/p", "/pi", "/pa", "/pai"
                    210: };
                    211: static const char *hwlds_name[8] = {
                    212:        "", "/r", "/a", "/ar", "/p", "/p?r", "_l-c", "_l-c/?r"
                    213: };
                    214:
                    215: /*
                    216:  * For this one we take the low nibble (valid values 0/2/9/b/d)
                    217:  * and shift it down one to get the row index.  Within a row
                    218:  * we can just take the high nibble deprived of the high bit
                    219:  * (valid values 0/1/2/3/4/6).  We could have used a flat 64
                    220:  * entry array, but in this way we use just 48 pointers.
                    221:  * BUGFIX: the 'cmpbge 0x0f' opcode fits in here too
                    222:  */
                    223: static const char *arit_c0[8] = {
                    224:        "addl", 0, "addq", 0, "addl/v", 0, "addq/v",
                    225: };
                    226: static const char *arit_c2[8] = {
                    227:        "s4addl", "s8addl", "s4addq", "s8addq",
                    228: };
                    229: static const char *arit_c9[8] = {
                    230:        "subl", 0, "subq", 0, "subl/v", 0, "subq/v",
                    231: };
                    232: static const char *arit_cB[8] = {
                    233:        "s4subl", "s8subl", "s4subq", "s8subq",
                    234: };
                    235: static const char *arit_cD[8] = {
                    236:        0, "cmpult", "cmpeq", "cmpule", "cmplt", 0, "cmple",
                    237: };
                    238: static const char *arit_cF[1] = {
                    239:        "cmpbge"
                    240: };
                    241: static const char **arit_opname[8] = {
                    242:        arit_c0, arit_c2, 0, 0, arit_c9, arit_cB, arit_cD, arit_cF
                    243: };
                    244:
                    245: static __inline const char *arit_name(int);
                    246: static __inline const char *
                    247: arit_name(op)
                    248:        int op;
                    249: {
                    250:        static char unk[32];
                    251:        const char *name = NULL;
                    252:
                    253:        if (arit_opname[((op)&0xe)>>1])
                    254:                name = arit_opname[((op)&0xe)>>1][((op)&0x70)>>4];
                    255:
                    256:        if (name != NULL)
                    257:                return (name);
                    258:
                    259:        snprintf(unk, sizeof unk, "?arit 0x%x?", op);
                    260:        return (unk);
                    261: }
                    262:
                    263: /*
                    264:  * Something similar for this one, except there are only
                    265:  * 16 entries so the row indexing is done by enumeration
                    266:  * of the low nibble (valid values 0/4/6/8).  Then we can
                    267:  * just shift the high nibble to index inside the row
                    268:  * (valid values are 0/2/4 or 1/2/4/6)
                    269:  *
                    270:  * There are two functions that don't play by these simple rules,
                    271:  * so we special-case them.
                    272:  */
                    273: static const char *logical_c0[4] = {
                    274:        "and", "or", "xor", 0
                    275: };
                    276: static const char *logical_c4[4] = {
                    277:        "cmovlbs", "cmoveq", "cmovlt", "cmovle"
                    278: };
                    279: static const char *logical_c6[4] = {
                    280:        "cmovlbc", "cmovne", "cmovge", "cmovgt"
                    281: };
                    282: static const char *logical_c8[4] = {
                    283:        "andnot", "ornot", "xornot", 0
                    284: };
                    285:
                    286: static __inline const char *logical_name(int);
                    287: static __inline const char *
                    288: logical_name(op)
                    289:        int op;
                    290: {
                    291:        static char unk[32];
                    292:        const char *name = NULL;
                    293:
                    294:        if (op == op_amask)
                    295:                return ("amask");
                    296:        else if (op == op_implver)
                    297:                return ("implver");
                    298:
                    299:        switch (op & 0xf) {
                    300:        case 0: name = logical_c0[((op)>>5)&3]; break;
                    301:        case 4: name = logical_c4[((op)>>5)&3]; break;
                    302:        case 6: name = logical_c6[((op)>>5)&3]; break;
                    303:        case 8: name = logical_c8[((op)>>5)&3]; break;
                    304:        }
                    305:
                    306:        if (name != NULL)
                    307:                return (name);
                    308:
                    309:        snprintf(unk, sizeof unk, "?logical 0x%x?", op);
                    310:        return (unk);
                    311: }
                    312:
                    313: /*
                    314:  * This is the messy one. First, we single out the dense
                    315:  * case of a 3 in the high nibble (valid values 0/1/2/4/6/9/b/c).
                    316:  * Then the case of a 2 in the low nibble (valid values 0/1/2/5/6/7).
                    317:  * For the remaining codes (6/7/a/b) we do as above: high
                    318:  * nibble has valid values 0/1/2 or 5/6/7.  The low nibble
                    319:  * can be used as row index picking bits 0 and 2, for the
                    320:  * high one just the lower two bits.
                    321:  */
                    322: static const char *bitop_c3[8] = {
                    323:        "zapnot", "mskql", "srl", "extql", "sll", "insql", "sra", 0
                    324: };
                    325: static const char *bitop_c2[8] = {
                    326:        "mskbl", "mskwl", "mskll", 0/*mskql*/, 0, "mskwh", "msklh", "mskqh"
                    327: };
                    328: static const char *bitop_c67ab[4][4] = {
                    329: /* a */        { 0, "extwh", "extlh", "extqh"},
                    330: /* b */        { "insbl", "inswl", "insll", 0 },
                    331: /* 6 */        { "extbl", "extwl", "extll", 0 },
                    332: /* 7 */        { 0, "inswh", "inslh", "insqh" },
                    333: };
                    334:
                    335: static __inline const char *bitop_name(int);
                    336: static __inline const char *
                    337: bitop_name(op)
                    338:        int op;
                    339: {
                    340:        static char unk[32];
                    341:        const char *name = NULL;
                    342:
                    343:        if ((op & 0x70) == 0x30)
                    344:                name = (op == op_zap) ? "zap" : bitop_c3[((op)&0xe)>>1];
                    345:        else if ((op & 0xf) == 0x02)
                    346:                name = bitop_c2[(op)>>4];
                    347:        else
                    348:                name =
                    349:                    bitop_c67ab[(((op)&1)|(((op)&0x4)>>1))][(((op)&0x30)>>4)];
                    350:
                    351:        if (name != NULL)
                    352:                return (name);
                    353:
                    354:        snprintf(unk, sizeof unk, "?bit 0x%x?", op);
                    355:        return (unk);
                    356: }
                    357:
                    358: /*
                    359:  * Only 5 entries in this one
                    360:  */
                    361: static const char *mul_opname[4] = {
                    362:        "mull", "mulq", "mull/v", "mulq/v"
                    363: };
                    364:
                    365: static __inline const char *mul_name(int);
                    366: static __inline const char *
                    367: mul_name(op)
                    368:        int op;
                    369: {
                    370:        static char unk[32];
                    371:        const char *name = NULL;
                    372:
                    373:        name = (op == op_umulh) ? "umulh" : mul_opname[((op)>>5)&3];
                    374:
                    375:        if (name != NULL)
                    376:                return (name);
                    377:
                    378:        snprintf(unk, sizeof unk, "?mul 0x%x?", op);
                    379:        return (unk);
                    380: }
                    381:
                    382: /*
                    383:  * These are few, the high nibble is usually enough to dispatch.
                    384:  * We single out the `f' case to halve the table size, as
                    385:  * well as the cases in which the high nibble isn't enough.
                    386:  */
                    387: static const char *special_opname[8] = {
                    388:        "trapb", 0, "mb", 0, "fetch", "fetch_m", "rpcc", "rc"
                    389: };
                    390:
                    391: static __inline const char *special_name(int);
                    392: static __inline const char *
                    393: special_name(op)
                    394:        int op;
                    395: {
                    396:        static char unk[32];
                    397:        const char *name;
                    398:
                    399:        switch (op) {
                    400:        case op_excb:           name = "excb";          break;
                    401:        case op_wmb:            name = "wmb";           break;
                    402:        case op_ecb:            name = "ecb";           break;
                    403:        case op_rs:             name = "rs";            break;
                    404:        case op_wh64:           name = "wh64";          break;
                    405:        default:
                    406:                name = special_opname[(op)>>13];
                    407:        }
                    408:
                    409:        if (name != NULL)
                    410:                return (name);
                    411:
                    412:        snprintf(unk, sizeof unk, "?special 0x%x?", op);
                    413:        return (unk);
                    414: }
                    415:
                    416: /*
                    417:  * This is trivial
                    418:  */
                    419: static const char *jump_opname[4] = {
                    420:        "jmp", "jsr", "ret", "jcr"
                    421: };
                    422: #define jump_name(ix)  jump_opname[ix]
                    423:
                    424: /*
                    425:  * For all but 4 of these, we can dispatch on the lower nibble of
                    426:  * the "function".
                    427:  */
                    428: static const char *intmisc_opname_3x[16] = {
                    429:        "ctpop", "perr", "ctlz", "cttz", "unpkbw", "unpkbl", "pkwb",
                    430:        "pklb", "minsb8", "minsw4", "minub8", "minuw4", "maxub8",
                    431:        "maxuw4", "maxsb8", "maxsw4",
                    432: };
                    433:
                    434: static __inline const char *intmisc_name(int);
                    435: static __inline const char *
                    436: intmisc_name(op)
                    437:        int op;
                    438: {
                    439:        static char unk[32];
                    440:
                    441:        if ((op & 0xf0) == 0x30)
                    442:                return (intmisc_opname_3x[op & 0x0f]);
                    443:
                    444:        switch (op) {
                    445:        case op_sextb: return ("sextb");
                    446:        case op_sextw: return ("sextw");
                    447:        case op_ftoit: return ("ftoit");
                    448:        case op_ftois: return ("ftois");
                    449:        }
                    450:
                    451:        snprintf(unk, sizeof unk, "?intmisc 0x%x?", op);
                    452:        return (unk);
                    453: }
                    454:
                    455: static const char *float_name(const struct tbl[], int, const char *type);
                    456:
                    457: static const char *
                    458: float_name(tbl, op, type)
                    459:        const struct tbl tbl[];
                    460:        int op;
                    461:        const char *type;
                    462: {
                    463:        static char unk[32];
                    464:        int i;
                    465:
                    466:        for (i = 0; tbl[i].name != NULL; i++) {
                    467:                if (tbl[i].code == op)
                    468:                        return (tbl[i].name);
                    469:        }
                    470:
                    471:        snprintf(unk, sizeof unk, "?%s 0x%x?", type, op);
                    472:        return (unk);
                    473: }
                    474:
                    475: #define vaxf_name(op)  float_name(vaxf_tbl, op, "vaxfl")
                    476: #define ieeef_name(op) float_name(ieeef_tbl, op, "ieeefl")
                    477: #define anyf_name(op)  float_name(anyf_tbl, op, "anyfl")
                    478:
                    479: static const struct tbl anyf_tbl[] = {
                    480:        { "cvtlq",      0x010},
                    481:        { "cpys",       0x020},
                    482:        { "cpysn",      0x021},
                    483:        { "cpyse",      0x022},
                    484:        { "mt_fpcr",    0x024},
                    485:        { "mf_fpcr",    0x025},
                    486:        { "fcmoveq",    0x02a},
                    487:        { "fcmovne",    0x02b},
                    488:        { "fcmovlt",    0x02c},
                    489:        { "fcmovge",    0x02d},
                    490:        { "fcmovle",    0x02e},
                    491:        { "fcmovgt",    0x02f},
                    492:        { "cvtql",      0x030},
                    493:        { "cvtql/v",    0x130},
                    494:        { "cvtql/sv",   0x330},
                    495:        { 0, 0},
                    496: };
                    497:
                    498: static const struct tbl ieeef_tbl[] = {
                    499:        { "adds/c",     0x000},
                    500:        { "subs/c",     0x001},
                    501:        { "muls/c",     0x002},
                    502:        { "divs/c",     0x003},
                    503:        { "addt/c",     0x020},
                    504:        { "subt/c",     0x021},
                    505:        { "mult/c",     0x022},
                    506:        { "divt/c",     0x023},
                    507:        { "cvtts/c",    0x02c},
                    508:        { "cvttq/c",    0x02f},
                    509:        { "cvtqs/c",    0x03c},
                    510:        { "cvtqt/c",    0x03e},
                    511:        { "adds/m",     0x040},
                    512:        { "subs/m",     0x041},
                    513:        { "muls/m",     0x042},
                    514:        { "divs/m",     0x043},
                    515:        { "addt/m",     0x060},
                    516:        { "subt/m",     0x061},
                    517:        { "mult/m",     0x062},
                    518:        { "divt/m",     0x063},
                    519:        { "cvtts/m",    0x06c},
                    520:        { "cvtqs/m",    0x07c},
                    521:        { "cvtqt/m",    0x07e},
                    522:        { "adds",       0x080},
                    523:        { "subs",       0x081},
                    524:        { "muls",       0x082},
                    525:        { "divs",       0x083},
                    526:        { "addt",       0x0a0},
                    527:        { "subt",       0x0a1},
                    528:        { "mult",       0x0a2},
                    529:        { "divt",       0x0a3},
                    530:        { "cmptun",     0x0a4},
                    531:        { "cmpteq",     0x0a5},
                    532:        { "cmptlt",     0x0a6},
                    533:        { "cmptle",     0x0a7},
                    534:        { "cvtts",      0x0ac},
                    535:        { "cvttq",      0x0af},
                    536:        { "cvtqs",      0x0bc},
                    537:        { "cvtqt",      0x0be},
                    538:        { "adds/d",     0x0c0},
                    539:        { "subs/d",     0x0c1},
                    540:        { "muls/d",     0x0c2},
                    541:        { "divs/d",     0x0c3},
                    542:        { "addt/d",     0x0e0},
                    543:        { "subt/d",     0x0e1},
                    544:        { "mult/d",     0x0e2},
                    545:        { "divt/d",     0x0e3},
                    546:        { "cvtts/d",    0x0ec},
                    547:        { "cvtqs/d",    0x0fc},
                    548:        { "cvtqt/d",    0x0fe},
                    549:        { "adds/uc",    0x100},
                    550:        { "subs/uc",    0x101},
                    551:        { "muls/uc",    0x102},
                    552:        { "divs/uc",    0x103},
                    553:        { "addt/uc",    0x120},
                    554:        { "subt/uc",    0x121},
                    555:        { "mult/uc",    0x122},
                    556:        { "divt/uc",    0x123},
                    557:        { "cvtts/uc",   0x12c},
                    558:        { "cvttq/vc",   0x12f},
                    559:        { "adds/um",    0x140},
                    560:        { "subs/um",    0x141},
                    561:        { "muls/um",    0x142},
                    562:        { "divs/um",    0x143},
                    563:        { "addt/um",    0x160},
                    564:        { "subt/um",    0x161},
                    565:        { "mult/um",    0x162},
                    566:        { "divt/um",    0x163},
                    567:        { "cvtts/um",   0x16c},
                    568:        { "adds/u",     0x180},
                    569:        { "subs/u",     0x181},
                    570:        { "muls/u",     0x182},
                    571:        { "divs/u",     0x183},
                    572:        { "addt/u",     0x1a0},
                    573:        { "subt/u",     0x1a1},
                    574:        { "mult/u",     0x1a2},
                    575:        { "divt/u",     0x1a3},
                    576:        { "cvtts/u",    0x1ac},
                    577:        { "cvttq/v",    0x1af},
                    578:        { "adds/ud",    0x1c0},
                    579:        { "subs/ud",    0x1c1},
                    580:        { "muls/ud",    0x1c2},
                    581:        { "divs/ud",    0x1c3},
                    582:        { "addt/ud",    0x1e0},
                    583:        { "subt/ud",    0x1e1},
                    584:        { "mult/ud",    0x1e2},
                    585:        { "divt/ud",    0x1e3},
                    586:        { "cvtts/ud",   0x1ec},
                    587:        { "adds/suc",   0x500},
                    588:        { "subs/suc",   0x501},
                    589:        { "muls/suc",   0x502},
                    590:        { "divs/suc",   0x503},
                    591:        { "addt/suc",   0x520},
                    592:        { "subt/suc",   0x521},
                    593:        { "mult/suc",   0x522},
                    594:        { "divt/suc",   0x523},
                    595:        { "cvtts/suc",  0x52c},
                    596:        { "cvttq/svc",  0x52f},
                    597:        { "adds/sum",   0x540},
                    598:        { "subs/sum",   0x541},
                    599:        { "muls/sum",   0x542},
                    600:        { "divs/sum",   0x543},
                    601:        { "addt/sum",   0x560},
                    602:        { "subt/sum",   0x561},
                    603:        { "mult/sum",   0x562},
                    604:        { "divt/sum",   0x563},
                    605:        { "cvtts/sum",  0x56c},
                    606:        { "adds/su",    0x580},
                    607:        { "subs/su",    0x581},
                    608:        { "muls/su",    0x582},
                    609:        { "divs/su",    0x583},
                    610:        { "addt/su",    0x5a0},
                    611:        { "subt/su",    0x5a1},
                    612:        { "mult/su",    0x5a2},
                    613:        { "divt/su",    0x5a3},
                    614:        { "cmptun/su",  0x5a4},
                    615:        { "cmpteq/su",  0x5a5},
                    616:        { "cmptlt/su",  0x5a6},
                    617:        { "cmptle/su",  0x5a7},
                    618:        { "cvtts/su",   0x5ac},
                    619:        { "cvttq/sv",   0x5af},
                    620:        { "adds/sud",   0x5c0},
                    621:        { "subs/sud",   0x5c1},
                    622:        { "muls/sud",   0x5c2},
                    623:        { "divs/sud",   0x5c3},
                    624:        { "addt/sud",   0x5e0},
                    625:        { "subt/sud",   0x5e1},
                    626:        { "mult/sud",   0x5e2},
                    627:        { "divt/sud",   0x5e3},
                    628:        { "cvtts/sud",  0x5ec},
                    629:        { "adds/suic",  0x700},
                    630:        { "subs/suic",  0x701},
                    631:        { "muls/suic",  0x702},
                    632:        { "divs/suic",  0x703},
                    633:        { "addt/suic",  0x720},
                    634:        { "subt/suic",  0x721},
                    635:        { "mult/suic",  0x722},
                    636:        { "divt/suic",  0x723},
                    637:        { "cvtts/suic", 0x72c},
                    638:        { "cvttq/svic", 0x72f},
                    639:        { "cvtqs/suic", 0x73c},
                    640:        { "cvtqt/suic", 0x73e},
                    641:        { "adds/suim",  0x740},
                    642:        { "subs/suim",  0x741},
                    643:        { "muls/suim",  0x742},
                    644:        { "divs/suim",  0x743},
                    645:        { "addt/suim",  0x760},
                    646:        { "subt/suim",  0x761},
                    647:        { "mult/suim",  0x762},
                    648:        { "divt/suim",  0x763},
                    649:        { "cvtts/suim", 0x76c},
                    650:        { "cvtqs/suim", 0x77c},
                    651:        { "cvtqt/suim", 0x77e},
                    652:        { "adds/sui",   0x780},
                    653:        { "subs/sui",   0x781},
                    654:        { "muls/sui",   0x782},
                    655:        { "divs/sui",   0x783},
                    656:        { "addt/sui",   0x7a0},
                    657:        { "subt/sui",   0x7a1},
                    658:        { "mult/sui",   0x7a2},
                    659:        { "divt/sui",   0x7a3},
                    660:        { "cvtts/sui",  0x7ac},
                    661:        { "cvttq/svi",  0x7af},
                    662:        { "cvtqs/sui",  0x7bc},
                    663:        { "cvtqt/sui",  0x7be},
                    664:        { "adds/suid",  0x7c0},
                    665:        { "subs/suid",  0x7c1},
                    666:        { "muls/suid",  0x7c2},
                    667:        { "divs/suid",  0x7c3},
                    668:        { "addt/suid",  0x7e0},
                    669:        { "subt/suid",  0x7e1},
                    670:        { "mult/suid",  0x7e2},
                    671:        { "divt/suid",  0x7e3},
                    672:        { "cvtts/suid", 0x7ec},
                    673:        { "cvtqs/suid", 0x7fc},
                    674:        { "cvtqt/suid", 0x7fe},
                    675:        { 0, 0}
                    676: };
                    677:
                    678: static const struct tbl vaxf_tbl[] = {
                    679:        { "addf/c",     0x000},
                    680:        { "subf/c",     0x001},
                    681:        { "mulf/c",     0x002},
                    682:        { "divf/c",     0x003},
                    683:        { "cvtdg/c",    0x01e},
                    684:        { "addg/c",     0x020},
                    685:        { "subg/c",     0x021},
                    686:        { "mulg/c",     0x022},
                    687:        { "divg/c",     0x023},
                    688:        { "cvtgf/c",    0x02c},
                    689:        { "cvtgd/c",    0x02d},
                    690:        { "cvtgq/c",    0x02f},
                    691:        { "cvtqf/c",    0x03c},
                    692:        { "cvtqg/c",    0x03e},
                    693:        { "addf",       0x080},
                    694:        { "subf",       0x081},
                    695:        { "mulf",       0x082},
                    696:        { "divf",       0x083},
                    697:        { "cvtdg",      0x09e},
                    698:        { "addg",       0x0a0},
                    699:        { "subg",       0x0a1},
                    700:        { "mulg",       0x0a2},
                    701:        { "divg",       0x0a3},
                    702:        { "cmpgeq",     0x0a5},
                    703:        { "cmpglt",     0x0a6},
                    704:        { "cmpgle",     0x0a7},
                    705:        { "cvtgf",      0x0ac},
                    706:        { "cvtgd",      0x0ad},
                    707:        { "cvtgq",      0x0af},
                    708:        { "cvtqf",      0x0bc},
                    709:        { "cvtqg",      0x0be},
                    710:        { "addf/uc",    0x100},
                    711:        { "subf/uc",    0x101},
                    712:        { "mulf/uc",    0x102},
                    713:        { "divf/uc",    0x103},
                    714:        { "cvtdg/uc",   0x11e},
                    715:        { "addg/uc",    0x120},
                    716:        { "subg/uc",    0x121},
                    717:        { "mulg/uc",    0x122},
                    718:        { "divg/uc",    0x123},
                    719:        { "cvtgf/uc",   0x12c},
                    720:        { "cvtgd/uc",   0x12d},
                    721:        { "cvtgq/vc",   0x12f},
                    722:        { "addf/u",     0x180},
                    723:        { "subf/u",     0x181},
                    724:        { "mulf/u",     0x182},
                    725:        { "divf/u",     0x183},
                    726:        { "cvtdg/u",    0x19e},
                    727:        { "addg/u",     0x1a0},
                    728:        { "subg/u",     0x1a1},
                    729:        { "mulg/u",     0x1a2},
                    730:        { "divg/u",     0x1a3},
                    731:        { "cvtgf/u",    0x1ac},
                    732:        { "cvtgd/u",    0x1ad},
                    733:        { "cvtgq/v",    0x1af},
                    734:        { "addf/sc",    0x400},
                    735:        { "subf/sc",    0x401},
                    736:        { "mulf/sc",    0x402},
                    737:        { "divf/sc",    0x403},
                    738:        { "cvtdg/sc",   0x41e},
                    739:        { "addg/sc",    0x420},
                    740:        { "subg/sc",    0x421},
                    741:        { "mulg/sc",    0x422},
                    742:        { "divg/sc",    0x423},
                    743:        { "cvtgf/sc",   0x42c},
                    744:        { "cvtgd/sc",   0x42d},
                    745:        { "cvtgq/sc",   0x42f},
                    746:        { "cvtqf/sc",   0x43c},
                    747:        { "cvtqg/sc",   0x43e},
                    748:        { "addf/s",     0x480},
                    749:        { "subf/s",     0x481},
                    750:        { "mulf/s",     0x482},
                    751:        { "divf/s",     0x483},
                    752:        { "cvtdg/s",    0x49e},
                    753:        { "addg/s",     0x4a0},
                    754:        { "subg/s",     0x4a1},
                    755:        { "mulg/s",     0x4a2},
                    756:        { "divg/s",     0x4a3},
                    757:        { "cmpgeq/s",   0x4a5},
                    758:        { "cmpglt/s",   0x4a6},
                    759:        { "cmpgle/s",   0x4a7},
                    760:        { "cvtgf/s",    0x4ac},
                    761:        { "cvtgd/s",    0x4ad},
                    762:        { "cvtgq/s",    0x4af},
                    763:        { "cvtqf/s",    0x4bc},
                    764:        { "cvtqg/s",    0x4be},
                    765:        { "addf/suc",   0x500},
                    766:        { "subf/suc",   0x501},
                    767:        { "mulf/suc",   0x502},
                    768:        { "divf/suc",   0x503},
                    769:        { "cvtdg/suc",  0x51e},
                    770:        { "addg/suc",   0x520},
                    771:        { "subg/suc",   0x521},
                    772:        { "mulg/suc",   0x522},
                    773:        { "divg/suc",   0x523},
                    774:        { "cvtgf/suc",  0x52c},
                    775:        { "cvtgd/suc",  0x52d},
                    776:        { "cvtgq/svc",  0x52f},
                    777:        { "addf/su",    0x580},
                    778:        { "subf/su",    0x581},
                    779:        { "mulf/su",    0x582},
                    780:        { "divf/su",    0x583},
                    781:        { "cvtdg/su",   0x59e},
                    782:        { "addg/su",    0x5a0},
                    783:        { "subg/su",    0x5a1},
                    784:        { "mulg/su",    0x5a2},
                    785:        { "divg/su",    0x5a3},
                    786:        { "cvtgf/su",   0x5ac},
                    787:        { "cvtgd/su",   0x5ad},
                    788:        { "cvtgq/sv",   0x5af},
                    789:        { 0, 0}
                    790: };
                    791:
                    792: /*
                    793:  * General purpose registers
                    794:  */
                    795: static const char *name_of_register[32] = {
                    796:        "v0",   "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",
                    797:        "t7",   "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",
                    798:        "a0",   "a1",   "a2",   "a3",   "a4",   "a5",   "t8",   "t9",
                    799:        "t10",  "t11",  "ra",   "pv",   "at",   "gp",   "sp",   "zero"
                    800: };
                    801:
                    802: static int regcount;           /* how many regs used in this inst */
                    803: static int regnum[3];          /* which regs used in this inst */
                    804:
                    805: static const char *register_name(int);
                    806:
                    807: static const char *
                    808: register_name (ireg)
                    809:        int ireg;
                    810: {
                    811:        int     i;
                    812:
                    813:        for (i = 0; i < regcount; i++)
                    814:                if (regnum[i] == ireg)
                    815:                        break;
                    816:        if (i >= regcount)
                    817:                regnum[regcount++] = ireg;
                    818:        return (name_of_register[ireg]);
                    819: }
                    820:
                    821: /*
                    822:  * Disassemble instruction at 'loc'.  'altfmt' specifies an
                    823:  * (optional) alternate format.  Return address of start of
                    824:  * next instruction.
                    825:  */
                    826: int    alpha_print_instruction(db_addr_t, alpha_instruction, boolean_t);
                    827:
                    828: db_addr_t
                    829: db_disasm(loc, altfmt)
                    830:        db_addr_t       loc;
                    831:        boolean_t       altfmt;
                    832: {
                    833:        alpha_instruction inst;
                    834:
                    835:        inst.bits = db_get_value(loc, 4, 0);
                    836:
                    837:        loc += alpha_print_instruction(loc, inst, altfmt);
                    838:        return (loc);
                    839: }
                    840:
                    841: int
                    842: alpha_print_instruction(iadr, i, showregs)
                    843:        db_addr_t       iadr;
                    844:        alpha_instruction i;
                    845:        boolean_t       showregs;
                    846: {
                    847:        const char      *opcode;
                    848:        int             ireg;
                    849:        long            signed_immediate;
                    850:        boolean_t       fstore;
                    851:        pal_instruction p;
                    852:
                    853:        regcount = 0;
                    854:        fstore = FALSE;
                    855:        opcode = op_name[i.mem_format.opcode];
                    856:
                    857:        /*
                    858:         *      Dispatch directly on the opcode, save code
                    859:         *      duplication sometimes via "harmless gotos".
                    860:         */
                    861:        switch (i.mem_format.opcode) {
                    862:        case op_pal:
                    863:                /* "call_pal" is a long string; just use a space. */
                    864:                db_printf("%s %s", opcode, pal_opname(i.pal_format.function));
                    865:                break;
                    866:        case op_lda:
                    867:        case op_ldah:
                    868:        case op_ldbu:
                    869:        case op_ldq_u:
                    870:        case op_ldwu:
                    871:        case op_stw:
                    872:        case op_stb:
                    873:        case op_stq_u:
                    874:                /*
                    875:                 * These loadstores are here to make compiling the
                    876:                 * switch a bit easier.  Could embellish the output
                    877:                 * someday, too.
                    878:                 */
                    879:                goto loadstore;
                    880:                break;
                    881:        case op_arit:
                    882:                /*
                    883:                 * For this and the following three groups we
                    884:                 * just need different opcode strings
                    885:                 */
                    886:                opcode = arit_name(i.operate_lit_format.function);
                    887:                goto operate;
                    888:                break;
                    889:        case op_logical:
                    890:                opcode = logical_name(i.operate_lit_format.function);
                    891:                goto operate;
                    892:                break;
                    893:        case op_bit:
                    894:                opcode = bitop_name(i.operate_lit_format.function);
                    895:                goto operate;
                    896:                break;
                    897:        case op_mul:
                    898:                opcode = mul_name(i.operate_lit_format.function);
                    899: operate:
                    900:                /*
                    901:                 * Nice and uniform, just check for literals
                    902:                 */
                    903:                db_printf("%s\t%s,", opcode,
                    904:                    register_name(i.operate_lit_format.ra));
                    905:                if (i.operate_lit_format.one)
                    906:                        db_printf("#0x%x", i.operate_lit_format.literal);
                    907:                else
                    908:                        db_printf("%s", register_name(i.operate_reg_format.rb));
                    909:                db_printf(",%s", register_name(i.operate_lit_format.rc));
                    910:                break;
                    911:        case op_vax_float:
                    912:                /*
                    913:                 * The three floating point groups are even simpler
                    914:                 */
                    915:                opcode = vaxf_name(i.float_format.function);
                    916:                goto foperate;
                    917:                break;
                    918:        case op_ieee_float:
                    919:                opcode = ieeef_name(i.float_format.function);
                    920:                goto foperate;
                    921:                break;
                    922:        case op_any_float:
                    923:                opcode = anyf_name(i.float_format.function);
                    924: foperate:
                    925:                db_printf("%s\tf%d,f%d,f%d", opcode,
                    926:                        i.float_format.fa,
                    927:                        i.float_format.fb,
                    928:                        i.float_format.fc);
                    929:                break;
                    930:        case op_special:
                    931:                /*
                    932:                 * Miscellaneous.
                    933:                 */
                    934:                {
                    935:                        register unsigned int code;
                    936:
                    937:                        code = (i.mem_format.displacement)&0xffff;
                    938:                        opcode = special_name(code);
                    939:
                    940:                        switch (code) {
                    941:                        case op_ecb:
                    942:                                db_printf("%s\t(%s)", opcode,
                    943:                                        register_name(i.mem_format.rb));
                    944:                                break;
                    945:                        case op_fetch:
                    946:                        case op_fetch_m:
                    947:                                db_printf("%s\t0(%s)", opcode,
                    948:                                        register_name(i.mem_format.rb));
                    949:                                break;
                    950:                        case op_rpcc:
                    951:                        case op_rc:
                    952:                        case op_rs:
                    953:                                db_printf("%s\t%s", opcode,
                    954:                                        register_name(i.mem_format.ra));
                    955:                                break;
                    956:                        default:
                    957:                                db_printf("%s", opcode);
                    958:                        break;
                    959:                        }
                    960:                }
                    961:                break;
                    962:        case op_j:
                    963:                /*
                    964:                 * Jump instructions really are of two sorts,
                    965:                 * depending on the use of the hint info.
                    966:                 */
                    967:                opcode = jump_name(i.jump_format.action);
                    968:                switch (i.jump_format.action) {
                    969:                case op_jmp:
                    970:                case op_jsr:
                    971:                        db_printf("%s\t%s,(%s),", opcode,
                    972:                                register_name(i.jump_format.ra),
                    973:                                register_name(i.jump_format.rb));
                    974:                        signed_immediate = i.jump_format.hint;
                    975:                        goto branch_displacement;
                    976:                        break;
                    977:                case op_ret:
                    978:                case op_jcr:
                    979:                        db_printf("%s\t%s,(%s)", opcode,
                    980:                                register_name(i.jump_format.ra),
                    981:                                register_name(i.jump_format.rb));
                    982:                        break;
                    983:                }
                    984:                break;
                    985:        case op_intmisc:
                    986:                /*
                    987:                 * These are just in "operate" format.
                    988:                 */
                    989:                opcode = intmisc_name(i.operate_lit_format.function);
                    990:                goto operate;
                    991:                break;
                    992:                        /* HW instructions, possibly chip-specific XXXX */
                    993:        case op_pal19:  /* "hw_mfpr" */
                    994:        case op_pal1d:  /* "hw_mtpr" */
                    995:                p.bits = i.bits;
                    996:                db_printf("\t%s%s\t%s, %d", opcode,
                    997:                        mXpr_name[p.mXpr_format.regset],
                    998:                        register_name(p.mXpr_format.rd),
                    999:                        p.mXpr_format.index);
                   1000:                break;
                   1001:        case op_pal1b:  /* "hw_ld" */
                   1002:        case op_pal1f:  /* "hw_st" */
                   1003:                p.bits = i.bits;
                   1004:                db_printf("\t%s%c%s\t%s,", opcode,
                   1005:                        (p.mem_format.qw) ? 'q' : 'l',
                   1006:                        hwlds_name[p.mem_format.qualif],
                   1007:                        register_name(p.mem_format.rd));
                   1008:                signed_immediate = (long)p.mem_format.displacement;
                   1009:                goto loadstore_address;
                   1010:
                   1011:        case op_pal1e:  /* "hw_rei" */
                   1012:                db_printf("\t%s", opcode);
                   1013:                break;
                   1014:
                   1015:        case op_ldf:
                   1016:        case op_ldg:
                   1017:        case op_lds:
                   1018:        case op_ldt:
                   1019:        case op_stf:
                   1020:        case op_stg:
                   1021:        case op_sts:
                   1022:        case op_stt:
                   1023:                fstore = TRUE;
                   1024:                /* FALLTHROUGH */
                   1025:        case op_ldl:
                   1026:        case op_ldq:
                   1027:        case op_ldl_l:
                   1028:        case op_ldq_l:
                   1029:        case op_stl:
                   1030:        case op_stq:
                   1031:        case op_stl_c:
                   1032:        case op_stq_c:
                   1033:                /*
                   1034:                 * Memory operations, including floats
                   1035:                 */
                   1036: loadstore:
                   1037:                if (fstore)
                   1038:                    db_printf("%s\tf%d,", opcode, i.mem_format.ra);
                   1039:                else
                   1040:                    db_printf("%s\t%s,", opcode,
                   1041:                        register_name(i.mem_format.ra));
                   1042:                signed_immediate = (long)i.mem_format.displacement;
                   1043: loadstore_address:
                   1044:                db_printf("%lz(%s)", signed_immediate,
                   1045:                        register_name(i.mem_format.rb));
                   1046:                /*
                   1047:                 * For convenience, do the address computation
                   1048:                 */
                   1049:                if (showregs) {
                   1050:                        if (i.mem_format.opcode == op_ldah)
                   1051:                                signed_immediate <<= 16;
                   1052:                        db_printf(" <0x%lx>", signed_immediate +
                   1053:                            db_register_value(DDB_REGS, i.mem_format.rb));
                   1054:                }
                   1055:                break;
                   1056:        case op_br:
                   1057:        case op_fbeq:
                   1058:        case op_fblt:
                   1059:        case op_fble:
                   1060:        case op_bsr:
                   1061:        case op_fbne:
                   1062:        case op_fbge:
                   1063:        case op_fbgt:
                   1064:        case op_blbc:
                   1065:        case op_beq:
                   1066:        case op_blt:
                   1067:        case op_ble:
                   1068:        case op_blbs:
                   1069:        case op_bne:
                   1070:        case op_bge:
                   1071:        case op_bgt:
                   1072:                /*
                   1073:                 * We want to know where we are branching to
                   1074:                 */
                   1075:                signed_immediate = (long)i.branch_format.displacement;
                   1076:                db_printf("%s\t%s,", opcode,
                   1077:                          register_name(i.branch_format.ra));
                   1078: branch_displacement:
                   1079:                db_printsym(iadr + sizeof(alpha_instruction) +
                   1080:                    (signed_immediate << 2), DB_STGY_PROC, db_printf);
                   1081:                break;
                   1082:        default:
                   1083:                /*
                   1084:                 * Shouldn't happen
                   1085:                 */
                   1086:                db_printf("? 0x%x ?", i.bits);
                   1087:        }
                   1088:
                   1089:        /*
                   1090:         *      Print out the registers used in this instruction
                   1091:         */
                   1092:        if (showregs && regcount > 0) {
                   1093:                db_printf("\t<");
                   1094:                for (ireg = 0; ireg < regcount; ireg++) {
                   1095:                        if (ireg != 0)
                   1096:                                db_printf(",");
                   1097:                        db_printf("%s=0x%lx",
                   1098:                            name_of_register[regnum[ireg]],
                   1099:                            db_register_value(DDB_REGS, regnum[ireg]));
                   1100:                }
                   1101:                db_printf(">");
                   1102:        }
                   1103:        db_printf("\n");
                   1104:        return (sizeof(alpha_instruction));
                   1105: }

CVSweb