lm32-dis.c 13 KB

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