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