* cgen-asm.in (insert_normal): Use CGEN_BOOL_ATTR.
[platform/upstream/binutils.git] / opcodes / m10200-dis.c
1 /* Disassemble MN10200 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/mn10200.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 long,
28                                  unsigned int));
29
30 int 
31 print_insn_mn10200 (memaddr, info)
32      bfd_vma memaddr;
33      struct disassemble_info *info;
34 {
35   int status;
36   bfd_byte buffer[4];
37   unsigned long insn;
38   unsigned long extension = 0;
39   unsigned int consume;
40
41   /* First figure out how big the opcode is.  */
42   status = (*info->read_memory_func) (memaddr, buffer, 1, info);
43   if (status != 0)
44     {
45       (*info->memory_error_func) (status, memaddr, info);
46       return -1;
47     }
48   insn = *(unsigned char *) buffer;
49
50   /* These are one byte insns.  */
51   if ((insn & 0xf0) == 0x00
52       || (insn & 0xf0) == 0x10
53       || (insn & 0xf0) == 0x20
54       || (insn & 0xf0) == 0x30
55       || ((insn & 0xf0) == 0x80
56           && (insn & 0x0c) >> 2 != (insn & 0x03))
57       || (insn & 0xf0) == 0x90
58       || (insn & 0xf0) == 0xa0
59       || (insn & 0xf0) == 0xb0
60       || (insn & 0xff) == 0xeb
61       || (insn & 0xff) == 0xf6
62       || (insn & 0xff) == 0xfe
63       || (insn & 0xff) == 0xff)
64     {
65       extension = 0;
66       consume = 1;
67     }
68
69   /* These are two byte insns.  */
70   else if ((insn & 0xf0) == 0x40
71            || (insn & 0xf0) == 0x50
72            || (insn & 0xf0) == 0x60
73            || (insn & 0xf0) == 0x70
74            || (insn & 0xf0) == 0x80
75            || (insn & 0xfc) == 0xd0
76            || (insn & 0xfc) == 0xd4
77            || (insn & 0xfc) == 0xd8
78            || (insn & 0xfc) == 0xe0
79            || (insn & 0xfc) == 0xe4
80            || (insn & 0xff) == 0xe8
81            || (insn & 0xff) == 0xe9
82            || (insn & 0xff) == 0xea
83            || (insn & 0xff) == 0xf0
84            || (insn & 0xff) == 0xf1
85            || (insn & 0xff) == 0xf2
86            || (insn & 0xff) == 0xf3)
87     {
88       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
89       if (status != 0)
90         {
91           (*info->memory_error_func) (status, memaddr, info);
92            return -1;
93         }
94       insn = bfd_getb16 (buffer);
95       consume = 2;
96     }
97
98   /* These are three byte insns with a 16bit operand in little
99      endian form.  */
100   else if ((insn & 0xf0) == 0xc0
101            || (insn & 0xfc) == 0xdc
102            || (insn & 0xfc) == 0xec
103            || (insn & 0xff) == 0xf8
104            || (insn & 0xff) == 0xf9
105            || (insn & 0xff) == 0xfa
106            || (insn & 0xff) == 0xfb
107            || (insn & 0xff) == 0xfc
108            || (insn & 0xff) == 0xfd)
109     {
110       status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
111       if (status != 0)
112         {
113           (*info->memory_error_func) (status, memaddr, info);
114           return -1;
115         }
116       insn <<= 16;
117       insn |= bfd_getl16 (buffer);
118       extension = 0;
119       consume = 3;
120     }
121   /* These are three byte insns too, but we don't have to mess with
122      endianness stuff.  */
123   else if ((insn & 0xff) == 0xf5)
124     {
125       status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
126       if (status != 0)
127         {
128           (*info->memory_error_func) (status, memaddr, info);
129           return -1;
130         }
131       insn <<= 16;
132       insn |= bfd_getb16 (buffer);
133       extension = 0;
134       consume = 3;
135     }
136
137   /* These are four byte insns.  */
138   else if ((insn & 0xff) == 0xf7)
139     {
140       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
141       if (status != 0)
142         {
143           (*info->memory_error_func) (status, memaddr, info);
144           return -1;
145         }
146       insn = bfd_getb16 (buffer);
147       insn <<= 16;
148       status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
149       if (status != 0)
150         {
151           (*info->memory_error_func) (status, memaddr, info);
152           return -1;
153         }
154       insn |= bfd_getl16 (buffer);
155       extension = 0;
156       consume = 4;
157     }
158
159   /* These are five byte insns.  */
160   else if ((insn & 0xff) == 0xf4)
161     {
162       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
163       if (status != 0)
164         {
165           (*info->memory_error_func) (status, memaddr, info);
166           return -1;
167         }
168       insn = bfd_getb16 (buffer);
169       insn <<= 16;
170
171       status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
172       if (status != 0)
173         {
174           (*info->memory_error_func) (status, memaddr, info);
175           return -1;
176         }
177       insn |= *(unsigned char *)buffer << 8;
178
179       status = (*info->read_memory_func) (memaddr + 3, buffer, 1, info);
180       if (status != 0)
181         {
182           (*info->memory_error_func) (status, memaddr, info);
183           return -1;
184         }
185       insn |= *(unsigned char *)buffer;
186
187       status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
188       if (status != 0)
189         {
190           (*info->memory_error_func) (status, memaddr, info);
191           return -1;
192         }
193       extension = *(unsigned char *)buffer;
194       consume = 5;
195     }
196   else
197     {
198       (*info->fprintf_func) (info->stream, _("unknown\t0x%02x"), insn);
199       return 1;
200     }
201
202   disassemble (memaddr, info, insn, extension, consume);
203
204   return consume;
205 }
206
207 static void
208 disassemble (memaddr, info, insn, extension, size)
209      bfd_vma memaddr;
210      struct disassemble_info *info;
211      unsigned long insn;
212      unsigned long extension;
213      unsigned int size;
214 {
215   struct mn10200_opcode *op = (struct mn10200_opcode *)mn10200_opcodes;
216   const struct mn10200_operand *operand;
217   int match = 0;
218
219   /* Find the opcode.  */
220   while (op->name)
221     {
222       int mysize, extra_shift;
223
224       if (op->format == FMT_1)
225         mysize = 1;
226       else if (op->format == FMT_2
227                || op->format == FMT_4)
228         mysize = 2;
229       else if (op->format == FMT_3
230                || op->format == FMT_5)
231         mysize = 3;
232       else if (op->format == FMT_6)
233         mysize = 4;
234       else if (op->format == FMT_7)
235         mysize = 5;
236       else
237         abort ();
238         
239       if (op->format == FMT_2 || op->format == FMT_5)
240         extra_shift = 8;
241       else if (op->format == FMT_3
242                || op->format == FMT_6
243                || op->format == FMT_7)
244         extra_shift = 16;
245       else
246         extra_shift = 0;
247
248       if ((op->mask & insn) == op->opcode
249           && size == (unsigned int) mysize)
250         {
251           const unsigned char *opindex_ptr;
252           unsigned int nocomma;
253           int paren = 0;
254           
255           match = 1;
256           (*info->fprintf_func) (info->stream, "%s\t", op->name);
257
258           /* Now print the operands.  */
259           for (opindex_ptr = op->operands, nocomma = 1;
260                *opindex_ptr != 0;
261                opindex_ptr++)
262             {
263               unsigned long value;
264
265               operand = &mn10200_operands[*opindex_ptr];
266
267               if ((operand->flags & MN10200_OPERAND_EXTENDED) != 0)
268                 {
269                   value = (insn & 0xffff) << 8;
270                   value |= extension;
271                 }
272               else
273                 {
274                   value = ((insn >> (operand->shift))
275                            & ((1 << operand->bits) - 1));
276                 }
277
278               if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
279                 value = ((long)(value << (32 - operand->bits))
280                           >> (32 - operand->bits));
281
282               if (!nocomma
283                   && (!paren
284                       || ((operand->flags & MN10200_OPERAND_PAREN) == 0)))
285                 (*info->fprintf_func) (info->stream, ",");
286
287               nocomma = 0;
288                 
289               if ((operand->flags & MN10200_OPERAND_DREG) != 0)
290                 {
291                   value = ((insn >> (operand->shift + extra_shift))
292                            & ((1 << operand->bits) - 1));
293                   (*info->fprintf_func) (info->stream, "d%d", value);
294                 }
295
296               else if ((operand->flags & MN10200_OPERAND_AREG) != 0)
297                 {
298                   value = ((insn >> (operand->shift + extra_shift))
299                            & ((1 << operand->bits) - 1));
300                   (*info->fprintf_func) (info->stream, "a%d", value);
301                 }
302
303               else if ((operand->flags & MN10200_OPERAND_PSW) != 0)
304                 (*info->fprintf_func) (info->stream, "psw");
305
306               else if ((operand->flags & MN10200_OPERAND_MDR) != 0)
307                 (*info->fprintf_func) (info->stream, "mdr");
308
309               else if ((operand->flags & MN10200_OPERAND_PAREN) != 0)
310                 {
311                   if (paren)
312                     (*info->fprintf_func) (info->stream, ")");
313                   else
314                     {
315                       (*info->fprintf_func) (info->stream, "(");
316                       nocomma = 1;
317                     }
318                   paren = !paren;
319                 }
320
321               else if ((operand->flags & MN10200_OPERAND_PCREL) != 0)
322                 (*info->print_address_func) ((value + memaddr + mysize) & 0xffffff, info);
323
324               else if ((operand->flags & MN10200_OPERAND_MEMADDR) != 0)
325                 (*info->print_address_func) (value, info);
326
327               else 
328                 (*info->fprintf_func) (info->stream, "%d", value);
329             }
330           /* All done. */
331           break;
332         }
333       op++;
334     }
335
336   if (!match)
337     {
338         (*info->fprintf_func) (info->stream, _("unknown\t0x%04x"), insn);
339     }
340 }