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. */
25 #include "am29k-opcode.h"
27 /* Print a symbolic representation of a general-purpose
28 register number NUM on STREAM.
29 NUM is a number as found in the instruction, not as found in
30 debugging symbols; it must be in the range 0-255. */
32 print_general (num
, stream
)
37 fprintf_filtered (stream
, "gr%d", num
);
39 fprintf_filtered (stream
, "lr%d", num
- 128);
42 /* Like print_general but a special-purpose register.
44 The mnemonics used by the AMD assembler are not quite the same
45 as the ones in the User's Manual. We use the ones that the
48 print_special (num
, stream
)
52 /* Register names of registers 0-SPEC0_NUM-1. */
53 static char *spec0_names
[] = {
54 "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr",
55 "pc0", "pc1", "pc2", "mmu", "lru"
57 #define SPEC0_NUM ((sizeof spec0_names) / (sizeof spec0_names[0]))
59 /* Register names of registers 128-128+SPEC128_NUM-1. */
60 static char *spec128_names
[] = {
61 "ipc", "ipa", "ipb", "q", "alu", "bp", "fc", "cr"
63 #define SPEC128_NUM ((sizeof spec128_names) / (sizeof spec128_names[0]))
65 /* Register names of registers 160-160+SPEC160_NUM-1. */
66 static char *spec160_names
[] = {
67 "fpe", "inte", "fps", "sr163", "exop"
69 #define SPEC160_NUM ((sizeof spec160_names) / (sizeof spec160_names[0]))
72 fprintf_filtered (stream
, spec0_names
[num
]);
73 else if (num
>= 128 && num
< 128 + SPEC128_NUM
)
74 fprintf_filtered (stream
, spec128_names
[num
-128]);
75 else if (num
>= 160 && num
< 160 + SPEC160_NUM
)
76 fprintf_filtered (stream
, spec160_names
[num
-160]);
78 fprintf_filtered (stream
, "sr%d", num
);
81 /* Is an instruction with OPCODE a delayed branch? */
83 is_delayed_branch (opcode
)
86 return (opcode
== 0xa8 || opcode
== 0xa9 || opcode
== 0xa0 || opcode
== 0xa1
87 || opcode
== 0xa4 || opcode
== 0xa5
88 || opcode
== 0xb4 || opcode
== 0xb5
89 || opcode
== 0xc4 || opcode
== 0xc0
90 || opcode
== 0xac || opcode
== 0xad
94 /* Now find the four bytes of INSN and put them in *INSN{0,8,16,24}.
95 Note that the amd can be set up as either
96 big or little-endian (the tm file says which) and we can't assume
97 the host machine is the same. */
99 find_bytes (insn
, insn0
, insn8
, insn16
, insn24
)
101 unsigned char *insn0
;
102 unsigned char *insn8
;
103 unsigned char *insn16
;
104 unsigned char *insn24
;
106 #if TARGET_BYTE_ORDER == BIG_ENDIAN
111 #else /* Little-endian. */
116 #endif /* Little-endian. */
119 /* Print one instruction from MEMADDR on STREAM.
120 Return the size of the instruction (always 4 on am29k). */
122 print_insn (memaddr
, stream
)
126 /* The raw instruction. */
129 /* The four bytes of the instruction. */
130 unsigned char insn24
, insn16
, insn8
, insn0
;
132 struct am29k_opcode
*opcode
;
134 read_memory (memaddr
, &insn
[0], 4);
136 find_bytes (insn
, &insn0
, &insn8
, &insn16
, &insn24
);
138 /* The opcode is always in insn24. */
139 for (opcode
= &am29k_opcodes
[0];
140 opcode
< &am29k_opcodes
[NUM_OPCODES
];
143 if (insn24
== opcode
->opcode
)
147 fprintf_filtered (stream
, "%s ", opcode
->name
);
148 for (s
= opcode
->args
; *s
!= '\0'; ++s
)
153 print_general (insn8
, stream
);
157 print_general (insn0
, stream
);
161 print_general (insn16
, stream
);
165 fprintf_filtered (stream
, "%d", insn0
);
169 fprintf_filtered (stream
, "%d", (insn16
<< 8) + insn0
);
173 fprintf_filtered (stream
, "0x%x",
174 (insn16
<< 24) + (insn0
<< 16));
178 fprintf_filtered (stream
, "%d",
179 ((insn16
<< 8) + insn0
) | 0xffff0000);
183 /* This output looks just like absolute addressing, but
184 maybe that's OK (it's what the GDB 68k and EBMON
185 29k disassemblers do). */
186 /* All the shifting is to sign-extend it. p*/
189 (((int)((insn16
<< 10) + (insn0
<< 2)) << 14) >> 14),
194 print_address ((insn16
<< 10) + (insn0
<< 2), stream
);
198 fprintf_filtered (stream
, "%d", insn16
>> 7);
202 fprintf_filtered (stream
, "0x%x", insn16
& 0x7f);
206 fprintf_filtered (stream
, "%#x", insn16
);
210 print_special (insn8
, stream
);
214 fprintf_filtered (stream
, "%d", insn0
>> 7);
218 fprintf_filtered (stream
, "%d", (insn0
>> 4) & 7);
222 fprintf_filtered (stream
, "%d", (insn0
>> 2) & 3);
226 fprintf_filtered (stream
, "%d", insn0
& 3);
230 fprintf_filtered (stream
, "%d", (insn0
>> 18) & 15);
234 fprintf_filtered (stream
, "%d", (insn0
>> 16) & 3);
238 fprintf_filtered (stream
, "%c", *s
);
242 /* Now we look for a const,consth pair of instructions,
243 in which case we try to print the symbolic address. */
244 if (insn24
== 2) /* consth */
248 unsigned char prev_insn0
, prev_insn8
, prev_insn16
, prev_insn24
;
250 errcode
= target_read_memory (memaddr
- 4,
255 /* If it is a delayed branch, we need to look at the
256 instruction before the delayed brach to handle
263 find_bytes (prev_insn
, &prev_insn0
, &prev_insn8
,
264 &prev_insn16
, &prev_insn24
);
265 if (is_delayed_branch (prev_insn24
))
267 errcode
= target_read_memory
268 (memaddr
- 8, &prev_insn
[0], 4);
269 find_bytes (prev_insn
, &prev_insn0
, &prev_insn8
,
270 &prev_insn16
, &prev_insn24
);
274 /* If there was a problem reading memory, then assume
275 the previous instruction was not const. */
278 /* Is it const to the same register? */
280 && prev_insn8
== insn8
)
282 fprintf_filtered (stream
, "\t; ");
283 print_address (((insn16
<< 24) + (insn0
<< 16)
284 + (prev_insn16
<< 8) + (prev_insn0
)),
293 fprintf_filtered (stream
, ".word %#8x",
294 (insn24
<< 24) + (insn16
<< 16) + (insn8
<< 8) + insn0
);
This page took 0.035866 seconds and 5 git commands to generate.