[vxworks 09/14] remote-wtx-hw / register fetch/store support.

Joel Brobecker
2010-04-25T15:48:24Z

This module is in charge of fetching/storing a given register. There
are two issues to consider:
- GDB regno to WTX regno translation;
- determine which register set a given register belongs to.

2010-04-24 Joel Brobecker <brobecker@adacore.com>

* remote-wtx-hw.h, remote-wtx-hw.c: New files.
---
gdb/remote-wtx-hw.c | 552 +++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/remote-wtx-hw.h | 56 +++++
2 files changed, 608 insertions(+), 0 deletions(-)
create mode 100644 gdb/remote-wtx-hw.c
create mode 100644 gdb/remote-wtx-hw.h

diff --git a/gdb/remote-wtx-hw.c b/gdb/remote-wtx-hw.c
new file mode 100644
index 0000000..fb87dab
--- /dev/null
+++ b/gdb/remote-wtx-hw.c
@@ -0,0 +1,552 @@
+/* Support for the WTX protocol.
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "remote-wtx-hw.h"
+#include "gdb_assert.h"
+#include "regcache.h"
+#include "gdbcmd.h"
+
+/* Registers in WTX are stored consecutively in a series of memory blocks,
+ with one block per register set. The following structure details
+ for a given register its position in the block, and the associated
+ register set. A negative offset means that the register is not
+ accessible with WTX.
+
+ brobecker/2007-06-25: On older versions of this code, we also used
+ to store the register size, but this should not be necessary.
+ GDB already knows the register size, and it should match the size
+ needed by WTX. */
+
+struct wtx_hw_register
+{
+ UINT32 register_offset;
+ WTX_REG_SET_TYPE register_set;
+};
+
+/* i386 registers description, as seen by VxWorks. */
+
+static const struct wtx_hw_register i386_register_map [] =
+{
+ /* Data registers. */
+ {0x1c, WTX_REG_SET_IU}, /* eax */
+ {0x18, WTX_REG_SET_IU}, /* ecx */
+ {0x14, WTX_REG_SET_IU}, /* edx */
+ {0x10, WTX_REG_SET_IU}, /* ebx */
+ {0x0c, WTX_REG_SET_IU}, /* esp */
+ {0x08, WTX_REG_SET_IU}, /* ebp */
+ {0x04, WTX_REG_SET_IU}, /* esi */
+ {0x00, WTX_REG_SET_IU}, /* edi */
+ {0x24, WTX_REG_SET_IU}, /* pc */
+ {0x20, WTX_REG_SET_IU}, /* eflags */
+
+ /* Segment registers (not accessible). */
+
+ {-1, WTX_REG_SET_IU}, /* cs */
+ {-1, WTX_REG_SET_IU}, /* ss */
+ {-1, WTX_REG_SET_IU}, /* ds */
+ {-1, WTX_REG_SET_IU}, /* es */
+ {-1, WTX_REG_SET_IU}, /* fs */
+ {-1, WTX_REG_SET_IU}, /* gs */
+
+ /* Floating Point registers. */
+ {0x1c, WTX_REG_SET_FPU}, /* st0 */
+ {0x16, WTX_REG_SET_FPU}, /* st1 */
+ {0x20, WTX_REG_SET_FPU}, /* st2 */
+ {0x2a, WTX_REG_SET_FPU}, /* st3 */
+ {0x34, WTX_REG_SET_FPU}, /* st4 */
+ {0x3e, WTX_REG_SET_FPU}, /* st5 */
+ {0x48, WTX_REG_SET_FPU}, /* st6 */
+ {0x52, WTX_REG_SET_FPU}, /* st7 */
+ {0x00, WTX_REG_SET_FPU}, /* fpc */
+ {0x04, WTX_REG_SET_FPU}, /* fps */
+ {0x08, WTX_REG_SET_FPU}, /* fpt */
+ {-1, WTX_REG_SET_IU}, /* fiseg */
+ {-1, WTX_REG_SET_IU}, /* fioff */
+ {-1, WTX_REG_SET_IU}, /* foseg */
+ {-1, WTX_REG_SET_IU}, /* fooff */
+ {-1, WTX_REG_SET_IU}, /* fop */
+ {-1, WTX_REG_SET_IU}, /* xmm0 */
+ {-1, WTX_REG_SET_IU}, /* xmm1 */
+ {-1, WTX_REG_SET_IU}, /* xmm2 */
+ {-1, WTX_REG_SET_IU}, /* xmm3 */
+ {-1, WTX_REG_SET_IU}, /* xmm4 */
+ {-1, WTX_REG_SET_IU}, /* xmm5 */
+ {-1, WTX_REG_SET_IU}, /* xmm6 */
+ {-1, WTX_REG_SET_IU}, /* xmm7 */
+ {-1, WTX_REG_SET_IU}, /* mxcsr */
+
+ /* MMX pseudo-registers (not accessible). */
+
+ {-1, WTX_REG_SET_IU}, /* mm0 */
+ {-1, WTX_REG_SET_IU}, /* mm1 */
+ {-1, WTX_REG_SET_IU}, /* mm2 */
+ {-1, WTX_REG_SET_IU}, /* mm3 */
+ {-1, WTX_REG_SET_IU}, /* mm4 */
+ {-1, WTX_REG_SET_IU}, /* mm5 */
+ {-1, WTX_REG_SET_IU}, /* mm6 */
+ {-1, WTX_REG_SET_IU} /* mm7 */
+};
+
+
+static const struct wtx_hw_register ppc_register_map[] =
+{
+ /* General purpose registers. */
+
+ {0x00, WTX_REG_SET_IU}, /* r0 (0) */
+ {0x04, WTX_REG_SET_IU}, /* r1 */
+ {0x08, WTX_REG_SET_IU}, /* r2 */
+ {0x0c, WTX_REG_SET_IU}, /* r3 */
+ {0x10, WTX_REG_SET_IU}, /* r4 */
+ {0x14, WTX_REG_SET_IU}, /* r5 */
+ {0x18, WTX_REG_SET_IU}, /* r6 */
+ {0x1c, WTX_REG_SET_IU}, /* r7 */
+ {0x20, WTX_REG_SET_IU}, /* r8 (8) */
+ {0x24, WTX_REG_SET_IU}, /* r9 */
+ {0x28, WTX_REG_SET_IU}, /* r10 */
+ {0x2c, WTX_REG_SET_IU}, /* r11 */
+ {0x30, WTX_REG_SET_IU}, /* r12 */
+ {0x34, WTX_REG_SET_IU}, /* r13 */
+ {0x38, WTX_REG_SET_IU}, /* r14 */
+ {0x3c, WTX_REG_SET_IU}, /* r15 (16) */
+ {0x40, WTX_REG_SET_IU}, /* r16 */
+ {0x44, WTX_REG_SET_IU}, /* r17 */
+ {0x48, WTX_REG_SET_IU}, /* r18 */
+ {0x4c, WTX_REG_SET_IU}, /* r19 */
+ {0x50, WTX_REG_SET_IU}, /* r20 */
+ {0x54, WTX_REG_SET_IU}, /* r21 */
+ {0x58, WTX_REG_SET_IU}, /* r22 */
+ {0x5c, WTX_REG_SET_IU}, /* r23 */
+ {0x60, WTX_REG_SET_IU}, /* r24 (24) */
+ {0x64, WTX_REG_SET_IU}, /* r25 */
+ {0x68, WTX_REG_SET_IU}, /* r26 */
+ {0x6c, WTX_REG_SET_IU}, /* r27 */
+ {0x70, WTX_REG_SET_IU}, /* r28 */
+ {0x74, WTX_REG_SET_IU}, /* r29 */
+ {0x78, WTX_REG_SET_IU}, /* r30 */
+ {0x7c, WTX_REG_SET_IU}, /* r31 */
+ {0x00, WTX_REG_SET_FPU}, /* f0 (32) */
+ {0x08, WTX_REG_SET_FPU}, /* f1 */
+ {0x10, WTX_REG_SET_FPU}, /* f2 */
+ {0x18, WTX_REG_SET_FPU}, /* f3 */
+ {0x20, WTX_REG_SET_FPU}, /* f4 */
+ {0x28, WTX_REG_SET_FPU}, /* f5 */
+ {0x30, WTX_REG_SET_FPU}, /* f6 */
+ {0x38, WTX_REG_SET_FPU}, /* f7 */
+ {0x40, WTX_REG_SET_FPU}, /* f8 (40) */
+ {0x48, WTX_REG_SET_FPU}, /* f9 */
+ {0x50, WTX_REG_SET_FPU}, /* f10 */
+ {0x58, WTX_REG_SET_FPU}, /* f11 */
+ {0x60, WTX_REG_SET_FPU}, /* f12 */
+ {0x68, WTX_REG_SET_FPU}, /* f13 */
+ {0x70, WTX_REG_SET_FPU}, /* f14 */
+ {0x78, WTX_REG_SET_FPU}, /* f15 */
+ {0x80, WTX_REG_SET_FPU}, /* f16 (48) */
+ {0x88, WTX_REG_SET_FPU}, /* f17 */
+ {0x90, WTX_REG_SET_FPU}, /* f18 */
+ {0x98, WTX_REG_SET_FPU}, /* f19 */
+ {0xa0, WTX_REG_SET_FPU}, /* f20 */
+ {0xa8, WTX_REG_SET_FPU}, /* f21 */
+ {0xb0, WTX_REG_SET_FPU}, /* f22 */
+ {0xb8, WTX_REG_SET_FPU}, /* f23 */
+ {0xc0, WTX_REG_SET_FPU}, /* f24 (56) */
+ {0xc8, WTX_REG_SET_FPU}, /* f25 */
+ {0xd0, WTX_REG_SET_FPU}, /* f26 */
+ {0xd8, WTX_REG_SET_FPU}, /* f27 */
+ {0xe0, WTX_REG_SET_FPU}, /* f28 */
+ {0xe8, WTX_REG_SET_FPU}, /* f29 */
+ {0xf0, WTX_REG_SET_FPU}, /* f30 */
+ {0xf8, WTX_REG_SET_FPU}, /* f31 */
+ {0x8c, WTX_REG_SET_IU}, /* pc (64) */
+ {0x80, WTX_REG_SET_IU}, /* ps/msr */
+
+ /* Special purpose registers. */
+
+ {0x90, WTX_REG_SET_IU}, /* cr (66) */
+ {0x84, WTX_REG_SET_IU}, /* lr */
+ {0x88, WTX_REG_SET_IU}, /* ctr */
+ {0x94, WTX_REG_SET_IU}, /* xer */
+ {0x100, WTX_REG_SET_FPU}, /* fpscr */
+
+ /* Unused register slots (71 - 105). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (71). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (72). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (73). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (74). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (75). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (76). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (77). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (78). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (79). */
+
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (80). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (81). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (82). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (83). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (84). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (85). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (86). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (87). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (88). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (89). */
+
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (90). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (91). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (92). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (93). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (94). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (95). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (96). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (97). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (98). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (99). */
+
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (100). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (101). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (102). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (103). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (104). */
+ {-1, WTX_REG_SET_IU}, /* Empty register slot (105). */
+
+ /* AltiVec registers.
+
+ They are only supported starting with VxWorks 5.5 and PSC 2.1.
+ brobecker/2007-11-02: For now, we removed support for these registers
+ regardless of the VxWorks version in order to allow us to build GDB
+ on older versions of VxWorks. We'll investigate conditional support
+ later (note that these registers are part of the WTX_REG_SET_AV
+ register set). */
+
+ {-1, WTX_REG_SET_IU}, /* vr0 (106) */
+ {-1, WTX_REG_SET_IU}, /* vr1 */
+ {-1, WTX_REG_SET_IU}, /* vr2 */
+ {-1, WTX_REG_SET_IU}, /* vr3 */
+ {-1, WTX_REG_SET_IU}, /* vr4 */
+ {-1, WTX_REG_SET_IU}, /* vr5 */
+ {-1, WTX_REG_SET_IU}, /* vr6 */
+ {-1, WTX_REG_SET_IU}, /* vr7 */
+ {-1, WTX_REG_SET_IU}, /* vr8 */
+ {-1, WTX_REG_SET_IU}, /* vr9 */
+ {-1, WTX_REG_SET_IU}, /* vr10 */
+ {-1, WTX_REG_SET_IU}, /* vr11 */
+ {-1, WTX_REG_SET_IU}, /* vr12 */
+ {-1, WTX_REG_SET_IU}, /* vr13 */
+ {-1, WTX_REG_SET_IU}, /* vr14 */
+ {-1, WTX_REG_SET_IU}, /* vr15 */
+ {-1, WTX_REG_SET_IU}, /* vr16 */
+ {-1, WTX_REG_SET_IU}, /* vr17 */
+ {-1, WTX_REG_SET_IU}, /* vr18 */
+ {-1, WTX_REG_SET_IU}, /* vr19 */
+ {-1, WTX_REG_SET_IU}, /* vr20 */
+ {-1, WTX_REG_SET_IU}, /* vr21 */
+ {-1, WTX_REG_SET_IU}, /* vr22 */
+ {-1, WTX_REG_SET_IU}, /* vr23 */
+ {-1, WTX_REG_SET_IU}, /* vr24 */
+ {-1, WTX_REG_SET_IU}, /* vr25 */
+ {-1, WTX_REG_SET_IU}, /* vr26 */
+ {-1, WTX_REG_SET_IU}, /* vr27 */
+ {-1, WTX_REG_SET_IU}, /* vr28 */
+ {-1, WTX_REG_SET_IU}, /* vr29 */
+ {-1, WTX_REG_SET_IU}, /* vr30 */
+ {-1, WTX_REG_SET_IU}, /* vr31 */
+ {-1, WTX_REG_SET_IU}, /* vscr */
+ {-1, WTX_REG_SET_IU}, /* vrsave */
+
+ /* dl registers (not accessible either). */
+ {-1, WTX_REG_SET_IU}, /* dl0 */
+ {-1, WTX_REG_SET_IU}, /* dl1 */
+ {-1, WTX_REG_SET_IU}, /* dl2 */
+ {-1, WTX_REG_SET_IU}, /* dl3 */
+ {-1, WTX_REG_SET_IU}, /* dl4 */
+ {-1, WTX_REG_SET_IU}, /* dl5 */
+ {-1, WTX_REG_SET_IU}, /* dl6 */
+ {-1, WTX_REG_SET_IU}, /* dl7 */
+ {-1, WTX_REG_SET_IU}, /* dl8 */
+ {-1, WTX_REG_SET_IU}, /* dl9 */
+ {-1, WTX_REG_SET_IU}, /* dl10 */
+ {-1, WTX_REG_SET_IU}, /* dl11 */
+ {-1, WTX_REG_SET_IU}, /* dl12 */
+ {-1, WTX_REG_SET_IU}, /* dl13 */
+ {-1, WTX_REG_SET_IU}, /* dl14 */
+ {-1, WTX_REG_SET_IU}, /* dl15 */
+};
+
+/* The following variables point to the appropriate register table
+ depending on the target. These are updated when we connect
+ to the target server. */
+
+static const struct wtx_hw_register *wtx_hw_register_map = NULL;
+static int wtx_hw_register_map_len = 0;
+
+/* Whether we should complain or not if we are trying to store/fetch a
+ register which is not accessible.
+
+ FIXME: guitton/2007-11-15: this should not be needed. We should always
+ have a warning if we are not able to store or fetch a register. However,
+ for some targets (e.g. x86), this generates a lot of bogus warnings. So
+ we disable these warnings for now. */
+
+static int wtx_register_complaints = 0;
+
+/* Inspect the target gdbarch vector, and initialize the internal
+ state of this module. This include initializing elements such
+ as the register map, for instance.
+
+ This function must be called before any other function is used. */
+
+void
+wtx_hw_initialize (void)
+{
+ const struct bfd_arch_info *arch_info =
+ gdbarch_bfd_arch_info (target_gdbarch);
+
+ gdb_assert (arch_info != NULL);
+
+ switch (arch_info->arch)
+ {
+ case bfd_arch_rs6000:
+ case bfd_arch_powerpc:
+ wtx_hw_register_map = ppc_register_map;
+ wtx_hw_register_map_len =
+ sizeof (ppc_register_map) / sizeof (struct wtx_hw_register);
+ break;
+
+ case bfd_arch_i386:
+ wtx_hw_register_map = i386_register_map;
+ wtx_hw_register_map_len =
+ sizeof (i386_register_map) / sizeof (struct wtx_hw_register);
+ break;
+
+ default:
+ error (_("This architecture is currently not supported"));
+ }
+}
+
+/* Return non-zero if the given register can be fetched & stored. */
+
+static int
+wtx_hw_register_supported_p (int gdb_regnum)
+{
+ gdb_assert (wtx_hw_register_map != NULL);
+ gdb_assert (gdb_regnum <= wtx_hw_register_map_len);
+
+ if (wtx_hw_register_map [gdb_regnum].register_offset == -1)
+ return 0; /* Offset unknown, register is not supported. */
+
+ return 1;
+}
+
+
+/* Fetch the value of a register given its GDB_REGNUM, and store it
+ inside REG_VAL.
+
+ Register numbering in GDB do not necessarily correspond to the
+ numbering used by WTX. This function translates the GDB_REGNUM
+ into a WTX register number before calling the WTX routine. */
+
+int
+wtx_hw_fetch_register (struct gdbarch *gdbarch,
+ WTX_CONTEXT_TYPE context_type,
+ WTX_CONTEXT_ID_T context_id,
+ int gdb_regnum,
+ gdb_byte *reg_val)
+{
+ if (!wtx_hw_register_supported_p (gdb_regnum))
+ {
+ if (wtx_register_complaints)
+ warning (_("Fetching register %s is not supported"),
+ gdbarch_register_name (gdbarch, gdb_regnum));
+ return 0;
+ }
+
+ return wtxapi_regs_get (context_type, context_id,
+ wtx_hw_register_map [gdb_regnum].register_set,
+ wtx_hw_register_map [gdb_regnum].register_offset,
+ register_size (gdbarch, gdb_regnum),
+ reg_val);
+}
+
+/* Fetch the value of the given register given its GDB_REGNUM,
+ and store it inside REG_VAL. Instead of using WTX to read
+ the register value, read the register value from the memory
+ region where the registers have been saved for this task.
+
+ REGS_ADDR is the base address where the GP registers have been saved.
+ FP_REGS_ADDR, is the base address where the FP registers have been saved.
+
+ GP registers are always supported, and FP registers are supported
+ only if FP_REGS_ADDR is not zero. Other registers (Eg altivec registers)
+ are not supported in this mode. */
+
+int
+wtx_hw_fetch_register_in_memory (struct gdbarch *gdbarch,
+ WTX_CONTEXT_TYPE context_type,
+ WTX_CONTEXT_ID_T context_id,
+ CORE_ADDR regs_addr,
+ CORE_ADDR fp_regs_addr,
+ int gdb_regnum,
+ gdb_byte *reg_val)
+{
+ int reg_offset;
+ CORE_ADDR reg_addr = 0;
+
+ if (!wtx_hw_register_supported_p (gdb_regnum))
+ {
+ if (wtx_register_complaints)
+ warning (_("Fetching register %s is not supported"),
+ gdbarch_register_name (gdbarch, gdb_regnum));
+ return 0;
+ }
+
+ reg_offset = wtx_hw_register_map [gdb_regnum].register_offset;
+ switch (wtx_hw_register_map [gdb_regnum].register_set)
+ {
+ case WTX_REG_SET_IU:
+ reg_addr = regs_addr + reg_offset;
+ break;
+ case WTX_REG_SET_FPU:
+ if (fp_regs_addr != 0)
+ reg_addr = fp_regs_addr + reg_offset;
+ break;
+ }
+
+ if (reg_addr == 0)
+ {
+ /* We couldn't determine the location where the register is stored.
+ Warn the user and abort. */
+ if (wtx_register_complaints)
+ warning (_("Cannot fetch register %s in this mode"),
+ gdbarch_register_name (gdbarch, gdb_regnum));
+ return 0;
+ }
+
+ return (wtxapi_mem_read (wtxapi_pd_current_get (), reg_addr, reg_val,
+ register_size (gdbarch, gdb_regnum))
+ != WTX_ERROR);
+}
+
+/* Store the value from REG_VAL into the register identified by
+ GDB_REGNUM.
+
+ Register numbering in GDB do not necessarily correspond to the
+ numbering used by WTX. This function translates the GDB_REGNUM
+ into a WTX register number before calling the WTX routine. */
+
+int
+wtx_hw_store_register (struct gdbarch *gdbarch, WTX_CONTEXT_TYPE context_type,
+ WTX_CONTEXT_ID_T context_id,
+ int gdb_regnum,
+ gdb_byte *reg_val)
+{
+ /* brobecker/2007-10-16: On powerpc targets, there seems to be a bug
+ in the VxWorks system that causes the storing of the msr register
+ to fail. Although the WTX request returns with no error, the actual
+ new value of the msr is often zero instead of the intended value,
+ later causing dramatic issues such as floating-point exceptions or
+ even system-wide crashes. So we simply silently ignore stores to
+ that register for now. */
+ if (wtx_hw_register_map == ppc_register_map
+ && gdb_regnum == 65)
+ return 0;
+
+ if (!wtx_hw_register_supported_p (gdb_regnum))
+ {
+ if (wtx_register_complaints)
+ warning (_("Storing register %s is not supported"),
+ gdbarch_register_name (gdbarch, gdb_regnum));
+ return 0;
+ }
+
+ return wtxapi_regs_set (context_type, context_id,
+ wtx_hw_register_map [gdb_regnum].register_set,
+ wtx_hw_register_map [gdb_regnum].register_offset,
+ register_size (gdbarch, gdb_regnum),
+ reg_val);
+}
+
+/* Store the value from REG_VAL into the register identified by
+ GDB_REGNUM. Instead of using WTX to write the register value,
+ we write the new value in the memory region where the register
+ has been saved for this task.
+
+ REGS_ADDR is the base address where the GP registers have been saved.
+ FP_REGS_ADDR, is the base address where the FP registers have been saved.
+
+ GP registers are always supported, and FP registers are supported
+ only if FP_REGS_ADDR is not zero. Other registers (Eg altivec registers)
+ are not supported in this mode. */
+
+int
+wtx_hw_store_register_in_memory (struct gdbarch *gdbarch,
+ WTX_CONTEXT_TYPE context_type,
+ WTX_CONTEXT_ID_T context_id,
+ CORE_ADDR regs_addr,
+ CORE_ADDR fp_regs_addr,
+ int gdb_regnum,
+ gdb_byte *reg_val)
+{
+ int reg_offset;
+ CORE_ADDR reg_addr = 0;
+
+ if (!wtx_hw_register_supported_p (gdb_regnum))
+ {
+ if (wtx_register_complaints)
+ warning (_("Storing register %s is not supported"),
+ gdbarch_register_name (gdbarch, gdb_regnum));
+ return 0;
+ }
+
+ reg_offset = wtx_hw_register_map [gdb_regnum].register_offset;
+ switch (wtx_hw_register_map [gdb_regnum].register_set)
+ {
+ case WTX_REG_SET_IU:
+ reg_addr = regs_addr + reg_offset;
+ break;
+ case WTX_REG_SET_FPU:
+ if (fp_regs_addr != 0)
+ reg_addr = fp_regs_addr + reg_offset;
+ break;
+ }
+
+ if (reg_addr == 0)
+ {
+ /* We couldn't determine the location where the register is stored.
+ Warn the user and abort. */
+ if (wtx_register_complaints)
+ warning (_("Cannot store register %s in this mode"),
+ gdbarch_register_name (gdbarch, gdb_regnum));
+ return 0;
+ }
+
+ return (wtxapi_mem_write (wtxapi_pd_current_get (), reg_val, reg_addr,
+ register_size (gdbarch, gdb_regnum))
+ != WTX_ERROR);
+}
+
+void
+initialize_remote_wtx_hw ()
+{
+ add_setshow_boolean_cmd ("wtx-register-complaints", no_class,
+ &wtx_register_complaints,"\
+Set whether to complain if a register is not accessible.", "\
+Show whether to complain if a register is not accessible.", "\
+If set, GDB complains when it cannot store/fetch a register.",
+ NULL, NULL,
+ &setlist, &showlist);
+}
diff --git a/gdb/remote-wtx-hw.h b/gdb/remote-wtx-hw.h
new file mode 100644
index 0000000..f5c7813
--- /dev/null
+++ b/gdb/remote-wtx-hw.h
@@ -0,0 +1,56 @@
+/* Support for the WTX protocol.
+
+ Copyright (C) 2007, 2010 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef REMOTE_WTX_HW_H
+#define REMOTE_WTX_HW_H
+
+#include "defs.h"
+#include "remote-wtxapi.h"
+
+extern void wtx_hw_initialize (void);
+
+extern int wtx_hw_fetch_register (struct gdbarch *gdbarch,
+ WTX_CONTEXT_TYPE context_type,
+ WTX_CONTEXT_ID_T context_id,
+ int gdb_regnum,
+ gdb_byte *reg_val);
+
+extern int wtx_hw_fetch_register_in_memory (struct gdbarch *gdbarch,
+ WTX_CONTEXT_TYPE context_type,
+ WTX_CONTEXT_ID_T context_id,
+ CORE_ADDR regs_addr,
+ CORE_ADDR fp_regs_addr,
+ int gdb_regnum,
+ gdb_byte *reg_val);
+
+extern int wtx_hw_store_register (struct gdbarch *gdbarch,
+ WTX_CONTEXT_TYPE context_type,
+ WTX_CONTEXT_ID_T context_id,
+ int gdb_regnum,
+ gdb_byte *reg_val);
+
+extern int wtx_hw_store_register_in_memory (struct gdbarch *gdbarch,
+ WTX_CONTEXT_TYPE context_type,
+ WTX_CONTEXT_ID_T context_id,
+ CORE_ADDR regs_addr,
+ CORE_ADDR fp_regs_addr,
+ int gdb_regnum,
+ gdb_byte *reg_val);
+
+#endif
--
1.6.3.3