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