qemu/disas/lm32.c
<<
>>
Prefs
   1/*
   2 *  Simple LatticeMico32 disassembler.
   3 *
   4 *  Copyright (c) 2012 Michael Walle <michael@walle.cc>
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 *
  19 */
  20
  21#include "qemu/osdep.h"
  22#include "disas/bfd.h"
  23
  24typedef enum {
  25    LM32_OP_SRUI = 0, LM32_OP_NORI, LM32_OP_MULI, LM32_OP_SH, LM32_OP_LB,
  26    LM32_OP_SRI, LM32_OP_XORI, LM32_OP_LH, LM32_OP_ANDI, LM32_OP_XNORI,
  27    LM32_OP_LW, LM32_OP_LHU, LM32_OP_SB, LM32_OP_ADDI, LM32_OP_ORI,
  28    LM32_OP_SLI, LM32_OP_LBU, LM32_OP_BE, LM32_OP_BG, LM32_OP_BGE,
  29    LM32_OP_BGEU, LM32_OP_BGU, LM32_OP_SW, LM32_OP_BNE, LM32_OP_ANDHI,
  30    LM32_OP_CMPEI, LM32_OP_CMPGI, LM32_OP_CMPGEI, LM32_OP_CMPGEUI,
  31    LM32_OP_CMPGUI, LM32_OP_ORHI, LM32_OP_CMPNEI, LM32_OP_SRU, LM32_OP_NOR,
  32    LM32_OP_MUL, LM32_OP_DIVU, LM32_OP_RCSR, LM32_OP_SR, LM32_OP_XOR,
  33    LM32_OP_ILL0, LM32_OP_AND, LM32_OP_XNOR, LM32_OP_ILL1, LM32_OP_SCALL,
  34    LM32_OP_SEXTB, LM32_OP_ADD, LM32_OP_OR, LM32_OP_SL, LM32_OP_B,
  35    LM32_OP_MODU, LM32_OP_SUB, LM32_OP_ILL2, LM32_OP_WCSR, LM32_OP_ILL3,
  36    LM32_OP_CALL, LM32_OP_SEXTH, LM32_OP_BI, LM32_OP_CMPE, LM32_OP_CMPG,
  37    LM32_OP_CMPGE, LM32_OP_CMPGEU, LM32_OP_CMPGU, LM32_OP_CALLI, LM32_OP_CMPNE,
  38} Lm32Opcode;
  39
  40typedef enum {
  41    FMT_INVALID = 0, FMT_RRI5, FMT_RRI16, FMT_IMM26, FMT_LOAD, FMT_STORE,
  42    FMT_RRR, FMT_R, FMT_RNR, FMT_CRN, FMT_CNR, FMT_BREAK,
  43} Lm32OpcodeFmt;
  44
  45typedef enum {
  46    LM32_CSR_IE = 0, LM32_CSR_IM, LM32_CSR_IP, LM32_CSR_ICC, LM32_CSR_DCC,
  47    LM32_CSR_CC, LM32_CSR_CFG, LM32_CSR_EBA, LM32_CSR_DC, LM32_CSR_DEBA,
  48    LM32_CSR_CFG2, LM32_CSR_JTX = 0xe, LM32_CSR_JRX, LM32_CSR_BP0,
  49    LM32_CSR_BP1, LM32_CSR_BP2, LM32_CSR_BP3, LM32_CSR_WP0 = 0x18,
  50    LM32_CSR_WP1, LM32_CSR_WP2, LM32_CSR_WP3,
  51} Lm32CsrNum;
  52
  53typedef struct {
  54    int csr;
  55    const char *name;
  56} Lm32CsrInfo;
  57
  58static const Lm32CsrInfo lm32_csr_info[] = {
  59    {LM32_CSR_IE,   "ie", },
  60    {LM32_CSR_IM,   "im", },
  61    {LM32_CSR_IP,   "ip", },
  62    {LM32_CSR_ICC,  "icc", },
  63    {LM32_CSR_DCC,  "dcc", },
  64    {LM32_CSR_CC,   "cc", },
  65    {LM32_CSR_CFG,  "cfg", },
  66    {LM32_CSR_EBA,  "eba", },
  67    {LM32_CSR_DC,   "dc", },
  68    {LM32_CSR_DEBA, "deba", },
  69    {LM32_CSR_CFG2, "cfg2", },
  70    {LM32_CSR_JTX,  "jtx", },
  71    {LM32_CSR_JRX,  "jrx", },
  72    {LM32_CSR_BP0,  "bp0", },
  73    {LM32_CSR_BP1,  "bp1", },
  74    {LM32_CSR_BP2,  "bp2", },
  75    {LM32_CSR_BP3,  "bp3", },
  76    {LM32_CSR_WP0,  "wp0", },
  77    {LM32_CSR_WP1,  "wp1", },
  78    {LM32_CSR_WP2,  "wp2", },
  79    {LM32_CSR_WP3,  "wp3", },
  80};
  81
  82static const Lm32CsrInfo *find_csr_info(int csr)
  83{
  84    const Lm32CsrInfo *info;
  85    int i;
  86
  87    for (i = 0; i < ARRAY_SIZE(lm32_csr_info); i++) {
  88        info = &lm32_csr_info[i];
  89        if (csr == info->csr) {
  90            return info;
  91        }
  92    }
  93
  94    return NULL;
  95}
  96
  97typedef struct {
  98    int reg;
  99    const char *name;
 100} Lm32RegInfo;
 101
 102typedef enum {
 103    LM32_REG_R0 = 0, LM32_REG_R1, LM32_REG_R2, LM32_REG_R3, LM32_REG_R4,
 104    LM32_REG_R5, LM32_REG_R6, LM32_REG_R7, LM32_REG_R8, LM32_REG_R9,
 105    LM32_REG_R10, LM32_REG_R11, LM32_REG_R12, LM32_REG_R13, LM32_REG_R14,
 106    LM32_REG_R15, LM32_REG_R16, LM32_REG_R17, LM32_REG_R18, LM32_REG_R19,
 107    LM32_REG_R20, LM32_REG_R21, LM32_REG_R22, LM32_REG_R23, LM32_REG_R24,
 108    LM32_REG_R25, LM32_REG_GP, LM32_REG_FP, LM32_REG_SP, LM32_REG_RA,
 109    LM32_REG_EA, LM32_REG_BA,
 110} Lm32RegNum;
 111
 112static const Lm32RegInfo lm32_reg_info[] = {
 113    {LM32_REG_R0,  "r0", },
 114    {LM32_REG_R1,  "r1", },
 115    {LM32_REG_R2,  "r2", },
 116    {LM32_REG_R3,  "r3", },
 117    {LM32_REG_R4,  "r4", },
 118    {LM32_REG_R5,  "r5", },
 119    {LM32_REG_R6,  "r6", },
 120    {LM32_REG_R7,  "r7", },
 121    {LM32_REG_R8,  "r8", },
 122    {LM32_REG_R9,  "r9", },
 123    {LM32_REG_R10, "r10", },
 124    {LM32_REG_R11, "r11", },
 125    {LM32_REG_R12, "r12", },
 126    {LM32_REG_R13, "r13", },
 127    {LM32_REG_R14, "r14", },
 128    {LM32_REG_R15, "r15", },
 129    {LM32_REG_R16, "r16", },
 130    {LM32_REG_R17, "r17", },
 131    {LM32_REG_R18, "r18", },
 132    {LM32_REG_R19, "r19", },
 133    {LM32_REG_R20, "r20", },
 134    {LM32_REG_R21, "r21", },
 135    {LM32_REG_R22, "r22", },
 136    {LM32_REG_R23, "r23", },
 137    {LM32_REG_R24, "r24", },
 138    {LM32_REG_R25, "r25", },
 139    {LM32_REG_GP,  "gp", },
 140    {LM32_REG_FP,  "fp", },
 141    {LM32_REG_SP,  "sp", },
 142    {LM32_REG_RA,  "ra", },
 143    {LM32_REG_EA,  "ea", },
 144    {LM32_REG_BA,  "ba", },
 145};
 146
 147static const Lm32RegInfo *find_reg_info(int reg)
 148{
 149    assert(ARRAY_SIZE(lm32_reg_info) == 32);
 150    return &lm32_reg_info[reg & 0x1f];
 151}
 152
 153typedef struct {
 154    struct {
 155        uint32_t code;
 156        uint32_t mask;
 157    } op;
 158    const char *name;
 159    const char *args_fmt;
 160} Lm32OpcodeInfo;
 161
 162static const Lm32OpcodeInfo lm32_opcode_info[] = {
 163    /* pseudo instructions */
 164    {{0x34000000, 0xffffffff}, "nop",   NULL},
 165    {{0xac000002, 0xffffffff}, "break", NULL},
 166    {{0xac000003, 0xffffffff}, "scall", NULL},
 167    {{0xc3e00000, 0xffffffff}, "bret",  NULL},
 168    {{0xc3c00000, 0xffffffff}, "eret",  NULL},
 169    {{0xc3a00000, 0xffffffff}, "ret",   NULL},
 170    {{0xa4000000, 0xfc1f07ff}, "not",   "%2, %0"},
 171    {{0xb8000000, 0xfc1f07ff}, "mv",    "%2, %0"},
 172    {{0x71e00000, 0xffe00000}, "mvhi",  "%1, %u"},
 173    {{0x34000000, 0xffe00000}, "mvi",   "%1, %s"},
 174
 175#define _O(op) {op << 26, 0x3f << 26}
 176    /* regular opcodes */
 177    {_O(LM32_OP_ADD),     "add",     "%2, %0, %1"  },
 178    {_O(LM32_OP_ADDI),    "addi",    "%1, %0, %s"  },
 179    {_O(LM32_OP_AND),     "and",     "%2, %0, %1"  },
 180    {_O(LM32_OP_ANDHI),   "andhi",   "%1, %0, %u"  },
 181    {_O(LM32_OP_ANDI),    "andi",    "%1, %0, %u"  },
 182    {_O(LM32_OP_B),       "b",       "%0",         },
 183    {_O(LM32_OP_BE),      "be",      "%1, %0, %r"  },
 184    {_O(LM32_OP_BG),      "bg",      "%1, %0, %r"  },
 185    {_O(LM32_OP_BGE),     "bge",     "%1, %0, %r"  },
 186    {_O(LM32_OP_BGEU),    "bgeu",    "%1, %0, %r"  },
 187    {_O(LM32_OP_BGU),     "bgu",     "%1, %0, %r"  },
 188    {_O(LM32_OP_BI),      "bi",      "%R",         },
 189    {_O(LM32_OP_BNE),     "bne",     "%1, %0, %r"  },
 190    {_O(LM32_OP_CALL),    "call",    "%0",         },
 191    {_O(LM32_OP_CALLI),   "calli",   "%R",         },
 192    {_O(LM32_OP_CMPE),    "cmpe",    "%2, %0, %1"  },
 193    {_O(LM32_OP_CMPEI),   "cmpei",   "%1, %0, %s"  },
 194    {_O(LM32_OP_CMPG),    "cmpg",    "%2, %0, %1"  },
 195    {_O(LM32_OP_CMPGE),   "cmpge",   "%2, %0, %1"  },
 196    {_O(LM32_OP_CMPGEI),  "cmpgei",  "%1, %0, %s"  },
 197    {_O(LM32_OP_CMPGEU),  "cmpgeu",  "%2, %0, %1"  },
 198    {_O(LM32_OP_CMPGEUI), "cmpgeui", "%1, %0, %s"  },
 199    {_O(LM32_OP_CMPGI),   "cmpgi",   "%1, %0, %s"  },
 200    {_O(LM32_OP_CMPGU),   "cmpgu",   "%2, %0, %1"  },
 201    {_O(LM32_OP_CMPGUI),  "cmpgui",  "%1, %0, %s"  },
 202    {_O(LM32_OP_CMPNE),   "cmpne",   "%2, %0, %1"  },
 203    {_O(LM32_OP_CMPNEI),  "cmpnei",  "%1, %0, %s"  },
 204    {_O(LM32_OP_DIVU),    "divu",    "%2, %0, %1"  },
 205    {_O(LM32_OP_LB),      "lb",      "%1, (%0+%s)" },
 206    {_O(LM32_OP_LBU),     "lbu",     "%1, (%0+%s)" },
 207    {_O(LM32_OP_LH),      "lh",      "%1, (%0+%s)" },
 208    {_O(LM32_OP_LHU),     "lhu",     "%1, (%0+%s)" },
 209    {_O(LM32_OP_LW),      "lw",      "%1, (%0+%s)" },
 210    {_O(LM32_OP_MODU),    "modu",    "%2, %0, %1"  },
 211    {_O(LM32_OP_MULI),    "muli",    "%1, %0, %s"  },
 212    {_O(LM32_OP_MUL),     "mul",     "%2, %0, %1"  },
 213    {_O(LM32_OP_NORI),    "nori",    "%1, %0, %u"  },
 214    {_O(LM32_OP_NOR),     "nor",     "%2, %0, %1"  },
 215    {_O(LM32_OP_ORHI),    "orhi",    "%1, %0, %u"  },
 216    {_O(LM32_OP_ORI),     "ori",     "%1, %0, %u"  },
 217    {_O(LM32_OP_OR),      "or",      "%2, %0, %1"  },
 218    {_O(LM32_OP_RCSR),    "rcsr",    "%2, %c",     },
 219    {_O(LM32_OP_SB),      "sb",      "(%0+%s), %1" },
 220    {_O(LM32_OP_SEXTB),   "sextb",   "%2, %0",     },
 221    {_O(LM32_OP_SEXTH),   "sexth",   "%2, %0",     },
 222    {_O(LM32_OP_SH),      "sh",      "(%0+%s), %1" },
 223    {_O(LM32_OP_SLI),     "sli",     "%1, %0, %h"  },
 224    {_O(LM32_OP_SL),      "sl",      "%2, %0, %1"  },
 225    {_O(LM32_OP_SRI),     "sri",     "%1, %0, %h"  },
 226    {_O(LM32_OP_SR),      "sr",      "%2, %0, %1"  },
 227    {_O(LM32_OP_SRUI),    "srui",    "%1, %0, %d"  },
 228    {_O(LM32_OP_SRU),     "sru",     "%2, %0, %s"  },
 229    {_O(LM32_OP_SUB),     "sub",     "%2, %0, %s"  },
 230    {_O(LM32_OP_SW),      "sw",      "(%0+%s), %1" },
 231    {_O(LM32_OP_WCSR),    "wcsr",    "%c, %1",     },
 232    {_O(LM32_OP_XNORI),   "xnori",   "%1, %0, %u"  },
 233    {_O(LM32_OP_XNOR),    "xnor",    "%2, %0, %1"  },
 234    {_O(LM32_OP_XORI),    "xori",    "%1, %0, %u"  },
 235    {_O(LM32_OP_XOR),     "xor",     "%2, %0, %1"  },
 236#undef _O
 237};
 238
 239static const Lm32OpcodeInfo *find_opcode_info(uint32_t opcode)
 240{
 241    const Lm32OpcodeInfo *info;
 242    int i;
 243    for (i = 0; i < ARRAY_SIZE(lm32_opcode_info); i++) {
 244        info = &lm32_opcode_info[i];
 245        if ((opcode & info->op.mask) == info->op.code) {
 246            return info;
 247        }
 248    }
 249
 250    return NULL;
 251}
 252
 253int print_insn_lm32(bfd_vma memaddr, struct disassemble_info *info)
 254{
 255    fprintf_function fprintf_fn = info->fprintf_func;
 256    void *stream = info->stream;
 257    int rc;
 258    uint8_t insn[4];
 259    const Lm32OpcodeInfo *opc_info;
 260    uint32_t op;
 261    const char *args_fmt;
 262
 263    rc = info->read_memory_func(memaddr, insn, 4, info);
 264    if (rc != 0) {
 265        info->memory_error_func(rc, memaddr, info);
 266        return -1;
 267    }
 268
 269    fprintf_fn(stream, "%02x %02x %02x %02x    ",
 270            insn[0], insn[1], insn[2], insn[3]);
 271
 272    op = bfd_getb32(insn);
 273    opc_info = find_opcode_info(op);
 274    if (opc_info) {
 275        fprintf_fn(stream, "%-8s ", opc_info->name);
 276        args_fmt = opc_info->args_fmt;
 277        while (args_fmt && *args_fmt) {
 278            if (*args_fmt == '%') {
 279                switch (*(++args_fmt)) {
 280                case '0': {
 281                    uint8_t r0;
 282                    const char *r0_name;
 283                    r0 = (op >> 21) & 0x1f;
 284                    r0_name = find_reg_info(r0)->name;
 285                    fprintf_fn(stream, "%s", r0_name);
 286                    break;
 287                }
 288                case '1': {
 289                    uint8_t r1;
 290                    const char *r1_name;
 291                    r1 = (op >> 16) & 0x1f;
 292                    r1_name = find_reg_info(r1)->name;
 293                    fprintf_fn(stream, "%s", r1_name);
 294                    break;
 295                }
 296                case '2': {
 297                    uint8_t r2;
 298                    const char *r2_name;
 299                    r2 = (op >> 11) & 0x1f;
 300                    r2_name = find_reg_info(r2)->name;
 301                    fprintf_fn(stream, "%s", r2_name);
 302                    break;
 303                }
 304                case 'c': {
 305                    uint8_t csr;
 306                    const Lm32CsrInfo *info;
 307                    csr = (op >> 21) & 0x1f;
 308                    info = find_csr_info(csr);
 309                    if (info) {
 310                        fprintf_fn(stream, "%s", info->name);
 311                    } else {
 312                        fprintf_fn(stream, "0x%x", csr);
 313                    }
 314                    break;
 315                }
 316                case 'u': {
 317                    uint16_t u16;
 318                    u16 = op & 0xffff;
 319                    fprintf_fn(stream, "0x%x", u16);
 320                    break;
 321                }
 322                case 's': {
 323                    int16_t s16;
 324                    s16 = (int16_t)(op & 0xffff);
 325                    fprintf_fn(stream, "%d", s16);
 326                    break;
 327                }
 328                case 'r': {
 329                    uint32_t rela;
 330                    rela = memaddr + (((int16_t)(op & 0xffff)) << 2);
 331                    fprintf_fn(stream, "%x", rela);
 332                    break;
 333                }
 334                case 'R': {
 335                    uint32_t rela;
 336                    int32_t imm26;
 337                    imm26 = (int32_t)((op & 0x3ffffff) << 6) >> 4;
 338                    rela = memaddr + imm26;
 339                    fprintf_fn(stream, "%x", rela);
 340                    break;
 341                }
 342                case 'h': {
 343                    uint8_t u5;
 344                    u5 = (op & 0x1f);
 345                    fprintf_fn(stream, "%d", u5);
 346                    break;
 347                }
 348                default:
 349                    break;
 350                }
 351            } else {
 352                fprintf_fn(stream, "%c", *args_fmt);
 353            }
 354            args_fmt++;
 355        }
 356    } else {
 357        fprintf_fn(stream, ".word 0x%x", op);
 358    }
 359
 360    return 4;
 361}
 362