[opcodes, ARM, 14/16] Add mode availability to coprocessor table entries
[binutils-gdb.git] / opcodes / visium-dis.c
blobc71f8cf25ab3aea3270aa711ede5df5f6cb529c8
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)
10 any later version.
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. */
22 #include "sysdep.h"
23 #include "disassemble.h"
24 #include "opcode/visium.h"
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <setjmp.h>
32 /* Maximum length of an instruction. */
33 #define MAXLEN 4
35 struct private
37 /* Points to first byte not fetched. */
38 bfd_byte *max_fetched;
39 bfd_byte the_buffer[MAXLEN];
40 bfd_vma insn_start;
41 jmp_buf bailout;
44 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
45 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
46 on error. */
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);
53 static int
54 fetch_data (struct disassemble_info *info, bfd_byte *addr)
56 int status;
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,
61 priv->max_fetched,
62 addr - priv->max_fetched, info);
63 if (status != 0)
65 (*info->memory_error_func) (status, start, info);
66 longjmp (priv->bailout, 1);
68 else
69 priv->max_fetched = addr;
70 return 1;
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. */
83 static int
84 disassem_class0 (disassemble_info *info, unsigned int ins)
86 int opcode = (ins >> 21) & 0x000f;
88 if (ins & CLASS0_UNUSED_MASK)
89 goto illegal_opcode;
91 switch (opcode)
93 case 0:
94 /* BRR instruction. */
96 unsigned cbf = (ins >> 27) & 0x000f;
97 int displacement = ((int) (ins << 16)) >> 16;
99 if (ins == 0)
100 (*info->fprintf_func) (info->stream, "nop");
101 else
102 (*info->fprintf_func) (info->stream, "brr %s,%+d",
103 cc_names[cbf], displacement);
105 break;
106 case 1:
107 /* Illegal opcode. */
108 goto illegal_opcode;
109 break;
110 case 2:
111 /* Illegal opcode. */
112 goto illegal_opcode;
113 break;
114 case 3:
115 /* Illegal opcode. */
116 goto illegal_opcode;
117 break;
118 case 4:
119 /* Illegal opcode. */
120 goto illegal_opcode;
121 break;
122 case 5:
123 /* Illegal opcode. */
124 goto illegal_opcode;
125 break;
126 case 6:
127 /* Illegal opcode. */
128 goto illegal_opcode;
129 break;
130 case 7:
131 /* Illegal opcode. */
132 goto illegal_opcode;
133 break;
134 case 8:
135 /* Illegal opcode. */
136 goto illegal_opcode;
137 break;
138 case 9:
139 /* Illegal opcode. */
140 goto illegal_opcode;
141 break;
142 case 10:
143 /* Illegal opcode. */
144 goto illegal_opcode;
145 break;
146 case 11:
147 /* Illegal opcode. */
148 goto illegal_opcode;
149 break;
150 case 12:
151 /* Illegal opcode. */
152 goto illegal_opcode;
153 break;
154 case 13:
155 /* Illegal opcode. */
156 goto illegal_opcode;
157 break;
158 case 14:
159 /* Illegal opcode. */
160 goto illegal_opcode;
161 break;
162 case 15:
163 /* Illegal opcode. */
164 goto illegal_opcode;
165 break;
167 return 0;
169 illegal_opcode:
170 return -1;
173 /* Disassemble non-storage register class instructions. */
175 static int
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)
186 goto illegal_opcode;
188 switch (opcode)
190 case 0:
191 /* Stop. */
192 (*info->fprintf_func) (info->stream, "stop %d,r%d", indx, source_a);
193 break;
194 case 1:
195 /* BMI - Block Move Indirect. */
196 if (ins != BMI)
197 goto illegal_opcode;
199 (*info->fprintf_func) (info->stream, "bmi r1,r2,r3");
200 break;
201 case 2:
202 /* Illegal opcode. */
203 goto illegal_opcode;
204 break;
205 case 3:
206 /* BMD - Block Move Direct. */
207 if (ins != BMD)
208 goto illegal_opcode;
210 (*info->fprintf_func) (info->stream, "bmd r1,r2,r3");
211 break;
212 case 4:
213 /* DSI - Disable Interrupts. */
214 if (ins != DSI)
215 goto illegal_opcode;
217 (*info->fprintf_func) (info->stream, "dsi");
218 break;
220 case 5:
221 /* ENI - Enable Interrupts. */
222 if (ins != ENI)
223 goto illegal_opcode;
225 (*info->fprintf_func) (info->stream, "eni");
226 break;
228 case 6:
229 /* Illegal opcode (was EUT). */
230 goto illegal_opcode;
231 break;
232 case 7:
233 /* RFI - Return from Interrupt. */
234 if (ins != RFI)
235 goto illegal_opcode;
237 (*info->fprintf_func) (info->stream, "rfi");
238 break;
239 case 8:
240 /* Illegal opcode. */
241 goto illegal_opcode;
242 break;
243 case 9:
244 /* Illegal opcode. */
245 goto illegal_opcode;
246 break;
247 case 10:
248 /* Illegal opcode. */
249 goto illegal_opcode;
250 break;
251 case 11:
252 /* Illegal opcode. */
253 goto illegal_opcode;
254 break;
255 case 12:
256 /* Illegal opcode. */
257 goto illegal_opcode;
258 break;
259 case 13:
260 goto illegal_opcode;
261 break;
262 case 14:
263 goto illegal_opcode;
264 break;
265 case 15:
266 if (ins & EAM_SELECT_MASK)
268 /* Extension arithmetic module write */
269 int fp_ins = (ins >> 27) & 0xf;
271 if (size != 4)
272 goto illegal_opcode;
274 if (ins & FP_SELECT_MASK)
276 /* Which floating point instructions don't need a fsrcB
277 register. */
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)
282 goto illegal_opcode;
284 /* Check that none of the floating register register numbers
285 is higher than 15. (If this is fload, then srcA is a
286 general register. */
287 if (ins & ((1 << 14) | (1 << 8)) || (fp_ins && ins & (1 << 20)))
288 goto illegal_opcode;
290 switch (fp_ins)
292 case 0:
293 (*info->fprintf_func) (info->stream, "fload f%d,r%d",
294 indx, source_a);
295 break;
296 case 1:
297 (*info->fprintf_func) (info->stream, "fadd f%d,f%d,f%d",
298 indx, source_a, source_b);
299 break;
300 case 2:
301 (*info->fprintf_func) (info->stream, "fsub f%d,f%d,f%d",
302 indx, source_a, source_b);
303 break;
304 case 3:
305 (*info->fprintf_func) (info->stream, "fmult f%d,f%d,f%d",
306 indx, source_a, source_b);
307 break;
308 case 4:
309 (*info->fprintf_func) (info->stream, "fdiv f%d,f%d,f%d",
310 indx, source_a, source_b);
311 break;
312 case 5:
313 (*info->fprintf_func) (info->stream, "fsqrt f%d,f%d",
314 indx, source_a);
315 break;
316 case 6:
317 (*info->fprintf_func) (info->stream, "fneg f%d,f%d",
318 indx, source_a);
319 break;
320 case 7:
321 (*info->fprintf_func) (info->stream, "fabs f%d,f%d",
322 indx, source_a);
323 break;
324 case 8:
325 (*info->fprintf_func) (info->stream, "ftoi f%d,f%d",
326 indx, source_a);
327 break;
328 case 9:
329 (*info->fprintf_func) (info->stream, "itof f%d,f%d",
330 indx, source_a);
331 break;
332 case 12:
333 (*info->fprintf_func) (info->stream, "fmove f%d,f%d",
334 indx, source_a);
335 break;
336 default:
337 (*info->fprintf_func) (info->stream,
338 "fpinst %d,f%d,f%d,f%d", fp_ins,
339 indx, source_a, source_b);
340 break;
343 else
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)
354 goto illegal_opcode;
356 if (fp_ins)
357 goto illegal_opcode;
359 switch (indx)
361 case 0:
362 (*info->fprintf_func) (info->stream, "mults r%d,r%d",
363 source_a, source_b);
364 break;
365 case 1:
366 (*info->fprintf_func) (info->stream, "multu r%d,r%d",
367 source_a, source_b);
368 break;
369 case 2:
370 (*info->fprintf_func) (info->stream, "divs r%d",
371 source_a);
372 break;
373 case 3:
374 (*info->fprintf_func) (info->stream, "divu r%d",
375 source_a);
376 break;
377 case 4:
378 (*info->fprintf_func) (info->stream, "writemd r%d,r%d",
379 source_a, source_b);
380 break;
381 case 5:
382 (*info->fprintf_func) (info->stream, "writemdc r%d",
383 source_a);
384 break;
385 case 6:
386 (*info->fprintf_func) (info->stream, "divds r%d",
387 source_a);
388 break;
389 case 7:
390 (*info->fprintf_func) (info->stream, "divdu r%d",
391 source_a);
392 break;
393 case 9:
394 (*info->fprintf_func) (info->stream, "asrd r%d",
395 source_a);
396 break;
397 case 10:
398 (*info->fprintf_func) (info->stream, "lsrd r%d",
399 source_a);
400 break;
401 case 11:
402 (*info->fprintf_func) (info->stream, "asld r%d",
403 source_a);
404 break;
405 default:
406 (*info->fprintf_func) (info->stream,
407 "eamwrite %d,r%d,r%d", indx,
408 source_a, source_b);
409 break;
413 else
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);
419 break;
422 return 0;
424 illegal_opcode:
425 return -1;
428 /* Disassemble storage immediate class instructions. */
430 static int
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;
437 if (ins & CC_MASK)
438 goto illegal_opcode;
440 switch (opcode)
442 case 0:
443 /* ADDI instruction. */
444 (*info->fprintf_func) (info->stream, "addi r%d,%d", source_a,
445 immediate);
446 break;
447 case 1:
448 /* Illegal opcode. */
449 goto illegal_opcode;
450 break;
451 case 2:
452 /* SUBI instruction. */
453 (*info->fprintf_func) (info->stream, "subi r%d,%d", source_a,
454 immediate);
455 break;
456 case 3:
457 /* Illegal opcode. */
458 goto illegal_opcode;
459 break;
460 case 4:
461 /* MOVIL instruction. */
462 (*info->fprintf_func) (info->stream, "movil r%d,0x%04X", source_a,
463 immediate);
464 break;
465 case 5:
466 /* MOVIU instruction. */
467 (*info->fprintf_func) (info->stream, "moviu r%d,0x%04X", source_a,
468 immediate);
469 break;
470 case 6:
471 /* MOVIQ instruction. */
472 (*info->fprintf_func) (info->stream, "moviq r%d,%u", source_a,
473 immediate);
474 break;
475 case 7:
476 /* Illegal opcode. */
477 goto illegal_opcode;
478 break;
479 case 8:
480 /* WRTL instruction. */
481 if (source_a != 0)
482 goto illegal_opcode;
484 (*info->fprintf_func) (info->stream, "wrtl 0x%04X", immediate);
485 break;
486 case 9:
487 /* WRTU instruction. */
488 if (source_a != 0)
489 goto illegal_opcode;
491 (*info->fprintf_func) (info->stream, "wrtu 0x%04X", immediate);
492 break;
493 case 10:
494 /* Illegal opcode. */
495 goto illegal_opcode;
496 break;
497 case 11:
498 /* Illegal opcode. */
499 goto illegal_opcode;
500 break;
501 case 12:
502 /* Illegal opcode. */
503 goto illegal_opcode;
504 break;
505 case 13:
506 /* Illegal opcode. */
507 goto illegal_opcode;
508 break;
509 case 14:
510 /* Illegal opcode. */
511 goto illegal_opcode;
512 break;
513 case 15:
514 /* Illegal opcode. */
515 goto illegal_opcode;
516 break;
519 return 0;
521 illegal_opcode:
522 return -1;
525 /* Disassemble storage register class instructions. */
527 static int
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)))
555 goto illegal_opcode;
558 switch (opcode)
560 case 0:
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);
564 break;
565 case 1:
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);
569 break;
570 case 2:
571 /* SUB instruction. */
572 if (dest == 0)
573 (*info->fprintf_func) (info->stream, "cmp.%s r%d,r%d",
574 size_names[size], source_a, source_b);
575 else
576 (*info->fprintf_func) (info->stream, "sub.%s r%d,r%d,r%d",
577 size_names[size], dest, source_a, source_b);
578 break;
579 case 3:
580 /* SUBC instruction. */
581 if (dest == 0)
582 (*info->fprintf_func) (info->stream, "cmpc.%s r%d,r%d",
583 size_names[size], source_a, source_b);
584 else
585 (*info->fprintf_func) (info->stream, "subc.%s r%d,r%d,r%d",
586 size_names[size], dest, source_a, source_b);
587 break;
588 case 4:
589 /* EXTW instruction. */
590 if (size == 1)
591 goto illegal_opcode;
593 (*info->fprintf_func) (info->stream, "extw.%s r%d,r%d",
594 size_names[size], dest, source_a);
595 break;
596 case 5:
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);
601 else
602 (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,r%d",
603 size_names[size], dest, source_a, source_b);
604 break;
605 case 6:
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);
610 else
611 (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,r%d",
612 size_names[size], dest, source_a, source_b);
613 break;
614 case 7:
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);
619 else
620 (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,r%d",
621 size_names[size], dest, source_a, source_b);
622 break;
623 case 8:
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);
627 break;
628 case 9:
629 /* OR instruction. */
630 if (source_b == 0)
631 (*info->fprintf_func) (info->stream, "move.%s r%d,r%d",
632 size_names[size], dest, source_a);
633 else
634 (*info->fprintf_func) (info->stream, "or.%s r%d,r%d,r%d",
635 size_names[size], dest, source_a, source_b);
636 break;
637 case 10:
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);
641 break;
642 case 11:
643 /* NOT instruction. */
644 (*info->fprintf_func) (info->stream, "not.%s r%d,r%d",
645 size_names[size], dest, source_a);
646 break;
647 case 12:
648 /* BRA instruction. */
650 unsigned cbf = (ins >> 27) & 0x000f;
652 if (size != 4)
653 goto illegal_opcode;
655 (*info->fprintf_func) (info->stream, "bra %s,r%d,r%d",
656 cc_names[cbf], source_a, dest);
658 break;
659 case 13:
660 /* RFLAG instruction. */
661 if (source_a || size != 4)
662 goto illegal_opcode;
664 (*info->fprintf_func) (info->stream, "rflag r%d", dest);
665 break;
666 case 14:
667 /* EXTB instruction. */
668 (*info->fprintf_func) (info->stream, "extb.%s r%d,r%d",
669 size_names[size], dest, source_a);
670 break;
671 case 15:
672 if (!(ins & CLASS3_SOURCEB_IMMED))
673 goto illegal_opcode;
675 if (ins & EAM_SELECT_MASK)
677 /* Extension arithmetic module read. */
678 int fp_ins = (ins >> 27) & 0xf;
680 if (size != 4)
681 goto illegal_opcode;
683 if (ins & FP_SELECT_MASK)
685 /* Check fsrcA <= 15 and fsrcB <= 15. */
686 if (ins & ((1 << 20) | (1 << 8)))
687 goto illegal_opcode;
689 switch (fp_ins)
691 case 0:
692 if (source_b)
693 goto illegal_opcode;
695 (*info->fprintf_func) (info->stream, "fstore r%d,f%d",
696 dest, source_a);
697 break;
698 case 10:
699 (*info->fprintf_func) (info->stream, "fcmp r%d,f%d,f%d",
700 dest, source_a, source_b);
701 break;
702 case 11:
703 (*info->fprintf_func) (info->stream, "fcmpe r%d,f%d,f%d",
704 dest, source_a, source_b);
705 break;
706 default:
707 (*info->fprintf_func) (info->stream,
708 "fpuread %d,r%d,f%d,f%d", fp_ins,
709 dest, source_a, source_b);
710 break;
713 else
715 if (fp_ins || source_a)
716 goto illegal_opcode;
718 switch (source_b)
720 case 0:
721 (*info->fprintf_func) (info->stream, "readmda r%d", dest);
722 break;
723 case 1:
724 (*info->fprintf_func) (info->stream, "readmdb r%d", dest);
725 break;
726 case 2:
727 (*info->fprintf_func) (info->stream, "readmdc r%d", dest);
728 break;
729 default:
730 (*info->fprintf_func) (info->stream, "eamread r%d,%d",
731 dest, source_b);
732 break;
736 else
738 if (ins & FP_SELECT_MASK)
739 goto illegal_opcode;
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);
745 break;
748 return 0;
750 illegal_opcode:
751 return -1;
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)
761 unsigned ins;
762 unsigned p1, p2;
763 int ans;
764 int i;
766 /* Stuff copied from m68k-dis.c. */
767 struct private priv;
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)
774 /* Error return. */
775 return -1;
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. */
788 info->target = 0;
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;
795 ins |= buffer[3];
797 ans = 0;
799 p1 = buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3];
800 p2 = 0;
801 for (i = 0; i < 8; i++)
803 p2 += p1 & 1;
804 p1 >>= 1;
807 /* Decode the instruction. */
808 if (p2 & 1)
809 ans = -1;
810 else
812 switch ((ins >> 25) & 0x3)
814 case 0:
815 ans = disassem_class0 (info, ins);
816 break;
817 case 1:
818 ans = disassem_class1 (info, ins);
819 break;
820 case 2:
821 ans = disassem_class2 (info, ins);
822 break;
823 case 3:
824 ans = disassem_class3 (info, ins);
825 break;
829 if (ans != 0)
830 (*info->fprintf_func) (info->stream, "err");
832 /* Return number of bytes consumed (always 4 for the Visium). */
833 return 4;