source: branches/libc-0.6/src/binutils/opcodes/h8300-dis.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 9.6 KB
Line 
1/* Disassemble h8300 instructions.
2 Copyright 1993, 1994, 1996, 1998, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19#define DEFINE_TABLE
20
21#include "sysdep.h"
22#define h8_opcodes h8ops
23#include "opcode/h8300.h"
24#include "dis-asm.h"
25#include "opintl.h"
26#include "libiberty.h"
27
28struct h8_instruction
29{
30 int length;
31 const struct h8_opcode *opcode;
32};
33
34struct h8_instruction *h8_instructions;
35
36static void bfd_h8_disassemble_init PARAMS ((void));
37static unsigned int bfd_h8_disassemble
38 PARAMS ((bfd_vma, disassemble_info *, int));
39
40/* Run through the opcodes and sort them into order to make them easy
41 to disassemble. */
42static void
43bfd_h8_disassemble_init ()
44{
45 unsigned int i;
46 unsigned int nopcodes;
47 const struct h8_opcode *p;
48 struct h8_instruction *pi;
49
50 nopcodes = sizeof (h8_opcodes) / sizeof (struct h8_opcode);
51
52 h8_instructions = (struct h8_instruction *)
53 xmalloc (nopcodes * sizeof (struct h8_instruction));
54
55 for (p = h8_opcodes, pi = h8_instructions; p->name; p++, pi++)
56 {
57 int n1 = 0;
58 int n2 = 0;
59
60 if ((int) p->data.nib[0] < 16)
61 n1 = (int) p->data.nib[0];
62 else
63 n1 = 0;
64
65 if ((int) p->data.nib[1] < 16)
66 n2 = (int) p->data.nib[1];
67 else
68 n2 = 0;
69
70 /* Just make sure there are an even number of nibbles in it, and
71 that the count is the same as the length. */
72 for (i = 0; p->data.nib[i] != E; i++)
73 ;
74
75 if (i & 1)
76 abort ();
77
78 pi->length = i / 2;
79 pi->opcode = p;
80 }
81
82 /* Add entry for the NULL vector terminator. */
83 pi->length = 0;
84 pi->opcode = p;
85}
86
87static unsigned int
88bfd_h8_disassemble (addr, info, mode)
89 bfd_vma addr;
90 disassemble_info *info;
91 int mode;
92{
93 /* Find the first entry in the table for this opcode. */
94 static const char *regnames[] =
95 {
96 "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h",
97 "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l"
98 };
99 static const char *wregnames[] =
100 {
101 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
102 "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7"
103 };
104 static const char *lregnames[] =
105 {
106 "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7",
107 "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7"
108 };
109 int rs = 0;
110 int rd = 0;
111 int rdisp = 0;
112 int abs = 0;
113 int bit = 0;
114 int plen = 0;
115 static bfd_boolean init = 0;
116 const struct h8_instruction *qi;
117 char const **pregnames = mode != 0 ? lregnames : wregnames;
118 int status;
119 int l;
120 unsigned char data[20];
121 void *stream = info->stream;
122 fprintf_ftype fprintf = info->fprintf_func;
123
124 if (!init)
125 {
126 bfd_h8_disassemble_init ();
127 init = 1;
128 }
129
130 status = info->read_memory_func (addr, data, 2, info);
131 if (status != 0)
132 {
133 info->memory_error_func (status, addr, info);
134 return -1;
135 }
136
137 for (l = 2; status == 0 && l < 10; l += 2)
138 status = info->read_memory_func (addr + l, data + l, 2, info);
139
140 /* Find the exact opcode/arg combo. */
141 for (qi = h8_instructions; qi->opcode->name; qi++)
142 {
143 const struct h8_opcode *q = qi->opcode;
144 op_type *nib = q->data.nib;
145 unsigned int len = 0;
146
147 while (1)
148 {
149 op_type looking_for = *nib;
150 int thisnib = data[len >> 1];
151
152 thisnib = (len & 1) ? (thisnib & 0xf) : ((thisnib >> 4) & 0xf);
153
154 if (looking_for < 16 && looking_for >= 0)
155 {
156 if (looking_for != thisnib)
157 goto fail;
158 }
159 else
160 {
161 if ((int) looking_for & (int) B31)
162 {
163 if (!(((int) thisnib & 0x8) != 0))
164 goto fail;
165
166 looking_for = (op_type) ((int) looking_for & ~(int) B31);
167 }
168
169 if ((int) looking_for & (int) B30)
170 {
171 if (!(((int) thisnib & 0x8) == 0))
172 goto fail;
173
174 looking_for = (op_type) ((int) looking_for & ~(int) B30);
175 }
176
177 if (looking_for & DBIT)
178 {
179 /* Exclude adds/subs by looking at bit 0 and 2, and
180 make sure the operand size, either w or l,
181 matches by looking at bit 1. */
182 if ((looking_for & 7) != (thisnib & 7))
183 goto fail;
184
185 abs = (thisnib & 0x8) ? 2 : 1;
186 }
187 else if (looking_for & (REG | IND | INC | DEC))
188 {
189 if (looking_for & SRC)
190 rs = thisnib;
191 else
192 rd = thisnib;
193 }
194 else if (looking_for & L_16)
195 {
196 abs = (data[len >> 1]) * 256 + data[(len + 2) >> 1];
197 plen = 16;
198 }
199 else if (looking_for & ABSJMP)
200 {
201 abs = (data[1] << 16) | (data[2] << 8) | (data[3]);
202 }
203 else if (looking_for & MEMIND)
204 {
205 abs = data[1];
206 }
207 else if (looking_for & L_32)
208 {
209 int i = len >> 1;
210
211 abs = (data[i] << 24)
212 | (data[i + 1] << 16)
213 | (data[i + 2] << 8)
214 | (data[i + 3]);
215
216 plen = 32;
217 }
218 else if (looking_for & L_24)
219 {
220 int i = len >> 1;
221
222 abs = (data[i] << 16) | (data[i + 1] << 8) | (data[i + 2]);
223 plen = 24;
224 }
225 else if (looking_for & IGNORE)
226 {
227 ;
228 }
229 else if (looking_for & DISPREG)
230 {
231 rdisp = thisnib;
232 }
233 else if (looking_for & KBIT)
234 {
235 switch (thisnib)
236 {
237 case 9:
238 abs = 4;
239 break;
240 case 8:
241 abs = 2;
242 break;
243 case 0:
244 abs = 1;
245 break;
246 default:
247 goto fail;
248 }
249 }
250 else if (looking_for & L_8)
251 {
252 plen = 8;
253 abs = data[len >> 1];
254 }
255 else if (looking_for & L_3)
256 {
257 bit = thisnib & 0x7;
258 }
259 else if (looking_for & L_2)
260 {
261 plen = 2;
262 abs = thisnib & 0x3;
263 }
264 else if (looking_for & MACREG)
265 {
266 abs = (thisnib == 3);
267 }
268 else if (looking_for == E)
269 {
270 int i;
271
272 for (i = 0; i < qi->length; i++)
273 fprintf (stream, "%02x ", data[i]);
274
275 for (; i < 6; i++)
276 fprintf (stream, " ");
277
278 fprintf (stream, "%s\t", q->name);
279
280 /* Gross. Disgusting. */
281 if (strcmp (q->name, "ldm.l") == 0)
282 {
283 int count, high;
284
285 count = (data[1] >> 4) & 0x3;
286 high = data[3] & 0x7;
287
288 fprintf (stream, "@sp+,er%d-er%d", high - count, high);
289 return qi->length;
290 }
291
292 if (strcmp (q->name, "stm.l") == 0)
293 {
294 int count, low;
295
296 count = (data[1] >> 4) & 0x3;
297 low = data[3] & 0x7;
298
299 fprintf (stream, "er%d-er%d,@-sp", low, low + count);
300 return qi->length;
301 }
302
303 /* Fill in the args. */
304 {
305 op_type *args = q->args.nib;
306 int hadone = 0;
307
308 while (*args != E)
309 {
310 int x = *args;
311
312 if (hadone)
313 fprintf (stream, ",");
314
315 if (x & L_3)
316 {
317 fprintf (stream, "#0x%x", (unsigned) bit);
318 }
319 else if (x & (IMM | KBIT | DBIT))
320 {
321 /* Bletch. For shal #2,er0 and friends. */
322 if (*(args + 1) & SRC_IN_DST)
323 abs = 2;
324
325 fprintf (stream, "#0x%x", (unsigned) abs);
326 }
327 else if (x & REG)
328 {
329 int rn = (x & DST) ? rd : rs;
330
331 switch (x & SIZE)
332 {
333 case L_8:
334 fprintf (stream, "%s", regnames[rn]);
335 break;
336 case L_16:
337 fprintf (stream, "%s", wregnames[rn]);
338 break;
339 case L_P:
340 case L_32:
341 fprintf (stream, "%s", lregnames[rn]);
342 break;
343 }
344 }
345 else if (x & MACREG)
346 {
347 fprintf (stream, "mac%c", abs ? 'l' : 'h');
348 }
349 else if (x & INC)
350 {
351 fprintf (stream, "@%s+", pregnames[rs]);
352 }
353 else if (x & DEC)
354 {
355 fprintf (stream, "@-%s", pregnames[rd]);
356 }
357 else if (x & IND)
358 {
359 int rn = (x & DST) ? rd : rs;
360 fprintf (stream, "@%s", pregnames[rn]);
361 }
362 else if (x & ABS8MEM)
363 {
364 fprintf (stream, "@0x%x:8", (unsigned) abs);
365 }
366 else if (x & (ABS | ABSJMP))
367 {
368 fprintf (stream, "@0x%x:%d", (unsigned) abs, plen);
369 }
370 else if (x & MEMIND)
371 {
372 fprintf (stream, "@@%d (%x)", abs, abs);
373 }
374 else if (x & PCREL)
375 {
376 if (x & L_16)
377 {
378 abs += 2;
379 fprintf (stream,
380 ".%s%d (%x)",
381 (short) abs > 0 ? "+" : "",
382 (short) abs, addr + (short) abs + 2);
383 }
384 else
385 {
386 fprintf (stream,
387 ".%s%d (%x)",
388 (char) abs > 0 ? "+" : "",
389 (char) abs, addr + (char) abs + 2);
390 }
391 }
392 else if (x & DISP)
393 {
394 fprintf (stream, "@(0x%x:%d,%s)",
395 abs, plen, pregnames[rdisp]);
396 }
397 else if (x & CCR)
398 {
399 fprintf (stream, "ccr");
400 }
401 else if (x & EXR)
402 {
403 fprintf (stream, "exr");
404 }
405 else
406 /* xgettext:c-format */
407 fprintf (stream, _("Hmmmm %x"), x);
408
409 hadone = 1;
410 args++;
411 }
412 }
413
414 return qi->length;
415 }
416 else
417 /* xgettext:c-format */
418 fprintf (stream, _("Don't understand %x \n"), looking_for);
419 }
420
421 len++;
422 nib++;
423 }
424
425 fail:
426 ;
427 }
428
429 /* Fell off the end. */
430 fprintf (stream, "%02x %02x .word\tH'%x,H'%x",
431 data[0], data[1],
432 data[0], data[1]);
433 return 2;
434}
435
436int
437print_insn_h8300 (addr, info)
438 bfd_vma addr;
439 disassemble_info *info;
440{
441 return bfd_h8_disassemble (addr, info, 0);
442}
443
444int
445print_insn_h8300h (addr, info)
446 bfd_vma addr;
447 disassemble_info *info;
448{
449 return bfd_h8_disassemble (addr, info, 1);
450}
451
452int
453print_insn_h8300s (addr, info)
454 bfd_vma addr;
455 disassemble_info *info;
456{
457 return bfd_h8_disassemble (addr, info, 2);
458}
Note: See TracBrowser for help on using the repository browser.