ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/disass/m68k-dis.c
Revision: 1.6
Committed: 2004-06-14T14:37:09Z (19 years, 11 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
CVS Tags: release_3-2, HEAD
Changes since 1.5: +9 -5 lines
Log Message:
Even more m68k disassembler fixes.

File Contents

# Content
1 /* Print Motorola 68k instructions.
2 Copyright 1986, 87, 89, 91, 92, 93, 94, 95, 96, 97, 1998
3 Free Software Foundation, Inc.
4
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19 #include <stdlib.h>
20 #include "dis-asm.h"
21 #include "floatformat.h"
22 #include "opintl.h"
23
24 #include "m68k.h"
25
26 /* Local function prototypes */
27
28 static int
29 fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
30
31 static void
32 dummy_print_address PARAMS ((bfd_vma, struct disassemble_info *));
33
34 static int
35 fetch_arg PARAMS ((unsigned char *, int, int, disassemble_info *));
36
37 static void
38 print_base PARAMS ((int, bfd_vma, disassemble_info*));
39
40 static unsigned char *
41 print_indexed PARAMS ((int, unsigned char *, bfd_vma, disassemble_info *));
42
43 static int
44 print_insn_arg PARAMS ((const char *, unsigned char *, unsigned char *,
45 bfd_vma, disassemble_info *));
46
47 CONST char * CONST fpcr_names[] = {
48 "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
49 "fpiar/fpcr", "fpsr/fpcr", "fpiar/fpsr/fpcr"};
50
51 static char *const reg_names[] = {
52 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
53 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
54 "sr", "pc"};
55
56 /* Sign-extend an (unsigned char). */
57 #if __STDC__ == 1
58 #define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
59 #else
60 #define COERCE_SIGNED_CHAR(ch) ((int)(((ch) ^ 0x80) & 0xFF) - 128)
61 #endif
62
63 /* Get a 1 byte signed integer. */
64 #define NEXTBYTE(p) (p += 2, FETCH_DATA (info, p), COERCE_SIGNED_CHAR(p[-1]))
65
66 /* Get a 2 byte signed integer. */
67 #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
68 #define NEXTWORD(p) \
69 (p += 2, FETCH_DATA (info, p), \
70 COERCE16 ((p[-2] << 8) + p[-1]))
71
72 /* Get a 4 byte signed integer. */
73 #define COERCE32(x) ((bfd_signed_vma) ((x) ^ 0x80000000) - 0x80000000)
74 #define NEXTLONG(p) \
75 (p += 4, FETCH_DATA (info, p), \
76 (COERCE32 ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])))
77
78 /* Get a 4 byte unsigned integer. */
79 #define NEXTULONG(p) \
80 (p += 4, FETCH_DATA (info, p), \
81 (unsigned int) ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]))
82
83 /* Get a single precision float. */
84 #define NEXTSINGLE(val, p) \
85 (p += 4, FETCH_DATA (info, p), \
86 floatformat_to_double (&floatformat_ieee_single_big, (char *) p - 4, &val))
87
88 /* Get a double precision float. */
89 #define NEXTDOUBLE(val, p) \
90 (p += 8, FETCH_DATA (info, p), \
91 floatformat_to_double (&floatformat_ieee_double_big, (char *) p - 8, &val))
92
93 /* Get an extended precision float. */
94 #define NEXTEXTEND(val, p) \
95 (p += 12, FETCH_DATA (info, p), \
96 floatformat_to_double (&floatformat_m68881_ext, (char *) p - 12, &val))
97
98 /* Need a function to convert from packed to double
99 precision. Actually, it's easier to print a
100 packed number than a double anyway, so maybe
101 there should be a special case to handle this... */
102 #define NEXTPACKED(p) \
103 (p += 12, FETCH_DATA (info, p), 0.0)
104
105
106 /* Maximum length of an instruction. */
107 #define MAXLEN 22
108
109 #include <setjmp.h>
110
111 struct private
112 {
113 /* Points to first byte not fetched. */
114 bfd_byte *max_fetched;
115 bfd_byte the_buffer[MAXLEN];
116 bfd_vma insn_start;
117 jmp_buf bailout;
118 };
119
120 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
121 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
122 on error. */
123 #define FETCH_DATA(info, addr) \
124 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
125 ? 1 : fetch_data ((info), (addr)))
126
127 static int
128 fetch_data (info, addr)
129 struct disassemble_info *info;
130 bfd_byte *addr;
131 {
132 int status;
133 struct private *priv = (struct private *)info->private_data;
134 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
135
136 status = (*info->read_memory_func) (start,
137 priv->max_fetched,
138 addr - priv->max_fetched,
139 info);
140 if (status != 0)
141 {
142 (*info->memory_error_func) (status, start, info);
143 longjmp (priv->bailout, 1);
144 }
145 else
146 priv->max_fetched = addr;
147 return 1;
148 }
149
150 /* This function is used to print to the bit-bucket. */
151 static int
152 #ifdef __STDC__
153 dummy_printer (FILE * file, const char * format, ...)
154 #else
155 dummy_printer (file) FILE *file;
156 #endif
157 { return 0; }
158
159 static void
160 dummy_print_address (vma, info)
161 bfd_vma vma;
162 struct disassemble_info *info;
163 {
164 }
165
166 /* Print the m68k instruction at address MEMADDR in debugged memory,
167 on INFO->STREAM. Returns length of the instruction, in bytes. */
168
169 int
170 print_insn_m68k (memaddr, info)
171 bfd_vma memaddr;
172 disassemble_info *info;
173 {
174 register int i;
175 register unsigned char *p;
176 unsigned char *save_p;
177 register const char *d;
178 register unsigned long bestmask;
179 const struct m68k_opcode *best = 0;
180 unsigned int arch_mask;
181 struct private priv;
182 bfd_byte *buffer = priv.the_buffer;
183 fprintf_ftype save_printer = info->fprintf_func;
184 void (*save_print_address) PARAMS((bfd_vma, struct disassemble_info*))
185 = info->print_address_func;
186 int major_opcode;
187 static int numopcodes[16];
188 static const struct m68k_opcode **opcodes[16];
189
190 if (!opcodes[0])
191 {
192 /* Speed up the matching by sorting the opcode table on the upper
193 four bits of the opcode. */
194 const struct m68k_opcode **opc_pointer[16];
195
196 /* First count how many opcodes are in each of the sixteen buckets. */
197 for (i = 0; i < m68k_numopcodes; i++)
198 numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++;
199
200 /* Then create a sorted table of pointers that point into the
201 unsorted table. */
202 opc_pointer[0] = ((const struct m68k_opcode **)
203 malloc (sizeof (struct m68k_opcode *)
204 * m68k_numopcodes));
205 opcodes[0] = opc_pointer[0];
206 for (i = 1; i < 16; i++)
207 {
208 opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1];
209 opcodes[i] = opc_pointer[i];
210 }
211
212 for (i = 0; i < m68k_numopcodes; i++)
213 *opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
214
215 }
216
217 info->private_data = (PTR) &priv;
218 /* Tell objdump to use two bytes per chunk and six bytes per line for
219 displaying raw data. */
220 info->bytes_per_chunk = 2;
221 info->bytes_per_line = 6;
222 info->display_endian = BFD_ENDIAN_BIG;
223 priv.max_fetched = priv.the_buffer;
224 priv.insn_start = memaddr;
225 if (setjmp (priv.bailout) != 0)
226 /* Error return. */
227 return -1;
228
229 switch (info->mach)
230 {
231 default:
232 case 0:
233 arch_mask = (unsigned int) -1;
234 break;
235 case bfd_mach_m68000:
236 arch_mask = m68000;
237 break;
238 case bfd_mach_m68008:
239 arch_mask = m68008;
240 break;
241 case bfd_mach_m68010:
242 arch_mask = m68010;
243 break;
244 case bfd_mach_m68020:
245 arch_mask = m68020;
246 break;
247 case bfd_mach_m68030:
248 arch_mask = m68030;
249 break;
250 case bfd_mach_m68040:
251 arch_mask = m68040;
252 break;
253 case bfd_mach_m68060:
254 arch_mask = m68060;
255 break;
256 }
257
258 arch_mask |= m68881 | m68851;
259
260 bestmask = 0;
261 FETCH_DATA (info, buffer + 2);
262 major_opcode = (buffer[0] >> 4) & 15;
263 for (i = 0; i < numopcodes[major_opcode]; i++)
264 {
265 const struct m68k_opcode *opc = opcodes[major_opcode][i];
266 unsigned long opcode = opc->opcode;
267 unsigned long match = opc->match;
268
269 if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
270 && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
271 /* Only fetch the next two bytes if we need to. */
272 && (((0xffff & match) == 0)
273 ||
274 (FETCH_DATA (info, buffer + 4)
275 && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
276 && ((0xff & buffer[3] & match) == (0xff & opcode)))
277 )
278 && (opc->arch & arch_mask) != 0)
279 {
280 /* Don't use for printout the variants of divul and divsl
281 that have the same register number in two places.
282 The more general variants will match instead. */
283 for (d = opc->args; *d; d += 2)
284 if (d[1] == 'D')
285 break;
286
287 /* Don't use for printout the variants of most floating
288 point coprocessor instructions which use the same
289 register number in two places, as above. */
290 if (*d == '\0')
291 for (d = opc->args; *d; d += 2)
292 if (d[1] == 't')
293 break;
294
295 /* Don't match fmovel with more than one register; wait for
296 fmoveml. */
297 if (*d == '\0')
298 {
299 for (d = opc->args; *d; d += 2)
300 {
301 if (d[0] == 's' && d[1] == '8')
302 {
303 int val;
304
305 val = fetch_arg (buffer, d[1], 3, info);
306 if ((val & (val - 1)) != 0)
307 break;
308 }
309 }
310 }
311
312 if (*d == '\0' && match > bestmask)
313 {
314 best = opc;
315 bestmask = match;
316 }
317 }
318 }
319
320 if (best == 0)
321 goto invalid;
322
323 /* Point at first word of argument data,
324 and at descriptor for first argument. */
325 p = buffer + 2;
326
327 /* Figure out how long the fixed-size portion of the instruction is.
328 The only place this is stored in the opcode table is
329 in the arguments--look for arguments which specify fields in the 2nd
330 or 3rd words of the instruction. */
331 for (d = best->args; *d; d += 2)
332 {
333 /* I don't think it is necessary to be checking d[0] here; I suspect
334 all this could be moved to the case statement below. */
335 if (d[0] == '#')
336 {
337 if (d[1] == 'l' && p - buffer < 6)
338 p = buffer + 6;
339 else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
340 p = buffer + 4;
341 }
342 if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
343 p = buffer + 4;
344 switch (d[1])
345 {
346 case '1':
347 case '2':
348 case '3':
349 case '7':
350 case '8':
351 case '9':
352 case 'i':
353 if (p - buffer < 4)
354 p = buffer + 4;
355 break;
356 case '4':
357 case '5':
358 case '6':
359 if (p - buffer < 6)
360 p = buffer + 6;
361 break;
362 default:
363 break;
364 }
365 }
366
367 /* pflusha is an exceptions. It takes no arguments but is two words
368 long. Recognize it by looking at the lower 16 bits of the mask. */
369 if (p - buffer < 4 && (best->match & 0xFFFF) != 0)
370 p = buffer + 4;
371
372 /* lpstop is another exception. It takes a one word argument but is
373 three words long. */
374 if (p - buffer < 6
375 && (best->match & 0xffff) == 0xffff
376 && best->args[0] == '#'
377 && best->args[1] == 'w')
378 {
379 /* Copy the one word argument into the usual location for a one
380 word argument, to simplify printing it. We can get away with
381 this because we know exactly what the second word is, and we
382 aren't going to print anything based on it. */
383 p = buffer + 6;
384 FETCH_DATA (info, p);
385 buffer[2] = buffer[4];
386 buffer[3] = buffer[5];
387 }
388
389 FETCH_DATA (info, p);
390
391 d = best->args;
392
393 /* We can the operands twice. The first time we don't print anything,
394 but look for errors. */
395
396 save_p = p;
397 info->print_address_func = dummy_print_address;
398 info->fprintf_func = (fprintf_ftype)dummy_printer;
399 for ( ; *d; d += 2)
400 {
401 int eaten = print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
402 if (eaten >= 0)
403 p += eaten;
404 else if (eaten == -1)
405 goto invalid;
406 else
407 {
408 (*info->fprintf_func)(info->stream,
409 /* xgettext:c-format */
410 _("<internal error in opcode table: %s %s>\n"),
411 best->name,
412 best->args);
413 goto invalid;
414 }
415
416 }
417 p = save_p;
418 info->fprintf_func = save_printer;
419 info->print_address_func = save_print_address;
420
421 d = best->args;
422
423 (*info->fprintf_func) (info->stream, "%s", best->name);
424
425 if (*d)
426 (*info->fprintf_func) (info->stream, "\t");
427
428 while (*d)
429 {
430 p += print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
431 d += 2;
432 if (*d && *(d - 2) != 'I' && *d != 'k')
433 (*info->fprintf_func) (info->stream, ",");
434 }
435 return p - buffer;
436
437 invalid: {
438 extern void print_68k_invalid_opcode(unsigned long, struct disassemble_info *);
439
440 /* Handle undefined instructions. */
441 info->fprintf_func = save_printer;
442 info->print_address_func = save_print_address;
443 print_68k_invalid_opcode((buffer[0] << 8) | buffer[1], info);
444 return 2;
445 }
446 }
447
448 /* Returns number of bytes "eaten" by the operand, or
449 return -1 if an invalid operand was found, or -2 if
450 an opcode tabe error was found. */
451
452 static int
453 print_insn_arg (d, buffer, p0, addr, info)
454 const char *d;
455 unsigned char *buffer;
456 unsigned char *p0;
457 bfd_vma addr; /* PC for this arg to be relative to */
458 disassemble_info *info;
459 {
460 register int val = 0;
461 register int place = d[1];
462 register unsigned char *p = p0;
463 int regno;
464 register CONST char *regname;
465 register unsigned char *p1;
466 double flval;
467 int flt_p;
468 bfd_signed_vma disp;
469 unsigned int uval;
470
471 switch (*d)
472 {
473 case 'c': /* cache identifier */
474 {
475 static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" };
476 val = fetch_arg (buffer, place, 2, info);
477 (*info->fprintf_func) (info->stream, cacheFieldName[val]);
478 break;
479 }
480
481 case 'a': /* address register indirect only. Cf. case '+'. */
482 {
483 (*info->fprintf_func)
484 (info->stream,
485 "(%s)",
486 reg_names [fetch_arg (buffer, place, 3, info) + 8]);
487 break;
488 }
489
490 case '_': /* 32-bit absolute address for move16. */
491 {
492 uval = NEXTULONG (p);
493 (*info->print_address_func) (uval, info);
494 break;
495 }
496
497 case 'C':
498 (*info->fprintf_func) (info->stream, "ccr");
499 break;
500
501 case 'S':
502 (*info->fprintf_func) (info->stream, "sr");
503 break;
504
505 case 'U':
506 (*info->fprintf_func) (info->stream, "usp");
507 break;
508
509 case 'J':
510 {
511 static const struct { char *name; int value; } names[]
512 = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
513 {"tc", 0x003}, {"itt0",0x004}, {"itt1", 0x005},
514 {"dtt0",0x006}, {"dtt1",0x007}, {"buscr",0x008},
515 {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
516 {"msp", 0x803}, {"isp", 0x804},
517
518 /* Should we be calling this psr like we do in case 'Y'? */
519 {"mmusr",0x805},
520
521 {"urp", 0x806}, {"srp", 0x807}, {"pcr", 0x808}};
522
523 val = fetch_arg (buffer, place, 12, info);
524 for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
525 if (names[regno].value == val)
526 {
527 (*info->fprintf_func) (info->stream, "%s", names[regno].name);
528 break;
529 }
530 if (regno < 0)
531 (*info->fprintf_func) (info->stream, "$%04x", val);
532 }
533 break;
534
535 case 'Q':
536 val = fetch_arg (buffer, place, 3, info);
537 /* 0 means 8, except for the bkpt instruction... */
538 if (val == 0 && d[1] != 's')
539 val = 8;
540 (*info->fprintf_func) (info->stream, "#%d", val);
541 break;
542
543 case 'M':
544 val = fetch_arg (buffer, place, 8, info);
545 if (val & 0x80)
546 val = val - 0x100;
547 (*info->fprintf_func) (info->stream, "#$%02x", val);
548 break;
549
550 case 'T':
551 val = fetch_arg (buffer, place, 4, info);
552 (*info->fprintf_func) (info->stream, "#$%08x", val);
553 break;
554
555 case 'D':
556 (*info->fprintf_func) (info->stream, "%s",
557 reg_names[fetch_arg (buffer, place, 3, info)]);
558 break;
559
560 case 'A':
561 (*info->fprintf_func)
562 (info->stream, "%s",
563 reg_names[fetch_arg (buffer, place, 3, info) + 010]);
564 break;
565
566 case 'R':
567 (*info->fprintf_func)
568 (info->stream, "%s",
569 reg_names[fetch_arg (buffer, place, 4, info)]);
570 break;
571
572 case 'r':
573 regno = fetch_arg (buffer, place, 4, info);
574 (*info->fprintf_func) (info->stream, "(%s)", reg_names[regno]);
575 break;
576
577 case 'F':
578 (*info->fprintf_func)
579 (info->stream, "fp%d",
580 fetch_arg (buffer, place, 3, info));
581 break;
582
583 case 'O':
584 val = fetch_arg (buffer, place, 6, info);
585 if (val & 0x20)
586 (*info->fprintf_func) (info->stream, "%s", reg_names [val & 7]);
587 else
588 (*info->fprintf_func) (info->stream, "%d", val);
589 break;
590
591 case '+':
592 (*info->fprintf_func)
593 (info->stream, "(%s)+",
594 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
595 break;
596
597 case '-':
598 (*info->fprintf_func)
599 (info->stream, "-(%s)",
600 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
601 break;
602
603 case 'k':
604 if (place == 'k')
605 (*info->fprintf_func)
606 (info->stream, "{%s}",
607 reg_names[fetch_arg (buffer, place, 3, info)]);
608 else if (place == 'C')
609 {
610 val = fetch_arg (buffer, place, 7, info);
611 if ( val > 63 ) /* This is a signed constant. */
612 val -= 128;
613 (*info->fprintf_func) (info->stream, "{#%d}", val);
614 }
615 else
616 return -2;
617 break;
618
619 case '#':
620 case '^':
621 p1 = buffer + (*d == '#' ? 2 : 4);
622 if (place == 's')
623 val = fetch_arg (buffer, place, 4, info);
624 else if (place == 'C')
625 val = fetch_arg (buffer, place, 7, info);
626 else if (place == '8')
627 val = fetch_arg (buffer, place, 3, info);
628 else if (place == '3')
629 val = fetch_arg (buffer, place, 8, info);
630 else if (place == 'b') {
631 val = NEXTBYTE (p1);
632 (*info->fprintf_func) (info->stream, "#$%02x", val & 0xff);
633 break;
634 }
635 else if (place == 'w' || place == 'W') {
636 val = NEXTWORD (p1);
637 (*info->fprintf_func) (info->stream, "#$%04x", val & 0xffff);
638 break;
639 }
640 else if (place == 'l') {
641 val = NEXTLONG (p1);
642 (*info->fprintf_func) (info->stream, "#$%08x", val);
643 break;
644 }
645 else
646 return -2;
647 (*info->fprintf_func) (info->stream, "#%d", val);
648 break;
649
650 case 'B':
651 if (place == 'b')
652 disp = NEXTBYTE (p);
653 else if (place == 'B')
654 disp = COERCE_SIGNED_CHAR(buffer[1]);
655 else if (place == 'w' || place == 'W')
656 disp = NEXTWORD (p);
657 else if (place == 'l' || place == 'L' || place == 'C')
658 disp = NEXTLONG (p);
659 else if (place == 'g')
660 {
661 disp = NEXTBYTE (buffer);
662 if (disp == 0)
663 disp = NEXTWORD (p);
664 else if (disp == -1)
665 disp = NEXTLONG (p);
666 }
667 else if (place == 'c')
668 {
669 if (buffer[1] & 0x40) /* If bit six is one, long offset */
670 disp = NEXTLONG (p);
671 else
672 disp = NEXTWORD (p);
673 }
674 else
675 return -2;
676
677 (*info->print_address_func) (addr + disp, info);
678 break;
679
680 case 'd':
681 val = NEXTWORD (p);
682 (*info->fprintf_func)
683 (info->stream, "($%04x,%s)",
684 val, reg_names[fetch_arg (buffer, place, 3, info) + 8]);
685 break;
686
687 case 's':
688 (*info->fprintf_func) (info->stream, "%s",
689 fpcr_names[fetch_arg (buffer, place, 3, info)]);
690 break;
691
692 case 'I':
693 /* Get coprocessor ID... */
694 val = fetch_arg (buffer, 'd', 3, info);
695
696 if (val != 1) /* Unusual coprocessor ID? */
697 (*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
698 break;
699
700 case '*':
701 case '~':
702 case '%':
703 case ';':
704 case '@':
705 case '!':
706 case '$':
707 case '?':
708 case '/':
709 case '&':
710 case '|':
711 case '<':
712 case '>':
713 case 'm':
714 case 'n':
715 case 'o':
716 case 'p':
717 case 'q':
718 case 'v':
719
720 if (place == 'd')
721 {
722 val = fetch_arg (buffer, 'x', 6, info);
723 val = ((val & 7) << 3) + ((val >> 3) & 7);
724 }
725 else
726 val = fetch_arg (buffer, 's', 6, info);
727
728 /* Get register number assuming address register. */
729 regno = (val & 7) + 8;
730 regname = reg_names[regno];
731 switch (val >> 3)
732 {
733 case 0:
734 (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
735 break;
736
737 case 1:
738 (*info->fprintf_func) (info->stream, "%s", regname);
739 break;
740
741 case 2:
742 (*info->fprintf_func) (info->stream, "(%s)", regname);
743 break;
744
745 case 3:
746 (*info->fprintf_func) (info->stream, "(%s)+", regname);
747 break;
748
749 case 4:
750 (*info->fprintf_func) (info->stream, "-(%s)", regname);
751 break;
752
753 case 5:
754 val = NEXTWORD (p);
755 (*info->fprintf_func) (info->stream, "($%04x,%s)", val, regname);
756 break;
757
758 case 6:
759 p = print_indexed (regno, p, addr, info);
760 break;
761
762 case 7:
763 switch (val & 7)
764 {
765 case 0:
766 val = NEXTWORD (p);
767 (*info->print_address_func) (val, info);
768 break;
769
770 case 1:
771 uval = NEXTULONG (p);
772 (*info->print_address_func) (uval, info);
773 break;
774
775 case 2:
776 val = NEXTWORD (p);
777 (*info->fprintf_func) (info->stream, "(");
778 (*info->print_address_func) (addr + val, info);
779 (*info->fprintf_func) (info->stream, ",pc)");
780 break;
781
782 case 3:
783 p = print_indexed (-1, p, addr, info);
784 break;
785
786 case 4:
787 switch( place )
788 {
789 case 'b':
790 val = NEXTBYTE (p);
791 (*info->fprintf_func) (info->stream, "#$%02x", val & 0xff);
792 goto imm_printed;
793
794 case 'w':
795 val = NEXTWORD (p);
796 (*info->fprintf_func) (info->stream, "#$%04x", val & 0xffff);
797 goto imm_printed;
798
799 case 'l':
800 val = NEXTLONG (p);
801 (*info->fprintf_func) (info->stream, "#$%08x", val);
802 goto imm_printed;
803
804 case 'f':
805 NEXTSINGLE(flval, p);
806 break;
807
808 case 'F':
809 NEXTDOUBLE(flval, p);
810 break;
811
812 case 'x':
813 NEXTEXTEND(flval, p);
814 break;
815
816 case 'p':
817 flval = NEXTPACKED(p);
818 break;
819
820 default:
821 return -1;
822 }
823 (*info->fprintf_func) (info->stream, "#%g", flval);
824 imm_printed:
825 break;
826
827 default:
828 return -1;
829 }
830 }
831 break;
832
833 case 'L':
834 case 'l':
835 if (place == 'w')
836 {
837 char doneany;
838 p1 = buffer + 2;
839 val = NEXTWORD (p1);
840 /* Move the pointer ahead if this point is farther ahead
841 than the last. */
842 p = p1 > p ? p1 : p;
843 if (val == 0)
844 {
845 (*info->fprintf_func) (info->stream, "#0");
846 break;
847 }
848 if (*d == 'l')
849 {
850 register int newval = 0;
851 for (regno = 0; regno < 16; ++regno)
852 if (val & (0x8000 >> regno))
853 newval |= 1 << regno;
854 val = newval;
855 }
856 val &= 0xffff;
857 doneany = 0;
858 for (regno = 0; regno < 16; ++regno)
859 if (val & (1 << regno))
860 {
861 int first_regno;
862 if (doneany)
863 (*info->fprintf_func) (info->stream, "/");
864 doneany = 1;
865 (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
866 first_regno = regno;
867 while (val & (1 << (regno + 1)))
868 ++regno;
869 if (regno > first_regno)
870 (*info->fprintf_func) (info->stream, "-%s",
871 reg_names[regno]);
872 }
873 }
874 else if (place == '3')
875 {
876 /* `fmovem' insn. */
877 char doneany;
878 val = fetch_arg (buffer, place, 8, info);
879 if (val == 0)
880 {
881 (*info->fprintf_func) (info->stream, "#0");
882 break;
883 }
884 if (*d == 'l')
885 {
886 register int newval = 0;
887 for (regno = 0; regno < 8; ++regno)
888 if (val & (0x80 >> regno))
889 newval |= 1 << regno;
890 val = newval;
891 }
892 val &= 0xff;
893 doneany = 0;
894 for (regno = 0; regno < 8; ++regno)
895 if (val & (1 << regno))
896 {
897 int first_regno;
898 if (doneany)
899 (*info->fprintf_func) (info->stream, "/");
900 doneany = 1;
901 (*info->fprintf_func) (info->stream, "fp%d", regno);
902 first_regno = regno;
903 while (val & (1 << (regno + 1)))
904 ++regno;
905 if (regno > first_regno)
906 (*info->fprintf_func) (info->stream, "-fp%d", regno);
907 }
908 }
909 else if (place == '8')
910 {
911 /* fmoveml for FP status registers */
912 (*info->fprintf_func) (info->stream, "%s",
913 fpcr_names[fetch_arg (buffer, place, 3,
914 info)]);
915 }
916 else
917 return -2;
918 break;
919
920 case 'X':
921 place = '8';
922 case 'Y':
923 case 'Z':
924 case 'W':
925 case '0':
926 case '1':
927 case '2':
928 case '3':
929 {
930 int val = fetch_arg (buffer, place, 5, info);
931 char *name = 0;
932 switch (val)
933 {
934 case 2: name = "tt0"; break;
935 case 3: name = "tt1"; break;
936 case 0x10: name = "tc"; break;
937 case 0x11: name = "drp"; break;
938 case 0x12: name = "srp"; break;
939 case 0x13: name = "crp"; break;
940 case 0x14: name = "cal"; break;
941 case 0x15: name = "val"; break;
942 case 0x16: name = "scc"; break;
943 case 0x17: name = "ac"; break;
944 case 0x18: name = "psr"; break;
945 case 0x19: name = "pcsr"; break;
946 case 0x1c:
947 case 0x1d:
948 {
949 int break_reg = ((buffer[3] >> 2) & 7);
950 (*info->fprintf_func)
951 (info->stream, val == 0x1c ? "bad%d" : "bac%d",
952 break_reg);
953 }
954 break;
955 default:
956 (*info->fprintf_func) (info->stream, "<mmu register %d>", val);
957 }
958 if (name)
959 (*info->fprintf_func) (info->stream, "%s", name);
960 }
961 break;
962
963 case 'f':
964 {
965 int fc = fetch_arg (buffer, place, 5, info);
966 if (fc == 1)
967 (*info->fprintf_func) (info->stream, "dfc");
968 else if (fc == 0)
969 (*info->fprintf_func) (info->stream, "sfc");
970 else
971 /* xgettext:c-format */
972 (*info->fprintf_func) (info->stream, _("<function code %d>"), fc);
973 }
974 break;
975
976 case 'V':
977 (*info->fprintf_func) (info->stream, "val");
978 break;
979
980 case 't':
981 {
982 int level = fetch_arg (buffer, place, 3, info);
983 (*info->fprintf_func) (info->stream, "%d", level);
984 }
985 break;
986
987 default:
988 return -2;
989 }
990
991 return p - p0;
992 }
993
994 /* Fetch BITS bits from a position in the instruction specified by CODE.
995 CODE is a "place to put an argument", or 'x' for a destination
996 that is a general address (mode and register).
997 BUFFER contains the instruction. */
998
999 static int
1000 fetch_arg (buffer, code, bits, info)
1001 unsigned char *buffer;
1002 int code;
1003 int bits;
1004 disassemble_info *info;
1005 {
1006 register int val = 0;
1007 switch (code)
1008 {
1009 case 's':
1010 val = buffer[1];
1011 break;
1012
1013 case 'd': /* Destination, for register or quick. */
1014 val = (buffer[0] << 8) + buffer[1];
1015 val >>= 9;
1016 break;
1017
1018 case 'x': /* Destination, for general arg */
1019 val = (buffer[0] << 8) + buffer[1];
1020 val >>= 6;
1021 break;
1022
1023 case 'k':
1024 FETCH_DATA (info, buffer + 3);
1025 val = (buffer[3] >> 4);
1026 break;
1027
1028 case 'C':
1029 FETCH_DATA (info, buffer + 3);
1030 val = buffer[3];
1031 break;
1032
1033 case '1':
1034 FETCH_DATA (info, buffer + 3);
1035 val = (buffer[2] << 8) + buffer[3];
1036 val >>= 12;
1037 break;
1038
1039 case '2':
1040 FETCH_DATA (info, buffer + 3);
1041 val = (buffer[2] << 8) + buffer[3];
1042 val >>= 6;
1043 break;
1044
1045 case '3':
1046 case 'j':
1047 FETCH_DATA (info, buffer + 3);
1048 val = (buffer[2] << 8) + buffer[3];
1049 break;
1050
1051 case '4':
1052 FETCH_DATA (info, buffer + 5);
1053 val = (buffer[4] << 8) + buffer[5];
1054 val >>= 12;
1055 break;
1056
1057 case '5':
1058 FETCH_DATA (info, buffer + 5);
1059 val = (buffer[4] << 8) + buffer[5];
1060 val >>= 6;
1061 break;
1062
1063 case '6':
1064 FETCH_DATA (info, buffer + 5);
1065 val = (buffer[4] << 8) + buffer[5];
1066 break;
1067
1068 case '7':
1069 FETCH_DATA (info, buffer + 3);
1070 val = (buffer[2] << 8) + buffer[3];
1071 val >>= 7;
1072 break;
1073
1074 case '8':
1075 FETCH_DATA (info, buffer + 3);
1076 val = (buffer[2] << 8) + buffer[3];
1077 val >>= 10;
1078 break;
1079
1080 case '9':
1081 FETCH_DATA (info, buffer + 3);
1082 val = (buffer[2] << 8) + buffer[3];
1083 val >>= 5;
1084 break;
1085
1086 case 'e':
1087 val = (buffer[1] >> 6);
1088 break;
1089
1090 default:
1091 abort ();
1092 }
1093
1094 switch (bits)
1095 {
1096 case 2:
1097 return val & 3;
1098 case 3:
1099 return val & 7;
1100 case 4:
1101 return val & 017;
1102 case 5:
1103 return val & 037;
1104 case 6:
1105 return val & 077;
1106 case 7:
1107 return val & 0177;
1108 case 8:
1109 return val & 0377;
1110 case 12:
1111 return val & 07777;
1112 default:
1113 abort ();
1114 }
1115 }
1116
1117 /* Print an indexed argument. The base register is BASEREG (-1 for pc).
1118 P points to extension word, in buffer.
1119 ADDR is the nominal core address of that extension word. */
1120
1121 static unsigned char *
1122 print_indexed (basereg, p, addr, info)
1123 int basereg;
1124 unsigned char *p;
1125 bfd_vma addr;
1126 disassemble_info *info;
1127 {
1128 register int word;
1129 static char *const scales[] = {"", "*2", "*4", "*8"};
1130 bfd_vma base_disp;
1131 bfd_vma outer_disp;
1132 char buf[40];
1133 char vmabuf[50];
1134
1135 word = NEXTWORD (p);
1136
1137 /* Generate the text for the index register.
1138 Where this will be output is not yet determined. */
1139 sprintf (buf, "%s.%c%s",
1140 reg_names[(word >> 12) & 0xf],
1141 (word & 0x800) ? 'l' : 'w',
1142 scales[(word >> 9) & 3]);
1143
1144 /* Handle the 68000 style of indexing. */
1145
1146 if ((word & 0x100) == 0)
1147 {
1148 base_disp = word & 0xff;
1149 if ((base_disp & 0x80) != 0)
1150 base_disp -= 0x100;
1151 if (basereg == -1)
1152 base_disp += addr;
1153 (*info->fprintf_func) (info->stream, "(", buf);
1154 print_base (basereg, base_disp, info);
1155 (*info->fprintf_func) (info->stream, ",%s)", buf);
1156 return p;
1157 }
1158
1159 /* Handle the generalized kind. */
1160 /* First, compute the displacement to add to the base register. */
1161
1162 if (word & 0200)
1163 {
1164 if (basereg == -1)
1165 basereg = -3;
1166 else
1167 basereg = -2;
1168 }
1169 if (word & 0100)
1170 buf[0] = '\0';
1171 base_disp = 0;
1172 switch ((word >> 4) & 3)
1173 {
1174 case 2:
1175 base_disp = NEXTWORD (p);
1176 break;
1177 case 3:
1178 base_disp = NEXTLONG (p);
1179 }
1180 if (basereg == -1)
1181 base_disp += addr;
1182
1183 /* Handle single-level case (not indirect) */
1184
1185 if ((word & 7) == 0)
1186 {
1187 (*info->fprintf_func) (info->stream, "(");
1188 print_base (basereg, base_disp, info);
1189 if (buf[0] != '\0')
1190 (*info->fprintf_func) (info->stream, ",%s", buf);
1191 (*info->fprintf_func) (info->stream, ")");
1192 return p;
1193 }
1194
1195 /* Two level. Compute displacement to add after indirection. */
1196
1197 outer_disp = 0;
1198 switch (word & 3)
1199 {
1200 case 2:
1201 outer_disp = NEXTWORD (p);
1202 break;
1203 case 3:
1204 outer_disp = NEXTLONG (p);
1205 }
1206
1207 (*info->fprintf_func) (info->stream, "([");
1208 print_base (basereg, base_disp, info);
1209 if ((word & 4) == 0 && buf[0] != '\0')
1210 {
1211 (*info->fprintf_func) (info->stream, ",%s", buf);
1212 buf[0] = '\0';
1213 }
1214 if (outer_disp)
1215 (*info->fprintf_func) (info->stream, "],$%08x", (uint32)outer_disp);
1216 else
1217 (*info->fprintf_func) (info->stream, "]");
1218 if (buf[0] != '\0')
1219 (*info->fprintf_func) (info->stream, ",%s", buf);
1220 (*info->fprintf_func) (info->stream, ")");
1221
1222 return p;
1223 }
1224
1225 /* Print a base register REGNO and displacement DISP, on INFO->STREAM.
1226 REGNO = -1 for pc, -2 for none (suppressed). */
1227
1228 static void
1229 print_base (regno, disp, info)
1230 int regno;
1231 bfd_vma disp;
1232 disassemble_info *info;
1233 {
1234 if (regno == -1) {
1235 (*info->print_address_func) (disp, info);
1236 (*info->fprintf_func) (info->stream, ",pc");
1237 }
1238 else {
1239 if (regno == -3) {
1240 (*info->print_address_func) (disp, info);
1241 (*info->fprintf_func) (info->stream, ",zpc");
1242 }
1243 else if (regno == -2)
1244 (*info->print_address_func) (disp, info);
1245 else
1246 (*info->fprintf_func) (info->stream, "$%08x,%s", (uint32)disp, reg_names[regno]);
1247 }
1248 }