aboutsummaryrefslogtreecommitdiff
path: root/gdb/rs6000-pinsn.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/rs6000-pinsn.c')
-rw-r--r--gdb/rs6000-pinsn.c377
1 files changed, 377 insertions, 0 deletions
diff --git a/gdb/rs6000-pinsn.c b/gdb/rs6000-pinsn.c
new file mode 100644
index 0000000..d1e2399
--- /dev/null
+++ b/gdb/rs6000-pinsn.c
@@ -0,0 +1,377 @@
+/* Print rs6000 instructions for objdump.
+ This file is part of the binutils.
+*/
+
+
+#include <stdio.h>
+#include "defs.h"
+#include "rs6k-opcode.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;
+{
+ 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;
+
+
+insn_found:
+ print_operator (stream, memaddr, the_insn, best);
+ return 4;
+
+not_found:
+ fprintf (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 [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);
+}
+