diff options
author | Chris Demetriou <cgd@google.com> | 2003-01-02 21:07:00 +0000 |
---|---|---|
committer | Chris Demetriou <cgd@google.com> | 2003-01-02 21:07:00 +0000 |
commit | 794ac9d07479b2baec21699a1e44b302f7513426 (patch) | |
tree | 3c64fd40b693f7a714458733680ec7cdbfa32e93 /opcodes/mips-dis.c | |
parent | b0ff34ea24a7ed191fdf6bb0a1ed8a3fee69801d (diff) | |
download | gdb-794ac9d07479b2baec21699a1e44b302f7513426.zip gdb-794ac9d07479b2baec21699a1e44b302f7513426.tar.gz gdb-794ac9d07479b2baec21699a1e44b302f7513426.tar.bz2 |
2003-01-02 Chris Demetriou <cgd@broadcom.com>
* mips-dis.c: Update copyright years.
(print_insn_arg): Rename to...
(print_insn_args): This, returning void. Process the whole
string of args rather than a single one. Reindent.
(print_insn_mips): Update to match the above.
Diffstat (limited to 'opcodes/mips-dis.c')
-rw-r--r-- | opcodes/mips-dis.c | 574 |
1 files changed, 284 insertions, 290 deletions
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c index a2f68e9..cbf87ce 100644 --- a/opcodes/mips-dis.c +++ b/opcodes/mips-dis.c @@ -1,6 +1,6 @@ /* Print mips instructions for GDB, the GNU debugger, or for objdump. Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 + 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp). @@ -50,7 +50,7 @@ static int _print_insn_mips PARAMS ((bfd_vma, struct disassemble_info *, enum bfd_endian)); static int print_insn_mips PARAMS ((bfd_vma, unsigned long int, struct disassemble_info *)); -static int print_insn_arg +static void print_insn_args PARAMS ((const char *, unsigned long, bfd_vma, struct disassemble_info *)); static int print_insn_mips16 PARAMS ((bfd_vma, struct disassemble_info *)); @@ -664,342 +664,344 @@ lookup_mips_cp0sel_name(names, len, cp0reg, sel) /* Print insn arguments for 32/64-bit code. */ -static int -print_insn_arg (d, l, pc, info) +static void +print_insn_args (d, l, pc, info) const char *d; register unsigned long int l; bfd_vma pc; struct disassemble_info *info; { - int op, delta, consumed; + int op, delta; - consumed = 1; - switch (*d) + for (; *d != '\0'; d++) { - case ',': - case '(': - case ')': - case '[': - case ']': - (*info->fprintf_func) (info->stream, "%c", *d); - break; - - case '+': - /* Extension character; switch for second char. */ - d++; - consumed++; switch (*d) { - case 'A': - (*info->fprintf_func) (info->stream, "0x%x", - (l >> OP_SH_SHAMT) & OP_MASK_SHAMT); + case ',': + case '(': + case ')': + case '[': + case ']': + (*info->fprintf_func) (info->stream, "%c", *d); break; + + case '+': + /* Extension character; switch for second char. */ + d++; + switch (*d) + { + case '\0': + /* xgettext:c-format */ + (*info->fprintf_func) (info->stream, + _("# internal error, incomplete extension sequence (+)")); + return; + + case 'A': + (*info->fprintf_func) (info->stream, "0x%x", + (l >> OP_SH_SHAMT) & OP_MASK_SHAMT); + break; - case 'B': - (*info->fprintf_func) (info->stream, "0x%x", - (((l >> OP_SH_INSMSB) & OP_MASK_INSMSB) - - ((l >> OP_SH_SHAMT) & OP_MASK_SHAMT) - + 1)); - break; + case 'B': + (*info->fprintf_func) (info->stream, "0x%x", + (((l >> OP_SH_INSMSB) & OP_MASK_INSMSB) + - ((l >> OP_SH_SHAMT) & OP_MASK_SHAMT) + + 1)); + break; + + case 'C': + (*info->fprintf_func) (info->stream, "0x%x", + (((l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD) + + 1)); + break; + + case 'D': + { + const struct mips_cp0sel_name *n; + unsigned int cp0reg, sel; + + cp0reg = (l >> OP_SH_RD) & OP_MASK_RD; + sel = (l >> OP_SH_SEL) & OP_MASK_SEL; + + /* CP0 register including 'sel' code for mtcN (et al.), to be + printed textually if known. If not known, print both + CP0 register name and sel numerically since CP0 register + with sel 0 may have a name unrelated to register being + printed. */ + n = lookup_mips_cp0sel_name(mips_cp0sel_names, + mips_cp0sel_names_len, cp0reg, sel); + if (n != NULL) + (*info->fprintf_func) (info->stream, "%s", n->name); + else + (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel); + break; + } - case 'C': - (*info->fprintf_func) (info->stream, "0x%x", - (((l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD) - + 1)); + default: + /* xgettext:c-format */ + (*info->fprintf_func) (info->stream, + _("# internal error, undefined extension sequence (+%c)"), + *d); + return; + } break; - case 'D': - { - const struct mips_cp0sel_name *n; - unsigned int cp0reg, sel; - - cp0reg = (l >> OP_SH_RD) & OP_MASK_RD; - sel = (l >> OP_SH_SEL) & OP_MASK_SEL; - - /* CP0 register including 'sel' code for mtcN (et al.), to be - printed textually if known. If not known, print both - CP0 register name and sel numerically since CP0 register - with sel 0 may have a name unrelated to register being - printed. */ - n = lookup_mips_cp0sel_name(mips_cp0sel_names, - mips_cp0sel_names_len, cp0reg, sel); - if (n != NULL) - (*info->fprintf_func) (info->stream, "%s", n->name); - else - (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel); - break; - } - - default: - /* xgettext:c-format */ - (*info->fprintf_func) (info->stream, - _("# internal error, undefined extension sequence (+%c)"), - *d); - /* Do not eat the trailing newline. */ - if (*d == '\0') - consumed--; + case 's': + case 'b': + case 'r': + case 'v': + (*info->fprintf_func) (info->stream, "%s", + mips_gpr_names[(l >> OP_SH_RS) & OP_MASK_RS]); break; - } - break; - - case 's': - case 'b': - case 'r': - case 'v': - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[(l >> OP_SH_RS) & OP_MASK_RS]); - break; - - case 't': - case 'w': - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]); - break; - case 'i': - case 'u': - (*info->fprintf_func) (info->stream, "0x%x", - (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE); - break; + case 't': + case 'w': + (*info->fprintf_func) (info->stream, "%s", + mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]); + break; - case 'j': /* Same as i, but sign-extended. */ - case 'o': - delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA; - if (delta & 0x8000) - delta |= ~0xffff; - (*info->fprintf_func) (info->stream, "%d", - delta); - break; + case 'i': + case 'u': + (*info->fprintf_func) (info->stream, "0x%x", + (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE); + break; - case 'h': - (*info->fprintf_func) (info->stream, "0x%x", - (unsigned int) ((l >> OP_SH_PREFX) - & OP_MASK_PREFX)); - break; + case 'j': /* Same as i, but sign-extended. */ + case 'o': + delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA; + if (delta & 0x8000) + delta |= ~0xffff; + (*info->fprintf_func) (info->stream, "%d", + delta); + break; - case 'k': - (*info->fprintf_func) (info->stream, "0x%x", - (unsigned int) ((l >> OP_SH_CACHE) - & OP_MASK_CACHE)); - break; + case 'h': + (*info->fprintf_func) (info->stream, "0x%x", + (unsigned int) ((l >> OP_SH_PREFX) + & OP_MASK_PREFX)); + break; - case 'a': - info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff) - | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)); - (*info->print_address_func) (info->target, info); - break; + case 'k': + (*info->fprintf_func) (info->stream, "0x%x", + (unsigned int) ((l >> OP_SH_CACHE) + & OP_MASK_CACHE)); + break; - case 'p': - /* Sign extend the displacement. */ - delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA; - if (delta & 0x8000) - delta |= ~0xffff; - info->target = (delta << 2) + pc + INSNLEN; - (*info->print_address_func) (info->target, info); - break; + case 'a': + info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff) + | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)); + (*info->print_address_func) (info->target, info); + break; - case 'd': - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[(l >> OP_SH_RD) & OP_MASK_RD]); - break; + case 'p': + /* Sign extend the displacement. */ + delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA; + if (delta & 0x8000) + delta |= ~0xffff; + info->target = (delta << 2) + pc + INSNLEN; + (*info->print_address_func) (info->target, info); + break; - case 'U': - { - /* First check for both rd and rt being equal. */ - unsigned int reg = (l >> OP_SH_RD) & OP_MASK_RD; - if (reg == ((l >> OP_SH_RT) & OP_MASK_RT)) + case 'd': (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[reg]); - else + mips_gpr_names[(l >> OP_SH_RD) & OP_MASK_RD]); + break; + + case 'U': { - /* If one is zero use the other. */ - if (reg == 0) - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]); - else if (((l >> OP_SH_RT) & OP_MASK_RT) == 0) + /* First check for both rd and rt being equal. */ + unsigned int reg = (l >> OP_SH_RD) & OP_MASK_RD; + if (reg == ((l >> OP_SH_RT) & OP_MASK_RT)) (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[reg]); - else /* Bogus, result depends on processor. */ - (*info->fprintf_func) (info->stream, "%s or %s", - mips_gpr_names[reg], - mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]); + else + { + /* If one is zero use the other. */ + if (reg == 0) + (*info->fprintf_func) (info->stream, "%s", + mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]); + else if (((l >> OP_SH_RT) & OP_MASK_RT) == 0) + (*info->fprintf_func) (info->stream, "%s", + mips_gpr_names[reg]); + else /* Bogus, result depends on processor. */ + (*info->fprintf_func) (info->stream, "%s or %s", + mips_gpr_names[reg], + mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]); + } } - } - break; + break; - case 'z': - (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]); - break; + case 'z': + (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]); + break; - case '<': - (*info->fprintf_func) (info->stream, "0x%x", - (l >> OP_SH_SHAMT) & OP_MASK_SHAMT); - break; + case '<': + (*info->fprintf_func) (info->stream, "0x%x", + (l >> OP_SH_SHAMT) & OP_MASK_SHAMT); + break; - case 'c': - (*info->fprintf_func) (info->stream, "0x%x", - (l >> OP_SH_CODE) & OP_MASK_CODE); - break; + case 'c': + (*info->fprintf_func) (info->stream, "0x%x", + (l >> OP_SH_CODE) & OP_MASK_CODE); + break; - case 'q': - (*info->fprintf_func) (info->stream, "0x%x", - (l >> OP_SH_CODE2) & OP_MASK_CODE2); - break; + case 'q': + (*info->fprintf_func) (info->stream, "0x%x", + (l >> OP_SH_CODE2) & OP_MASK_CODE2); + break; - case 'C': - (*info->fprintf_func) (info->stream, "0x%x", - (l >> OP_SH_COPZ) & OP_MASK_COPZ); - break; + case 'C': + (*info->fprintf_func) (info->stream, "0x%x", + (l >> OP_SH_COPZ) & OP_MASK_COPZ); + break; - case 'B': - (*info->fprintf_func) (info->stream, "0x%x", - (l >> OP_SH_CODE20) & OP_MASK_CODE20); - break; + case 'B': + (*info->fprintf_func) (info->stream, "0x%x", + (l >> OP_SH_CODE20) & OP_MASK_CODE20); + break; - case 'J': - (*info->fprintf_func) (info->stream, "0x%x", - (l >> OP_SH_CODE19) & OP_MASK_CODE19); - break; + case 'J': + (*info->fprintf_func) (info->stream, "0x%x", + (l >> OP_SH_CODE19) & OP_MASK_CODE19); + break; - case 'S': - case 'V': - (*info->fprintf_func) (info->stream, "%s", - mips_fpr_names[(l >> OP_SH_FS) & OP_MASK_FS]); - break; + case 'S': + case 'V': + (*info->fprintf_func) (info->stream, "%s", + mips_fpr_names[(l >> OP_SH_FS) & OP_MASK_FS]); + break; - case 'T': - case 'W': - (*info->fprintf_func) (info->stream, "%s", - mips_fpr_names[(l >> OP_SH_FT) & OP_MASK_FT]); - break; + case 'T': + case 'W': + (*info->fprintf_func) (info->stream, "%s", + mips_fpr_names[(l >> OP_SH_FT) & OP_MASK_FT]); + break; - case 'D': - (*info->fprintf_func) (info->stream, "%s", - mips_fpr_names[(l >> OP_SH_FD) & OP_MASK_FD]); - break; + case 'D': + (*info->fprintf_func) (info->stream, "%s", + mips_fpr_names[(l >> OP_SH_FD) & OP_MASK_FD]); + break; - case 'R': - (*info->fprintf_func) (info->stream, "%s", - mips_fpr_names[(l >> OP_SH_FR) & OP_MASK_FR]); - break; + case 'R': + (*info->fprintf_func) (info->stream, "%s", + mips_fpr_names[(l >> OP_SH_FR) & OP_MASK_FR]); + break; - case 'E': - /* Coprocessor register for lwcN instructions, et al. - - Note that there is no load/store cp0 instructions, and - that FPU (cp1) instructions disassemble this field using - 'T' format. Therefore, until we gain understanding of - cp2 register names, - we can simply print the register numbers. */ - (*info->fprintf_func) (info->stream, "$%d", - (l >> OP_SH_RT) & OP_MASK_RT); - break; + case 'E': + /* Coprocessor register for lwcN instructions, et al. - case 'G': - /* Coprocessor register for mtcN instructions, et al. - Note that FPU (cp1) instructions disassemble this field using - 'S' format. Therefore, we only need to worry about cp0, cp2, - and cp3. */ - op = (l >> OP_SH_OP) & OP_MASK_OP; - if (op == OP_OP_COP0) - (*info->fprintf_func) (info->stream, "%s", - mips_cp0_names[(l >> OP_SH_RD) & OP_MASK_RD]); - else - (*info->fprintf_func) (info->stream, "$%d", - (l >> OP_SH_RD) & OP_MASK_RD); - break; + Note that there is no load/store cp0 instructions, and + that FPU (cp1) instructions disassemble this field using + 'T' format. Therefore, until we gain understanding of + cp2 register names, we can simply print the register + numbers. */ + (*info->fprintf_func) (info->stream, "$%d", + (l >> OP_SH_RT) & OP_MASK_RT); + break; - case 'K': - (*info->fprintf_func) (info->stream, "%s", - mips_hwr_names[(l >> OP_SH_RD) & OP_MASK_RD]); - break; + case 'G': + /* Coprocessor register for mtcN instructions, et al. Note + that FPU (cp1) instructions disassemble this field using + 'S' format. Therefore, we only need to worry about cp0, + cp2, and cp3. */ + op = (l >> OP_SH_OP) & OP_MASK_OP; + if (op == OP_OP_COP0) + (*info->fprintf_func) (info->stream, "%s", + mips_cp0_names[(l >> OP_SH_RD) & OP_MASK_RD]); + else + (*info->fprintf_func) (info->stream, "$%d", + (l >> OP_SH_RD) & OP_MASK_RD); + break; - case 'N': - (*info->fprintf_func) (info->stream, "$fcc%d", - (l >> OP_SH_BCC) & OP_MASK_BCC); - break; + case 'K': + (*info->fprintf_func) (info->stream, "%s", + mips_hwr_names[(l >> OP_SH_RD) & OP_MASK_RD]); + break; - case 'M': - (*info->fprintf_func) (info->stream, "$fcc%d", - (l >> OP_SH_CCC) & OP_MASK_CCC); - break; + case 'N': + (*info->fprintf_func) (info->stream, "$fcc%d", + (l >> OP_SH_BCC) & OP_MASK_BCC); + break; - case 'P': - (*info->fprintf_func) (info->stream, "%d", - (l >> OP_SH_PERFREG) & OP_MASK_PERFREG); - break; + case 'M': + (*info->fprintf_func) (info->stream, "$fcc%d", + (l >> OP_SH_CCC) & OP_MASK_CCC); + break; - case 'e': - (*info->fprintf_func) (info->stream, "%d", - (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE); - break; + case 'P': + (*info->fprintf_func) (info->stream, "%d", + (l >> OP_SH_PERFREG) & OP_MASK_PERFREG); + break; - case '%': - (*info->fprintf_func) (info->stream, "%d", - (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN); - break; + case 'e': + (*info->fprintf_func) (info->stream, "%d", + (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE); + break; - case 'H': - (*info->fprintf_func) (info->stream, "%d", - (l >> OP_SH_SEL) & OP_MASK_SEL); - break; + case '%': + (*info->fprintf_func) (info->stream, "%d", + (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN); + break; - case 'O': - (*info->fprintf_func) (info->stream, "%d", - (l >> OP_SH_ALN) & OP_MASK_ALN); - break; + case 'H': + (*info->fprintf_func) (info->stream, "%d", + (l >> OP_SH_SEL) & OP_MASK_SEL); + break; - case 'Q': - { - unsigned int vsel = (l >> OP_SH_VSEL) & OP_MASK_VSEL; - if ((vsel & 0x10) == 0) - { - int fmt; - vsel &= 0x0f; - for (fmt = 0; fmt < 3; fmt++, vsel >>= 1) - if ((vsel & 1) == 0) - break; - (*info->fprintf_func) (info->stream, "$v%d[%d]", - (l >> OP_SH_FT) & OP_MASK_FT, - vsel >> 1); - } - else if ((vsel & 0x08) == 0) - { - (*info->fprintf_func) (info->stream, "$v%d", - (l >> OP_SH_FT) & OP_MASK_FT); - } - else + case 'O': + (*info->fprintf_func) (info->stream, "%d", + (l >> OP_SH_ALN) & OP_MASK_ALN); + break; + + case 'Q': { - (*info->fprintf_func) (info->stream, "0x%x", - (l >> OP_SH_FT) & OP_MASK_FT); + unsigned int vsel = (l >> OP_SH_VSEL) & OP_MASK_VSEL; + if ((vsel & 0x10) == 0) + { + int fmt; + vsel &= 0x0f; + for (fmt = 0; fmt < 3; fmt++, vsel >>= 1) + if ((vsel & 1) == 0) + break; + (*info->fprintf_func) (info->stream, "$v%d[%d]", + (l >> OP_SH_FT) & OP_MASK_FT, + vsel >> 1); + } + else if ((vsel & 0x08) == 0) + { + (*info->fprintf_func) (info->stream, "$v%d", + (l >> OP_SH_FT) & OP_MASK_FT); + } + else + { + (*info->fprintf_func) (info->stream, "0x%x", + (l >> OP_SH_FT) & OP_MASK_FT); + } } - } - break; + break; - case 'X': - (*info->fprintf_func) (info->stream, "$v%d", - (l >> OP_SH_FD) & OP_MASK_FD); - break; + case 'X': + (*info->fprintf_func) (info->stream, "$v%d", + (l >> OP_SH_FD) & OP_MASK_FD); + break; - case 'Y': - (*info->fprintf_func) (info->stream, "$v%d", - (l >> OP_SH_FS) & OP_MASK_FS); - break; + case 'Y': + (*info->fprintf_func) (info->stream, "$v%d", + (l >> OP_SH_FS) & OP_MASK_FS); + break; - case 'Z': - (*info->fprintf_func) (info->stream, "$v%d", - (l >> OP_SH_FT) & OP_MASK_FT); - break; + case 'Z': + (*info->fprintf_func) (info->stream, "$v%d", + (l >> OP_SH_FT) & OP_MASK_FT); + break; - default: - /* xgettext:c-format */ - (*info->fprintf_func) (info->stream, - _("# internal error, undefined modifier(%c)"), - *d); - break; + default: + /* xgettext:c-format */ + (*info->fprintf_func) (info->stream, + _("# internal error, undefined modifier(%c)"), + *d); + return; + } } - - return consumed; } /* Check if the object uses NewABI conventions. */ @@ -1106,16 +1108,8 @@ print_insn_mips (memaddr, word, info) d = op->args; if (d != NULL && *d != '\0') { - int consumed; - (*info->fprintf_func) (info->stream, "\t"); - while (*d != '\0') - { - /* print_insn_arg will not eat the trailing NUL - of (erroneous) multi-character strings. */ - consumed = print_insn_arg (d, word, memaddr, info); - d += consumed; - } + print_insn_args (d, word, memaddr, info); } return INSNLEN; |