mt.opc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /* Morpho Technologies mRISC opcode support, for GNU Binutils. -*- C -*-
  2. Copyright 2001, 2007, 2008, 2009, 2012 Free Software Foundation, Inc.
  3. Contributed by Red Hat Inc; developed under contract from
  4. Morpho Technologies.
  5. This file is part of the GNU Binutils.
  6. This program 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 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public 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. /* Each section is delimited with start and end markers.
  19. <arch>-opc.h additions use: "-- opc.h"
  20. <arch>-opc.c additions use: "-- opc.c"
  21. <arch>-asm.c additions use: "-- asm.c"
  22. <arch>-dis.c additions use: "-- dis.c"
  23. <arch>-ibd.h additions use: "-- ibd.h" */
  24. /* -- opc.h */
  25. /* Check applicability of instructions against machines. */
  26. #define CGEN_VALIDATE_INSN_SUPPORTED
  27. /* Allows reason codes to be output when assembler errors occur. */
  28. #define CGEN_VERBOSE_ASSEMBLER_ERRORS
  29. /* Override disassembly hashing - there are variable bits in the top
  30. byte of these instructions. */
  31. #define CGEN_DIS_HASH_SIZE 8
  32. #define CGEN_DIS_HASH(buf, value) (((* (unsigned char *) (buf)) >> 5) % CGEN_DIS_HASH_SIZE)
  33. #define CGEN_ASM_HASH_SIZE 127
  34. #define CGEN_ASM_HASH(insn) mt_asm_hash (insn)
  35. extern unsigned int mt_asm_hash (const char *);
  36. extern int mt_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
  37. /* -- opc.c */
  38. #include "safe-ctype.h"
  39. /* Special check to ensure that instruction exists for given machine. */
  40. int
  41. mt_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
  42. {
  43. int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
  44. /* No mach attribute? Assume it's supported for all machs. */
  45. if (machs == 0)
  46. return 1;
  47. return ((machs & cd->machs) != 0);
  48. }
  49. /* A better hash function for instruction mnemonics. */
  50. unsigned int
  51. mt_asm_hash (const char* insn)
  52. {
  53. unsigned int hash;
  54. const char* m = insn;
  55. for (hash = 0; *m && ! ISSPACE (*m); m++)
  56. hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
  57. /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
  58. return hash % CGEN_ASM_HASH_SIZE;
  59. }
  60. /* -- asm.c */
  61. /* Range checking for signed numbers. Returns 0 if acceptable
  62. and 1 if the value is out of bounds for a signed quantity. */
  63. static int
  64. signed_out_of_bounds (long val)
  65. {
  66. if ((val < -32768) || (val > 32767))
  67. return 1;
  68. return 0;
  69. }
  70. static const char *
  71. parse_loopsize (CGEN_CPU_DESC cd,
  72. const char **strp,
  73. int opindex,
  74. void *arg)
  75. {
  76. signed long * valuep = (signed long *) arg;
  77. const char *errmsg;
  78. bfd_reloc_code_real_type code = BFD_RELOC_NONE;
  79. enum cgen_parse_operand_result result_type;
  80. bfd_vma value;
  81. /* Is it a control transfer instructions? */
  82. if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_LOOPSIZE)
  83. {
  84. code = BFD_RELOC_MT_PCINSN8;
  85. errmsg = cgen_parse_address (cd, strp, opindex, code,
  86. & result_type, & value);
  87. *valuep = value;
  88. return errmsg;
  89. }
  90. abort ();
  91. }
  92. static const char *
  93. parse_imm16 (CGEN_CPU_DESC cd,
  94. const char **strp,
  95. int opindex,
  96. void *arg)
  97. {
  98. signed long * valuep = (signed long *) arg;
  99. const char *errmsg;
  100. enum cgen_parse_operand_result result_type;
  101. bfd_reloc_code_real_type code = BFD_RELOC_NONE;
  102. bfd_vma value;
  103. /* Is it a control transfer instructions? */
  104. if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16O)
  105. {
  106. code = BFD_RELOC_16_PCREL;
  107. errmsg = cgen_parse_address (cd, strp, opindex, code,
  108. & result_type, & value);
  109. if (errmsg == NULL)
  110. {
  111. if (signed_out_of_bounds (value))
  112. errmsg = _("Operand out of range. Must be between -32768 and 32767.");
  113. }
  114. *valuep = value;
  115. return errmsg;
  116. }
  117. /* If it's not a control transfer instruction, then
  118. we have to check for %OP relocating operators. */
  119. if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16L)
  120. ;
  121. else if (strncmp (*strp, "%hi16", 5) == 0)
  122. {
  123. *strp += 5;
  124. code = BFD_RELOC_HI16;
  125. }
  126. else if (strncmp (*strp, "%lo16", 5) == 0)
  127. {
  128. *strp += 5;
  129. code = BFD_RELOC_LO16;
  130. }
  131. /* If we found a %OP relocating operator, then parse it as an address.
  132. If not, we need to parse it as an integer, either signed or unsigned
  133. depending on which operand type we have. */
  134. if (code != BFD_RELOC_NONE)
  135. {
  136. /* %OP relocating operator found. */
  137. errmsg = cgen_parse_address (cd, strp, opindex, code,
  138. & result_type, & value);
  139. if (errmsg == NULL)
  140. {
  141. switch (result_type)
  142. {
  143. case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
  144. if (code == BFD_RELOC_HI16)
  145. value = (value >> 16) & 0xFFFF;
  146. else if (code == BFD_RELOC_LO16)
  147. value = value & 0xFFFF;
  148. else
  149. errmsg = _("Biiiig Trouble in parse_imm16!");
  150. break;
  151. case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
  152. /* No special processing for this case. */
  153. break;
  154. default:
  155. errmsg = _("The percent-operator's operand is not a symbol");
  156. break;
  157. }
  158. }
  159. *valuep = value;
  160. }
  161. else
  162. {
  163. /* Parse hex values like 0xffff as unsigned, and sign extend
  164. them manually. */
  165. int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MT_OPERAND_IMM16);
  166. if ((*strp)[0] == '0'
  167. && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
  168. parse_signed = 0;
  169. /* No relocating operator. Parse as an number. */
  170. if (parse_signed)
  171. {
  172. /* Parse as as signed integer. */
  173. errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
  174. if (errmsg == NULL)
  175. {
  176. #if 0
  177. /* Manual range checking is needed for the signed case. */
  178. if (*valuep & 0x8000)
  179. value = 0xffff0000 | *valuep;
  180. else
  181. value = *valuep;
  182. if (signed_out_of_bounds (value))
  183. errmsg = _("Operand out of range. Must be between -32768 and 32767.");
  184. /* Truncate to 16 bits. This is necessary
  185. because cgen will have sign extended *valuep. */
  186. *valuep &= 0xFFFF;
  187. #endif
  188. }
  189. }
  190. else
  191. {
  192. /* MT_OPERAND_IMM16Z. Parse as an unsigned integer. */
  193. errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
  194. if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16
  195. && *valuep >= 0x8000
  196. && *valuep <= 0xffff)
  197. *valuep -= 0x10000;
  198. }
  199. }
  200. return errmsg;
  201. }
  202. static const char *
  203. parse_dup (CGEN_CPU_DESC cd,
  204. const char **strp,
  205. int opindex,
  206. unsigned long *valuep)
  207. {
  208. const char *errmsg = NULL;
  209. if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
  210. {
  211. *strp += 3;
  212. *valuep = 1;
  213. }
  214. else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
  215. {
  216. *strp += 2;
  217. *valuep = 0;
  218. }
  219. else
  220. errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
  221. return errmsg;
  222. }
  223. static const char *
  224. parse_ball (CGEN_CPU_DESC cd,
  225. const char **strp,
  226. int opindex,
  227. unsigned long *valuep)
  228. {
  229. const char *errmsg = NULL;
  230. if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
  231. {
  232. *strp += 3;
  233. *valuep = 1;
  234. }
  235. else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
  236. {
  237. *strp += 3;
  238. *valuep = 0;
  239. }
  240. else
  241. errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
  242. return errmsg;
  243. }
  244. static const char *
  245. parse_xmode (CGEN_CPU_DESC cd,
  246. const char **strp,
  247. int opindex,
  248. unsigned long *valuep)
  249. {
  250. const char *errmsg = NULL;
  251. if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
  252. {
  253. *strp += 2;
  254. *valuep = 1;
  255. }
  256. else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
  257. {
  258. *strp += 2;
  259. *valuep = 0;
  260. }
  261. else
  262. errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
  263. return errmsg;
  264. }
  265. static const char *
  266. parse_rc (CGEN_CPU_DESC cd,
  267. const char **strp,
  268. int opindex,
  269. unsigned long *valuep)
  270. {
  271. const char *errmsg = NULL;
  272. if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
  273. {
  274. *strp += 1;
  275. *valuep = 1;
  276. }
  277. else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
  278. {
  279. *strp += 1;
  280. *valuep = 0;
  281. }
  282. else
  283. errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
  284. return errmsg;
  285. }
  286. static const char *
  287. parse_cbrb (CGEN_CPU_DESC cd,
  288. const char **strp,
  289. int opindex,
  290. unsigned long *valuep)
  291. {
  292. const char *errmsg = NULL;
  293. if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
  294. {
  295. *strp += 2;
  296. *valuep = 1;
  297. }
  298. else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
  299. {
  300. *strp += 2;
  301. *valuep = 0;
  302. }
  303. else
  304. errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
  305. return errmsg;
  306. }
  307. static const char *
  308. parse_rbbc (CGEN_CPU_DESC cd,
  309. const char **strp,
  310. int opindex,
  311. unsigned long *valuep)
  312. {
  313. const char *errmsg = NULL;
  314. if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
  315. {
  316. *strp += 2;
  317. *valuep = 0;
  318. }
  319. else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
  320. {
  321. *strp += 3;
  322. *valuep = 1;
  323. }
  324. else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
  325. {
  326. *strp += 3;
  327. *valuep = 2;
  328. }
  329. else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
  330. {
  331. *strp += 2;
  332. *valuep = 3;
  333. }
  334. else
  335. errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
  336. return errmsg;
  337. }
  338. static const char *
  339. parse_type (CGEN_CPU_DESC cd,
  340. const char **strp,
  341. int opindex,
  342. unsigned long *valuep)
  343. {
  344. const char *errmsg = NULL;
  345. if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
  346. {
  347. *strp += 3;
  348. *valuep = 0;
  349. }
  350. else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
  351. {
  352. *strp += 4;
  353. *valuep = 1;
  354. }
  355. else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
  356. {
  357. *strp += 2;
  358. *valuep = 2;
  359. }
  360. else
  361. errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
  362. if ((errmsg == NULL) && (*valuep == 3))
  363. errmsg = _("invalid operand. type may have values 0,1,2 only.");
  364. return errmsg;
  365. }
  366. /* -- dis.c */
  367. static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
  368. static void print_pcrel (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
  369. static void
  370. print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
  371. void * dis_info,
  372. long value,
  373. unsigned int attrs ATTRIBUTE_UNUSED,
  374. bfd_vma pc ATTRIBUTE_UNUSED,
  375. int length ATTRIBUTE_UNUSED)
  376. {
  377. disassemble_info *info = (disassemble_info *) dis_info;
  378. info->fprintf_func (info->stream, "$%lx", value & 0xffffffff);
  379. if (0)
  380. print_normal (cd, dis_info, value, attrs, pc, length);
  381. }
  382. static void
  383. print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
  384. void * dis_info,
  385. long value,
  386. unsigned int attrs ATTRIBUTE_UNUSED,
  387. bfd_vma pc ATTRIBUTE_UNUSED,
  388. int length ATTRIBUTE_UNUSED)
  389. {
  390. print_address (cd, dis_info, value + pc, attrs, pc, length);
  391. }
  392. /* -- */