(root)/
binutils-2.41/
opcodes/
moxie-dis.c
       1  /* Disassemble moxie instructions.
       2     Copyright (C) 2009-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  
      24  #define STATIC_TABLE
      25  #define DEFINE_TABLE
      26  
      27  #include "opcode/moxie.h"
      28  #include "disassemble.h"
      29  
      30  static fprintf_ftype fpr;
      31  static void *stream;
      32  
      33  /* Macros to extract operands from the instruction word.  */
      34  #define OP_A(i) ((i >> 4) & 0xf)
      35  #define OP_B(i) (i & 0xf)
      36  #define INST2OFFSET(o) (((((o) & 0x3ff) ^ 0x200) - 0x200) * 2)
      37  
      38  static const char * reg_names[16] =
      39    { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
      40      "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
      41  
      42  int
      43  print_insn_moxie (bfd_vma addr, struct disassemble_info * info)
      44  {
      45    int length = 2;
      46    int status;
      47    stream = info->stream;
      48    const moxie_opc_info_t * opcode;
      49    bfd_byte buffer[4];
      50    unsigned short iword;
      51    fpr = info->fprintf_func;
      52  
      53    if ((status = info->read_memory_func (addr, buffer, 2, info)))
      54      goto fail;
      55  
      56    if (info->endian == BFD_ENDIAN_BIG)
      57      iword = bfd_getb16 (buffer);
      58    else
      59      iword = bfd_getl16 (buffer);
      60  
      61    /* Form 1 instructions have the high bit set to 0.  */
      62    if ((iword & (1<<15)) == 0)
      63      {
      64        /* Extract the Form 1 opcode.  */
      65        opcode = &moxie_form1_opc_info[iword >> 8];
      66        switch (opcode->itype)
      67  	{
      68  	case MOXIE_F1_NARG:
      69  	  fpr (stream, "%s", opcode->name);
      70  	  break;
      71  	case MOXIE_F1_A:
      72  	  fpr (stream, "%s\t%s", opcode->name,
      73  	       reg_names[OP_A(iword)]);
      74  	  break;
      75  	case MOXIE_F1_AB:
      76  	  fpr (stream, "%s\t%s, %s", opcode->name,
      77  	       reg_names[OP_A(iword)],
      78  	       reg_names[OP_B(iword)]);
      79  	  break;
      80  	case MOXIE_F1_A4:
      81  	  {
      82  	    unsigned imm;
      83  	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
      84  	      goto fail;
      85  	    if (info->endian == BFD_ENDIAN_BIG)
      86  	      imm = bfd_getb32 (buffer);
      87  	    else
      88  	      imm = bfd_getl32 (buffer);
      89  	    fpr (stream, "%s\t%s, 0x%x", opcode->name,
      90  		 reg_names[OP_A(iword)], imm);
      91  	    length = 6;
      92  	  }
      93  	  break;
      94  	case MOXIE_F1_4:
      95  	  {
      96  	    unsigned imm;
      97  	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
      98  	      goto fail;
      99  	    if (info->endian == BFD_ENDIAN_BIG)
     100  	      imm = bfd_getb32 (buffer);
     101  	    else
     102  	      imm = bfd_getl32 (buffer);
     103  	    fpr (stream, "%s\t0x%x", opcode->name, imm);
     104  	    length = 6;
     105  	  }
     106  	  break;
     107  	case MOXIE_F1_M:
     108  	  {
     109  	    unsigned imm;
     110  	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
     111  	      goto fail;
     112  	    if (info->endian == BFD_ENDIAN_BIG)
     113  	      imm = bfd_getb32 (buffer);
     114  	    else
     115  	      imm = bfd_getl32 (buffer);
     116  	    fpr (stream, "%s\t", opcode->name);
     117  	    info->print_address_func ((bfd_vma) imm, info);
     118  	    length = 6;
     119  	  }
     120  	  break;
     121  	case MOXIE_F1_AiB:
     122  	  fpr (stream, "%s\t(%s), %s", opcode->name,
     123  	       reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
     124  	  break;
     125  	case MOXIE_F1_ABi:
     126  	  fpr (stream, "%s\t%s, (%s)", opcode->name,
     127  	       reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
     128  	  break;
     129  	case MOXIE_F1_4A:
     130  	  {
     131  	    unsigned imm;
     132  	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
     133  	      goto fail;
     134  	    if (info->endian == BFD_ENDIAN_BIG)
     135  	      imm = bfd_getb32 (buffer);
     136  	    else
     137  	      imm = bfd_getl32 (buffer);
     138  	    fpr (stream, "%s\t0x%x, %s",
     139  		 opcode->name, imm, reg_names[OP_A(iword)]);
     140  	    length = 6;
     141  	  }
     142  	  break;
     143  	case MOXIE_F1_AiB2:
     144  	  {
     145  	    unsigned imm;
     146  	    if ((status = info->read_memory_func (addr+2, buffer, 2, info)))
     147  	      goto fail;
     148  	    if (info->endian == BFD_ENDIAN_BIG)
     149  	      imm = bfd_getb16 (buffer);
     150  	    else
     151  	      imm = bfd_getl16 (buffer);
     152  	    fpr (stream, "%s\t0x%x(%s), %s", opcode->name,
     153  		 imm,
     154  		 reg_names[OP_A(iword)],
     155  		 reg_names[OP_B(iword)]);
     156  	    length = 4;
     157  	  }
     158  	  break;
     159  	case MOXIE_F1_ABi2:
     160  	  {
     161  	    unsigned imm;
     162  	    if ((status = info->read_memory_func (addr+2, buffer, 2, info)))
     163  	      goto fail;
     164  	    if (info->endian == BFD_ENDIAN_BIG)
     165  	      imm = bfd_getb16 (buffer);
     166  	    else
     167  	      imm = bfd_getl16 (buffer);
     168  	    fpr (stream, "%s\t%s, 0x%x(%s)",
     169  		 opcode->name,
     170  		 reg_names[OP_A(iword)],
     171  		 imm,
     172  		 reg_names[OP_B(iword)]);
     173  	    length = 4;
     174  	  }
     175  	  break;
     176          case MOXIE_BAD:
     177  	  fpr (stream, "bad");
     178  	  break;
     179  	default:
     180  	  abort();
     181  	}
     182      }
     183    else if ((iword & (1<<14)) == 0)
     184      {
     185        /* Extract the Form 2 opcode.  */
     186        opcode = &moxie_form2_opc_info[(iword >> 12) & 3];
     187        switch (opcode->itype)
     188  	{
     189  	case MOXIE_F2_A8V:
     190  	  fpr (stream, "%s\t%s, 0x%x",
     191  	       opcode->name,
     192  	       reg_names[(iword >> 8) & 0xf],
     193  	       iword & ((1 << 8) - 1));
     194  	  break;
     195  	case MOXIE_F2_NARG:
     196  	  fpr (stream, "%s", opcode->name);
     197  	  break;
     198          case MOXIE_BAD:
     199  	  fpr (stream, "bad");
     200  	  break;
     201  	default:
     202  	  abort();
     203  	}
     204      }
     205    else
     206      {
     207        /* Extract the Form 3 opcode.  */
     208        opcode = &moxie_form3_opc_info[(iword >> 10) & 15];
     209        switch (opcode->itype)
     210  	{
     211  	case MOXIE_F3_PCREL:
     212  	  fpr (stream, "%s\t", opcode->name);
     213  	  info->print_address_func (addr + INST2OFFSET (iword) + 2, info);
     214  	  break;
     215          case MOXIE_BAD:
     216  	  fpr (stream, "bad");
     217  	  break;
     218  	default:
     219  	  abort();
     220  	}
     221      }
     222  
     223    return length;
     224  
     225   fail:
     226    info->memory_error_func (status, addr, info);
     227    return -1;
     228  }