* m10300-dis.c (print_insn_mn10300): 0xf7 opcode prefix specifies
[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            /* 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         {
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           /* start-sanitize-am33 */
270           else if (op->format == FMT_D7
271                    || op->format == FMT_D8
272                    || op->format == FMT_D9)
273             extra_shift = 8;
274           /* end-sanitize-am33 */
275           else
276             extra_shift = 0;
277
278           if (size == 1 || size == 2)
279             {
280               extension = 0;
281             }
282           else if (size == 3
283                    && (op->format == FMT_D1
284                        || op->opcode == 0xdf0000
285                        || op->opcode == 0xde0000))
286             {
287               extension = 0;
288             }
289           /* start-sanitize-am33 */
290           else if (size == 3
291                    && op->format == FMT_D6)
292             {
293               extension = 0;
294             }
295           /* end-sanitize-am33 */
296           else if (size == 3)
297             {
298               insn &= 0xff0000;
299               status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
300               if (status != 0)
301                 {
302                   (*info->memory_error_func) (status, memaddr, info);
303                   return;
304                 }
305
306               insn |= bfd_getl16 (buffer);
307               extension = 0;
308             }
309           else if (size == 4
310                    && (op->opcode == 0xfaf80000
311                        || op->opcode == 0xfaf00000
312                        || op->opcode == 0xfaf40000))
313             {
314               extension = 0;
315             }
316           /* start-sanitize-am33 */
317           else if (size == 4
318                    && (op->format == FMT_D7
319                        || op->format == FMT_D10))
320             {
321               extension = 0;
322             }
323           /* end-sanitize-am33 */
324           else if (size == 4)
325             {
326               insn &= 0xffff0000;
327               status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
328               if (status != 0)
329                 {
330                   (*info->memory_error_func) (status, memaddr, info);
331                   return;
332                 }
333
334               insn |= bfd_getl16 (buffer);
335               extension = 0;
336             }
337           else if (size == 5 && op->opcode == 0xdc000000)
338             {
339               unsigned long temp = 0;
340               status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
341               if (status != 0)
342                 {
343                   (*info->memory_error_func) (status, memaddr, info);
344                   return;
345                 }
346               temp |= bfd_getl32 (buffer);
347
348               insn &= 0xff000000;
349               insn |= (temp & 0xffffff00) >> 8;
350               extension = temp & 0xff;
351             }
352           else if (size == 5)
353             {
354               unsigned long temp = 0;
355               status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
356               if (status != 0)
357                 {
358                   (*info->memory_error_func) (status, memaddr, info);
359                   return;
360                 }
361               temp |= bfd_getl16 (buffer);
362
363               insn &= 0xff0000ff;
364               insn |= temp << 8;
365
366               status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
367               if (status != 0)
368                 {
369                   (*info->memory_error_func) (status, memaddr, info);
370                   return;
371                 }
372               extension = *(unsigned char *)buffer;
373             }
374           /* start-sanitize-am33 */
375           else if (size == 6 && op->format == FMT_D8)
376             {
377               insn &= 0xffffff00;
378               status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
379               if (status != 0)
380                 {
381                   (*info->memory_error_func) (status, memaddr, info);
382                   return;
383                 }
384               insn |= *(unsigned char *)buffer;
385
386               status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
387               if (status != 0)
388                 {
389                   (*info->memory_error_func) (status, memaddr, info);
390                   return;
391                 }
392               extension = bfd_getl16 (buffer);
393             }
394           /* end-sanitize-am33 */
395           else if (size == 6)
396             {
397               unsigned long temp = 0;
398               status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
399               if (status != 0)
400                 {
401                   (*info->memory_error_func) (status, memaddr, info);
402                   return;
403                 }
404               temp |= bfd_getl32 (buffer);
405
406               insn &= 0xffff0000;
407               insn |= (temp >> 16) & 0xffff;
408               extension = temp & 0xffff;
409             }
410           /* start-sanitize-am33 */
411           else if (size == 7 && op->format == FMT_D9)
412             {
413               insn &= 0xffffff00;
414               status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
415               if (status != 0)
416                 {
417                   (*info->memory_error_func) (status, memaddr, info);
418                   return;
419                 }
420               extension = bfd_getl32 (buffer);
421               insn |= (extension & 0xff000000) >> 24;
422               extension &= 0xffffff;
423             }
424           /* end-sanitize-am33 */
425           else if (size == 7 && op->opcode == 0xdd000000)
426             {
427               unsigned long temp = 0;
428               status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
429               if (status != 0)
430                 {
431                   (*info->memory_error_func) (status, memaddr, info);
432                   return;
433                 }
434               temp |= bfd_getl32 (buffer);
435
436               insn &= 0xff000000;
437               insn |= (temp >> 8) & 0xffffff;
438               extension = (temp & 0xff) << 16;
439               
440               status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
441               if (status != 0)
442                 {
443                   (*info->memory_error_func) (status, memaddr, info);
444                   return;
445                 }
446               extension |= bfd_getb16 (buffer);
447             }
448           else if (size == 7)
449             {
450               unsigned long temp = 0;
451               status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
452               if (status != 0)
453                 {
454                   (*info->memory_error_func) (status, memaddr, info);
455                   return;
456                 }
457               temp |= bfd_getl32 (buffer);
458
459               insn &= 0xffff0000;
460               insn |= (temp >> 16) & 0xffff;
461               extension = (temp & 0xffff) << 8;
462               
463               status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
464               if (status != 0)
465                 {
466                   (*info->memory_error_func) (status, memaddr, info);
467                   return;
468                 }
469               extension |= *(unsigned char *)buffer;
470             }
471
472           match = 1;
473           (*info->fprintf_func) (info->stream, "%s\t", op->name);
474
475           /* Now print the operands.  */
476           for (opindex_ptr = op->operands, nocomma = 1;
477                *opindex_ptr != 0;
478                opindex_ptr++)
479             {
480               unsigned long value;
481
482               operand = &mn10300_operands[*opindex_ptr];
483
484               if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
485                 {
486                   unsigned long temp;
487                   value = insn & ((1 << operand->bits) - 1);
488                   value <<= (32 - operand->bits);
489                   temp = extension >> operand->shift;
490                   temp &= ((1 << (32 - operand->bits)) - 1);
491                   value |= temp;
492                 }
493               /* start-sanitize-am33 */
494               else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
495                 {
496                   unsigned long temp;
497                   value = insn & ((1 << operand->bits) - 1);
498                   value <<= (24 - operand->bits);
499                   temp = extension >> operand->shift;
500                   temp &= ((1 << (24 - operand->bits)) - 1);
501                   value |= temp;
502                   if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
503                     value = ((value & 0xffffff) ^ (~0x7fffff)) + 0x800000;
504                 }
505               /* end-sanitize-am33 */
506               else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
507                 {
508                   value = ((extension >> (operand->shift))
509                            & ((1 << operand->bits) - 1));
510                 }
511               else
512                 {
513                   value = ((insn >> (operand->shift))
514                            & ((1 << operand->bits) - 1));
515                 }
516
517               if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
518                    /* start-sanitize-am33 */
519                    /* These are properly extended by the code above.  */
520                    && ((operand->flags & MN10300_OPERAND_24BIT) == 0)
521                    /* end-sanitize-am33 */
522                   )
523                 value = ((long)(value << (32 - operand->bits))
524                           >> (32 - operand->bits));
525
526               if (!nocomma
527                   && (!paren
528                       || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
529                 (*info->fprintf_func) (info->stream, ",");
530
531               nocomma = 0;
532                 
533               if ((operand->flags & MN10300_OPERAND_DREG) != 0)
534                 {
535                   value = ((insn >> (operand->shift + extra_shift))
536                            & ((1 << operand->bits) - 1));
537                   (*info->fprintf_func) (info->stream, "d%d", value);
538                 }
539
540               else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
541                 {
542                   value = ((insn >> (operand->shift + extra_shift))
543                            & ((1 << operand->bits) - 1));
544                   (*info->fprintf_func) (info->stream, "a%d", value);
545                 }
546
547               else if ((operand->flags & MN10300_OPERAND_SP) != 0)
548                 (*info->fprintf_func) (info->stream, "sp");
549
550               else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
551                 (*info->fprintf_func) (info->stream, "psw");
552
553               else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
554                 (*info->fprintf_func) (info->stream, "mdr");
555
556               /* start-sanitize-am33 */
557               else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
558                 {
559                   value = ((insn >> (operand->shift + extra_shift))
560                            & ((1 << operand->bits) - 1));
561                   (*info->fprintf_func) (info->stream, "r%d", value);
562                 }
563
564               else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
565                 {
566                   value = ((insn >> (operand->shift + extra_shift))
567                            & ((1 << operand->bits) - 1));
568                   (*info->fprintf_func) (info->stream, "xr%d", value);
569                 }
570
571               else if ((operand->flags & MN10300_OPERAND_USP) != 0)
572                 (*info->fprintf_func) (info->stream, "usp");
573
574               else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
575                 (*info->fprintf_func) (info->stream, "ssp");
576
577               else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
578                 (*info->fprintf_func) (info->stream, "msp");
579
580               else if ((operand->flags & MN10300_OPERAND_PC) != 0)
581                 (*info->fprintf_func) (info->stream, "pc");
582
583               else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
584                 (*info->fprintf_func) (info->stream, "epsw");
585
586               else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
587                 (*info->fprintf_func) (info->stream, "+");
588               /* end-sanitize-am33 */
589
590               else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
591                 {
592                   if (paren)
593                     (*info->fprintf_func) (info->stream, ")");
594                   else
595                     {
596                       (*info->fprintf_func) (info->stream, "(");
597                       nocomma = 1;
598                     }
599                   paren = !paren;
600                 }
601
602               else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
603                 (*info->print_address_func) ((long) value + memaddr, info);
604
605               else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
606                 (*info->print_address_func) (value, info);
607
608               else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
609                 {
610                   int comma = 0;
611
612                   (*info->fprintf_func) (info->stream, "[");
613                   if (value & 0x80)
614                     {
615                       (*info->fprintf_func) (info->stream, "d2");
616                       comma = 1;
617                     }
618
619                   if (value & 0x40)
620                     {
621                       if (comma)
622                         (*info->fprintf_func) (info->stream, ",");
623                       (*info->fprintf_func) (info->stream, "d3");
624                       comma = 1;
625                     }
626
627                   if (value & 0x20)
628                     {
629                       if (comma)
630                         (*info->fprintf_func) (info->stream, ",");
631                       (*info->fprintf_func) (info->stream, "a2");
632                       comma = 1;
633                     }
634
635                   if (value & 0x10)
636                     {
637                       if (comma)
638                         (*info->fprintf_func) (info->stream, ",");
639                       (*info->fprintf_func) (info->stream, "a3");
640                       comma = 1;
641                     }
642
643                   if (value & 0x08)
644                     {
645                       if (comma)
646                         (*info->fprintf_func) (info->stream, ",");
647                       (*info->fprintf_func) (info->stream, "other");
648                       comma = 1;
649                     }
650
651                   /* start-sanitize-am33 */
652                   if (value & 0x04)
653                     {
654                       if (comma)
655                         (*info->fprintf_func) (info->stream, ",");
656                       (*info->fprintf_func) (info->stream, "exreg0");
657                       comma = 1;
658                     }
659                   if (value & 0x02)
660                     {
661                       if (comma)
662                         (*info->fprintf_func) (info->stream, ",");
663                       (*info->fprintf_func) (info->stream, "exreg1");
664                       comma = 1;
665                     }
666                   if (value & 0x01)
667                     {
668                       if (comma)
669                         (*info->fprintf_func) (info->stream, ",");
670                       (*info->fprintf_func) (info->stream, "exother");
671                       comma = 1;
672                     }
673                   /* end-sanitize-am33 */
674                   (*info->fprintf_func) (info->stream, "]");
675                 }
676
677               else 
678                 (*info->fprintf_func) (info->stream, "%d", value);
679             }
680           /* All done. */
681           break;
682         }
683       op++;
684     }
685
686   if (!match)
687     {
688       /* xgettext:c-format */
689       (*info->fprintf_func) (info->stream, _("unknown\t0x%04x"), insn);
690     }
691 }