1 /* Single instruction disassembler for the Visium.
3 Copyright (C) 2002-2019 Free Software Foundation, Inc.
5 This file is part of the GNU opcodes library.
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
23 #include "disassemble.h"
24 #include "opcode/visium.h"
32 /* Maximum length of an instruction. */
37 /* Points to first byte not fetched. */
38 bfd_byte *max_fetched;
39 bfd_byte the_buffer[MAXLEN];
44 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
45 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
47 #define FETCH_DATA(info, addr) \
48 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
49 ? 1 : fetch_data ((info), (addr)))
51 static int fetch_data (struct disassemble_info *info, bfd_byte * addr);
54 fetch_data (struct disassemble_info *info, bfd_byte *addr)
57 struct private *priv = (struct private *) info->private_data;
58 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
60 status = (*info->read_memory_func) (start,
62 addr - priv->max_fetched, info);
65 (*info->memory_error_func) (status, start, info);
66 longjmp (priv->bailout, 1);
69 priv->max_fetched = addr;
73 static char *size_names[] = { "?", "b", "w", "?", "l", "?", "?", "?" };
75 static char *cc_names[] =
77 "fa", "eq", "cs", "os", "ns", "ne", "cc", "oc",
78 "nc", "ge", "gt", "hi", "le", "ls", "lt", "tr"
81 /* Disassemble non-storage relative instructions. */
84 disassem_class0 (disassemble_info *info, unsigned int ins)
86 int opcode = (ins >> 21) & 0x000f;
88 if (ins & CLASS0_UNUSED_MASK)
94 /* BRR instruction. */
96 unsigned cbf = (ins >> 27) & 0x000f;
97 int displacement = ((int) (ins << 16)) >> 16;
100 (*info->fprintf_func) (info->stream, "nop");
102 (*info->fprintf_func) (info->stream, "brr %s,%+d",
103 cc_names[cbf], displacement);
107 /* Illegal opcode. */
111 /* Illegal opcode. */
115 /* Illegal opcode. */
119 /* Illegal opcode. */
123 /* Illegal opcode. */
127 /* Illegal opcode. */
131 /* Illegal opcode. */
135 /* Illegal opcode. */
139 /* Illegal opcode. */
143 /* Illegal opcode. */
147 /* Illegal opcode. */
151 /* Illegal opcode. */
155 /* Illegal opcode. */
159 /* Illegal opcode. */
163 /* Illegal opcode. */
173 /* Disassemble non-storage register class instructions. */
176 disassem_class1 (disassemble_info *info, unsigned int ins)
178 int opcode = (ins >> 21) & 0xf;
179 int source_a = (ins >> 16) & 0x1f;
180 int source_b = (ins >> 4) & 0x1f;
181 int indx = (ins >> 10) & 0x1f;
183 int size = ins & 0x7;
185 if (ins & CLASS1_UNUSED_MASK)
192 (*info->fprintf_func) (info->stream, "stop %d,r%d", indx, source_a);
195 /* BMI - Block Move Indirect. */
199 (*info->fprintf_func) (info->stream, "bmi r1,r2,r3");
202 /* Illegal opcode. */
206 /* BMD - Block Move Direct. */
210 (*info->fprintf_func) (info->stream, "bmd r1,r2,r3");
213 /* DSI - Disable Interrupts. */
217 (*info->fprintf_func) (info->stream, "dsi");
221 /* ENI - Enable Interrupts. */
225 (*info->fprintf_func) (info->stream, "eni");
229 /* Illegal opcode (was EUT). */
233 /* RFI - Return from Interrupt. */
237 (*info->fprintf_func) (info->stream, "rfi");
240 /* Illegal opcode. */
244 /* Illegal opcode. */
248 /* Illegal opcode. */
252 /* Illegal opcode. */
256 /* Illegal opcode. */
266 if (ins & EAM_SELECT_MASK)
268 /* Extension arithmetic module write */
269 int fp_ins = (ins >> 27) & 0xf;
274 if (ins & FP_SELECT_MASK)
276 /* Which floating point instructions don't need a fsrcB
278 const int no_fsrcb[16] = { 1, 0, 0, 0, 0, 1, 1, 1,
279 1, 1, 0, 0, 1, 0, 0, 0
281 if (no_fsrcb[fp_ins] && source_b)
284 /* Check that none of the floating register register numbers
285 is higher than 15. (If this is fload, then srcA is a
287 if (ins & ((1 << 14) | (1 << 8)) || (fp_ins && ins & (1 << 20)))
293 (*info->fprintf_func) (info->stream, "fload f%d,r%d",
297 (*info->fprintf_func) (info->stream, "fadd f%d,f%d,f%d",
298 indx, source_a, source_b);
301 (*info->fprintf_func) (info->stream, "fsub f%d,f%d,f%d",
302 indx, source_a, source_b);
305 (*info->fprintf_func) (info->stream, "fmult f%d,f%d,f%d",
306 indx, source_a, source_b);
309 (*info->fprintf_func) (info->stream, "fdiv f%d,f%d,f%d",
310 indx, source_a, source_b);
313 (*info->fprintf_func) (info->stream, "fsqrt f%d,f%d",
317 (*info->fprintf_func) (info->stream, "fneg f%d,f%d",
321 (*info->fprintf_func) (info->stream, "fabs f%d,f%d",
325 (*info->fprintf_func) (info->stream, "ftoi f%d,f%d",
329 (*info->fprintf_func) (info->stream, "itof f%d,f%d",
333 (*info->fprintf_func) (info->stream, "fmove f%d,f%d",
337 (*info->fprintf_func) (info->stream,
338 "fpinst %d,f%d,f%d,f%d", fp_ins,
339 indx, source_a, source_b);
345 /* Which EAM operations do not need a srcB register. */
346 const int no_srcb[32] =
347 { 0, 0, 1, 1, 0, 1, 1, 1,
348 0, 1, 1, 1, 0, 0, 0, 0,
349 0, 0, 0, 0, 0, 0, 0, 0,
350 0, 0, 0, 0, 0, 0, 0, 0
353 if (no_srcb[indx] && source_b)
362 (*info->fprintf_func) (info->stream, "mults r%d,r%d",
366 (*info->fprintf_func) (info->stream, "multu r%d,r%d",
370 (*info->fprintf_func) (info->stream, "divs r%d",
374 (*info->fprintf_func) (info->stream, "divu r%d",
378 (*info->fprintf_func) (info->stream, "writemd r%d,r%d",
382 (*info->fprintf_func) (info->stream, "writemdc r%d",
386 (*info->fprintf_func) (info->stream, "divds r%d",
390 (*info->fprintf_func) (info->stream, "divdu r%d",
394 (*info->fprintf_func) (info->stream, "asrd r%d",
398 (*info->fprintf_func) (info->stream, "lsrd r%d",
402 (*info->fprintf_func) (info->stream, "asld r%d",
406 (*info->fprintf_func) (info->stream,
407 "eamwrite %d,r%d,r%d", indx,
415 /* WRITE - write to memory. */
416 (*info->fprintf_func) (info->stream, "write.%s %d(r%d),r%d",
417 size_names[size], indx, source_a, source_b);
428 /* Disassemble storage immediate class instructions. */
431 disassem_class2 (disassemble_info *info, unsigned int ins)
433 int opcode = (ins >> 21) & 0xf;
434 int source_a = (ins >> 16) & 0x1f;
435 unsigned immediate = ins & 0x0000ffff;
443 /* ADDI instruction. */
444 (*info->fprintf_func) (info->stream, "addi r%d,%d", source_a,
448 /* Illegal opcode. */
452 /* SUBI instruction. */
453 (*info->fprintf_func) (info->stream, "subi r%d,%d", source_a,
457 /* Illegal opcode. */
461 /* MOVIL instruction. */
462 (*info->fprintf_func) (info->stream, "movil r%d,0x%04X", source_a,
466 /* MOVIU instruction. */
467 (*info->fprintf_func) (info->stream, "moviu r%d,0x%04X", source_a,
471 /* MOVIQ instruction. */
472 (*info->fprintf_func) (info->stream, "moviq r%d,%u", source_a,
476 /* Illegal opcode. */
480 /* WRTL instruction. */
484 (*info->fprintf_func) (info->stream, "wrtl 0x%04X", immediate);
487 /* WRTU instruction. */
491 (*info->fprintf_func) (info->stream, "wrtu 0x%04X", immediate);
494 /* Illegal opcode. */
498 /* Illegal opcode. */
502 /* Illegal opcode. */
506 /* Illegal opcode. */
510 /* Illegal opcode. */
514 /* Illegal opcode. */
525 /* Disassemble storage register class instructions. */
528 disassem_class3 (disassemble_info *info, unsigned int ins)
530 int opcode = (ins >> 21) & 0xf;
531 int source_b = (ins >> 4) & 0x1f;
532 int source_a = (ins >> 16) & 0x1f;
533 int size = ins & 0x7;
534 int dest = (ins >> 10) & 0x1f;
536 /* Those instructions that don't have a srcB register. */
537 const int no_srcb[16] =
538 { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 };
540 /* These are instructions which can take an immediate srcB value. */
541 const int srcb_immed[16] =
542 { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 };
544 /* User opcodes should not provide a non-zero srcB register
545 when none is required. Only a BRA or floating point
546 instruction should have a non-zero condition code field.
547 Only a WRITE or EAMWRITE (opcode 15) should select an EAM
548 or floating point operation. Note that FP_SELECT_MASK is
549 the same bit (bit 3) as the interrupt bit which
550 distinguishes SYS1 from BRA and SYS2 from RFLAG. */
551 if ((no_srcb[opcode] && source_b)
552 || (!srcb_immed[opcode] && ins & CLASS3_SOURCEB_IMMED)
553 || (opcode != 12 && opcode != 15 && ins & CC_MASK)
554 || (opcode != 15 && ins & (EAM_SELECT_MASK | FP_SELECT_MASK)))
561 /* ADD instruction. */
562 (*info->fprintf_func) (info->stream, "add.%s r%d,r%d,r%d",
563 size_names[size], dest, source_a, source_b);
566 /* ADC instruction. */
567 (*info->fprintf_func) (info->stream, "adc.%s r%d,r%d,r%d",
568 size_names[size], dest, source_a, source_b);
571 /* SUB instruction. */
573 (*info->fprintf_func) (info->stream, "cmp.%s r%d,r%d",
574 size_names[size], source_a, source_b);
576 (*info->fprintf_func) (info->stream, "sub.%s r%d,r%d,r%d",
577 size_names[size], dest, source_a, source_b);
580 /* SUBC instruction. */
582 (*info->fprintf_func) (info->stream, "cmpc.%s r%d,r%d",
583 size_names[size], source_a, source_b);
585 (*info->fprintf_func) (info->stream, "subc.%s r%d,r%d,r%d",
586 size_names[size], dest, source_a, source_b);
589 /* EXTW instruction. */
593 (*info->fprintf_func) (info->stream, "extw.%s r%d,r%d",
594 size_names[size], dest, source_a);
597 /* ASR instruction. */
598 if (ins & CLASS3_SOURCEB_IMMED)
599 (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,%d",
600 size_names[size], dest, source_a, source_b);
602 (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,r%d",
603 size_names[size], dest, source_a, source_b);
606 /* LSR instruction. */
607 if (ins & CLASS3_SOURCEB_IMMED)
608 (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,%d",
609 size_names[size], dest, source_a, source_b);
611 (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,r%d",
612 size_names[size], dest, source_a, source_b);
615 /* ASL instruction. */
616 if (ins & CLASS3_SOURCEB_IMMED)
617 (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,%d",
618 size_names[size], dest, source_a, source_b);
620 (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,r%d",
621 size_names[size], dest, source_a, source_b);
624 /* XOR instruction. */
625 (*info->fprintf_func) (info->stream, "xor.%s r%d,r%d,r%d",
626 size_names[size], dest, source_a, source_b);
629 /* OR instruction. */
631 (*info->fprintf_func) (info->stream, "move.%s r%d,r%d",
632 size_names[size], dest, source_a);
634 (*info->fprintf_func) (info->stream, "or.%s r%d,r%d,r%d",
635 size_names[size], dest, source_a, source_b);
638 /* AND instruction. */
639 (*info->fprintf_func) (info->stream, "and.%s r%d,r%d,r%d",
640 size_names[size], dest, source_a, source_b);
643 /* NOT instruction. */
644 (*info->fprintf_func) (info->stream, "not.%s r%d,r%d",
645 size_names[size], dest, source_a);
648 /* BRA instruction. */
650 unsigned cbf = (ins >> 27) & 0x000f;
655 (*info->fprintf_func) (info->stream, "bra %s,r%d,r%d",
656 cc_names[cbf], source_a, dest);
660 /* RFLAG instruction. */
661 if (source_a || size != 4)
664 (*info->fprintf_func) (info->stream, "rflag r%d", dest);
667 /* EXTB instruction. */
668 (*info->fprintf_func) (info->stream, "extb.%s r%d,r%d",
669 size_names[size], dest, source_a);
672 if (!(ins & CLASS3_SOURCEB_IMMED))
675 if (ins & EAM_SELECT_MASK)
677 /* Extension arithmetic module read. */
678 int fp_ins = (ins >> 27) & 0xf;
683 if (ins & FP_SELECT_MASK)
685 /* Check fsrcA <= 15 and fsrcB <= 15. */
686 if (ins & ((1 << 20) | (1 << 8)))
695 (*info->fprintf_func) (info->stream, "fstore r%d,f%d",
699 (*info->fprintf_func) (info->stream, "fcmp r%d,f%d,f%d",
700 dest, source_a, source_b);
703 (*info->fprintf_func) (info->stream, "fcmpe r%d,f%d,f%d",
704 dest, source_a, source_b);
707 (*info->fprintf_func) (info->stream,
708 "fpuread %d,r%d,f%d,f%d", fp_ins,
709 dest, source_a, source_b);
715 if (fp_ins || source_a)
721 (*info->fprintf_func) (info->stream, "readmda r%d", dest);
724 (*info->fprintf_func) (info->stream, "readmdb r%d", dest);
727 (*info->fprintf_func) (info->stream, "readmdc r%d", dest);
730 (*info->fprintf_func) (info->stream, "eamread r%d,%d",
738 if (ins & FP_SELECT_MASK)
741 /* READ instruction. */
742 (*info->fprintf_func) (info->stream, "read.%s r%d,%d(r%d)",
743 size_names[size], dest, source_b, source_a);
755 /* Print the visium instruction at address addr in debugged memory,
756 on info->stream. Return length of the instruction, in bytes. */
759 print_insn_visium (bfd_vma addr, disassemble_info *info)
766 /* Stuff copied from m68k-dis.c. */
768 bfd_byte *buffer = priv.the_buffer;
769 info->private_data = (PTR) & priv;
770 priv.max_fetched = priv.the_buffer;
771 priv.insn_start = addr;
772 if (setjmp (priv.bailout) != 0)
778 /* We do return this info. */
779 info->insn_info_valid = 1;
781 /* Assume non branch insn. */
782 info->insn_type = dis_nonbranch;
784 /* Assume no delay. */
785 info->branch_delay_insns = 0;
787 /* Assume no target known. */
790 /* Get 32-bit instruction word. */
791 FETCH_DATA (info, buffer + 4);
792 ins = buffer[0] << 24;
793 ins |= buffer[1] << 16;
794 ins |= buffer[2] << 8;
799 p1 = buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3];
801 for (i = 0; i < 8; i++)
807 /* Decode the instruction. */
812 switch ((ins >> 25) & 0x3)
815 ans = disassem_class0 (info, ins);
818 ans = disassem_class1 (info, ins);
821 ans = disassem_class2 (info, ins);
824 ans = disassem_class3 (info, ins);
830 (*info->fprintf_func) (info->stream, "err");
832 /* Return number of bytes consumed (always 4 for the Visium). */