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). */