22fa5d7e3d023b345c97dede10f0a7550f8cb199
1 /* Print m68k instructions for GDB, the GNU debugger.
2 Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
4 This file is part of GDB.
6 GDB is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
11 GDB is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GDB; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
30 /* 68k instructions are never longer than this many bytes. */
33 /* Number of elements in the opcode table. */
34 #define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
36 extern char *reg_names
[];
37 char *fpcr_names
[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
38 "fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
40 static unsigned char *print_insn_arg ();
41 static unsigned char *print_indexed ();
42 static void print_base ();
43 static int fetch_arg ();
45 #define NEXTBYTE(p) (p += 2, ((char *)p)[-1])
48 (p += 2, ((((char *)p)[-2]) << 8) + p[-1])
51 (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
53 #define NEXTSINGLE(p) \
54 (p += 4, *((float *)(p - 4)))
56 #define NEXTDOUBLE(p) \
57 (p += 8, *((double *)(p - 8)))
59 #define NEXTEXTEND(p) \
60 (p += 12, 0.0) /* Need a function to convert from extended to double
63 #define NEXTPACKED(p) \
64 (p += 12, 0.0) /* Need a function to convert from packed to double
65 precision. Actually, it's easier to print a
66 packed number than a double anyway, so maybe
67 there should be a special case to handle this... */
69 /* Print the m68k instruction at address MEMADDR in debugged memory,
70 on STREAM. Returns length of the instruction, in bytes. */
73 print_insn (memaddr
, stream
)
77 unsigned char buffer
[MAXLEN
];
79 register unsigned char *p
;
81 register int bestmask
;
84 read_memory (memaddr
, buffer
, MAXLEN
);
88 for (i
= 0; i
< NOPCODES
; i
++)
90 register unsigned int opcode
= m68k_opcodes
[i
].opcode
;
91 register unsigned int match
= m68k_opcodes
[i
].match
;
92 if (((0xff & buffer
[0] & (match
>> 24)) == (0xff & (opcode
>> 24)))
93 && ((0xff & buffer
[1] & (match
>> 16)) == (0xff & (opcode
>> 16)))
94 && ((0xff & buffer
[2] & (match
>> 8)) == (0xff & (opcode
>> 8)))
95 && ((0xff & buffer
[3] & match
) == (0xff & opcode
)))
97 /* Don't use for printout the variants of divul and divsl
98 that have the same register number in two places.
99 The more general variants will match instead. */
100 for (d
= m68k_opcodes
[i
].args
; *d
; d
+= 2)
104 /* Don't use for printout the variants of most floating
105 point coprocessor instructions which use the same
106 register number in two places, as above. */
108 for (d
= m68k_opcodes
[i
].args
; *d
; d
+= 2)
112 if (*d
== 0 && match
> bestmask
)
120 /* Handle undefined instructions. */
123 fprintf_filtered (stream
, "0%o", (buffer
[0] << 8) + buffer
[1]);
127 fprintf_filtered (stream
, "%s", m68k_opcodes
[best
].name
);
129 /* Point at first word of argument data,
130 and at descriptor for first argument. */
133 /* Why do this this way? -MelloN */
134 for (d
= m68k_opcodes
[best
].args
; *d
; d
+= 2)
138 if (d
[1] == 'l' && p
- buffer
< 6)
140 else if (p
- buffer
< 4 && d
[1] != 'C' && d
[1] != '8' )
143 if (d
[1] >= '1' && d
[1] <= '3' && p
- buffer
< 4)
145 if (d
[1] >= '4' && d
[1] <= '6' && p
- buffer
< 6)
147 if ((d
[0] == 'L' || d
[0] == 'l') && d
[1] == 'w' && p
- buffer
< 4)
151 d
= m68k_opcodes
[best
].args
;
154 fputs_filtered (" ", stream
);
158 p
= print_insn_arg (d
, buffer
, p
, memaddr
+ p
- buffer
, stream
);
160 if (*d
&& *(d
- 2) != 'I' && *d
!= 'k')
161 fputs_filtered (",", stream
);
166 static unsigned char *
167 print_insn_arg (d
, buffer
, p
, addr
, stream
)
169 unsigned char *buffer
;
170 register unsigned char *p
;
171 CORE_ADDR addr
; /* PC for this arg to be relative to */
175 register int place
= d
[1];
177 register char *regname
;
178 register unsigned char *p1
;
179 register double flval
;
185 fprintf_filtered (stream
, "ccr");
189 fprintf_filtered (stream
, "sr");
193 fprintf_filtered (stream
, "usp");
198 static struct { char *name
; int value
; } names
[]
199 = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
200 {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
201 {"msp", 0x803}, {"isp", 0x804}};
203 val
= fetch_arg (buffer
, place
, 12);
204 for (regno
= sizeof names
/ sizeof names
[0] - 1; regno
>= 0; regno
--)
205 if (names
[regno
].value
== val
)
207 fprintf_filtered (stream
, names
[regno
].name
);
211 fprintf_filtered (stream
, "%d", val
);
216 val
= fetch_arg (buffer
, place
, 3);
217 if (val
== 0) val
= 8;
218 fprintf_filtered (stream
, "#%d", val
);
222 val
= fetch_arg (buffer
, place
, 8);
225 fprintf_filtered (stream
, "#%d", val
);
229 val
= fetch_arg (buffer
, place
, 4);
230 fprintf_filtered (stream
, "#%d", val
);
234 fprintf_filtered (stream
, "%s", reg_names
[fetch_arg (buffer
, place
, 3)]);
238 fprintf_filtered (stream
, "%s",
239 reg_names
[fetch_arg (buffer
, place
, 3) + 010]);
243 fprintf_filtered (stream
, "%s", reg_names
[fetch_arg (buffer
, place
, 4)]);
247 fprintf_filtered (stream
, "fp%d", fetch_arg (buffer
, place
, 3));
251 val
= fetch_arg (buffer
, place
, 6);
253 fprintf_filtered (stream
, "%s", reg_names
[val
& 7]);
255 fprintf_filtered (stream
, "%d", val
);
259 fprintf_filtered (stream
, "%s@+",
260 reg_names
[fetch_arg (buffer
, place
, 3) + 8]);
264 fprintf_filtered (stream
, "%s@-",
265 reg_names
[fetch_arg (buffer
, place
, 3) + 8]);
270 fprintf_filtered (stream
, "{%s}", reg_names
[fetch_arg (buffer
, place
, 3)]);
271 else if (place
== 'C')
273 val
= fetch_arg (buffer
, place
, 7);
274 if ( val
> 63 ) /* This is a signed constant. */
276 fprintf_filtered (stream
, "{#%d}", val
);
279 error ("Invalid arg format in opcode table: \"%c%c\".",
285 p1
= buffer
+ (*d
== '#' ? 2 : 4);
287 val
= fetch_arg (buffer
, place
, 4);
288 else if (place
== 'C')
289 val
= fetch_arg (buffer
, place
, 7);
290 else if (place
== '8')
291 val
= fetch_arg (buffer
, place
, 3);
292 else if (place
== '3')
293 val
= fetch_arg (buffer
, place
, 8);
294 else if (place
== 'b')
296 else if (place
== 'w')
298 else if (place
== 'l')
301 error ("Invalid arg format in opcode table: \"%c%c\".",
303 fprintf_filtered (stream
, "#%d", val
);
309 else if (place
== 'w')
311 else if (place
== 'l')
313 else if (place
== 'g')
315 val
= ((char *)buffer
)[1];
321 else if (place
== 'c')
323 if (buffer
[1] & 0x40) /* If bit six is one, long offset */
329 error ("Invalid arg format in opcode table: \"%c%c\".",
332 print_address (addr
+ val
, stream
);
337 fprintf_filtered (stream
, "%s@(%d)",
338 reg_names
[fetch_arg (buffer
, place
, 3)], val
);
342 fprintf_filtered (stream
, "%s",
343 fpcr_names
[fetch_arg (buffer
, place
, 3)]);
347 val
= fetch_arg (buffer
, 'd', 3); /* Get coprocessor ID... */
348 if (val
!= 1) /* Unusual coprocessor ID? */
349 fprintf_filtered (stream
, "(cpid=%d) ", val
);
351 p
+= 2; /* Skip coprocessor extended operands */
367 val
= fetch_arg (buffer
, 'x', 6);
368 val
= ((val
& 7) << 3) + ((val
>> 3) & 7);
371 val
= fetch_arg (buffer
, 's', 6);
373 /* Get register number assuming address register. */
374 regno
= (val
& 7) + 8;
375 regname
= reg_names
[regno
];
379 fprintf_filtered (stream
, "%s", reg_names
[val
]);
383 fprintf_filtered (stream
, "%s", regname
);
387 fprintf_filtered (stream
, "%s@", regname
);
391 fprintf_filtered (stream
, "%s@+", regname
);
395 fprintf_filtered (stream
, "%s@-", regname
);
400 fprintf_filtered (stream
, "%s@(%d)", regname
, val
);
404 p
= print_indexed (regno
, p
, addr
, stream
);
412 fprintf_filtered (stream
, "@#");
413 print_address (val
, stream
);
418 fprintf_filtered (stream
, "@#");
419 print_address (val
, stream
);
424 print_address (addr
+ val
, stream
);
428 p
= print_indexed (-1, p
, addr
, stream
);
432 flt_p
= 1; /* Assume it's a float... */
451 flval
= NEXTSINGLE(p
);
455 flval
= NEXTDOUBLE(p
);
459 flval
= NEXTEXTEND(p
);
463 flval
= NEXTPACKED(p
);
467 error ("Invalid arg format in opcode table: \"%c%c\".",
470 if ( flt_p
) /* Print a float? */
471 fprintf_filtered (stream
, "#%g", flval
);
473 fprintf_filtered (stream
, "#%d", val
);
477 fprintf_filtered (stream
, "<invalid address mode 0%o>", val
);
489 /* Move the pointer ahead if this point is farther ahead
494 fputs_filtered ("#0", stream
);
499 register int newval
= 0;
500 for (regno
= 0; regno
< 16; ++regno
)
501 if (val
& (0x8000 >> regno
))
502 newval
|= 1 << regno
;
507 for (regno
= 0; regno
< 16; ++regno
)
508 if (val
& (1 << regno
))
512 fputs_filtered ("/", stream
);
514 fprintf_filtered (stream
, "%s", reg_names
[regno
]);
516 while (val
& (1 << (regno
+ 1)))
518 if (regno
> first_regno
)
519 fprintf_filtered (stream
, "-%s", reg_names
[regno
]);
522 else if (place
== '3')
526 val
= fetch_arg (buffer
, place
, 8);
529 fputs_filtered ("#0", stream
);
534 register int newval
= 0;
535 for (regno
= 0; regno
< 8; ++regno
)
536 if (val
& (0x80 >> regno
))
537 newval
|= 1 << regno
;
542 for (regno
= 0; regno
< 8; ++regno
)
543 if (val
& (1 << regno
))
547 fputs_filtered ("/", stream
);
549 fprintf_filtered (stream
, "fp%d", regno
);
551 while (val
& (1 << (regno
+ 1)))
553 if (regno
> first_regno
)
554 fprintf_filtered (stream
, "-fp%d", regno
);
562 error ("Invalid arg format in opcode table: \"%c\".", *d
);
565 return (unsigned char *) p
;
568 /* Fetch BITS bits from a position in the instruction specified by CODE.
569 CODE is a "place to put an argument", or 'x' for a destination
570 that is a general address (mode and register).
571 BUFFER contains the instruction. */
574 fetch_arg (buffer
, code
, bits
)
575 unsigned char *buffer
;
586 case 'd': /* Destination, for register or quick. */
587 val
= (buffer
[0] << 8) + buffer
[1];
591 case 'x': /* Destination, for general arg */
592 val
= (buffer
[0] << 8) + buffer
[1];
597 val
= (buffer
[3] >> 4);
605 val
= (buffer
[2] << 8) + buffer
[3];
610 val
= (buffer
[2] << 8) + buffer
[3];
616 val
= (buffer
[2] << 8) + buffer
[3];
620 val
= (buffer
[4] << 8) + buffer
[5];
625 val
= (buffer
[4] << 8) + buffer
[5];
630 val
= (buffer
[4] << 8) + buffer
[5];
634 val
= (buffer
[2] << 8) + buffer
[3];
639 val
= (buffer
[2] << 8) + buffer
[3];
668 /* Print an indexed argument. The base register is BASEREG (-1 for pc).
669 P points to extension word, in buffer.
670 ADDR is the nominal core address of that extension word. */
672 static unsigned char *
673 print_indexed (basereg
, p
, addr
, stream
)
680 static char *scales
[] = {"", "*2", "*4", "*8"};
681 register int base_disp
;
682 register int outer_disp
;
687 /* Generate the text for the index register.
688 Where this will be output is not yet determined. */
689 sprintf (buf
, "[%s.%c%s]",
690 reg_names
[(word
>> 12) & 0xf],
691 (word
& 0x800) ? 'l' : 'w',
692 scales
[(word
>> 9) & 3]);
694 /* Handle the 68000 style of indexing. */
696 if ((word
& 0x100) == 0)
699 ((word
& 0x80) ? word
| 0xff00 : word
& 0xff)
700 + ((basereg
== -1) ? addr
: 0),
702 fputs_filtered (buf
, stream
);
706 /* Handle the generalized kind. */
707 /* First, compute the displacement to add to the base register. */
714 switch ((word
>> 4) & 3)
717 base_disp
= NEXTWORD (p
);
720 base_disp
= NEXTLONG (p
);
725 /* Handle single-level case (not indirect) */
729 print_base (basereg
, base_disp
, stream
);
730 fputs_filtered (buf
, stream
);
734 /* Two level. Compute displacement to add after indirection. */
740 outer_disp
= NEXTWORD (p
);
743 outer_disp
= NEXTLONG (p
);
746 fprintf_filtered (stream
, "%d(", outer_disp
);
747 print_base (basereg
, base_disp
, stream
);
749 /* If postindexed, print the closeparen before the index. */
751 fprintf_filtered (stream
, ")%s", buf
);
752 /* If preindexed, print the closeparen after the index. */
754 fprintf_filtered (stream
, "%s)", buf
);
759 /* Print a base register REGNO and displacement DISP, on STREAM.
760 REGNO = -1 for pc, -2 for none (suppressed). */
763 print_base (regno
, disp
, stream
)
769 fprintf_filtered (stream
, "%d", disp
);
770 else if (regno
== -1)
771 fprintf_filtered (stream
, "0x%x", disp
);
773 fprintf_filtered (stream
, "%d(%s)", disp
, reg_names
[regno
]);
776 /* Nonzero if the host system has a 68881 (or compatible)
777 floating-point unit. This does *not* indicate whether the target
778 system has a co-processor, just whether the host system does.
779 There might be a difference in the case of remote debugging. */
780 static int have_fpu
= 1;
782 /* This is not part of insn printing, but it is machine-specific,
783 so this is a convenient place to put it.
785 Convert a 68881 extended float to a double.
786 FROM is the address of the extended float.
787 Store the double in *TO. */
789 convert_from_68881 (from
, to
)
799 asm ("mov.l 8(%a6),%a0");
800 asm ("mov.l 12(%a6),%a1");
801 asm ("fmove.x (%a0),%fp0");
802 asm ("fmove.d %fp0,(%a1)");
803 #else /* not HPUX_ASM */
805 asm ("movl a6@(8),a0");
806 asm ("movl a6@(12),a1");
807 asm ("fmovex a0@,fp0");
808 asm ("fmoved fp0,a1@");
810 /* Hand-assemble those insns since some assemblers lose
811 and some have different syntax. */
812 asm (".word 020156");
814 asm (".word 021156");
816 asm (".long 0xf2104800");
817 asm (".long 0xf2117400");
819 #endif /* not HPUX_ASM */
822 /* The converse: convert the double *FROM to an extended float
823 and store where TO points. */
825 convert_to_68881 (from
, to
)
832 asm ("mov.l 8(%a6),%a0");
833 asm ("mov.l 12(%a6),%a1");
834 asm ("fmove.d (%a0),%fp0");
835 asm ("fmove.x %fp0,(%a1)");
836 #else /* not HPUX_ASM */
838 asm ("movl a6@(8),a0");
839 asm ("movl a6@(12),a1");
840 asm ("fmoved a0@,fp0");
841 asm ("fmovex fp0,a1@");
843 /* Hand-assemble those insns since some assemblers lose. */
844 asm (".word 020156");
846 asm (".word 021156");
848 asm (".long 0xf2105400");
849 asm (".long 0xf2116800");
851 #endif /* not HPUX_ASM */
854 static jmp_buf fpu_check
;
860 longjmp (fpu_check
, 1);
866 /* Want to figure out if we've got a coprocessor. The idea is to catch the
867 signal that gets delivered if no coprocessor is around (SIGEMT) then
868 execute a coprocessor instruction and see what happens. have_fpu is set
869 to zero if the EMT signal arrives. Else it is left at 1. */
870 /* If this turns out not to be portable to all 68k machines, we'll
871 have to move it to the dep files. */
872 void (*emthandler
) ();
874 emthandler
= (void (*) ()) signal (SIGEMT
, sigemt
);
875 if (!setjmp (fpu_check
))
877 #if defined(HPUX_ASM)
878 asm (" long 0xf2000600"); /* fmovel fp0, d0 */
880 asm(".long 0xf2000600"); /* fmovel fp0, d0 */
883 signal(SIGEMT
, emthandler
);
This page took 0.048364 seconds and 4 git commands to generate.