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