cr16-dis.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. /* Disassembler code for CR16.
  2. Copyright (C) 2007-2015 Free Software Foundation, Inc.
  3. Contributed by M R Swami Reddy (MR.Swami.Reddy@nsc.com).
  4. This file is part of GAS, GDB and the GNU binutils.
  5. This program is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU General Public License as published by the
  7. Free Software Foundation; either version 3, or (at your option)
  8. any later version.
  9. This program is distributed in the hope that it will be useful, but WITHOUT
  10. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. 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 Foundation,
  15. Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
  16. #include "sysdep.h"
  17. #include "dis-asm.h"
  18. #include "opcode/cr16.h"
  19. #include "libiberty.h"
  20. /* String to print when opcode was not matched. */
  21. #define ILLEGAL "illegal"
  22. /* Escape to 16-bit immediate. */
  23. #define ESCAPE_16_BIT 0xB
  24. /* Extract 'n_bits' from 'a' starting from offset 'offs'. */
  25. #define EXTRACT(a, offs, n_bits) \
  26. (n_bits == 32 ? (((a) >> (offs)) & 0xffffffffL) \
  27. : (((a) >> (offs)) & ((1 << (n_bits)) -1)))
  28. /* Set Bit Mask - a mask to set all bits starting from offset 'offs'. */
  29. #define SBM(offs) ((((1 << (32 - offs)) -1) << (offs)))
  30. typedef struct
  31. {
  32. dwordU val;
  33. int nbits;
  34. } parameter;
  35. /* Structure to map valid 'cinv' instruction options. */
  36. typedef struct
  37. {
  38. /* Cinv printed string. */
  39. char *istr;
  40. /* Value corresponding to the string. */
  41. char *ostr;
  42. }
  43. cinv_entry;
  44. /* CR16 'cinv' options mapping. */
  45. const cinv_entry cr16_cinvs[] =
  46. {
  47. {"cinv[i]", "cinv [i]"},
  48. {"cinv[i,u]", "cinv [i,u]"},
  49. {"cinv[d]", "cinv [d]"},
  50. {"cinv[d,u]", "cinv [d,u]"},
  51. {"cinv[d,i]", "cinv [d,i]"},
  52. {"cinv[d,i,u]", "cinv [d,i,u]"}
  53. };
  54. /* Number of valid 'cinv' instruction options. */
  55. static int NUMCINVS = ARRAY_SIZE (cr16_cinvs);
  56. /* Enum to distinguish different registers argument types. */
  57. typedef enum REG_ARG_TYPE
  58. {
  59. /* General purpose register (r<N>). */
  60. REG_ARG = 0,
  61. /*Processor register */
  62. P_ARG,
  63. }
  64. REG_ARG_TYPE;
  65. /* Current opcode table entry we're disassembling. */
  66. const inst *instruction;
  67. /* Current instruction we're disassembling. */
  68. ins cr16_currInsn;
  69. /* The current instruction is read into 3 consecutive words. */
  70. wordU cr16_words[3];
  71. /* Contains all words in appropriate order. */
  72. ULONGLONG cr16_allWords;
  73. /* Holds the current processed argument number. */
  74. int processing_argument_number;
  75. /* Nonzero means a IMM4 instruction. */
  76. int imm4flag;
  77. /* Nonzero means the instruction's original size is
  78. incremented (escape sequence is used). */
  79. int size_changed;
  80. /* Print the constant expression length. */
  81. static char *
  82. print_exp_len (int size)
  83. {
  84. switch (size)
  85. {
  86. case 4:
  87. case 5:
  88. case 6:
  89. case 8:
  90. case 14:
  91. case 16:
  92. return ":s";
  93. case 20:
  94. case 24:
  95. case 32:
  96. return ":m";
  97. case 48:
  98. return ":l";
  99. default:
  100. return "";
  101. }
  102. }
  103. /* Retrieve the number of operands for the current assembled instruction. */
  104. static int
  105. get_number_of_operands (void)
  106. {
  107. int i;
  108. for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
  109. ;
  110. return i;
  111. }
  112. /* Return the bit size for a given operand. */
  113. static int
  114. getbits (operand_type op)
  115. {
  116. if (op < MAX_OPRD)
  117. return cr16_optab[op].bit_size;
  118. return 0;
  119. }
  120. /* Return the argument type of a given operand. */
  121. static argtype
  122. getargtype (operand_type op)
  123. {
  124. if (op < MAX_OPRD)
  125. return cr16_optab[op].arg_type;
  126. return nullargs;
  127. }
  128. /* Given a 'CC' instruction constant operand, return its corresponding
  129. string. This routine is used when disassembling the 'CC' instruction. */
  130. static char *
  131. getccstring (unsigned cc_insn)
  132. {
  133. return (char *) cr16_b_cond_tab[cc_insn];
  134. }
  135. /* Given a 'cinv' instruction constant operand, return its corresponding
  136. string. This routine is used when disassembling the 'cinv' instruction. */
  137. static char *
  138. getcinvstring (const char *str)
  139. {
  140. const cinv_entry *cinv;
  141. for (cinv = cr16_cinvs; cinv < (cr16_cinvs + NUMCINVS); cinv++)
  142. if (strcmp (cinv->istr, str) == 0)
  143. return cinv->ostr;
  144. return ILLEGAL;
  145. }
  146. /* Given the trap index in dispatch table, return its name.
  147. This routine is used when disassembling the 'excp' instruction. */
  148. static char *
  149. gettrapstring (unsigned int trap_index)
  150. {
  151. const trap_entry *trap;
  152. for (trap = cr16_traps; trap < cr16_traps + NUMTRAPS; trap++)
  153. if (trap->entry == trap_index)
  154. return trap->name;
  155. return ILLEGAL;
  156. }
  157. /* Given a register enum value, retrieve its name. */
  158. static char *
  159. getregname (reg r)
  160. {
  161. const reg_entry * regentry = cr16_regtab + r;
  162. if (regentry->type != CR16_R_REGTYPE)
  163. return ILLEGAL;
  164. return regentry->name;
  165. }
  166. /* Given a register pair enum value, retrieve its name. */
  167. static char *
  168. getregpname (reg r)
  169. {
  170. const reg_entry * regentry = cr16_regptab + r;
  171. if (regentry->type != CR16_RP_REGTYPE)
  172. return ILLEGAL;
  173. return regentry->name;
  174. }
  175. /* Given a index register pair enum value, retrieve its name. */
  176. static char *
  177. getidxregpname (reg r)
  178. {
  179. const reg_entry * regentry;
  180. switch (r)
  181. {
  182. case 0: r = 0; break;
  183. case 1: r = 2; break;
  184. case 2: r = 4; break;
  185. case 3: r = 6; break;
  186. case 4: r = 8; break;
  187. case 5: r = 10; break;
  188. case 6: r = 3; break;
  189. case 7: r = 5; break;
  190. default:
  191. break;
  192. }
  193. regentry = cr16_regptab + r;
  194. if (regentry->type != CR16_RP_REGTYPE)
  195. return ILLEGAL;
  196. return regentry->name;
  197. }
  198. /* Getting a processor register name. */
  199. static char *
  200. getprocregname (int reg_index)
  201. {
  202. const reg_entry *r;
  203. for (r = cr16_pregtab; r < cr16_pregtab + NUMPREGS; r++)
  204. if (r->image == reg_index)
  205. return r->name;
  206. return "ILLEGAL REGISTER";
  207. }
  208. /* Getting a processor register name - 32 bit size. */
  209. static char *
  210. getprocpregname (int reg_index)
  211. {
  212. const reg_entry *r;
  213. for (r = cr16_pregptab; r < cr16_pregptab + NUMPREGPS; r++)
  214. if (r->image == reg_index)
  215. return r->name;
  216. return "ILLEGAL REGISTER";
  217. }
  218. /* START and END are relating 'cr16_allWords' struct, which is 48 bits size.
  219. START|--------|END
  220. +---------+---------+---------+---------+
  221. | | V | A | L |
  222. +---------+---------+---------+---------+
  223. 0 16 32 48
  224. words [0] [1] [2] */
  225. static parameter
  226. makelongparameter (ULONGLONG val, int start, int end)
  227. {
  228. parameter p;
  229. p.val = (dwordU) EXTRACT (val, 48 - end, end - start);
  230. p.nbits = end - start;
  231. return p;
  232. }
  233. /* Build a mask of the instruction's 'constant' opcode,
  234. based on the instruction's printing flags. */
  235. static unsigned long
  236. build_mask (void)
  237. {
  238. unsigned long mask = SBM (instruction->match_bits);
  239. /* Adjust mask for bcond with 32-bit size instruction. */
  240. if ((IS_INSN_MNEMONIC("b") && instruction->size == 2))
  241. mask = 0xff0f0000;
  242. return mask;
  243. }
  244. /* Search for a matching opcode. Return 1 for success, 0 for failure. */
  245. int
  246. cr16_match_opcode (void)
  247. {
  248. unsigned long mask;
  249. /* The instruction 'constant' opcode doesn't exceed 32 bits. */
  250. unsigned long doubleWord = (cr16_words[1]
  251. + (cr16_words[0] << 16)) & 0xffffffff;
  252. /* Start searching from end of instruction table. */
  253. instruction = &cr16_instruction[NUMOPCODES - 2];
  254. /* Loop over instruction table until a full match is found. */
  255. while (instruction >= cr16_instruction)
  256. {
  257. mask = build_mask ();
  258. /* Adjust mask for bcond with 32-bit size instruction */
  259. if ((IS_INSN_MNEMONIC("b") && instruction->size == 2))
  260. mask = 0xff0f0000;
  261. if ((doubleWord & mask) == BIN (instruction->match,
  262. instruction->match_bits))
  263. return 1;
  264. else
  265. instruction--;
  266. }
  267. return 0;
  268. }
  269. /* Set the proper parameter value for different type of arguments. */
  270. static void
  271. make_argument (argument * a, int start_bits)
  272. {
  273. int inst_bit_size;
  274. parameter p;
  275. if ((instruction->size == 3) && a->size >= 16)
  276. inst_bit_size = 48;
  277. else
  278. inst_bit_size = 32;
  279. switch (a->type)
  280. {
  281. case arg_r:
  282. p = makelongparameter (cr16_allWords,
  283. inst_bit_size - (start_bits + a->size),
  284. inst_bit_size - start_bits);
  285. a->r = p.val;
  286. break;
  287. case arg_rp:
  288. p = makelongparameter (cr16_allWords,
  289. inst_bit_size - (start_bits + a->size),
  290. inst_bit_size - start_bits);
  291. a->rp = p.val;
  292. break;
  293. case arg_pr:
  294. p = makelongparameter (cr16_allWords,
  295. inst_bit_size - (start_bits + a->size),
  296. inst_bit_size - start_bits);
  297. a->pr = p.val;
  298. break;
  299. case arg_prp:
  300. p = makelongparameter (cr16_allWords,
  301. inst_bit_size - (start_bits + a->size),
  302. inst_bit_size - start_bits);
  303. a->prp = p.val;
  304. break;
  305. case arg_ic:
  306. p = makelongparameter (cr16_allWords,
  307. inst_bit_size - (start_bits + a->size),
  308. inst_bit_size - start_bits);
  309. a->constant = p.val;
  310. break;
  311. case arg_cc:
  312. p = makelongparameter (cr16_allWords,
  313. inst_bit_size - (start_bits + a->size),
  314. inst_bit_size - start_bits);
  315. a->cc = p.val;
  316. break;
  317. case arg_idxr:
  318. if ((IS_INSN_MNEMONIC ("cbitb"))
  319. || (IS_INSN_MNEMONIC ("sbitb"))
  320. || (IS_INSN_MNEMONIC ("tbitb")))
  321. p = makelongparameter (cr16_allWords, 8, 9);
  322. else
  323. p = makelongparameter (cr16_allWords, 9, 10);
  324. a->i_r = p.val;
  325. p = makelongparameter (cr16_allWords,
  326. inst_bit_size - a->size, inst_bit_size);
  327. a->constant = p.val;
  328. break;
  329. case arg_idxrp:
  330. p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 13);
  331. a->i_r = p.val;
  332. p = makelongparameter (cr16_allWords, start_bits + 13, start_bits + 16);
  333. a->rp = p.val;
  334. if (inst_bit_size > 32)
  335. {
  336. p = makelongparameter (cr16_allWords, inst_bit_size - start_bits - 12,
  337. inst_bit_size);
  338. a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
  339. }
  340. else if (instruction->size == 2)
  341. {
  342. p = makelongparameter (cr16_allWords, inst_bit_size - 22,
  343. inst_bit_size);
  344. a->constant = (p.val & 0xf) | (((p.val >>20) & 0x3) << 4)
  345. | ((p.val >>14 & 0x3) << 6) | (((p.val >>7) & 0x1f) <<7);
  346. }
  347. else if (instruction->size == 1 && a->size == 0)
  348. a->constant = 0;
  349. break;
  350. case arg_rbase:
  351. p = makelongparameter (cr16_allWords, inst_bit_size, inst_bit_size);
  352. a->constant = p.val;
  353. p = makelongparameter (cr16_allWords, inst_bit_size - (start_bits + 4),
  354. inst_bit_size - start_bits);
  355. a->r = p.val;
  356. break;
  357. case arg_cr:
  358. p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 16);
  359. a->r = p.val;
  360. p = makelongparameter (cr16_allWords, inst_bit_size - 16, inst_bit_size);
  361. a->constant = p.val;
  362. break;
  363. case arg_crp:
  364. if (instruction->size == 1)
  365. p = makelongparameter (cr16_allWords, 12, 16);
  366. else
  367. p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 16);
  368. a->rp = p.val;
  369. if (inst_bit_size > 32)
  370. {
  371. p = makelongparameter (cr16_allWords, inst_bit_size - start_bits - 12,
  372. inst_bit_size);
  373. a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
  374. }
  375. else if (instruction->size == 2)
  376. {
  377. p = makelongparameter (cr16_allWords, inst_bit_size - 16,
  378. inst_bit_size);
  379. a->constant = p.val;
  380. }
  381. else if (instruction->size == 1 && a->size != 0)
  382. {
  383. p = makelongparameter (cr16_allWords, 4, 8);
  384. if (IS_INSN_MNEMONIC ("loadw")
  385. || IS_INSN_MNEMONIC ("loadd")
  386. || IS_INSN_MNEMONIC ("storw")
  387. || IS_INSN_MNEMONIC ("stord"))
  388. a->constant = (p.val * 2);
  389. else
  390. a->constant = p.val;
  391. }
  392. else /* below case for 0x0(reg pair) */
  393. a->constant = 0;
  394. break;
  395. case arg_c:
  396. if ((IS_INSN_TYPE (BRANCH_INS))
  397. || (IS_INSN_MNEMONIC ("bal"))
  398. || (IS_INSN_TYPE (CSTBIT_INS))
  399. || (IS_INSN_TYPE (LD_STOR_INS)))
  400. {
  401. switch (a->size)
  402. {
  403. case 8 :
  404. p = makelongparameter (cr16_allWords, 0, start_bits);
  405. a->constant = ((((p.val&0xf00)>>4)) | (p.val&0xf));
  406. break;
  407. case 24:
  408. if (instruction->size == 3)
  409. {
  410. p = makelongparameter (cr16_allWords, 16, inst_bit_size);
  411. a->constant = ((((p.val>>16)&0xf) << 20)
  412. | (((p.val>>24)&0xf) << 16)
  413. | (p.val & 0xffff));
  414. }
  415. else if (instruction->size == 2)
  416. {
  417. p = makelongparameter (cr16_allWords, 8, inst_bit_size);
  418. a->constant = p.val;
  419. }
  420. break;
  421. default:
  422. p = makelongparameter (cr16_allWords,
  423. inst_bit_size - (start_bits + a->size),
  424. inst_bit_size - start_bits);
  425. a->constant = p.val;
  426. break;
  427. }
  428. }
  429. else
  430. {
  431. p = makelongparameter (cr16_allWords,
  432. inst_bit_size - (start_bits + a->size),
  433. inst_bit_size - start_bits);
  434. a->constant = p.val;
  435. }
  436. break;
  437. default:
  438. break;
  439. }
  440. }
  441. /* Print a single argument. */
  442. static void
  443. print_arg (argument *a, bfd_vma memaddr, struct disassemble_info *info)
  444. {
  445. LONGLONG longdisp, mask;
  446. int sign_flag = 0;
  447. int relative = 0;
  448. bfd_vma number;
  449. PTR stream = info->stream;
  450. fprintf_ftype func = info->fprintf_func;
  451. switch (a->type)
  452. {
  453. case arg_r:
  454. func (stream, "%s", getregname (a->r));
  455. break;
  456. case arg_rp:
  457. func (stream, "%s", getregpname (a->rp));
  458. break;
  459. case arg_pr:
  460. func (stream, "%s", getprocregname (a->pr));
  461. break;
  462. case arg_prp:
  463. func (stream, "%s", getprocpregname (a->prp));
  464. break;
  465. case arg_cc:
  466. func (stream, "%s", getccstring (a->cc));
  467. func (stream, "%s", "\t");
  468. break;
  469. case arg_ic:
  470. if (IS_INSN_MNEMONIC ("excp"))
  471. {
  472. func (stream, "%s", gettrapstring (a->constant));
  473. break;
  474. }
  475. else if ((IS_INSN_TYPE (ARITH_INS) || IS_INSN_TYPE (ARITH_BYTE_INS))
  476. && ((instruction->size == 1) && (a->constant == 9)))
  477. func (stream, "$%d", -1);
  478. else if (INST_HAS_REG_LIST)
  479. func (stream, "$0x%lx", a->constant +1);
  480. else if (IS_INSN_TYPE (SHIFT_INS))
  481. {
  482. longdisp = a->constant;
  483. mask = ((LONGLONG)1 << a->size) - 1;
  484. if (longdisp & ((LONGLONG)1 << (a->size -1)))
  485. {
  486. sign_flag = 1;
  487. longdisp = ~(longdisp) + 1;
  488. }
  489. a->constant = (unsigned long int) (longdisp & mask);
  490. func (stream, "$%d", ((int)(sign_flag ? -a->constant :
  491. a->constant)));
  492. }
  493. else
  494. func (stream, "$0x%lx", a->constant);
  495. switch (a->size)
  496. {
  497. case 4 : case 5 : case 6 : case 8 :
  498. func (stream, "%s", ":s"); break;
  499. case 16 : case 20 : func (stream, "%s", ":m"); break;
  500. case 24 : case 32 : func (stream, "%s", ":l"); break;
  501. default: break;
  502. }
  503. break;
  504. case arg_idxr:
  505. if (a->i_r == 0) func (stream, "[r12]");
  506. if (a->i_r == 1) func (stream, "[r13]");
  507. func (stream, "0x%lx", a->constant);
  508. func (stream, "%s", print_exp_len (instruction->size * 16));
  509. break;
  510. case arg_idxrp:
  511. if (a->i_r == 0) func (stream, "[r12]");
  512. if (a->i_r == 1) func (stream, "[r13]");
  513. func (stream, "0x%lx", a->constant);
  514. func (stream, "%s", print_exp_len (instruction->size * 16));
  515. func (stream, "%s", getidxregpname (a->rp));
  516. break;
  517. case arg_rbase:
  518. func (stream, "(%s)", getregname (a->r));
  519. break;
  520. case arg_cr:
  521. func (stream, "0x%lx", a->constant);
  522. func (stream, "%s", print_exp_len (instruction->size * 16));
  523. func (stream, "(%s)", getregname (a->r));
  524. break;
  525. case arg_crp:
  526. func (stream, "0x%lx", a->constant);
  527. func (stream, "%s", print_exp_len (instruction->size * 16));
  528. func (stream, "%s", getregpname (a->rp));
  529. break;
  530. case arg_c:
  531. /*Removed the *2 part as because implicit zeros are no more required.
  532. Have to fix this as this needs a bit of extension in terms of branch
  533. instructions. */
  534. if (IS_INSN_TYPE (BRANCH_INS) || IS_INSN_MNEMONIC ("bal"))
  535. {
  536. relative = 1;
  537. longdisp = a->constant;
  538. /* REVISIT: To sync with WinIDEA and CR16 4.1tools, the below
  539. line commented */
  540. /* longdisp <<= 1; */
  541. mask = ((LONGLONG)1 << a->size) - 1;
  542. switch (a->size)
  543. {
  544. case 8 :
  545. {
  546. longdisp <<= 1;
  547. if (longdisp & ((LONGLONG)1 << a->size))
  548. {
  549. sign_flag = 1;
  550. longdisp = ~(longdisp) + 1;
  551. }
  552. break;
  553. }
  554. case 16 :
  555. case 24 :
  556. {
  557. if (longdisp & 1)
  558. {
  559. sign_flag = 1;
  560. longdisp = ~(longdisp) + 1;
  561. }
  562. break;
  563. }
  564. default:
  565. func (stream, "Wrong offset used in branch/bal instruction");
  566. break;
  567. }
  568. a->constant = (unsigned long int) (longdisp & mask);
  569. }
  570. /* For branch Neq instruction it is 2*offset + 2. */
  571. else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
  572. a->constant = 2 * a->constant + 2;
  573. if ((!IS_INSN_TYPE (CSTBIT_INS)) && (!IS_INSN_TYPE (LD_STOR_INS)))
  574. (sign_flag) ? func (stream, "%s", "*-"): func (stream, "%s","*+");
  575. /* PR 10173: Avoid printing the 0x prefix twice. */
  576. if (info->symtab_size > 0)
  577. func (stream, "%s", "0x");
  578. number = ((relative ? memaddr : 0) +
  579. (sign_flag ? ((- a->constant) & 0xffffffe) : a->constant));
  580. (*info->print_address_func) ((number & ((1 << 24) - 1)), info);
  581. func (stream, "%s", print_exp_len (instruction->size * 16));
  582. break;
  583. default:
  584. break;
  585. }
  586. }
  587. /* Print all the arguments of CURRINSN instruction. */
  588. static void
  589. print_arguments (ins *currentInsn, bfd_vma memaddr, struct disassemble_info *info)
  590. {
  591. int i;
  592. /* For "pop/push/popret RA instruction only. */
  593. if ((IS_INSN_MNEMONIC ("pop")
  594. || (IS_INSN_MNEMONIC ("popret")
  595. || (IS_INSN_MNEMONIC ("push"))))
  596. && currentInsn->nargs == 1)
  597. {
  598. info->fprintf_func (info->stream, "RA");
  599. return;
  600. }
  601. for (i = 0; i < currentInsn->nargs; i++)
  602. {
  603. processing_argument_number = i;
  604. /* For "bal (ra), disp17" instruction only. */
  605. if ((IS_INSN_MNEMONIC ("bal")) && (i == 0) && instruction->size == 2)
  606. {
  607. info->fprintf_func (info->stream, "(ra),");
  608. continue;
  609. }
  610. if ((INST_HAS_REG_LIST) && (i == 2))
  611. info->fprintf_func (info->stream, "RA");
  612. else
  613. print_arg (&currentInsn->arg[i], memaddr, info);
  614. if ((i != currentInsn->nargs - 1) && (!IS_INSN_MNEMONIC ("b")))
  615. info->fprintf_func (info->stream, ",");
  616. }
  617. }
  618. /* Build the instruction's arguments. */
  619. void
  620. cr16_make_instruction (void)
  621. {
  622. int i;
  623. unsigned int shift;
  624. for (i = 0; i < cr16_currInsn.nargs; i++)
  625. {
  626. argument a;
  627. memset (&a, 0, sizeof (a));
  628. a.type = getargtype (instruction->operands[i].op_type);
  629. a.size = getbits (instruction->operands[i].op_type);
  630. shift = instruction->operands[i].shift;
  631. make_argument (&a, shift);
  632. cr16_currInsn.arg[i] = a;
  633. }
  634. /* Calculate instruction size (in bytes). */
  635. cr16_currInsn.size = instruction->size + (size_changed ? 1 : 0);
  636. /* Now in bits. */
  637. cr16_currInsn.size *= 2;
  638. }
  639. /* Retrieve a single word from a given memory address. */
  640. static wordU
  641. get_word_at_PC (bfd_vma memaddr, struct disassemble_info *info)
  642. {
  643. bfd_byte buffer[4];
  644. int status;
  645. wordU insn = 0;
  646. status = info->read_memory_func (memaddr, buffer, 2, info);
  647. if (status == 0)
  648. insn = (wordU) bfd_getl16 (buffer);
  649. return insn;
  650. }
  651. /* Retrieve multiple words (3) from a given memory address. */
  652. static void
  653. get_words_at_PC (bfd_vma memaddr, struct disassemble_info *info)
  654. {
  655. int i;
  656. bfd_vma mem;
  657. for (i = 0, mem = memaddr; i < 3; i++, mem += 2)
  658. cr16_words[i] = get_word_at_PC (mem, info);
  659. cr16_allWords = ((ULONGLONG) cr16_words[0] << 32)
  660. + ((unsigned long) cr16_words[1] << 16) + cr16_words[2];
  661. }
  662. /* Prints the instruction by calling print_arguments after proper matching. */
  663. int
  664. print_insn_cr16 (bfd_vma memaddr, struct disassemble_info *info)
  665. {
  666. int is_decoded; /* Nonzero means instruction has a match. */
  667. /* Initialize global variables. */
  668. imm4flag = 0;
  669. size_changed = 0;
  670. /* Retrieve the encoding from current memory location. */
  671. get_words_at_PC (memaddr, info);
  672. /* Find a matching opcode in table. */
  673. is_decoded = cr16_match_opcode ();
  674. /* If found, print the instruction's mnemonic and arguments. */
  675. if (is_decoded > 0 && (cr16_words[0] << 16 || cr16_words[1]) != 0)
  676. {
  677. if (strneq (instruction->mnemonic, "cinv", 4))
  678. info->fprintf_func (info->stream,"%s", getcinvstring (instruction->mnemonic));
  679. else
  680. info->fprintf_func (info->stream, "%s", instruction->mnemonic);
  681. if (((cr16_currInsn.nargs = get_number_of_operands ()) != 0)
  682. && ! (IS_INSN_MNEMONIC ("b")))
  683. info->fprintf_func (info->stream, "\t");
  684. cr16_make_instruction ();
  685. /* For push/pop/pushrtn with RA instructions. */
  686. if ((INST_HAS_REG_LIST) && ((cr16_words[0] >> 7) & 0x1))
  687. cr16_currInsn.nargs +=1;
  688. print_arguments (&cr16_currInsn, memaddr, info);
  689. return cr16_currInsn.size;
  690. }
  691. /* No match found. */
  692. info->fprintf_func (info->stream,"%s ",ILLEGAL);
  693. return 2;
  694. }