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 value
= (insn24
<< 24) + (insn16
<< 16) + (insn8
<< 8) + insn0
;
164 /* Handle the nop (aseq 0x40,gr1,gr1) specially */
165 if ((insn24
==0x70) && (insn16
==0x40) && (insn8
==0x01) && (insn0
==0x01)) {
166 fprintf_filtered (stream
,"nop");
171 /* The opcode is always in insn24. */
172 for (opcode
= &am29k_opcodes
[0];
173 opcode
< &am29k_opcodes
[NUM_OPCODES
];
177 if (insn24
== opcode
->opcode
)
179 if (insn24
== (opcode
->opcode
>> 24))
184 fprintf_filtered (stream
, "%s ", opcode
->name
);
185 for (s
= opcode
->args
; *s
!= '\0'; ++s
)
190 print_general (insn8
, stream
);
194 print_general (insn0
, stream
);
198 print_general (insn16
, stream
);
202 fprintf_filtered (stream
, "%d", insn0
);
206 fprintf_filtered (stream
, "%d", (insn16
<< 8) + insn0
);
210 fprintf_filtered (stream
, "0x%x",
211 (insn16
<< 24) + (insn0
<< 16));
215 fprintf_filtered (stream
, "%d",
216 ((insn16
<< 8) + insn0
) | 0xffff0000);
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*/
226 (((int)((insn16
<< 10) + (insn0
<< 2)) << 14) >> 14),
231 print_address ((insn16
<< 10) + (insn0
<< 2), stream
);
235 fprintf_filtered (stream
, "%d", insn16
>> 7);
239 fprintf_filtered (stream
, "0x%x", insn16
& 0x7f);
243 fprintf_filtered (stream
, "%x", insn16
);
247 print_special (insn8
, stream
);
251 fprintf_filtered (stream
, "%d", insn0
>> 7);
255 fprintf_filtered (stream
, "%d", (insn0
>> 4) & 7);
259 fprintf_filtered (stream
, "%d", (insn0
>> 2) & 3);
263 fprintf_filtered (stream
, "%d", insn0
& 3);
267 fprintf_filtered (stream
, "%d", (value
>> 18) & 0xf);
271 fprintf_filtered (stream
, "%d", (value
>> 16) & 3);
275 fprintf_filtered (stream
, "%c", *s
);
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 */
285 unsigned char prev_insn0
, prev_insn8
, prev_insn16
, prev_insn24
;
288 errcode
= target_read_memory (memaddr
- 4,
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];
300 /* If it is a delayed branch, we need to look at the
301 instruction before the delayed brach to handle
308 find_bytes (prev_insn
, &prev_insn0
, &prev_insn8
,
309 &prev_insn16
, &prev_insn24
);
310 if (is_delayed_branch (prev_insn24
))
313 errcode
= target_read_memory
314 (memaddr
- 8, &prev_insn
[0], 4);
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];
322 find_bytes (prev_insn
, &prev_insn0
, &prev_insn8
,
323 &prev_insn16
, &prev_insn24
);
327 /* If there was a problem reading memory, then assume
328 the previous instruction was not const. */
331 /* Is it const to the same register? */
333 && prev_insn8
== insn8
)
335 fprintf_filtered (stream
, "\t; ");
336 print_address (((insn16
<< 24) + (insn0
<< 16)
337 + (prev_insn16
<< 8) + (prev_insn0
)),
346 fprintf_filtered (stream
, ".word %8x",
347 (insn24
<< 24) + (insn16
<< 16) + (insn8
<< 8) + insn0
);
This page took 0.037404 seconds and 4 git commands to generate.