avr-dis.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /* Disassemble AVR instructions.
  2. Copyright (C) 1999-2022 Free Software Foundation, Inc.
  3. Contributed by Denis Chertykov <denisc@overta.ru>
  4. This file is part of libopcodes.
  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 <assert.h>
  19. #include "disassemble.h"
  20. #include "opintl.h"
  21. #include "libiberty.h"
  22. #include <stdint.h>
  23. struct avr_opcodes_s
  24. {
  25. char *name;
  26. char *constraints;
  27. char *opcode;
  28. int insn_size; /* In words. */
  29. int isa;
  30. unsigned int bin_opcode;
  31. };
  32. #define AVR_INSN(NAME, CONSTR, OPCODE, SIZE, ISA, BIN) \
  33. {#NAME, CONSTR, OPCODE, SIZE, ISA, BIN},
  34. const struct avr_opcodes_s avr_opcodes[] =
  35. {
  36. #include "opcode/avr.h"
  37. {NULL, NULL, NULL, 0, 0, 0}
  38. };
  39. static const char * comment_start = "0x";
  40. static int
  41. avr_operand (unsigned int insn,
  42. unsigned int insn2,
  43. unsigned int pc,
  44. int constraint,
  45. char * opcode_str,
  46. char * buf,
  47. char * comment,
  48. int regs,
  49. int * sym,
  50. bfd_vma * sym_addr,
  51. disassemble_info * info)
  52. {
  53. int ok = 1;
  54. *sym = 0;
  55. switch (constraint)
  56. {
  57. /* Any register operand. */
  58. case 'r':
  59. if (regs)
  60. insn = (insn & 0xf) | ((insn & 0x0200) >> 5); /* Source register. */
  61. else
  62. insn = (insn & 0x01f0) >> 4; /* Destination register. */
  63. sprintf (buf, "r%d", insn);
  64. break;
  65. case 'd':
  66. if (regs)
  67. sprintf (buf, "r%d", 16 + (insn & 0xf));
  68. else
  69. sprintf (buf, "r%d", 16 + ((insn & 0xf0) >> 4));
  70. break;
  71. case 'w':
  72. sprintf (buf, "r%d", 24 + ((insn & 0x30) >> 3));
  73. break;
  74. case 'a':
  75. if (regs)
  76. sprintf (buf, "r%d", 16 + (insn & 7));
  77. else
  78. sprintf (buf, "r%d", 16 + ((insn >> 4) & 7));
  79. break;
  80. case 'v':
  81. if (regs)
  82. sprintf (buf, "r%d", (insn & 0xf) * 2);
  83. else
  84. sprintf (buf, "r%d", ((insn & 0xf0) >> 3));
  85. break;
  86. case 'e':
  87. {
  88. char *xyz;
  89. switch (insn & 0x100f)
  90. {
  91. case 0x0000: xyz = "Z"; break;
  92. case 0x1001: xyz = "Z+"; break;
  93. case 0x1002: xyz = "-Z"; break;
  94. case 0x0008: xyz = "Y"; break;
  95. case 0x1009: xyz = "Y+"; break;
  96. case 0x100a: xyz = "-Y"; break;
  97. case 0x100c: xyz = "X"; break;
  98. case 0x100d: xyz = "X+"; break;
  99. case 0x100e: xyz = "-X"; break;
  100. default: xyz = "??"; ok = 0;
  101. }
  102. strcpy (buf, xyz);
  103. if (AVR_UNDEF_P (insn))
  104. sprintf (comment, _("undefined"));
  105. }
  106. break;
  107. case 'z':
  108. *buf++ = 'Z';
  109. /* Check for post-increment. */
  110. char *s;
  111. for (s = opcode_str; *s; ++s)
  112. {
  113. if (*s == '+')
  114. {
  115. if (insn & (1 << (15 - (s - opcode_str))))
  116. *buf++ = '+';
  117. break;
  118. }
  119. }
  120. *buf = '\0';
  121. if (AVR_UNDEF_P (insn))
  122. sprintf (comment, _("undefined"));
  123. break;
  124. case 'b':
  125. {
  126. unsigned int x;
  127. x = (insn & 7);
  128. x |= (insn >> 7) & (3 << 3);
  129. x |= (insn >> 8) & (1 << 5);
  130. if (insn & 0x8)
  131. *buf++ = 'Y';
  132. else
  133. *buf++ = 'Z';
  134. sprintf (buf, "+%d", x);
  135. sprintf (comment, "0x%02x", x);
  136. }
  137. break;
  138. case 'h':
  139. *sym = 1;
  140. *sym_addr = ((((insn & 1) | ((insn & 0x1f0) >> 3)) << 16) | insn2) * 2;
  141. /* See PR binutils/2454. Ideally we would like to display the hex
  142. value of the address only once, but this would mean recoding
  143. objdump_print_address() which would affect many targets. */
  144. sprintf (buf, "%#lx", (unsigned long) *sym_addr);
  145. strcpy (comment, comment_start);
  146. info->insn_info_valid = 1;
  147. info->insn_type = dis_jsr;
  148. info->target = *sym_addr;
  149. break;
  150. case 'L':
  151. {
  152. int rel_addr = (((insn & 0xfff) ^ 0x800) - 0x800) * 2;
  153. sprintf (buf, ".%+-8d", rel_addr);
  154. *sym = 1;
  155. *sym_addr = pc + 2 + rel_addr;
  156. strcpy (comment, comment_start);
  157. info->insn_info_valid = 1;
  158. info->insn_type = dis_branch;
  159. info->target = *sym_addr;
  160. }
  161. break;
  162. case 'l':
  163. {
  164. int rel_addr = ((((insn >> 3) & 0x7f) ^ 0x40) - 0x40) * 2;
  165. sprintf (buf, ".%+-8d", rel_addr);
  166. *sym = 1;
  167. *sym_addr = pc + 2 + rel_addr;
  168. strcpy (comment, comment_start);
  169. info->insn_info_valid = 1;
  170. info->insn_type = dis_condbranch;
  171. info->target = *sym_addr;
  172. }
  173. break;
  174. case 'i':
  175. {
  176. unsigned int val = insn2 | 0x800000;
  177. *sym = 1;
  178. *sym_addr = val;
  179. sprintf (buf, "0x%04X", insn2);
  180. strcpy (comment, comment_start);
  181. }
  182. break;
  183. case 'j':
  184. {
  185. unsigned int val = ((insn & 0xf) | ((insn & 0x600) >> 5)
  186. | ((insn & 0x100) >> 2));
  187. if ((insn & 0x100) == 0)
  188. val |= 0x80;
  189. *sym = 1;
  190. *sym_addr = val | 0x800000;
  191. sprintf (buf, "0x%02x", val);
  192. strcpy (comment, comment_start);
  193. }
  194. break;
  195. case 'M':
  196. sprintf (buf, "0x%02X", ((insn & 0xf00) >> 4) | (insn & 0xf));
  197. sprintf (comment, "%d", ((insn & 0xf00) >> 4) | (insn & 0xf));
  198. break;
  199. case 'n':
  200. sprintf (buf, "??");
  201. /* xgettext:c-format */
  202. opcodes_error_handler (_("internal disassembler error"));
  203. ok = 0;
  204. break;
  205. case 'K':
  206. {
  207. unsigned int x;
  208. x = (insn & 0xf) | ((insn >> 2) & 0x30);
  209. sprintf (buf, "0x%02x", x);
  210. sprintf (comment, "%d", x);
  211. }
  212. break;
  213. case 's':
  214. sprintf (buf, "%d", insn & 7);
  215. break;
  216. case 'S':
  217. sprintf (buf, "%d", (insn >> 4) & 7);
  218. break;
  219. case 'P':
  220. {
  221. unsigned int x;
  222. x = (insn & 0xf);
  223. x |= (insn >> 5) & 0x30;
  224. sprintf (buf, "0x%02x", x);
  225. sprintf (comment, "%d", x);
  226. }
  227. break;
  228. case 'p':
  229. {
  230. unsigned int x;
  231. x = (insn >> 3) & 0x1f;
  232. sprintf (buf, "0x%02x", x);
  233. sprintf (comment, "%d", x);
  234. }
  235. break;
  236. case 'E':
  237. sprintf (buf, "%d", (insn >> 4) & 15);
  238. break;
  239. case '?':
  240. *buf = '\0';
  241. break;
  242. default:
  243. sprintf (buf, "??");
  244. /* xgettext:c-format */
  245. opcodes_error_handler (_("unknown constraint `%c'"), constraint);
  246. ok = 0;
  247. }
  248. return ok;
  249. }
  250. /* Read the opcode from ADDR. Return 0 in success and save opcode
  251. in *INSN, otherwise, return -1. */
  252. static int
  253. avrdis_opcode (bfd_vma addr, disassemble_info *info, uint16_t *insn)
  254. {
  255. bfd_byte buffer[2];
  256. int status;
  257. status = info->read_memory_func (addr, buffer, 2, info);
  258. if (status == 0)
  259. {
  260. *insn = bfd_getl16 (buffer);
  261. return 0;
  262. }
  263. info->memory_error_func (status, addr, info);
  264. return -1;
  265. }
  266. int
  267. print_insn_avr (bfd_vma addr, disassemble_info *info)
  268. {
  269. uint16_t insn, insn2;
  270. const struct avr_opcodes_s *opcode;
  271. static unsigned int *maskptr;
  272. void *stream = info->stream;
  273. fprintf_ftype prin = info->fprintf_func;
  274. static unsigned int *avr_bin_masks;
  275. static int initialized;
  276. int cmd_len = 2;
  277. int ok = 0;
  278. char op1[20], op2[20], comment1[40], comment2[40];
  279. int sym_op1 = 0, sym_op2 = 0;
  280. bfd_vma sym_addr1, sym_addr2;
  281. /* Clear instruction information field. */
  282. info->insn_info_valid = 0;
  283. info->branch_delay_insns = 0;
  284. info->data_size = 0;
  285. info->insn_type = dis_noninsn;
  286. info->target = 0;
  287. info->target2 = 0;
  288. if (!initialized)
  289. {
  290. unsigned int nopcodes;
  291. /* PR 4045: Try to avoid duplicating the 0x prefix that
  292. objdump_print_addr() will put on addresses when there
  293. is no symbol table available. */
  294. if (info->symtab_size == 0)
  295. comment_start = " ";
  296. nopcodes = sizeof (avr_opcodes) / sizeof (struct avr_opcodes_s);
  297. avr_bin_masks = xmalloc (nopcodes * sizeof (unsigned int));
  298. for (opcode = avr_opcodes, maskptr = avr_bin_masks;
  299. opcode->name;
  300. opcode++, maskptr++)
  301. {
  302. char * s;
  303. unsigned int bin = 0;
  304. unsigned int mask = 0;
  305. for (s = opcode->opcode; *s; ++s)
  306. {
  307. bin <<= 1;
  308. mask <<= 1;
  309. bin |= (*s == '1');
  310. mask |= (*s == '1' || *s == '0');
  311. }
  312. assert (s - opcode->opcode == 16);
  313. assert (opcode->bin_opcode == bin);
  314. *maskptr = mask;
  315. }
  316. initialized = 1;
  317. }
  318. if (avrdis_opcode (addr, info, &insn) != 0)
  319. return -1;
  320. for (opcode = avr_opcodes, maskptr = avr_bin_masks;
  321. opcode->name;
  322. opcode++, maskptr++)
  323. {
  324. if ((opcode->isa == AVR_ISA_TINY) && (info->mach != bfd_mach_avrtiny))
  325. continue;
  326. if ((insn & *maskptr) == opcode->bin_opcode)
  327. break;
  328. }
  329. /* Special case: disassemble `ldd r,b+0' as `ld r,b', and
  330. `std b+0,r' as `st b,r' (next entry in the table). */
  331. if (AVR_DISP0_P (insn))
  332. opcode++;
  333. op1[0] = 0;
  334. op2[0] = 0;
  335. comment1[0] = 0;
  336. comment2[0] = 0;
  337. if (opcode->name)
  338. {
  339. char *constraints = opcode->constraints;
  340. char *opcode_str = opcode->opcode;
  341. insn2 = 0;
  342. ok = 1;
  343. if (opcode->insn_size > 1)
  344. {
  345. if (avrdis_opcode (addr + 2, info, &insn2) != 0)
  346. return -1;
  347. cmd_len = 4;
  348. }
  349. if (*constraints && *constraints != '?')
  350. {
  351. int regs = REGISTER_P (*constraints);
  352. ok = avr_operand (insn, insn2, addr, *constraints, opcode_str, op1,
  353. comment1, 0, &sym_op1, &sym_addr1, info);
  354. if (ok && *(++constraints) == ',')
  355. ok = avr_operand (insn, insn2, addr, *(++constraints), opcode_str,
  356. op2, *comment1 ? comment2 : comment1, regs,
  357. &sym_op2, &sym_addr2, info);
  358. }
  359. }
  360. if (!ok)
  361. {
  362. /* Unknown opcode, or invalid combination of operands. */
  363. sprintf (op1, "0x%04x", insn);
  364. op2[0] = 0;
  365. sprintf (comment1, "????");
  366. comment2[0] = 0;
  367. }
  368. (*prin) (stream, "%s", ok ? opcode->name : ".word");
  369. if (*op1)
  370. (*prin) (stream, "\t%s", op1);
  371. if (*op2)
  372. (*prin) (stream, ", %s", op2);
  373. if (*comment1)
  374. (*prin) (stream, "\t; %s", comment1);
  375. if (sym_op1)
  376. info->print_address_func (sym_addr1, info);
  377. if (*comment2)
  378. (*prin) (stream, " %s", comment2);
  379. if (sym_op2)
  380. info->print_address_func (sym_addr2, info);
  381. return cmd_len;
  382. }