summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorbjh21 <bjh21@NetBSD.org>2001-10-25 20:55:13 +0000
committerbjh21 <bjh21@NetBSD.org>2001-10-25 20:55:13 +0000
commitb685397e2d2d99d8946bf79c836fbd85628cc29f (patch)
tree2e035389b4d82533018568b0f1a4defb202385e0 /gnu
parent786a6026c691bc5abe01d7201f13f800f83bd11a (diff)
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.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/dist/toolchain/gdb/armnbsd-nat.c50
1 files changed, 28 insertions, 22 deletions
diff --git a/gnu/dist/toolchain/gdb/armnbsd-nat.c b/gnu/dist/toolchain/gdb/armnbsd-nat.c
index 523ef216098..acedc6c8984 100644
--- a/gnu/dist/toolchain/gdb/armnbsd-nat.c
+++ b/gnu/dist/toolchain/gdb/armnbsd-nat.c
@@ -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;
-}