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