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