xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/moxie-dis.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* Disassemble moxie instructions.
2*e992f068Schristos    Copyright (C) 2009-2022 Free Software Foundation, Inc.
375fd0b74Schristos 
475fd0b74Schristos    This file is part of the GNU opcodes library.
575fd0b74Schristos 
675fd0b74Schristos    This library is free software; you can redistribute it and/or modify
775fd0b74Schristos    it under the terms of the GNU General Public License as published by
875fd0b74Schristos    the Free Software Foundation; either version 3, or (at your option)
975fd0b74Schristos    any later version.
1075fd0b74Schristos 
1175fd0b74Schristos    It is distributed in the hope that it will be useful, but WITHOUT
1275fd0b74Schristos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1375fd0b74Schristos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1475fd0b74Schristos    License for more details.
1575fd0b74Schristos 
1675fd0b74Schristos    You should have received a copy of the GNU General Public License
1775fd0b74Schristos    along with this program; if not, write to the Free Software
1875fd0b74Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
1975fd0b74Schristos    MA 02110-1301, USA.  */
2075fd0b74Schristos 
2175fd0b74Schristos #include "sysdep.h"
2275fd0b74Schristos #include <stdio.h>
2375fd0b74Schristos 
2475fd0b74Schristos #define STATIC_TABLE
2575fd0b74Schristos #define DEFINE_TABLE
2675fd0b74Schristos 
2775fd0b74Schristos #include "opcode/moxie.h"
28ede78133Schristos #include "disassemble.h"
2975fd0b74Schristos 
3075fd0b74Schristos static fprintf_ftype fpr;
3175fd0b74Schristos static void *stream;
3275fd0b74Schristos 
3375fd0b74Schristos /* Macros to extract operands from the instruction word.  */
3475fd0b74Schristos #define OP_A(i) ((i >> 4) & 0xf)
3575fd0b74Schristos #define OP_B(i) (i & 0xf)
36012573ebSchristos #define INST2OFFSET(o) (((((o) & 0x3ff) ^ 0x200) - 0x200) * 2)
3775fd0b74Schristos 
3875fd0b74Schristos static const char * reg_names[16] =
3975fd0b74Schristos   { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
4075fd0b74Schristos     "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
4175fd0b74Schristos 
4275fd0b74Schristos int
print_insn_moxie(bfd_vma addr,struct disassemble_info * info)4375fd0b74Schristos print_insn_moxie (bfd_vma addr, struct disassemble_info * info)
4475fd0b74Schristos {
4575fd0b74Schristos   int length = 2;
4675fd0b74Schristos   int status;
4775fd0b74Schristos   stream = info->stream;
4875fd0b74Schristos   const moxie_opc_info_t * opcode;
4975fd0b74Schristos   bfd_byte buffer[4];
5075fd0b74Schristos   unsigned short iword;
5175fd0b74Schristos   fpr = info->fprintf_func;
5275fd0b74Schristos 
5375fd0b74Schristos   if ((status = info->read_memory_func (addr, buffer, 2, info)))
5475fd0b74Schristos     goto fail;
5575fd0b74Schristos 
5675fd0b74Schristos   if (info->endian == BFD_ENDIAN_BIG)
5775fd0b74Schristos     iword = bfd_getb16 (buffer);
5875fd0b74Schristos   else
5975fd0b74Schristos     iword = bfd_getl16 (buffer);
6075fd0b74Schristos 
6175fd0b74Schristos   /* Form 1 instructions have the high bit set to 0.  */
6275fd0b74Schristos   if ((iword & (1<<15)) == 0)
6375fd0b74Schristos     {
6475fd0b74Schristos       /* Extract the Form 1 opcode.  */
6575fd0b74Schristos       opcode = &moxie_form1_opc_info[iword >> 8];
6675fd0b74Schristos       switch (opcode->itype)
6775fd0b74Schristos 	{
6875fd0b74Schristos 	case MOXIE_F1_NARG:
6975fd0b74Schristos 	  fpr (stream, "%s", opcode->name);
7075fd0b74Schristos 	  break;
7175fd0b74Schristos 	case MOXIE_F1_A:
7275fd0b74Schristos 	  fpr (stream, "%s\t%s", opcode->name,
7375fd0b74Schristos 	       reg_names[OP_A(iword)]);
7475fd0b74Schristos 	  break;
7575fd0b74Schristos 	case MOXIE_F1_AB:
7675fd0b74Schristos 	  fpr (stream, "%s\t%s, %s", opcode->name,
7775fd0b74Schristos 	       reg_names[OP_A(iword)],
7875fd0b74Schristos 	       reg_names[OP_B(iword)]);
7975fd0b74Schristos 	  break;
8075fd0b74Schristos 	case MOXIE_F1_A4:
8175fd0b74Schristos 	  {
8275fd0b74Schristos 	    unsigned imm;
8375fd0b74Schristos 	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
8475fd0b74Schristos 	      goto fail;
8575fd0b74Schristos 	    if (info->endian == BFD_ENDIAN_BIG)
8675fd0b74Schristos 	      imm = bfd_getb32 (buffer);
8775fd0b74Schristos 	    else
8875fd0b74Schristos 	      imm = bfd_getl32 (buffer);
8975fd0b74Schristos 	    fpr (stream, "%s\t%s, 0x%x", opcode->name,
9075fd0b74Schristos 		 reg_names[OP_A(iword)], imm);
9175fd0b74Schristos 	    length = 6;
9275fd0b74Schristos 	  }
9375fd0b74Schristos 	  break;
9475fd0b74Schristos 	case MOXIE_F1_4:
9575fd0b74Schristos 	  {
9675fd0b74Schristos 	    unsigned imm;
9775fd0b74Schristos 	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
9875fd0b74Schristos 	      goto fail;
9975fd0b74Schristos 	    if (info->endian == BFD_ENDIAN_BIG)
10075fd0b74Schristos 	      imm = bfd_getb32 (buffer);
10175fd0b74Schristos 	    else
10275fd0b74Schristos 	      imm = bfd_getl32 (buffer);
10375fd0b74Schristos 	    fpr (stream, "%s\t0x%x", opcode->name, imm);
10475fd0b74Schristos 	    length = 6;
10575fd0b74Schristos 	  }
10675fd0b74Schristos 	  break;
10775fd0b74Schristos 	case MOXIE_F1_M:
10875fd0b74Schristos 	  {
10975fd0b74Schristos 	    unsigned imm;
11075fd0b74Schristos 	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
11175fd0b74Schristos 	      goto fail;
11275fd0b74Schristos 	    if (info->endian == BFD_ENDIAN_BIG)
11375fd0b74Schristos 	      imm = bfd_getb32 (buffer);
11475fd0b74Schristos 	    else
11575fd0b74Schristos 	      imm = bfd_getl32 (buffer);
11675fd0b74Schristos 	    fpr (stream, "%s\t", opcode->name);
11775fd0b74Schristos 	    info->print_address_func ((bfd_vma) imm, info);
11875fd0b74Schristos 	    length = 6;
11975fd0b74Schristos 	  }
12075fd0b74Schristos 	  break;
12175fd0b74Schristos 	case MOXIE_F1_AiB:
12275fd0b74Schristos 	  fpr (stream, "%s\t(%s), %s", opcode->name,
12375fd0b74Schristos 	       reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
12475fd0b74Schristos 	  break;
12575fd0b74Schristos 	case MOXIE_F1_ABi:
12675fd0b74Schristos 	  fpr (stream, "%s\t%s, (%s)", opcode->name,
12775fd0b74Schristos 	       reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
12875fd0b74Schristos 	  break;
12975fd0b74Schristos 	case MOXIE_F1_4A:
13075fd0b74Schristos 	  {
13175fd0b74Schristos 	    unsigned imm;
13275fd0b74Schristos 	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
13375fd0b74Schristos 	      goto fail;
13475fd0b74Schristos 	    if (info->endian == BFD_ENDIAN_BIG)
13575fd0b74Schristos 	      imm = bfd_getb32 (buffer);
13675fd0b74Schristos 	    else
13775fd0b74Schristos 	      imm = bfd_getl32 (buffer);
13875fd0b74Schristos 	    fpr (stream, "%s\t0x%x, %s",
13975fd0b74Schristos 		 opcode->name, imm, reg_names[OP_A(iword)]);
14075fd0b74Schristos 	    length = 6;
14175fd0b74Schristos 	  }
14275fd0b74Schristos 	  break;
14375fd0b74Schristos 	case MOXIE_F1_AiB2:
14475fd0b74Schristos 	  {
14575fd0b74Schristos 	    unsigned imm;
14675fd0b74Schristos 	    if ((status = info->read_memory_func (addr+2, buffer, 2, info)))
14775fd0b74Schristos 	      goto fail;
14875fd0b74Schristos 	    if (info->endian == BFD_ENDIAN_BIG)
14975fd0b74Schristos 	      imm = bfd_getb16 (buffer);
15075fd0b74Schristos 	    else
15175fd0b74Schristos 	      imm = bfd_getl16 (buffer);
15275fd0b74Schristos 	    fpr (stream, "%s\t0x%x(%s), %s", opcode->name,
15375fd0b74Schristos 		 imm,
15475fd0b74Schristos 		 reg_names[OP_A(iword)],
15575fd0b74Schristos 		 reg_names[OP_B(iword)]);
15675fd0b74Schristos 	    length = 4;
15775fd0b74Schristos 	  }
15875fd0b74Schristos 	  break;
15975fd0b74Schristos 	case MOXIE_F1_ABi2:
16075fd0b74Schristos 	  {
16175fd0b74Schristos 	    unsigned imm;
16275fd0b74Schristos 	    if ((status = info->read_memory_func (addr+2, buffer, 2, info)))
16375fd0b74Schristos 	      goto fail;
16475fd0b74Schristos 	    if (info->endian == BFD_ENDIAN_BIG)
16575fd0b74Schristos 	      imm = bfd_getb16 (buffer);
16675fd0b74Schristos 	    else
16775fd0b74Schristos 	      imm = bfd_getl16 (buffer);
16875fd0b74Schristos 	    fpr (stream, "%s\t%s, 0x%x(%s)",
16975fd0b74Schristos 		 opcode->name,
17075fd0b74Schristos 		 reg_names[OP_A(iword)],
17175fd0b74Schristos 		 imm,
17275fd0b74Schristos 		 reg_names[OP_B(iword)]);
17375fd0b74Schristos 	    length = 4;
17475fd0b74Schristos 	  }
17575fd0b74Schristos 	  break;
17675fd0b74Schristos         case MOXIE_BAD:
17775fd0b74Schristos 	  fpr (stream, "bad");
17875fd0b74Schristos 	  break;
17975fd0b74Schristos 	default:
18075fd0b74Schristos 	  abort();
18175fd0b74Schristos 	}
18275fd0b74Schristos     }
18375fd0b74Schristos   else if ((iword & (1<<14)) == 0)
18475fd0b74Schristos     {
18575fd0b74Schristos       /* Extract the Form 2 opcode.  */
18675fd0b74Schristos       opcode = &moxie_form2_opc_info[(iword >> 12) & 3];
18775fd0b74Schristos       switch (opcode->itype)
18875fd0b74Schristos 	{
18975fd0b74Schristos 	case MOXIE_F2_A8V:
19075fd0b74Schristos 	  fpr (stream, "%s\t%s, 0x%x",
19175fd0b74Schristos 	       opcode->name,
19275fd0b74Schristos 	       reg_names[(iword >> 8) & 0xf],
19375fd0b74Schristos 	       iword & ((1 << 8) - 1));
19475fd0b74Schristos 	  break;
19575fd0b74Schristos 	case MOXIE_F2_NARG:
19675fd0b74Schristos 	  fpr (stream, "%s", opcode->name);
19775fd0b74Schristos 	  break;
19875fd0b74Schristos         case MOXIE_BAD:
19975fd0b74Schristos 	  fpr (stream, "bad");
20075fd0b74Schristos 	  break;
20175fd0b74Schristos 	default:
20275fd0b74Schristos 	  abort();
20375fd0b74Schristos 	}
20475fd0b74Schristos     }
20575fd0b74Schristos   else
20675fd0b74Schristos     {
20775fd0b74Schristos       /* Extract the Form 3 opcode.  */
20875fd0b74Schristos       opcode = &moxie_form3_opc_info[(iword >> 10) & 15];
20975fd0b74Schristos       switch (opcode->itype)
21075fd0b74Schristos 	{
21175fd0b74Schristos 	case MOXIE_F3_PCREL:
21275fd0b74Schristos 	  fpr (stream, "%s\t", opcode->name);
213012573ebSchristos 	  info->print_address_func (addr + INST2OFFSET (iword) + 2, info);
21475fd0b74Schristos 	  break;
21575fd0b74Schristos         case MOXIE_BAD:
21675fd0b74Schristos 	  fpr (stream, "bad");
21775fd0b74Schristos 	  break;
21875fd0b74Schristos 	default:
21975fd0b74Schristos 	  abort();
22075fd0b74Schristos 	}
22175fd0b74Schristos     }
22275fd0b74Schristos 
22375fd0b74Schristos   return length;
22475fd0b74Schristos 
22575fd0b74Schristos  fail:
22675fd0b74Schristos   info->memory_error_func (status, addr, info);
22775fd0b74Schristos   return -1;
22875fd0b74Schristos }
229