Updated to point to where the header files are now
[deliverable/binutils-gdb.git] / binutils / am29k-pinsn.c
CommitLineData
2013f9b4
SC
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.
4
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 1, or (at your option)
10any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21#include <stdio.h>
22
23#ifdef GDB
24# include "defs.h"
25# include "target.h"
4aa58a0a 26# include "opcode/a29k.h"
2013f9b4 27#else
2013f9b4 28# include "bfd.h"
2a5f387b 29# include "sysdep.h"
4aa58a0a 30# include "opcode/a29k.h"
2013f9b4
SC
31# define am29k_opcodes a29k_opcodes
32# define am29k_opcode a29k_opcode
33# define NUM_OPCODES num_opcodes
34# define fprintf_filtered fprintf
35#endif
36
37
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. */
42static void
43print_general (num, stream)
44 int num;
45 FILE *stream;
46{
47 if (num < 128)
48 fprintf_filtered (stream, "gr%d", num);
49 else
50 fprintf_filtered (stream, "lr%d", num - 128);
51}
52
53/* Like print_general but a special-purpose register.
54
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
57 assembler uses. */
58static void
59print_special (num, stream)
60 int num;
61 FILE *stream;
62{
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"
67 };
68#define SPEC0_NUM ((sizeof spec0_names) / (sizeof spec0_names[0]))
69
70 /* Register names of registers 128-128+SPEC128_NUM-1. */
71 static char *spec128_names[] = {
72 "ipc", "ipa", "ipb", "q", "alu", "bp", "fc", "cr"
73 };
74#define SPEC128_NUM ((sizeof spec128_names) / (sizeof spec128_names[0]))
75
76 /* Register names of registers 160-160+SPEC160_NUM-1. */
77 static char *spec160_names[] = {
78 "fpe", "inte", "fps", "sr163", "exop"
79 };
80#define SPEC160_NUM ((sizeof spec160_names) / (sizeof spec160_names[0]))
81
82 if (num < SPEC0_NUM)
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]);
88 else
89 fprintf_filtered (stream, "sr%d", num);
90}
91
92/* Is an instruction with OPCODE a delayed branch? */
93static int
94is_delayed_branch (opcode)
95 int opcode;
96{
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
102 || opcode == 0xcc);
103}
104
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. */
109static void
110find_bytes (insn, insn0, insn8, insn16, insn24)
111 char *insn;
112 unsigned char *insn0;
113 unsigned char *insn8;
114 unsigned char *insn16;
115 unsigned char *insn24;
116{
117#if TARGET_BYTE_ORDER == BIG_ENDIAN
118 *insn24 = insn[0];
119 *insn16 = insn[1];
120 *insn8 = insn[2];
121 *insn0 = insn[3];
122#else /* Little-endian. */
123 *insn24 = insn[3];
124 *insn16 = insn[2];
125 *insn8 = insn[1];
126 *insn0 = insn[0];
127#endif /* Little-endian. */
128}
129
130/* Print one instruction from MEMADDR on STREAM.
131 Return the size of the instruction (always 4 on am29k). */
132#ifdef GDB
133print_insn (memaddr, stream)
134 CORE_ADDR memaddr;
135 FILE *stream;
136#else
137int
138print_insn_a29k (memaddr, buffer, stream)
139 bfd_vma memaddr;
140 uint8e_type *buffer;
141 FILE *stream;
142#endif
143{
144 /* The raw instruction. */
145 char insn[4];
146
147 /* The four bytes of the instruction. */
148 unsigned char insn24, insn16, insn8, insn0;
66f3e594 149 unsigned long value;
821f042d 150 CONST struct am29k_opcode *opcode;
2013f9b4
SC
151
152#ifdef GDB
153 read_memory (memaddr, &insn[0], 4);
154#else
155 insn[0] = ((char*)buffer)[0];
156 insn[1] = ((char*)buffer)[1];
157 insn[2] = ((char*)buffer)[2];
158 insn[3] = ((char*)buffer)[3];
159#endif
160
161 find_bytes (insn, &insn0, &insn8, &insn16, &insn24);
162
66f3e594 163 value = (insn24 << 24) + (insn16 << 16) + (insn8 << 8) + insn0;
2013f9b4
SC
164 /* Handle the nop (aseq 0x40,gr1,gr1) specially */
165 if ((insn24==0x70) && (insn16==0x40) && (insn8==0x01) && (insn0==0x01)) {
166 fprintf_filtered (stream,"nop");
167 return 4;
168 }
169
170
171 /* The opcode is always in insn24. */
172 for (opcode = &am29k_opcodes[0];
173 opcode < &am29k_opcodes[NUM_OPCODES];
174 ++opcode)
175 {
176#ifdef GDB
177 if (insn24 == opcode->opcode)
178#else
179 if (insn24 == (opcode->opcode >> 24))
180#endif
181 {
182 char *s;
183
184 fprintf_filtered (stream, "%s ", opcode->name);
185 for (s = opcode->args; *s != '\0'; ++s)
186 {
187 switch (*s)
188 {
189 case 'a':
190 print_general (insn8, stream);
191 break;
192
193 case 'b':
194 print_general (insn0, stream);
195 break;
196
197 case 'c':
198 print_general (insn16, stream);
199 break;
200
201 case 'i':
202 fprintf_filtered (stream, "%d", insn0);
203 break;
204
205 case 'x':
206 fprintf_filtered (stream, "%d", (insn16 << 8) + insn0);
207 break;
208
209 case 'h':
210 fprintf_filtered (stream, "0x%x",
211 (insn16 << 24) + (insn0 << 16));
212 break;
213
214 case 'X':
215 fprintf_filtered (stream, "%d",
216 ((insn16 << 8) + insn0) | 0xffff0000);
217 break;
218
219 case 'P':
220 /* This output looks just like absolute addressing, but
221 maybe that's OK (it's what the GDB 68k and EBMON
222 29k disassemblers do). */
223 /* All the shifting is to sign-extend it. p*/
224 print_address
225 (memaddr +
226 (((int)((insn16 << 10) + (insn0 << 2)) << 14) >> 14),
227 stream);
228 break;
229
230 case 'A':
231 print_address ((insn16 << 10) + (insn0 << 2), stream);
232 break;
233
234 case 'e':
235 fprintf_filtered (stream, "%d", insn16 >> 7);
236 break;
237
238 case 'n':
239 fprintf_filtered (stream, "0x%x", insn16 & 0x7f);
240 break;
241
242 case 'v':
243 fprintf_filtered (stream, "%x", insn16);
244 break;
245
246 case 's':
247 print_special (insn8, stream);
248 break;
249
250 case 'u':
251 fprintf_filtered (stream, "%d", insn0 >> 7);
252 break;
253
254 case 'r':
255 fprintf_filtered (stream, "%d", (insn0 >> 4) & 7);
256 break;
257
258 case 'd':
259 fprintf_filtered (stream, "%d", (insn0 >> 2) & 3);
260 break;
261
262 case 'f':
263 fprintf_filtered (stream, "%d", insn0 & 3);
264 break;
265
266 case 'F':
66f3e594 267 fprintf_filtered (stream, "%d", (value >> 18) & 0xf);
2013f9b4
SC
268 break;
269
270 case 'C':
66f3e594 271 fprintf_filtered (stream, "%d", (value >> 16) & 3);
2013f9b4
SC
272 break;
273
274 default:
275 fprintf_filtered (stream, "%c", *s);
276 }
277 }
278
279 /* Now we look for a const,consth pair of instructions,
280 in which case we try to print the symbolic address. */
281 if (insn24 == 2) /* consth */
282 {
283 int errcode;
284 char prev_insn[4];
285 unsigned char prev_insn0, prev_insn8, prev_insn16, prev_insn24;
286
287#ifdef GDB
288 errcode = target_read_memory (memaddr - 4,
289 &prev_insn[0],
290 4);
291#else
292 prev_insn[0] = ((char*)buffer)[0-4];
293 prev_insn[1] = ((char*)buffer)[1-4];
294 prev_insn[2] = ((char*)buffer)[2-4];
295 prev_insn[3] = ((char*)buffer)[3-4];
296 errcode = 0;
297#endif
298 if (errcode == 0)
299 {
300 /* If it is a delayed branch, we need to look at the
301 instruction before the delayed brach to handle
302 things like
303
304 const _foo
305 call _printf
306 consth _foo
307 */
308 find_bytes (prev_insn, &prev_insn0, &prev_insn8,
309 &prev_insn16, &prev_insn24);
310 if (is_delayed_branch (prev_insn24))
311 {
312#ifdef GDB
313 errcode = target_read_memory
314 (memaddr - 8, &prev_insn[0], 4);
315#else
316 prev_insn[0] = ((char*)buffer)[0-8];
317 prev_insn[1] = ((char*)buffer)[1-8];
318 prev_insn[2] = ((char*)buffer)[2-8];
319 prev_insn[3] = ((char*)buffer)[3-8];
320 errcode = 0;
321#endif
322 find_bytes (prev_insn, &prev_insn0, &prev_insn8,
323 &prev_insn16, &prev_insn24);
324 }
325 }
326
327 /* If there was a problem reading memory, then assume
328 the previous instruction was not const. */
329 if (errcode == 0)
330 {
331 /* Is it const to the same register? */
332 if (prev_insn24 == 3
333 && prev_insn8 == insn8)
334 {
335 fprintf_filtered (stream, "\t; ");
336 print_address (((insn16 << 24) + (insn0 << 16)
337 + (prev_insn16 << 8) + (prev_insn0)),
338 stream);
339 }
340 }
341 }
342
343 return 4;
344 }
345 }
346 fprintf_filtered (stream, ".word %8x",
347 (insn24 << 24) + (insn16 << 16) + (insn8 << 8) + insn0);
348 return 4;
349}
This page took 0.067813 seconds and 4 git commands to generate.