This commit was generated by cvs2svn to track changes on a CVS vendor
[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            || (insn & 0xff) == 0xcc)
124     {
125       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
126       if (status != 0)
127         {
128           (*info->memory_error_func) (status, memaddr, info);
129           return -1;
130         }
131       insn = bfd_getb16 (buffer);
132       insn <<= 8;
133       status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
134       if (status != 0)
135         {
136           (*info->memory_error_func) (status, memaddr, info);
137           return -1;
138         }
139       insn |= *(unsigned char *)buffer;
140       consume = 3;
141     }
142
143   /* These are four byte insns.  */
144   else if ((insn & 0xff) == 0xfa
145            || (insn & 0xff) == 0xfb)
146     {
147       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
148       if (status != 0)
149         {
150           (*info->memory_error_func) (status, memaddr, info);
151           return -1;
152         }
153       insn = bfd_getb32 (buffer);
154       consume = 4;
155     }
156
157   /* These are five byte insns.  */
158   else if ((insn & 0xff) == 0xcd
159            || (insn & 0xff) == 0xdc)
160     {
161       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
162       if (status != 0)
163         {
164           (*info->memory_error_func) (status, memaddr, info);
165           return -1;
166         }
167       insn = bfd_getb32 (buffer);
168       consume = 5;
169     }
170
171   /* These are six byte insns.  */
172   else if ((insn & 0xff) == 0xfd
173            || (insn & 0xff) == 0xfc)
174     {
175       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
176       if (status != 0)
177         {
178           (*info->memory_error_func) (status, memaddr, info);
179           return -1;
180         }
181
182       insn = bfd_getb32 (buffer);
183       consume = 6;
184     }
185
186   /* Else its a seven byte insns (in theory).  */
187   else
188     {
189       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
190       if (status != 0)
191         {
192           (*info->memory_error_func) (status, memaddr, info);
193           return -1;
194         }
195
196       insn = bfd_getb32 (buffer);
197       consume = 7;
198     }
199
200   disassemble (memaddr, info, insn, consume);
201
202   return consume;
203 }
204
205 static void
206 disassemble (memaddr, info, insn, size)
207      bfd_vma memaddr;
208      struct disassemble_info *info;
209      unsigned long insn;
210      unsigned int size;
211 {
212   struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
213   const struct mn10300_operand *operand;
214   bfd_byte buffer[4];
215   unsigned long extension = 0;
216   int status, match = 0;
217
218   /* Find the opcode.  */
219   while (op->name)
220     {
221       int mysize, extra_shift;
222
223       if (op->format == FMT_S0)
224         mysize = 1;
225       else if (op->format == FMT_S1
226                || op->format == FMT_D0)
227         mysize = 2;
228       else if (op->format == FMT_S2
229                || op->format == FMT_D1)
230         mysize = 3;
231       else if (op->format == FMT_S4)
232         mysize = 5;
233       else if (op->format == FMT_D2)
234         mysize = 4;
235       else if (op->format == FMT_D4)
236         mysize = 6;
237       else
238         mysize = 7;
239         
240       if ((op->mask & insn) == op->opcode
241           && size == (unsigned int) mysize
242           && (op->machine == 0
243               || op->machine == info->mach))
244         {
245           const unsigned char *opindex_ptr;
246           unsigned int nocomma;
247           int paren = 0;
248           
249           if (op->format == FMT_D1 || op->format == FMT_S1)
250             extra_shift = 8;
251           else if (op->format == FMT_D2 || op->format == FMT_D4
252                    || op->format == FMT_S2 || op->format == FMT_S4
253                    || op->format == FMT_S6 || op->format == FMT_D5)
254             extra_shift = 16;
255           else
256             extra_shift = 0;
257
258           if (size == 1 || size == 2)
259             {
260               extension = 0;
261             }
262           else if (size == 3
263                    && (op->format == FMT_D1
264                        || op->opcode == 0xdf0000
265                        || op->opcode == 0xde0000))
266             {
267               extension = 0;
268             }
269           else if (size == 3)
270             {
271               insn &= 0xff0000;
272               status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
273               if (status != 0)
274                 {
275                   (*info->memory_error_func) (status, memaddr, info);
276                   return;
277                 }
278
279               insn |= bfd_getl16 (buffer);
280               extension = 0;
281             }
282           else if (size == 4
283                    && (op->opcode == 0xfaf80000
284                        || op->opcode == 0xfaf00000
285                        || op->opcode == 0xfaf40000))
286             {
287               extension = 0;
288             }
289           else if (size == 4)
290             {
291               insn &= 0xffff0000;
292               status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
293               if (status != 0)
294                 {
295                   (*info->memory_error_func) (status, memaddr, info);
296                   return;
297                 }
298
299               insn |= bfd_getl16 (buffer);
300               extension = 0;
301             }
302           else if (size == 5 && op->opcode == 0xdc000000)
303             {
304               unsigned long temp = 0;
305               status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
306               if (status != 0)
307                 {
308                   (*info->memory_error_func) (status, memaddr, info);
309                   return;
310                 }
311               temp |= bfd_getl32 (buffer);
312
313               insn &= 0xff000000;
314               insn |= (temp & 0xffffff00) >> 8;
315               extension = temp & 0xff;
316             }
317           else if (size == 5)
318             {
319               unsigned long temp = 0;
320               status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
321               if (status != 0)
322                 {
323                   (*info->memory_error_func) (status, memaddr, info);
324                   return;
325                 }
326               temp |= bfd_getl16 (buffer);
327
328               insn &= 0xff0000ff;
329               insn |= temp << 8;
330
331               status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
332               if (status != 0)
333                 {
334                   (*info->memory_error_func) (status, memaddr, info);
335                   return;
336                 }
337               extension = *(unsigned char *)buffer;
338             }
339           else if (size == 6)
340             {
341               unsigned long temp = 0;
342               status = (*info->read_memory_func) (memaddr + 2, 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 &= 0xffff0000;
351               insn |= (temp >> 16) & 0xffff;
352               extension = temp & 0xffff;
353             }
354           else if (size == 7 && op->opcode == 0xdd000000)
355             {
356               unsigned long temp = 0;
357               status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
358               if (status != 0)
359                 {
360                   (*info->memory_error_func) (status, memaddr, info);
361                   return;
362                 }
363               temp |= bfd_getl32 (buffer);
364
365               insn &= 0xff000000;
366               insn |= (temp >> 8) & 0xffffff;
367               extension = (temp & 0xff) << 16;
368               
369               status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
370               if (status != 0)
371                 {
372                   (*info->memory_error_func) (status, memaddr, info);
373                   return;
374                 }
375               extension |= bfd_getb16 (buffer);
376             }
377           else if (size == 7)
378             {
379               unsigned long temp = 0;
380               status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
381               if (status != 0)
382                 {
383                   (*info->memory_error_func) (status, memaddr, info);
384                   return;
385                 }
386               temp |= bfd_getl32 (buffer);
387
388               insn &= 0xffff0000;
389               insn |= (temp >> 16) & 0xffff;
390               extension = (temp & 0xffff) << 8;
391               
392               status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
393               if (status != 0)
394                 {
395                   (*info->memory_error_func) (status, memaddr, info);
396                   return;
397                 }
398               extension |= *(unsigned char *)buffer;
399             }
400
401           match = 1;
402           (*info->fprintf_func) (info->stream, "%s\t", op->name);
403
404           /* Now print the operands.  */
405           for (opindex_ptr = op->operands, nocomma = 1;
406                *opindex_ptr != 0;
407                opindex_ptr++)
408             {
409               unsigned long value;
410
411               operand = &mn10300_operands[*opindex_ptr];
412
413
414               if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
415                 {
416                   unsigned long temp;
417                   value = insn & ((1 << operand->bits) - 1);
418                   value <<= (32 - operand->bits);
419                   temp = extension >> operand->shift;
420                   temp &= ((1 << (32 - operand->bits)) - 1);
421                   value |= temp;
422                 }
423               else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
424                 {
425                   value = ((extension >> (operand->shift))
426                            & ((1 << operand->bits) - 1));
427                 }
428               else
429                 {
430                   value = ((insn >> (operand->shift))
431                            & ((1 << operand->bits) - 1));
432                 }
433
434               if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
435                   )
436                 value = ((long)(value << (32 - operand->bits))
437                           >> (32 - operand->bits));
438
439               if (!nocomma
440                   && (!paren
441                       || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
442                 (*info->fprintf_func) (info->stream, ",");
443
444               nocomma = 0;
445                 
446               if ((operand->flags & MN10300_OPERAND_DREG) != 0)
447                 {
448                   value = ((insn >> (operand->shift + extra_shift))
449                            & ((1 << operand->bits) - 1));
450                   (*info->fprintf_func) (info->stream, "d%d", value);
451                 }
452
453               else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
454                 {
455                   value = ((insn >> (operand->shift + extra_shift))
456                            & ((1 << operand->bits) - 1));
457                   (*info->fprintf_func) (info->stream, "a%d", value);
458                 }
459
460               else if ((operand->flags & MN10300_OPERAND_SP) != 0)
461                 (*info->fprintf_func) (info->stream, "sp");
462
463               else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
464                 (*info->fprintf_func) (info->stream, "psw");
465
466               else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
467                 (*info->fprintf_func) (info->stream, "mdr");
468
469
470               else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
471                 {
472                   if (paren)
473                     (*info->fprintf_func) (info->stream, ")");
474                   else
475                     {
476                       (*info->fprintf_func) (info->stream, "(");
477                       nocomma = 1;
478                     }
479                   paren = !paren;
480                 }
481
482               else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
483                 (*info->print_address_func) ((long) value + memaddr, info);
484
485               else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
486                 (*info->print_address_func) (value, info);
487
488               else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
489                 {
490                   int comma = 0;
491
492                   (*info->fprintf_func) (info->stream, "[");
493                   if (value & 0x80)
494                     {
495                       (*info->fprintf_func) (info->stream, "d2");
496                       comma = 1;
497                     }
498
499                   if (value & 0x40)
500                     {
501                       if (comma)
502                         (*info->fprintf_func) (info->stream, ",");
503                       (*info->fprintf_func) (info->stream, "d3");
504                       comma = 1;
505                     }
506
507                   if (value & 0x20)
508                     {
509                       if (comma)
510                         (*info->fprintf_func) (info->stream, ",");
511                       (*info->fprintf_func) (info->stream, "a2");
512                       comma = 1;
513                     }
514
515                   if (value & 0x10)
516                     {
517                       if (comma)
518                         (*info->fprintf_func) (info->stream, ",");
519                       (*info->fprintf_func) (info->stream, "a3");
520                       comma = 1;
521                     }
522
523                   if (value & 0x08)
524                     {
525                       if (comma)
526                         (*info->fprintf_func) (info->stream, ",");
527                       (*info->fprintf_func) (info->stream, "other");
528                       comma = 1;
529                     }
530
531                   (*info->fprintf_func) (info->stream, "]");
532                 }
533
534               else 
535                 (*info->fprintf_func) (info->stream, "%d", value);
536             }
537           /* All done. */
538           break;
539         }
540       op++;
541     }
542
543   if (!match)
544     {
545       /* xgettext:c-format */
546       (*info->fprintf_func) (info->stream, _("unknown\t0x%04x"), insn);
547     }
548 }