2008-08-09 Richard Sandiford <rdsandiford@googlemail.com>
+ * config/mips/mips.h (MASK_RETURN_ADDR): Expand commentary.
+ * config/mips/linux-unwind.h (mips_fallback_frame_state): Add 2
+ rather than 4 to PC.
+
+2008-08-09 Richard Sandiford <rdsandiford@googlemail.com>
+
* config/mips/mips.h (STATIC_CHAIN_REGNUM): Remap to $15.
(FUNCTION_PROFILER): Save the static chain pointer into $2
beforehand and restore it aftewards.
fs->regs.reg[i].loc.offset
= (_Unwind_Ptr)&(sc->sc_regs[i]) + reg_offset - new_cfa;
}
- /* The PC points to the faulting instruction, but the unwind tables
- expect it point to the following instruction. We compensate by
- reporting a return address at the next instruction. */
+ /* "PC & -2" points to the faulting instruction, but the unwind code
+ searches for "(ADDR & -2) - 1". (See MASK_RETURN_ADDR for the source
+ of the -2 mask.) Adding 2 here ensures that "(ADDR & -2) - 1" is the
+ address of the second byte of the faulting instruction.
+
+ Note that setting fs->signal_frame would not work. As the comment
+ above MASK_RETURN_ADDR explains, MIPS unwinders must earch for an
+ odd-valued address. */
fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_VAL_OFFSET;
fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset
- = (_Unwind_Ptr)(sc->sc_pc) + 4 - new_cfa;
+ = (_Unwind_Ptr)(sc->sc_pc) + 2 - new_cfa;
fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN;
return _URC_NO_REASON;
#define RETURN_ADDR_RTX mips_return_addr
-/* Since the mips16 ISA mode is encoded in the least-significant bit
- of the address, mask it off return addresses for purposes of
- finding exception handling regions. */
-
+/* Mask off the MIPS16 ISA bit in unwind addresses.
+
+ The reason for this is a little subtle. When unwinding a call,
+ we are given the call's return address, which on most targets
+ is the address of the following instruction. However, what we
+ actually want to find is the EH region for the call itself.
+ The target-independent unwind code therefore searches for "RA - 1".
+
+ In the MIPS16 case, RA is always an odd-valued (ISA-encoded) address.
+ RA - 1 is therefore the real (even-valued) start of the return
+ instruction. EH region labels are usually odd-valued MIPS16 symbols
+ too, so a search for an even address within a MIPS16 region would
+ usually work.
+
+ However, there is an exception. If the end of an EH region is also
+ the end of a function, the end label is allowed to be even. This is
+ necessary because a following non-MIPS16 function may also need EH
+ information for its first instruction.
+
+ Thus a MIPS16 region may be terminated by an ISA-encoded or a
+ non-ISA-encoded address. This probably isn't ideal, but it is
+ the traditional (legacy) behavior. It is therefore only safe
+ to search MIPS EH regions for an _odd-valued_ address.
+
+ Masking off the ISA bit means that the target-independent code
+ will search for "(RA & -2) - 1", which is guaranteed to be odd. */
#define MASK_RETURN_ADDR GEN_INT (-2)