1 /* Print IBM RS/6000 instructions for GNU software.
2 Copyright 1991 Free Software Foundation, Inc.
3 Contributed by IBM Corporation.
5 This file is part of GDB and the GNU binutils.
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 2 of the License, or
10 (at your option) any later version.
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; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 #include "opcode/rs6k.h"
24 /* Print the rs6k instruction at address MEMADDR in debugged memory,
25 on STREAM. Returns length of the instruction, in bytes. */
28 print_insn (memaddr, stream)
32 int pop, eop, probable_eop; /* primary and extended opcodes */
34 int best = -1; /* found best opcode index */
36 unsigned int the_insn;
38 read_memory (memaddr, &the_insn, sizeof (the_insn));
39 pop = (unsigned)(the_insn >> 26);
40 min = 0, max = NOPCODES-1;
43 best = (min + max) / 2;
45 /* see if we are running in loops */
50 if (pop < rs6k_ops [best].p_opcode)
53 else if (pop > rs6k_ops [best].p_opcode)
57 /* Opcode matched, check extended opcode. */
59 if (rs6k_ops [best].e_opcode == -1) {
60 /* there is no valid extended opcode, what we've got is
65 /* Largest possible value of extended opcode. */
66 probable_eop = ((the_insn) >> 1) & 0x3ff;
68 eop = probable_eop & eopMask [rs6k_ops [best].format];
70 if (eop < rs6k_ops [best].e_opcode) {
72 while (pop == rs6k_ops [best].p_opcode) {
73 if (eop == rs6k_ops [best].e_opcode) /* found it! */
76 eop = probable_eop & eopMask [rs6k_ops [best].format];
81 else if (eop > rs6k_ops [best].e_opcode) {
83 while (pop == rs6k_ops [best].p_opcode) {
84 if (eop == rs6k_ops [best].e_opcode) /* found it! */
87 eop = probable_eop & eopMask [rs6k_ops [best].format];
92 else /* eop == rs6k_ops [best].e_opcode */
98 if (pop == rs6k_ops [best].p_opcode &&
99 (rs6k_ops [best].e_opcode == -1 || rs6k_ops [best].e_opcode == eop))
107 print_operator (stream, memaddr, the_insn, best);
111 fprintf (stream, "0x%08x", the_insn);
117 /* condition code names */
118 static char *cond_code [] = {
119 "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", "nl", "ng", "z", "nz" };
122 print_operator (stream, memaddr, insn_word, insn_no)
130 char *pp = rs6k_ops[insn_no].opr_ext;
132 int nocomma = 0; /* true if no comma needed */
149 if ((insn_word & 0x03e00000) == 0x01800000)
154 if ((insn_word & 0x03e00000) == 0x00800000)
164 if (insn_word & 0x4000)
168 case '1': /* exception #1 for bb/bc ambiguity */
169 tmp = (insn_word >> 21) & 0x1f; /* extract BO */
170 if (tmp != 0xc && tmp != 0x4) {
171 /* you can't use `bb' now. switch to `bc' */
174 pp = rs6k_ops[insn_no].opr_ext;
187 fprintf (stream, "%s%s\t", rs6k_ops[insn_no].operator, buf);
189 /* parse the operand now. */
190 pp = rs6k_ops[insn_no].oprnd_format;
195 fprintf (stream, "%d", (insn_word >> 21) & 0x1f);
200 fprintf (stream, "r%d", (insn_word >> 21) & 0x1f);
204 tmp = (insn_word >> 16) & 0x1f;
206 fprintf (stream, "{unknown cond code: 0x%x}", insn_word);
209 fprintf (stream, "%s", cond_code [tmp]);
214 tmp = (insn_word & 0xfffc);
215 if (tmp & 0x8000) /* fix sign extension */
218 if ((insn_word & 0x2) == 0) /* if AA not set */
221 print_address (tmp, stream);
225 tmp = insn_word & 0x03fffffc;
229 if ((insn_word & 0x2) == 0) /* if no AA bit set */
232 print_address (tmp, stream);
235 case LEV : /* for svc only */
236 if (insn_word & 0x2) { /* SA is set */
240 fprintf (stream, "%d", (insn_word >> 5) & 0x7f);
243 case FL1 : /* for svc only */
244 if (insn_word & 0x2) { /* SA is set */
248 fprintf (stream, "%d", (insn_word >> 12) & 0xf);
251 case FL2 : /* for svc only */
253 if (insn_word & 0x2) /* SA is set */
254 fprintf (stream, "%d", (insn_word >> 2) & 0x3fff);
256 fprintf (stream, "%d", (insn_word >> 2) & 0x7);
261 fprintf (stream, "r%d)", (insn_word >> 16) & 0x1f);
265 fprintf (stream, "r%d", (insn_word >> 16) & 0x1f);
269 fprintf (stream, "r%d", (insn_word >> 11) & 0x1f);
273 tmp = insn_word & 0xffff;
276 fprintf (stream, "%d", tmp);
280 fprintf (stream, "%d", insn_word & 0xffff);
284 fprintf (stream, "%d", (insn_word >> 23) & 0x7);
288 fprintf (stream, "%d", (insn_word >> 18) & 0x7);
292 fprintf (stream, "%d", (insn_word >> 21) & 0x1f);
296 fprintf (stream, "%d", (insn_word >> 16) & 0x1f);
300 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
304 fprintf (stream, "%d", (insn_word >> 21) & 0x1f);
308 fprintf (stream, "%d", (insn_word >> 16) & 0x1f);
312 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
316 fprintf (stream, "0x%x", (insn_word >> 6) & 0x1f);
320 fprintf (stream, "0x%x", (insn_word >> 1) & 0x1f);
324 fprintf (stream, "%d", (insn_word >> 16) & 0x1f);
329 tmp = insn_word & 0xffff;
332 fprintf (stream, "%d(", tmp);
336 fprintf (stream, "0x%x", (insn_word >> 12) & 0xff);
341 fprintf (stream, "f%d", (insn_word >> 21) & 0x1f);
345 fprintf (stream, "f%d", (insn_word >> 16) & 0x1f);
349 fprintf (stream, "f%d", (insn_word >> 11) & 0x1f);
353 fprintf (stream, "f%d", (insn_word >> 6) & 0x1f);
357 fprintf (stream, "0x%x", (insn_word >> 17) & 0xff);
361 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
365 fprintf (stream, "%d", (insn_word >> 12) & 0xf);
370 "{Internal error: Unknown operand format identifier %d}",