arm-macosx-nat-exec.c [plain text]
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "target.h"
#include "gdbcore.h"
#include "symfile.h"
#include "objfiles.h"
#include "regcache.h"
#include "gdbarch.h"
#include "arch-utils.h"
#include "macosx-nat-mutils.h"
#include "arm-tdep.h"
#include "arm-macosx-thread-status.h"
#include "arm-macosx-tdep.h"
extern enum gdb_osabi arm_set_osabi_from_host_info ();
static inline uint32_t
collect_uint32 (int regnum)
{
gdb_byte buf[sizeof(uint32_t)];
regcache_raw_collect (current_regcache, regnum, buf);
return extract_unsigned_integer (buf, sizeof(uint32_t));
}
static inline uint64_t
collect_uint64 (int regnum)
{
gdb_byte buf[sizeof(uint64_t)];
regcache_raw_collect (current_regcache, regnum, buf);
return extract_unsigned_integer (buf, sizeof(uint64_t));
}
static inline void
supply_uint32 (int regnum, uint32_t val)
{
gdb_byte buf[sizeof(val)];
store_unsigned_integer (buf, sizeof(val), val);
regcache_raw_supply (current_regcache, regnum, buf);
}
static inline void
supply_uint64 (int regnum, uint64_t val)
{
gdb_byte buf[sizeof(val)];
store_unsigned_integer (buf, sizeof(val), val);
regcache_raw_supply (current_regcache, regnum, buf);
}
void
arm_macosx_fetch_gp_registers (struct gdb_arm_thread_state *gp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_GP_REGS; i++)
supply_uint32 (ARM_R0_REGNUM + i, gp_regs->r[i]);
supply_uint32 (ARM_PS_REGNUM, gp_regs->cpsr);
}
void
arm_macosx_fetch_gp_registers_raw (struct gdb_arm_thread_state *gp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_GP_REGS; i++)
regcache_raw_supply (current_regcache, ARM_R0_REGNUM + i, &gp_regs->r[i]);
regcache_raw_supply (current_regcache, ARM_PS_REGNUM, &gp_regs->cpsr);
}
void
arm_macosx_store_gp_registers (struct gdb_arm_thread_state *gp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_GP_REGS; i++)
gp_regs->r[i] = collect_uint32 (ARM_R0_REGNUM + i);
gp_regs->cpsr = collect_uint32 (ARM_PS_REGNUM);
}
void
arm_macosx_store_gp_registers_raw (struct gdb_arm_thread_state *gp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_GP_REGS; i++)
regcache_raw_collect (current_regcache, ARM_R0_REGNUM + i, &gp_regs->r[i]);
regcache_raw_collect (current_regcache, ARM_PS_REGNUM, &gp_regs->cpsr);
}
void
arm_macosx_fetch_vfpv1_regs (gdb_arm_thread_vfpv1_state_t *fp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_VFP_REGS; i++)
supply_uint32 (ARM_VFP_REGNUM_S0 + i, fp_regs->r[i]);
supply_uint32 (ARM_VFP_REGNUM_FPSCR, fp_regs->fpscr);
}
void
arm_macosx_fetch_vfpv3_regs (gdb_arm_thread_vfpv3_state_t *fp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_VFP_REGS; i++)
supply_uint32 (ARM_VFP_REGNUM_S0 + i, fp_regs->s[i]);
for (i = 0; i < ARM_MACOSX_NUM_VFPV3_REGS; i++)
supply_uint64 (ARM_VFPV3_REGNUM_D16 + i, fp_regs->d[i]);
supply_uint32 (ARM_VFP_REGNUM_FPSCR, fp_regs->fpscr);
}
void
arm_macosx_fetch_vfpv1_regs_raw (gdb_arm_thread_vfpv1_state_t *fp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_VFP_REGS; i++)
regcache_raw_supply (current_regcache, ARM_VFP_REGNUM_S0 + i,
&fp_regs->r[i]);
regcache_raw_supply (current_regcache, ARM_VFP_REGNUM_FPSCR, &fp_regs->fpscr);
}
void
arm_macosx_fetch_vfpv3_regs_raw (gdb_arm_thread_vfpv3_state_t *fp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_VFP_REGS; i++)
regcache_raw_supply (current_regcache, ARM_VFP_REGNUM_S0 + i,
&fp_regs->s[i]);
regcache_raw_supply (current_regcache, ARM_VFP_REGNUM_FPSCR, &fp_regs->fpscr);
for (i = 0; i < ARM_MACOSX_NUM_VFPV3_REGS; i++)
regcache_raw_supply (current_regcache, ARM_VFPV3_REGNUM_D16 + i,
&fp_regs->d[i]);
}
void
arm_macosx_store_vfpv1_regs (gdb_arm_thread_vfpv1_state_t *fp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_VFP_REGS; i++)
fp_regs->r[i] = collect_uint32 (ARM_VFP_REGNUM_S0 + i);
fp_regs->fpscr = collect_uint32 (ARM_VFP_REGNUM_FPSCR);
}
void
arm_macosx_store_vfpv3_regs (gdb_arm_thread_vfpv3_state_t *fp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_VFP_REGS; i++)
fp_regs->s[i] = collect_uint32 (ARM_VFP_REGNUM_S0 + i);
for (i = 0; i < ARM_MACOSX_NUM_VFPV3_REGS; i++)
fp_regs->d[i] = collect_uint64 (ARM_VFPV3_REGNUM_D16 + i);
fp_regs->fpscr = collect_uint32 (ARM_VFP_REGNUM_FPSCR);
}
void
arm_macosx_store_vfpv1_regs_raw (gdb_arm_thread_vfpv1_state_t *fp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_VFP_REGS; i++)
regcache_raw_collect (current_regcache, ARM_VFP_REGNUM_S0 + i,
&fp_regs->r[i]);
regcache_raw_collect (current_regcache, ARM_VFP_REGNUM_FPSCR, &fp_regs->fpscr);
}
void
arm_macosx_store_vfpv3_regs_raw (gdb_arm_thread_vfpv3_state_t *fp_regs)
{
int i;
for (i = 0; i < ARM_MACOSX_NUM_VFP_REGS; i++)
regcache_raw_collect (current_regcache, ARM_VFP_REGNUM_S0 + i,
&fp_regs->s[i]);
regcache_raw_collect (current_regcache, ARM_VFP_REGNUM_FPSCR, &fp_regs->fpscr);
for (i = 0; i < ARM_MACOSX_NUM_VFPV3_REGS; i++)
regcache_raw_collect (current_regcache, ARM_VFPV3_REGNUM_D16 + i,
&fp_regs->d[i]);
}
static void
validate_inferior_registers (int regno)
{
int i;
if (regno == -1)
{
for (i = 0; i < NUM_GREGS; i++)
{
if (!register_cached (i))
fetch_inferior_registers (i);
}
if (!register_cached (ARM_PS_REGNUM))
fetch_inferior_registers (ARM_PS_REGNUM);
}
else if (!register_cached (regno))
{
fetch_inferior_registers (regno);
}
}
void
fetch_inferior_registers (int regno)
{
int i;
thread_t current_thread = ptid_get_tid (inferior_ptid);
kern_return_t ret = KERN_SUCCESS;
if (TARGET_OSABI == GDB_OSABI_UNKNOWN)
arm_set_osabi_from_host_info ();
if ((regno == -1) || ARM_MACOSX_IS_GP_RELATED_REGNUM (regno))
{
struct gdb_arm_thread_state gp_regs;
unsigned int gp_count = GDB_ARM_THREAD_STATE_COUNT;
ret = thread_get_state
(current_thread, GDB_ARM_THREAD_STATE, (thread_state_t) & gp_regs,
&gp_count);
if (ret != KERN_SUCCESS)
{
printf ("Error calling thread_get_state for GP registers for thread 0x%ulx",
current_thread);
MACH_CHECK_ERROR (ret);
}
MACH_CHECK_ERROR (ret);
arm_macosx_fetch_gp_registers (&gp_regs);
}
if ((regno == -1) || ARM_MACOSX_IS_FP_RELATED_REGNUM (regno))
{
for (i = ARM_F0_REGNUM; i <= ARM_F7_REGNUM; i++)
set_register_cached (i, 1);
set_register_cached (ARM_FPS_REGNUM, 1);
}
if ((regno == -1) || ARM_MACOSX_IS_VFP_RELATED_REGNUM (regno))
{
enum arm_vfp_version vfp_version;
vfp_version = gdbarch_tdep (current_gdbarch)->vfp_version;
int fp_byte_size = -1;
switch (vfp_version)
{
case ARM_VFP_UNSUPPORTED:
fp_byte_size = 0;
break;
case ARM_VFP_VERSION_1:
{
gdb_arm_thread_vfpv1_state_t fp_regs;
mach_msg_type_number_t fp_count = GDB_ARM_THREAD_FPSTATE_VFPV1_COUNT;
ret = thread_get_state (current_thread, GDB_ARM_THREAD_FPSTATE,
(thread_state_t) & fp_regs,
&fp_count);
if (ret != KERN_SUCCESS)
{
printf ("Error calling thread_get_state for VFP registers for thread 0x%ulx",
current_thread);
MACH_CHECK_ERROR (ret);
}
arm_macosx_fetch_vfpv1_regs (&fp_regs);
}
break;
case ARM_VFP_VERSION_3:
{
gdb_arm_thread_vfpv3_state_t fp_regs;
mach_msg_type_number_t fp_count = GDB_ARM_THREAD_FPSTATE_VFPV3_COUNT;
ret = thread_get_state (current_thread, GDB_ARM_THREAD_FPSTATE,
(thread_state_t) & fp_regs,
&fp_count);
if (ret != KERN_SUCCESS)
{
printf ("Error calling thread_get_state for VFP registers for thread 0x%ulx",
current_thread);
MACH_CHECK_ERROR (ret);
}
arm_macosx_fetch_vfpv3_regs (&fp_regs);
}
break;
default:
error ("fetch_inferior_registers: unable to fetch ARM_THREAD_FPSTATE: "
"unsupported vfp version: %d", (int)vfp_version);
break;
}
}
}
void
store_inferior_registers (int regno)
{
int current_pid;
thread_t current_thread;
kern_return_t ret;
current_pid = ptid_get_pid (inferior_ptid);
current_thread = ptid_get_tid (inferior_ptid);
validate_inferior_registers (regno);
if ((regno == -1) || ARM_MACOSX_IS_GP_RELATED_REGNUM (regno))
{
struct gdb_arm_thread_state gp_regs;
arm_macosx_store_gp_registers (&gp_regs);
ret = thread_set_state (current_thread, GDB_ARM_THREAD_STATE,
(thread_state_t) & gp_regs,
GDB_ARM_THREAD_STATE_COUNT);
MACH_CHECK_ERROR (ret);
}
if ((regno == -1) || ARM_MACOSX_IS_VFP_RELATED_REGNUM (regno))
{
enum arm_vfp_version vfp_version;
vfp_version = gdbarch_tdep (current_gdbarch)->vfp_version;
int fp_byte_size = -1;
switch (vfp_version)
{
case ARM_VFP_UNSUPPORTED:
fp_byte_size = 0;
break;
case ARM_VFP_VERSION_1:
{
gdb_arm_thread_vfpv1_state_t fp_regs;
arm_macosx_store_vfpv1_regs (&fp_regs);
ret = thread_set_state (current_thread, GDB_ARM_THREAD_FPSTATE,
(thread_state_t) & fp_regs,
GDB_ARM_THREAD_FPSTATE_VFPV1_COUNT);
MACH_CHECK_ERROR (ret);
}
break;
case ARM_VFP_VERSION_3:
{
gdb_arm_thread_vfpv3_state_t fp_regs;
arm_macosx_store_vfpv3_regs (&fp_regs);
ret = thread_set_state (current_thread, GDB_ARM_THREAD_FPSTATE,
(thread_state_t) & fp_regs,
GDB_ARM_THREAD_FPSTATE_VFPV3_COUNT);
MACH_CHECK_ERROR (ret);
}
break;
default:
error ("store_inferior_registers: unable to store ARM_THREAD_FPSTATE: "
"unsupported vfp version: %d", (int)vfp_version);
break;
}
}
}
void
macosx_complete_child_target (struct target_ops *target)
{
}