cr16-dis.c 20 KB

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