m10300-dis.c revision 1.1.1.1
1/* Disassemble MN10300 instructions.
2   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18
19#include <stdio.h>
20
21#include "ansidecl.h"
22#include "opcode/mn10300.h"
23#include "dis-asm.h"
24
25static void disassemble PARAMS ((bfd_vma, struct disassemble_info *,
26				 unsigned long insn, unsigned int));
27
28int
29print_insn_mn10300 (memaddr, info)
30     bfd_vma memaddr;
31     struct disassemble_info *info;
32{
33  int status;
34  bfd_byte buffer[4];
35  unsigned long insn;
36  unsigned int consume;
37
38  /* First figure out how big the opcode is.  */
39  status = (*info->read_memory_func) (memaddr, buffer, 1, info);
40  if (status != 0)
41    {
42      (*info->memory_error_func) (status, memaddr, info);
43      return -1;
44    }
45  insn = *(unsigned char *) buffer;
46
47  /* These are one byte insns.  */
48  if ((insn & 0xf3) == 0x00
49      || (insn & 0xf0) == 0x10
50      || (insn & 0xfc) == 0x3c
51      || (insn & 0xf3) == 0x41
52      || (insn & 0xf3) == 0x40
53      || (insn & 0xfc) == 0x50
54      || (insn & 0xfc) == 0x54
55      || (insn & 0xf0) == 0x60
56      || (insn & 0xf0) == 0x70
57      || ((insn & 0xf0) == 0x80
58	  && (insn & 0x0c) >> 2 != (insn & 0x03))
59      || ((insn & 0xf0) == 0x90
60	  && (insn & 0x0c) >> 2 != (insn & 0x03))
61      || ((insn & 0xf0) == 0xa0
62	  && (insn & 0x0c) >> 2 != (insn & 0x03))
63      || ((insn & 0xf0) == 0xb0
64	  && (insn & 0x0c) >> 2 != (insn & 0x03))
65      || (insn & 0xff) == 0xcb
66      || (insn & 0xfc) == 0xd0
67      || (insn & 0xfc) == 0xd4
68      || (insn & 0xfc) == 0xd8
69      || (insn & 0xf0) == 0xe0)
70    {
71      consume = 1;
72    }
73
74  /* These are two byte insns.  */
75  else if ((insn & 0xf0) == 0x80
76	   || (insn & 0xf0) == 0x90
77	   || (insn & 0xf0) == 0xa0
78	   || (insn & 0xf0) == 0xb0
79	   || (insn & 0xfc) == 0x20
80	   || (insn & 0xfc) == 0x28
81	   || (insn & 0xf3) == 0x43
82	   || (insn & 0xf3) == 0x42
83	   || (insn & 0xfc) == 0x58
84	   || (insn & 0xfc) == 0x5c
85	   || ((insn & 0xf0) == 0xc0
86	       && (insn & 0xff) != 0xcb
87	       && (insn & 0xff) != 0xcc
88	       && (insn & 0xff) != 0xcd)
89	   || (insn & 0xff) == 0xf0
90	   || (insn & 0xff) == 0xf1
91	   || (insn & 0xff) == 0xf2
92	   || (insn & 0xff) == 0xf3
93	   || (insn & 0xff) == 0xf4
94	   || (insn & 0xff) == 0xf5
95	   || (insn & 0xff) == 0xf6)
96    {
97      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
98      if (status != 0)
99	{
100	  (*info->memory_error_func) (status, memaddr, info);
101	   return -1;
102	}
103      insn = bfd_getb16 (buffer);
104      consume = 2;
105    }
106
107  /* These are three byte insns.  */
108  else if ((insn & 0xff) == 0xf8
109	   || (insn & 0xff) == 0xcc
110	   || (insn & 0xff) == 0xf9
111	   || (insn & 0xf3) == 0x01
112	   || (insn & 0xf3) == 0x02
113	   || (insn & 0xf3) == 0x03
114	   || (insn & 0xfc) == 0x24
115	   || (insn & 0xfc) == 0x2c
116	   || (insn & 0xfc) == 0x30
117	   || (insn & 0xfc) == 0x34
118	   || (insn & 0xfc) == 0x38
119	   || (insn & 0xff) == 0xde
120	   || (insn & 0xff) == 0xdf
121	   || (insn & 0xff) == 0xcc)
122    {
123      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
124      if (status != 0)
125	{
126	  (*info->memory_error_func) (status, memaddr, info);
127	  return -1;
128	}
129      insn = bfd_getb16 (buffer);
130      insn <<= 8;
131      status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
132      if (status != 0)
133	{
134	  (*info->memory_error_func) (status, memaddr, info);
135	  return -1;
136	}
137      insn |= *(unsigned char *)buffer;
138      consume = 3;
139    }
140
141  /* These are four byte insns.  */
142  else if ((insn & 0xff) == 0xfa
143	   || (insn & 0xff) == 0xfb)
144    {
145      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
146      if (status != 0)
147	{
148	  (*info->memory_error_func) (status, memaddr, info);
149	  return -1;
150	}
151      insn = bfd_getb32 (buffer);
152      consume = 4;
153    }
154
155  /* These are five byte insns.  */
156  else if ((insn & 0xff) == 0xcd
157	   || (insn & 0xff) == 0xdc)
158    {
159      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
160      if (status != 0)
161	{
162	  (*info->memory_error_func) (status, memaddr, info);
163	  return -1;
164	}
165      insn = bfd_getb32 (buffer);
166      consume = 5;
167    }
168
169  /* These are six byte insns.  */
170  else if ((insn & 0xff) == 0xfd
171	   || (insn & 0xff) == 0xfc)
172    {
173      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
174      if (status != 0)
175	{
176	  (*info->memory_error_func) (status, memaddr, info);
177	  return -1;
178	}
179
180      insn = bfd_getb32 (buffer);
181      consume = 6;
182    }
183
184  /* Else its a seven byte insns (in theory).  */
185  else
186    {
187      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
188      if (status != 0)
189	{
190	  (*info->memory_error_func) (status, memaddr, info);
191	  return -1;
192	}
193
194      insn = bfd_getb32 (buffer);
195      consume = 7;
196    }
197
198  disassemble (memaddr, info, insn, consume);
199
200  return consume;
201}
202
203static void
204disassemble (memaddr, info, insn, size)
205     bfd_vma memaddr;
206     struct disassemble_info *info;
207     unsigned long insn;
208     unsigned int size;
209{
210  struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
211  const struct mn10300_operand *operand;
212  bfd_byte buffer[4];
213  unsigned long extension = 0;
214  int status, match = 0;
215
216  /* Find the opcode.  */
217  while (op->name)
218    {
219      int mysize, extra_shift;
220
221      if (op->format == FMT_S0)
222	mysize = 1;
223      else if (op->format == FMT_S1
224	       || op->format == FMT_D0)
225	mysize = 2;
226      else if (op->format == FMT_S2
227	       || op->format == FMT_D1)
228	mysize = 3;
229      else if (op->format == FMT_S4)
230	mysize = 5;
231      else if (op->format == FMT_D2)
232	mysize = 4;
233      else if (op->format == FMT_D4)
234	mysize = 6;
235      else
236	mysize = 7;
237
238      if ((op->mask & insn) == op->opcode
239	  && size == mysize)
240	{
241	  const unsigned char *opindex_ptr;
242	  unsigned int nocomma;
243	  int paren = 0;
244
245	  if (op->format == FMT_D1 || op->format == FMT_S1)
246	    extra_shift = 8;
247	  else if (op->format == FMT_D2 || op->format == FMT_D4
248		   || op->format == FMT_S2 || op->format == FMT_S4
249		   || op->format == FMT_S6 || op->format == FMT_D5)
250	    extra_shift = 16;
251	  else
252	    extra_shift = 0;
253
254	  if (size == 1 || size == 2)
255	    {
256	      extension = 0;
257	    }
258	  else if (size == 3
259		   && (op->format == FMT_D1
260		       || op->opcode == 0xdf0000
261		       || op->opcode == 0xde0000))
262	    {
263	      extension = 0;
264	    }
265	  else if (size == 3)
266	    {
267	      insn &= 0xff0000;
268	      status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
269	      if (status != 0)
270		{
271		  (*info->memory_error_func) (status, memaddr, info);
272		  return;
273		}
274
275	      insn |= bfd_getl16 (buffer);
276	      extension = 0;
277	    }
278	  else if (size == 4
279		   && (op->opcode == 0xfaf80000
280		       || op->opcode == 0xfaf00000
281		       || op->opcode == 0xfaf40000))
282	    {
283	      extension = 0;
284	    }
285	  else if (size == 4)
286	    {
287	      insn &= 0xffff0000;
288	      status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
289	      if (status != 0)
290		{
291		  (*info->memory_error_func) (status, memaddr, info);
292		  return;
293		}
294
295	      insn |= bfd_getl16 (buffer);
296	      extension = 0;
297	    }
298	  else if (size == 5 && op->opcode == 0xdc000000)
299	    {
300	      unsigned long temp = 0;
301	      status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
302	      if (status != 0)
303		{
304		  (*info->memory_error_func) (status, memaddr, info);
305		  return;
306		}
307	      temp |= bfd_getl32 (buffer);
308
309	      insn &= 0xff000000;
310	      insn |= (temp & 0xffffff00) >> 8;
311	      extension = temp & 0xff;
312	    }
313	  else if (size == 5)
314	    {
315	      unsigned long temp = 0;
316	      status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
317	      if (status != 0)
318		{
319		  (*info->memory_error_func) (status, memaddr, info);
320		  return;
321		}
322	      temp |= bfd_getl16 (buffer);
323
324	      insn &= 0xff0000ff;
325	      insn |= temp << 8;
326
327	      status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
328	      if (status != 0)
329		{
330		  (*info->memory_error_func) (status, memaddr, info);
331		  return;
332		}
333	      extension = *(unsigned char *)buffer;
334	    }
335	  else if (size == 6)
336	    {
337	      unsigned long temp = 0;
338	      status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
339	      if (status != 0)
340		{
341		  (*info->memory_error_func) (status, memaddr, info);
342		  return;
343		}
344	      temp |= bfd_getl32 (buffer);
345
346	      insn &= 0xffff0000;
347	      insn |= (temp >> 16) & 0xffff;
348	      extension = temp & 0xffff;
349	    }
350	  else if (size == 7 && op->opcode == 0xdd000000)
351	    {
352	      unsigned long temp = 0;
353	      status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
354	      if (status != 0)
355		{
356		  (*info->memory_error_func) (status, memaddr, info);
357		  return;
358		}
359	      temp |= bfd_getl32 (buffer);
360
361	      insn &= 0xff000000;
362	      insn |= (temp >> 8) & 0xffffff;
363	      extension = (temp & 0xff) << 16;
364
365	      status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
366	      if (status != 0)
367		{
368		  (*info->memory_error_func) (status, memaddr, info);
369		  return;
370		}
371	      extension |= bfd_getb16 (buffer);
372	    }
373	  else if (size == 7)
374	    {
375	      unsigned long temp = 0;
376	      status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
377	      if (status != 0)
378		{
379		  (*info->memory_error_func) (status, memaddr, info);
380		  return;
381		}
382	      temp |= bfd_getl32 (buffer);
383
384	      insn &= 0xffff0000;
385	      insn |= (temp >> 16) & 0xffff;
386	      extension = (temp & 0xffff) << 8;
387
388	      status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
389	      if (status != 0)
390		{
391		  (*info->memory_error_func) (status, memaddr, info);
392		  return;
393		}
394	      extension |= *(unsigned char *)buffer;
395	    }
396
397	  match = 1;
398	  (*info->fprintf_func) (info->stream, "%s\t", op->name);
399
400	  /* Now print the operands.  */
401	  for (opindex_ptr = op->operands, nocomma = 1;
402	       *opindex_ptr != 0;
403	       opindex_ptr++)
404	    {
405	      unsigned long value;
406
407	      operand = &mn10300_operands[*opindex_ptr];
408
409	      if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
410		{
411		  unsigned long temp;
412		  value = insn & ((1 << operand->bits) - 1);
413		  value <<= (32 - operand->bits);
414		  temp = extension >> operand->shift;
415		  temp &= ((1 << (32 - operand->bits)) - 1);
416		  value |= temp;
417		}
418	      else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
419		{
420		  value = ((extension >> (operand->shift))
421			   & ((1 << operand->bits) - 1));
422		}
423	      else
424		{
425		  value = ((insn >> (operand->shift))
426			   & ((1 << operand->bits) - 1));
427		}
428
429	      if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
430		value = ((long)(value << (32 - operand->bits))
431			  >> (32 - operand->bits));
432
433	      if (!nocomma
434		  && (!paren
435		      || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
436		(*info->fprintf_func) (info->stream, ",");
437
438	      nocomma = 0;
439
440	      if ((operand->flags & MN10300_OPERAND_DREG) != 0)
441		{
442		  value = ((insn >> (operand->shift + extra_shift))
443			   & ((1 << operand->bits) - 1));
444		  (*info->fprintf_func) (info->stream, "d%d", value);
445		}
446
447	      else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
448		{
449		  value = ((insn >> (operand->shift + extra_shift))
450			   & ((1 << operand->bits) - 1));
451		  (*info->fprintf_func) (info->stream, "a%d", value);
452		}
453
454	      else if ((operand->flags & MN10300_OPERAND_SP) != 0)
455		(*info->fprintf_func) (info->stream, "sp");
456
457	      else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
458		(*info->fprintf_func) (info->stream, "psw");
459
460	      else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
461		(*info->fprintf_func) (info->stream, "mdr");
462
463	      else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
464		{
465		  if (paren)
466		    (*info->fprintf_func) (info->stream, ")");
467		  else
468		    {
469		      (*info->fprintf_func) (info->stream, "(");
470		      nocomma = 1;
471		    }
472		  paren = !paren;
473		}
474
475	      else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
476		(*info->print_address_func) (value + memaddr, info);
477
478	      else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
479		(*info->print_address_func) (value, info);
480
481	      else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
482		{
483		  int comma = 0;
484
485		  (*info->fprintf_func) (info->stream, "[");
486		  if (value & 0x80)
487		    {
488		      (*info->fprintf_func) (info->stream, "d2");
489		      comma = 1;
490		    }
491
492		  if (value & 0x40)
493		    {
494		      if (comma)
495			(*info->fprintf_func) (info->stream, ",");
496		      (*info->fprintf_func) (info->stream, "d3");
497		      comma = 1;
498		    }
499
500		  if (value & 0x20)
501		    {
502		      if (comma)
503			(*info->fprintf_func) (info->stream, ",");
504		      (*info->fprintf_func) (info->stream, "a2");
505		      comma = 1;
506		    }
507
508		  if (value & 0x10)
509		    {
510		      if (comma)
511			(*info->fprintf_func) (info->stream, ",");
512		      (*info->fprintf_func) (info->stream, "a3");
513		      comma = 1;
514		    }
515
516		  if (value & 0x08)
517		    {
518		      if (comma)
519			(*info->fprintf_func) (info->stream, ",");
520		      (*info->fprintf_func) (info->stream, "other");
521		      comma = 1;
522		    }
523		  (*info->fprintf_func) (info->stream, "]");
524		}
525
526	      else
527		(*info->fprintf_func) (info->stream, "%d", value);
528	    }
529	  /* All done. */
530	  break;
531	}
532      op++;
533    }
534
535  if (!match)
536    {
537	(*info->fprintf_func) (info->stream, "unknown\t0x%04x", insn);
538    }
539}
540