New targets binutils.mm, binutils.me
[deliverable/binutils-gdb.git] / binutils / am29k-pinsn.c
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
5 This file is part of GDB.
6
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)
10 any later version.
11
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.
16
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. */
20
21 #include <stdio.h>
22
23 #ifdef GDB
24 # include "defs.h"
25 # include "target.h"
26 # include "am29k-opcode.h"
27 #else
28 # include "bfd.h"
29 # include "sysdep.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
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. */
42 static void
43 print_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. */
58 static void
59 print_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? */
93 static int
94 is_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. */
109 static void
110 find_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
133 print_insn (memaddr, stream)
134 CORE_ADDR memaddr;
135 FILE *stream;
136 #else
137 int
138 print_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;
149
150 CONST struct am29k_opcode *opcode;
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
163 /* Handle the nop (aseq 0x40,gr1,gr1) specially */
164 if ((insn24==0x70) && (insn16==0x40) && (insn8==0x01) && (insn0==0x01)) {
165 fprintf_filtered (stream,"nop");
166 return 4;
167 }
168
169
170 /* The opcode is always in insn24. */
171 for (opcode = &am29k_opcodes[0];
172 opcode < &am29k_opcodes[NUM_OPCODES];
173 ++opcode)
174 {
175 #ifdef GDB
176 if (insn24 == opcode->opcode)
177 #else
178 if (insn24 == (opcode->opcode >> 24))
179 #endif
180 {
181 char *s;
182
183 fprintf_filtered (stream, "%s ", opcode->name);
184 for (s = opcode->args; *s != '\0'; ++s)
185 {
186 switch (*s)
187 {
188 case 'a':
189 print_general (insn8, stream);
190 break;
191
192 case 'b':
193 print_general (insn0, stream);
194 break;
195
196 case 'c':
197 print_general (insn16, stream);
198 break;
199
200 case 'i':
201 fprintf_filtered (stream, "%d", insn0);
202 break;
203
204 case 'x':
205 fprintf_filtered (stream, "%d", (insn16 << 8) + insn0);
206 break;
207
208 case 'h':
209 fprintf_filtered (stream, "0x%x",
210 (insn16 << 24) + (insn0 << 16));
211 break;
212
213 case 'X':
214 fprintf_filtered (stream, "%d",
215 ((insn16 << 8) + insn0) | 0xffff0000);
216 break;
217
218 case 'P':
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*/
223 print_address
224 (memaddr +
225 (((int)((insn16 << 10) + (insn0 << 2)) << 14) >> 14),
226 stream);
227 break;
228
229 case 'A':
230 print_address ((insn16 << 10) + (insn0 << 2), stream);
231 break;
232
233 case 'e':
234 fprintf_filtered (stream, "%d", insn16 >> 7);
235 break;
236
237 case 'n':
238 fprintf_filtered (stream, "0x%x", insn16 & 0x7f);
239 break;
240
241 case 'v':
242 fprintf_filtered (stream, "%x", insn16);
243 break;
244
245 case 's':
246 print_special (insn8, stream);
247 break;
248
249 case 'u':
250 fprintf_filtered (stream, "%d", insn0 >> 7);
251 break;
252
253 case 'r':
254 fprintf_filtered (stream, "%d", (insn0 >> 4) & 7);
255 break;
256
257 case 'd':
258 fprintf_filtered (stream, "%d", (insn0 >> 2) & 3);
259 break;
260
261 case 'f':
262 fprintf_filtered (stream, "%d", insn0 & 3);
263 break;
264
265 case 'F':
266 fprintf_filtered (stream, "%d", (insn0 >> 18) & 15);
267 break;
268
269 case 'C':
270 fprintf_filtered (stream, "%d", (insn0 >> 16) & 3);
271 break;
272
273 default:
274 fprintf_filtered (stream, "%c", *s);
275 }
276 }
277
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 */
281 {
282 int errcode;
283 char prev_insn[4];
284 unsigned char prev_insn0, prev_insn8, prev_insn16, prev_insn24;
285
286 #ifdef GDB
287 errcode = target_read_memory (memaddr - 4,
288 &prev_insn[0],
289 4);
290 #else
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];
295 errcode = 0;
296 #endif
297 if (errcode == 0)
298 {
299 /* If it is a delayed branch, we need to look at the
300 instruction before the delayed brach to handle
301 things like
302
303 const _foo
304 call _printf
305 consth _foo
306 */
307 find_bytes (prev_insn, &prev_insn0, &prev_insn8,
308 &prev_insn16, &prev_insn24);
309 if (is_delayed_branch (prev_insn24))
310 {
311 #ifdef GDB
312 errcode = target_read_memory
313 (memaddr - 8, &prev_insn[0], 4);
314 #else
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];
319 errcode = 0;
320 #endif
321 find_bytes (prev_insn, &prev_insn0, &prev_insn8,
322 &prev_insn16, &prev_insn24);
323 }
324 }
325
326 /* If there was a problem reading memory, then assume
327 the previous instruction was not const. */
328 if (errcode == 0)
329 {
330 /* Is it const to the same register? */
331 if (prev_insn24 == 3
332 && prev_insn8 == insn8)
333 {
334 fprintf_filtered (stream, "\t; ");
335 print_address (((insn16 << 24) + (insn0 << 16)
336 + (prev_insn16 << 8) + (prev_insn0)),
337 stream);
338 }
339 }
340 }
341
342 return 4;
343 }
344 }
345 fprintf_filtered (stream, ".word %8x",
346 (insn24 << 24) + (insn16 << 16) + (insn8 << 8) + insn0);
347 return 4;
348 }
This page took 0.037695 seconds and 4 git commands to generate.