ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/disass/m68k-dis.c
Revision: 1.4
Committed: 2003-04-13T09:54:26Z (21 years, 7 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
CVS Tags: release_3-1
Changes since 1.3: +3 -1 lines
Log Message:
Fix printing of m68k addresses, we assume they are always 32-bit values
even in real addressing mode.

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 #if 1
678 /* FIXME: We are bound to have 32-bit addresses even if cxmon is
679 requested to run in real mode, because m68k is 32-bit. */
680 (*info->fprintf_func) (info->stream, "$%08x", (uint32)(addr + disp));
681 #else
682 (*info->print_address_func) (addr + disp, info);
683 #endif
684 break;
685
686 case 'd':
687 val = NEXTWORD (p);
688 (*info->fprintf_func)
689 (info->stream, "($%04x,%s)",
690 val, reg_names[fetch_arg (buffer, place, 3, info) + 8]);
691 break;
692
693 case 's':
694 (*info->fprintf_func) (info->stream, "%s",
695 fpcr_names[fetch_arg (buffer, place, 3, info)]);
696 break;
697
698 case 'I':
699 /* Get coprocessor ID... */
700 val = fetch_arg (buffer, 'd', 3, info);
701
702 if (val != 1) /* Unusual coprocessor ID? */
703 (*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
704 break;
705
706 case '*':
707 case '~':
708 case '%':
709 case ';':
710 case '@':
711 case '!':
712 case '$':
713 case '?':
714 case '/':
715 case '&':
716 case '|':
717 case '<':
718 case '>':
719 case 'm':
720 case 'n':
721 case 'o':
722 case 'p':
723 case 'q':
724 case 'v':
725
726 if (place == 'd')
727 {
728 val = fetch_arg (buffer, 'x', 6, info);
729 val = ((val & 7) << 3) + ((val >> 3) & 7);
730 }
731 else
732 val = fetch_arg (buffer, 's', 6, info);
733
734 /* Get register number assuming address register. */
735 regno = (val & 7) + 8;
736 regname = reg_names[regno];
737 switch (val >> 3)
738 {
739 case 0:
740 (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
741 break;
742
743 case 1:
744 (*info->fprintf_func) (info->stream, "%s", regname);
745 break;
746
747 case 2:
748 (*info->fprintf_func) (info->stream, "(%s)", regname);
749 break;
750
751 case 3:
752 (*info->fprintf_func) (info->stream, "(%s)+", regname);
753 break;
754
755 case 4:
756 (*info->fprintf_func) (info->stream, "-(%s)", regname);
757 break;
758
759 case 5:
760 val = NEXTWORD (p);
761 (*info->fprintf_func) (info->stream, "($%04x,%s)", val, regname);
762 break;
763
764 case 6:
765 p = print_indexed (regno, p, addr, info);
766 break;
767
768 case 7:
769 switch (val & 7)
770 {
771 case 0:
772 val = NEXTWORD (p);
773 (*info->print_address_func) (val, info);
774 break;
775
776 case 1:
777 uval = NEXTULONG (p);
778 (*info->print_address_func) (uval, info);
779 break;
780
781 case 2:
782 val = NEXTWORD (p);
783 (*info->fprintf_func) (info->stream, "($%08x,pc)", addr + val);
784 break;
785
786 case 3:
787 p = print_indexed (-1, p, addr, info);
788 break;
789
790 case 4:
791 switch( place )
792 {
793 case 'b':
794 val = NEXTBYTE (p);
795 (*info->fprintf_func) (info->stream, "#$%02x", val & 0xff);
796 goto imm_printed;
797
798 case 'w':
799 val = NEXTWORD (p);
800 (*info->fprintf_func) (info->stream, "#$%04x", val & 0xffff);
801 goto imm_printed;
802
803 case 'l':
804 val = NEXTLONG (p);
805 (*info->fprintf_func) (info->stream, "#$%08x", val);
806 goto imm_printed;
807
808 case 'f':
809 NEXTSINGLE(flval, p);
810 break;
811
812 case 'F':
813 NEXTDOUBLE(flval, p);
814 break;
815
816 case 'x':
817 NEXTEXTEND(flval, p);
818 break;
819
820 case 'p':
821 flval = NEXTPACKED(p);
822 break;
823
824 default:
825 return -1;
826 }
827 (*info->fprintf_func) (info->stream, "#%g", flval);
828 imm_printed:
829 break;
830
831 default:
832 return -1;
833 }
834 }
835 break;
836
837 case 'L':
838 case 'l':
839 if (place == 'w')
840 {
841 char doneany;
842 p1 = buffer + 2;
843 val = NEXTWORD (p1);
844 /* Move the pointer ahead if this point is farther ahead
845 than the last. */
846 p = p1 > p ? p1 : p;
847 if (val == 0)
848 {
849 (*info->fprintf_func) (info->stream, "#0");
850 break;
851 }
852 if (*d == 'l')
853 {
854 register int newval = 0;
855 for (regno = 0; regno < 16; ++regno)
856 if (val & (0x8000 >> regno))
857 newval |= 1 << regno;
858 val = newval;
859 }
860 val &= 0xffff;
861 doneany = 0;
862 for (regno = 0; regno < 16; ++regno)
863 if (val & (1 << regno))
864 {
865 int first_regno;
866 if (doneany)
867 (*info->fprintf_func) (info->stream, "/");
868 doneany = 1;
869 (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
870 first_regno = regno;
871 while (val & (1 << (regno + 1)))
872 ++regno;
873 if (regno > first_regno)
874 (*info->fprintf_func) (info->stream, "-%s",
875 reg_names[regno]);
876 }
877 }
878 else if (place == '3')
879 {
880 /* `fmovem' insn. */
881 char doneany;
882 val = fetch_arg (buffer, place, 8, info);
883 if (val == 0)
884 {
885 (*info->fprintf_func) (info->stream, "#0");
886 break;
887 }
888 if (*d == 'l')
889 {
890 register int newval = 0;
891 for (regno = 0; regno < 8; ++regno)
892 if (val & (0x80 >> regno))
893 newval |= 1 << regno;
894 val = newval;
895 }
896 val &= 0xff;
897 doneany = 0;
898 for (regno = 0; regno < 8; ++regno)
899 if (val & (1 << regno))
900 {
901 int first_regno;
902 if (doneany)
903 (*info->fprintf_func) (info->stream, "/");
904 doneany = 1;
905 (*info->fprintf_func) (info->stream, "fp%d", regno);
906 first_regno = regno;
907 while (val & (1 << (regno + 1)))
908 ++regno;
909 if (regno > first_regno)
910 (*info->fprintf_func) (info->stream, "-fp%d", regno);
911 }
912 }
913 else if (place == '8')
914 {
915 /* fmoveml for FP status registers */
916 (*info->fprintf_func) (info->stream, "%s",
917 fpcr_names[fetch_arg (buffer, place, 3,
918 info)]);
919 }
920 else
921 return -2;
922 break;
923
924 case 'X':
925 place = '8';
926 case 'Y':
927 case 'Z':
928 case 'W':
929 case '0':
930 case '1':
931 case '2':
932 case '3':
933 {
934 int val = fetch_arg (buffer, place, 5, info);
935 char *name = 0;
936 switch (val)
937 {
938 case 2: name = "tt0"; break;
939 case 3: name = "tt1"; break;
940 case 0x10: name = "tc"; break;
941 case 0x11: name = "drp"; break;
942 case 0x12: name = "srp"; break;
943 case 0x13: name = "crp"; break;
944 case 0x14: name = "cal"; break;
945 case 0x15: name = "val"; break;
946 case 0x16: name = "scc"; break;
947 case 0x17: name = "ac"; break;
948 case 0x18: name = "psr"; break;
949 case 0x19: name = "pcsr"; break;
950 case 0x1c:
951 case 0x1d:
952 {
953 int break_reg = ((buffer[3] >> 2) & 7);
954 (*info->fprintf_func)
955 (info->stream, val == 0x1c ? "bad%d" : "bac%d",
956 break_reg);
957 }
958 break;
959 default:
960 (*info->fprintf_func) (info->stream, "<mmu register %d>", val);
961 }
962 if (name)
963 (*info->fprintf_func) (info->stream, "%s", name);
964 }
965 break;
966
967 case 'f':
968 {
969 int fc = fetch_arg (buffer, place, 5, info);
970 if (fc == 1)
971 (*info->fprintf_func) (info->stream, "dfc");
972 else if (fc == 0)
973 (*info->fprintf_func) (info->stream, "sfc");
974 else
975 /* xgettext:c-format */
976 (*info->fprintf_func) (info->stream, _("<function code %d>"), fc);
977 }
978 break;
979
980 case 'V':
981 (*info->fprintf_func) (info->stream, "val");
982 break;
983
984 case 't':
985 {
986 int level = fetch_arg (buffer, place, 3, info);
987 (*info->fprintf_func) (info->stream, "%d", level);
988 }
989 break;
990
991 default:
992 return -2;
993 }
994
995 return p - p0;
996 }
997
998 /* Fetch BITS bits from a position in the instruction specified by CODE.
999 CODE is a "place to put an argument", or 'x' for a destination
1000 that is a general address (mode and register).
1001 BUFFER contains the instruction. */
1002
1003 static int
1004 fetch_arg (buffer, code, bits, info)
1005 unsigned char *buffer;
1006 int code;
1007 int bits;
1008 disassemble_info *info;
1009 {
1010 register int val = 0;
1011 switch (code)
1012 {
1013 case 's':
1014 val = buffer[1];
1015 break;
1016
1017 case 'd': /* Destination, for register or quick. */
1018 val = (buffer[0] << 8) + buffer[1];
1019 val >>= 9;
1020 break;
1021
1022 case 'x': /* Destination, for general arg */
1023 val = (buffer[0] << 8) + buffer[1];
1024 val >>= 6;
1025 break;
1026
1027 case 'k':
1028 FETCH_DATA (info, buffer + 3);
1029 val = (buffer[3] >> 4);
1030 break;
1031
1032 case 'C':
1033 FETCH_DATA (info, buffer + 3);
1034 val = buffer[3];
1035 break;
1036
1037 case '1':
1038 FETCH_DATA (info, buffer + 3);
1039 val = (buffer[2] << 8) + buffer[3];
1040 val >>= 12;
1041 break;
1042
1043 case '2':
1044 FETCH_DATA (info, buffer + 3);
1045 val = (buffer[2] << 8) + buffer[3];
1046 val >>= 6;
1047 break;
1048
1049 case '3':
1050 case 'j':
1051 FETCH_DATA (info, buffer + 3);
1052 val = (buffer[2] << 8) + buffer[3];
1053 break;
1054
1055 case '4':
1056 FETCH_DATA (info, buffer + 5);
1057 val = (buffer[4] << 8) + buffer[5];
1058 val >>= 12;
1059 break;
1060
1061 case '5':
1062 FETCH_DATA (info, buffer + 5);
1063 val = (buffer[4] << 8) + buffer[5];
1064 val >>= 6;
1065 break;
1066
1067 case '6':
1068 FETCH_DATA (info, buffer + 5);
1069 val = (buffer[4] << 8) + buffer[5];
1070 break;
1071
1072 case '7':
1073 FETCH_DATA (info, buffer + 3);
1074 val = (buffer[2] << 8) + buffer[3];
1075 val >>= 7;
1076 break;
1077
1078 case '8':
1079 FETCH_DATA (info, buffer + 3);
1080 val = (buffer[2] << 8) + buffer[3];
1081 val >>= 10;
1082 break;
1083
1084 case '9':
1085 FETCH_DATA (info, buffer + 3);
1086 val = (buffer[2] << 8) + buffer[3];
1087 val >>= 5;
1088 break;
1089
1090 case 'e':
1091 val = (buffer[1] >> 6);
1092 break;
1093
1094 default:
1095 abort ();
1096 }
1097
1098 switch (bits)
1099 {
1100 case 2:
1101 return val & 3;
1102 case 3:
1103 return val & 7;
1104 case 4:
1105 return val & 017;
1106 case 5:
1107 return val & 037;
1108 case 6:
1109 return val & 077;
1110 case 7:
1111 return val & 0177;
1112 case 8:
1113 return val & 0377;
1114 case 12:
1115 return val & 07777;
1116 default:
1117 abort ();
1118 }
1119 }
1120
1121 /* Print an indexed argument. The base register is BASEREG (-1 for pc).
1122 P points to extension word, in buffer.
1123 ADDR is the nominal core address of that extension word. */
1124
1125 static unsigned char *
1126 print_indexed (basereg, p, addr, info)
1127 int basereg;
1128 unsigned char *p;
1129 bfd_vma addr;
1130 disassemble_info *info;
1131 {
1132 register int word;
1133 static char *const scales[] = {"", "*2", "*4", "*8"};
1134 bfd_vma base_disp;
1135 bfd_vma outer_disp;
1136 char buf[40];
1137 char vmabuf[50];
1138
1139 word = NEXTWORD (p);
1140
1141 /* Generate the text for the index register.
1142 Where this will be output is not yet determined. */
1143 sprintf (buf, "%s.%c%s",
1144 reg_names[(word >> 12) & 0xf],
1145 (word & 0x800) ? 'l' : 'w',
1146 scales[(word >> 9) & 3]);
1147
1148 /* Handle the 68000 style of indexing. */
1149
1150 if ((word & 0x100) == 0)
1151 {
1152 base_disp = word & 0xff;
1153 if ((base_disp & 0x80) != 0)
1154 base_disp -= 0x100;
1155 if (basereg == -1)
1156 base_disp += addr;
1157 (*info->fprintf_func) (info->stream, "(", buf);
1158 print_base (basereg, base_disp, info);
1159 (*info->fprintf_func) (info->stream, ",%s)", buf);
1160 return p;
1161 }
1162
1163 /* Handle the generalized kind. */
1164 /* First, compute the displacement to add to the base register. */
1165
1166 if (word & 0200)
1167 {
1168 if (basereg == -1)
1169 basereg = -3;
1170 else
1171 basereg = -2;
1172 }
1173 if (word & 0100)
1174 buf[0] = '\0';
1175 base_disp = 0;
1176 switch ((word >> 4) & 3)
1177 {
1178 case 2:
1179 base_disp = NEXTWORD (p);
1180 break;
1181 case 3:
1182 base_disp = NEXTLONG (p);
1183 }
1184 if (basereg == -1)
1185 base_disp += addr;
1186
1187 /* Handle single-level case (not indirect) */
1188
1189 if ((word & 7) == 0)
1190 {
1191 (*info->fprintf_func) (info->stream, "(");
1192 print_base (basereg, base_disp, info);
1193 if (buf[0] != '\0')
1194 (*info->fprintf_func) (info->stream, ",%s", buf);
1195 (*info->fprintf_func) (info->stream, ")");
1196 return p;
1197 }
1198
1199 /* Two level. Compute displacement to add after indirection. */
1200
1201 outer_disp = 0;
1202 switch (word & 3)
1203 {
1204 case 2:
1205 outer_disp = NEXTWORD (p);
1206 break;
1207 case 3:
1208 outer_disp = NEXTLONG (p);
1209 }
1210
1211 (*info->fprintf_func) (info->stream, "([");
1212 print_base (basereg, base_disp, info);
1213 if ((word & 4) == 0 && buf[0] != '\0')
1214 {
1215 (*info->fprintf_func) (info->stream, ",%s", buf);
1216 buf[0] = '\0';
1217 }
1218 if (outer_disp)
1219 (*info->fprintf_func) (info->stream, "],$%08x", outer_disp);
1220 else
1221 (*info->fprintf_func) (info->stream, "]", outer_disp);
1222 if (buf[0] != '\0')
1223 (*info->fprintf_func) (info->stream, ",%s", buf);
1224 (*info->fprintf_func) (info->stream, ")");
1225
1226 return p;
1227 }
1228
1229 /* Print a base register REGNO and displacement DISP, on INFO->STREAM.
1230 REGNO = -1 for pc, -2 for none (suppressed). */
1231
1232 static void
1233 print_base (regno, disp, info)
1234 int regno;
1235 bfd_vma disp;
1236 disassemble_info *info;
1237 {
1238 if (regno == -1)
1239 (*info->fprintf_func) (info->stream, "$%08x,pc", disp);
1240 else {
1241 if (regno == -3)
1242 (*info->fprintf_func) (info->stream, "$%08x,zpc", disp);
1243 else if (regno == -2)
1244 (*info->print_address_func) (disp, info);
1245 else
1246 (*info->fprintf_func) (info->stream, "$%08x,%s", disp, reg_names[regno]);
1247 }
1248 }