visium-dis.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. /* Single instruction disassembler for the Visium.
  2. Copyright (C) 2002-2022 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 "disassemble.h"
  18. #include "opcode/visium.h"
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <setjmp.h>
  24. /* Maximum length of an instruction. */
  25. #define MAXLEN 4
  26. struct private
  27. {
  28. /* Points to first byte not fetched. */
  29. bfd_byte *max_fetched;
  30. bfd_byte the_buffer[MAXLEN];
  31. bfd_vma insn_start;
  32. jmp_buf bailout;
  33. };
  34. /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
  35. to ADDR (exclusive) are valid. Returns 1 for success, longjmps
  36. on error. */
  37. #define FETCH_DATA(info, addr) \
  38. ((addr) <= ((struct private *)(info->private_data))->max_fetched \
  39. ? 1 : fetch_data ((info), (addr)))
  40. static int fetch_data (struct disassemble_info *info, bfd_byte * addr);
  41. static int
  42. fetch_data (struct disassemble_info *info, bfd_byte *addr)
  43. {
  44. int status;
  45. struct private *priv = (struct private *) info->private_data;
  46. bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
  47. status = (*info->read_memory_func) (start,
  48. priv->max_fetched,
  49. addr - priv->max_fetched, info);
  50. if (status != 0)
  51. {
  52. (*info->memory_error_func) (status, start, info);
  53. longjmp (priv->bailout, 1);
  54. }
  55. else
  56. priv->max_fetched = addr;
  57. return 1;
  58. }
  59. static char *size_names[] = { "?", "b", "w", "?", "l", "?", "?", "?" };
  60. static char *cc_names[] =
  61. {
  62. "fa", "eq", "cs", "os", "ns", "ne", "cc", "oc",
  63. "nc", "ge", "gt", "hi", "le", "ls", "lt", "tr"
  64. };
  65. /* Disassemble non-storage relative instructions. */
  66. static int
  67. disassem_class0 (disassemble_info *info, unsigned int ins)
  68. {
  69. int opcode = (ins >> 21) & 0x000f;
  70. if (ins & CLASS0_UNUSED_MASK)
  71. goto illegal_opcode;
  72. switch (opcode)
  73. {
  74. case 0:
  75. /* BRR instruction. */
  76. {
  77. unsigned cbf = (ins >> 27) & 0x000f;
  78. int displacement = ((ins & 0xffff) ^ 0x8000) - 0x8000;
  79. if (ins == 0)
  80. (*info->fprintf_func) (info->stream, "nop");
  81. else
  82. (*info->fprintf_func) (info->stream, "brr %s,%+d",
  83. cc_names[cbf], displacement);
  84. }
  85. break;
  86. case 1:
  87. /* Illegal opcode. */
  88. goto illegal_opcode;
  89. break;
  90. case 2:
  91. /* Illegal opcode. */
  92. goto illegal_opcode;
  93. break;
  94. case 3:
  95. /* Illegal opcode. */
  96. goto illegal_opcode;
  97. break;
  98. case 4:
  99. /* Illegal opcode. */
  100. goto illegal_opcode;
  101. break;
  102. case 5:
  103. /* Illegal opcode. */
  104. goto illegal_opcode;
  105. break;
  106. case 6:
  107. /* Illegal opcode. */
  108. goto illegal_opcode;
  109. break;
  110. case 7:
  111. /* Illegal opcode. */
  112. goto illegal_opcode;
  113. break;
  114. case 8:
  115. /* Illegal opcode. */
  116. goto illegal_opcode;
  117. break;
  118. case 9:
  119. /* Illegal opcode. */
  120. goto illegal_opcode;
  121. break;
  122. case 10:
  123. /* Illegal opcode. */
  124. goto illegal_opcode;
  125. break;
  126. case 11:
  127. /* Illegal opcode. */
  128. goto illegal_opcode;
  129. break;
  130. case 12:
  131. /* Illegal opcode. */
  132. goto illegal_opcode;
  133. break;
  134. case 13:
  135. /* Illegal opcode. */
  136. goto illegal_opcode;
  137. break;
  138. case 14:
  139. /* Illegal opcode. */
  140. goto illegal_opcode;
  141. break;
  142. case 15:
  143. /* Illegal opcode. */
  144. goto illegal_opcode;
  145. break;
  146. }
  147. return 0;
  148. illegal_opcode:
  149. return -1;
  150. }
  151. /* Disassemble non-storage register class instructions. */
  152. static int
  153. disassem_class1 (disassemble_info *info, unsigned int ins)
  154. {
  155. int opcode = (ins >> 21) & 0xf;
  156. int source_a = (ins >> 16) & 0x1f;
  157. int source_b = (ins >> 4) & 0x1f;
  158. int indx = (ins >> 10) & 0x1f;
  159. int size = ins & 0x7;
  160. if (ins & CLASS1_UNUSED_MASK)
  161. goto illegal_opcode;
  162. switch (opcode)
  163. {
  164. case 0:
  165. /* Stop. */
  166. (*info->fprintf_func) (info->stream, "stop %d,r%d", indx, source_a);
  167. break;
  168. case 1:
  169. /* BMI - Block Move Indirect. */
  170. if (ins != BMI)
  171. goto illegal_opcode;
  172. (*info->fprintf_func) (info->stream, "bmi r1,r2,r3");
  173. break;
  174. case 2:
  175. /* Illegal opcode. */
  176. goto illegal_opcode;
  177. break;
  178. case 3:
  179. /* BMD - Block Move Direct. */
  180. if (ins != BMD)
  181. goto illegal_opcode;
  182. (*info->fprintf_func) (info->stream, "bmd r1,r2,r3");
  183. break;
  184. case 4:
  185. /* DSI - Disable Interrupts. */
  186. if (ins != DSI)
  187. goto illegal_opcode;
  188. (*info->fprintf_func) (info->stream, "dsi");
  189. break;
  190. case 5:
  191. /* ENI - Enable Interrupts. */
  192. if (ins != ENI)
  193. goto illegal_opcode;
  194. (*info->fprintf_func) (info->stream, "eni");
  195. break;
  196. case 6:
  197. /* Illegal opcode (was EUT). */
  198. goto illegal_opcode;
  199. break;
  200. case 7:
  201. /* RFI - Return from Interrupt. */
  202. if (ins != RFI)
  203. goto illegal_opcode;
  204. (*info->fprintf_func) (info->stream, "rfi");
  205. break;
  206. case 8:
  207. /* Illegal opcode. */
  208. goto illegal_opcode;
  209. break;
  210. case 9:
  211. /* Illegal opcode. */
  212. goto illegal_opcode;
  213. break;
  214. case 10:
  215. /* Illegal opcode. */
  216. goto illegal_opcode;
  217. break;
  218. case 11:
  219. /* Illegal opcode. */
  220. goto illegal_opcode;
  221. break;
  222. case 12:
  223. /* Illegal opcode. */
  224. goto illegal_opcode;
  225. break;
  226. case 13:
  227. goto illegal_opcode;
  228. break;
  229. case 14:
  230. goto illegal_opcode;
  231. break;
  232. case 15:
  233. if (ins & EAM_SELECT_MASK)
  234. {
  235. /* Extension arithmetic module write */
  236. int fp_ins = (ins >> 27) & 0xf;
  237. if (size != 4)
  238. goto illegal_opcode;
  239. if (ins & FP_SELECT_MASK)
  240. {
  241. /* Which floating point instructions don't need a fsrcB
  242. register. */
  243. const int no_fsrcb[16] = { 1, 0, 0, 0, 0, 1, 1, 1,
  244. 1, 1, 0, 0, 1, 0, 0, 0
  245. };
  246. if (no_fsrcb[fp_ins] && source_b)
  247. goto illegal_opcode;
  248. /* Check that none of the floating register register numbers
  249. is higher than 15. (If this is fload, then srcA is a
  250. general register. */
  251. if (ins & ((1 << 14) | (1 << 8)) || (fp_ins && ins & (1 << 20)))
  252. goto illegal_opcode;
  253. switch (fp_ins)
  254. {
  255. case 0:
  256. (*info->fprintf_func) (info->stream, "fload f%d,r%d",
  257. indx, source_a);
  258. break;
  259. case 1:
  260. (*info->fprintf_func) (info->stream, "fadd f%d,f%d,f%d",
  261. indx, source_a, source_b);
  262. break;
  263. case 2:
  264. (*info->fprintf_func) (info->stream, "fsub f%d,f%d,f%d",
  265. indx, source_a, source_b);
  266. break;
  267. case 3:
  268. (*info->fprintf_func) (info->stream, "fmult f%d,f%d,f%d",
  269. indx, source_a, source_b);
  270. break;
  271. case 4:
  272. (*info->fprintf_func) (info->stream, "fdiv f%d,f%d,f%d",
  273. indx, source_a, source_b);
  274. break;
  275. case 5:
  276. (*info->fprintf_func) (info->stream, "fsqrt f%d,f%d",
  277. indx, source_a);
  278. break;
  279. case 6:
  280. (*info->fprintf_func) (info->stream, "fneg f%d,f%d",
  281. indx, source_a);
  282. break;
  283. case 7:
  284. (*info->fprintf_func) (info->stream, "fabs f%d,f%d",
  285. indx, source_a);
  286. break;
  287. case 8:
  288. (*info->fprintf_func) (info->stream, "ftoi f%d,f%d",
  289. indx, source_a);
  290. break;
  291. case 9:
  292. (*info->fprintf_func) (info->stream, "itof f%d,f%d",
  293. indx, source_a);
  294. break;
  295. case 12:
  296. (*info->fprintf_func) (info->stream, "fmove f%d,f%d",
  297. indx, source_a);
  298. break;
  299. default:
  300. (*info->fprintf_func) (info->stream,
  301. "fpinst %d,f%d,f%d,f%d", fp_ins,
  302. indx, source_a, source_b);
  303. break;
  304. }
  305. }
  306. else
  307. {
  308. /* Which EAM operations do not need a srcB register. */
  309. const int no_srcb[32] =
  310. { 0, 0, 1, 1, 0, 1, 1, 1,
  311. 0, 1, 1, 1, 0, 0, 0, 0,
  312. 0, 0, 0, 0, 0, 0, 0, 0,
  313. 0, 0, 0, 0, 0, 0, 0, 0
  314. };
  315. if (no_srcb[indx] && source_b)
  316. goto illegal_opcode;
  317. if (fp_ins)
  318. goto illegal_opcode;
  319. switch (indx)
  320. {
  321. case 0:
  322. (*info->fprintf_func) (info->stream, "mults r%d,r%d",
  323. source_a, source_b);
  324. break;
  325. case 1:
  326. (*info->fprintf_func) (info->stream, "multu r%d,r%d",
  327. source_a, source_b);
  328. break;
  329. case 2:
  330. (*info->fprintf_func) (info->stream, "divs r%d",
  331. source_a);
  332. break;
  333. case 3:
  334. (*info->fprintf_func) (info->stream, "divu r%d",
  335. source_a);
  336. break;
  337. case 4:
  338. (*info->fprintf_func) (info->stream, "writemd r%d,r%d",
  339. source_a, source_b);
  340. break;
  341. case 5:
  342. (*info->fprintf_func) (info->stream, "writemdc r%d",
  343. source_a);
  344. break;
  345. case 6:
  346. (*info->fprintf_func) (info->stream, "divds r%d",
  347. source_a);
  348. break;
  349. case 7:
  350. (*info->fprintf_func) (info->stream, "divdu r%d",
  351. source_a);
  352. break;
  353. case 9:
  354. (*info->fprintf_func) (info->stream, "asrd r%d",
  355. source_a);
  356. break;
  357. case 10:
  358. (*info->fprintf_func) (info->stream, "lsrd r%d",
  359. source_a);
  360. break;
  361. case 11:
  362. (*info->fprintf_func) (info->stream, "asld r%d",
  363. source_a);
  364. break;
  365. default:
  366. (*info->fprintf_func) (info->stream,
  367. "eamwrite %d,r%d,r%d", indx,
  368. source_a, source_b);
  369. break;
  370. }
  371. }
  372. }
  373. else
  374. {
  375. /* WRITE - write to memory. */
  376. (*info->fprintf_func) (info->stream, "write.%s %d(r%d),r%d",
  377. size_names[size], indx, source_a, source_b);
  378. }
  379. break;
  380. }
  381. return 0;
  382. illegal_opcode:
  383. return -1;
  384. }
  385. /* Disassemble storage immediate class instructions. */
  386. static int
  387. disassem_class2 (disassemble_info *info, unsigned int ins)
  388. {
  389. int opcode = (ins >> 21) & 0xf;
  390. int source_a = (ins >> 16) & 0x1f;
  391. unsigned immediate = ins & 0x0000ffff;
  392. if (ins & CC_MASK)
  393. goto illegal_opcode;
  394. switch (opcode)
  395. {
  396. case 0:
  397. /* ADDI instruction. */
  398. (*info->fprintf_func) (info->stream, "addi r%d,%d", source_a,
  399. immediate);
  400. break;
  401. case 1:
  402. /* Illegal opcode. */
  403. goto illegal_opcode;
  404. break;
  405. case 2:
  406. /* SUBI instruction. */
  407. (*info->fprintf_func) (info->stream, "subi r%d,%d", source_a,
  408. immediate);
  409. break;
  410. case 3:
  411. /* Illegal opcode. */
  412. goto illegal_opcode;
  413. break;
  414. case 4:
  415. /* MOVIL instruction. */
  416. (*info->fprintf_func) (info->stream, "movil r%d,0x%04X", source_a,
  417. immediate);
  418. break;
  419. case 5:
  420. /* MOVIU instruction. */
  421. (*info->fprintf_func) (info->stream, "moviu r%d,0x%04X", source_a,
  422. immediate);
  423. break;
  424. case 6:
  425. /* MOVIQ instruction. */
  426. (*info->fprintf_func) (info->stream, "moviq r%d,%u", source_a,
  427. immediate);
  428. break;
  429. case 7:
  430. /* Illegal opcode. */
  431. goto illegal_opcode;
  432. break;
  433. case 8:
  434. /* WRTL instruction. */
  435. if (source_a != 0)
  436. goto illegal_opcode;
  437. (*info->fprintf_func) (info->stream, "wrtl 0x%04X", immediate);
  438. break;
  439. case 9:
  440. /* WRTU instruction. */
  441. if (source_a != 0)
  442. goto illegal_opcode;
  443. (*info->fprintf_func) (info->stream, "wrtu 0x%04X", immediate);
  444. break;
  445. case 10:
  446. /* Illegal opcode. */
  447. goto illegal_opcode;
  448. break;
  449. case 11:
  450. /* Illegal opcode. */
  451. goto illegal_opcode;
  452. break;
  453. case 12:
  454. /* Illegal opcode. */
  455. goto illegal_opcode;
  456. break;
  457. case 13:
  458. /* Illegal opcode. */
  459. goto illegal_opcode;
  460. break;
  461. case 14:
  462. /* Illegal opcode. */
  463. goto illegal_opcode;
  464. break;
  465. case 15:
  466. /* Illegal opcode. */
  467. goto illegal_opcode;
  468. break;
  469. }
  470. return 0;
  471. illegal_opcode:
  472. return -1;
  473. }
  474. /* Disassemble storage register class instructions. */
  475. static int
  476. disassem_class3 (disassemble_info *info, unsigned int ins)
  477. {
  478. int opcode = (ins >> 21) & 0xf;
  479. int source_b = (ins >> 4) & 0x1f;
  480. int source_a = (ins >> 16) & 0x1f;
  481. int size = ins & 0x7;
  482. int dest = (ins >> 10) & 0x1f;
  483. /* Those instructions that don't have a srcB register. */
  484. const int no_srcb[16] =
  485. { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 };
  486. /* These are instructions which can take an immediate srcB value. */
  487. const int srcb_immed[16] =
  488. { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 };
  489. /* User opcodes should not provide a non-zero srcB register
  490. when none is required. Only a BRA or floating point
  491. instruction should have a non-zero condition code field.
  492. Only a WRITE or EAMWRITE (opcode 15) should select an EAM
  493. or floating point operation. Note that FP_SELECT_MASK is
  494. the same bit (bit 3) as the interrupt bit which
  495. distinguishes SYS1 from BRA and SYS2 from RFLAG. */
  496. if ((no_srcb[opcode] && source_b)
  497. || (!srcb_immed[opcode] && ins & CLASS3_SOURCEB_IMMED)
  498. || (opcode != 12 && opcode != 15 && ins & CC_MASK)
  499. || (opcode != 15 && ins & (EAM_SELECT_MASK | FP_SELECT_MASK)))
  500. goto illegal_opcode;
  501. switch (opcode)
  502. {
  503. case 0:
  504. /* ADD instruction. */
  505. (*info->fprintf_func) (info->stream, "add.%s r%d,r%d,r%d",
  506. size_names[size], dest, source_a, source_b);
  507. break;
  508. case 1:
  509. /* ADC instruction. */
  510. (*info->fprintf_func) (info->stream, "adc.%s r%d,r%d,r%d",
  511. size_names[size], dest, source_a, source_b);
  512. break;
  513. case 2:
  514. /* SUB instruction. */
  515. if (dest == 0)
  516. (*info->fprintf_func) (info->stream, "cmp.%s r%d,r%d",
  517. size_names[size], source_a, source_b);
  518. else
  519. (*info->fprintf_func) (info->stream, "sub.%s r%d,r%d,r%d",
  520. size_names[size], dest, source_a, source_b);
  521. break;
  522. case 3:
  523. /* SUBC instruction. */
  524. if (dest == 0)
  525. (*info->fprintf_func) (info->stream, "cmpc.%s r%d,r%d",
  526. size_names[size], source_a, source_b);
  527. else
  528. (*info->fprintf_func) (info->stream, "subc.%s r%d,r%d,r%d",
  529. size_names[size], dest, source_a, source_b);
  530. break;
  531. case 4:
  532. /* EXTW instruction. */
  533. if (size == 1)
  534. goto illegal_opcode;
  535. (*info->fprintf_func) (info->stream, "extw.%s r%d,r%d",
  536. size_names[size], dest, source_a);
  537. break;
  538. case 5:
  539. /* ASR instruction. */
  540. if (ins & CLASS3_SOURCEB_IMMED)
  541. (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,%d",
  542. size_names[size], dest, source_a, source_b);
  543. else
  544. (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,r%d",
  545. size_names[size], dest, source_a, source_b);
  546. break;
  547. case 6:
  548. /* LSR instruction. */
  549. if (ins & CLASS3_SOURCEB_IMMED)
  550. (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,%d",
  551. size_names[size], dest, source_a, source_b);
  552. else
  553. (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,r%d",
  554. size_names[size], dest, source_a, source_b);
  555. break;
  556. case 7:
  557. /* ASL instruction. */
  558. if (ins & CLASS3_SOURCEB_IMMED)
  559. (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,%d",
  560. size_names[size], dest, source_a, source_b);
  561. else
  562. (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,r%d",
  563. size_names[size], dest, source_a, source_b);
  564. break;
  565. case 8:
  566. /* XOR instruction. */
  567. (*info->fprintf_func) (info->stream, "xor.%s r%d,r%d,r%d",
  568. size_names[size], dest, source_a, source_b);
  569. break;
  570. case 9:
  571. /* OR instruction. */
  572. if (source_b == 0)
  573. (*info->fprintf_func) (info->stream, "move.%s r%d,r%d",
  574. size_names[size], dest, source_a);
  575. else
  576. (*info->fprintf_func) (info->stream, "or.%s r%d,r%d,r%d",
  577. size_names[size], dest, source_a, source_b);
  578. break;
  579. case 10:
  580. /* AND instruction. */
  581. (*info->fprintf_func) (info->stream, "and.%s r%d,r%d,r%d",
  582. size_names[size], dest, source_a, source_b);
  583. break;
  584. case 11:
  585. /* NOT instruction. */
  586. (*info->fprintf_func) (info->stream, "not.%s r%d,r%d",
  587. size_names[size], dest, source_a);
  588. break;
  589. case 12:
  590. /* BRA instruction. */
  591. {
  592. unsigned cbf = (ins >> 27) & 0x000f;
  593. if (size != 4)
  594. goto illegal_opcode;
  595. (*info->fprintf_func) (info->stream, "bra %s,r%d,r%d",
  596. cc_names[cbf], source_a, dest);
  597. }
  598. break;
  599. case 13:
  600. /* RFLAG instruction. */
  601. if (source_a || size != 4)
  602. goto illegal_opcode;
  603. (*info->fprintf_func) (info->stream, "rflag r%d", dest);
  604. break;
  605. case 14:
  606. /* EXTB instruction. */
  607. (*info->fprintf_func) (info->stream, "extb.%s r%d,r%d",
  608. size_names[size], dest, source_a);
  609. break;
  610. case 15:
  611. if (!(ins & CLASS3_SOURCEB_IMMED))
  612. goto illegal_opcode;
  613. if (ins & EAM_SELECT_MASK)
  614. {
  615. /* Extension arithmetic module read. */
  616. int fp_ins = (ins >> 27) & 0xf;
  617. if (size != 4)
  618. goto illegal_opcode;
  619. if (ins & FP_SELECT_MASK)
  620. {
  621. /* Check fsrcA <= 15 and fsrcB <= 15. */
  622. if (ins & ((1 << 20) | (1 << 8)))
  623. goto illegal_opcode;
  624. switch (fp_ins)
  625. {
  626. case 0:
  627. if (source_b)
  628. goto illegal_opcode;
  629. (*info->fprintf_func) (info->stream, "fstore r%d,f%d",
  630. dest, source_a);
  631. break;
  632. case 10:
  633. (*info->fprintf_func) (info->stream, "fcmp r%d,f%d,f%d",
  634. dest, source_a, source_b);
  635. break;
  636. case 11:
  637. (*info->fprintf_func) (info->stream, "fcmpe r%d,f%d,f%d",
  638. dest, source_a, source_b);
  639. break;
  640. default:
  641. (*info->fprintf_func) (info->stream,
  642. "fpuread %d,r%d,f%d,f%d", fp_ins,
  643. dest, source_a, source_b);
  644. break;
  645. }
  646. }
  647. else
  648. {
  649. if (fp_ins || source_a)
  650. goto illegal_opcode;
  651. switch (source_b)
  652. {
  653. case 0:
  654. (*info->fprintf_func) (info->stream, "readmda r%d", dest);
  655. break;
  656. case 1:
  657. (*info->fprintf_func) (info->stream, "readmdb r%d", dest);
  658. break;
  659. case 2:
  660. (*info->fprintf_func) (info->stream, "readmdc r%d", dest);
  661. break;
  662. default:
  663. (*info->fprintf_func) (info->stream, "eamread r%d,%d",
  664. dest, source_b);
  665. break;
  666. }
  667. }
  668. }
  669. else
  670. {
  671. if (ins & FP_SELECT_MASK)
  672. goto illegal_opcode;
  673. /* READ instruction. */
  674. (*info->fprintf_func) (info->stream, "read.%s r%d,%d(r%d)",
  675. size_names[size], dest, source_b, source_a);
  676. }
  677. break;
  678. }
  679. return 0;
  680. illegal_opcode:
  681. return -1;
  682. }
  683. /* Print the visium instruction at address addr in debugged memory,
  684. on info->stream. Return length of the instruction, in bytes. */
  685. int
  686. print_insn_visium (bfd_vma addr, disassemble_info *info)
  687. {
  688. unsigned ins;
  689. unsigned p1, p2;
  690. int ans;
  691. int i;
  692. /* Stuff copied from m68k-dis.c. */
  693. struct private priv;
  694. bfd_byte *buffer = priv.the_buffer;
  695. info->private_data = (PTR) & priv;
  696. priv.max_fetched = priv.the_buffer;
  697. priv.insn_start = addr;
  698. if (setjmp (priv.bailout) != 0)
  699. {
  700. /* Error return. */
  701. return -1;
  702. }
  703. /* We do return this info. */
  704. info->insn_info_valid = 1;
  705. /* Assume non branch insn. */
  706. info->insn_type = dis_nonbranch;
  707. /* Assume no delay. */
  708. info->branch_delay_insns = 0;
  709. /* Assume no target known. */
  710. info->target = 0;
  711. /* Get 32-bit instruction word. */
  712. FETCH_DATA (info, buffer + 4);
  713. ins = (unsigned) buffer[0] << 24;
  714. ins |= buffer[1] << 16;
  715. ins |= buffer[2] << 8;
  716. ins |= buffer[3];
  717. ans = 0;
  718. p1 = buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3];
  719. p2 = 0;
  720. for (i = 0; i < 8; i++)
  721. {
  722. p2 += p1 & 1;
  723. p1 >>= 1;
  724. }
  725. /* Decode the instruction. */
  726. if (p2 & 1)
  727. ans = -1;
  728. else
  729. {
  730. switch ((ins >> 25) & 0x3)
  731. {
  732. case 0:
  733. ans = disassem_class0 (info, ins);
  734. break;
  735. case 1:
  736. ans = disassem_class1 (info, ins);
  737. break;
  738. case 2:
  739. ans = disassem_class2 (info, ins);
  740. break;
  741. case 3:
  742. ans = disassem_class3 (info, ins);
  743. break;
  744. }
  745. }
  746. if (ans != 0)
  747. (*info->fprintf_func) (info->stream, "err");
  748. /* Return number of bytes consumed (always 4 for the Visium). */
  749. return 4;
  750. }