When fetching registers, if CPSR is zero (and hence we've just fetched from

a 26-bit target), split R15 into PC and CPSR.  Similarly, when storing
registers, copy CPSR back into R15 if CPSR indicates a 26-bit mode.
This makes single-stepping work correctly on arm26.

Also, when fetching registers, set arm_apcs_32 based on the mode the target's
in.  This removes the need to kludge it manually.  The variable should really
be lost entirely, and arm-tdep.c should look at the mode bits in CPSR, but
the ARM Linux target is horribly broken in this area, and will either need
fixing or working around.
This commit is contained in:
bjh21 2001-10-25 20:55:13 +00:00
parent 786a6026c6
commit b685397e2d
1 changed files with 28 additions and 22 deletions

View File

@ -28,6 +28,14 @@
#include <machine/frame.h>
#include "inferior.h"
#define R15_PSR 0xfc000003
#define R15_PC 0x03fffffc
#define PSR_MODE_32 0x00000010
/* From arm-tdep.c */
extern int arm_apcs_32;
void
fetch_inferior_registers (regno)
int regno;
@ -36,6 +44,13 @@ fetch_inferior_registers (regno)
struct fpreg inferior_fpregisters;
ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &inferior_registers, 0);
if (inferior_registers.r_cpsr == 0)
{
/* 26-bit target: split PC and PSR out of R15. */
inferior_registers.r_cpsr = inferior_registers.r_pc & R15_PSR;
inferior_registers.r_pc = inferior_registers.r_pc & R15_PC;
}
arm_apcs_32 = (inferior_registers.r_cpsr & PSR_MODE_32) != 0;
memcpy (&registers[REGISTER_BYTE (0)], &inferior_registers,
16 * sizeof (unsigned int));
memcpy (&registers[REGISTER_BYTE (PS_REGNUM)], &inferior_registers.r_cpsr,
@ -59,6 +74,12 @@ store_inferior_registers (regno)
16 * sizeof (unsigned int));
memcpy (&inferior_registers.r_cpsr, &registers[REGISTER_BYTE (PS_REGNUM)],
sizeof (unsigned int));
if ((inferior_registers.r_cpsr & PSR_MODE_32) == 0)
{
/* Target is in 26-bit mode. Merge PSR into R15. */
inferior_registers.r_pc &= R15_PC;
inferior_registers.r_pc |= inferior_registers.r_cpsr & R15_PSR;
}
ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &inferior_registers, 0);
/* XXX Set FP regs. */
@ -79,6 +100,13 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
{
struct md_core *core_reg = (struct md_core *) core_reg_sect;
if (core_reg->intreg.r_cpsr == 0)
{
/* 26-bit target: split PC and PSR out of R15. */
core_reg->intreg.r_cpsr = core_reg->intreg.r_pc & R15_PSR;
core_reg->intreg.r_pc = core_reg->intreg.r_pc & R15_PC;
}
arm_apcs_32 = (core_reg->intreg.r_cpsr & PSR_MODE_32) != 0;
/* integer registers */
memcpy (&registers[REGISTER_BYTE (0)], &core_reg->intreg,
sizeof (struct reg));
@ -95,25 +123,3 @@ get_longjmp_target (CORE_ADDR *addr)
{
return 0;
}
extern int arm_apcs_32;
void
_initialize_armnbsd_nat (void)
{
int mib[2];
char machine[16];
size_t len;
/* XXX Grotty hack to guess whether this is a 26-bit system. This
should really be determined on the fly, to allow debugging a
32-bit core on a 26-bit machine, or a 26-bit process on a 32-bit
machine. For now, users will just have to use "set apcs32" as
appropriate. */
mib[0] = CTL_HW;
mib[1] = HW_MACHINE;
len = sizeof (machine);
if (sysctl (mib, 2, machine, &len, NULL, 0) == 0 &&
strcmp (machine, "arm26") == 0)
arm_apcs_32 = 0;
}