* eval.c (evaluate_struct_tuple): Fix thinko.
[deliverable/binutils-gdb.git] / opcodes / a29k-dis.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
720b3aed
JK
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
2013f9b4
SC
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
720b3aed 18along with this program; if not, write to the Free Software
943fbd5b 19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
2013f9b4 20
720b3aed
JK
21#include "dis-asm.h"
22#include "opcode/a29k.h"
2013f9b4
SC
23
24/* Print a symbolic representation of a general-purpose
25 register number NUM on STREAM.
26 NUM is a number as found in the instruction, not as found in
27 debugging symbols; it must be in the range 0-255. */
28static void
720b3aed 29print_general (num, info)
2013f9b4 30 int num;
720b3aed 31 struct disassemble_info *info;
2013f9b4
SC
32{
33 if (num < 128)
720b3aed 34 (*info->fprintf_func) (info->stream, "gr%d", num);
2013f9b4 35 else
720b3aed 36 (*info->fprintf_func) (info->stream, "lr%d", num - 128);
2013f9b4
SC
37}
38
39/* Like print_general but a special-purpose register.
40
41 The mnemonics used by the AMD assembler are not quite the same
42 as the ones in the User's Manual. We use the ones that the
43 assembler uses. */
44static void
720b3aed 45print_special (num, info)
a3cf92e5 46 unsigned int num;
720b3aed 47 struct disassemble_info *info;
2013f9b4
SC
48{
49 /* Register names of registers 0-SPEC0_NUM-1. */
50 static char *spec0_names[] = {
51 "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr",
009946c9
ILT
52 "pc0", "pc1", "pc2", "mmu", "lru", "rsn", "rma0", "rmc0", "rma1", "rmc1",
53 "spc0", "spc1", "spc2", "iba0", "ibc0", "iba1", "ibc1", "dba", "dbc",
54 "cir", "cdr"
2013f9b4
SC
55 };
56#define SPEC0_NUM ((sizeof spec0_names) / (sizeof spec0_names[0]))
57
58 /* Register names of registers 128-128+SPEC128_NUM-1. */
59 static char *spec128_names[] = {
60 "ipc", "ipa", "ipb", "q", "alu", "bp", "fc", "cr"
61 };
62#define SPEC128_NUM ((sizeof spec128_names) / (sizeof spec128_names[0]))
63
64 /* Register names of registers 160-160+SPEC160_NUM-1. */
65 static char *spec160_names[] = {
66 "fpe", "inte", "fps", "sr163", "exop"
67 };
68#define SPEC160_NUM ((sizeof spec160_names) / (sizeof spec160_names[0]))
69
70 if (num < SPEC0_NUM)
720b3aed 71 (*info->fprintf_func) (info->stream, spec0_names[num]);
2013f9b4 72 else if (num >= 128 && num < 128 + SPEC128_NUM)
720b3aed 73 (*info->fprintf_func) (info->stream, spec128_names[num-128]);
2013f9b4 74 else if (num >= 160 && num < 160 + SPEC160_NUM)
720b3aed 75 (*info->fprintf_func) (info->stream, spec160_names[num-160]);
2013f9b4 76 else
720b3aed 77 (*info->fprintf_func) (info->stream, "sr%d", num);
2013f9b4
SC
78}
79
80/* Is an instruction with OPCODE a delayed branch? */
81static int
82is_delayed_branch (opcode)
83 int opcode;
84{
85 return (opcode == 0xa8 || opcode == 0xa9 || opcode == 0xa0 || opcode == 0xa1
86 || opcode == 0xa4 || opcode == 0xa5
87 || opcode == 0xb4 || opcode == 0xb5
88 || opcode == 0xc4 || opcode == 0xc0
89 || opcode == 0xac || opcode == 0xad
90 || opcode == 0xcc);
91}
92
720b3aed 93/* Now find the four bytes of INSN and put them in *INSN{0,8,16,24}. */
2013f9b4 94static void
720b3aed 95find_bytes_big (insn, insn0, insn8, insn16, insn24)
2013f9b4
SC
96 char *insn;
97 unsigned char *insn0;
98 unsigned char *insn8;
99 unsigned char *insn16;
100 unsigned char *insn24;
101{
2013f9b4
SC
102 *insn24 = insn[0];
103 *insn16 = insn[1];
104 *insn8 = insn[2];
105 *insn0 = insn[3];
720b3aed
JK
106}
107
108static void
109find_bytes_little (insn, insn0, insn8, insn16, insn24)
110 char *insn;
111 unsigned char *insn0;
112 unsigned char *insn8;
113 unsigned char *insn16;
114 unsigned char *insn24;
115{
2013f9b4
SC
116 *insn24 = insn[3];
117 *insn16 = insn[2];
118 *insn8 = insn[1];
119 *insn0 = insn[0];
2013f9b4
SC
120}
121
720b3aed
JK
122typedef (*find_byte_func_type)
123 PARAMS ((char *, unsigned char *, unsigned char *,
124 unsigned char *, unsigned char *));
125
4b2febd3 126/* Print one instruction from MEMADDR on INFO->STREAM.
720b3aed 127 Return the size of the instruction (always 4 on a29k). */
4b2febd3 128
720b3aed
JK
129static int
130print_insn (memaddr, info)
2013f9b4 131 bfd_vma memaddr;
720b3aed 132 struct disassemble_info *info;
2013f9b4
SC
133{
134 /* The raw instruction. */
135 char insn[4];
136
137 /* The four bytes of the instruction. */
138 unsigned char insn24, insn16, insn8, insn0;
2013f9b4 139
720b3aed
JK
140 find_byte_func_type find_byte_func = (find_byte_func_type)info->private_data;
141
e9aff87e 142 struct a29k_opcode CONST * opcode;
2013f9b4 143
720b3aed
JK
144 {
145 int status =
0e57a495 146 (*info->read_memory_func) (memaddr, (bfd_byte *) &insn[0], 4, info);
720b3aed
JK
147 if (status != 0)
148 {
149 (*info->memory_error_func) (status, memaddr, info);
150 return -1;
151 }
152 }
153
154 (*find_byte_func) (insn, &insn0, &insn8, &insn16, &insn24);
2013f9b4 155
e96a2b1d
ILT
156 printf ("%02x%02x%02x%02x ", insn24, insn16, insn8, insn0);
157
2013f9b4
SC
158 /* Handle the nop (aseq 0x40,gr1,gr1) specially */
159 if ((insn24==0x70) && (insn16==0x40) && (insn8==0x01) && (insn0==0x01)) {
720b3aed 160 (*info->fprintf_func) (info->stream,"nop");
2013f9b4
SC
161 return 4;
162 }
163
2013f9b4 164 /* The opcode is always in insn24. */
720b3aed
JK
165 for (opcode = &a29k_opcodes[0];
166 opcode < &a29k_opcodes[num_opcodes];
2013f9b4
SC
167 ++opcode)
168 {
a3cf92e5 169 if (((unsigned long) insn24 << 24) == opcode->opcode)
2013f9b4
SC
170 {
171 char *s;
172
720b3aed 173 (*info->fprintf_func) (info->stream, "%s ", opcode->name);
2013f9b4
SC
174 for (s = opcode->args; *s != '\0'; ++s)
175 {
176 switch (*s)
177 {
178 case 'a':
720b3aed 179 print_general (insn8, info);
2013f9b4
SC
180 break;
181
182 case 'b':
720b3aed 183 print_general (insn0, info);
2013f9b4
SC
184 break;
185
186 case 'c':
720b3aed 187 print_general (insn16, info);
2013f9b4
SC
188 break;
189
190 case 'i':
720b3aed 191 (*info->fprintf_func) (info->stream, "%d", insn0);
2013f9b4
SC
192 break;
193
194 case 'x':
ab678720 195 (*info->fprintf_func) (info->stream, "0x%x", (insn16 << 8) + insn0);
2013f9b4
SC
196 break;
197
198 case 'h':
720b3aed
JK
199 /* This used to be %x for binutils. */
200 (*info->fprintf_func) (info->stream, "0x%x",
2013f9b4
SC
201 (insn16 << 24) + (insn0 << 16));
202 break;
203
204 case 'X':
720b3aed 205 (*info->fprintf_func) (info->stream, "%d",
2013f9b4
SC
206 ((insn16 << 8) + insn0) | 0xffff0000);
207 break;
208
209 case 'P':
210 /* This output looks just like absolute addressing, but
720b3aed
JK
211 maybe that's OK (it's what the GDB m68k and EBMON
212 a29k disassemblers do). */
2013f9b4 213 /* All the shifting is to sign-extend it. p*/
720b3aed 214 (*info->print_address_func)
2013f9b4
SC
215 (memaddr +
216 (((int)((insn16 << 10) + (insn0 << 2)) << 14) >> 14),
720b3aed 217 info);
2013f9b4
SC
218 break;
219
220 case 'A':
720b3aed
JK
221 (*info->print_address_func)
222 ((insn16 << 10) + (insn0 << 2), info);
2013f9b4
SC
223 break;
224
225 case 'e':
720b3aed 226 (*info->fprintf_func) (info->stream, "%d", insn16 >> 7);
2013f9b4
SC
227 break;
228
229 case 'n':
720b3aed 230 (*info->fprintf_func) (info->stream, "0x%x", insn16 & 0x7f);
2013f9b4
SC
231 break;
232
233 case 'v':
720b3aed 234 (*info->fprintf_func) (info->stream, "0x%x", insn16);
2013f9b4
SC
235 break;
236
237 case 's':
720b3aed 238 print_special (insn8, info);
2013f9b4
SC
239 break;
240
241 case 'u':
720b3aed 242 (*info->fprintf_func) (info->stream, "%d", insn0 >> 7);
2013f9b4
SC
243 break;
244
245 case 'r':
720b3aed 246 (*info->fprintf_func) (info->stream, "%d", (insn0 >> 4) & 7);
2013f9b4
SC
247 break;
248
009946c9
ILT
249 case 'I':
250 if ((insn16 & 3) != 0)
251 (*info->fprintf_func) (info->stream, "%d", insn16 & 3);
252 break;
253
2013f9b4 254 case 'd':
720b3aed 255 (*info->fprintf_func) (info->stream, "%d", (insn0 >> 2) & 3);
2013f9b4
SC
256 break;
257
258 case 'f':
720b3aed 259 (*info->fprintf_func) (info->stream, "%d", insn0 & 3);
2013f9b4
SC
260 break;
261
262 case 'F':
720b3aed 263 (*info->fprintf_func) (info->stream, "%d", (insn16 >> 2) & 15);
2013f9b4
SC
264 break;
265
266 case 'C':
720b3aed 267 (*info->fprintf_func) (info->stream, "%d", insn16 & 3);
2013f9b4
SC
268 break;
269
270 default:
720b3aed 271 (*info->fprintf_func) (info->stream, "%c", *s);
2013f9b4
SC
272 }
273 }
274
275 /* Now we look for a const,consth pair of instructions,
276 in which case we try to print the symbolic address. */
277 if (insn24 == 2) /* consth */
278 {
279 int errcode;
280 char prev_insn[4];
281 unsigned char prev_insn0, prev_insn8, prev_insn16, prev_insn24;
282
720b3aed 283 errcode = (*info->read_memory_func) (memaddr - 4,
0e57a495 284 (bfd_byte *) &prev_insn[0],
720b3aed
JK
285 4,
286 info);
2013f9b4
SC
287 if (errcode == 0)
288 {
289 /* If it is a delayed branch, we need to look at the
290 instruction before the delayed brach to handle
291 things like
292
293 const _foo
294 call _printf
295 consth _foo
296 */
720b3aed
JK
297 (*find_byte_func) (prev_insn, &prev_insn0, &prev_insn8,
298 &prev_insn16, &prev_insn24);
2013f9b4
SC
299 if (is_delayed_branch (prev_insn24))
300 {
720b3aed 301 errcode = (*info->read_memory_func)
0e57a495 302 (memaddr - 8, (bfd_byte *) &prev_insn[0], 4, info);
720b3aed
JK
303 (*find_byte_func) (prev_insn, &prev_insn0, &prev_insn8,
304 &prev_insn16, &prev_insn24);
2013f9b4
SC
305 }
306 }
307
308 /* If there was a problem reading memory, then assume
309 the previous instruction was not const. */
310 if (errcode == 0)
311 {
312 /* Is it const to the same register? */
313 if (prev_insn24 == 3
314 && prev_insn8 == insn8)
315 {
720b3aed
JK
316 (*info->fprintf_func) (info->stream, "\t; ");
317 (*info->print_address_func)
318 (((insn16 << 24) + (insn0 << 16)
319 + (prev_insn16 << 8) + (prev_insn0)),
320 info);
2013f9b4
SC
321 }
322 }
323 }
324
325 return 4;
326 }
327 }
720b3aed
JK
328 /* This used to be %8x for binutils. */
329 (*info->fprintf_func)
d75a406d 330 (info->stream, ".word 0x%08x",
720b3aed 331 (insn24 << 24) + (insn16 << 16) + (insn8 << 8) + insn0);
2013f9b4
SC
332 return 4;
333}
720b3aed
JK
334
335/* Disassemble an big-endian a29k instruction. */
336int
337print_insn_big_a29k (memaddr, info)
338 bfd_vma memaddr;
339 struct disassemble_info *info;
340{
341 info->private_data = (PTR) find_bytes_big;
342 return print_insn (memaddr, info);
343}
344
345/* Disassemble a little-endian a29k instruction. */
346int
347print_insn_little_a29k (memaddr, info)
348 bfd_vma memaddr;
349 struct disassemble_info *info;
350{
351 info->private_data = (PTR) find_bytes_little;
352 return print_insn (memaddr, info);
353}
This page took 0.159788 seconds and 4 git commands to generate.