Annotation of previous/src/dimension/i860dis.cpp, revision 1.1.1.1

1.1       root        1: /***************************************************************************
                      2: 
                      3:     i860dis.c
                      4: 
                      5:     Disassembler for the Intel i860 emulator.
                      6: 
                      7:     Copyright (C) 1995-present Jason Eckhardt ([email protected])
                      8:     Released for general non-commercial use under the MAME license
                      9:     with the additional requirement that you are free to use and
                     10:     redistribute this code in modified or unmodified form, provided
                     11:     you list me in the credits.
                     12:     Visit http://mamedev.org for licensing and usage restrictions.
                     13: 
                     14:     Changes for previous/NeXTdimension by Simon Schubiger (SC)
                     15: 
                     16: ***************************************************************************/
                     17: 
                     18: #include <string.h>
                     19: #include <stdio.h>
                     20: #include "i860.hpp"
                     21: 
                     22: /* Macros for accessing register fields in instruction word.  */
                     23: #define get_isrc1(bits) (((bits) >> 11) & 0x1f)
                     24: #define get_isrc2(bits) (((bits) >> 21) & 0x1f)
                     25: #define get_idest(bits) (((bits) >> 16) & 0x1f)
                     26: #define get_fsrc1(bits) (((bits) >> 11) & 0x1f)
                     27: #define get_fsrc2(bits) (((bits) >> 21) & 0x1f)
                     28: #define get_fdest(bits) (((bits) >> 16) & 0x1f)
                     29: #define get_creg(bits)  (((bits) >> 21) & 0x7)
                     30: 
                     31: /* Macros for accessing immediate fields.  */
                     32: /* 16-bit immediate.  */
                     33: #define get_imm16(insn) ((insn) & 0xffff)
                     34: 
                     35: 
                     36: /* Control register names.  */
                     37: static const char *const cr2str[] =
                     38:        {"fir", "psr", "dirbase", "db", "fsr", "epsr", "!", "!"};
                     39: 
                     40: 
                     41: /* Sign extend N-bit number.  */
                     42: static INT32 sign_ext(UINT32 x, int n)
                     43: {
                     44:        INT32 t;
                     45:        t = x >> (n - 1);
                     46:        t = ((-t) << n) | x;
                     47:        return t;
                     48: }
                     49: 
                     50: 
                     51: /* Basic integer 3-address register format:
                     52:  *   mnemonic %rs1,%rs2,%rd  */
                     53: static void int_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                     54: {
                     55:        /* Possibly prefix shrd with 'd.' */
                     56:        if (((insn & 0xfc000000) == 0xb0000000) && (insn & 0x200))
                     57:                sprintf(buf, "d.%s\t%%r%d,%%r%d,%%r%d", mnemonic,
                     58:                        get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
                     59:        else
                     60:                sprintf(buf, "  %s\t%%r%d,%%r%d,%%r%d", mnemonic,
                     61:                        get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
                     62: }
                     63: 
                     64: 
                     65: /* Basic integer 3-address imm16 format:
                     66:  *   mnemonic #imm16,%rs2,%rd  */
                     67: static void int_i2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                     68: {
                     69:        /* Sign extend the 16-bit immediate.
                     70:           Print as hex for the bitwise operations.  */
                     71:        int upper_6bits = (insn >> 26) & 0x3f;
                     72:        if (upper_6bits >= 0x30 && upper_6bits <= 0x3f)
                     73:                sprintf(buf, "  %s\t0x%04x,%%r%d,%%r%d", mnemonic,
                     74:                        (UINT32)(get_imm16 (insn)), get_isrc2 (insn), get_idest (insn));
                     75:        else
                     76:                sprintf(buf, "  %s\t%d,%%r%d,%%r%d", mnemonic,
                     77:                        sign_ext(get_imm16 (insn), 16), get_isrc2 (insn), get_idest (insn));
                     78: }
                     79: 
                     80: 
                     81: /* Integer (mixed) 2-address  isrc1ni,fdest.  */
                     82: static void int_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                     83: {
                     84:        sprintf(buf, "  %s\t%%r%d,%%f%d", mnemonic, get_isrc1 (insn), get_fdest (insn));
                     85: }
                     86: 
                     87: 
                     88: /* Integer (mixed) 2-address  csrc2,idest.  */
                     89: static void int_cd(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                     90: {
                     91:        sprintf(buf, "  %s\t%%%s,%%r%d", mnemonic, cr2str[get_creg (insn)], get_idest (insn));
                     92: }
                     93: 
                     94: 
                     95: /* Integer (mixed) 2-address  isrc1,csrc2.  */
                     96: static void int_1c(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                     97: {
                     98:        sprintf(buf, "  %s\t%%r%d,%%%s", mnemonic, get_isrc1(insn), cr2str[get_creg (insn)]);
                     99: }
                    100: 
                    101: 
                    102: /* Integer 1-address register format:
                    103:  *   mnemonic %rs1  */
                    104: static void int_1(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    105: {
                    106:        sprintf(buf, "  %s\t%%r%d", mnemonic, get_isrc1 (insn));
                    107: }
                    108: 
                    109: 
                    110: /* Integer no-address register format:
                    111:  *   mnemonic  */
                    112: static void int_0(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    113: {
                    114:        sprintf(buf, "  %s", mnemonic);
                    115: }
                    116: 
                    117: 
                    118: /* Basic floating-point 3-address register format:
                    119:  *   mnemonic %fs1,%fs2,%fd  */
                    120: static void flop_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    121: {
                    122:        const char *const suffix[4] = { "ss", "sd", "ds", "dd" };
                    123:        const char *prefix_d, *prefix_p;
                    124:        prefix_p = (insn & 0x400) ? "p" : "";
                    125:        prefix_d = (insn & 0x200) ? "d." : "  ";
                    126: 
                    127:        /* Special case: pf[m]am and pf[m]sm families are always pipelined, so they
                    128:           do not have a prefix.  Also, for the pfmam and pfmsm families, replace
                    129:           any 'a' in the mnemonic with 'm' and prepend an 'm'.  */
                    130:        if ((insn & 0x7f) < 0x20)
                    131:        {
                    132:                int is_pfam = insn & 0x400;
                    133:                if (!is_pfam)
                    134:                {
                    135:                        char newname[256];
                    136:                        char *op = mnemonic;
                    137:                        char *np = newname + 1;
                    138:                        newname[0] = 'm';
                    139:                        while (*op)
                    140:                        {
                    141:                                if (*op == 'a')
                    142:                                        *np = 'm';
                    143:                                else
                    144:                                        *np = *op;
                    145:                                np++;
                    146:                                op++;
                    147:                        }
                    148:                        *np = 0;
                    149:                        mnemonic = newname;
                    150:                }
                    151:                prefix_p = "";
                    152:        }
                    153: 
                    154:        /* Special case: pfgt/pfle-- R-bit distinguishes the two.  */
                    155:        if ((insn & 0x7f) == 0x34)
                    156:        {
                    157:                const char *const mn[2] = { "fgt.", "fle." };
                    158:                int r = (insn & 0x080) >> 7;
                    159:                int s = (insn & 0x100) ? 3 : 0;
                    160:                sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mn[r],
                    161:                        suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn));
                    162:        }
                    163:        else
                    164:        {
                    165:                int s = (insn & 0x180) >> 7;
                    166:                sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mnemonic,
                    167:                        suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn));
                    168:        }
                    169: }
                    170: 
                    171: 
                    172: /* Floating-point 2-address register format:
                    173:  *   mnemonic %fs1,%fd  */
                    174: static void flop_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    175: {
                    176:        const char *const suffix[4] = { "ss", "sd", "ds", "dd" };
                    177:        const char *prefix_d, *prefix_p;
                    178:        int s = (insn & 0x180) >> 7;
                    179:        prefix_p = (insn & 0x400) ? "p" : "";
                    180:        prefix_d = (insn & 0x200) ? "d." : "  ";
                    181:        sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d", prefix_d, prefix_p, mnemonic,
                    182:                suffix[s], get_fsrc1 (insn), get_fdest (insn));
                    183: }
                    184: 
                    185: 
                    186: /* Floating-point 2-address register format:
                    187:  *   mnemonic %fs2,%fd  */
                    188: static void flop_2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    189: {
                    190:        const char *const suffix[4] = { "ss", "sd", "ds", "dd" };
                    191:        const char *prefix_d;
                    192:        int s = (insn & 0x180) >> 7;
                    193:        prefix_d = (insn & 0x200) ? "d." : "  ";
                    194:        sprintf(buf, "%s%s%s\t%%f%d,%%f%d", prefix_d, mnemonic, suffix[s],
                    195:                get_fsrc2 (insn), get_fdest (insn));
                    196: }
                    197: 
                    198: 
                    199: /* Floating-point (mixed) 2-address register format:
                    200:  *  fxfr fsrc1,idest.  */
                    201: static void flop_fxfr(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    202: {
                    203:        const char *prefix_d = (insn & 0x200) ? "d." : "  ";
                    204:        sprintf(buf, "%s%s\t%%f%d,%%r%d", prefix_d, mnemonic, get_fsrc1 (insn),
                    205:                get_idest (insn));
                    206: }
                    207: 
                    208: 
                    209: /* Branch with reg,reg,sbroff format:
                    210:  *   mnemonic %rs1,%rs2,sbroff  */
                    211: static void int_12S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    212: {
                    213:        INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
                    214:        INT32 rel = (INT32)pc + (sbroff << 2) + 4;
                    215: 
                    216:        sprintf(buf, "  %s\t%%r%d,%%r%d,0x%08x", mnemonic, get_isrc1 (insn),
                    217:                get_isrc2 (insn), (UINT32)rel);
                    218: }
                    219: 
                    220: 
                    221: /* Branch with #const5,reg,sbroff format:
                    222:  *   mnemonic #const5,%rs2,sbroff  */
                    223: static void int_i2S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    224: {
                    225:        INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
                    226:        INT32 rel = (INT32)pc + (sbroff << 2) + 4;
                    227: 
                    228:        sprintf(buf, "  %s\t%d,%%r%d,0x%08x", mnemonic, ((insn >> 11) & 0x1f),
                    229:                get_isrc2 (insn), (UINT32)rel);
                    230: }
                    231: 
                    232: 
                    233: /* Branch with lbroff format:
                    234:  *   mnemonic lbroff  */
                    235: static void int_L(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    236: {
                    237:        INT32 lbroff =  sign_ext ((insn & 0x03ffffff), 26);
                    238:        INT32 rel = (INT32)pc + (lbroff << 2) + 4;
                    239: 
                    240:        sprintf(buf, "  %s\t0x%08x", mnemonic, (UINT32)rel);
                    241: }
                    242: 
                    243: 
                    244: /* Integer load.
                    245:  *  ld.{b,s,l} isrc1(isrc2),idest
                    246:  *  ld.{b,s,l} #const(isrc2),idest  */
                    247: static void int_ldx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    248: {
                    249:        /* Operand size, in bytes.  */
                    250:        int sizes[4] = { 1, 1, 2, 4 };
                    251:        const char *const suffix[4] = { "b", "b", "s", "l" };
                    252:        UINT32 idx = 0;
                    253: 
                    254:        /* Bits 28 and 0 determine the operand size.  */
                    255:        idx = ((insn >> 27) & 2) | (insn & 1);
                    256: 
                    257:        /* Bit 26 determines the addressing mode (reg+reg or disp+reg).  */
                    258:        if (insn & 0x04000000)
                    259:        {
                    260:                /* Chop off lower bits of displacement.  */
                    261:                INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
                    262:                int size = sizes[idx];
                    263:                immsrc1 &= ~(size - 1);
                    264:                sprintf(buf, "  %s%s\t%d(%%r%d),%%r%d", mnemonic, suffix[idx],
                    265:                        immsrc1, get_isrc2 (insn), get_idest (insn));
                    266:        }
                    267:        else
                    268:                sprintf(buf, "  %s%s\t%%r%d(%%r%d),%%r%d", mnemonic, suffix[idx],
                    269:                        get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
                    270: }
                    271: 
                    272: 
                    273: /* Integer store: st.b isrc1ni,#const(isrc2)  */
                    274: static void int_stx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    275: {
                    276:        /* Operand size, in bytes.  */
                    277:        int sizes[4] = { 1, 1, 2, 4 };
                    278:        const char *const suffix[4] = { "b", "b", "s", "l" };
                    279:        int idx = 0;
                    280:        int size;
                    281:        INT32 immsrc = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
                    282: 
                    283:        /* Bits 28 and 0 determine the operand size.  */
                    284:        idx = ((insn >> 27) & 2) | (insn & 1);
                    285: 
                    286:        /* Chop off lower bits of displacement.  */
                    287:        size = sizes[idx];
                    288:        immsrc &= ~(size - 1);
                    289:        sprintf(buf, "  %s%s\t%%r%d,%d(%%r%d)", mnemonic, suffix[idx],
                    290:                get_isrc1 (insn), immsrc, get_isrc2 (insn));
                    291: }
                    292: 
                    293: 
                    294: /* Disassemble:
                    295:  *  "[p]fld.y isrc1(isrc2),fdest", "[p]fld.y isrc1(isrc2)++,idest",
                    296:  *  "[p]fld.y #const(isrc2),fdest" or "[p]fld.y #const(isrc2)++,idest".
                    297:  *  "fst.y fdest,isrc1(isrc2)", "fst.y fdest,isrc1(isrc2)++",
                    298:  *  "fst.y fdest,#const(isrc2)" or "fst.y fdest,#const(isrc2)++"
                    299:  *  Where y = {l,d,q}.  Note, there is no pfld.q, though.  */
                    300: static void int_fldst(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    301: {
                    302:        INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
                    303:        /* Operand size, in bytes.  */
                    304:        int sizes[4] = { 8, 4, 16, 4 };
                    305:        const char *const suffix[4] = { "d", "l", "q", "l" };
                    306:        int idx = 0;
                    307:        int size = 0;
                    308:        int auto_inc = (insn & 1);
                    309:        const char *const auto_suff[2] = { "", "++" };
                    310:        int piped = (insn & 0x40000000) >> 30;
                    311:        const char *const piped_suff[2] = { "", "p" };
                    312:        int upper_6bits = (insn >> 26) & 0x3f;
                    313:        int is_load = (upper_6bits == 8 || upper_6bits == 9 || upper_6bits == 24
                    314:                                        || upper_6bits == 25);
                    315: 
                    316:        /* Bits 2 and 1 determine the operand size.  */
                    317:        idx = ((insn >> 1) & 3);
                    318:        size = sizes[idx];
                    319: 
                    320:        /* There is no pipelined load quad on XR.  */
                    321:        if (piped && size == 16)
                    322:        {
                    323:                sprintf (buf, ".long\t%#08x; *", insn);
                    324:                return;
                    325:        }
                    326: 
                    327:        /* There is only a 64-bit pixel store.  */
                    328:        if ((upper_6bits == 15) && size != 8)
                    329:        {
                    330:                sprintf (buf, ".long\t%#08x", insn);
                    331:                return;
                    332:        }
                    333: 
                    334:        /* Bit 26 determines the addressing mode (reg+reg or disp+reg).  */
                    335:        if (insn & 0x04000000)
                    336:        {
                    337:                /* Chop off lower bits of displacement.  */
                    338:                immsrc1 &= ~(size - 1);
                    339:                if (is_load)
                    340:                        sprintf(buf, "  %s%s%s\t%d(%%r%d)%s,%%f%d", piped_suff[piped], mnemonic,
                    341:                                suffix[idx], immsrc1, get_isrc2 (insn), auto_suff[auto_inc],
                    342:                                get_fdest (insn));
                    343:                else
                    344:                        sprintf(buf, "  %s%s\t%%f%d,%d(%%r%d)%s", mnemonic, suffix[idx],
                    345:                                get_fdest (insn), immsrc1, get_isrc2 (insn), auto_suff[auto_inc]);
                    346:        }
                    347:        else
                    348:        {
                    349:                if (is_load)
                    350:                        sprintf(buf, "  %s%s%s\t%%r%d(%%r%d)%s,%%f%d", piped_suff[piped],
                    351:                                mnemonic, suffix[idx], get_isrc1 (insn), get_isrc2 (insn),
                    352:                                auto_suff[auto_inc], get_fdest (insn));
                    353:                else
                    354:                        sprintf(buf, "  %s%s\t%%f%d,%%r%d(%%r%d)%s", mnemonic, suffix[idx],
                    355:                                get_fdest (insn), get_isrc1 (insn), get_isrc2 (insn),
                    356:                                auto_suff[auto_inc]);
                    357:        }
                    358: }
                    359: 
                    360: 
                    361: /* flush #const(isrc2)[++].  */
                    362: static void int_flush(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
                    363: {
                    364:        const char *const auto_suff[2] = { "", "++" };
                    365:        INT32 immsrc = sign_ext (get_imm16 (insn), 16);
                    366:        immsrc &= ~(16-1);
                    367:        sprintf(buf, "  %s\t%d(%%r%d)%s", mnemonic, immsrc, get_isrc2 (insn),
                    368:                auto_suff[(insn & 1)]);
                    369: }
                    370: 
                    371: 
                    372: /* Flags for the decode table.  */
                    373: enum
                    374: {
                    375:        DEC_MORE    = 1,    /* More decoding necessary.  */
                    376:        DEC_DECODED = 2     /* Fully decoded, go.  */
                    377: };
                    378: 
                    379: 
                    380: struct decode_tbl_t
                    381: {
                    382:        /* Disassembly function for this opcode.
                    383:           Call with buffer, mnemonic, pc, insn.  */
                    384:        void (*insn_dis)(char *, char *, UINT32, UINT32);
                    385: 
                    386:        /* Flags for this opcode.  */
                    387:        char flags;
                    388: 
                    389:        /* Mnemonic of this opcode (sometimes partial when more decode is
                    390:           done in disassembly routines-- e.g., loads and stores).  */
                    391:        const char *mnemonic;
                    392: };
                    393: 
                    394: 
                    395: /* First-level decode table (i.e., for the 6 primary opcode bits).  */
                    396: static const decode_tbl_t decode_tbl[64] =
                    397: {
                    398:        /* A slight bit of decoding for loads and stores is done in the
                    399:           execution routines (operand size and addressing mode), which
                    400:           is why their respective entries are identical.  */
                    401:        { int_ldx,   DEC_DECODED, "ld."        }, /* ld.b isrc1(isrc2),idest.  */
                    402:        { int_ldx,   DEC_DECODED, "ld."        }, /* ld.b #const(isrc2),idest.  */
                    403:        { int_1d,    DEC_DECODED, "ixfr"       }, /* ixfr isrc1ni,fdest.        */
                    404:        { int_stx,   DEC_DECODED, "st."        }, /* st.b isrc1ni,#const(isrc2).  */
                    405:        { int_ldx,   DEC_DECODED, "ld."        }, /* ld.{s,l} isrc1(isrc2),idest.  */
                    406:        { int_ldx,   DEC_DECODED, "ld."        }, /* ld.{s,l} #const(isrc2),idest.  */
                    407:        { 0,         0           , 0           },
                    408:        { int_stx,   DEC_DECODED, "st."        }, /* st.{s,l} isrc1ni,#const(isrc2),idest.*/
                    409:        { int_fldst, DEC_DECODED, "fld."       }, /* fld.{l,d,q} isrc1(isrc2)[++],fdest.  */
                    410:        { int_fldst, DEC_DECODED, "fld."       }, /* fld.{l,d,q} #const(isrc2)[++],fdest. */
                    411:        { int_fldst, DEC_DECODED, "fst."       }, /* fst.{l,d,q} fdest,isrc1(isrc2)[++]   */
                    412:        { int_fldst, DEC_DECODED, "fst."       }, /* fst.{l,d,q} fdest,#const(isrc2)[++]  */
                    413:        { int_cd,    DEC_DECODED, "ld.c"       }, /* ld.c csrc2,idest.                    */
                    414:        { int_flush, DEC_DECODED, "flush"      }, /* flush #const(isrc2) (or autoinc).    */
                    415:        { int_1c,    DEC_DECODED, "st.c"       }, /* st.c isrc1,csrc2.                    */
                    416:        { int_fldst, DEC_DECODED, "pstd."      }, /* pst.d fdest,#const(isrc2)[++].       */
                    417:        { int_1,     DEC_DECODED, "bri"        }, /* bri isrc1ni.                         */
                    418:        { int_12d,   DEC_DECODED, "trap"       }, /* trap isrc1ni,isrc2,idest.            */
                    419:        { 0,         DEC_MORE,    0            }, /* FP ESCAPE FORMAT, more decode.       */
                    420:        { 0,         DEC_MORE,    0            }, /* CORE ESCAPE FORMAT, more decode.     */
                    421:        { int_12S,   DEC_DECODED, "btne"       }, /* btne isrc1,isrc2,sbroff.             */
                    422:        { int_i2S,   DEC_DECODED, "btne"       }, /* btne #const,isrc2,sbroff.            */
                    423:        { int_12S,   DEC_DECODED, "bte"        }, /* bte isrc1,isrc2,sbroff.              */
                    424:        { int_i2S,   DEC_DECODED, "bte"        }, /* bte #const5,isrc2,idest.             */
                    425:        { int_fldst, DEC_DECODED, "pfld."      }, /* pfld.{l,d,q} isrc1(isrc2)[++],fdest. */
                    426:        { int_fldst, DEC_DECODED, "pfld."      }, /* pfld.{l,d,q} #const(isrc2)[++],fdest.*/
                    427:        { int_L,     DEC_DECODED, "br"         }, /* br lbroff.    */
                    428:        { int_L,     DEC_DECODED, "call"       }, /* call lbroff . */
                    429:        { int_L,     DEC_DECODED, "bc"         }, /* bc lbroff.    */
                    430:        { int_L,     DEC_DECODED, "bc.t"       }, /* bc.t lbroff.  */
                    431:        { int_L,     DEC_DECODED, "bnc"        }, /* bnc lbroff.   */
                    432:        { int_L,     DEC_DECODED, "bnc.t"      }, /* bnc.t lbroff. */
                    433:        { int_12d,   DEC_DECODED, "addu"       }, /* addu isrc1,isrc2,idest.    */
                    434:        { int_i2d,   DEC_DECODED, "addu"       }, /* addu #const,isrc2,idest.   */
                    435:        { int_12d,   DEC_DECODED, "subu"       }, /* subu isrc1,isrc2,idest.    */
                    436:        { int_i2d,   DEC_DECODED, "subu"       }, /* subu #const,isrc2,idest.   */
                    437:        { int_12d,   DEC_DECODED, "adds"       }, /* adds isrc1,isrc2,idest.    */
                    438:        { int_i2d,   DEC_DECODED, "adds"       }, /* adds #const,isrc2,idest.   */
                    439:        { int_12d,   DEC_DECODED, "subs"       }, /* subs isrc1,isrc2,idest.    */
                    440:        { int_i2d,   DEC_DECODED, "subs"       }, /* subs #const,isrc2,idest.   */
                    441:        { int_12d,   DEC_DECODED, "shl"        }, /* shl isrc1,isrc2,idest.     */
                    442:        { int_i2d,   DEC_DECODED, "shl"        }, /* shl #const,isrc2,idest.    */
                    443:        { int_12d,   DEC_DECODED, "shr"        }, /* shr isrc1,isrc2,idest.     */
                    444:        { int_i2d,   DEC_DECODED, "shr"        }, /* shr #const,isrc2,idest.    */
                    445:        { int_12d,   DEC_DECODED, "shrd"       }, /* shrd isrc1ni,isrc2,idest.  */
                    446:        { int_12S,   DEC_DECODED, "bla"        }, /* bla isrc1ni,isrc2,sbroff.  */
                    447:        { int_12d,   DEC_DECODED, "shra"       }, /* shra isrc1,isrc2,idest.    */
                    448:        { int_i2d,   DEC_DECODED, "shra"       }, /* shra #const,isrc2,idest.   */
                    449:        { int_12d,   DEC_DECODED, "and"        }, /* and isrc1,isrc2,idest.     */
                    450:        { int_i2d,   DEC_DECODED, "and"        }, /* and #const,isrc2,idest.    */
                    451:        { 0,         0           , 0           },
                    452:        { int_i2d,   DEC_DECODED, "andh"       }, /* andh #const,isrc2,idest.   */
                    453:        { int_12d,   DEC_DECODED, "andnot"     }, /* andnot isrc1,isrc2,idest.  */
                    454:        { int_i2d,   DEC_DECODED, "andnot"     }, /* andnot #const,isrc2,idest. */
                    455:        { 0,         0           , 0           },
                    456:        { int_i2d,   DEC_DECODED, "andnoth"    }, /* andnoth #const,isrc2,idest.*/
                    457:        { int_12d,   DEC_DECODED, "or"         }, /* or isrc1,isrc2,idest.      */
                    458:        { int_i2d,   DEC_DECODED, "or"         }, /* or #const,isrc2,idest.     */
                    459:        { 0,         0           , 0           },
                    460:        { int_i2d,   DEC_DECODED, "orh"        }, /* orh #const,isrc2,idest.    */
                    461:        { int_12d,   DEC_DECODED, "xor"        }, /* xor isrc1,isrc2,idest.     */
                    462:        { int_i2d,   DEC_DECODED, "xor"        }, /* xor #const,isrc2,idest.    */
                    463:        { 0,         0           , 0           },
                    464:        { int_i2d,   DEC_DECODED, "xorh"       }, /* xorh #const,isrc2,idest.   */
                    465: };
                    466: 
                    467: 
                    468: /* Second-level decode table (i.e., for the 3 core escape opcode bits).  */
                    469: static const decode_tbl_t core_esc_decode_tbl[8] =
                    470: {
                    471:        { 0,         0          , 0           },
                    472:        { int_0,     DEC_DECODED, "lock"      }, /* lock.           */
                    473:        { int_1,     DEC_DECODED, "calli"     }, /* calli isrc1ni.  */
                    474:        { 0,         0          , 0           },
                    475:        { int_0,     DEC_DECODED, "intovr"    }, /* intovr.         */
                    476:        { 0,         0          , 0           },
                    477:        { 0,         0          , 0           },
                    478:        { int_0,     DEC_DECODED, "unlock"    }, /* unlock.         */
                    479: };
                    480: 
                    481: 
                    482: /* Second-level decode table (i.e., for the 7 FP extended opcode bits).  */
                    483: static const decode_tbl_t fp_decode_tbl[128] =
                    484: {
                    485:        /* Floating point instructions.  The least significant 7 bits are
                    486:           the (extended) opcode and bits 10:7 are P,D,S,R respectively
                    487:           ([p]ipelined, [d]ual, [s]ource prec., [r]esult prec.).
                    488:           For some operations, I defer decoding the P,S,R bits to the
                    489:           emulation routine for them.  */
                    490:        { flop_12d,  DEC_DECODED, "r2p1."     }, /* 0x00 pf[m]am */
                    491:        { flop_12d,  DEC_DECODED, "r2pt."     }, /* 0x01 pf[m]am */
                    492:        { flop_12d,  DEC_DECODED, "r2ap1."    }, /* 0x02 pf[m]am */
                    493:        { flop_12d,  DEC_DECODED, "r2apt."    }, /* 0x03 pf[m]am */
                    494:        { flop_12d,  DEC_DECODED, "i2p1."     }, /* 0x04 pf[m]am */
                    495:        { flop_12d,  DEC_DECODED, "i2pt."     }, /* 0x05 pf[m]am */
                    496:        { flop_12d,  DEC_DECODED, "i2ap1."    }, /* 0x06 pf[m]am */
                    497:        { flop_12d,  DEC_DECODED, "i2apt."    }, /* 0x07 pf[m]am */
                    498:        { flop_12d,  DEC_DECODED, "rat1p2."   }, /* 0x08 pf[m]am */
                    499:        { flop_12d,  DEC_DECODED, "m12apm."   }, /* 0x09 pf[m]am */
                    500:        { flop_12d,  DEC_DECODED, "ra1p2."    }, /* 0x0A pf[m]am */
                    501:        { flop_12d,  DEC_DECODED, "m12ttpa."  }, /* 0x0B pf[m]am */
                    502:        { flop_12d,  DEC_DECODED, "iat1p2."   }, /* 0x0C pf[m]am */
                    503:        { flop_12d,  DEC_DECODED, "m12tpm."   }, /* 0x0D pf[m]am */
                    504:        { flop_12d,  DEC_DECODED, "ia1p2."    }, /* 0x0E pf[m]am */
                    505:        { flop_12d,  DEC_DECODED, "m12tpa."   }, /* 0x0F pf[m]am */
                    506:        { flop_12d,  DEC_DECODED, "r2s1."     }, /* 0x10 pf[m]sm */
                    507:        { flop_12d,  DEC_DECODED, "r2st."     }, /* 0x11 pf[m]sm */
                    508:        { flop_12d,  DEC_DECODED, "r2as1."    }, /* 0x12 pf[m]sm */
                    509:        { flop_12d,  DEC_DECODED, "r2ast."    }, /* 0x13 pf[m]sm */
                    510:        { flop_12d,  DEC_DECODED, "i2s1."     }, /* 0x14 pf[m]sm */
                    511:        { flop_12d,  DEC_DECODED, "i2st."     }, /* 0x15 pf[m]sm */
                    512:        { flop_12d,  DEC_DECODED, "i2as1."    }, /* 0x16 pf[m]sm */
                    513:        { flop_12d,  DEC_DECODED, "i2ast."    }, /* 0x17 pf[m]sm */
                    514:        { flop_12d,  DEC_DECODED, "rat1s2."   }, /* 0x18 pf[m]sm */
                    515:        { flop_12d,  DEC_DECODED, "m12asm."   }, /* 0x19 pf[m]sm */
                    516:        { flop_12d,  DEC_DECODED, "ra1s2."    }, /* 0x1A pf[m]sm */
                    517:        { flop_12d,  DEC_DECODED, "m12ttsa."  }, /* 0x1B pf[m]sm */
                    518:        { flop_12d,  DEC_DECODED, "iat1s2."   }, /* 0x1C pf[m]sm */
                    519:        { flop_12d,  DEC_DECODED, "m12tsm."   }, /* 0x1D pf[m]sm */
                    520:        { flop_12d,  DEC_DECODED, "ia1s2."    }, /* 0x1E pf[m]sm */
                    521:        { flop_12d,  DEC_DECODED, "m12tsa."   }, /* 0x1F pf[m]sm */
                    522:        { flop_12d,  DEC_DECODED, "fmul."     }, /* 0x20 [p]fmul */
                    523:        { flop_12d,  DEC_DECODED, "fmlow."    }, /* 0x21 fmlow.dd */
                    524:        { flop_2d,   DEC_DECODED, "frcp."     }, /* 0x22 frcp.{ss,sd,dd} */
                    525:        { flop_2d,   DEC_DECODED, "frsqr."    }, /* 0x23 frsqr.{ss,sd,dd} */
                    526:        { flop_12d,  DEC_DECODED, "pfmul3.dd" }, /* 0x24 pfmul3.dd */
                    527:        { 0,         0          , 0           }, /* 0x25 */
                    528:        { 0,         0          , 0           }, /* 0x26 */
                    529:        { 0,         0          , 0           }, /* 0x27 */
                    530:        { 0,         0          , 0           }, /* 0x28 */
                    531:        { 0,         0          , 0           }, /* 0x29 */
                    532:        { 0,         0          , 0           }, /* 0x2A */
                    533:        { 0,         0          , 0           }, /* 0x2B */
                    534:        { 0,         0          , 0           }, /* 0x2C */
                    535:        { 0,         0          , 0           }, /* 0x2D */
                    536:        { 0,         0          , 0           }, /* 0x2E */
                    537:        { 0,         0          , 0           }, /* 0x2F */
                    538:        { flop_12d,  DEC_DECODED, "fadd."     }, /* 0x30, [p]fadd.{ss,sd,dd} */
                    539:        { flop_12d,  DEC_DECODED, "fsub."     }, /* 0x31, [p]fsub.{ss,sd,dd} */
                    540:        { flop_1d,   DEC_DECODED, "fix."      }, /* 0x32, [p]fix.{ss,sd,dd} */
                    541:        { flop_1d,   DEC_DECODED, "famov."    }, /* 0x33, [p]famov.{ss,sd,ds,dd} */
                    542:        { flop_12d,  DEC_DECODED, "f{gt,le}"  }, /* 0x34, pf{gt,le}.{ss,dd} */
                    543:        { flop_12d,  DEC_DECODED, "feq."      }, /* 0x35, pfeq.{ss,dd} */
                    544:        { 0,         0          , 0           }, /* 0x36 */
                    545:        { 0,         0          , 0           }, /* 0x37 */
                    546:        { 0,         0          , 0           }, /* 0x38 */
                    547:        { 0,         0          , 0           }, /* 0x39 */
                    548:        { flop_1d,   DEC_DECODED, "ftrunc."   }, /* 0x3A, [p]ftrunc.{ss,sd,dd} */
                    549:        { 0,         0          , 0           }, /* 0x3B */
                    550:        { 0,         0          , 0           }, /* 0x3C */
                    551:        { 0,         0          , 0           }, /* 0x3D */
                    552:        { 0,         0          , 0           }, /* 0x3E */
                    553:        { 0,         0          , 0           }, /* 0x3F */
                    554:        { flop_fxfr, DEC_DECODED, "fxfr"      }, /* 0x40, fxfr fsrc1,idest. */
                    555:        { 0,         0          , 0           }, /* 0x41 */
                    556:        { 0,         0          , 0           }, /* 0x42 */
                    557:        { 0,         0          , 0           }, /* 0x43 */
                    558:        { 0,         0          , 0           }, /* 0x44 */
                    559:        { 0,         0          , 0           }, /* 0x45 */
                    560:        { 0,         0          , 0           }, /* 0x46 */
                    561:        { 0,         0          , 0           }, /* 0x47 */
                    562:        { 0,         0          , 0           }, /* 0x48 */
                    563:        { flop_12d,  DEC_DECODED, "fiadd."    }, /* 0x49, [p]fiadd.{ss,dd} */
                    564:        { 0,         0          , 0           }, /* 0x4A */
                    565:        { 0,         0          , 0           }, /* 0x4B */
                    566:        { 0,         0          , 0           }, /* 0x4C */
                    567:        { flop_12d,  DEC_DECODED, "fisub."    }, /* 0x4D, [p]fisub.{ss,dd} */
                    568:        { 0,         0          , 0           }, /* 0x4E */
                    569:        { 0,         0          , 0           }, /* 0x4F */
                    570:        { flop_12d,  DEC_DECODED, "faddp"     }, /* 0x50, [p]faddp */
                    571:        { flop_12d,  DEC_DECODED, "faddz"     }, /* 0x51, [p]faddz */
                    572:        { 0,         0          , 0           }, /* 0x52 */
                    573:        { 0,         0          , 0           }, /* 0x53 */
                    574:        { 0,         0          , 0           }, /* 0x54 */
                    575:        { 0,         0          , 0           }, /* 0x55 */
                    576:        { 0,         0          , 0           }, /* 0x56 */
                    577:        { flop_12d,  DEC_DECODED, "fzchkl"    }, /* 0x57, [p]fzchkl */
                    578:        { 0,         0          , 0           }, /* 0x58 */
                    579:        { 0,         0          , 0           }, /* 0x59 */
                    580:        { flop_1d,   DEC_DECODED, "form"      }, /* 0x5A, [p]form.dd */
                    581:        { 0,         0          , 0           }, /* 0x5B */
                    582:        { 0,         0          , 0           }, /* 0x5C */
                    583:        { 0,         0          , 0           }, /* 0x5D */
                    584:        { 0,         0          , 0           }, /* 0x5E */
                    585:        { flop_12d,  DEC_DECODED, "fzchks"    }, /* 0x5F, [p]fzchks */
                    586:        { 0,         0          , 0           }, /* 0x60 */
                    587:        { 0,         0          , 0           }, /* 0x61 */
                    588:        { 0,         0          , 0           }, /* 0x62 */
                    589:        { 0,         0          , 0           }, /* 0x63 */
                    590:        { 0,         0          , 0           }, /* 0x64 */
                    591:        { 0,         0          , 0           }, /* 0x65 */
                    592:        { 0,         0          , 0           }, /* 0x66 */
                    593:        { 0,         0          , 0           }, /* 0x67 */
                    594:        { 0,         0          , 0           }, /* 0x68 */
                    595:        { 0,         0          , 0           }, /* 0x69 */
                    596:        { 0,         0          , 0           }, /* 0x6A */
                    597:        { 0,         0          , 0           }, /* 0x6B */
                    598:        { 0,         0          , 0           }, /* 0x6C */
                    599:        { 0,         0          , 0           }, /* 0x6D */
                    600:        { 0,         0          , 0           }, /* 0x6E */
                    601:        { 0,         0          , 0           }, /* 0x6F */
                    602:        { 0,         0          , 0           }, /* 0x70 */
                    603:        { 0,         0          , 0           }, /* 0x71 */
                    604:        { 0,         0          , 0           }, /* 0x72 */
                    605:        { 0,         0          , 0           }, /* 0x73 */
                    606:        { 0,         0          , 0           }, /* 0x74 */
                    607:        { 0,         0          , 0           }, /* 0x75 */
                    608:        { 0,         0          , 0           }, /* 0x76 */
                    609:        { 0,         0          , 0           }, /* 0x77 */
                    610:        { 0,         0          , 0           }, /* 0x78 */
                    611:        { 0,         0          , 0           }, /* 0x79 */
                    612:        { 0,         0          , 0           }, /* 0x7A */
                    613:        { 0,         0          , 0           }, /* 0x7B */
                    614:        { 0,         0          , 0           }, /* 0x7C */
                    615:        { 0,         0          , 0           }, /* 0x7D */
                    616:        { 0,         0          , 0           }, /* 0x7E */
                    617:        { 0,         0          , 0           }, /* 0x7F */
                    618: };
                    619: 
                    620: 
                    621: /* Replaces tabs with spaces.  */
                    622: static void i860_dasm_tab_replacer(char* buf, int tab_size)
                    623: {
                    624:        int i = 0;
                    625:        int tab_count = 0;
                    626:        char tab_buf[1024];
                    627:        memset(tab_buf, 0, 1024);
                    628: 
                    629:        while (i != strlen(buf))
                    630:        {
                    631:                if (buf[i] != '\t')
                    632:                {
                    633:                        tab_buf[tab_count] = buf[i];
                    634:                        tab_count++;
                    635:                }
                    636:                else
                    637:                {
                    638:                        while (tab_count % tab_size != 0)
                    639:                        {
                    640:                                strcat(tab_buf, " ");
                    641:                                tab_count++;
                    642:                        }
                    643:                }
                    644:                i++;
                    645:        }
                    646: 
                    647:        tab_buf[tab_count] = 0x00;
                    648:        strcpy(buf, tab_buf);
                    649: }
                    650: 
                    651: 
                    652: int i860_disassembler(UINT32 pc, UINT32 insn, char* buffer) {
                    653:        int unrecognized_op = 1;
                    654:     
                    655:        int upper_6bits = (insn >> 26) & 0x3f;
                    656:        char flags = decode_tbl[upper_6bits].flags;
                    657:     if(insn == INSN_NOP) {
                    658:         strcpy(buffer, "  nop");
                    659:         unrecognized_op = 0;
                    660:     } else if(insn == INSN_FNOP) {
                    661:         strcpy(buffer, "  fnop");
                    662:         unrecognized_op = 0;
                    663:     } else if(insn == INSN_FNOP_DIM) {
                    664:         strcpy(buffer, "d.fnop");
                    665:         unrecognized_op = 0;
                    666:     } else if (flags & DEC_DECODED) {
                    667:                const char *s = decode_tbl[upper_6bits].mnemonic;
                    668:                decode_tbl[upper_6bits].insn_dis (buffer, (char *)s, pc, insn);
                    669:                unrecognized_op = 0;
                    670:        } else if (flags & DEC_MORE) {
                    671:                if (upper_6bits == 0x12) {
                    672:                        /* FP instruction format handled here.  */
                    673:                        char fp_flags = fp_decode_tbl[insn & 0x7f].flags;
                    674:                        const char *s = fp_decode_tbl[insn & 0x7f].mnemonic;
                    675:                        if (fp_flags & DEC_DECODED) {
                    676:                                fp_decode_tbl[insn & 0x7f].insn_dis (buffer, (char *)s, pc, insn);
                    677:                                unrecognized_op = 0;
                    678:                        }
                    679:                }
                    680:                else if (upper_6bits == 0x13) {
                    681:                        /* Core escape instruction format handled here.  */
                    682:                        char esc_flags = core_esc_decode_tbl[insn & 0x3].flags;
                    683:                        const char *s = core_esc_decode_tbl[insn & 0x3].mnemonic;
                    684:                        if (esc_flags & DEC_DECODED)
                    685:                        {
                    686:                                core_esc_decode_tbl[insn & 0x3].insn_dis (buffer, (char *)s, pc, insn);
                    687:                                unrecognized_op = 0;
                    688:                        }
                    689:                }
                    690:        }
                    691: 
                    692:        if (unrecognized_op)
                    693:                sprintf (buffer, "  .long\t%#08x", insn);
                    694: 
                    695:        /* Replace tabs with spaces */
                    696:        i860_dasm_tab_replacer(buffer, 10);
                    697: 
                    698:        /* Return number of bytes disassembled.  */
                    699:        /* MAME dasm flags haven't been added yet */
                    700:        return (4);
                    701: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.