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