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