s12z-dis.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. /* s12z-dis.c -- Freescale S12Z disassembly
  2. Copyright (C) 2018-2022 Free Software Foundation, Inc.
  3. This file is part of the GNU opcodes library.
  4. This library is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3, or (at your option)
  7. any later version.
  8. It is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  11. License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  15. MA 02110-1301, USA. */
  16. #include "sysdep.h"
  17. #include <stdio.h>
  18. #include <stdint.h>
  19. #include <stdbool.h>
  20. #include <assert.h>
  21. #include "opcode/s12z.h"
  22. #include "bfd.h"
  23. #include "dis-asm.h"
  24. #include "disassemble.h"
  25. #include "s12z-opc.h"
  26. #include "opintl.h"
  27. struct mem_read_abstraction
  28. {
  29. struct mem_read_abstraction_base base;
  30. bfd_vma memaddr;
  31. struct disassemble_info* info;
  32. };
  33. static void
  34. advance (struct mem_read_abstraction_base *b)
  35. {
  36. struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
  37. mra->memaddr ++;
  38. }
  39. static bfd_vma
  40. posn (struct mem_read_abstraction_base *b)
  41. {
  42. struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
  43. return mra->memaddr;
  44. }
  45. static int
  46. abstract_read_memory (struct mem_read_abstraction_base *b,
  47. int offset,
  48. size_t n, bfd_byte *bytes)
  49. {
  50. struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
  51. int status = (*mra->info->read_memory_func) (mra->memaddr + offset,
  52. bytes, n, mra->info);
  53. if (status != 0)
  54. (*mra->info->memory_error_func) (status, mra->memaddr + offset,
  55. mra->info);
  56. return status != 0 ? -1 : 0;
  57. }
  58. /* Start of disassembly file. */
  59. const struct reg registers[S12Z_N_REGISTERS] =
  60. {
  61. {"d2", 2},
  62. {"d3", 2},
  63. {"d4", 2},
  64. {"d5", 2},
  65. {"d0", 1},
  66. {"d1", 1},
  67. {"d6", 4},
  68. {"d7", 4},
  69. {"x", 3},
  70. {"y", 3},
  71. {"s", 3},
  72. {"p", 3},
  73. {"cch", 1},
  74. {"ccl", 1},
  75. {"ccw", 2}
  76. };
  77. static const char *mnemonics[] =
  78. {
  79. "!!invalid!!",
  80. "psh",
  81. "pul",
  82. "tbne", "tbeq", "tbpl", "tbmi", "tbgt", "tble",
  83. "dbne", "dbeq", "dbpl", "dbmi", "dbgt", "dble",
  84. "sex",
  85. "exg",
  86. "lsl", "lsr",
  87. "asl", "asr",
  88. "rol", "ror",
  89. "bfins", "bfext",
  90. "trap",
  91. "ld",
  92. "st",
  93. "cmp",
  94. "stop",
  95. "wai",
  96. "sys",
  97. "minu",
  98. "mins",
  99. "maxu",
  100. "maxs",
  101. "abs",
  102. "adc",
  103. "bit",
  104. "sbc",
  105. "rti",
  106. "clb",
  107. "eor",
  108. "sat",
  109. "nop",
  110. "bgnd",
  111. "brclr",
  112. "brset",
  113. "rts",
  114. "lea",
  115. "mov",
  116. "bra",
  117. "bsr",
  118. "bhi",
  119. "bls",
  120. "bcc",
  121. "bcs",
  122. "bne",
  123. "beq",
  124. "bvc",
  125. "bvs",
  126. "bpl",
  127. "bmi",
  128. "bge",
  129. "blt",
  130. "bgt",
  131. "ble",
  132. "inc",
  133. "clr",
  134. "dec",
  135. "add",
  136. "sub",
  137. "and",
  138. "or",
  139. "tfr",
  140. "jmp",
  141. "jsr",
  142. "com",
  143. "andcc",
  144. "neg",
  145. "orcc",
  146. "bclr",
  147. "bset",
  148. "btgl",
  149. "swi",
  150. "mulu",
  151. "divu",
  152. "modu",
  153. "macu",
  154. "qmulu",
  155. "muls",
  156. "divs",
  157. "mods",
  158. "macs",
  159. "qmuls",
  160. NULL
  161. };
  162. static void
  163. operand_separator (struct disassemble_info *info)
  164. {
  165. if ((info->flags & 0x2))
  166. (*info->fprintf_func) (info->stream, ",");
  167. (*info->fprintf_func) (info->stream, " ");
  168. info->flags |= 0x2;
  169. }
  170. /* Render the symbol name whose value is ADDR + BASE or the adddress itself if
  171. there is no symbol. If BASE is non zero, then the a PC relative adddress is
  172. assumend (ie BASE is the value in the PC. */
  173. static void
  174. decode_possible_symbol (bfd_vma addr, bfd_vma base,
  175. struct disassemble_info *info, bool relative)
  176. {
  177. const char *fmt = relative ? "*%+" BFD_VMA_FMT "d" : "%" BFD_VMA_FMT "d";
  178. asymbol *sym = info->symbol_at_address_func (addr + base, info);
  179. if (!sym)
  180. (*info->fprintf_func) (info->stream, fmt, addr);
  181. else
  182. (*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
  183. }
  184. /* Emit the disassembled text for OPR */
  185. static void
  186. opr_emit_disassembly (const struct operand *opr,
  187. struct disassemble_info *info)
  188. {
  189. operand_separator (info);
  190. switch (opr->cl)
  191. {
  192. case OPND_CL_IMMEDIATE:
  193. (*info->fprintf_func) (info->stream, "#%d",
  194. ((struct immediate_operand *) opr)->value);
  195. break;
  196. case OPND_CL_REGISTER:
  197. {
  198. int r = ((struct register_operand*) opr)->reg;
  199. if (r < 0 || r >= S12Z_N_REGISTERS)
  200. (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
  201. else
  202. (*info->fprintf_func) (info->stream, "%s", registers[r].name);
  203. }
  204. break;
  205. case OPND_CL_REGISTER_ALL16:
  206. (*info->fprintf_func) (info->stream, "%s", "ALL16b");
  207. break;
  208. case OPND_CL_REGISTER_ALL:
  209. (*info->fprintf_func) (info->stream, "%s", "ALL");
  210. break;
  211. case OPND_CL_BIT_FIELD:
  212. (*info->fprintf_func) (info->stream, "#%d:%d",
  213. ((struct bitfield_operand*)opr)->width,
  214. ((struct bitfield_operand*)opr)->offset);
  215. break;
  216. case OPND_CL_SIMPLE_MEMORY:
  217. {
  218. struct simple_memory_operand *mo =
  219. (struct simple_memory_operand *) opr;
  220. decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
  221. }
  222. break;
  223. case OPND_CL_MEMORY:
  224. {
  225. int used_reg = 0;
  226. struct memory_operand *mo = (struct memory_operand *) opr;
  227. (*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
  228. const char *fmt;
  229. assert (mo->mutation == OPND_RM_NONE || mo->n_regs == 1);
  230. switch (mo->mutation)
  231. {
  232. case OPND_RM_PRE_DEC:
  233. fmt = "-%s";
  234. break;
  235. case OPND_RM_PRE_INC:
  236. fmt = "+%s";
  237. break;
  238. case OPND_RM_POST_DEC:
  239. fmt = "%s-";
  240. break;
  241. case OPND_RM_POST_INC:
  242. fmt = "%s+";
  243. break;
  244. case OPND_RM_NONE:
  245. default:
  246. if (mo->n_regs < 2)
  247. (*info->fprintf_func) (info->stream, (mo->n_regs == 0) ? "%d" : "%d,", mo->base_offset);
  248. fmt = "%s";
  249. break;
  250. }
  251. if (mo->n_regs > 0)
  252. {
  253. int r = mo->regs[0];
  254. if (r < 0 || r >= S12Z_N_REGISTERS)
  255. (*info->fprintf_func) (info->stream, fmt, _("<illegal reg num>"));
  256. else
  257. (*info->fprintf_func) (info->stream, fmt, registers[r].name);
  258. }
  259. used_reg = 1;
  260. if (mo->n_regs > used_reg)
  261. {
  262. int r = mo->regs[used_reg];
  263. if (r < 0 || r >= S12Z_N_REGISTERS)
  264. (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
  265. else
  266. (*info->fprintf_func) (info->stream, ",%s",
  267. registers[r].name);
  268. }
  269. (*info->fprintf_func) (info->stream, "%c",
  270. mo->indirect ? ']' : ')');
  271. }
  272. break;
  273. };
  274. }
  275. #define S12Z_N_SIZES 4
  276. static const char shift_size_table[S12Z_N_SIZES] =
  277. {
  278. 'b', 'w', 'p', 'l'
  279. };
  280. int
  281. print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
  282. {
  283. int o;
  284. enum optr operator = OP_INVALID;
  285. int n_operands = 0;
  286. /* The longest instruction in S12Z can have 6 operands.
  287. (Most have 3 or less. Only PSH and PUL have so many. */
  288. struct operand *operands[6];
  289. struct mem_read_abstraction mra;
  290. mra.base.read = (void *) abstract_read_memory ;
  291. mra.base.advance = advance ;
  292. mra.base.posn = posn;
  293. mra.memaddr = memaddr;
  294. mra.info = info;
  295. short osize = -1;
  296. int n_bytes =
  297. decode_s12z (&operator, &osize, &n_operands, operands,
  298. (struct mem_read_abstraction_base *) &mra);
  299. (info->fprintf_func) (info->stream, "%s", mnemonics[(long)operator]);
  300. /* Ship out size sufficies for those instructions which
  301. need them. */
  302. if (osize == -1)
  303. {
  304. bool suffix = false;
  305. for (o = 0; o < n_operands; ++o)
  306. {
  307. if (operands[o] && operands[o]->osize != -1)
  308. {
  309. if (!suffix)
  310. {
  311. (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
  312. suffix = true;
  313. }
  314. osize = operands[o]->osize;
  315. if (osize < 0 || osize >= S12Z_N_SIZES)
  316. (*mra.info->fprintf_func) (mra.info->stream, _("<bad>"));
  317. else
  318. (*mra.info->fprintf_func) (mra.info->stream, "%c",
  319. shift_size_table[osize]);
  320. }
  321. }
  322. }
  323. else
  324. {
  325. if (osize < 0 || osize >= S12Z_N_SIZES)
  326. (*mra.info->fprintf_func) (mra.info->stream, _(".<bad>"));
  327. else
  328. (*mra.info->fprintf_func) (mra.info->stream, ".%c",
  329. shift_size_table[osize]);
  330. }
  331. /* Ship out the operands. */
  332. for (o = 0; o < n_operands; ++o)
  333. {
  334. if (operands[o])
  335. opr_emit_disassembly (operands[o], mra.info);
  336. free (operands[o]);
  337. }
  338. return n_bytes;
  339. }