(root)/
binutils-2.41/
opcodes/
mcore-dis.c
       1  /* Disassemble Motorola M*Core instructions.
       2     Copyright (C) 1993-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 "libiberty.h"
      24  #define STATIC_TABLE
      25  #define DEFINE_TABLE
      26  
      27  #include "mcore-opc.h"
      28  #include "disassemble.h"
      29  
      30  /* Mask for each mcore_opclass: */
      31  static const unsigned short imsk[] = {
      32      /* O0  */ 0xFFFF,
      33      /* OT  */ 0xFFFC,
      34      /* O1  */ 0xFFF0,
      35      /* OC  */ 0xFE00,
      36      /* O2  */ 0xFF00,
      37      /* X1  */ 0xFFF0,
      38      /* OI  */ 0xFE00,
      39      /* OB  */ 0xFE00,
      40  
      41      /* OMa */ 0xFFF0,
      42      /* SI  */ 0xFE00,
      43      /* I7  */ 0xF800,
      44      /* LS  */ 0xF000,
      45      /* BR  */ 0xF800,
      46      /* BL  */ 0xFF00,
      47      /* LR  */ 0xF000,
      48      /* LJ  */ 0xFF00,
      49  
      50      /* RM  */ 0xFFF0,
      51      /* RQ  */ 0xFFF0,
      52      /* JSR */ 0xFFF0,
      53      /* JMP */ 0xFFF0,
      54      /* OBRa*/ 0xFFF0,
      55      /* OBRb*/ 0xFF80,
      56      /* OBRc*/ 0xFF00,
      57      /* OBR2*/ 0xFE00,
      58  
      59      /* O1R1*/ 0xFFF0,
      60      /* OMb */ 0xFF80,
      61      /* OMc */ 0xFF00,
      62      /* SIa */ 0xFE00,
      63  
      64    /* MULSH */ 0xFF00,
      65    /* OPSR  */ 0xFFF8,   /* psrset/psrclr */
      66  
      67      /* JC  */ 0,		/* JC,JU,JL don't appear in object */
      68      /* JU  */ 0,
      69      /* JL  */ 0,
      70      /* RSI */ 0,
      71      /* DO21*/ 0,
      72      /* OB2 */ 0 		/* OB2 won't appear in object.  */
      73  };
      74  
      75  static const char *grname[] = {
      76   "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
      77   "r8",  "r9", "r10", "r11", "r12", "r13", "r14", "r15"
      78  };
      79  
      80  static const char X[] = "??";
      81  
      82  static const char *crname[] = {
      83    "psr",  "vbr", "epsr", "fpsr", "epc",  "fpc",  "ss0",  "ss1",
      84    "ss2",  "ss3", "ss4",  "gcr",  "gsr",     X,      X,      X,
      85       X,      X,      X,      X,      X,     X,      X,      X,
      86       X,      X,      X,      X,      X,     X,      X,      X
      87  };
      88  
      89  static const unsigned isiz[] = { 2, 0, 1, 0 };
      90  
      91  int
      92  print_insn_mcore (bfd_vma memaddr,
      93  		  struct disassemble_info *info)
      94  {
      95    unsigned char ibytes[4];
      96    fprintf_ftype print_func = info->fprintf_func;
      97    void *stream = info->stream;
      98    unsigned int inst;
      99    unsigned int i;
     100    int status;
     101  
     102    info->bytes_per_chunk = 2;
     103  
     104    status = info->read_memory_func (memaddr, ibytes, 2, info);
     105  
     106    if (status != 0)
     107      {
     108        info->memory_error_func (status, memaddr, info);
     109        return -1;
     110      }
     111  
     112    if (info->endian == BFD_ENDIAN_BIG)
     113      inst = (ibytes[0] << 8) | ibytes[1];
     114    else if (info->endian == BFD_ENDIAN_LITTLE)
     115      inst = (ibytes[1] << 8) | ibytes[0];
     116    else
     117      abort ();
     118  
     119    /* Just a linear search of the table.  */
     120    for (i = 0; i < ARRAY_SIZE (mcore_table); i++)
     121      if (mcore_table[i].inst == (inst & imsk[mcore_table[i].opclass]))
     122        break;
     123  
     124    if (i == ARRAY_SIZE (mcore_table))
     125      (*print_func) (stream, ".short 0x%04x", inst);
     126    else
     127      {
     128        const char *name = grname[inst & 0x0F];
     129  
     130        (*print_func) (stream, "%s", mcore_table[i].name);
     131  
     132        switch (mcore_table[i].opclass)
     133  	{
     134  	case O0:
     135  	  break;
     136  
     137  	case OT:
     138  	  (*print_func) (stream, "\t%d", inst & 0x3);
     139  	  break;
     140  
     141  	case O1:
     142  	case JMP:
     143  	case JSR:
     144  	  (*print_func) (stream, "\t%s", name);
     145  	  break;
     146  
     147  	case OC:
     148  	  (*print_func) (stream, "\t%s, %s", name, crname[(inst >> 4) & 0x1F]);
     149  	  break;
     150  
     151  	case O1R1:
     152  	  (*print_func) (stream, "\t%s, r1", name);
     153  	  break;
     154  
     155  	case MULSH:
     156  	case O2:
     157  	  (*print_func) (stream, "\t%s, %s", name, grname[(inst >> 4) & 0xF]);
     158  	  break;
     159  
     160  	case X1:
     161  	  (*print_func) (stream, "\tr1, %s", name);
     162  	  break;
     163  
     164  	case OI:
     165  	  (*print_func) (stream, "\t%s, %d", name, ((inst >> 4) & 0x1F) + 1);
     166  	  break;
     167  
     168  	case RM:
     169  	  (*print_func) (stream, "\t%s-r15, (r0)", name);
     170  	  break;
     171  
     172  	case RQ:
     173  	  (*print_func) (stream, "\tr4-r7, (%s)", name);
     174  	  break;
     175  
     176  	case OB:
     177  	case OBRa:
     178  	case OBRb:
     179  	case OBRc:
     180  	case SI:
     181  	case SIa:
     182  	case OMa:
     183  	case OMb:
     184  	case OMc:
     185  	  (*print_func) (stream, "\t%s, %d", name, (inst >> 4) & 0x1F);
     186  	  break;
     187  
     188  	case I7:
     189  	  (*print_func) (stream, "\t%s, %d", name, (inst >> 4) & 0x7F);
     190  	  break;
     191  
     192  	case LS:
     193  	  (*print_func) (stream, "\t%s, (%s, %d)", grname[(inst >> 8) & 0xF],
     194  			 name, ((inst >> 4) & 0xF) << isiz[(inst >> 13) & 3]);
     195  	  break;
     196  
     197  	case BR:
     198  	  {
     199  	    uint32_t val = ((inst & 0x3FF) ^ 0x400) - 0x400;
     200  
     201  	    val = memaddr + 2 + (val << 1);
     202  	    (*print_func) (stream, "\t0x%x", val);
     203  
     204  	    if (strcmp (mcore_table[i].name, "bsr") == 0)
     205  	      {
     206  		/* For bsr, we'll try to get a symbol for the target.  */
     207  		if (info->print_address_func && val != 0)
     208  		  {
     209  		    (*print_func) (stream, "\t// ");
     210  		    info->print_address_func (val, info);
     211  		  }
     212  	      }
     213  	  }
     214  	  break;
     215  
     216  	case BL:
     217  	  {
     218  	    uint32_t val = memaddr + 2 + ((inst | ~0xF) << 1);
     219  
     220  	    (*print_func) (stream, "\t%s, 0x%x",
     221  			   grname[(inst >> 4) & 0xF], val);
     222  	  }
     223  	  break;
     224  
     225  	case LR:
     226  	  {
     227  	    uint32_t val;
     228  
     229  	    val = (memaddr + 2 + ((inst & 0xFF) << 2)) & ~3;
     230  
     231  	    /* We are not reading an instruction, so allow
     232  	       reads to extend beyond the next symbol.  */
     233  	    info->stop_vma = 0;
     234  	    status = info->read_memory_func (val, ibytes, 4, info);
     235  	    if (status != 0)
     236  	      {
     237  		info->memory_error_func (status, memaddr, info);
     238  		break;
     239  	      }
     240  
     241  	    if (info->endian == BFD_ENDIAN_LITTLE)
     242  	      val = (((unsigned) ibytes[3] << 24) | (ibytes[2] << 16)
     243  		     | (ibytes[1] << 8) | (ibytes[0]));
     244  	    else
     245  	      val = (((unsigned) ibytes[0] << 24) | (ibytes[1] << 16)
     246  		     | (ibytes[2] << 8) | (ibytes[3]));
     247  
     248  	    /* Removed [] around literal value to match ABI syntax 12/95.  */
     249  	    (*print_func) (stream, "\t%s, 0x%X", grname[(inst >> 8) & 0xF], val);
     250  
     251  	    if (val == 0)
     252  	      (*print_func) (stream, "\t// from address pool at 0x%x",
     253  			     (uint32_t) (memaddr + 2
     254  					 + ((inst & 0xFF) << 2)) & ~3);
     255  	  }
     256  	  break;
     257  
     258  	case LJ:
     259  	  {
     260  	    uint32_t val;
     261  
     262  	    val = (memaddr + 2 + ((inst & 0xFF) << 2)) & ~3;
     263  
     264  	    /* We are not reading an instruction, so allow
     265  	       reads to extend beyond the next symbol.  */
     266  	    info->stop_vma = 0;
     267  	    status = info->read_memory_func (val, ibytes, 4, info);
     268  	    if (status != 0)
     269  	      {
     270  		info->memory_error_func (status, memaddr, info);
     271  		break;
     272  	      }
     273  
     274  	    if (info->endian == BFD_ENDIAN_LITTLE)
     275  	      val = (((unsigned) ibytes[3] << 24) | (ibytes[2] << 16)
     276  		     | (ibytes[1] << 8) | (ibytes[0]));
     277  	    else
     278  	      val = (((unsigned) ibytes[0] << 24) | (ibytes[1] << 16)
     279  		     | (ibytes[2] << 8) | (ibytes[3]));
     280  
     281  	    /* Removed [] around literal value to match ABI syntax 12/95.  */
     282  	    (*print_func) (stream, "\t0x%X", val);
     283  	    /* For jmpi/jsri, we'll try to get a symbol for the target.  */
     284  	    if (info->print_address_func && val != 0)
     285  	      {
     286  		(*print_func) (stream, "\t// ");
     287  		info->print_address_func (val, info);
     288  	      }
     289  	    else
     290  	      {
     291  		(*print_func) (stream, "\t// from address pool at 0x%x",
     292  			       (uint32_t) (memaddr + 2
     293  					   + ((inst & 0xFF) << 2)) & ~3);
     294  	      }
     295  	  }
     296  	  break;
     297  
     298  	case OPSR:
     299  	  {
     300  	    static char *fields[] = {
     301  	      "af", "ie",    "fe",    "fe,ie",
     302  	      "ee", "ee,ie", "ee,fe", "ee,fe,ie"
     303  	    };
     304  
     305  	    (*print_func) (stream, "\t%s", fields[inst & 0x7]);
     306  	  }
     307  	  break;
     308  
     309  	default:
     310  	  /* If the disassembler lags the instruction set.  */
     311  	  (*print_func) (stream, "\tundecoded operands, inst is 0x%04x", inst);
     312  	  break;
     313  	}
     314      }
     315  
     316    /* Say how many bytes we consumed.  */
     317    return 2;
     318  }