moxie-dis.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /* Disassemble moxie instructions.
  2. Copyright (C) 2009-2015 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. #define STATIC_TABLE
  19. #define DEFINE_TABLE
  20. #include "opcode/moxie.h"
  21. #include "dis-asm.h"
  22. static fprintf_ftype fpr;
  23. static void *stream;
  24. /* Macros to extract operands from the instruction word. */
  25. #define OP_A(i) ((i >> 4) & 0xf)
  26. #define OP_B(i) (i & 0xf)
  27. #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
  28. static const char * reg_names[16] =
  29. { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
  30. "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
  31. int
  32. print_insn_moxie (bfd_vma addr, struct disassemble_info * info)
  33. {
  34. int length = 2;
  35. int status;
  36. stream = info->stream;
  37. const moxie_opc_info_t * opcode;
  38. bfd_byte buffer[4];
  39. unsigned short iword;
  40. fpr = info->fprintf_func;
  41. if ((status = info->read_memory_func (addr, buffer, 2, info)))
  42. goto fail;
  43. if (info->endian == BFD_ENDIAN_BIG)
  44. iword = bfd_getb16 (buffer);
  45. else
  46. iword = bfd_getl16 (buffer);
  47. /* Form 1 instructions have the high bit set to 0. */
  48. if ((iword & (1<<15)) == 0)
  49. {
  50. /* Extract the Form 1 opcode. */
  51. opcode = &moxie_form1_opc_info[iword >> 8];
  52. switch (opcode->itype)
  53. {
  54. case MOXIE_F1_NARG:
  55. fpr (stream, "%s", opcode->name);
  56. break;
  57. case MOXIE_F1_A:
  58. fpr (stream, "%s\t%s", opcode->name,
  59. reg_names[OP_A(iword)]);
  60. break;
  61. case MOXIE_F1_AB:
  62. fpr (stream, "%s\t%s, %s", opcode->name,
  63. reg_names[OP_A(iword)],
  64. reg_names[OP_B(iword)]);
  65. break;
  66. case MOXIE_F1_A4:
  67. {
  68. unsigned imm;
  69. if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
  70. goto fail;
  71. if (info->endian == BFD_ENDIAN_BIG)
  72. imm = bfd_getb32 (buffer);
  73. else
  74. imm = bfd_getl32 (buffer);
  75. fpr (stream, "%s\t%s, 0x%x", opcode->name,
  76. reg_names[OP_A(iword)], imm);
  77. length = 6;
  78. }
  79. break;
  80. case MOXIE_F1_4:
  81. {
  82. unsigned imm;
  83. if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
  84. goto fail;
  85. if (info->endian == BFD_ENDIAN_BIG)
  86. imm = bfd_getb32 (buffer);
  87. else
  88. imm = bfd_getl32 (buffer);
  89. fpr (stream, "%s\t0x%x", opcode->name, imm);
  90. length = 6;
  91. }
  92. break;
  93. case MOXIE_F1_M:
  94. {
  95. unsigned imm;
  96. if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
  97. goto fail;
  98. if (info->endian == BFD_ENDIAN_BIG)
  99. imm = bfd_getb32 (buffer);
  100. else
  101. imm = bfd_getl32 (buffer);
  102. fpr (stream, "%s\t", opcode->name);
  103. info->print_address_func ((bfd_vma) imm, info);
  104. length = 6;
  105. }
  106. break;
  107. case MOXIE_F1_AiB:
  108. fpr (stream, "%s\t(%s), %s", opcode->name,
  109. reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
  110. break;
  111. case MOXIE_F1_ABi:
  112. fpr (stream, "%s\t%s, (%s)", opcode->name,
  113. reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
  114. break;
  115. case MOXIE_F1_4A:
  116. {
  117. unsigned imm;
  118. if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
  119. goto fail;
  120. if (info->endian == BFD_ENDIAN_BIG)
  121. imm = bfd_getb32 (buffer);
  122. else
  123. imm = bfd_getl32 (buffer);
  124. fpr (stream, "%s\t0x%x, %s",
  125. opcode->name, imm, reg_names[OP_A(iword)]);
  126. length = 6;
  127. }
  128. break;
  129. case MOXIE_F1_AiB2:
  130. {
  131. unsigned imm;
  132. if ((status = info->read_memory_func (addr+2, buffer, 2, info)))
  133. goto fail;
  134. if (info->endian == BFD_ENDIAN_BIG)
  135. imm = bfd_getb16 (buffer);
  136. else
  137. imm = bfd_getl16 (buffer);
  138. fpr (stream, "%s\t0x%x(%s), %s", opcode->name,
  139. imm,
  140. reg_names[OP_A(iword)],
  141. reg_names[OP_B(iword)]);
  142. length = 4;
  143. }
  144. break;
  145. case MOXIE_F1_ABi2:
  146. {
  147. unsigned imm;
  148. if ((status = info->read_memory_func (addr+2, buffer, 2, info)))
  149. goto fail;
  150. if (info->endian == BFD_ENDIAN_BIG)
  151. imm = bfd_getb16 (buffer);
  152. else
  153. imm = bfd_getl16 (buffer);
  154. fpr (stream, "%s\t%s, 0x%x(%s)",
  155. opcode->name,
  156. reg_names[OP_A(iword)],
  157. imm,
  158. reg_names[OP_B(iword)]);
  159. length = 4;
  160. }
  161. break;
  162. case MOXIE_BAD:
  163. fpr (stream, "bad");
  164. break;
  165. default:
  166. abort();
  167. }
  168. }
  169. else if ((iword & (1<<14)) == 0)
  170. {
  171. /* Extract the Form 2 opcode. */
  172. opcode = &moxie_form2_opc_info[(iword >> 12) & 3];
  173. switch (opcode->itype)
  174. {
  175. case MOXIE_F2_A8V:
  176. fpr (stream, "%s\t%s, 0x%x",
  177. opcode->name,
  178. reg_names[(iword >> 8) & 0xf],
  179. iword & ((1 << 8) - 1));
  180. break;
  181. case MOXIE_F2_NARG:
  182. fpr (stream, "%s", opcode->name);
  183. break;
  184. case MOXIE_BAD:
  185. fpr (stream, "bad");
  186. break;
  187. default:
  188. abort();
  189. }
  190. }
  191. else
  192. {
  193. /* Extract the Form 3 opcode. */
  194. opcode = &moxie_form3_opc_info[(iword >> 10) & 15];
  195. switch (opcode->itype)
  196. {
  197. case MOXIE_F3_PCREL:
  198. fpr (stream, "%s\t", opcode->name);
  199. info->print_address_func ((bfd_vma) (addr + INST2OFFSET(iword) + 2),
  200. info);
  201. break;
  202. case MOXIE_BAD:
  203. fpr (stream, "bad");
  204. break;
  205. default:
  206. abort();
  207. }
  208. }
  209. return length;
  210. fail:
  211. info->memory_error_func (status, addr, info);
  212. return -1;
  213. }