m10200-dis.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /* Disassemble MN10200 instructions.
  2. Copyright (C) 1996-2017 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 "opcode/mn10200.h"
  19. #include "disassemble.h"
  20. #include "opintl.h"
  21. static void
  22. disassemble (bfd_vma memaddr,
  23. struct disassemble_info *info,
  24. unsigned long insn,
  25. unsigned long extension,
  26. unsigned int size)
  27. {
  28. struct mn10200_opcode *op = (struct mn10200_opcode *)mn10200_opcodes;
  29. const struct mn10200_operand *operand;
  30. int match = 0;
  31. /* Find the opcode. */
  32. while (op->name)
  33. {
  34. int mysize, extra_shift;
  35. if (op->format == FMT_1)
  36. mysize = 1;
  37. else if (op->format == FMT_2
  38. || op->format == FMT_4)
  39. mysize = 2;
  40. else if (op->format == FMT_3
  41. || op->format == FMT_5)
  42. mysize = 3;
  43. else if (op->format == FMT_6)
  44. mysize = 4;
  45. else if (op->format == FMT_7)
  46. mysize = 5;
  47. else
  48. abort ();
  49. if (op->format == FMT_2 || op->format == FMT_5)
  50. extra_shift = 8;
  51. else if (op->format == FMT_3
  52. || op->format == FMT_6
  53. || op->format == FMT_7)
  54. extra_shift = 16;
  55. else
  56. extra_shift = 0;
  57. if ((op->mask & insn) == op->opcode
  58. && size == (unsigned int) mysize)
  59. {
  60. const unsigned char *opindex_ptr;
  61. unsigned int nocomma;
  62. int paren = 0;
  63. match = 1;
  64. (*info->fprintf_func) (info->stream, "%s\t", op->name);
  65. /* Now print the operands. */
  66. for (opindex_ptr = op->operands, nocomma = 1;
  67. *opindex_ptr != 0;
  68. opindex_ptr++)
  69. {
  70. unsigned long value;
  71. operand = &mn10200_operands[*opindex_ptr];
  72. if ((operand->flags & MN10200_OPERAND_EXTENDED) != 0)
  73. {
  74. value = (insn & 0xffff) << 8;
  75. value |= extension;
  76. }
  77. else
  78. {
  79. value = ((insn >> (operand->shift))
  80. & ((1L << operand->bits) - 1L));
  81. }
  82. if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
  83. value = ((long)(value << (32 - operand->bits))
  84. >> (32 - operand->bits));
  85. if (!nocomma
  86. && (!paren
  87. || ((operand->flags & MN10200_OPERAND_PAREN) == 0)))
  88. (*info->fprintf_func) (info->stream, ",");
  89. nocomma = 0;
  90. if ((operand->flags & MN10200_OPERAND_DREG) != 0)
  91. {
  92. value = ((insn >> (operand->shift + extra_shift))
  93. & ((1 << operand->bits) - 1));
  94. (*info->fprintf_func) (info->stream, "d%ld", value);
  95. }
  96. else if ((operand->flags & MN10200_OPERAND_AREG) != 0)
  97. {
  98. value = ((insn >> (operand->shift + extra_shift))
  99. & ((1 << operand->bits) - 1));
  100. (*info->fprintf_func) (info->stream, "a%ld", value);
  101. }
  102. else if ((operand->flags & MN10200_OPERAND_PSW) != 0)
  103. (*info->fprintf_func) (info->stream, "psw");
  104. else if ((operand->flags & MN10200_OPERAND_MDR) != 0)
  105. (*info->fprintf_func) (info->stream, "mdr");
  106. else if ((operand->flags & MN10200_OPERAND_PAREN) != 0)
  107. {
  108. if (paren)
  109. (*info->fprintf_func) (info->stream, ")");
  110. else
  111. {
  112. (*info->fprintf_func) (info->stream, "(");
  113. nocomma = 1;
  114. }
  115. paren = !paren;
  116. }
  117. else if ((operand->flags & MN10200_OPERAND_PCREL) != 0)
  118. (*info->print_address_func)
  119. ((value + memaddr + mysize) & 0xffffff, info);
  120. else if ((operand->flags & MN10200_OPERAND_MEMADDR) != 0)
  121. (*info->print_address_func) (value, info);
  122. else
  123. (*info->fprintf_func) (info->stream, "%ld", value);
  124. }
  125. /* All done. */
  126. break;
  127. }
  128. op++;
  129. }
  130. if (!match)
  131. (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn);
  132. }
  133. int
  134. print_insn_mn10200 (bfd_vma memaddr, struct disassemble_info *info)
  135. {
  136. int status;
  137. bfd_byte buffer[4];
  138. unsigned long insn;
  139. unsigned long extension = 0;
  140. unsigned int consume;
  141. /* First figure out how big the opcode is. */
  142. status = (*info->read_memory_func) (memaddr, buffer, 1, info);
  143. if (status != 0)
  144. {
  145. (*info->memory_error_func) (status, memaddr, info);
  146. return -1;
  147. }
  148. insn = *(unsigned char *) buffer;
  149. /* These are one byte insns. */
  150. if ((insn & 0xf0) == 0x00
  151. || (insn & 0xf0) == 0x10
  152. || (insn & 0xf0) == 0x20
  153. || (insn & 0xf0) == 0x30
  154. || ((insn & 0xf0) == 0x80
  155. && (insn & 0x0c) >> 2 != (insn & 0x03))
  156. || (insn & 0xf0) == 0x90
  157. || (insn & 0xf0) == 0xa0
  158. || (insn & 0xf0) == 0xb0
  159. || (insn & 0xff) == 0xeb
  160. || (insn & 0xff) == 0xf6
  161. || (insn & 0xff) == 0xfe
  162. || (insn & 0xff) == 0xff)
  163. {
  164. extension = 0;
  165. consume = 1;
  166. }
  167. /* These are two byte insns. */
  168. else if ((insn & 0xf0) == 0x40
  169. || (insn & 0xf0) == 0x50
  170. || (insn & 0xf0) == 0x60
  171. || (insn & 0xf0) == 0x70
  172. || (insn & 0xf0) == 0x80
  173. || (insn & 0xfc) == 0xd0
  174. || (insn & 0xfc) == 0xd4
  175. || (insn & 0xfc) == 0xd8
  176. || (insn & 0xfc) == 0xe0
  177. || (insn & 0xfc) == 0xe4
  178. || (insn & 0xff) == 0xe8
  179. || (insn & 0xff) == 0xe9
  180. || (insn & 0xff) == 0xea
  181. || (insn & 0xff) == 0xf0
  182. || (insn & 0xff) == 0xf1
  183. || (insn & 0xff) == 0xf2
  184. || (insn & 0xff) == 0xf3)
  185. {
  186. status = (*info->read_memory_func) (memaddr, buffer, 2, info);
  187. if (status != 0)
  188. {
  189. (*info->memory_error_func) (status, memaddr, info);
  190. return -1;
  191. }
  192. insn = bfd_getb16 (buffer);
  193. consume = 2;
  194. }
  195. /* These are three byte insns with a 16bit operand in little
  196. endian form. */
  197. else if ((insn & 0xf0) == 0xc0
  198. || (insn & 0xfc) == 0xdc
  199. || (insn & 0xfc) == 0xec
  200. || (insn & 0xff) == 0xf8
  201. || (insn & 0xff) == 0xf9
  202. || (insn & 0xff) == 0xfa
  203. || (insn & 0xff) == 0xfb
  204. || (insn & 0xff) == 0xfc
  205. || (insn & 0xff) == 0xfd)
  206. {
  207. status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
  208. if (status != 0)
  209. {
  210. (*info->memory_error_func) (status, memaddr, info);
  211. return -1;
  212. }
  213. insn <<= 16;
  214. insn |= bfd_getl16 (buffer);
  215. extension = 0;
  216. consume = 3;
  217. }
  218. /* These are three byte insns too, but we don't have to mess with
  219. endianness stuff. */
  220. else if ((insn & 0xff) == 0xf5)
  221. {
  222. status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
  223. if (status != 0)
  224. {
  225. (*info->memory_error_func) (status, memaddr, info);
  226. return -1;
  227. }
  228. insn <<= 16;
  229. insn |= bfd_getb16 (buffer);
  230. extension = 0;
  231. consume = 3;
  232. }
  233. /* These are four byte insns. */
  234. else if ((insn & 0xff) == 0xf7)
  235. {
  236. status = (*info->read_memory_func) (memaddr, buffer, 2, info);
  237. if (status != 0)
  238. {
  239. (*info->memory_error_func) (status, memaddr, info);
  240. return -1;
  241. }
  242. insn = bfd_getb16 (buffer);
  243. insn <<= 16;
  244. status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
  245. if (status != 0)
  246. {
  247. (*info->memory_error_func) (status, memaddr, info);
  248. return -1;
  249. }
  250. insn |= bfd_getl16 (buffer);
  251. extension = 0;
  252. consume = 4;
  253. }
  254. /* These are five byte insns. */
  255. else if ((insn & 0xff) == 0xf4)
  256. {
  257. status = (*info->read_memory_func) (memaddr, buffer, 2, info);
  258. if (status != 0)
  259. {
  260. (*info->memory_error_func) (status, memaddr, info);
  261. return -1;
  262. }
  263. insn = bfd_getb16 (buffer);
  264. insn <<= 16;
  265. status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
  266. if (status != 0)
  267. {
  268. (*info->memory_error_func) (status, memaddr, info);
  269. return -1;
  270. }
  271. insn |= (*(unsigned char *)buffer << 8) & 0xff00;
  272. status = (*info->read_memory_func) (memaddr + 3, buffer, 1, info);
  273. if (status != 0)
  274. {
  275. (*info->memory_error_func) (status, memaddr, info);
  276. return -1;
  277. }
  278. insn |= (*(unsigned char *)buffer) & 0xff;
  279. status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
  280. if (status != 0)
  281. {
  282. (*info->memory_error_func) (status, memaddr, info);
  283. return -1;
  284. }
  285. extension = (*(unsigned char *)buffer) & 0xff;
  286. consume = 5;
  287. }
  288. else
  289. {
  290. (*info->fprintf_func) (info->stream, _("unknown\t0x%02lx"), insn);
  291. return 1;
  292. }
  293. disassemble (memaddr, info, insn, extension, consume);
  294. return consume;
  295. }