1 /* Instruction printing code for the AMD 29000
2 Copyright (C) 1990 Free Software Foundation, Inc.
3 Contributed by Cygnus Support. Written by Jim Kingdon.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 1, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26 # include "am29k-opcode.h"
30 # include "a29k-opcode.h"
31 # define am29k_opcodes a29k_opcodes
32 # define am29k_opcode a29k_opcode
33 # define NUM_OPCODES num_opcodes
34 # define fprintf_filtered fprintf
38 /* Print a symbolic representation of a general-purpose
39 register number NUM on STREAM.
40 NUM is a number as found in the instruction, not as found in
41 debugging symbols; it must be in the range 0-255. */
43 print_general (num, stream)
48 fprintf_filtered (stream, "gr%d", num);
50 fprintf_filtered (stream, "lr%d", num - 128);
53 /* Like print_general but a special-purpose register.
55 The mnemonics used by the AMD assembler are not quite the same
56 as the ones in the User's Manual. We use the ones that the
59 print_special (num, stream)
63 /* Register names of registers 0-SPEC0_NUM-1. */
64 static char *spec0_names[] = {
65 "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr",
66 "pc0", "pc1", "pc2", "mmu", "lru"
68 #define SPEC0_NUM ((sizeof spec0_names) / (sizeof spec0_names[0]))
70 /* Register names of registers 128-128+SPEC128_NUM-1. */
71 static char *spec128_names[] = {
72 "ipc", "ipa", "ipb", "q", "alu", "bp", "fc", "cr"
74 #define SPEC128_NUM ((sizeof spec128_names) / (sizeof spec128_names[0]))
76 /* Register names of registers 160-160+SPEC160_NUM-1. */
77 static char *spec160_names[] = {
78 "fpe", "inte", "fps", "sr163", "exop"
80 #define SPEC160_NUM ((sizeof spec160_names) / (sizeof spec160_names[0]))
83 fprintf_filtered (stream, spec0_names[num]);
84 else if (num >= 128 && num < 128 + SPEC128_NUM)
85 fprintf_filtered (stream, spec128_names[num-128]);
86 else if (num >= 160 && num < 160 + SPEC160_NUM)
87 fprintf_filtered (stream, spec160_names[num-160]);
89 fprintf_filtered (stream, "sr%d", num);
92 /* Is an instruction with OPCODE a delayed branch? */
94 is_delayed_branch (opcode)
97 return (opcode == 0xa8 || opcode == 0xa9 || opcode == 0xa0 || opcode == 0xa1
98 || opcode == 0xa4 || opcode == 0xa5
99 || opcode == 0xb4 || opcode == 0xb5
100 || opcode == 0xc4 || opcode == 0xc0
101 || opcode == 0xac || opcode == 0xad
105 /* Now find the four bytes of INSN and put them in *INSN{0,8,16,24}.
106 Note that the amd can be set up as either
107 big or little-endian (the tm file says which) and we can't assume
108 the host machine is the same. */
110 find_bytes (insn, insn0, insn8, insn16, insn24)
112 unsigned char *insn0;
113 unsigned char *insn8;
114 unsigned char *insn16;
115 unsigned char *insn24;
117 #if TARGET_BYTE_ORDER == BIG_ENDIAN
122 #else /* Little-endian. */
127 #endif /* Little-endian. */
130 /* Print one instruction from MEMADDR on STREAM.
131 Return the size of the instruction (always 4 on am29k). */
133 print_insn (memaddr, stream)
138 print_insn_a29k (memaddr, buffer, stream)
144 /* The raw instruction. */
147 /* The four bytes of the instruction. */
148 unsigned char insn24, insn16, insn8, insn0;
150 CONST struct am29k_opcode *opcode;
153 read_memory (memaddr, &insn[0], 4);
155 insn[0] = ((char*)buffer)[0];
156 insn[1] = ((char*)buffer)[1];
157 insn[2] = ((char*)buffer)[2];
158 insn[3] = ((char*)buffer)[3];
161 find_bytes (insn, &insn0, &insn8, &insn16, &insn24);
163 /* Handle the nop (aseq 0x40,gr1,gr1) specially */
164 if ((insn24==0x70) && (insn16==0x40) && (insn8==0x01) && (insn0==0x01)) {
165 fprintf_filtered (stream,"nop");
170 /* The opcode is always in insn24. */
171 for (opcode = &am29k_opcodes[0];
172 opcode < &am29k_opcodes[NUM_OPCODES];
176 if (insn24 == opcode->opcode)
178 if (insn24 == (opcode->opcode >> 24))
183 fprintf_filtered (stream, "%s ", opcode->name);
184 for (s = opcode->args; *s != '\0'; ++s)
189 print_general (insn8, stream);
193 print_general (insn0, stream);
197 print_general (insn16, stream);
201 fprintf_filtered (stream, "%d", insn0);
205 fprintf_filtered (stream, "%d", (insn16 << 8) + insn0);
209 fprintf_filtered (stream, "0x%x",
210 (insn16 << 24) + (insn0 << 16));
214 fprintf_filtered (stream, "%d",
215 ((insn16 << 8) + insn0) | 0xffff0000);
219 /* This output looks just like absolute addressing, but
220 maybe that's OK (it's what the GDB 68k and EBMON
221 29k disassemblers do). */
222 /* All the shifting is to sign-extend it. p*/
225 (((int)((insn16 << 10) + (insn0 << 2)) << 14) >> 14),
230 print_address ((insn16 << 10) + (insn0 << 2), stream);
234 fprintf_filtered (stream, "%d", insn16 >> 7);
238 fprintf_filtered (stream, "0x%x", insn16 & 0x7f);
242 fprintf_filtered (stream, "%x", insn16);
246 print_special (insn8, stream);
250 fprintf_filtered (stream, "%d", insn0 >> 7);
254 fprintf_filtered (stream, "%d", (insn0 >> 4) & 7);
258 fprintf_filtered (stream, "%d", (insn0 >> 2) & 3);
262 fprintf_filtered (stream, "%d", insn0 & 3);
266 fprintf_filtered (stream, "%d", (insn0 >> 18) & 15);
270 fprintf_filtered (stream, "%d", (insn0 >> 16) & 3);
274 fprintf_filtered (stream, "%c", *s);
278 /* Now we look for a const,consth pair of instructions,
279 in which case we try to print the symbolic address. */
280 if (insn24 == 2) /* consth */
284 unsigned char prev_insn0, prev_insn8, prev_insn16, prev_insn24;
287 errcode = target_read_memory (memaddr - 4,
291 prev_insn[0] = ((char*)buffer)[0-4];
292 prev_insn[1] = ((char*)buffer)[1-4];
293 prev_insn[2] = ((char*)buffer)[2-4];
294 prev_insn[3] = ((char*)buffer)[3-4];
299 /* If it is a delayed branch, we need to look at the
300 instruction before the delayed brach to handle
307 find_bytes (prev_insn, &prev_insn0, &prev_insn8,
308 &prev_insn16, &prev_insn24);
309 if (is_delayed_branch (prev_insn24))
312 errcode = target_read_memory
313 (memaddr - 8, &prev_insn[0], 4);
315 prev_insn[0] = ((char*)buffer)[0-8];
316 prev_insn[1] = ((char*)buffer)[1-8];
317 prev_insn[2] = ((char*)buffer)[2-8];
318 prev_insn[3] = ((char*)buffer)[3-8];
321 find_bytes (prev_insn, &prev_insn0, &prev_insn8,
322 &prev_insn16, &prev_insn24);
326 /* If there was a problem reading memory, then assume
327 the previous instruction was not const. */
330 /* Is it const to the same register? */
332 && prev_insn8 == insn8)
334 fprintf_filtered (stream, "\t; ");
335 print_address (((insn16 << 24) + (insn0 << 16)
336 + (prev_insn16 << 8) + (prev_insn0)),
345 fprintf_filtered (stream, ".word %8x",
346 (insn24 << 24) + (insn16 << 16) + (insn8 << 8) + insn0);