/* Print IBM RS/6000 instructions for GNU software.
- Copyright 1991 Free Software Foundation, Inc.
- Contributed by IBM Corporation.
+ Copyright 1991,1994 Free Software Foundation, Inc.
+ Original version was contributed by IBM Corporation.
+ Now we just use the disassembler in the opcodes directory.
-This file is part of GDB and the GNU binutils.
+This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
-#include "opcode/rs6k.h"
+#include "dis-asm.h"
/* Print the rs6k instruction at address MEMADDR in debugged memory,
on STREAM. Returns length of the instruction, in bytes. */
CORE_ADDR memaddr;
GDB_FILE *stream;
{
- int pop, eop, probable_eop; /* primary and extended opcodes */
- int min, max;
- int best = -1; /* found best opcode index */
- int oldbest = -1;
- unsigned int the_insn;
+ disassemble_info info;
- read_memory (memaddr, &the_insn, sizeof (the_insn));
- pop = (unsigned)(the_insn >> 26);
- min = 0, max = NOPCODES-1;
+ GDB_INIT_DISASSEMBLE_INFO (info, stream);
- while (min < max) {
- best = (min + max) / 2;
-
- /* see if we are running in loops */
- if (best == oldbest)
- goto not_found;
- oldbest = best;
-
- if (pop < rs6k_ops [best].p_opcode)
- max = best;
-
- else if (pop > rs6k_ops [best].p_opcode)
- min = best;
-
- else {
- /* Opcode matched, check extended opcode. */
-
- if (rs6k_ops [best].e_opcode == -1) {
- /* there is no valid extended opcode, what we've got is
- just fine. */
- goto insn_found;
- }
-
- /* Largest possible value of extended opcode. */
- probable_eop = ((the_insn) >> 1) & 0x3ff;
-
- eop = probable_eop & eopMask [rs6k_ops [best].format];
-
- if (eop < rs6k_ops [best].e_opcode) {
-
- while (pop == rs6k_ops [best].p_opcode) {
- if (eop == rs6k_ops [best].e_opcode) /* found it! */
- goto insn_found;
- --best;
- eop = probable_eop & eopMask [rs6k_ops [best].format];
- }
- goto not_found;
- }
-
- else if (eop > rs6k_ops [best].e_opcode) {
-
- while (pop == rs6k_ops [best].p_opcode) {
- if (eop == rs6k_ops [best].e_opcode) /* found it! */
- goto insn_found;
- ++best;
- eop = probable_eop & eopMask [rs6k_ops [best].format];
- }
- goto not_found;
- }
-
- else /* eop == rs6k_ops [best].e_opcode */
- goto insn_found;
- }
- }
-
- best = min;
- if (pop == rs6k_ops [best].p_opcode &&
- (rs6k_ops [best].e_opcode == -1 || rs6k_ops [best].e_opcode == eop))
- goto insn_found;
-
- else
- goto not_found;
-
-
-insn_found:
- print_operator (stream, memaddr, the_insn, best);
- return 4;
-
-not_found:
- fprintf_unfiltered (stream, "0x%08x", the_insn);
- return 4;
-}
-
-
-
-/* condition code names */
-static char *cond_code [] = {
- "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", "nl", "ng", "z", "nz" };
-
-
-print_operator (stream, memaddr, insn_word, insn_no)
-FILE *stream;
-long memaddr;
-long insn_word;
-int insn_no;
-{
- char buf [20];
- char *qq = buf;
- char *pp = rs6k_ops[insn_no].opr_ext;
- int tmp;
- int nocomma = 0; /* true if no comma needed */
-
- if (pp) {
- while (*pp) {
-
- switch ( *pp ) {
- case '.':
- if (insn_word & 0x1)
- *qq++ = '.';
- break;
-
- case 'l':
- if (insn_word & 0x1)
- *qq++ = 'l';
- break;
-
- case 't':
- if ((insn_word & 0x03e00000) == 0x01800000)
- *qq++ = 't';
- break;
-
- case 'f':
- if ((insn_word & 0x03e00000) == 0x00800000)
- *qq++ = 'f';
- break;
-
- case 'a':
- if (insn_word & 0x2)
- *qq++ = 'a';
- break;
-
- case 'o':
- if (insn_word & 0x4000)
- *qq++ = 'o';
- break;
-
- case '1': /* exception #1 for bb/bc ambiguity */
- tmp = (insn_word >> 21) & 0x1f; /* extract BO */
- if (tmp != 0xc && tmp != 0x4) {
- /* you can't use `bb' now. switch to `bc' */
- *(qq-1) = 'c';
- ++insn_no;
- pp = rs6k_ops[insn_no].opr_ext;
- continue;
- }
- break;
-
- default:
- abort ();
- }
- ++pp;
- }
- }
- *qq = '\0';
-
- fprintf_unfiltered (stream, "%s%s\t", rs6k_ops[insn_no].operator, buf);
-
- /* parse the operand now. */
- pp = rs6k_ops[insn_no].oprnd_format;
-
- while (*pp != 0) {
- switch (*pp) {
- case TO :
- fprintf_unfiltered (stream, "%d", (insn_word >> 21) & 0x1f);
- break;
-
- case RT :
- case RS :
- fprintf_unfiltered (stream, "r%d", (insn_word >> 21) & 0x1f);
- break;
-
- case LI :
- tmp = (insn_word >> 16) & 0x1f;
-#if 0
- /* This is wrong, wrong, wrong. The condition code only goes
- from 0 to 3 (for the instructions which can use extended
- mnemonics of this type), and the XX (lt, gt, eq etc.) goes
- into the mnemonic, not as an operand.
-
- Probably the best way to get this right in both assembler
- and disassembler is to switch to a match/lose style opcode
- table like the sparc. */
- if (tmp > 11) {
- fprintf_unfiltered (stream, "{unknown cond code: 0x%x}", insn_word);
- tmp = 0;
- }
- fprintf_unfiltered (stream, "%s", cond_code [tmp]);
-#else
- /* So for just always use the "bbf/bbt" form. This is perfectly
- correct, just not necessarily as legible.
-
- If tmp is not in the range 0-3, we can't use an XX form anyway. */
- fprintf_unfiltered (stream, "%d", tmp);
-#endif
- break;
-
- case A2 :
- case TA14 :
- tmp = (insn_word & 0xfffc);
- if (tmp & 0x8000) /* fix sign extension */
- tmp -= 0x10000;
-
- if ((insn_word & 0x2) == 0) /* if AA not set */
- tmp += memaddr;
-
- print_address (tmp, stream);
- break;
-
- case TA24 :
- tmp = insn_word & 0x03fffffc;
- if (tmp & 0x2000000)
- tmp -= 0x4000000;
-
- if ((insn_word & 0x2) == 0) /* if no AA bit set */
- tmp += memaddr;
-
- print_address (tmp, stream);
- break;
-
- case LEV : /* for svc only */
- if (insn_word & 0x2) { /* SA is set */
- nocomma = 1;
- }
- else
- fprintf_unfiltered (stream, "%d", (insn_word >> 5) & 0x7f);
- break;
-
- case FL1 : /* for svc only */
- if (insn_word & 0x2) { /* SA is set */
- nocomma = 1;
- }
- else
- fprintf_unfiltered (stream, "%d", (insn_word >> 12) & 0xf);
- break;
-
- case FL2 : /* for svc only */
- nocomma = 0;
- if (insn_word & 0x2) /* SA is set */
- fprintf_unfiltered (stream, "%d", (insn_word >> 2) & 0x3fff);
- else
- fprintf_unfiltered (stream, "%d", (insn_word >> 2) & 0x7);
- break;
-
- case RA :
- if (nocomma) {
- fprintf_unfiltered (stream, "r%d)", (insn_word >> 16) & 0x1f);
- nocomma = 0;
- }
- else
- fprintf_unfiltered (stream, "r%d", (insn_word >> 16) & 0x1f);
- break;
-
- case RB :
- fprintf_unfiltered (stream, "r%d", (insn_word >> 11) & 0x1f);
- break;
-
- case SI :
- tmp = insn_word & 0xffff;
- if (tmp & 0x8000)
- tmp -= 0x10000;
- fprintf_unfiltered (stream, "%d", tmp);
- break;
-
- case UI :
- fprintf_unfiltered (stream, "%d", insn_word & 0xffff);
- break;
-
- case BF :
- fprintf_unfiltered (stream, "%d", (insn_word >> 23) & 0x7);
- break;
-
- case BFA :
- fprintf_unfiltered (stream, "%d", (insn_word >> 18) & 0x7);
- break;
-
- case BT :
- fprintf_unfiltered (stream, "%d", (insn_word >> 21) & 0x1f);
- break;
-
- case BA :
- fprintf_unfiltered (stream, "%d", (insn_word >> 16) & 0x1f);
- break;
-
- case BB :
- fprintf_unfiltered (stream, "%d", (insn_word >> 11) & 0x1f);
- break;
-
- case BO :
- fprintf_unfiltered (stream, "%d", (insn_word >> 21) & 0x1f);
- break;
-
- case BI :
- fprintf_unfiltered (stream, "%d", (insn_word >> 16) & 0x1f);
- break;
-
- case SH :
- fprintf_unfiltered (stream, "%d", (insn_word >> 11) & 0x1f);
- break;
-
- case MB :
- fprintf_unfiltered (stream, "0x%x", (insn_word >> 6) & 0x1f);
- break;
-
- case ME :
- fprintf_unfiltered (stream, "0x%x", (insn_word >> 1) & 0x1f);
- break;
-
- case SPR :
- fprintf_unfiltered (stream, "%d", (insn_word >> 16) & 0x1f);
- break;
-
- case DIS :
- nocomma = 1;
- tmp = insn_word & 0xffff;
- if (tmp & 0x8000)
- tmp -= 0x10000;
- fprintf_unfiltered (stream, "%d(", tmp);
- break;
-
- case FXM :
- fprintf_unfiltered (stream, "0x%x", (insn_word >> 12) & 0xff);
- break;
-
- case FRT :
- case FRS :
- fprintf_unfiltered (stream, "f%d", (insn_word >> 21) & 0x1f);
- break;
-
- case FRA :
- fprintf_unfiltered (stream, "f%d", (insn_word >> 16) & 0x1f);
- break;
-
- case FRB :
- fprintf_unfiltered (stream, "f%d", (insn_word >> 11) & 0x1f);
- break;
-
- case FRC :
- fprintf_unfiltered (stream, "f%d", (insn_word >> 6) & 0x1f);
- break;
-
- case FLM :
- fprintf_unfiltered (stream, "0x%x", (insn_word >> 17) & 0xff);
- break;
-
- case NB :
- fprintf_unfiltered (stream, "%d", (insn_word >> 11) & 0x1f);
- break;
-
- case I :
- fprintf_unfiltered (stream, "%d", (insn_word >> 12) & 0xf);
- break;
-
- default :
- fprintf_unfiltered (stream,
- "{Internal error: Unknown operand format identifier %d}",
- *pp);
- }
- ++pp;
-
- if (*pp != '\0' && !nocomma)
- fputc_unfiltered(',', stream);
- }
+ return print_insn_rs6000 ((bfd_vma) memaddr, &info);
}