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