]> Git Repo - binutils.git/blob - opcodes/mn10300-dis.c
* ppc-opc.c: Add PPC 403 instructions and extended opcodes. From
[binutils.git] / opcodes / mn10300-dis.c
1 /* Disassemble MN10300 instructions.
2    Copyright (C) 1996, 1997 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
25 static void disassemble PARAMS ((bfd_vma, struct disassemble_info *,
26                                  unsigned long insn, unsigned int));
27
28 int 
29 print_insn_mn10300 (memaddr, info)
30      bfd_vma memaddr;
31      struct disassemble_info *info;
32 {
33   int status;
34   bfd_byte buffer[4];
35   unsigned long insn;
36   unsigned int consume;
37
38   /* First figure out how big the opcode is.  */
39   status = (*info->read_memory_func) (memaddr, buffer, 1, info);
40   if (status != 0)
41     {
42       (*info->memory_error_func) (status, memaddr, info);
43       return -1;
44     }
45   insn = *(unsigned char *) buffer;
46
47   /* These are one byte insns.  */
48   if ((insn & 0xf3) == 0x00
49       || (insn & 0xf0) == 0x10
50       || (insn & 0xfc) == 0x3c
51       || (insn & 0xf3) == 0x41
52       || (insn & 0xf3) == 0x40
53       || (insn & 0xfc) == 0x50
54       || (insn & 0xfc) == 0x54
55       || (insn & 0xf0) == 0x60
56       || (insn & 0xf0) == 0x70
57       || ((insn & 0xf0) == 0x80
58           && (insn & 0x0c) >> 2 != (insn & 0x03))
59       || ((insn & 0xf0) == 0x90
60           && (insn & 0x0c) >> 2 != (insn & 0x03))
61       || ((insn & 0xf0) == 0xa0
62           && (insn & 0x0c) >> 2 != (insn & 0x03))
63       || ((insn & 0xf0) == 0xb0
64           && (insn & 0x0c) >> 2 != (insn & 0x03))
65       || (insn & 0xff) == 0xcb
66       || (insn & 0xfc) == 0xd0
67       || (insn & 0xfc) == 0xd4
68       || (insn & 0xfc) == 0xd8
69       || (insn & 0xf0) == 0xe0)
70     {
71       consume = 1;
72     }
73
74   /* These are two byte insns.  */
75   else if ((insn & 0xf0) == 0x80
76            || (insn & 0xf0) == 0x90
77            || (insn & 0xf0) == 0xa0
78            || (insn & 0xf0) == 0xb0
79            || (insn & 0xfc) == 0x20
80            || (insn & 0xfc) == 0x28
81            || (insn & 0xf3) == 0x43
82            || (insn & 0xf3) == 0x42
83            || (insn & 0xfc) == 0x58
84            || (insn & 0xfc) == 0x5c
85            || ((insn & 0xf0) == 0xc0
86                && (insn & 0xff) != 0xcb
87                && (insn & 0xff) != 0xcc
88                && (insn & 0xff) != 0xcd)
89            || (insn & 0xff) == 0xf0
90            || (insn & 0xff) == 0xf1
91            || (insn & 0xff) == 0xf2
92            || (insn & 0xff) == 0xf3
93            || (insn & 0xff) == 0xf4
94            || (insn & 0xff) == 0xf5
95            || (insn & 0xff) == 0xf6)
96     {
97       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
98       if (status != 0)
99         {
100           (*info->memory_error_func) (status, memaddr, info);
101            return -1;
102         }
103       insn = bfd_getb16 (buffer);
104       consume = 2;
105     }
106
107   /* These are three byte insns.  */
108   else if ((insn & 0xff) == 0xf8
109            || (insn & 0xff) == 0xcc 
110            || (insn & 0xff) == 0xf9
111            || (insn & 0xf3) == 0x01
112            || (insn & 0xf3) == 0x02
113            || (insn & 0xf3) == 0x03
114            || (insn & 0xfc) == 0x24
115            || (insn & 0xfc) == 0x2c
116            || (insn & 0xfc) == 0x30
117            || (insn & 0xfc) == 0x34
118            || (insn & 0xfc) == 0x38
119            || (insn & 0xff) == 0xde
120            || (insn & 0xff) == 0xdf
121            || (insn & 0xff) == 0xcc)
122     {
123       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
124       if (status != 0)
125         {
126           (*info->memory_error_func) (status, memaddr, info);
127           return -1;
128         }
129       insn = bfd_getb16 (buffer);
130       insn <<= 8;
131       status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
132       if (status != 0)
133         {
134           (*info->memory_error_func) (status, memaddr, info);
135           return -1;
136         }
137       insn |= *(unsigned char *)buffer;
138       consume = 3;
139     }
140
141   /* These are four byte insns.  */
142   else if ((insn & 0xff) == 0xfa
143            || (insn & 0xff) == 0xfb)
144     {
145       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
146       if (status != 0)
147         {
148           (*info->memory_error_func) (status, memaddr, info);
149           return -1;
150         }
151       insn = bfd_getb32 (buffer);
152       consume = 4;
153     }
154
155   /* These are five byte insns.  */
156   else if ((insn & 0xff) == 0xcd
157            || (insn & 0xff) == 0xdc)
158     {
159       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
160       if (status != 0)
161         {
162           (*info->memory_error_func) (status, memaddr, info);
163           return -1;
164         }
165       insn = bfd_getb32 (buffer);
166       consume = 5;
167     }
168
169   /* These are six byte insns.  */
170   else if ((insn & 0xff) == 0xfd
171            || (insn & 0xff) == 0xfc)
172     {
173       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
174       if (status != 0)
175         {
176           (*info->memory_error_func) (status, memaddr, info);
177           return -1;
178         }
179
180       insn = bfd_getb32 (buffer);
181       consume = 6;
182     }
183
184   /* Else its a seven byte insns (in theory).  */
185   else
186     {
187       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
188       if (status != 0)
189         {
190           (*info->memory_error_func) (status, memaddr, info);
191           return -1;
192         }
193
194       insn = bfd_getb32 (buffer);
195       consume = 7;
196     }
197
198   disassemble (memaddr, info, insn, consume);
199
200   return consume;
201 }
202
203 static void
204 disassemble (memaddr, info, insn, size)
205      bfd_vma memaddr;
206      struct disassemble_info *info;
207      unsigned long insn;
208      unsigned int size;
209 {
210   struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
211   const struct mn10300_operand *operand;
212   bfd_byte buffer[4];
213   unsigned long extension = 0;
214   int status, match = 0;
215
216   /* Find the opcode.  */
217   while (op->name)
218     {
219       int mysize, extra_shift;
220
221       if (op->format == FMT_S0)
222         mysize = 1;
223       else if (op->format == FMT_S1
224                || op->format == FMT_D0)
225         mysize = 2;
226       else if (op->format == FMT_S2
227                || op->format == FMT_D1)
228         mysize = 3;
229       else if (op->format == FMT_S4)
230         mysize = 5;
231       else if (op->format == FMT_D2)
232         mysize = 4;
233       else if (op->format == FMT_D4)
234         mysize = 6;
235       else
236         mysize = 7;
237         
238       if ((op->mask & insn) == op->opcode
239           && size == mysize)
240         {
241           const unsigned char *opindex_ptr;
242           unsigned int nocomma;
243           int paren = 0;
244           
245           if (op->format == FMT_D1 || op->format == FMT_S1)
246             extra_shift = 8;
247           else if (op->format == FMT_D2 || op->format == FMT_D4
248                    || op->format == FMT_S2 || op->format == FMT_S4
249                    || op->format == FMT_S6 || op->format == FMT_D5)
250             extra_shift = 16;
251           else
252             extra_shift = 0;
253
254           if (size == 1 || size == 2)
255             {
256               extension = 0;
257             }
258           else if (size == 3
259                    && (op->format == FMT_D1
260                        || op->opcode == 0xdf0000
261                        || op->opcode == 0xde0000))
262             {
263               extension = 0;
264             }
265           else if (size == 3)
266             {
267               insn &= 0xff0000;
268               status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
269               if (status != 0)
270                 {
271                   (*info->memory_error_func) (status, memaddr, info);
272                   return;
273                 }
274
275               insn |= bfd_getl16 (buffer);
276               extension = 0;
277             }
278           else if (size == 4
279                    && (op->opcode == 0xfaf80000
280                        || op->opcode == 0xfaf00000
281                        || op->opcode == 0xfaf40000))
282             {
283               extension = 0;
284             }
285           else if (size == 4)
286             {
287               insn &= 0xffff0000;
288               status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
289               if (status != 0)
290                 {
291                   (*info->memory_error_func) (status, memaddr, info);
292                   return;
293                 }
294
295               insn |= bfd_getl16 (buffer);
296               extension = 0;
297             }
298           else if (size == 5 && op->opcode == 0xdc000000)
299             {
300               unsigned long temp = 0;
301               status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
302               if (status != 0)
303                 {
304                   (*info->memory_error_func) (status, memaddr, info);
305                   return;
306                 }
307               temp |= bfd_getl32 (buffer);
308
309               insn &= 0xff000000;
310               insn |= (temp & 0xffffff00) >> 8;
311               extension = temp & 0xff;
312             }
313           else if (size == 5)
314             {
315               unsigned long temp = 0;
316               status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
317               if (status != 0)
318                 {
319                   (*info->memory_error_func) (status, memaddr, info);
320                   return;
321                 }
322               temp |= bfd_getl16 (buffer);
323
324               insn &= 0xff0000ff;
325               insn |= temp << 8;
326
327               status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
328               if (status != 0)
329                 {
330                   (*info->memory_error_func) (status, memaddr, info);
331                   return;
332                 }
333               extension = *(unsigned char *)buffer;
334             }
335           else if (size == 6)
336             {
337               unsigned long temp = 0;
338               status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
339               if (status != 0)
340                 {
341                   (*info->memory_error_func) (status, memaddr, info);
342                   return;
343                 }
344               temp |= bfd_getl32 (buffer);
345
346               insn &= 0xffff0000;
347               insn |= (temp >> 16) & 0xffff;
348               extension = temp & 0xffff;
349             }
350           else if (size == 7 && op->opcode == 0xdd000000)
351             {
352               unsigned long temp = 0;
353               status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
354               if (status != 0)
355                 {
356                   (*info->memory_error_func) (status, memaddr, info);
357                   return;
358                 }
359               temp |= bfd_getl32 (buffer);
360
361               insn &= 0xff000000;
362               insn |= (temp >> 8) & 0xffffff;
363               extension = (temp & 0xff) << 16;
364               
365               status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
366               if (status != 0)
367                 {
368                   (*info->memory_error_func) (status, memaddr, info);
369                   return;
370                 }
371               extension |= bfd_getb16 (buffer);
372             }
373           else if (size == 7)
374             {
375               unsigned long temp = 0;
376               status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
377               if (status != 0)
378                 {
379                   (*info->memory_error_func) (status, memaddr, info);
380                   return;
381                 }
382               temp |= bfd_getl32 (buffer);
383
384               insn &= 0xffff0000;
385               insn |= (temp >> 16) & 0xffff;
386               extension = (temp & 0xffff) << 8;
387               
388               status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
389               if (status != 0)
390                 {
391                   (*info->memory_error_func) (status, memaddr, info);
392                   return;
393                 }
394               extension |= *(unsigned char *)buffer;
395             }
396
397           match = 1;
398           (*info->fprintf_func) (info->stream, "%s\t", op->name);
399
400           /* Now print the operands.  */
401           for (opindex_ptr = op->operands, nocomma = 1;
402                *opindex_ptr != 0;
403                opindex_ptr++)
404             {
405               unsigned long value;
406
407               operand = &mn10300_operands[*opindex_ptr];
408
409               if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
410                 {
411                   unsigned long temp;
412                   value = insn & ((1 << operand->bits) - 1);
413                   value <<= (32 - operand->bits);
414                   temp = extension >> operand->shift;
415                   temp &= ((1 << (32 - operand->bits)) - 1);
416                   value |= temp;
417                 }
418               else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
419                 {
420                   value = ((extension >> (operand->shift))
421                            & ((1 << operand->bits) - 1));
422                 }
423               else
424                 {
425                   value = ((insn >> (operand->shift))
426                            & ((1 << operand->bits) - 1));
427                 }
428
429               if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
430                 value = ((long)(value << (32 - operand->bits))
431                           >> (32 - operand->bits));
432
433               if (!nocomma
434                   && (!paren
435                       || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
436                 (*info->fprintf_func) (info->stream, ",");
437
438               nocomma = 0;
439                 
440               if ((operand->flags & MN10300_OPERAND_DREG) != 0)
441                 {
442                   value = ((insn >> (operand->shift + extra_shift))
443                            & ((1 << operand->bits) - 1));
444                   (*info->fprintf_func) (info->stream, "d%d", value);
445                 }
446
447               else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
448                 {
449                   value = ((insn >> (operand->shift + extra_shift))
450                            & ((1 << operand->bits) - 1));
451                   (*info->fprintf_func) (info->stream, "a%d", value);
452                 }
453
454               else if ((operand->flags & MN10300_OPERAND_SP) != 0)
455                 (*info->fprintf_func) (info->stream, "sp");
456
457               else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
458                 (*info->fprintf_func) (info->stream, "psw");
459
460               else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
461                 (*info->fprintf_func) (info->stream, "mdr");
462
463               else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
464                 {
465                   if (paren)
466                     (*info->fprintf_func) (info->stream, ")");
467                   else
468                     {
469                       (*info->fprintf_func) (info->stream, "(");
470                       nocomma = 1;
471                     }
472                   paren = !paren;
473                 }
474
475               else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
476                 (*info->print_address_func) (value + memaddr, info);
477
478               else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
479                 (*info->print_address_func) (value, info);
480
481               else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
482                 {
483                   int comma = 0;
484
485                   (*info->fprintf_func) (info->stream, "[");
486                   if (value & 0x80)
487                     {
488                       (*info->fprintf_func) (info->stream, "d2");
489                       comma = 1;
490                     }
491
492                   if (value & 0x40)
493                     {
494                       if (comma)
495                         (*info->fprintf_func) (info->stream, ",");
496                       (*info->fprintf_func) (info->stream, "d3");
497                       comma = 1;
498                     }
499
500                   if (value & 0x20)
501                     {
502                       if (comma)
503                         (*info->fprintf_func) (info->stream, ",");
504                       (*info->fprintf_func) (info->stream, "a2");
505                       comma = 1;
506                     }
507
508                   if (value & 0x10)
509                     {
510                       if (comma)
511                         (*info->fprintf_func) (info->stream, ",");
512                       (*info->fprintf_func) (info->stream, "a3");
513                       comma = 1;
514                     }
515
516                   if (value & 0x08)
517                     {
518                       if (comma)
519                         (*info->fprintf_func) (info->stream, ",");
520                       (*info->fprintf_func) (info->stream, "other");
521                       comma = 1;
522                     }
523                   (*info->fprintf_func) (info->stream, "]");
524                 }
525
526               else 
527                 (*info->fprintf_func) (info->stream, "%d", value);
528             }
529           /* All done. */
530           break;
531         }
532       op++;
533     }
534
535   if (!match)
536     {
537         (*info->fprintf_func) (info->stream, "unknown\t0x%04x", insn);
538     }
539 }
This page took 0.055801 seconds and 4 git commands to generate.