+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ int ireg, reg_position;
+ CORE_ADDR frame_sp = get_frame_sp (this_frame);
+ CORE_ADDR sigcontext_base;
+ const struct mips_regnum *regs = mips_regnum (gdbarch);
+ CORE_ADDR regs_base;
+
+ if (self == &mips_linux_o32_sigframe)
+ sigcontext_base = frame_sp + SIGFRAME_SIGCONTEXT_OFFSET;
+ else
+ sigcontext_base = frame_sp + RTSIGFRAME_SIGCONTEXT_OFFSET;
+
+ /* I'm not proud of this hack. Eventually we will have the
+ infrastructure to indicate the size of saved registers on a
+ per-frame basis, but right now we don't; the kernel saves eight
+ bytes but we only want four. Use regs_base to access any
+ 64-bit fields. */
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ regs_base = sigcontext_base + 4;
+ else
+ regs_base = sigcontext_base;
+
+ if (mips_linux_restart_reg_p (gdbarch))
+ trad_frame_set_reg_addr (this_cache,
+ (MIPS_RESTART_REGNUM
+ + gdbarch_num_regs (gdbarch)),
+ regs_base + SIGCONTEXT_REGS);
+
+ for (ireg = 1; ireg < 32; ireg++)
+ trad_frame_set_reg_addr (this_cache,
+ ireg + MIPS_ZERO_REGNUM
+ + gdbarch_num_regs (gdbarch),
+ regs_base + SIGCONTEXT_REGS
+ + ireg * SIGCONTEXT_REG_SIZE);
+
+ /* The way that floating point registers are saved, unfortunately,
+ depends on the architecture the kernel is built for. For the r3000 and
+ tx39, four bytes of each register are at the beginning of each of the
+ 32 eight byte slots. For everything else, the registers are saved
+ using double precision; only the even-numbered slots are initialized,
+ and the high bits are the odd-numbered register. Assume the latter
+ layout, since we can't tell, and it's much more common. Which bits are
+ the "high" bits depends on endianness. */
+ for (ireg = 0; ireg < 32; ireg++)
+ if ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) != (ireg & 1))
+ trad_frame_set_reg_addr (this_cache,
+ ireg + regs->fp0 +
+ gdbarch_num_regs (gdbarch),
+ sigcontext_base + SIGCONTEXT_FPREGS + 4
+ + (ireg & ~1) * SIGCONTEXT_REG_SIZE);
+ else
+ trad_frame_set_reg_addr (this_cache,
+ ireg + regs->fp0
+ + gdbarch_num_regs (gdbarch),
+ sigcontext_base + SIGCONTEXT_FPREGS
+ + (ireg & ~1) * SIGCONTEXT_REG_SIZE);
+
+ trad_frame_set_reg_addr (this_cache,
+ regs->pc + gdbarch_num_regs (gdbarch),
+ regs_base + SIGCONTEXT_PC);
+
+ trad_frame_set_reg_addr (this_cache,
+ regs->fp_control_status
+ + gdbarch_num_regs (gdbarch),
+ sigcontext_base + SIGCONTEXT_FPCSR);
+ trad_frame_set_reg_addr (this_cache,
+ regs->hi + gdbarch_num_regs (gdbarch),
+ regs_base + SIGCONTEXT_HI);
+ trad_frame_set_reg_addr (this_cache,
+ regs->lo + gdbarch_num_regs (gdbarch),
+ regs_base + SIGCONTEXT_LO);
+ trad_frame_set_reg_addr (this_cache,
+ regs->cause + gdbarch_num_regs (gdbarch),
+ sigcontext_base + SIGCONTEXT_CAUSE);
+ trad_frame_set_reg_addr (this_cache,
+ regs->badvaddr + gdbarch_num_regs (gdbarch),
+ sigcontext_base + SIGCONTEXT_BADVADDR);
+
+ /* Choice of the bottom of the sigframe is somewhat arbitrary. */
+ trad_frame_set_id (this_cache, frame_id_build (frame_sp, func));
+}