diff options
author | John Gilmore <gnu@cygnus> | 1991-11-12 15:50:47 +0000 |
---|---|---|
committer | John Gilmore <gnu@cygnus> | 1991-11-12 15:50:47 +0000 |
commit | 41abdfbd2de07837ba8088092765154eaa66351d (patch) | |
tree | bb912925e95a78628143f4d2e98b0c32e372f3ac /gdb/rs6000-pinsn.c | |
parent | 37b637f3b7327782b3217f1655fea4258cfb1701 (diff) | |
download | gdb-41abdfbd2de07837ba8088092765154eaa66351d.zip gdb-41abdfbd2de07837ba8088092765154eaa66351d.tar.gz gdb-41abdfbd2de07837ba8088092765154eaa66351d.tar.bz2 |
* rs6000-pinsn.c, rs6000-tdep.c, rs6000-xdep.c, tm-rs6000.h,
xm-rs6000.h: New files.
* xcoffexec.c: New file for handling AIX shared libraries.
Diffstat (limited to 'gdb/rs6000-pinsn.c')
-rw-r--r-- | gdb/rs6000-pinsn.c | 377 |
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); +} + |