2000-08-08 Jason Eckhardt <jle@cygnus.com>
[external/binutils.git] / opcodes / m10300-dis.c
1 /* Disassemble MN10300 instructions.
2    Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18
19 #include <stdio.h>
20
21 #include "sysdep.h"
22 #include "opcode/mn10300.h" 
23 #include "dis-asm.h"
24 #include "opintl.h"
25
26 static void disassemble PARAMS ((bfd_vma, struct disassemble_info *,
27                                  unsigned long insn, unsigned int));
28
29 #define HAVE_AM33 (info->mach == AM33)
30 #define HAVE_AM30 (info->mach == AM30)
31
32 int 
33 print_insn_mn10300 (memaddr, info)
34      bfd_vma memaddr;
35      struct disassemble_info *info;
36 {
37   int status;
38   bfd_byte buffer[4];
39   unsigned long insn;
40   unsigned int consume;
41
42   /* First figure out how big the opcode is.  */
43   status = (*info->read_memory_func) (memaddr, buffer, 1, info);
44   if (status != 0)
45     {
46       (*info->memory_error_func) (status, memaddr, info);
47       return -1;
48     }
49   insn = *(unsigned char *) buffer;
50
51   /* These are one byte insns.  */
52   if ((insn & 0xf3) == 0x00
53       || (insn & 0xf0) == 0x10
54       || (insn & 0xfc) == 0x3c
55       || (insn & 0xf3) == 0x41
56       || (insn & 0xf3) == 0x40
57       || (insn & 0xfc) == 0x50
58       || (insn & 0xfc) == 0x54
59       || (insn & 0xf0) == 0x60
60       || (insn & 0xf0) == 0x70
61       || ((insn & 0xf0) == 0x80
62           && (insn & 0x0c) >> 2 != (insn & 0x03))
63       || ((insn & 0xf0) == 0x90
64           && (insn & 0x0c) >> 2 != (insn & 0x03))
65       || ((insn & 0xf0) == 0xa0
66           && (insn & 0x0c) >> 2 != (insn & 0x03))
67       || ((insn & 0xf0) == 0xb0
68           && (insn & 0x0c) >> 2 != (insn & 0x03))
69       || (insn & 0xff) == 0xcb
70       || (insn & 0xfc) == 0xd0
71       || (insn & 0xfc) == 0xd4
72       || (insn & 0xfc) == 0xd8
73       || (insn & 0xf0) == 0xe0
74       || (insn & 0xff) == 0xff)
75     {
76       consume = 1;
77     }
78
79   /* These are two byte insns.  */
80   else if ((insn & 0xf0) == 0x80
81            || (insn & 0xf0) == 0x90
82            || (insn & 0xf0) == 0xa0
83            || (insn & 0xf0) == 0xb0
84            || (insn & 0xfc) == 0x20
85            || (insn & 0xfc) == 0x28
86            || (insn & 0xf3) == 0x43
87            || (insn & 0xf3) == 0x42
88            || (insn & 0xfc) == 0x58
89            || (insn & 0xfc) == 0x5c
90            || ((insn & 0xf0) == 0xc0
91                && (insn & 0xff) != 0xcb
92                && (insn & 0xff) != 0xcc
93                && (insn & 0xff) != 0xcd)
94            || (insn & 0xff) == 0xf0
95            || (insn & 0xff) == 0xf1
96            || (insn & 0xff) == 0xf2
97            || (insn & 0xff) == 0xf3
98            || (insn & 0xff) == 0xf4
99            || (insn & 0xff) == 0xf5
100            || (insn & 0xff) == 0xf6)
101     {
102       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
103       if (status != 0)
104         {
105           (*info->memory_error_func) (status, memaddr, info);
106            return -1;
107         }
108       insn = bfd_getb16 (buffer);
109       consume = 2;
110     }
111
112   /* These are three byte insns.  */
113   else if ((insn & 0xff) == 0xf8
114            || (insn & 0xff) == 0xcc 
115            || (insn & 0xff) == 0xf9
116            || (insn & 0xf3) == 0x01
117            || (insn & 0xf3) == 0x02
118            || (insn & 0xf3) == 0x03
119            || (insn & 0xfc) == 0x24
120            || (insn & 0xfc) == 0x2c
121            || (insn & 0xfc) == 0x30
122            || (insn & 0xfc) == 0x34
123            || (insn & 0xfc) == 0x38
124            || (insn & 0xff) == 0xde
125            || (insn & 0xff) == 0xdf
126            || (insn & 0xff) == 0xf9
127            || (insn & 0xff) == 0xcc)
128     {
129       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
130       if (status != 0)
131         {
132           (*info->memory_error_func) (status, memaddr, info);
133           return -1;
134         }
135       insn = bfd_getb16 (buffer);
136       insn <<= 8;
137       status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
138       if (status != 0)
139         {
140           (*info->memory_error_func) (status, memaddr, info);
141           return -1;
142         }
143       insn |= *(unsigned char *)buffer;
144       consume = 3;
145     }
146
147   /* These are four byte insns.  */
148   else if ((insn & 0xff) == 0xfa
149            || (insn & 0xff) == 0xf7
150            || (insn & 0xff) == 0xfb)
151     {
152       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
153       if (status != 0)
154         {
155           (*info->memory_error_func) (status, memaddr, info);
156           return -1;
157         }
158       insn = bfd_getb32 (buffer);
159       consume = 4;
160     }
161
162   /* These are five byte insns.  */
163   else if ((insn & 0xff) == 0xcd
164            || (insn & 0xff) == 0xdc)
165     {
166       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
167       if (status != 0)
168         {
169           (*info->memory_error_func) (status, memaddr, info);
170           return -1;
171         }
172       insn = bfd_getb32 (buffer);
173       consume = 5;
174     }
175
176   /* These are six byte insns.  */
177   else if ((insn & 0xff) == 0xfd
178            || (insn & 0xff) == 0xfc)
179     {
180       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
181       if (status != 0)
182         {
183           (*info->memory_error_func) (status, memaddr, info);
184           return -1;
185         }
186
187       insn = bfd_getb32 (buffer);
188       consume = 6;
189     }
190
191   /* Else its a seven byte insns (in theory).  */
192   else
193     {
194       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
195       if (status != 0)
196         {
197           (*info->memory_error_func) (status, memaddr, info);
198           return -1;
199         }
200
201       insn = bfd_getb32 (buffer);
202       consume = 7;
203     }
204
205   disassemble (memaddr, info, insn, consume);
206
207   return consume;
208 }
209
210 static void
211 disassemble (memaddr, info, insn, size)
212      bfd_vma memaddr;
213      struct disassemble_info *info;
214      unsigned long insn;
215      unsigned int size;
216 {
217   struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
218   const struct mn10300_operand *operand;
219   bfd_byte buffer[4];
220   unsigned long extension = 0;
221   int status, match = 0;
222
223   /* Find the opcode.  */
224   while (op->name)
225     {
226       int mysize, extra_shift;
227
228       if (op->format == FMT_S0)
229         mysize = 1;
230       else if (op->format == FMT_S1
231                || op->format == FMT_D0)
232         mysize = 2;
233       else if (op->format == FMT_S2
234                || op->format == FMT_D1)
235         mysize = 3;
236       else if (op->format == FMT_S4)
237         mysize = 5;
238       else if (op->format == FMT_D2)
239         mysize = 4;
240       else if (op->format == FMT_D4)
241         mysize = 6;
242       else if (op->format == FMT_D6)
243         mysize = 3;
244       else if (op->format == FMT_D7 || op->format == FMT_D10)
245         mysize = 4;
246       else if (op->format == FMT_D8)
247         mysize = 6;
248       else if (op->format == FMT_D9)
249         mysize = 7;
250       else
251         mysize = 7;
252         
253       if ((op->mask & insn) == op->opcode
254           && size == (unsigned int) mysize
255           && (op->machine == 0
256               || (op->machine == AM33 && HAVE_AM33)
257               || (op->machine == AM30 && HAVE_AM30)))
258         {
259           const unsigned char *opindex_ptr;
260           unsigned int nocomma;
261           int paren = 0;
262           
263           if (op->format == FMT_D1 || op->format == FMT_S1)
264             extra_shift = 8;
265           else if (op->format == FMT_D2 || op->format == FMT_D4
266                    || op->format == FMT_S2 || op->format == FMT_S4
267                    || op->format == FMT_S6 || op->format == FMT_D5)
268             extra_shift = 16;
269           else if (op->format == FMT_D7
270                    || op->format == FMT_D8
271                    || op->format == FMT_D9)
272             extra_shift = 8;
273           else
274             extra_shift = 0;
275
276           if (size == 1 || size == 2)
277             {
278               extension = 0;
279             }
280           else if (size == 3
281                    && (op->format == FMT_D1
282                        || op->opcode == 0xdf0000
283                        || op->opcode == 0xde0000))
284             {
285               extension = 0;
286             }
287           else if (size == 3
288                    && op->format == FMT_D6)
289             {
290               extension = 0;
291             }
292           else if (size == 3)
293             {
294               insn &= 0xff0000;
295               status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
296               if (status != 0)
297                 {
298                   (*info->memory_error_func) (status, memaddr, info);
299                   return;
300                 }
301
302               insn |= bfd_getl16 (buffer);
303               extension = 0;
304             }
305           else if (size == 4
306                    && (op->opcode == 0xfaf80000
307                        || op->opcode == 0xfaf00000
308                        || op->opcode == 0xfaf40000))
309             {
310               extension = 0;
311             }
312           else if (size == 4
313                    && (op->format == FMT_D7
314                        || op->format == FMT_D10))
315             {
316               extension = 0;
317             }
318           else if (size == 4)
319             {
320               insn &= 0xffff0000;
321               status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
322               if (status != 0)
323                 {
324                   (*info->memory_error_func) (status, memaddr, info);
325                   return;
326                 }
327
328               insn |= bfd_getl16 (buffer);
329               extension = 0;
330             }
331           else if (size == 5 && op->opcode == 0xdc000000)
332             {
333               unsigned long temp = 0;
334               status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
335               if (status != 0)
336                 {
337                   (*info->memory_error_func) (status, memaddr, info);
338                   return;
339                 }
340               temp |= bfd_getl32 (buffer);
341
342               insn &= 0xff000000;
343               insn |= (temp & 0xffffff00) >> 8;
344               extension = temp & 0xff;
345             }
346           else if (size == 5)
347             {
348               unsigned long temp = 0;
349               status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
350               if (status != 0)
351                 {
352                   (*info->memory_error_func) (status, memaddr, info);
353                   return;
354                 }
355               temp |= bfd_getl16 (buffer);
356
357               insn &= 0xff0000ff;
358               insn |= temp << 8;
359
360               status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
361               if (status != 0)
362                 {
363                   (*info->memory_error_func) (status, memaddr, info);
364                   return;
365                 }
366               extension = *(unsigned char *)buffer;
367             }
368           else if (size == 6 && op->format == FMT_D8)
369             {
370               insn &= 0xffffff00;
371               status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
372               if (status != 0)
373                 {
374                   (*info->memory_error_func) (status, memaddr, info);
375                   return;
376                 }
377               insn |= *(unsigned char *)buffer;
378
379               status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
380               if (status != 0)
381                 {
382                   (*info->memory_error_func) (status, memaddr, info);
383                   return;
384                 }
385               extension = bfd_getl16 (buffer);
386             }
387           else if (size == 6)
388             {
389               unsigned long temp = 0;
390               status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
391               if (status != 0)
392                 {
393                   (*info->memory_error_func) (status, memaddr, info);
394                   return;
395                 }
396               temp |= bfd_getl32 (buffer);
397
398               insn &= 0xffff0000;
399               insn |= (temp >> 16) & 0xffff;
400               extension = temp & 0xffff;
401             }
402           else if (size == 7 && op->format == FMT_D9)
403             {
404               insn &= 0xffffff00;
405               status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
406               if (status != 0)
407                 {
408                   (*info->memory_error_func) (status, memaddr, info);
409                   return;
410                 }
411               extension = bfd_getl32 (buffer);
412               insn |= (extension & 0xff000000) >> 24;
413               extension &= 0xffffff;
414             }
415           else if (size == 7 && op->opcode == 0xdd000000)
416             {
417               unsigned long temp = 0;
418               status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
419               if (status != 0)
420                 {
421                   (*info->memory_error_func) (status, memaddr, info);
422                   return;
423                 }
424               temp |= bfd_getl32 (buffer);
425
426               insn &= 0xff000000;
427               insn |= (temp >> 8) & 0xffffff;
428               extension = (temp & 0xff) << 16;
429               
430               status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
431               if (status != 0)
432                 {
433                   (*info->memory_error_func) (status, memaddr, info);
434                   return;
435                 }
436               extension |= bfd_getb16 (buffer);
437             }
438           else if (size == 7)
439             {
440               unsigned long temp = 0;
441               status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
442               if (status != 0)
443                 {
444                   (*info->memory_error_func) (status, memaddr, info);
445                   return;
446                 }
447               temp |= bfd_getl32 (buffer);
448
449               insn &= 0xffff0000;
450               insn |= (temp >> 16) & 0xffff;
451               extension = (temp & 0xffff) << 8;
452               
453               status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
454               if (status != 0)
455                 {
456                   (*info->memory_error_func) (status, memaddr, info);
457                   return;
458                 }
459               extension |= *(unsigned char *)buffer;
460             }
461
462           match = 1;
463           (*info->fprintf_func) (info->stream, "%s\t", op->name);
464
465           /* Now print the operands.  */
466           for (opindex_ptr = op->operands, nocomma = 1;
467                *opindex_ptr != 0;
468                opindex_ptr++)
469             {
470               unsigned long value;
471
472               operand = &mn10300_operands[*opindex_ptr];
473
474               /* If this operand is a PLUS (autoincrement), then do not emit
475                  a comma before emitting the plus.  */
476               if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
477                 nocomma = 1;
478
479               if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
480                 {
481                   unsigned long temp;
482                   value = insn & ((1 << operand->bits) - 1);
483                   value <<= (32 - operand->bits);
484                   temp = extension >> operand->shift;
485                   temp &= ((1 << (32 - operand->bits)) - 1);
486                   value |= temp;
487                   value = ((value ^ (((unsigned long)1) << 31))
488                            - (((unsigned long)1) << 31));
489                 }
490               else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
491                 {
492                   unsigned long temp;
493                   value = insn & ((1 << operand->bits) - 1);
494                   value <<= (24 - operand->bits);
495                   temp = extension >> operand->shift;
496                   temp &= ((1 << (24 - operand->bits)) - 1);
497                   value |= temp;
498                   if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
499                     value = ((value & 0xffffff) ^ 0x800000) - 0x800000;
500                 }
501               else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
502                 {
503                   value = ((extension >> (operand->shift))
504                            & ((1 << operand->bits) - 1));
505                 }
506               else
507                 {
508                   value = ((insn >> (operand->shift))
509                            & ((1 << operand->bits) - 1));
510                 }
511
512               if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
513                   /* These are properly extended by the code above.  */
514                   && ((operand->flags & MN10300_OPERAND_24BIT) == 0))
515                 value = ((value ^ (((unsigned long)1) << (operand->bits - 1)))
516                          - (((unsigned long)1) << (operand->bits - 1)));
517
518               if (!nocomma
519                   && (!paren
520                       || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
521                 (*info->fprintf_func) (info->stream, ",");
522
523               nocomma = 0;
524                 
525               if ((operand->flags & MN10300_OPERAND_DREG) != 0)
526                 {
527                   value = ((insn >> (operand->shift + extra_shift))
528                            & ((1 << operand->bits) - 1));
529                   (*info->fprintf_func) (info->stream, "d%d", (int)value);
530                 }
531
532               else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
533                 {
534                   value = ((insn >> (operand->shift + extra_shift))
535                            & ((1 << operand->bits) - 1));
536                   (*info->fprintf_func) (info->stream, "a%d", (int)value);
537                 }
538
539               else if ((operand->flags & MN10300_OPERAND_SP) != 0)
540                 (*info->fprintf_func) (info->stream, "sp");
541
542               else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
543                 (*info->fprintf_func) (info->stream, "psw");
544
545               else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
546                 (*info->fprintf_func) (info->stream, "mdr");
547
548               else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
549                 {
550                   value = ((insn >> (operand->shift + extra_shift))
551                            & ((1 << operand->bits) - 1));
552                   if (value < 8)
553                     (*info->fprintf_func) (info->stream, "r%d", (int)value);
554                   else if (value < 12)
555                     (*info->fprintf_func) (info->stream, "a%d", (int)value - 8);
556                   else
557                     (*info->fprintf_func) (info->stream, "d%d", (int)value - 12);
558                 }
559
560               else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
561                 {
562                   value = ((insn >> (operand->shift + extra_shift))
563                            & ((1 << operand->bits) - 1));
564                   if (value == 0)
565                     (*info->fprintf_func) (info->stream, "sp", value);
566                   else
567                   (*info->fprintf_func) (info->stream, "xr%d", (int)value);
568                 }
569
570               else if ((operand->flags & MN10300_OPERAND_USP) != 0)
571                 (*info->fprintf_func) (info->stream, "usp");
572
573               else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
574                 (*info->fprintf_func) (info->stream, "ssp");
575
576               else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
577                 (*info->fprintf_func) (info->stream, "msp");
578
579               else if ((operand->flags & MN10300_OPERAND_PC) != 0)
580                 (*info->fprintf_func) (info->stream, "pc");
581
582               else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
583                 (*info->fprintf_func) (info->stream, "epsw");
584
585               else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
586                 (*info->fprintf_func) (info->stream, "+");
587
588               else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
589                 {
590                   if (paren)
591                     (*info->fprintf_func) (info->stream, ")");
592                   else
593                     {
594                       (*info->fprintf_func) (info->stream, "(");
595                       nocomma = 1;
596                     }
597                   paren = !paren;
598                 }
599
600               else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
601                 (*info->print_address_func) ((long) value + memaddr, info);
602
603               else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
604                 (*info->print_address_func) (value, info);
605
606               else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
607                 {
608                   int comma = 0;
609
610                   (*info->fprintf_func) (info->stream, "[");
611                   if (value & 0x80)
612                     {
613                       (*info->fprintf_func) (info->stream, "d2");
614                       comma = 1;
615                     }
616
617                   if (value & 0x40)
618                     {
619                       if (comma)
620                         (*info->fprintf_func) (info->stream, ",");
621                       (*info->fprintf_func) (info->stream, "d3");
622                       comma = 1;
623                     }
624
625                   if (value & 0x20)
626                     {
627                       if (comma)
628                         (*info->fprintf_func) (info->stream, ",");
629                       (*info->fprintf_func) (info->stream, "a2");
630                       comma = 1;
631                     }
632
633                   if (value & 0x10)
634                     {
635                       if (comma)
636                         (*info->fprintf_func) (info->stream, ",");
637                       (*info->fprintf_func) (info->stream, "a3");
638                       comma = 1;
639                     }
640
641                   if (value & 0x08)
642                     {
643                       if (comma)
644                         (*info->fprintf_func) (info->stream, ",");
645                       (*info->fprintf_func) (info->stream, "other");
646                       comma = 1;
647                     }
648
649                   if (value & 0x04)
650                     {
651                       if (comma)
652                         (*info->fprintf_func) (info->stream, ",");
653                       (*info->fprintf_func) (info->stream, "exreg0");
654                       comma = 1;
655                     }
656                   if (value & 0x02)
657                     {
658                       if (comma)
659                         (*info->fprintf_func) (info->stream, ",");
660                       (*info->fprintf_func) (info->stream, "exreg1");
661                       comma = 1;
662                     }
663                   if (value & 0x01)
664                     {
665                       if (comma)
666                         (*info->fprintf_func) (info->stream, ",");
667                       (*info->fprintf_func) (info->stream, "exother");
668                       comma = 1;
669                     }
670                   (*info->fprintf_func) (info->stream, "]");
671                 }
672
673               else 
674                 (*info->fprintf_func) (info->stream, "%ld", (long)value);
675             }
676           /* All done. */
677           break;
678         }
679       op++;
680     }
681
682   if (!match)
683     {
684       /* xgettext:c-format */
685       (*info->fprintf_func) (info->stream, _("unknown\t0x%04x"), insn);
686     }
687 }