rx-dis.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /* Disassembler code for Renesas RX.
  2. Copyright (C) 2008-2022 Free Software Foundation, Inc.
  3. Contributed by Red Hat.
  4. Written by DJ Delorie.
  5. This file is part of the GNU opcodes library.
  6. This library is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 3, or (at your option)
  9. any later version.
  10. It is distributed in the hope that it will be useful, but WITHOUT
  11. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  12. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  13. License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  17. MA 02110-1301, USA. */
  18. #include "sysdep.h"
  19. #include <stdio.h>
  20. #include "bfd.h"
  21. #include "dis-asm.h"
  22. #include "opcode/rx.h"
  23. #include "libiberty.h"
  24. #include "opintl.h"
  25. #include <setjmp.h>
  26. typedef struct
  27. {
  28. bfd_vma pc;
  29. disassemble_info * dis;
  30. } RX_Data;
  31. struct private
  32. {
  33. OPCODES_SIGJMP_BUF bailout;
  34. };
  35. static int
  36. rx_get_byte (void * vdata)
  37. {
  38. bfd_byte buf[1];
  39. RX_Data *rx_data = (RX_Data *) vdata;
  40. int status;
  41. status = rx_data->dis->read_memory_func (rx_data->pc,
  42. buf,
  43. 1,
  44. rx_data->dis);
  45. if (status != 0)
  46. {
  47. struct private *priv = (struct private *) rx_data->dis->private_data;
  48. rx_data->dis->memory_error_func (status, rx_data->pc,
  49. rx_data->dis);
  50. OPCODES_SIGLONGJMP (priv->bailout, 1);
  51. }
  52. rx_data->pc ++;
  53. return buf[0];
  54. }
  55. static char const * size_names[RX_MAX_SIZE] =
  56. {
  57. "", ".b", ".ub", ".b", ".w", ".uw", ".w", ".a", ".l", "", "<error>"
  58. };
  59. static char const * opsize_names[RX_MAX_SIZE] =
  60. {
  61. "", ".b", ".b", ".b", ".w", ".w", ".w", ".a", ".l", ".d", "<error>"
  62. };
  63. static char const * register_names[] =
  64. {
  65. /* General registers. */
  66. "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  67. "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
  68. /* Control registers. */
  69. "psw", "pc", "usp", "fpsw", NULL, NULL, NULL, NULL,
  70. "bpsw", "bpc", "isp", "fintv", "intb", "extb", NULL, NULL,
  71. "a0", "a1", NULL, NULL, NULL, NULL, NULL, NULL,
  72. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  73. };
  74. static char const * condition_names[] =
  75. {
  76. /* Condition codes. */
  77. "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n",
  78. "ge", "lt", "gt", "le", "o", "no", "<invalid>", "<invalid>"
  79. };
  80. static const char * flag_names[] =
  81. {
  82. "c", "z", "s", "o", "", "", "", "",
  83. "", "", "", "", "", "", "", "",
  84. "i", "u", "", "", "", "", "", "",
  85. "", "", "", "", "", "", "", ""
  86. };
  87. static const char * double_register_names[] =
  88. {
  89. "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7",
  90. "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15"
  91. };
  92. static const char * double_register_high_names[] =
  93. {
  94. "drh0", "drh1", "drh2", "drh3", "drh4", "drh5", "drh6", "drh7",
  95. "drh8", "drh9", "drh10", "drh11", "drh12", "drh13", "drh14", "drh15"
  96. };
  97. static const char * double_register_low_names[] =
  98. {
  99. "drl0", "drl1", "drl2", "drl3", "drl4", "drl5", "drl6", "drl7",
  100. "drl8", "drl9", "drl10", "drl11", "drl12", "drl13", "drl14", "drl15"
  101. };
  102. static const char * double_control_register_names[] =
  103. {
  104. "dpsw", "dcmr", "decnt", "depc"
  105. };
  106. static const char * double_condition_names[] =
  107. {
  108. "", "un", "eq", "", "lt", "", "le"
  109. };
  110. static inline const char *
  111. get_register_name (unsigned int reg)
  112. {
  113. if (reg < ARRAY_SIZE (register_names))
  114. return register_names[reg];
  115. return _("<invalid register number>");
  116. }
  117. static inline const char *
  118. get_condition_name (unsigned int cond)
  119. {
  120. if (cond < ARRAY_SIZE (condition_names))
  121. return condition_names[cond];
  122. return _("<invalid condition code>");
  123. }
  124. static inline const char *
  125. get_flag_name (unsigned int flag)
  126. {
  127. if (flag < ARRAY_SIZE (flag_names))
  128. return flag_names[flag];
  129. return _("<invalid flag>");
  130. }
  131. static inline const char *
  132. get_double_register_name (unsigned int reg)
  133. {
  134. if (reg < ARRAY_SIZE (double_register_names))
  135. return double_register_names[reg];
  136. return _("<invalid register number>");
  137. }
  138. static inline const char *
  139. get_double_register_high_name (unsigned int reg)
  140. {
  141. if (reg < ARRAY_SIZE (double_register_high_names))
  142. return double_register_high_names[reg];
  143. return _("<invalid register number>");
  144. }
  145. static inline const char *
  146. get_double_register_low_name (unsigned int reg)
  147. {
  148. if (reg < ARRAY_SIZE (double_register_low_names))
  149. return double_register_low_names[reg];
  150. return _("<invalid register number>");
  151. }
  152. static inline const char *
  153. get_double_control_register_name (unsigned int reg)
  154. {
  155. if (reg < ARRAY_SIZE (double_control_register_names))
  156. return double_control_register_names[reg];
  157. return _("<invalid register number>");
  158. }
  159. static inline const char *
  160. get_double_condition_name (unsigned int cond)
  161. {
  162. if (cond < ARRAY_SIZE (double_condition_names))
  163. return double_condition_names[cond];
  164. return _("<invalid condition code>");
  165. }
  166. static inline const char *
  167. get_opsize_name (unsigned int opsize)
  168. {
  169. if (opsize < ARRAY_SIZE (opsize_names))
  170. return opsize_names[opsize];
  171. return _("<invalid opsize>");
  172. }
  173. static inline const char *
  174. get_size_name (unsigned int size)
  175. {
  176. if (size < ARRAY_SIZE (size_names))
  177. return size_names[size];
  178. return _("<invalid size>");
  179. }
  180. int
  181. print_insn_rx (bfd_vma addr, disassemble_info * dis)
  182. {
  183. int rv;
  184. RX_Data rx_data;
  185. RX_Opcode_Decoded opcode;
  186. const char * s;
  187. struct private priv;
  188. dis->private_data = (PTR) &priv;
  189. rx_data.pc = addr;
  190. rx_data.dis = dis;
  191. if (OPCODES_SIGSETJMP (priv.bailout) != 0)
  192. {
  193. /* Error return. */
  194. return -1;
  195. }
  196. rv = rx_decode_opcode (addr, &opcode, rx_get_byte, &rx_data);
  197. dis->bytes_per_line = 10;
  198. #define PR (dis->fprintf_func)
  199. #define PS (dis->stream)
  200. #define PC(c) PR (PS, "%c", c)
  201. /* Detect illegal instructions. */
  202. if (opcode.op[0].size == RX_Bad_Size
  203. || register_names [opcode.op[0].reg] == NULL
  204. || register_names [opcode.op[1].reg] == NULL
  205. || register_names [opcode.op[2].reg] == NULL)
  206. {
  207. bfd_byte buf[10];
  208. int i;
  209. PR (PS, ".byte ");
  210. rx_data.dis->read_memory_func (rx_data.pc - rv, buf, rv, rx_data.dis);
  211. for (i = 0 ; i < rv; i++)
  212. PR (PS, "0x%02x ", buf[i]);
  213. return rv;
  214. }
  215. for (s = opcode.syntax; *s; s++)
  216. {
  217. if (*s != '%')
  218. {
  219. PC (*s);
  220. }
  221. else
  222. {
  223. RX_Opcode_Operand * oper;
  224. int do_size = 0;
  225. int do_hex = 0;
  226. int do_addr = 0;
  227. s ++;
  228. if (*s == 'S')
  229. {
  230. do_size = 1;
  231. s++;
  232. }
  233. if (*s == 'x')
  234. {
  235. do_hex = 1;
  236. s++;
  237. }
  238. if (*s == 'a')
  239. {
  240. do_addr = 1;
  241. s++;
  242. }
  243. switch (*s)
  244. {
  245. case '%':
  246. PC ('%');
  247. break;
  248. case 's':
  249. PR (PS, "%s", get_opsize_name (opcode.size));
  250. break;
  251. case 'b':
  252. s ++;
  253. if (*s == 'f')
  254. {
  255. int imm = opcode.op[2].addend;
  256. int slsb, dlsb, width;
  257. dlsb = (imm >> 5) & 0x1f;
  258. slsb = (imm & 0x1f);
  259. slsb = (slsb >= 0x10?(slsb ^ 0x1f) + 1:slsb);
  260. slsb = dlsb - slsb;
  261. slsb = (slsb < 0?-slsb:slsb);
  262. width = ((imm >> 10) & 0x1f) - dlsb;
  263. PR (PS, "#%d, #%d, #%d, %s, %s",
  264. slsb, dlsb, width,
  265. get_register_name (opcode.op[1].reg),
  266. get_register_name (opcode.op[0].reg));
  267. }
  268. break;
  269. case '0':
  270. case '1':
  271. case '2':
  272. oper = opcode.op + (*s - '0');
  273. if (do_size)
  274. {
  275. if (oper->type == RX_Operand_Indirect || oper->type == RX_Operand_Zero_Indirect)
  276. PR (PS, "%s", get_size_name (oper->size));
  277. }
  278. else
  279. switch (oper->type)
  280. {
  281. case RX_Operand_Immediate:
  282. if (do_addr)
  283. dis->print_address_func (oper->addend, dis);
  284. else if (do_hex
  285. || oper->addend > 999
  286. || oper->addend < -999)
  287. PR (PS, "%#x", oper->addend);
  288. else
  289. PR (PS, "%d", oper->addend);
  290. break;
  291. case RX_Operand_Register:
  292. case RX_Operand_TwoReg:
  293. PR (PS, "%s", get_register_name (oper->reg));
  294. break;
  295. case RX_Operand_Indirect:
  296. PR (PS, "%d[%s]", oper->addend, get_register_name (oper->reg));
  297. break;
  298. case RX_Operand_Zero_Indirect:
  299. PR (PS, "[%s]", get_register_name (oper->reg));
  300. break;
  301. case RX_Operand_Postinc:
  302. PR (PS, "[%s+]", get_register_name (oper->reg));
  303. break;
  304. case RX_Operand_Predec:
  305. PR (PS, "[-%s]", get_register_name (oper->reg));
  306. break;
  307. case RX_Operand_Condition:
  308. PR (PS, "%s", get_condition_name (oper->reg));
  309. break;
  310. case RX_Operand_Flag:
  311. PR (PS, "%s", get_flag_name (oper->reg));
  312. break;
  313. case RX_Operand_DoubleReg:
  314. PR (PS, "%s", get_double_register_name (oper->reg));
  315. break;
  316. case RX_Operand_DoubleRegH:
  317. PR (PS, "%s", get_double_register_high_name (oper->reg));
  318. break;
  319. case RX_Operand_DoubleRegL:
  320. PR (PS, "%s", get_double_register_low_name (oper->reg));
  321. break;
  322. case RX_Operand_DoubleCReg:
  323. PR (PS, "%s", get_double_control_register_name (oper->reg));
  324. break;
  325. case RX_Operand_DoubleCond:
  326. PR (PS, "%s", get_double_condition_name (oper->reg));
  327. break;
  328. default:
  329. PR (PS, "[???]");
  330. break;
  331. }
  332. }
  333. }
  334. }
  335. return rv;
  336. }