dlx-dis.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /* Instruction printing code for the DLX Microprocessor
  2. Copyright (C) 2002-2022 Free Software Foundation, Inc.
  3. Contributed by Kuang Hwa Lin. Written by Kuang Hwa Lin, 03/2002.
  4. This file is part of the GNU opcodes library.
  5. This library is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3, or (at your option)
  8. any later version.
  9. It is distributed in the hope that it will be useful, but WITHOUT
  10. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  12. License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  16. MA 02110-1301, USA. */
  17. #include "sysdep.h"
  18. #include "disassemble.h"
  19. #include "opcode/dlx.h"
  20. #define R_ERROR 0x1
  21. #define R_TYPE 0x2
  22. #define ILD_TYPE 0x3
  23. #define IST_TYPE 0x4
  24. #define IAL_TYPE 0x5
  25. #define IBR_TYPE 0x6
  26. #define IJ_TYPE 0x7
  27. #define IJR_TYPE 0x8
  28. #define NIL 0x9
  29. #define OPC(x) ((x >> 26) & 0x3F)
  30. #define FUNC(x) (x & 0x7FF)
  31. unsigned char opc, rs1, rs2, rd;
  32. unsigned long imm26, imm16, func, current_insn_addr;
  33. /* Print one instruction from MEMADDR on INFO->STREAM.
  34. Return the size of the instruction (always 4 on dlx). */
  35. static unsigned char
  36. dlx_get_opcode (unsigned long opcode)
  37. {
  38. return (unsigned char) ((opcode >> 26) & 0x3F);
  39. }
  40. static unsigned char
  41. dlx_get_rs1 (unsigned long opcode)
  42. {
  43. return (unsigned char) ((opcode >> 21) & 0x1F);
  44. }
  45. static unsigned char
  46. dlx_get_rs2 (unsigned long opcode)
  47. {
  48. return (unsigned char) ((opcode >> 16) & 0x1F);
  49. }
  50. static unsigned char
  51. dlx_get_rdR (unsigned long opcode)
  52. {
  53. return (unsigned char) ((opcode >> 11) & 0x1F);
  54. }
  55. static unsigned long
  56. dlx_get_func (unsigned long opcode)
  57. {
  58. return (unsigned char) (opcode & 0x7FF);
  59. }
  60. static unsigned long
  61. dlx_get_imm16 (unsigned long opcode)
  62. {
  63. return (unsigned long) (opcode & 0xFFFF);
  64. }
  65. static unsigned long
  66. dlx_get_imm26 (unsigned long opcode)
  67. {
  68. return (unsigned long) (opcode & 0x03FFFFFF);
  69. }
  70. /* Fill the opcode to the max length. */
  71. static void
  72. operand_deliminator (struct disassemble_info *info, char *ptr)
  73. {
  74. int difft = 8 - (int) strlen (ptr);
  75. while (difft > 0)
  76. {
  77. (*info->fprintf_func) (info->stream, "%c", ' ');
  78. difft -= 1;
  79. }
  80. }
  81. /* Process the R-type opcode. */
  82. static unsigned char
  83. dlx_r_type (struct disassemble_info *info)
  84. {
  85. unsigned char r_opc[] = { OPC(ALUOP) }; /* Fix ME */
  86. int r_opc_num = (sizeof r_opc) / (sizeof (char));
  87. struct _r_opcode
  88. {
  89. unsigned long func;
  90. char *name;
  91. }
  92. dlx_r_opcode[] =
  93. {
  94. { NOPF, "nop" }, /* NOP */
  95. { ADDF, "add" }, /* Add */
  96. { ADDUF, "addu" }, /* Add Unsigned */
  97. { SUBF, "sub" }, /* SUB */
  98. { SUBUF, "subu" }, /* Sub Unsigned */
  99. { MULTF, "mult" }, /* MULTIPLY */
  100. { MULTUF, "multu" }, /* MULTIPLY Unsigned */
  101. { DIVF, "div" }, /* DIVIDE */
  102. { DIVUF, "divu" }, /* DIVIDE Unsigned */
  103. { ANDF, "and" }, /* AND */
  104. { ORF, "or" }, /* OR */
  105. { XORF, "xor" }, /* Exclusive OR */
  106. { SLLF, "sll" }, /* SHIFT LEFT LOGICAL */
  107. { SRAF, "sra" }, /* SHIFT RIGHT ARITHMETIC */
  108. { SRLF, "srl" }, /* SHIFT RIGHT LOGICAL */
  109. { SEQF, "seq" }, /* Set if equal */
  110. { SNEF, "sne" }, /* Set if not equal */
  111. { SLTF, "slt" }, /* Set if less */
  112. { SGTF, "sgt" }, /* Set if greater */
  113. { SLEF, "sle" }, /* Set if less or equal */
  114. { SGEF, "sge" }, /* Set if greater or equal */
  115. { SEQUF, "sequ" }, /* Set if equal */
  116. { SNEUF, "sneu" }, /* Set if not equal */
  117. { SLTUF, "sltu" }, /* Set if less */
  118. { SGTUF, "sgtu" }, /* Set if greater */
  119. { SLEUF, "sleu" }, /* Set if less or equal */
  120. { SGEUF, "sgeu" }, /* Set if greater or equal */
  121. { MVTSF, "mvts" }, /* Move to special register */
  122. { MVFSF, "mvfs" }, /* Move from special register */
  123. { BSWAPF, "bswap" }, /* Byte swap ?? */
  124. { LUTF, "lut" } /* ????????? ?? */
  125. };
  126. int dlx_r_opcode_num = (sizeof dlx_r_opcode) / (sizeof dlx_r_opcode[0]);
  127. int idx;
  128. for (idx = 0; idx < r_opc_num; idx++)
  129. {
  130. if (r_opc[idx] != opc)
  131. continue;
  132. else
  133. break;
  134. }
  135. if (idx == r_opc_num)
  136. return NIL;
  137. for (idx = 0 ; idx < dlx_r_opcode_num; idx++)
  138. if (dlx_r_opcode[idx].func == func)
  139. {
  140. (*info->fprintf_func) (info->stream, "%s", dlx_r_opcode[idx].name);
  141. if (func != NOPF)
  142. {
  143. /* This is not a nop. */
  144. operand_deliminator (info, dlx_r_opcode[idx].name);
  145. (*info->fprintf_func) (info->stream, "r%d,", (int)rd);
  146. (*info->fprintf_func) (info->stream, "r%d", (int)rs1);
  147. if (func != MVTSF && func != MVFSF)
  148. (*info->fprintf_func) (info->stream, ",r%d", (int)rs2);
  149. }
  150. return (unsigned char) R_TYPE;
  151. }
  152. return (unsigned char) R_ERROR;
  153. }
  154. /* Process the memory read opcode. */
  155. static unsigned char
  156. dlx_load_type (struct disassemble_info* info)
  157. {
  158. struct _load_opcode
  159. {
  160. unsigned long opcode;
  161. char *name;
  162. }
  163. dlx_load_opcode[] =
  164. {
  165. { OPC(LHIOP), "lhi" }, /* Load HI to register. */
  166. { OPC(LBOP), "lb" }, /* load byte sign extended. */
  167. { OPC(LBUOP), "lbu" }, /* load byte unsigned. */
  168. { OPC(LSBUOP),"ldstbu"}, /* load store byte unsigned. */
  169. { OPC(LHOP), "lh" }, /* load halfword sign extended. */
  170. { OPC(LHUOP), "lhu" }, /* load halfword unsigned. */
  171. { OPC(LSHUOP),"ldsthu"}, /* load store halfword unsigned. */
  172. { OPC(LWOP), "lw" }, /* load word. */
  173. { OPC(LSWOP), "ldstw" } /* load store word. */
  174. };
  175. int dlx_load_opcode_num =
  176. (sizeof dlx_load_opcode) / (sizeof dlx_load_opcode[0]);
  177. int idx;
  178. for (idx = 0 ; idx < dlx_load_opcode_num; idx++)
  179. if (dlx_load_opcode[idx].opcode == opc)
  180. {
  181. if (opc == OPC (LHIOP))
  182. {
  183. (*info->fprintf_func) (info->stream, "%s", dlx_load_opcode[idx].name);
  184. operand_deliminator (info, dlx_load_opcode[idx].name);
  185. (*info->fprintf_func) (info->stream, "r%d,", (int)rs2);
  186. (*info->fprintf_func) (info->stream, "0x%04x", (int)imm16);
  187. }
  188. else
  189. {
  190. (*info->fprintf_func) (info->stream, "%s", dlx_load_opcode[idx].name);
  191. operand_deliminator (info, dlx_load_opcode[idx].name);
  192. (*info->fprintf_func) (info->stream, "r%d,", (int)rs2);
  193. (*info->fprintf_func) (info->stream, "0x%04x[r%d]", (int)imm16, (int)rs1);
  194. }
  195. return (unsigned char) ILD_TYPE;
  196. }
  197. return (unsigned char) NIL;
  198. }
  199. /* Process the memory store opcode. */
  200. static unsigned char
  201. dlx_store_type (struct disassemble_info* info)
  202. {
  203. struct _store_opcode
  204. {
  205. unsigned long opcode;
  206. char *name;
  207. }
  208. dlx_store_opcode[] =
  209. {
  210. { OPC(SBOP), "sb" }, /* Store byte. */
  211. { OPC(SHOP), "sh" }, /* Store halfword. */
  212. { OPC(SWOP), "sw" }, /* Store word. */
  213. };
  214. int dlx_store_opcode_num =
  215. (sizeof dlx_store_opcode) / (sizeof dlx_store_opcode[0]);
  216. int idx;
  217. for (idx = 0 ; idx < dlx_store_opcode_num; idx++)
  218. if (dlx_store_opcode[idx].opcode == opc)
  219. {
  220. (*info->fprintf_func) (info->stream, "%s", dlx_store_opcode[idx].name);
  221. operand_deliminator (info, dlx_store_opcode[idx].name);
  222. (*info->fprintf_func) (info->stream, "0x%04x[r%d],", (int)imm16, (int)rs1);
  223. (*info->fprintf_func) (info->stream, "r%d", (int)rs2);
  224. return (unsigned char) IST_TYPE;
  225. }
  226. return (unsigned char) NIL;
  227. }
  228. /* Process the Arithmetic and Logical I-TYPE opcode. */
  229. static unsigned char
  230. dlx_aluI_type (struct disassemble_info* info)
  231. {
  232. struct _aluI_opcode
  233. {
  234. unsigned long opcode;
  235. char *name;
  236. }
  237. dlx_aluI_opcode[] =
  238. {
  239. { OPC(ADDIOP), "addi" }, /* Store byte. */
  240. { OPC(ADDUIOP), "addui" }, /* Store halfword. */
  241. { OPC(SUBIOP), "subi" }, /* Store word. */
  242. { OPC(SUBUIOP), "subui" }, /* Store word. */
  243. { OPC(ANDIOP), "andi" }, /* Store word. */
  244. { OPC(ORIOP), "ori" }, /* Store word. */
  245. { OPC(XORIOP), "xori" }, /* Store word. */
  246. { OPC(SLLIOP), "slli" }, /* Store word. */
  247. { OPC(SRAIOP), "srai" }, /* Store word. */
  248. { OPC(SRLIOP), "srli" }, /* Store word. */
  249. { OPC(SEQIOP), "seqi" }, /* Store word. */
  250. { OPC(SNEIOP), "snei" }, /* Store word. */
  251. { OPC(SLTIOP), "slti" }, /* Store word. */
  252. { OPC(SGTIOP), "sgti" }, /* Store word. */
  253. { OPC(SLEIOP), "slei" }, /* Store word. */
  254. { OPC(SGEIOP), "sgei" }, /* Store word. */
  255. { OPC(SEQUIOP), "sequi" }, /* Store word. */
  256. { OPC(SNEUIOP), "sneui" }, /* Store word. */
  257. { OPC(SLTUIOP), "sltui" }, /* Store word. */
  258. { OPC(SGTUIOP), "sgtui" }, /* Store word. */
  259. { OPC(SLEUIOP), "sleui" }, /* Store word. */
  260. { OPC(SGEUIOP), "sgeui" }, /* Store word. */
  261. #if 0
  262. { OPC(MVTSOP), "mvts" }, /* Store word. */
  263. { OPC(MVFSOP), "mvfs" }, /* Store word. */
  264. #endif
  265. };
  266. int dlx_aluI_opcode_num =
  267. (sizeof dlx_aluI_opcode) / (sizeof dlx_aluI_opcode[0]);
  268. int idx;
  269. for (idx = 0 ; idx < dlx_aluI_opcode_num; idx++)
  270. if (dlx_aluI_opcode[idx].opcode == opc)
  271. {
  272. (*info->fprintf_func) (info->stream, "%s", dlx_aluI_opcode[idx].name);
  273. operand_deliminator (info, dlx_aluI_opcode[idx].name);
  274. (*info->fprintf_func) (info->stream, "r%d,", (int)rs2);
  275. (*info->fprintf_func) (info->stream, "r%d,", (int)rs1);
  276. (*info->fprintf_func) (info->stream, "0x%04x", (int)imm16);
  277. return (unsigned char) IAL_TYPE;
  278. }
  279. return (unsigned char) NIL;
  280. }
  281. /* Process the branch instruction. */
  282. static unsigned char
  283. dlx_br_type (struct disassemble_info* info)
  284. {
  285. struct _br_opcode
  286. {
  287. unsigned long opcode;
  288. char *name;
  289. }
  290. dlx_br_opcode[] =
  291. {
  292. { OPC(BEQOP), "beqz" }, /* Store byte. */
  293. { OPC(BNEOP), "bnez" } /* Store halfword. */
  294. };
  295. int dlx_br_opcode_num =
  296. (sizeof dlx_br_opcode) / (sizeof dlx_br_opcode[0]);
  297. int idx;
  298. for (idx = 0 ; idx < dlx_br_opcode_num; idx++)
  299. if (dlx_br_opcode[idx].opcode == opc)
  300. {
  301. if (imm16 & 0x00008000)
  302. imm16 |= 0xFFFF0000;
  303. imm16 += (current_insn_addr + 4);
  304. (*info->fprintf_func) (info->stream, "%s", dlx_br_opcode[idx].name);
  305. operand_deliminator (info, dlx_br_opcode[idx].name);
  306. (*info->fprintf_func) (info->stream, "r%d,", (int) rs1);
  307. (*info->fprintf_func) (info->stream, "0x%08x", (int) imm16);
  308. return (unsigned char) IBR_TYPE;
  309. }
  310. return (unsigned char) NIL;
  311. }
  312. /* Process the jump instruction. */
  313. static unsigned char
  314. dlx_jmp_type (struct disassemble_info* info)
  315. {
  316. struct _jmp_opcode
  317. {
  318. unsigned long opcode;
  319. char *name;
  320. }
  321. dlx_jmp_opcode[] =
  322. {
  323. { OPC(JOP), "j" }, /* Store byte. */
  324. { OPC(JALOP), "jal" }, /* Store halfword. */
  325. { OPC(BREAKOP), "break" }, /* Store halfword. */
  326. { OPC(TRAPOP), "trap" }, /* Store halfword. */
  327. { OPC(RFEOP), "rfe" } /* Store halfword. */
  328. };
  329. int dlx_jmp_opcode_num =
  330. (sizeof dlx_jmp_opcode) / (sizeof dlx_jmp_opcode[0]);
  331. int idx;
  332. for (idx = 0 ; idx < dlx_jmp_opcode_num; idx++)
  333. if (dlx_jmp_opcode[idx].opcode == opc)
  334. {
  335. if (imm26 & 0x02000000)
  336. imm26 |= 0xFC000000;
  337. imm26 += (current_insn_addr + 4);
  338. (*info->fprintf_func) (info->stream, "%s", dlx_jmp_opcode[idx].name);
  339. operand_deliminator (info, dlx_jmp_opcode[idx].name);
  340. (*info->fprintf_func) (info->stream, "0x%08x", (int)imm26);
  341. return (unsigned char) IJ_TYPE;
  342. }
  343. return (unsigned char) NIL;
  344. }
  345. /* Process the jump register instruction. */
  346. static unsigned char
  347. dlx_jr_type (struct disassemble_info* info)
  348. {
  349. struct _jr_opcode
  350. {
  351. unsigned long opcode;
  352. char *name;
  353. }
  354. dlx_jr_opcode[] =
  355. {
  356. { OPC(JROP), "jr" }, /* Store byte. */
  357. { OPC(JALROP), "jalr" } /* Store halfword. */
  358. };
  359. int dlx_jr_opcode_num =
  360. (sizeof dlx_jr_opcode) / (sizeof dlx_jr_opcode[0]);
  361. int idx;
  362. for (idx = 0 ; idx < dlx_jr_opcode_num; idx++)
  363. if (dlx_jr_opcode[idx].opcode == opc)
  364. {
  365. (*info->fprintf_func) (info->stream, "%s", dlx_jr_opcode[idx].name);
  366. operand_deliminator (info, dlx_jr_opcode[idx].name);
  367. (*info->fprintf_func) (info->stream, "r%d", (int)rs1);
  368. return (unsigned char) IJR_TYPE;
  369. }
  370. return (unsigned char) NIL;
  371. }
  372. typedef unsigned char (* dlx_insn) (struct disassemble_info *);
  373. /* This is the main DLX insn handling routine. */
  374. int
  375. print_insn_dlx (bfd_vma memaddr, struct disassemble_info* info)
  376. {
  377. bfd_byte buffer[4];
  378. int insn_idx;
  379. unsigned long insn_word;
  380. dlx_insn dlx_insn_type[] =
  381. {
  382. dlx_r_type,
  383. dlx_load_type,
  384. dlx_store_type,
  385. dlx_aluI_type,
  386. dlx_br_type,
  387. dlx_jmp_type,
  388. dlx_jr_type,
  389. (dlx_insn) NULL
  390. };
  391. int dlx_insn_type_num = ((sizeof dlx_insn_type) / (sizeof (dlx_insn))) - 1;
  392. int status =
  393. (*info->read_memory_func) (memaddr, (bfd_byte *) &buffer[0], 4, info);
  394. if (status != 0)
  395. {
  396. (*info->memory_error_func) (status, memaddr, info);
  397. return -1;
  398. }
  399. /* Now decode the insn */
  400. insn_word = bfd_getb32 (buffer);
  401. opc = dlx_get_opcode (insn_word);
  402. rs1 = dlx_get_rs1 (insn_word);
  403. rs2 = dlx_get_rs2 (insn_word);
  404. rd = dlx_get_rdR (insn_word);
  405. func = dlx_get_func (insn_word);
  406. imm16= dlx_get_imm16 (insn_word);
  407. imm26= dlx_get_imm26 (insn_word);
  408. #if 0
  409. printf ("print_insn_big_dlx: opc = 0x%02x\n"
  410. " rs1 = 0x%02x\n"
  411. " rs2 = 0x%02x\n"
  412. " rd = 0x%02x\n"
  413. " func = 0x%08x\n"
  414. " imm16 = 0x%08x\n"
  415. " imm26 = 0x%08x\n",
  416. opc, rs1, rs2, rd, func, imm16, imm26);
  417. #endif
  418. /* Scan through all the insn type and print the insn out. */
  419. current_insn_addr = (unsigned long) memaddr;
  420. for (insn_idx = 0; dlx_insn_type[insn_idx] != 0x0; insn_idx++)
  421. switch ((dlx_insn_type[insn_idx]) (info))
  422. {
  423. /* Found the correct opcode */
  424. case R_TYPE:
  425. case ILD_TYPE:
  426. case IST_TYPE:
  427. case IAL_TYPE:
  428. case IBR_TYPE:
  429. case IJ_TYPE:
  430. case IJR_TYPE:
  431. return 4;
  432. /* Wrong insn type check next one. */
  433. default:
  434. case NIL:
  435. continue;
  436. /* All rest of the return code are not recongnized, treat it as error */
  437. /* we should never get here, I hope! */
  438. case R_ERROR:
  439. return -1;
  440. }
  441. if (insn_idx == dlx_insn_type_num)
  442. /* Well, does not recoganize this opcode. */
  443. (*info->fprintf_func) (info->stream, "<%s>", "Unrecognized Opcode");
  444. return 4;
  445. }