* m10300-dis.c: Only recognize instructions from the currently
[platform/upstream/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            /* start-sanitize-am33 */
124            || (insn & 0xff) == 0xf9
125            /* end-sanitize-am33 */
126            || (insn & 0xff) == 0xcc)
127     {
128       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
129       if (status != 0)
130         {
131           (*info->memory_error_func) (status, memaddr, info);
132           return -1;
133         }
134       insn = bfd_getb16 (buffer);
135       insn <<= 8;
136       status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
137       if (status != 0)
138         {
139           (*info->memory_error_func) (status, memaddr, info);
140           return -1;
141         }
142       insn |= *(unsigned char *)buffer;
143       consume = 3;
144     }
145
146   /* These are four byte insns.  */
147   else if ((insn & 0xff) == 0xfa
148             /* start-sanitize-am33 */
149            || (insn & 0xff) == 0xf7
150             /* end-sanitize-am33 */
151            || (insn & 0xff) == 0xfb)
152     {
153       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
154       if (status != 0)
155         {
156           (*info->memory_error_func) (status, memaddr, info);
157           return -1;
158         }
159       insn = bfd_getb32 (buffer);
160       consume = 4;
161     }
162
163   /* These are five byte insns.  */
164   else if ((insn & 0xff) == 0xcd
165            || (insn & 0xff) == 0xdc)
166     {
167       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
168       if (status != 0)
169         {
170           (*info->memory_error_func) (status, memaddr, info);
171           return -1;
172         }
173       insn = bfd_getb32 (buffer);
174       consume = 5;
175     }
176
177   /* These are six byte insns.  */
178   else if ((insn & 0xff) == 0xfd
179            || (insn & 0xff) == 0xfc)
180     {
181       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
182       if (status != 0)
183         {
184           (*info->memory_error_func) (status, memaddr, info);
185           return -1;
186         }
187
188       insn = bfd_getb32 (buffer);
189       consume = 6;
190     }
191
192   /* Else its a seven byte insns (in theory).  */
193   else
194     {
195       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
196       if (status != 0)
197         {
198           (*info->memory_error_func) (status, memaddr, info);
199           return -1;
200         }
201
202       insn = bfd_getb32 (buffer);
203       consume = 7;
204     }
205
206   disassemble (memaddr, info, insn, consume);
207
208   return consume;
209 }
210
211 static void
212 disassemble (memaddr, info, insn, size)
213      bfd_vma memaddr;
214      struct disassemble_info *info;
215      unsigned long insn;
216      unsigned int size;
217 {
218   struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
219   const struct mn10300_operand *operand;
220   bfd_byte buffer[4];
221   unsigned long extension = 0;
222   int status, match = 0;
223
224   /* Find the opcode.  */
225   while (op->name)
226     {
227       int mysize, extra_shift;
228
229       if (op->format == FMT_S0)
230         mysize = 1;
231       else if (op->format == FMT_S1
232                || op->format == FMT_D0)
233         mysize = 2;
234       else if (op->format == FMT_S2
235                || op->format == FMT_D1)
236         mysize = 3;
237       else if (op->format == FMT_S4)
238         mysize = 5;
239       else if (op->format == FMT_D2)
240         mysize = 4;
241       else if (op->format == FMT_D4)
242         mysize = 6;
243       /* start-sanitize-am33 */
244       else if (op->format == FMT_D6)
245         mysize = 3;
246       else if (op->format == FMT_D7 || op->format == FMT_D10)
247         mysize = 4;
248       else if (op->format == FMT_D8)
249         mysize = 6;
250       else if (op->format == FMT_D9)
251         mysize = 7;
252       /* end-sanitize-am33 */
253       else
254         mysize = 7;
255         
256       if ((op->mask & insn) == op->opcode
257           && size == (unsigned int) mysize
258           && (op->machine == 0
259               || op->machine == info->mach))
260         {
261           const unsigned char *opindex_ptr;
262           unsigned int nocomma;
263           int paren = 0;
264           
265           if (op->format == FMT_D1 || op->format == FMT_S1)
266             extra_shift = 8;
267           else if (op->format == FMT_D2 || op->format == FMT_D4
268                    || op->format == FMT_S2 || op->format == FMT_S4
269                    || op->format == FMT_S6 || op->format == FMT_D5)
270             extra_shift = 16;
271           /* start-sanitize-am33 */
272           else if (op->format == FMT_D7
273                    || op->format == FMT_D8
274                    || op->format == FMT_D9)
275             extra_shift = 8;
276           /* end-sanitize-am33 */
277           else
278             extra_shift = 0;
279
280           if (size == 1 || size == 2)
281             {
282               extension = 0;
283             }
284           else if (size == 3
285                    && (op->format == FMT_D1
286                        || op->opcode == 0xdf0000
287                        || op->opcode == 0xde0000))
288             {
289               extension = 0;
290             }
291           /* start-sanitize-am33 */
292           else if (size == 3
293                    && op->format == FMT_D6)
294             {
295               extension = 0;
296             }
297           /* end-sanitize-am33 */
298           else if (size == 3)
299             {
300               insn &= 0xff0000;
301               status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
302               if (status != 0)
303                 {
304                   (*info->memory_error_func) (status, memaddr, info);
305                   return;
306                 }
307
308               insn |= bfd_getl16 (buffer);
309               extension = 0;
310             }
311           else if (size == 4
312                    && (op->opcode == 0xfaf80000
313                        || op->opcode == 0xfaf00000
314                        || op->opcode == 0xfaf40000))
315             {
316               extension = 0;
317             }
318           /* start-sanitize-am33 */
319           else if (size == 4
320                    && (op->format == FMT_D7
321                        || op->format == FMT_D10))
322             {
323               extension = 0;
324             }
325           /* end-sanitize-am33 */
326           else if (size == 4)
327             {
328               insn &= 0xffff0000;
329               status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
330               if (status != 0)
331                 {
332                   (*info->memory_error_func) (status, memaddr, info);
333                   return;
334                 }
335
336               insn |= bfd_getl16 (buffer);
337               extension = 0;
338             }
339           else if (size == 5 && op->opcode == 0xdc000000)
340             {
341               unsigned long temp = 0;
342               status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
343               if (status != 0)
344                 {
345                   (*info->memory_error_func) (status, memaddr, info);
346                   return;
347                 }
348               temp |= bfd_getl32 (buffer);
349
350               insn &= 0xff000000;
351               insn |= (temp & 0xffffff00) >> 8;
352               extension = temp & 0xff;
353             }
354           else if (size == 5)
355             {
356               unsigned long temp = 0;
357               status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
358               if (status != 0)
359                 {
360                   (*info->memory_error_func) (status, memaddr, info);
361                   return;
362                 }
363               temp |= bfd_getl16 (buffer);
364
365               insn &= 0xff0000ff;
366               insn |= temp << 8;
367
368               status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
369               if (status != 0)
370                 {
371                   (*info->memory_error_func) (status, memaddr, info);
372                   return;
373                 }
374               extension = *(unsigned char *)buffer;
375             }
376           /* start-sanitize-am33 */
377           else if (size == 6 && op->format == FMT_D8)
378             {
379               insn &= 0xffffff00;
380               status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
381               if (status != 0)
382                 {
383                   (*info->memory_error_func) (status, memaddr, info);
384                   return;
385                 }
386               insn |= *(unsigned char *)buffer;
387
388               status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
389               if (status != 0)
390                 {
391                   (*info->memory_error_func) (status, memaddr, info);
392                   return;
393                 }
394               extension = bfd_getl16 (buffer);
395             }
396           /* end-sanitize-am33 */
397           else if (size == 6)
398             {
399               unsigned long temp = 0;
400               status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
401               if (status != 0)
402                 {
403                   (*info->memory_error_func) (status, memaddr, info);
404                   return;
405                 }
406               temp |= bfd_getl32 (buffer);
407
408               insn &= 0xffff0000;
409               insn |= (temp >> 16) & 0xffff;
410               extension = temp & 0xffff;
411             }
412           /* start-sanitize-am33 */
413           else if (size == 7 && op->format == FMT_D9)
414             {
415               insn &= 0xffffff00;
416               status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
417               if (status != 0)
418                 {
419                   (*info->memory_error_func) (status, memaddr, info);
420                   return;
421                 }
422               extension = bfd_getl32 (buffer);
423               insn |= (extension & 0xff000000) >> 24;
424               extension &= 0xffffff;
425             }
426           /* end-sanitize-am33 */
427           else if (size == 7 && op->opcode == 0xdd000000)
428             {
429               unsigned long temp = 0;
430               status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
431               if (status != 0)
432                 {
433                   (*info->memory_error_func) (status, memaddr, info);
434                   return;
435                 }
436               temp |= bfd_getl32 (buffer);
437
438               insn &= 0xff000000;
439               insn |= (temp >> 8) & 0xffffff;
440               extension = (temp & 0xff) << 16;
441               
442               status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
443               if (status != 0)
444                 {
445                   (*info->memory_error_func) (status, memaddr, info);
446                   return;
447                 }
448               extension |= bfd_getb16 (buffer);
449             }
450           else if (size == 7)
451             {
452               unsigned long temp = 0;
453               status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
454               if (status != 0)
455                 {
456                   (*info->memory_error_func) (status, memaddr, info);
457                   return;
458                 }
459               temp |= bfd_getl32 (buffer);
460
461               insn &= 0xffff0000;
462               insn |= (temp >> 16) & 0xffff;
463               extension = (temp & 0xffff) << 8;
464               
465               status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
466               if (status != 0)
467                 {
468                   (*info->memory_error_func) (status, memaddr, info);
469                   return;
470                 }
471               extension |= *(unsigned char *)buffer;
472             }
473
474           match = 1;
475           (*info->fprintf_func) (info->stream, "%s\t", op->name);
476
477           /* Now print the operands.  */
478           for (opindex_ptr = op->operands, nocomma = 1;
479                *opindex_ptr != 0;
480                opindex_ptr++)
481             {
482               unsigned long value;
483
484               operand = &mn10300_operands[*opindex_ptr];
485
486               if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
487                 {
488                   unsigned long temp;
489                   value = insn & ((1 << operand->bits) - 1);
490                   value <<= (32 - operand->bits);
491                   temp = extension >> operand->shift;
492                   temp &= ((1 << (32 - operand->bits)) - 1);
493                   value |= temp;
494                 }
495               /* start-sanitize-am33 */
496               else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
497                 {
498                   unsigned long temp;
499                   value = insn & ((1 << operand->bits) - 1);
500                   value <<= (24 - operand->bits);
501                   temp = extension >> operand->shift;
502                   temp &= ((1 << (24 - operand->bits)) - 1);
503                   value |= temp;
504                   if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
505                     value = ((value & 0xffffff) ^ (~0x7fffff)) + 0x800000;
506                 }
507               /* end-sanitize-am33 */
508               else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
509                 {
510                   value = ((extension >> (operand->shift))
511                            & ((1 << operand->bits) - 1));
512                 }
513               else
514                 {
515                   value = ((insn >> (operand->shift))
516                            & ((1 << operand->bits) - 1));
517                 }
518
519               if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
520                    /* start-sanitize-am33 */
521                    /* These are properly extended by the code above.  */
522                    && ((operand->flags & MN10300_OPERAND_24BIT) == 0)
523                    /* end-sanitize-am33 */
524                   )
525                 value = ((long)(value << (32 - operand->bits))
526                           >> (32 - operand->bits));
527
528               if (!nocomma
529                   && (!paren
530                       || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
531                 (*info->fprintf_func) (info->stream, ",");
532
533               nocomma = 0;
534                 
535               if ((operand->flags & MN10300_OPERAND_DREG) != 0)
536                 {
537                   value = ((insn >> (operand->shift + extra_shift))
538                            & ((1 << operand->bits) - 1));
539                   (*info->fprintf_func) (info->stream, "d%d", value);
540                 }
541
542               else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
543                 {
544                   value = ((insn >> (operand->shift + extra_shift))
545                            & ((1 << operand->bits) - 1));
546                   (*info->fprintf_func) (info->stream, "a%d", value);
547                 }
548
549               else if ((operand->flags & MN10300_OPERAND_SP) != 0)
550                 (*info->fprintf_func) (info->stream, "sp");
551
552               else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
553                 (*info->fprintf_func) (info->stream, "psw");
554
555               else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
556                 (*info->fprintf_func) (info->stream, "mdr");
557
558               /* start-sanitize-am33 */
559               else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
560                 {
561                   value = ((insn >> (operand->shift + extra_shift))
562                            & ((1 << operand->bits) - 1));
563                   (*info->fprintf_func) (info->stream, "r%d", value);
564                 }
565
566               else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
567                 {
568                   value = ((insn >> (operand->shift + extra_shift))
569                            & ((1 << operand->bits) - 1));
570                   (*info->fprintf_func) (info->stream, "xr%d", value);
571                 }
572
573               else if ((operand->flags & MN10300_OPERAND_USP) != 0)
574                 (*info->fprintf_func) (info->stream, "usp");
575
576               else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
577                 (*info->fprintf_func) (info->stream, "ssp");
578
579               else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
580                 (*info->fprintf_func) (info->stream, "msp");
581
582               else if ((operand->flags & MN10300_OPERAND_PC) != 0)
583                 (*info->fprintf_func) (info->stream, "pc");
584
585               else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
586                 (*info->fprintf_func) (info->stream, "epsw");
587
588               else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
589                 (*info->fprintf_func) (info->stream, "+");
590               /* end-sanitize-am33 */
591
592               else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
593                 {
594                   if (paren)
595                     (*info->fprintf_func) (info->stream, ")");
596                   else
597                     {
598                       (*info->fprintf_func) (info->stream, "(");
599                       nocomma = 1;
600                     }
601                   paren = !paren;
602                 }
603
604               else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
605                 (*info->print_address_func) ((long) value + memaddr, info);
606
607               else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
608                 (*info->print_address_func) (value, info);
609
610               else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
611                 {
612                   int comma = 0;
613
614                   (*info->fprintf_func) (info->stream, "[");
615                   if (value & 0x80)
616                     {
617                       (*info->fprintf_func) (info->stream, "d2");
618                       comma = 1;
619                     }
620
621                   if (value & 0x40)
622                     {
623                       if (comma)
624                         (*info->fprintf_func) (info->stream, ",");
625                       (*info->fprintf_func) (info->stream, "d3");
626                       comma = 1;
627                     }
628
629                   if (value & 0x20)
630                     {
631                       if (comma)
632                         (*info->fprintf_func) (info->stream, ",");
633                       (*info->fprintf_func) (info->stream, "a2");
634                       comma = 1;
635                     }
636
637                   if (value & 0x10)
638                     {
639                       if (comma)
640                         (*info->fprintf_func) (info->stream, ",");
641                       (*info->fprintf_func) (info->stream, "a3");
642                       comma = 1;
643                     }
644
645                   if (value & 0x08)
646                     {
647                       if (comma)
648                         (*info->fprintf_func) (info->stream, ",");
649                       (*info->fprintf_func) (info->stream, "other");
650                       comma = 1;
651                     }
652
653                   /* start-sanitize-am33 */
654                   if (value & 0x04)
655                     {
656                       if (comma)
657                         (*info->fprintf_func) (info->stream, ",");
658                       (*info->fprintf_func) (info->stream, "exreg0");
659                       comma = 1;
660                     }
661                   if (value & 0x02)
662                     {
663                       if (comma)
664                         (*info->fprintf_func) (info->stream, ",");
665                       (*info->fprintf_func) (info->stream, "exreg1");
666                       comma = 1;
667                     }
668                   if (value & 0x01)
669                     {
670                       if (comma)
671                         (*info->fprintf_func) (info->stream, ",");
672                       (*info->fprintf_func) (info->stream, "exother");
673                       comma = 1;
674                     }
675                   /* end-sanitize-am33 */
676                   (*info->fprintf_func) (info->stream, "]");
677                 }
678
679               else 
680                 (*info->fprintf_func) (info->stream, "%d", value);
681             }
682           /* All done. */
683           break;
684         }
685       op++;
686     }
687
688   if (!match)
689     {
690       /* xgettext:c-format */
691       (*info->fprintf_func) (info->stream, _("unknown\t0x%04x"), insn);
692     }
693 }