along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
-#include <string.h>
-#include "gdb_assert.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
-static int mips32_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR);
-static int micromips_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR,
- int);
-static int mips16_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR,
- int);
+static int mips32_instruction_has_delay_slot (struct gdbarch *gdbarch,
+ ULONGEST inst);
+static int micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32);
+static int mips16_instruction_has_delay_slot (unsigned short inst,
+ int mustbe32);
+
+static int mips32_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
+ CORE_ADDR addr);
+static int micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
+ CORE_ADDR addr, int mustbe32);
+static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
+ CORE_ADDR addr, int mustbe32);
/* A useful bit in the CP0 status register (MIPS_PS_REGNUM). */
/* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip. */
return ((addr) | (CORE_ADDR) 1);
}
+/* Extern version of unmake_compact_addr; we use a separate function
+ so that unmake_compact_addr can be inlined throughout this file. */
+
+CORE_ADDR
+mips_unmake_compact_addr (CORE_ADDR addr)
+{
+ return unmake_compact_addr (addr);
+}
+
/* Functions for setting and testing a bit in a minimal symbol that
marks it as MIPS16 or microMIPS function. The MSB of the minimal
symbol's "info" field is used for this purpose.
return;
if (ELF_ST_IS_MICROMIPS (st_other))
- MSYMBOL_TARGET_FLAG_2 (msym) = 1;
+ {
+ MSYMBOL_TARGET_FLAG_2 (msym) = 1;
+ SET_MSYMBOL_VALUE_ADDRESS (msym, MSYMBOL_VALUE_RAW_ADDRESS (msym) | 1);
+ }
else if (ELF_ST_IS_MIPS16 (st_other))
- MSYMBOL_TARGET_FLAG_1 (msym) = 1;
+ {
+ MSYMBOL_TARGET_FLAG_1 (msym) = 1;
+ SET_MSYMBOL_VALUE_ADDRESS (msym, MSYMBOL_VALUE_RAW_ADDRESS (msym) | 1);
+ }
}
/* Return one iff MSYM refers to standard ISA code. */
return MSYMBOL_TARGET_FLAG_2 (msym);
}
+/* Set the ISA bit in the main symbol too, complementing the corresponding
+ minimal symbol setting and reflecting the run-time value of the symbol.
+ The need for comes from the ISA bit having been cleared as code in
+ `_bfd_mips_elf_symbol_processing' separated it into the ELF symbol's
+ `st_other' STO_MIPS16 or STO_MICROMIPS annotation, making the values
+ of symbols referring to compressed code different in GDB to the values
+ used by actual code. That in turn makes them evaluate incorrectly in
+ expressions, producing results different to what the same expressions
+ yield when compiled into the program being debugged. */
+
+static void
+mips_make_symbol_special (struct symbol *sym, struct objfile *objfile)
+{
+ if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ /* We are in symbol reading so it is OK to cast away constness. */
+ struct block *block = (struct block *) SYMBOL_BLOCK_VALUE (sym);
+ CORE_ADDR compact_block_start;
+ struct bound_minimal_symbol msym;
+
+ compact_block_start = BLOCK_START (block) | 1;
+ msym = lookup_minimal_symbol_by_pc (compact_block_start);
+ if (msym.minsym && !msymbol_is_mips (msym.minsym))
+ {
+ BLOCK_START (block) = compact_block_start;
+ }
+ }
+}
+
/* XFER a value from the big/little/left end of the register.
Depending on the size of the value it might occupy the entire
register or just part of it. Make an allowance for this, aligning
stored by elfread.c in the high bit of the info field. Use this
to decide if the function is standard MIPS. Otherwise if bit 0
of the address is clear, then this is a standard MIPS function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_mips (sym.minsym);
else
elfread.c in the high bit of the info field. Use this to decide
if the function is MIPS16. Otherwise if bit 0 of the address is
set, then ELF file flags will tell if this is a MIPS16 function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_mips16 (sym.minsym);
else
if the function is microMIPS. Otherwise if bit 0 of the address
is set, then ELF file flags will tell if this is a microMIPS
function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_micromips (sym.minsym);
else
this to decide if the function is MIPS16 or microMIPS or normal
MIPS. Otherwise if bit 0 of the address is set, then ELF file
flags will tell if this is a MIPS16 or a microMIPS function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
{
if (msymbol_is_micromips (sym.minsym))
}
}
+/* Set the ISA bit correctly in the PC, used by DWARF-2 machinery.
+ The need for comes from the ISA bit having been cleared, making
+ addresses in FDE, range records, etc. referring to compressed code
+ different to those in line information, the symbol table and finally
+ the PC register. That in turn confuses many operations. */
+
+static CORE_ADDR
+mips_adjust_dwarf2_addr (CORE_ADDR pc)
+{
+ pc = unmake_compact_addr (pc);
+ return mips_pc_is_mips (pc) ? pc : make_compact_addr (pc);
+}
+
+/* Recalculate the line record requested so that the resulting PC has
+ the ISA bit set correctly, used by DWARF-2 machinery. The need for
+ this adjustment comes from some records associated with compressed
+ code having the ISA bit cleared, most notably at function prologue
+ ends. The ISA bit is in this context retrieved from the minimal
+ symbol covering the address requested, which in turn has been
+ constructed from the binary's symbol table rather than DWARF-2
+ information. The correct setting of the ISA bit is required for
+ breakpoint addresses to correctly match against the stop PC.
+
+ As line entries can specify relative address adjustments we need to
+ keep track of the absolute value of the last line address recorded
+ in line information, so that we can calculate the actual address to
+ apply the ISA bit adjustment to. We use PC for this tracking and
+ keep the original address there.
+
+ As such relative address adjustments can be odd within compressed
+ code we need to keep track of the last line address with the ISA
+ bit adjustment applied too, as the original address may or may not
+ have had the ISA bit set. We use ADJ_PC for this tracking and keep
+ the adjusted address there.
+
+ For relative address adjustments we then use these variables to
+ calculate the address intended by line information, which will be
+ PC-relative, and return an updated adjustment carrying ISA bit
+ information, which will be ADJ_PC-relative. For absolute address
+ adjustments we just return the same address that we store in ADJ_PC
+ too.
+
+ As the first line entry can be relative to an implied address value
+ of 0 we need to have the initial address set up that we store in PC
+ and ADJ_PC. This is arranged with a call from `dwarf_decode_lines_1'
+ that sets PC to 0 and ADJ_PC accordingly, usually 0 as well. */
+
+static CORE_ADDR
+mips_adjust_dwarf2_line (CORE_ADDR addr, int rel)
+{
+ static CORE_ADDR adj_pc;
+ static CORE_ADDR pc;
+ CORE_ADDR isa_pc;
+
+ pc = rel ? pc + addr : addr;
+ isa_pc = mips_adjust_dwarf2_addr (pc);
+ addr = rel ? isa_pc - adj_pc : isa_pc;
+ adj_pc = isa_pc;
+ return addr;
+}
+
/* Various MIPS16 thunk (aka stub or trampoline) names. */
static const char mips_str_mips16_call_stub[] = "__mips16_call_stub_";
LONGEST pc;
regcache_cooked_read_signed (regcache, regnum, &pc);
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
return pc;
}
CORE_ADDR pc;
pc = frame_unwind_register_signed (next_frame, gdbarch_pc_regnum (gdbarch));
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
/* macro/2012-04-20: This hack skips over MIPS16 call thunks as
intermediate frames. In this case we can get the caller's address
from $ra, or if $ra contains an address within a thunk as well, then
{
pc = frame_unwind_register_signed
(next_frame, gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM);
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
if (mips_in_frame_stub (pc))
- {
- pc = frame_unwind_register_signed
- (next_frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM);
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = frame_unwind_register_signed
+ (next_frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM);
}
return pc;
}
{
int regnum = gdbarch_pc_regnum (get_regcache_arch (regcache));
- if (mips_pc_is_mips (pc))
- regcache_cooked_write_unsigned (regcache, regnum, pc);
- else
- regcache_cooked_write_unsigned (regcache, regnum, make_compact_addr (pc));
+ regcache_cooked_write_unsigned (regcache, regnum, pc);
}
/* Fetch and return instruction from the specified location. Handle
}
+/* Calculate the destination of a branch whose 16-bit opcode word is at PC,
+ and having a signed 16-bit OFFSET. */
+
static CORE_ADDR
add_offset_16 (CORE_ADDR pc, int offset)
{
- return ((offset << 2) | ((pc + 2) & (~(CORE_ADDR) 0x0fffffff)));
+ return pc + (offset << 1) + 2;
}
static CORE_ADDR
{
struct upk_mips16 upk;
unpack_mips16 (gdbarch, pc, extension, insn, itype, &upk);
- pc += (upk.offset << 1) + 2;
+ pc = add_offset_16 (pc, upk.offset);
break;
}
case 3: /* JAL , JALX - Watch out, these are 32 bit
{
struct upk_mips16 upk;
unpack_mips16 (gdbarch, pc, extension, insn, jalxtype, &upk);
- pc = add_offset_16 (pc, upk.offset);
+ pc = ((pc + 2) & (~(CORE_ADDR) 0x0fffffff)) | (upk.offset << 2);
if ((insn >> 10) & 0x01) /* Exchange mode */
pc = pc & ~0x01; /* Clear low bit, indicate 32 bit mode. */
else
unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
reg = get_frame_register_signed (frame, mips_reg3_to_reg[upk.regx]);
if (reg == 0)
- pc += (upk.offset << 1) + 2;
+ pc = add_offset_16 (pc, upk.offset);
else
pc += 2;
break;
unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
reg = get_frame_register_signed (frame, mips_reg3_to_reg[upk.regx]);
if (reg != 0)
- pc += (upk.offset << 1) + 2;
+ pc = add_offset_16 (pc, upk.offset);
else
pc += 2;
break;
reg = get_frame_register_signed (frame, 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;
+ pc = add_offset_16 (pc, upk.offset);
else
pc += 2;
break;
return mips32_next_pc (frame, pc);
}
+/* Return non-zero if the MIPS16 instruction INSN is a compact branch
+ or jump. */
+
+static int
+mips16_instruction_is_compact_branch (unsigned short insn)
+{
+ switch (insn & 0xf800)
+ {
+ case 0xe800:
+ return (insn & 0x009f) == 0x80; /* JALRC/JRC */
+ case 0x6000:
+ return (insn & 0x0600) == 0; /* BTNEZ/BTEQZ */
+ case 0x2800: /* BNEZ */
+ case 0x2000: /* BEQZ */
+ case 0x1000: /* B */
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Return non-zero if the microMIPS instruction INSN is a compact branch
+ or jump. */
+
+static int
+micromips_instruction_is_compact_branch (unsigned short insn)
+{
+ switch (micromips_op (insn))
+ {
+ case 0x11: /* POOL16C: bits 010001 */
+ return (b5s5_op (insn) == 0x18
+ /* JRADDIUSP: bits 010001 11000 */
+ || b5s5_op (insn) == 0xd);
+ /* JRC: bits 010011 01101 */
+ case 0x10: /* POOL32I: bits 010000 */
+ return (b5s5_op (insn) & 0x1d) == 0x5;
+ /* BEQZC/BNEZC: bits 010000 001x1 */
+ default:
+ return 0;
+ }
+}
+
struct mips_frame_cache
{
CORE_ADDR base;
struct frame_info *this_frame,
struct mips_frame_cache *this_cache)
{
+ int prev_non_prologue_insn = 0;
+ int this_non_prologue_insn;
+ int non_prologue_insns = 0;
+ CORE_ADDR prev_pc;
CORE_ADDR cur_pc;
CORE_ADDR frame_addr = 0; /* Value of $r17, used as frame pointer. */
CORE_ADDR sp;
unsigned inst = 0; /* current instruction */
unsigned entry_inst = 0; /* the entry instruction */
unsigned save_inst = 0; /* the save instruction */
+ int prev_delay_slot = 0;
+ int in_delay_slot;
int reg, offset;
int extend_bytes = 0;
- int prev_extend_bytes;
- CORE_ADDR end_prologue_addr = 0;
+ int prev_extend_bytes = 0;
+ CORE_ADDR end_prologue_addr;
/* Can be called when there's no process, and hence when there's no
THIS_FRAME. */
if (limit_pc > start_pc + 200)
limit_pc = start_pc + 200;
+ prev_pc = start_pc;
+ /* Permit at most one non-prologue non-control-transfer instruction
+ in the middle which may have been reordered by the compiler for
+ optimisation. */
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN16_SIZE)
{
+ this_non_prologue_insn = 0;
+ in_delay_slot = 0;
+
/* Save the previous instruction. If it's an EXTEND, we'll extract
the immediate offset extension from it in mips16_get_imm. */
prev_inst = inst;
if (prev_extend_bytes) /* extend */
save_inst |= prev_inst << 16;
}
- else if ((inst & 0xf800) == 0x1800) /* jal(x) */
- cur_pc += MIPS_INSN16_SIZE; /* 32-bit instruction */
else if ((inst & 0xff1c) == 0x6704) /* move reg,$a0-$a3 */
{
/* This instruction is part of the prologue, but we don't
need to do anything special to handle it. */
}
+ else if (mips16_instruction_has_delay_slot (inst, 0))
+ /* JAL/JALR/JALX/JR */
+ {
+ /* The instruction in the delay slot can be a part
+ of the prologue, so move forward once more. */
+ in_delay_slot = 1;
+ if (mips16_instruction_has_delay_slot (inst, 1))
+ /* JAL/JALX */
+ {
+ prev_extend_bytes = MIPS_INSN16_SIZE;
+ cur_pc += MIPS_INSN16_SIZE; /* 32-bit instruction */
+ }
+ }
else
{
- /* This instruction is not an instruction typically found
- in a prologue, so we must have reached the end of the
- prologue. */
- if (end_prologue_addr == 0)
- end_prologue_addr = cur_pc - prev_extend_bytes;
+ this_non_prologue_insn = 1;
}
+
+ non_prologue_insns += this_non_prologue_insn;
+
+ /* A jump or branch, or enough non-prologue insns seen? If so,
+ then we must have reached the end of the prologue by now. */
+ if (prev_delay_slot || non_prologue_insns > 1
+ || mips16_instruction_is_compact_branch (inst))
+ break;
+
+ prev_non_prologue_insn = this_non_prologue_insn;
+ prev_delay_slot = in_delay_slot;
+ prev_pc = cur_pc - prev_extend_bytes;
}
/* The entry instruction is typically the first instruction in a function,
= this_cache->saved_regs[gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM];
}
- /* If we didn't reach the end of the prologue when scanning the function
- instructions, then set end_prologue_addr to the address of the
- instruction immediately after the last one we scanned. */
- if (end_prologue_addr == 0)
- end_prologue_addr = cur_pc;
+ /* Set end_prologue_addr to the address of the instruction immediately
+ after the last one we scanned. Unless the last one looked like a
+ non-prologue instruction (and we looked ahead), in which case use
+ its address instead. */
+ end_prologue_addr = (prev_non_prologue_insn || prev_delay_slot
+ ? prev_pc : cur_pc - prev_extend_bytes);
return end_prologue_addr;
}
struct frame_info *this_frame,
struct mips_frame_cache *this_cache)
{
- CORE_ADDR end_prologue_addr = 0;
+ CORE_ADDR end_prologue_addr;
int prev_non_prologue_insn = 0;
int frame_reg = MIPS_SP_REGNUM;
int this_non_prologue_insn;
long frame_offset = 0; /* Size of stack frame. */
long frame_adjust = 0; /* Offset of FP from SP. */
CORE_ADDR frame_addr = 0; /* Value of $30, used as frame pointer. */
+ int prev_delay_slot = 0;
+ int in_delay_slot;
CORE_ADDR prev_pc;
CORE_ADDR cur_pc;
ULONGEST insn; /* current instruction */
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += loc)
{
this_non_prologue_insn = 0;
+ in_delay_slot = 0;
sp_adj = 0;
loc = 0;
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, cur_pc, NULL);
break;
default:
- this_non_prologue_insn = 1;
+ /* The instruction in the delay slot can be a part
+ of the prologue, so move forward once more. */
+ if (micromips_instruction_has_delay_slot (insn, 0))
+ in_delay_slot = 1;
+ else
+ this_non_prologue_insn = 1;
break;
}
+ insn >>= 16;
break;
/* 16-bit instructions. */
break;
default:
- this_non_prologue_insn = 1;
+ /* The instruction in the delay slot can be a part
+ of the prologue, so move forward once more. */
+ if (micromips_instruction_has_delay_slot (insn << 16, 0))
+ in_delay_slot = 1;
+ else
+ this_non_prologue_insn = 1;
break;
}
break;
frame_offset -= sp_adj;
non_prologue_insns += this_non_prologue_insn;
- /* Enough non-prologue insns seen or positive stack adjustment? */
- if (end_prologue_addr == 0 && (non_prologue_insns > 1 || sp_adj > 0))
- {
- end_prologue_addr = prev_non_prologue_insn ? prev_pc : cur_pc;
- break;
- }
+
+ /* A jump or branch, enough non-prologue insns seen or positive
+ stack adjustment? If so, then we must have reached the end
+ of the prologue by now. */
+ if (prev_delay_slot || non_prologue_insns > 1 || sp_adj > 0
+ || micromips_instruction_is_compact_branch (insn))
+ break;
+
prev_non_prologue_insn = this_non_prologue_insn;
+ prev_delay_slot = in_delay_slot;
prev_pc = cur_pc;
}
= this_cache->saved_regs[gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM];
}
- /* If we didn't reach the end of the prologue when scanning the function
- instructions, then set end_prologue_addr to the address of the
- instruction immediately after the last one we scanned. Unless the
- last one looked like a non-prologue instruction (and we looked ahead),
- in which case use its address instead. */
- if (end_prologue_addr == 0)
- end_prologue_addr = prev_non_prologue_insn ? prev_pc : cur_pc;
+ /* Set end_prologue_addr to the address of the instruction immediately
+ after the last one we scanned. Unless the last one looked like a
+ non-prologue instruction (and we looked ahead), in which case use
+ its address instead. */
+ end_prologue_addr
+ = prev_non_prologue_insn || prev_delay_slot ? prev_pc : cur_pc;
return end_prologue_addr;
}
struct frame_info *this_frame,
struct mips_frame_cache *this_cache)
{
- CORE_ADDR cur_pc;
+ int prev_non_prologue_insn;
+ int this_non_prologue_insn;
+ int non_prologue_insns;
CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for
frame-pointer. */
+ int prev_delay_slot;
+ CORE_ADDR prev_pc;
+ CORE_ADDR cur_pc;
CORE_ADDR sp;
long frame_offset;
int frame_reg = MIPS_SP_REGNUM;
- CORE_ADDR end_prologue_addr = 0;
+ CORE_ADDR end_prologue_addr;
int seen_sp_adjust = 0;
int load_immediate_bytes = 0;
- int in_delay_slot = 0;
+ int in_delay_slot;
int regsize_is_64_bits = (mips_abi_regsize (gdbarch) == 8);
/* Can be called when there's no process, and hence when there's no
limit_pc = start_pc + 200;
restart:
+ prev_non_prologue_insn = 0;
+ non_prologue_insns = 0;
+ prev_delay_slot = 0;
+ prev_pc = start_pc;
+ /* Permit at most one non-prologue non-control-transfer instruction
+ in the middle which may have been reordered by the compiler for
+ optimisation. */
frame_offset = 0;
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN32_SIZE)
{
unsigned long inst, high_word, low_word;
int reg;
+ this_non_prologue_insn = 0;
+ in_delay_slot = 0;
+
/* Fetch the instruction. */
inst = (unsigned long) mips_fetch_instruction (gdbarch, ISA_MIPS,
cur_pc, NULL);
initialize a local variable, so we accept them only before
a stack adjustment instruction was seen. */
else if (!seen_sp_adjust
+ && !prev_delay_slot
&& (high_word == 0x3c01 /* lui $at,n */
|| high_word == 0x3c08 /* lui $t0,n */
|| high_word == 0x3421 /* ori $at,$at,n */
|| high_word == 0x3408 /* ori $t0,$zero,n */
))
{
- if (end_prologue_addr == 0)
- load_immediate_bytes += MIPS_INSN32_SIZE; /* FIXME! */
+ load_immediate_bytes += MIPS_INSN32_SIZE; /* FIXME! */
+ }
+ /* Check for branches and jumps. The instruction in the delay
+ slot can be a part of the prologue, so move forward once more. */
+ else if (mips32_instruction_has_delay_slot (gdbarch, inst))
+ {
+ in_delay_slot = 1;
}
+ /* This instruction is not an instruction typically found
+ in a prologue, so we must have reached the end of the
+ prologue. */
else
{
- /* This instruction is not an instruction typically found
- in a prologue, so we must have reached the end of the
- prologue. */
- /* FIXME: brobecker/2004-10-10: Can't we just break out of this
- loop now? Why would we need to continue scanning the function
- instructions? */
- if (end_prologue_addr == 0)
- end_prologue_addr = cur_pc;
-
- /* Check for branches and jumps. For now, only jump to
- register are caught (i.e. returns). */
- if ((itype_op (inst) & 0x07) == 0 && rtype_funct (inst) == 8)
- in_delay_slot = 1;
+ this_non_prologue_insn = 1;
}
- /* If the previous instruction was a jump, we must have reached
- the end of the prologue by now. Stop scanning so that we do
- not go past the function return. */
- if (in_delay_slot)
+ non_prologue_insns += this_non_prologue_insn;
+
+ /* A jump or branch, or enough non-prologue insns seen? If so,
+ then we must have reached the end of the prologue by now. */
+ if (prev_delay_slot || non_prologue_insns > 1)
break;
+
+ prev_non_prologue_insn = this_non_prologue_insn;
+ prev_delay_slot = in_delay_slot;
+ prev_pc = cur_pc;
}
if (this_cache != NULL)
+ MIPS_RA_REGNUM];
}
- /* If we didn't reach the end of the prologue when scanning the function
- instructions, then set end_prologue_addr to the address of the
- instruction immediately after the last one we scanned. */
- /* brobecker/2004-10-10: I don't think this would ever happen, but
- we may as well be careful and do our best if we have a null
- end_prologue_addr. */
- if (end_prologue_addr == 0)
- end_prologue_addr = cur_pc;
+ /* Set end_prologue_addr to the address of the instruction immediately
+ after the last one we scanned. Unless the last one looked like a
+ non-prologue instruction (and we looked ahead), in which case use
+ its address instead. */
+ end_prologue_addr
+ = prev_non_prologue_insn || prev_delay_slot ? prev_pc : cur_pc;
/* In a frameless function, we might have incorrectly
skipped some load immediate instructions. Undo the skipping
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- if (is_compact_addr (addr))
- addr = unmake_compact_addr (addr);
-
if (mips_mask_address_p (tdep) && (((ULONGEST) addr) >> 32 == 0xffffffffUL))
/* This hack is a work-around for existing boards using PMON, the
simulator, and any other 64-bit targets that doesn't have true
"mips_eabi_push_dummy_call: %d len=%d type=%d",
argnum + 1, len, (int) typecode);
- /* Function pointer arguments to mips16 code need to be made into
- mips16 pointers. */
- if (typecode == TYPE_CODE_PTR
- && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
- {
- CORE_ADDR addr = extract_signed_integer (value_contents (arg),
- len, byte_order);
- if (mips_pc_is_mips (addr))
- val = value_contents (arg);
- else
- {
- store_signed_integer (valbuf, len, byte_order,
- make_compact_addr (addr));
- val = valbuf;
- }
- }
/* The EABI passes structures that do not fit in a register by
reference. */
- else if (len > regsize
+ if (len > regsize
&& (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
{
store_unsigned_integer (valbuf, regsize, byte_order,
for (argnum = 0; argnum < nargs; argnum++)
{
const gdb_byte *val;
- gdb_byte valbuf[MAX_REGISTER_SIZE];
struct value *arg = args[argnum];
struct type *arg_type = check_typedef (value_type (arg));
int len = TYPE_LENGTH (arg_type);
val = value_contents (arg);
- /* Function pointer arguments to mips16 code need to be made into
- mips16 pointers. */
- if (typecode == TYPE_CODE_PTR
- && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
- {
- CORE_ADDR addr = extract_signed_integer (value_contents (arg),
- len, byte_order);
- if (!mips_pc_is_mips (addr))
- {
- store_signed_integer (valbuf, len, byte_order,
- make_compact_addr (addr));
- val = valbuf;
- }
- }
-
/* Floating point arguments passed in registers have to be
treated specially. On 32-bit architectures, doubles are
passed in register pairs; the even FP register gets the
}
val = get_frame_register_value (frame, regnum);
- if (value_optimized_out (val))
- {
- fprintf_filtered (file, "%s: [Invalid]",
- gdbarch_register_name (gdbarch, regnum));
- return;
- }
fputs_filtered (gdbarch_register_name (gdbarch, regnum), file);
int size;
if ((mips_pc_is_mips (pc)
- && !mips32_instruction_has_delay_slot (gdbarch, pc))
+ && !mips32_insn_at_pc_has_delay_slot (gdbarch, pc))
|| (mips_pc_is_micromips (gdbarch, pc)
- && !micromips_instruction_has_delay_slot (gdbarch, pc, 0))
+ && !micromips_insn_at_pc_has_delay_slot (gdbarch, pc, 0))
|| (mips_pc_is_mips16 (gdbarch, pc)
- && !mips16_instruction_has_delay_slot (gdbarch, pc, 0)))
+ && !mips16_insn_at_pc_has_delay_slot (gdbarch, pc, 0)))
return 0;
isa = mips_pc_isa (gdbarch, pc);
*kindptr = 4;
}
-/* Return non-zero if the ADDR instruction has a branch delay slot
- (i.e. it is a jump or branch instruction). This function is based
- on mips32_next_pc. */
+/* Return non-zero if the standard MIPS instruction INST has a branch
+ delay slot (i.e. it is a jump or branch instruction). This function
+ is based on mips32_next_pc. */
static int
-mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr)
+mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
{
- unsigned long inst;
- int status;
int op;
int rs;
int rt;
- inst = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status);
- if (status)
- return 0;
-
op = itype_op (inst);
if ((inst & 0xe0000000) != 0)
{
}
}
-/* Return non-zero if the ADDR instruction, which must be a 32-bit
- instruction if MUSTBE32 is set or can be any instruction otherwise,
- has a branch delay slot (i.e. it is a non-compact jump instruction). */
+/* Return non-zero if a standard MIPS instruction at ADDR has a branch
+ delay slot (i.e. it is a jump or branch instruction). */
static int
-micromips_instruction_has_delay_slot (struct gdbarch *gdbarch,
- CORE_ADDR addr, int mustbe32)
+mips32_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr)
{
ULONGEST insn;
int status;
- insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status);
+ insn = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status);
if (status)
return 0;
- if (!mustbe32) /* 16-bit instructions. */
- return (micromips_op (insn) == 0x11
- /* POOL16C: bits 010001 */
- && (b5s5_op (insn) == 0xc
+ return mips32_instruction_has_delay_slot (gdbarch, insn);
+}
+
+/* Return non-zero if the microMIPS instruction INSN, comprising the
+ 16-bit major opcode word in the high 16 bits and any second word
+ in the low 16 bits, has a branch delay slot (i.e. it is a non-compact
+ jump or branch instruction). The instruction must be 32-bit if
+ MUSTBE32 is set or can be any instruction otherwise. */
+
+static int
+micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32)
+{
+ ULONGEST major = insn >> 16;
+
+ switch (micromips_op (major))
+ {
+ /* 16-bit instructions. */
+ case 0x33: /* B16: bits 110011 */
+ case 0x2b: /* BNEZ16: bits 101011 */
+ case 0x23: /* BEQZ16: bits 100011 */
+ return !mustbe32;
+ case 0x11: /* POOL16C: bits 010001 */
+ return (!mustbe32
+ && ((b5s5_op (major) == 0xc
/* JR16: bits 010001 01100 */
- || (b5s5_op (insn) & 0x1e) == 0xe))
+ || (b5s5_op (major) & 0x1e) == 0xe)));
/* JALR16, JALRS16: bits 010001 0111x */
- || (micromips_op (insn) & 0x37) == 0x23
- /* BEQZ16, BNEZ16: bits 10x011 */
- || micromips_op (insn) == 0x33;
- /* B16: bits 110011 */
-
- /* 32-bit instructions. */
- if (micromips_op (insn) == 0x0)
- /* POOL32A: bits 000000 */
- {
- insn <<= 16;
- insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status);
- if (status)
- return 0;
- return b0s6_op (insn) == 0x3c
- /* POOL32Axf: bits 000000 ... 111100 */
- && (b6s10_ext (insn) & 0x2bf) == 0x3c;
- /* JALR, JALR.HB: 000000 000x111100 111100 */
- /* JALRS, JALRS.HB: 000000 010x111100 111100 */
- }
-
- return (micromips_op (insn) == 0x10
- /* POOL32I: bits 010000 */
- && ((b5s5_op (insn) & 0x1c) == 0x0
+ /* 32-bit instructions. */
+ case 0x3d: /* JAL: bits 111101 */
+ case 0x3c: /* JALX: bits 111100 */
+ case 0x35: /* J: bits 110101 */
+ case 0x2d: /* BNE: bits 101101 */
+ case 0x25: /* BEQ: bits 100101 */
+ case 0x1d: /* JALS: bits 011101 */
+ return 1;
+ case 0x10: /* POOL32I: bits 010000 */
+ return ((b5s5_op (major) & 0x1c) == 0x0
/* BLTZ, BLTZAL, BGEZ, BGEZAL: 010000 000xx */
- || (b5s5_op (insn) & 0x1d) == 0x4
+ || (b5s5_op (major) & 0x1d) == 0x4
/* BLEZ, BGTZ: bits 010000 001x0 */
- || (b5s5_op (insn) & 0x1d) == 0x11
+ || (b5s5_op (major) & 0x1d) == 0x11
/* BLTZALS, BGEZALS: bits 010000 100x1 */
- || ((b5s5_op (insn) & 0x1e) == 0x14
- && (insn & 0x3) == 0x0)
+ || ((b5s5_op (major) & 0x1e) == 0x14
+ && (major & 0x3) == 0x0)
/* BC2F, BC2T: bits 010000 1010x xxx00 */
- || (b5s5_op (insn) & 0x1e) == 0x1a
+ || (b5s5_op (major) & 0x1e) == 0x1a
/* BPOSGE64, BPOSGE32: bits 010000 1101x */
- || ((b5s5_op (insn) & 0x1e) == 0x1c
- && (insn & 0x3) == 0x0)
+ || ((b5s5_op (major) & 0x1e) == 0x1c
+ && (major & 0x3) == 0x0)
/* BC1F, BC1T: bits 010000 1110x xxx00 */
- || ((b5s5_op (insn) & 0x1c) == 0x1c
- && (insn & 0x3) == 0x1)))
+ || ((b5s5_op (major) & 0x1c) == 0x1c
+ && (major & 0x3) == 0x1));
/* BC1ANY*: bits 010000 111xx xxx01 */
- || (micromips_op (insn) & 0x1f) == 0x1d
- /* JALS, JAL: bits x11101 */
- || (micromips_op (insn) & 0x37) == 0x25
- /* BEQ, BNE: bits 10x101 */
- || micromips_op (insn) == 0x35
- /* J: bits 110101 */
- || micromips_op (insn) == 0x3c;
- /* JALX: bits 111100 */
+ case 0x0: /* POOL32A: bits 000000 */
+ return (b0s6_op (insn) == 0x3c
+ /* POOL32Axf: bits 000000 ... 111100 */
+ && (b6s10_ext (insn) & 0x2bf) == 0x3c);
+ /* JALR, JALR.HB: 000000 000x111100 111100 */
+ /* JALRS, JALRS.HB: 000000 010x111100 111100 */
+ default:
+ return 0;
+ }
}
+/* Return non-zero if a microMIPS instruction at ADDR has a branch delay
+ slot (i.e. it is a non-compact jump instruction). The instruction
+ must be 32-bit if MUSTBE32 is set or can be any instruction otherwise. */
+
static int
-mips16_instruction_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr,
- int mustbe32)
+micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
+ CORE_ADDR addr, int mustbe32)
{
- unsigned short inst;
+ ULONGEST insn;
int status;
- inst = mips_fetch_instruction (gdbarch, ISA_MIPS16, addr, &status);
+ insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status);
if (status)
return 0;
+ insn <<= 16;
+ if (mips_insn_size (ISA_MICROMIPS, insn) == 2 * MIPS_INSN16_SIZE)
+ {
+ insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status);
+ if (status)
+ return 0;
+ }
- if (!mustbe32)
- return (inst & 0xf89f) == 0xe800; /* JR/JALR (16-bit instruction) */
+ return micromips_instruction_has_delay_slot (insn, mustbe32);
+}
+
+/* Return non-zero if the MIPS16 instruction INST, which must be
+ a 32-bit instruction if MUSTBE32 is set or can be any instruction
+ otherwise, has a branch delay slot (i.e. it is a non-compact jump
+ instruction). This function is based on mips16_next_pc. */
+
+static int
+mips16_instruction_has_delay_slot (unsigned short inst, int mustbe32)
+{
+ if ((inst & 0xf89f) == 0xe800) /* JR/JALR (16-bit instruction) */
+ return !mustbe32;
return (inst & 0xf800) == 0x1800; /* JAL/JALX (32-bit instruction) */
}
+/* Return non-zero if a MIPS16 instruction at ADDR has a branch delay
+ slot (i.e. it is a non-compact jump instruction). The instruction
+ must be 32-bit if MUSTBE32 is set or can be any instruction otherwise. */
+
+static int
+mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
+ CORE_ADDR addr, int mustbe32)
+{
+ unsigned short insn;
+ int status;
+
+ insn = mips_fetch_instruction (gdbarch, ISA_MIPS16, addr, &status);
+ if (status)
+ return 0;
+
+ return mips16_instruction_has_delay_slot (insn, mustbe32);
+}
+
/* Calculate the starting address of the MIPS memory segment BPADDR is in.
This assumes KSSEG exists. */
/* If the previous instruction has a branch delay slot, we have
to move the breakpoint to the branch instruction. */
prev_addr = bpaddr - 4;
- if (mips32_instruction_has_delay_slot (gdbarch, prev_addr))
+ if (mips32_insn_at_pc_has_delay_slot (gdbarch, prev_addr))
bpaddr = prev_addr;
}
else
{
- int (*instruction_has_delay_slot) (struct gdbarch *, CORE_ADDR, int);
+ int (*insn_at_pc_has_delay_slot) (struct gdbarch *, CORE_ADDR, int);
CORE_ADDR addr, jmpaddr;
int i;
2 bytes, so the idea is the same.
FIXME: We have to assume that bpaddr is not the second half
of an extended instruction. */
- instruction_has_delay_slot = (mips_pc_is_micromips (gdbarch, bpaddr)
- ? micromips_instruction_has_delay_slot
- : mips16_instruction_has_delay_slot);
+ insn_at_pc_has_delay_slot = (mips_pc_is_micromips (gdbarch, bpaddr)
+ ? micromips_insn_at_pc_has_delay_slot
+ : mips16_insn_at_pc_has_delay_slot);
jmpaddr = 0;
addr = bpaddr;
if (unmake_compact_addr (addr) == boundary)
break;
addr -= MIPS_INSN16_SIZE;
- if (i == 1 && instruction_has_delay_slot (gdbarch, addr, 0))
+ if (i == 1 && insn_at_pc_has_delay_slot (gdbarch, addr, 0))
/* Looks like a JR/JALR at [target-1], but it could be
the second word of a previous JAL/JALX, so record it
and check back one more. */
jmpaddr = addr;
- else if (i > 1 && instruction_has_delay_slot (gdbarch, addr, 1))
+ else if (i > 1 && insn_at_pc_has_delay_slot (gdbarch, addr, 1))
{
if (i == 2)
/* Looks like a JAL/JALX at [target-2], but it could also
which jumps to foo. */
msym = lookup_minimal_symbol_by_pc (pc);
if (msym.minsym == NULL
- || MSYMBOL_VALUE_ADDRESS (msym.minsym) != pc
+ || BMSYMBOL_VALUE_ADDRESS (msym) != pc
|| MSYMBOL_LINKAGE_NAME (msym.minsym) == NULL
|| strncmp (MSYMBOL_LINKAGE_NAME (msym.minsym), ".pic.", 5) != 0)
return 0;
new_pc = mips_skip_mips16_trampoline_code (frame, pc);
if (new_pc)
- {
- pc = new_pc;
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = new_pc;
new_pc = find_solib_trampoline_target (frame, pc);
if (new_pc)
- {
- pc = new_pc;
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = new_pc;
new_pc = mips_skip_pic_trampoline_code (frame, pc);
if (new_pc)
- {
- pc = new_pc;
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = new_pc;
}
while (pc != target_pc);
arches != NULL;
arches = gdbarch_list_lookup_by_info (arches->next, &info))
{
- /* MIPS needs to be pedantic about which ABI the object is
- using. */
+ /* MIPS needs to be pedantic about which ABI and the compressed
+ ISA variation the object is using. */
if (gdbarch_tdep (arches->gdbarch)->elf_flags != elf_flags)
continue;
if (gdbarch_tdep (arches->gdbarch)->mips_abi != mips_abi)
continue;
+ if (gdbarch_tdep (arches->gdbarch)->mips_isa != mips_isa)
+ continue;
/* Need to be pedantic about which register virtual size is
used. */
if (gdbarch_tdep (arches->gdbarch)->mips64_transfers_32bit_regs_p
tdep->mips_fpu_type = fpu_type;
tdep->register_size_valid_p = 0;
tdep->register_size = 0;
- tdep->gregset = NULL;
- tdep->gregset64 = NULL;
- tdep->fpregset = NULL;
- tdep->fpregset64 = NULL;
if (info.target_desc)
{
set_gdbarch_elf_make_msymbol_special (gdbarch,
mips_elf_make_msymbol_special);
+ set_gdbarch_make_symbol_special (gdbarch, mips_make_symbol_special);
+ set_gdbarch_adjust_dwarf2_addr (gdbarch, mips_adjust_dwarf2_addr);
+ set_gdbarch_adjust_dwarf2_line (gdbarch, mips_adjust_dwarf2_line);
regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct mips_regnum);
*regnum = mips_regnum;