diff options
-rw-r--r-- | gdb/ChangeLog | 16 | ||||
-rw-r--r-- | gdb/mips-tdep.c | 337 |
2 files changed, 179 insertions, 174 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index fe6b497..7e49688 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +Thu Nov 30 01:24:37 2000 Andrew Cagney <cagney@b1.cygnus.com> + + * mips-tdep.c (struct upk_mips16): Delete fields ``inst'' and + ``fmt''. Make ``offset'' a CORE_ADDR. + (print_unpack): Delete. + (extended_offset): Construct and return a CORE_ADDR. + (fetch_mips_16): Return an int. Don't assume short is 16 bits. + (unpack_mips16): Rewrite. Add ``extension'' parameter instead of + incorrectly guessing if the instruction had an extension. + (map16): Delete array. + (mips16_op): Delete macro. + (extended_mips16_next_pc): Rewrite of old mips16_next_pc function. + When an extended instruction do a recursive call. + (mips16_next_pc): Call extended_mips16_next_pc. + (mips_next_pc): Cleanup. + Sat Dec 2 10:40:16 2000 Andrew Cagney <cagney@b1.cygnus.com> * ser-e7kpc.c (e7000pc_setstopbits): New function. diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index daac363..3d119c8 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -861,34 +861,23 @@ enum mips16_inst_fmts extRi64type, /* 20 5,6,5,5,3,3,5 */ extshift64type /* 21 5,5,1,1,1,1,1,1,5,1,1,1,3,5 */ }; -/* I am heaping all the fields of the formats into one structure and then, - only the fields which are involved in instruction extension */ +/* I am heaping all the fields of the formats into one structure and + then, only the fields which are involved in instruction extension */ struct upk_mips16 { - unsigned short inst; - enum mips16_inst_fmts fmt; - unsigned long offset; + CORE_ADDR offset; unsigned int regx; /* Function in i8 type */ unsigned int regy; }; +/* The EXT-I, EXT-ri nad EXT-I8 instructions all have the same format + for the bits which make up the immediatate extension. */ -static void -print_unpack (char *comment, - struct upk_mips16 *u) -{ - printf ("%s %04x ,f(%d) off(%s) (x(%x) y(%x)\n", - comment, u->inst, u->fmt, paddr (u->offset), u->regx, u->regy); -} - -/* The EXT-I, EXT-ri nad EXT-I8 instructions all have the same - format for the bits which make up the immediatate extension. - */ -static unsigned long -extended_offset (unsigned long extension) +static CORE_ADDR +extended_offset (unsigned int extension) { - unsigned long value; + CORE_ADDR value; value = (extension >> 21) & 0x3f; /* * extract 15:11 */ value = value << 6; value |= (extension >> 16) & 0x1f; /* extrace 10:5 */ @@ -906,7 +895,7 @@ extended_offset (unsigned long extension) when the offset is to be used in relative addressing */ -static unsigned short +static unsigned int fetch_mips_16 (CORE_ADDR pc) { char buf[8]; @@ -917,36 +906,33 @@ fetch_mips_16 (CORE_ADDR pc) static void unpack_mips16 (CORE_ADDR pc, + unsigned int extension, + unsigned int inst, + enum mips16_inst_fmts insn_format, struct upk_mips16 *upk) { - CORE_ADDR extpc; - unsigned long extension; - int extended; - extpc = (pc - 4) & ~0x01; /* Extensions are 32 bit instructions */ - /* Decrement to previous address and loose the 16bit mode flag */ - /* return if the instruction was extendable, but not actually extended */ - extended = ((mips32_op (extension) == 30) ? 1 : 0); - if (extended) - { - extension = mips_fetch_instruction (extpc); - } - switch (upk->fmt) + CORE_ADDR offset; + int regx; + int regy; + switch (insn_format) { case itype: { - unsigned long value; - if (extended) + CORE_ADDR value; + if (extension) { value = extended_offset (extension); value = value << 11; /* rom for the original value */ - value |= upk->inst & 0x7ff; /* eleven bits from instruction */ + value |= inst & 0x7ff; /* eleven bits from instruction */ } else { - value = upk->inst & 0x7ff; + value = inst & 0x7ff; /* FIXME : Consider sign extension */ } - upk->offset = value; + offset = value; + regx = -1; + regy = -1; } break; case ritype: @@ -954,13 +940,13 @@ unpack_mips16 (CORE_ADDR pc, { /* A register identifier and an offset */ /* Most of the fields are the same as I type but the immediate value is of a different length */ - unsigned long value; - if (extended) + CORE_ADDR value; + if (extension) { value = extended_offset (extension); value = value << 8; /* from the original instruction */ - value |= upk->inst & 0xff; /* eleven bits from instruction */ - upk->regx = (extension >> 8) & 0x07; /* or i8 funct */ + value |= inst & 0xff; /* eleven bits from instruction */ + regx = (extension >> 8) & 0x07; /* or i8 funct */ if (value & 0x4000) /* test the sign bit , bit 26 */ { value &= ~0x3fff; /* remove the sign bit */ @@ -969,48 +955,41 @@ unpack_mips16 (CORE_ADDR pc, } else { - value = upk->inst & 0xff; /* 8 bits */ - upk->regx = (upk->inst >> 8) & 0x07; /* or i8 funct */ + value = inst & 0xff; /* 8 bits */ + regx = (inst >> 8) & 0x07; /* or i8 funct */ /* FIXME: Do sign extension , this format needs it */ if (value & 0x80) /* THIS CONFUSES ME */ { value &= 0xef; /* remove the sign bit */ value = -value; } - } - upk->offset = value; + offset = value; + regy = -1; break; } case jalxtype: { unsigned long value; - unsigned short nexthalf; - value = ((upk->inst & 0x1f) << 5) | ((upk->inst >> 5) & 0x1f); + unsigned int nexthalf; + value = ((inst & 0x1f) << 5) | ((inst >> 5) & 0x1f); value = value << 16; nexthalf = mips_fetch_instruction (pc + 2); /* low bit still set */ value |= nexthalf; - upk->offset = value; + offset = value; + regx = -1; + regy = -1; break; } default: - printf_filtered ("Decoding unimplemented instruction format type\n"); - break; + internal_error ("%s:%d: bad switch", __FILE__, __LINE__); } - /* print_unpack("UPK",upk) ; */ + upk->offset = offset; + upk->regx = regx; + upk->regy = regy; } -#define mips16_op(x) (x >> 11) - -/* This is a map of the opcodes which ae known to perform branches */ -static unsigned char map16[32] = -{0, 0, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 1, 0 -}; - static CORE_ADDR add_offset_16 (CORE_ADDR pc, int offset) { @@ -1018,137 +997,147 @@ add_offset_16 (CORE_ADDR pc, int offset) } - - -static struct upk_mips16 upk; - -CORE_ADDR -mips16_next_pc (CORE_ADDR pc) +static CORE_ADDR +extended_mips16_next_pc (CORE_ADDR pc, + unsigned int extension, + unsigned int insn) { - int op; - t_inst inst; - /* inst = mips_fetch_instruction(pc) ; - This doesnt always work */ - inst = fetch_mips_16 (pc); - upk.inst = inst; - op = mips16_op (upk.inst); - if (map16[op]) + int op = (insn >> 11); + switch (op) { - int reg; - switch (op) - { - case 2: /* Branch */ - upk.fmt = itype; - unpack_mips16 (pc, &upk); + case 2: /* Branch */ + { + CORE_ADDR offset; + struct upk_mips16 upk; + unpack_mips16 (pc, extension, insn, itype, &upk); + offset = upk.offset; + if (offset & 0x800) { - long offset; - offset = upk.offset; - if (offset & 0x800) + offset &= 0xeff; + offset = -offset; + } + pc += (offset << 1) + 2; + break; + } + case 3: /* JAL , JALX - Watch out, these are 32 bit instruction */ + { + struct upk_mips16 upk; + unpack_mips16 (pc, extension, insn, jalxtype, &upk); + pc = add_offset_16 (pc, upk.offset); + if ((insn >> 10) & 0x01) /* Exchange mode */ + pc = pc & ~0x01; /* Clear low bit, indicate 32 bit mode */ + else + pc |= 0x01; + break; + } + case 4: /* beqz */ + { + struct upk_mips16 upk; + int reg; + unpack_mips16 (pc, extension, insn, ritype, &upk); + reg = read_signed_register (upk.regx); + if (reg == 0) + pc += (upk.offset << 1) + 2; + else + pc += 2; + break; + } + case 5: /* bnez */ + { + struct upk_mips16 upk; + int reg; + unpack_mips16 (pc, extension, insn, ritype, &upk); + reg = read_signed_register (upk.regx); + if (reg != 0) + pc += (upk.offset << 1) + 2; + else + pc += 2; + break; + } + case 12: /* I8 Formats btez btnez */ + { + struct upk_mips16 upk; + int reg; + unpack_mips16 (pc, extension, insn, i8type, &upk); + /* upk.regx contains the opcode */ + reg = read_signed_register (24); /* Test register is 24 */ + if (((upk.regx == 0) && (reg == 0)) /* BTEZ */ + || ((upk.regx == 1) && (reg != 0))) /* BTNEZ */ + /* pc = add_offset_16(pc,upk.offset) ; */ + pc += (upk.offset << 1) + 2; + else + pc += 2; + break; + } + case 29: /* RR Formats JR, JALR, JALR-RA */ + { + struct upk_mips16 upk; + /* upk.fmt = rrtype; */ + op = insn & 0x1f; + if (op == 0) + { + int reg; + upk.regx = (insn >> 8) & 0x07; + upk.regy = (insn >> 5) & 0x07; + switch (upk.regy) { - offset &= 0xeff; - offset = -offset; + case 0: + reg = upk.regx; + break; + case 1: + reg = 31; + break; /* Function return instruction */ + case 2: + reg = upk.regx; + break; + default: + reg = 31; + break; /* BOGUS Guess */ } - pc += (offset << 1) + 2; + pc = read_signed_register (reg); } - break; - case 3: /* JAL , JALX - Watch out, these are 32 bit instruction */ - upk.fmt = jalxtype; - unpack_mips16 (pc, &upk); - pc = add_offset_16 (pc, upk.offset); - if ((upk.inst >> 10) & 0x01) /* Exchange mode */ - pc = pc & ~0x01; /* Clear low bit, indicate 32 bit mode */ - else - pc |= 0x01; - break; - case 4: /* beqz */ - upk.fmt = ritype; - unpack_mips16 (pc, &upk); - reg = read_signed_register (upk.regx); - if (reg == 0) - pc += (upk.offset << 1) + 2; - else - pc += 2; - break; - case 5: /* bnez */ - upk.fmt = ritype; - unpack_mips16 (pc, &upk); - reg = read_signed_register (upk.regx); - if (reg != 0) - pc += (upk.offset << 1) + 2; - else - pc += 2; - break; - case 12: /* I8 Formats btez btnez */ - upk.fmt = i8type; - unpack_mips16 (pc, &upk); - /* upk.regx contains the opcode */ - reg = read_signed_register (24); /* Test register is 24 */ - if (((upk.regx == 0) && (reg == 0)) /* BTEZ */ - || ((upk.regx == 1) && (reg != 0))) /* BTNEZ */ - /* pc = add_offset_16(pc,upk.offset) ; */ - pc += (upk.offset << 1) + 2; - else - pc += 2; - break; - case 29: /* RR Formats JR, JALR, JALR-RA */ - upk.fmt = rrtype; - op = upk.inst & 0x1f; - if (op == 0) - { - upk.regx = (upk.inst >> 8) & 0x07; - upk.regy = (upk.inst >> 5) & 0x07; - switch (upk.regy) - { - case 0: - reg = upk.regx; - break; - case 1: - reg = 31; - break; /* Function return instruction */ - case 2: - reg = upk.regx; - break; - default: - reg = 31; - break; /* BOGUS Guess */ - } - pc = read_signed_register (reg); - } - else - pc += 2; - break; - case 30: /* This is an extend instruction */ - pc += 4; /* Dont be setting breakpoints on the second half */ - break; - default: - printf ("Filtered - next PC probably incorrect due to jump inst\n"); + else pc += 2; - break; - } + break; + } + case 30: + /* This is an instruction extension. Fetch the real instruction + (which follows the extension) and decode things based on + that. */ + { + pc += 2; + pc = extended_mips16_next_pc (pc, insn, fetch_mips_16 (pc)); + break; + } + default: + { + pc += 2; + break; + } } - else - pc += 2; /* just a good old instruction */ - /* See if we CAN actually break on the next instruction */ - /* printf("NXTm16PC %08x\n",(unsigned long)pc) ; */ return pc; -} /* mips16_next_pc */ +} -/* The mips_next_pc function supports single_step when the remote +CORE_ADDR +mips16_next_pc (CORE_ADDR pc) +{ + unsigned int insn = fetch_mips_16 (pc); + return extended_mips16_next_pc (pc, 0, insn); +} + +/* The mips_next_pc function supports single_step when the remote target monitor or stub is not developed enough to do a single_step. - It works by decoding the current instruction and predicting where a branch - will go. This isnt hard because all the data is available. - The MIPS32 and MIPS16 variants are quite different - */ + It works by decoding the current instruction and predicting where a + branch will go. This isnt hard because all the data is available. + The MIPS32 and MIPS16 variants are quite different */ CORE_ADDR mips_next_pc (CORE_ADDR pc) { - t_inst inst; - /* inst = mips_fetch_instruction(pc) ; */ - /* if (pc_is_mips16) <----- This is failing */ if (pc & 0x01) return mips16_next_pc (pc); else return mips32_next_pc (pc); -} /* mips_next_pc */ +} /* Guaranteed to set fci->saved_regs to some values (it never leaves it NULL). */ |