-/* Print rs6000 instructions for objdump.
- This file is part of the binutils.
-*/
+/* Print IBM RS/6000 instructions for GNU software.
+ 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.
-#include <stdio.h>
-#include "defs.h"
-#include "rs6k-opcode.h"
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "dis-asm.h"
/* Print the rs6k instruction at address MEMADDR in debugged memory,
on STREAM. Returns length of the instruction, in bytes. */
int
print_insn (memaddr, stream)
CORE_ADDR memaddr;
- FILE *stream;
+ GDB_FILE *stream;
{
- int pop, eop; /* primary and extended opcodes */
- int min, max;
- int best = -1; /* found best opcode index */
- int oldbest = -1;
- unsigned int the_insn;
-
- read_memory (memaddr, &the_insn, sizeof (the_insn));
- pop = (unsigned)(the_insn >> 26);
- eop = ((the_insn) >> 1) & 0x3ff;
- min = 0, max = NOPCODES-1;
-
- 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;
- }
-
- 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;
- }
- 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;
- }
- 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;
-
+ disassemble_info info;
-insn_found:
- print_operator (stream, memaddr, the_insn, best);
- return 4;
+ GDB_INIT_DISASSEMBLE_INFO (info, stream);
-not_found:
- fprintf (stream, "0x%08x", the_insn);
- return 4;
+ return print_insn_rs6000 ((bfd_vma) memaddr, &info);
}
-
-
-
-/* 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 [BUFSIZ];
- char *qq = buf;
- char *pp = rs6k_ops[insn_no].opr_ext;
- int tmp;
- int nocomma = 0; /* true if no comma needed */
-
- *qq = '\0';
- 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;
- }
- }
-
- /* tab between orerator and operand */
- *qq++ = '\t';
-
- /* parse the operand now. */
- pp = rs6k_ops[insn_no].oprnd_format;
-
- while (1) {
- switch (*pp) {
- case TO :
- sprintf (qq, "%d", (insn_word >> 21) & 0x1f);
- break;
-
- case RT :
- case RS :
- sprintf (qq, "r%d", (insn_word >> 21) & 0x1f);
- break;
-
- case LI :
- tmp = (insn_word >> 16) & 0x1f;
- if (tmp > 11) {
- fprintf (stderr, "Internal error: unknown cond code: 0x%x\n", insn_word);
- tmp = 0;
- }
- sprintf (qq, "%s", cond_code [tmp]);
- break;
-
-#if 0
- case A2 :
- tmp = (insn_word >> 2) & 0x3fff;
- if (tmp & 0x2000)
- tmp -= 0x4000;
- sprintf (qq, "0x%x", tmp * 4 + memaddr);
- break;
-#endif
- 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;
-
- sprintf (qq, "0x%x", tmp);
- break;
-
- case TA24 :
- tmp = insn_word & 0x03fffffc;
- if (tmp & 0x2000000)
- tmp -= 0x4000000;
-
- if ((insn_word & 0x2) == 0) /* if no AA bit set */
- tmp += memaddr;
-
- sprintf (qq, "0x%x", tmp);
- break;
-
- case LEV : /* for svc only */
- if (insn_word & 0x2) { /* SA is set */
- nocomma = 1;
- *qq = '\0';
- }
- else
- sprintf (qq, "%d", (insn_word >> 5) & 0x7f);
- break;
-
- case FL1 : /* for svc only */
- if (insn_word & 0x2) { /* SA is set */
- nocomma = 1;
- *qq = '\0';
- }
- else
- sprintf (qq, "%d", (insn_word >> 12) & 0xf);
- break;
-
- case FL2 : /* for svc only */
- nocomma = 0;
- if (insn_word & 0x2) /* SA is set */
- sprintf (qq, "%d", (insn_word >> 2) & 0x3fff);
- else
- sprintf (qq, "%d", (insn_word >> 2) & 0x7);
- break;
-
- case RA :
- if (nocomma) {
- sprintf (qq, "r%d)", (insn_word >> 16) & 0x1f);
- nocomma = 0;
- }
- else
- sprintf (qq, "r%d", (insn_word >> 16) & 0x1f);
- break;
-
- case RB :
- sprintf (qq, "r%d", (insn_word >> 11) & 0x1f);
- break;
-
- case SI :
- tmp = insn_word & 0xffff;
- if (tmp & 0x8000)
- tmp -= 0x10000;
- sprintf (qq, "%d", tmp);
- break;
-
- case UI :
- sprintf (qq, "%d", insn_word & 0xffff);
- break;
-
- case BF :
- sprintf (qq, "%d", (insn_word >> 23) & 0x7);
- break;
-
- case BFA :
- sprintf (qq, "%d", (insn_word >> 18) & 0x7);
- break;
-
- case BT :
- sprintf (qq, "%d", (insn_word >> 21) & 0x1f);
- break;
-
- case BA :
- sprintf (qq, "%d", (insn_word >> 16) & 0x1f);
- break;
-
- case BB :
- sprintf (qq, "%d", (insn_word >> 11) & 0x1f);
- break;
-
- case BO :
- sprintf (qq, "%d", (insn_word >> 21) & 0x1f);
- break;
-
- case BI :
- sprintf (qq, "%d", (insn_word >> 16) & 0x1f);
- break;
-
- case SH :
- sprintf (qq, "%d", (insn_word >> 11) & 0x1f);
- break;
-
- case MB :
- sprintf (qq, "0x%x", (insn_word >> 6) & 0x1f);
- break;
-
- case ME :
- sprintf (qq, "0x%x", (insn_word >> 1) & 0x1f);
- break;
-
- case SPR :
- sprintf (qq, "%d", (insn_word >> 16) & 0x1f);
- break;
-
- case DIS :
- nocomma = 1;
- tmp = insn_word & 0xffff;
- if (tmp & 0x8000)
- tmp -= 0x10000;
- sprintf (qq, "%d(", tmp);
- break;
-
- case FXM :
- sprintf (qq, "0x%x", (insn_word >> 12) & 0xff);
- break;
-
- case FRT :
- case FRS :
- sprintf (qq, "f%d", (insn_word >> 21) & 0x1f);
- break;
-
- case FRA :
- sprintf (qq, "f%d", (insn_word >> 16) & 0x1f);
- break;
-
- case FRB :
- sprintf (qq, "f%d", (insn_word >> 11) & 0x1f);
- break;
-
- case FRC :
- sprintf (qq, "f%d", (insn_word >> 6) & 0x1f);
- break;
-
- case FLM :
- sprintf (qq, "0x%x", (insn_word >> 17) & 0xff);
- break;
-
- case NB :
- sprintf (qq, "%d", (insn_word >> 11) & 0x1f);
- break;
-
- case I :
- sprintf (qq, "%d", (insn_word >> 12) & 0xf);
- break;
-
- default :
- sprintf (qq, "Unknown operand format identifier????");
- abort ();
- }
- while (*qq) ++qq;
- ++pp;
-
- if (*pp == '\0')
- break;
- else if (!nocomma)
- *qq++ = ',';
- }
- *qq = '\0';
-
- fprintf (stream, "0x%08x\t%s%s",
- insn_word, rs6k_ops[insn_no].operator, buf);
-}
-