/* Target-dependent code for FreeBSD/mips.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
This file is part of GDB.
/* Number of registers in `struct fpreg' from <machine/reg.h>. The
first 32 hold floating point registers. 33 holds the FSR. The
- 34th is a dummy for padding. */
+ 34th holds FIR on FreeBSD 12.0 and newer kernels. On older kernels
+ it was a zero-filled dummy for padding. */
#define MIPS_FBSD_NUM_FPREGS 34
/* Supply a single register. The register size might not match, so use
mips_fbsd_supply_fpregs (struct regcache *regcache, int regnum,
const void *fpregs, size_t regsize)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
const gdb_byte *regs = (const gdb_byte *) fpregs;
- int i, fp0num, fsrnum;
+ int i, fp0num;
fp0num = mips_regnum (gdbarch)->fp0;
- fsrnum = mips_regnum (gdbarch)->fp_control_status;
- for (i = fp0num; i <= fsrnum; i++)
- if (regnum == i || regnum == -1)
- mips_fbsd_supply_reg (regcache, i,
- regs + (i - fp0num) * regsize, regsize);
+ for (i = 0; i <= 32; i++)
+ if (regnum == fp0num + i || regnum == -1)
+ mips_fbsd_supply_reg (regcache, fp0num + i,
+ regs + i * regsize, regsize);
+ if (regnum == mips_regnum (gdbarch)->fp_control_status || regnum == -1)
+ mips_fbsd_supply_reg (regcache, mips_regnum (gdbarch)->fp_control_status,
+ regs + 32 * regsize, regsize);
+ if ((regnum == mips_regnum (gdbarch)->fp_implementation_revision
+ || regnum == -1)
+ && extract_unsigned_integer (regs + 33 * regsize, regsize,
+ gdbarch_byte_order (gdbarch)) != 0)
+ mips_fbsd_supply_reg (regcache,
+ mips_regnum (gdbarch)->fp_implementation_revision,
+ regs + 33 * regsize, regsize);
}
/* Supply the general-purpose registers stored in GREGS to REGCACHE.
mips_fbsd_supply_gregs (struct regcache *regcache, int regnum,
const void *gregs, size_t regsize)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
const gdb_byte *regs = (const gdb_byte *) gregs;
int i;
mips_fbsd_collect_fpregs (const struct regcache *regcache, int regnum,
void *fpregs, size_t regsize)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
gdb_byte *regs = (gdb_byte *) fpregs;
- int i, fp0num, fsrnum;
+ int i, fp0num;
fp0num = mips_regnum (gdbarch)->fp0;
- fsrnum = mips_regnum (gdbarch)->fp_control_status;
- for (i = fp0num; i <= fsrnum; i++)
- if (regnum == i || regnum == -1)
- mips_fbsd_collect_reg (regcache, i,
- regs + (i - fp0num) * regsize, regsize);
+ for (i = 0; i < 32; i++)
+ if (regnum == fp0num + i || regnum == -1)
+ mips_fbsd_collect_reg (regcache, fp0num + i,
+ regs + i * regsize, regsize);
+ if (regnum == mips_regnum (gdbarch)->fp_control_status || regnum == -1)
+ mips_fbsd_collect_reg (regcache, mips_regnum (gdbarch)->fp_control_status,
+ regs + 32 * regsize, regsize);
+ if (regnum == mips_regnum (gdbarch)->fp_implementation_revision
+ || regnum == -1)
+ mips_fbsd_collect_reg (regcache,
+ mips_regnum (gdbarch)->fp_implementation_revision,
+ regs + 33 * regsize, regsize);
}
/* Collect the general-purpose registers from REGCACHE and store them
mips_fbsd_collect_gregs (const struct regcache *regcache, int regnum,
void *gregs, size_t regsize)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
gdb_byte *regs = (gdb_byte *) gregs;
int i;
struct regcache *regcache,
int regnum, const void *fpregs, size_t len)
{
- size_t regsize = mips_abi_regsize (get_regcache_arch (regcache));
+ size_t regsize = mips_abi_regsize (regcache->arch ());
gdb_assert (len >= MIPS_FBSD_NUM_FPREGS * regsize);
const struct regcache *regcache,
int regnum, void *fpregs, size_t len)
{
- size_t regsize = mips_abi_regsize (get_regcache_arch (regcache));
+ size_t regsize = mips_abi_regsize (regcache->arch ());
gdb_assert (len >= MIPS_FBSD_NUM_FPREGS * regsize);
struct regcache *regcache, int regnum,
const void *gregs, size_t len)
{
- size_t regsize = mips_abi_regsize (get_regcache_arch (regcache));
+ size_t regsize = mips_abi_regsize (regcache->arch ());
gdb_assert (len >= MIPS_FBSD_NUM_GREGS * regsize);
const struct regcache *regcache,
int regnum, void *gregs, size_t len)
{
- size_t regsize = mips_abi_regsize (get_regcache_arch (regcache));
+ size_t regsize = mips_abi_regsize (regcache->arch ());
gdb_assert (len >= MIPS_FBSD_NUM_GREGS * regsize);
{
size_t regsize = mips_abi_regsize (gdbarch);
- cb (".reg", MIPS_FBSD_NUM_GREGS * regsize, &mips_fbsd_gregset,
- NULL, cb_data);
- cb (".reg2", MIPS_FBSD_NUM_FPREGS * regsize, &mips_fbsd_fpregset,
- NULL, cb_data);
+ cb (".reg", MIPS_FBSD_NUM_GREGS * regsize, MIPS_FBSD_NUM_GREGS * regsize,
+ &mips_fbsd_gregset, NULL, cb_data);
+ cb (".reg2", MIPS_FBSD_NUM_FPREGS * regsize, MIPS_FBSD_NUM_FPREGS * regsize,
+ &mips_fbsd_fpregset, NULL, cb_data);
}
/* Signal trampoline support. */
SIGTRAMP_FRAME,
MIPS_INSN32_SIZE,
{
- { MIPS_INST_ADDIU_A0_SP_O32, -1 }, /* addiu a0, sp, SIGF_UC */
- { MIPS_INST_LI_V0_SIGRETURN, -1 }, /* li v0, SYS_sigreturn */
- { MIPS_INST_SYSCALL, -1 }, /* syscall */
- { MIPS_INST_BREAK, -1 }, /* break */
- { TRAMP_SENTINEL_INSN, -1 }
+ { MIPS_INST_ADDIU_A0_SP_O32, ULONGEST_MAX }, /* addiu a0, sp, SIGF_UC */
+ { MIPS_INST_LI_V0_SIGRETURN, ULONGEST_MAX }, /* li v0, SYS_sigreturn */
+ { MIPS_INST_SYSCALL, ULONGEST_MAX }, /* syscall */
+ { MIPS_INST_BREAK, ULONGEST_MAX }, /* break */
+ { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
},
mips_fbsd_sigframe_init
};
trad_frame_set_id (cache, frame_id_build (sp, func));
}
+#define MIPS_INST_ADDIU_A0_SP_N32 (0x27a40000 \
+ + N64_SIGFRAME_UCONTEXT_OFFSET)
+
+static const struct tramp_frame mipsn32_fbsd_sigframe =
+{
+ SIGTRAMP_FRAME,
+ MIPS_INSN32_SIZE,
+ {
+ { MIPS_INST_ADDIU_A0_SP_N32, ULONGEST_MAX }, /* addiu a0, sp, SIGF_UC */
+ { MIPS_INST_LI_V0_SIGRETURN, ULONGEST_MAX }, /* li v0, SYS_sigreturn */
+ { MIPS_INST_SYSCALL, ULONGEST_MAX }, /* syscall */
+ { MIPS_INST_BREAK, ULONGEST_MAX }, /* break */
+ { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
+ },
+ mips64_fbsd_sigframe_init
+};
+
#define MIPS_INST_DADDIU_A0_SP_N64 (0x67a40000 \
+ N64_SIGFRAME_UCONTEXT_OFFSET)
SIGTRAMP_FRAME,
MIPS_INSN32_SIZE,
{
- { MIPS_INST_DADDIU_A0_SP_N64, -1 }, /* daddiu a0, sp, SIGF_UC */
- { MIPS_INST_LI_V0_SIGRETURN, -1 }, /* li v0, SYS_sigreturn */
- { MIPS_INST_SYSCALL, -1 }, /* syscall */
- { MIPS_INST_BREAK, -1 }, /* break */
- { TRAMP_SENTINEL_INSN, -1 }
+ { MIPS_INST_DADDIU_A0_SP_N64, ULONGEST_MAX }, /* daddiu a0, sp, SIGF_UC */
+ { MIPS_INST_LI_V0_SIGRETURN, ULONGEST_MAX }, /* li v0, SYS_sigreturn */
+ { MIPS_INST_SYSCALL, ULONGEST_MAX }, /* syscall */
+ { MIPS_INST_BREAK, ULONGEST_MAX }, /* break */
+ { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
},
mips64_fbsd_sigframe_init
};
tramp_frame_prepend_unwinder (gdbarch, &mips_fbsd_sigframe);
break;
case MIPS_ABI_N32:
+ tramp_frame_prepend_unwinder (gdbarch, &mipsn32_fbsd_sigframe);
break;
case MIPS_ABI_N64:
tramp_frame_prepend_unwinder (gdbarch, &mips64_fbsd_sigframe);
mips_fbsd_ilp32_fetch_link_map_offsets :
mips_fbsd_lp64_fetch_link_map_offsets));
}
-\f
-
-/* Provide a prototype to silence -Wmissing-prototypes. */
-void _initialize_mips_fbsd_tdep (void);
void
_initialize_mips_fbsd_tdep (void)