xref: /netbsd-src/external/gpl3/binutils/dist/opcodes/moxie-dis.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
1 /* Disassemble moxie instructions.
2    Copyright 2009, 2012
3    Free Software Foundation, Inc.
4 
5    This file is part of the GNU opcodes library.
6 
7    This library is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11 
12    It is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21 
22 #include "sysdep.h"
23 #include <stdio.h>
24 
25 #define STATIC_TABLE
26 #define DEFINE_TABLE
27 
28 #include "opcode/moxie.h"
29 #include "dis-asm.h"
30 
31 static fprintf_ftype fpr;
32 static void *stream;
33 
34 /* Macros to extract operands from the instruction word.  */
35 #define OP_A(i) ((i >> 4) & 0xf)
36 #define OP_B(i) (i & 0xf)
37 #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
38 
39 static const char * reg_names[16] =
40   { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
41     "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
42 
43 int
44 print_insn_moxie (bfd_vma addr, struct disassemble_info * info)
45 {
46   int length = 2;
47   int status;
48   stream = info->stream;
49   const moxie_opc_info_t * opcode;
50   bfd_byte buffer[4];
51   unsigned short iword;
52   fpr = info->fprintf_func;
53 
54   if ((status = info->read_memory_func (addr, buffer, 2, info)))
55     goto fail;
56   iword = bfd_getb16 (buffer);
57 
58   /* Form 1 instructions have the high bit set to 0.  */
59   if ((iword & (1<<15)) == 0)
60     {
61       /* Extract the Form 1 opcode.  */
62       opcode = &moxie_form1_opc_info[iword >> 8];
63       switch (opcode->itype)
64 	{
65 	case MOXIE_F1_NARG:
66 	  fpr (stream, "%s", opcode->name);
67 	  break;
68 	case MOXIE_F1_A:
69 	  fpr (stream, "%s\t%s", opcode->name,
70 	       reg_names[OP_A(iword)]);
71 	  break;
72 	case MOXIE_F1_AB:
73 	  fpr (stream, "%s\t%s, %s", opcode->name,
74 	       reg_names[OP_A(iword)],
75 	       reg_names[OP_B(iword)]);
76 	  break;
77 	case MOXIE_F1_A4:
78 	  {
79 	    unsigned imm;
80 	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
81 	      goto fail;
82 	    imm = bfd_getb32 (buffer);
83 	    fpr (stream, "%s\t%s, 0x%x", opcode->name,
84 		 reg_names[OP_A(iword)], imm);
85 	    length = 6;
86 	  }
87 	  break;
88 	case MOXIE_F1_4:
89 	  {
90 	    unsigned imm;
91 	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
92 	      goto fail;
93 	    imm = bfd_getb32 (buffer);
94 	    fpr (stream, "%s\t0x%x", opcode->name, imm);
95 	    length = 6;
96 	  }
97 	  break;
98 	case MOXIE_F1_M:
99 	  {
100 	    unsigned imm;
101 	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
102 	      goto fail;
103 	    imm = bfd_getb32 (buffer);
104 	    fpr (stream, "%s\t", opcode->name);
105 	    info->print_address_func ((bfd_vma) imm, info);
106 	    length = 6;
107 	  }
108 	  break;
109 	case MOXIE_F1_AiB:
110 	  fpr (stream, "%s\t(%s), %s", opcode->name,
111 	       reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
112 	  break;
113 	case MOXIE_F1_ABi:
114 	  fpr (stream, "%s\t%s, (%s)", opcode->name,
115 	       reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
116 	  break;
117 	case MOXIE_F1_4A:
118 	  {
119 	    unsigned imm;
120 	    if ((status = info->read_memory_func (addr + 2, buffer, 4, info)))
121 	      goto fail;
122 	    imm = bfd_getb32 (buffer);
123 	    fpr (stream, "%s\t0x%x, %s",
124 		 opcode->name, imm, reg_names[OP_A(iword)]);
125 	    length = 6;
126 	  }
127 	  break;
128 	case MOXIE_F1_AiB4:
129 	  {
130 	    unsigned imm;
131 	    if ((status = info->read_memory_func (addr+2, buffer, 4, info)))
132 	      goto fail;
133 	    imm = bfd_getb32 (buffer);
134 	    fpr (stream, "%s\t0x%x(%s), %s", opcode->name,
135 		 imm,
136 		 reg_names[OP_A(iword)],
137 		 reg_names[OP_B(iword)]);
138 	    length = 6;
139 	  }
140 	  break;
141 	case MOXIE_F1_ABi4:
142 	  {
143 	    unsigned imm;
144 	    if ((status = info->read_memory_func (addr+2, buffer, 4, info)))
145 	      goto fail;
146 	    imm = bfd_getb32 (buffer);
147 	    fpr (stream, "%s\t%s, 0x%x(%s)",
148 		 opcode->name,
149 		 reg_names[OP_A(iword)],
150 		 imm,
151 		 reg_names[OP_B(iword)]);
152 	    length = 6;
153 	  }
154 	  break;
155 	default:
156 	  abort ();
157 	}
158     }
159   else if ((iword & (1<<14)) == 0)
160     {
161       /* Extract the Form 2 opcode.  */
162       opcode = &moxie_form2_opc_info[(iword >> 12) & 3];
163       switch (opcode->itype)
164 	{
165 	case MOXIE_F2_A8V:
166 	  fpr (stream, "%s\t%s, 0x%x",
167 	       opcode->name,
168 	       reg_names[(iword >> 8) & 0xf],
169 	       iword & ((1 << 8) - 1));
170 	  break;
171 	case MOXIE_F2_NARG:
172 	  fpr (stream, "%s", opcode->name);
173 	  break;
174 	default:
175 	  abort();
176 	}
177     }
178   else
179     {
180       /* Extract the Form 3 opcode.  */
181       opcode = &moxie_form3_opc_info[(iword >> 10) & 15];
182       switch (opcode->itype)
183 	{
184 	case MOXIE_F3_PCREL:
185 	  fpr (stream, "%s\t", opcode->name);
186 	  info->print_address_func ((bfd_vma) (addr + INST2OFFSET(iword)),
187 				    info);
188 	  break;
189 	default:
190 	  abort();
191 	}
192     }
193 
194   return length;
195 
196  fail:
197   info->memory_error_func (status, addr, info);
198   return -1;
199 }
200