]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/m68k-pinsn.c
gdb-2.5.1
[thirdparty/binutils-gdb.git] / gdb / m68k-pinsn.c
1 /* Print m68k instructions for GDB, the GNU debugger.
2 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
3
4 GDB is distributed in the hope that it will be useful, but WITHOUT ANY
5 WARRANTY. No author or distributor accepts responsibility to anyone
6 for the consequences of using it or for whether it serves any
7 particular purpose or works at all, unless he says so in writing.
8 Refer to the GDB General Public License for full details.
9
10 Everyone is granted permission to copy, modify and redistribute GDB,
11 but only under the conditions described in the GDB General Public
12 License. A copy of this license is supposed to have been given to you
13 along with GDB so you can know your rights and responsibilities. It
14 should be in a file named COPYING. Among other things, the copyright
15 notice and this notice must be preserved on all copies.
16
17 In other words, go ahead and share GDB, but don't try to stop
18 anyone else from sharing it farther. Help stamp out software hoarding!
19 */
20
21 #include <stdio.h>
22
23 #include "defs.h"
24 #include "param.h"
25 #include "symtab.h"
26 #include "m68k-opcode.h"
27
28 /* 68k instructions are never longer than this many bytes. */
29 #define MAXLEN 22
30
31 /* Number of elements in the opcode table. */
32 #define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
33
34 extern char *reg_names[];
35 char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
36 "fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
37
38 static unsigned char *print_insn_arg ();
39 static unsigned char *print_indexed ();
40 static void print_base ();
41 static int fetch_arg ();
42
43 #define NEXTBYTE(p) (p += 2, ((char *)p)[-1])
44
45 #define NEXTWORD(p) \
46 (p += 2, ((((char *)p)[-2]) << 8) + p[-1])
47
48 #define NEXTLONG(p) \
49 (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
50
51 #define NEXTSINGLE(p) \
52 (p += 4, *((float *)(p - 4)))
53
54 #define NEXTDOUBLE(p) \
55 (p += 8, *((double *)(p - 8)))
56
57 #define NEXTEXTEND(p) \
58 (p += 12, 0.0) /* Need a function to convert from extended to double
59 precision... */
60
61 #define NEXTPACKED(p) \
62 (p += 12, 0.0) /* Need a function to convert from packed to double
63 precision. Actually, it's easier to print a
64 packed number than a double anyway, so maybe
65 there should be a special case to handle this... */
66 \f
67 /* Print the m68k instruction at address MEMADDR in debugged memory,
68 on STREAM. Returns length of the instruction, in bytes. */
69
70 int
71 print_insn (memaddr, stream)
72 CORE_ADDR memaddr;
73 FILE *stream;
74 {
75 unsigned char buffer[MAXLEN];
76 register int i;
77 register unsigned char *p;
78 register char *d;
79 register int bestmask;
80 int best;
81
82 read_memory (memaddr, buffer, MAXLEN);
83
84 bestmask = 0;
85 best = -1;
86 for (i = 0; i < NOPCODES; i++)
87 {
88 register unsigned int opcode = m68k_opcodes[i].opcode;
89 register unsigned int match = m68k_opcodes[i].match;
90 if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
91 && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
92 && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
93 && ((0xff & buffer[3] & match) == (0xff & opcode)))
94 {
95 /* Don't use for printout the variants of divul and divsl
96 that have the same register number in two places.
97 The more general variants will match instead. */
98 for (d = m68k_opcodes[i].args; *d; d += 2)
99 if (d[1] == 'D')
100 break;
101
102 /* Don't use for printout the variants of most floating
103 point coprocessor instructions which use the same
104 register number in two places, as above. */
105 if (*d == 0)
106 for (d = m68k_opcodes[i].args; *d; d += 2)
107 if (d[1] == 't')
108 break;
109
110 if (*d == 0 && match > bestmask)
111 {
112 best = i;
113 bestmask = match;
114 }
115 }
116 }
117
118 /* Handle undefined instructions. */
119 if (best < 0)
120 {
121 fprintf (stream, "0%o", (buffer[0] << 8) + buffer[1]);
122 return 2;
123 }
124
125 fprintf (stream, "%s", m68k_opcodes[best].name);
126
127 /* Point at first word of argument data,
128 and at descriptor for first argument. */
129 p = buffer + 2;
130
131 /* Why do this this way? -MelloN */
132 for (d = m68k_opcodes[best].args; *d; d += 2)
133 {
134 if (d[0] == '#')
135 {
136 if (d[1] == 'l' && p - buffer < 6)
137 p = buffer + 6;
138 else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
139 p = buffer + 4;
140 }
141 if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
142 p = buffer + 4;
143 if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
144 p = buffer + 6;
145 }
146
147 d = m68k_opcodes[best].args;
148
149 if (*d)
150 fputc (' ', stream);
151
152 while (*d)
153 {
154 p = print_insn_arg (d, buffer, p, memaddr + p - buffer, stream);
155 d += 2;
156 if (*d && *(d - 2) != 'I' && *d != 'k')
157 fprintf (stream, ",");
158 }
159 return p - buffer;
160 }
161
162 static unsigned char *
163 print_insn_arg (d, buffer, p, addr, stream)
164 char *d;
165 unsigned char *buffer;
166 register unsigned char *p;
167 CORE_ADDR addr; /* PC for this arg to be relative to */
168 FILE *stream;
169 {
170 register int val;
171 register int place = d[1];
172 int regno;
173 register char *regname;
174 register unsigned char *p1;
175 register double flval;
176 int flt_p;
177
178 switch (*d)
179 {
180 case 'C':
181 fprintf (stream, "ccr");
182 break;
183
184 case 'S':
185 fprintf (stream, "sr");
186 break;
187
188 case 'U':
189 fprintf (stream, "usp");
190 break;
191
192 case 'J':
193 {
194 static struct { char *name; int value; } names[]
195 = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
196 {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
197 {"msp", 0x803}, {"isp", 0x804}};
198
199 val = fetch_arg (buffer, place, 12);
200 for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
201 if (names[regno].value == val)
202 {
203 fprintf (stream, names[regno].name);
204 break;
205 }
206 if (regno < 0)
207 fprintf (stream, "%d", val);
208 }
209 break;
210
211 case 'Q':
212 val = fetch_arg (buffer, place, 3);
213 if (val == 0) val = 8;
214 fprintf (stream, "#%d", val);
215 break;
216
217 case 'M':
218 val = fetch_arg (buffer, place, 8);
219 if (val & 0x80)
220 val = val - 0x100;
221 fprintf (stream, "#%d", val);
222 break;
223
224 case 'T':
225 val = fetch_arg (buffer, place, 4);
226 fprintf (stream, "#%d", val);
227 break;
228
229 case 'D':
230 fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]);
231 break;
232
233 case 'A':
234 fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3) + 010]);
235 break;
236
237 case 'R':
238 fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]);
239 break;
240
241 case 'F':
242 fprintf (stream, "fp%d", fetch_arg (buffer, place, 3));
243 break;
244
245 case 'O':
246 val = fetch_arg (buffer, place, 6);
247 if (val & 0x20)
248 fprintf (stream, "%s", reg_names [val & 7]);
249 else
250 fprintf (stream, "%d", val);
251 break;
252
253 case '+':
254 fprintf (stream, "(%s)+", reg_names[fetch_arg (buffer, place, 3) + 8]);
255 break;
256
257 case '-':
258 fprintf (stream, "-(%s)", reg_names[fetch_arg (buffer, place, 3) + 8]);
259 break;
260
261 case 'k':
262 if (place == 'k')
263 fprintf (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]);
264 else if (place == 'C')
265 {
266 val = fetch_arg (buffer, place, 7);
267 if ( val > 63 ) /* This is a signed constant. */
268 val -= 128;
269 fprintf (stream, "{#%d}", val);
270 }
271 else
272 error ("Invalid arg format in opcode table: \"%c%c\".",
273 *d, place);
274 break;
275
276 case '#':
277 p1 = buffer + 2;
278 if (place == 's')
279 val = fetch_arg (buffer, place, 4);
280 else if (place == 'C')
281 val = fetch_arg (buffer, place, 7);
282 else if (place == '8')
283 val = fetch_arg (buffer, place, 3);
284 else if (place == '3')
285 val = fetch_arg (buffer, place, 8);
286 else if (place == 'b')
287 val = NEXTBYTE (p1);
288 else if (place == 'w')
289 val = NEXTWORD (p1);
290 else if (place == 'l')
291 val = NEXTLONG (p1);
292 else
293 error ("Invalid arg format in opcode table: \"%c%c\".",
294 *d, place);
295 fprintf (stream, "#%d", val);
296 break;
297
298 case '^':
299 if (place == 's')
300 val = fetch_arg (buffer, place, 4);
301 else if (place == 'C')
302 val = fetch_arg (buffer, place, 7);
303 else if (place == '8')
304 val = fetch_arg (buffer, place, 3);
305 else if (place == 'b')
306 val = NEXTBYTE (p);
307 else if (place == 'w')
308 val = NEXTWORD (p);
309 else if (place == 'l')
310 val = NEXTLONG (p);
311 else
312 error ("Invalid arg format in opcode table: \"%c%c\".",
313 *d, place);
314 fprintf (stream, "#%d", val);
315 break;
316
317 case 'B':
318 if (place == 'b')
319 val = NEXTBYTE (p);
320 else if (place == 'w')
321 val = NEXTWORD (p);
322 else if (place == 'l')
323 val = NEXTLONG (p);
324 else if (place == 'g')
325 {
326 val = ((char *)buffer)[1];
327 if (val == 0)
328 val = NEXTWORD (p);
329 else if (val == -1)
330 val = NEXTLONG (p);
331 }
332 else if (place == 'c')
333 {
334 if (buffer[1] & 0x40) /* If bit six is one, long offset */
335 val = NEXTLONG (p);
336 else
337 val = NEXTWORD (p);
338 }
339 else
340 error ("Invalid arg format in opcode table: \"%c%c\".",
341 *d, place);
342
343 print_address (addr + val, stream);
344 break;
345
346 case 'd':
347 val = NEXTWORD (p);
348 fprintf (stream, "%d(%s)", val, reg_names[fetch_arg (buffer, place, 3)]);
349 break;
350
351 case 's':
352 fprintf (stream, "%s", fpcr_names[fetch_arg (buffer, place, 3)]);
353 break;
354
355 case 'I':
356 val = fetch_arg (buffer, 'd', 3); /* Get coprocessor ID... */
357 if (val != 1) /* Unusual coprocessor ID? */
358 fprintf (stream, "(cpid=%d) ", val);
359 if (place == 'i')
360 p += 2; /* Skip coprocessor extended operands */
361 break;
362
363 case '*':
364 case '~':
365 case '%':
366 case ';':
367 case '@':
368 case '!':
369 case '$':
370 case '?':
371 case '/':
372 case '&':
373
374 if (place == 'd')
375 {
376 val = fetch_arg (buffer, 'x', 6);
377 val = ((val & 7) << 3) + ((val >> 3) & 7);
378 }
379 else
380 val = fetch_arg (buffer, 's', 6);
381
382 /* Get register number assuming address register. */
383 regno = (val & 7) + 8;
384 regname = reg_names[regno];
385 switch (val >> 3)
386 {
387 case 0:
388 fprintf (stream, "%s", reg_names[val]);
389 break;
390
391 case 1:
392 fprintf (stream, "%s", regname);
393 break;
394
395 case 2:
396 fprintf (stream, "(%s)", regname);
397 break;
398
399 case 3:
400 fprintf (stream, "(%s)+", regname);
401 break;
402
403 case 4:
404 fprintf (stream, "-(%s)", regname);
405 break;
406
407 case 5:
408 val = NEXTWORD (p);
409 fprintf (stream, "%d(%s)", val, regname);
410 break;
411
412 case 6:
413 p = print_indexed (regno, p, addr, stream);
414 break;
415
416 case 7:
417 switch (val & 7)
418 {
419 case 0:
420 val = NEXTWORD (p);
421 fprintf (stream, "@#");
422 print_address (val, stream);
423 break;
424
425 case 1:
426 val = NEXTLONG (p);
427 fprintf (stream, "@#");
428 print_address (val, stream);
429 break;
430
431 case 2:
432 val = NEXTWORD (p);
433 print_address (addr + val, stream);
434 break;
435
436 case 3:
437 p = print_indexed (-1, p, addr, stream);
438 break;
439
440 case 4:
441 flt_p = 1; /* Assume it's a float... */
442 switch( place )
443 {
444 case 'b':
445 val = NEXTBYTE (p);
446 flt_p = 0;
447 break;
448
449 case 'w':
450 val = NEXTWORD (p);
451 flt_p = 0;
452 break;
453
454 case 'l':
455 val = NEXTLONG (p);
456 flt_p = 0;
457 break;
458
459 case 'f':
460 flval = NEXTSINGLE(p);
461 break;
462
463 case 'F':
464 flval = NEXTDOUBLE(p);
465 break;
466
467 case 'x':
468 flval = NEXTEXTEND(p);
469 break;
470
471 case 'p':
472 flval = NEXTPACKED(p);
473 break;
474
475 default:
476 error ("Invalid arg format in opcode table: \"%c%c\".",
477 *d, place);
478 }
479 if ( flt_p ) /* Print a float? */
480 fprintf (stream, "#%g", flval);
481 else
482 fprintf (stream, "#%d", val);
483 break;
484
485 default:
486 fprintf (stream, "<invalid address mode 0%o>", val);
487 }
488 }
489 break;
490
491 default:
492 error ("Invalid arg format in opcode table: \"%c\".", *d);
493 }
494
495 return (unsigned char *) p;
496 }
497
498 /* Fetch BITS bits from a position in the instruction specified by CODE.
499 CODE is a "place to put an argument", or 'x' for a destination
500 that is a general address (mode and register).
501 BUFFER contains the instruction. */
502
503 static int
504 fetch_arg (buffer, code, bits)
505 unsigned char *buffer;
506 char code;
507 int bits;
508 {
509 register int val;
510 switch (code)
511 {
512 case 's':
513 val = buffer[1];
514 break;
515
516 case 'd': /* Destination, for register or quick. */
517 val = (buffer[0] << 8) + buffer[1];
518 val >>= 9;
519 break;
520
521 case 'x': /* Destination, for general arg */
522 val = (buffer[0] << 8) + buffer[1];
523 val >>= 6;
524 break;
525
526 case 'k':
527 val = (buffer[3] >> 4);
528 break;
529
530 case 'C':
531 val = buffer[3];
532 break;
533
534 case '1':
535 val = (buffer[2] << 8) + buffer[3];
536 val >>= 12;
537 break;
538
539 case '2':
540 val = (buffer[2] << 8) + buffer[3];
541 val >>= 6;
542 break;
543
544 case '3':
545 case 'j':
546 val = (buffer[2] << 8) + buffer[3];
547 break;
548
549 case '4':
550 val = (buffer[4] << 8) + buffer[5];
551 val >>= 12;
552 break;
553
554 case '5':
555 val = (buffer[4] << 8) + buffer[5];
556 val >>= 6;
557 break;
558
559 case '6':
560 val = (buffer[4] << 8) + buffer[5];
561 break;
562
563 case '7':
564 val = (buffer[2] << 8) + buffer[3];
565 val >>= 7;
566 break;
567
568 case '8':
569 val = (buffer[2] << 8) + buffer[3];
570 val >>= 10;
571 break;
572
573 default:
574 abort ();
575 }
576
577 switch (bits)
578 {
579 case 3:
580 return val & 7;
581 case 4:
582 return val & 017;
583 case 5:
584 return val & 037;
585 case 6:
586 return val & 077;
587 case 7:
588 return val & 0177;
589 case 8:
590 return val & 0377;
591 case 12:
592 return val & 07777;
593 default:
594 abort ();
595 }
596 }
597
598 /* Print an indexed argument. The base register is BASEREG (-1 for pc).
599 P points to extension word, in buffer.
600 ADDR is the nominal core address of that extension word. */
601
602 static unsigned char *
603 print_indexed (basereg, p, addr, stream)
604 int basereg;
605 unsigned char *p;
606 FILE *stream;
607 CORE_ADDR addr;
608 {
609 register int word;
610 static char *scales[] = {"", "*2", "*4", "*8"};
611 register int base_disp;
612 register int outer_disp;
613 char buf[40];
614
615 word = NEXTWORD (p);
616
617 /* Generate the text for the index register.
618 Where this will be output is not yet determined. */
619 sprintf (buf, "[%s.%c%s]",
620 reg_names[(word >> 12) & 0xf],
621 (word & 0x800) ? 'l' : 'w',
622 scales[(word >> 9) & 3]);
623
624 /* Handle the 68000 style of indexing. */
625
626 if ((word & 0x100) == 0)
627 {
628 print_base (basereg,
629 ((word & 0x80) ? word | 0xff00 : word & 0xff)
630 + ((basereg == -1) ? addr : 0),
631 stream);
632 fprintf (stream, "%s", buf);
633 return p;
634 }
635
636 /* Handle the generalized kind. */
637 /* First, compute the displacement to add to the base register. */
638
639 if (word & 0200)
640 basereg = -2;
641 if (word & 0100)
642 buf[0] = 0;
643 base_disp = 0;
644 switch ((word >> 4) & 3)
645 {
646 case 2:
647 base_disp = NEXTWORD (p);
648 break;
649 case 3:
650 base_disp = NEXTLONG (p);
651 }
652 if (basereg == -1)
653 base_disp += addr;
654
655 /* Handle single-level case (not indirect) */
656
657 if ((word & 7) == 0)
658 {
659 print_base (basereg, base_disp, stream);
660 fprintf (stream, "%s", buf);
661 return p;
662 }
663
664 /* Two level. Compute displacement to add after indirection. */
665
666 outer_disp = 0;
667 switch (word & 3)
668 {
669 case 2:
670 outer_disp = NEXTWORD (p);
671 break;
672 case 3:
673 outer_disp = NEXTLONG (p);
674 }
675
676 fprintf (stream, "%d(", outer_disp);
677 print_base (basereg, base_disp, stream);
678
679 /* If postindexed, print the closeparen before the index. */
680 if (word & 4)
681 fprintf (stream, ")%s", buf);
682 /* If preindexed, print the closeparen after the index. */
683 else
684 fprintf (stream, "%s)", buf);
685
686 return p;
687 }
688
689 /* Print a base register REGNO and displacement DISP, on STREAM.
690 REGNO = -1 for pc, -2 for none (suppressed). */
691
692 static void
693 print_base (regno, disp, stream)
694 int regno;
695 int disp;
696 FILE *stream;
697 {
698 if (regno == -2)
699 fprintf (stream, "%d", disp);
700 else if (regno == -1)
701 fprintf (stream, "0x%x", disp);
702 else
703 fprintf (stream, "%d(%s)", disp, reg_names[regno]);
704 }
705 \f
706 /* This is not part of insn printing, but it is machine-specific,
707 so this is a convenient place to put it.
708
709 Convert a 68881 extended float to a double.
710 FROM is the address of the extended float.
711 Store the double in *TO. */
712
713 convert_from_68881 (from, to)
714 char *from;
715 double *to;
716 {
717 #if 0
718 asm ("movl a6@(8),a0");
719 asm ("movl a6@(12),a1");
720 asm ("fmovex a0@,fp0");
721 asm ("fmoved fp0,a1@");
722 #else
723 /* Hand-assemble those insns since some assemblers lose
724 and some have different syntax. */
725 asm (".word 020156");
726 asm (".word 8");
727 asm (".word 021156");
728 asm (".word 12");
729 asm (".long 0xf2104800");
730 asm (".long 0xf2117400");
731 #endif
732 }
733
734 /* The converse: convert the double *FROM to an extended float
735 and store where TO points. */
736
737 convert_to_68881 (from, to)
738 double *from;
739 char *to;
740 {
741 #if 0
742 asm ("movl a6@(8),a0");
743 asm ("movl a6@(12),a1");
744 asm ("fmoved a0@,fp0");
745 asm ("fmovex fp0,a1@");
746 #else
747 /* Hand-assemble those insns since some assemblers lose. */
748 asm (".word 020156");
749 asm (".word 8");
750 asm (".word 021156");
751 asm (".word 12");
752 asm (".long 0xf2105400");
753 asm (".long 0xf2116800");
754 #endif
755 }