(root)/
binutils-2.41/
opcodes/
m10200-dis.c
       1  /* Disassemble MN10200 instructions.
       2     Copyright (C) 1996-2023 Free Software Foundation, Inc.
       3  
       4     This file is part of the GNU opcodes library.
       5  
       6     This library is free software; you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as published by
       8     the Free Software Foundation; either version 3, or (at your option)
       9     any later version.
      10  
      11     It is distributed in the hope that it will be useful, but WITHOUT
      12     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      13     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      14     License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with this program; if not, write to the Free Software
      18     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      19     MA 02110-1301, USA.  */
      20  
      21  #include "sysdep.h"
      22  #include <stdio.h>
      23  #include "opcode/mn10200.h"
      24  #include "disassemble.h"
      25  #include "opintl.h"
      26  
      27  static void
      28  disassemble (bfd_vma memaddr,
      29  	     struct disassemble_info *info,
      30  	     unsigned long insn,
      31  	     unsigned long extension,
      32  	     unsigned int size)
      33  {
      34    struct mn10200_opcode *op = (struct mn10200_opcode *)mn10200_opcodes;
      35    const struct mn10200_operand *operand;
      36    int match = 0;
      37  
      38    /* Find the opcode.  */
      39    while (op->name)
      40      {
      41        int mysize, extra_shift;
      42  
      43        if (op->format == FMT_1)
      44  	mysize = 1;
      45        else if (op->format == FMT_2
      46  	       || op->format == FMT_4)
      47  	mysize = 2;
      48        else if (op->format == FMT_3
      49  	       || op->format == FMT_5)
      50  	mysize = 3;
      51        else if (op->format == FMT_6)
      52  	mysize = 4;
      53        else if (op->format == FMT_7)
      54  	mysize = 5;
      55        else
      56  	abort ();
      57  
      58        if (op->format == FMT_2 || op->format == FMT_5)
      59  	extra_shift = 8;
      60        else if (op->format == FMT_3
      61  	       || op->format == FMT_6
      62  	       || op->format == FMT_7)
      63  	extra_shift = 16;
      64        else
      65  	extra_shift = 0;
      66  
      67        if ((op->mask & insn) == op->opcode
      68  	  && size == (unsigned int) mysize)
      69  	{
      70  	  const unsigned char *opindex_ptr;
      71  	  unsigned int nocomma;
      72  	  int paren = 0;
      73  
      74  	  match = 1;
      75  	  (*info->fprintf_func) (info->stream, "%s\t", op->name);
      76  
      77  	  /* Now print the operands.  */
      78  	  for (opindex_ptr = op->operands, nocomma = 1;
      79  	       *opindex_ptr != 0;
      80  	       opindex_ptr++)
      81  	    {
      82  	      unsigned long value;
      83  
      84  	      operand = &mn10200_operands[*opindex_ptr];
      85  
      86  	      if ((operand->flags & MN10200_OPERAND_DREG) != 0
      87  		  || (operand->flags & MN10200_OPERAND_AREG) != 0)
      88  		value = ((insn >> (operand->shift + extra_shift))
      89  			 & ((1 << operand->bits) - 1));
      90  	      else if ((operand->flags & MN10200_OPERAND_EXTENDED) != 0)
      91  		{
      92  		  value = (insn & 0xffff) << 8;
      93  		  value |= extension;
      94  		}
      95  	      else
      96  		value = ((insn >> (operand->shift))
      97  			 & ((1L << operand->bits) - 1L));
      98  
      99  	      if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
     100  		value = ((long)(value << (32 - operand->bits))
     101  			  >> (32 - operand->bits));
     102  
     103  	      if (!nocomma
     104  		  && (!paren
     105  		      || ((operand->flags & MN10200_OPERAND_PAREN) == 0)))
     106  		(*info->fprintf_func) (info->stream, ",");
     107  
     108  	      nocomma = 0;
     109  
     110  	      if ((operand->flags & MN10200_OPERAND_DREG) != 0)
     111  		(*info->fprintf_func) (info->stream, "d%ld", value);
     112  
     113  	      else if ((operand->flags & MN10200_OPERAND_AREG) != 0)
     114  		(*info->fprintf_func) (info->stream, "a%ld", value);
     115  
     116  	      else if ((operand->flags & MN10200_OPERAND_PSW) != 0)
     117  		(*info->fprintf_func) (info->stream, "psw");
     118  
     119  	      else if ((operand->flags & MN10200_OPERAND_MDR) != 0)
     120  		(*info->fprintf_func) (info->stream, "mdr");
     121  
     122  	      else if ((operand->flags & MN10200_OPERAND_PAREN) != 0)
     123  		{
     124  		  if (paren)
     125  		    (*info->fprintf_func) (info->stream, ")");
     126  		  else
     127  		    {
     128  		      (*info->fprintf_func) (info->stream, "(");
     129  		      nocomma = 1;
     130  		    }
     131  		  paren = !paren;
     132  		}
     133  
     134  	      else if ((operand->flags & MN10200_OPERAND_PCREL) != 0)
     135  		(*info->print_address_func)
     136  		  ((value + memaddr + mysize) & 0xffffff, info);
     137  
     138  	      else if ((operand->flags & MN10200_OPERAND_MEMADDR) != 0)
     139  		(*info->print_address_func) (value, info);
     140  
     141  	      else
     142  		(*info->fprintf_func) (info->stream, "%ld", value);
     143  	    }
     144  	  /* All done. */
     145  	  break;
     146  	}
     147        op++;
     148      }
     149  
     150    if (!match)
     151      (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn);
     152  }
     153  
     154  int
     155  print_insn_mn10200 (bfd_vma memaddr, struct disassemble_info *info)
     156  {
     157    int status;
     158    bfd_byte buffer[4];
     159    unsigned long insn;
     160    unsigned long extension = 0;
     161    unsigned int consume;
     162  
     163    /* First figure out how big the opcode is.  */
     164    status = (*info->read_memory_func) (memaddr, buffer, 1, info);
     165    if (status != 0)
     166      {
     167        (*info->memory_error_func) (status, memaddr, info);
     168        return -1;
     169      }
     170  
     171    insn = *(unsigned char *) buffer;
     172  
     173    /* These are one byte insns.  */
     174    if ((insn & 0xf0) == 0x00
     175        || (insn & 0xf0) == 0x10
     176        || (insn & 0xf0) == 0x20
     177        || (insn & 0xf0) == 0x30
     178        || ((insn & 0xf0) == 0x80
     179  	  && (insn & 0x0c) >> 2 != (insn & 0x03))
     180        || (insn & 0xf0) == 0x90
     181        || (insn & 0xf0) == 0xa0
     182        || (insn & 0xf0) == 0xb0
     183        || (insn & 0xff) == 0xeb
     184        || (insn & 0xff) == 0xf6
     185        || (insn & 0xff) == 0xfe
     186        || (insn & 0xff) == 0xff)
     187      {
     188        extension = 0;
     189        consume = 1;
     190      }
     191  
     192    /* These are two byte insns.  */
     193    else if ((insn & 0xf0) == 0x40
     194  	   || (insn & 0xf0) == 0x50
     195  	   || (insn & 0xf0) == 0x60
     196  	   || (insn & 0xf0) == 0x70
     197  	   || (insn & 0xf0) == 0x80
     198  	   || (insn & 0xfc) == 0xd0
     199  	   || (insn & 0xfc) == 0xd4
     200  	   || (insn & 0xfc) == 0xd8
     201  	   || (insn & 0xfc) == 0xe0
     202  	   || (insn & 0xfc) == 0xe4
     203  	   || (insn & 0xff) == 0xe8
     204  	   || (insn & 0xff) == 0xe9
     205  	   || (insn & 0xff) == 0xea
     206  	   || (insn & 0xff) == 0xf0
     207  	   || (insn & 0xff) == 0xf1
     208  	   || (insn & 0xff) == 0xf2
     209  	   || (insn & 0xff) == 0xf3)
     210      {
     211        status = (*info->read_memory_func) (memaddr, buffer, 2, info);
     212        if (status != 0)
     213  	{
     214  	  (*info->memory_error_func) (status, memaddr, info);
     215  	   return -1;
     216  	}
     217        insn = bfd_getb16 (buffer);
     218        consume = 2;
     219      }
     220  
     221    /* These are three byte insns with a 16bit operand in little
     222       endian form.  */
     223    else if ((insn & 0xf0) == 0xc0
     224  	   || (insn & 0xfc) == 0xdc
     225  	   || (insn & 0xfc) == 0xec
     226  	   || (insn & 0xff) == 0xf8
     227  	   || (insn & 0xff) == 0xf9
     228  	   || (insn & 0xff) == 0xfa
     229  	   || (insn & 0xff) == 0xfb
     230  	   || (insn & 0xff) == 0xfc
     231  	   || (insn & 0xff) == 0xfd)
     232      {
     233        status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
     234        if (status != 0)
     235  	{
     236  	  (*info->memory_error_func) (status, memaddr, info);
     237  	  return -1;
     238  	}
     239        insn <<= 16;
     240        insn |= bfd_getl16 (buffer);
     241        extension = 0;
     242        consume = 3;
     243      }
     244    /* These are three byte insns too, but we don't have to mess with
     245       endianness stuff.  */
     246    else if ((insn & 0xff) == 0xf5)
     247      {
     248        status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
     249        if (status != 0)
     250  	{
     251  	  (*info->memory_error_func) (status, memaddr, info);
     252  	  return -1;
     253  	}
     254        insn <<= 16;
     255        insn |= bfd_getb16 (buffer);
     256        extension = 0;
     257        consume = 3;
     258      }
     259  
     260    /* These are four byte insns.  */
     261    else if ((insn & 0xff) == 0xf7)
     262      {
     263        status = (*info->read_memory_func) (memaddr, buffer, 2, info);
     264        if (status != 0)
     265  	{
     266  	  (*info->memory_error_func) (status, memaddr, info);
     267  	  return -1;
     268  	}
     269        insn = bfd_getb16 (buffer);
     270        insn <<= 16;
     271        status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
     272        if (status != 0)
     273  	{
     274  	  (*info->memory_error_func) (status, memaddr, info);
     275  	  return -1;
     276  	}
     277        insn |= bfd_getl16 (buffer);
     278        extension = 0;
     279        consume = 4;
     280      }
     281  
     282    /* These are five byte insns.  */
     283    else if ((insn & 0xff) == 0xf4)
     284      {
     285        status = (*info->read_memory_func) (memaddr, buffer, 2, info);
     286        if (status != 0)
     287  	{
     288  	  (*info->memory_error_func) (status, memaddr, info);
     289  	  return -1;
     290  	}
     291        insn = bfd_getb16 (buffer);
     292        insn <<= 16;
     293  
     294        status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
     295        if (status != 0)
     296  	{
     297  	  (*info->memory_error_func) (status, memaddr, info);
     298  	  return -1;
     299  	}
     300        insn |= (*(unsigned char *)buffer << 8) & 0xff00;
     301  
     302        status = (*info->read_memory_func) (memaddr + 3, buffer, 1, info);
     303        if (status != 0)
     304  	{
     305  	  (*info->memory_error_func) (status, memaddr, info);
     306  	  return -1;
     307  	}
     308        insn |= (*(unsigned char *)buffer) & 0xff;
     309  
     310        status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
     311        if (status != 0)
     312  	{
     313  	  (*info->memory_error_func) (status, memaddr, info);
     314  	  return -1;
     315  	}
     316        extension = (*(unsigned char *)buffer) & 0xff;
     317        consume = 5;
     318      }
     319    else
     320      {
     321        (*info->fprintf_func) (info->stream, _("unknown\t0x%02lx"), insn);
     322        return 1;
     323      }
     324  
     325    disassemble (memaddr, info, insn, extension, consume);
     326  
     327    return consume;
     328  }