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