* [RFA] W.I.P. AltiVec ppc registers support.
2001-11-28 18:09 [RFA] W.I.P. AltiVec ppc registers support Elena Zannoni
@ 2001-11-18 13:27 ` Elena Zannoni
2001-11-18 14:11 ` Daniel Jacobowitz
` (2 subsequent siblings)
3 siblings, 0 replies; 63+ messages in thread
From: Elena Zannoni @ 2001-11-18 13:27 UTC (permalink / raw)
To: gdb-patches
AltiVec registers are 32 128-bit wide registers found on the G4
powerpc processor family. This patch adds some initial support for
such registers to gdb on a linux ppc platform.
The Altivec registers are not displayed in a normal 'info reg' command
output. They are shown (like fp regs) if one says 'info all' instead.
Furthermore I added a specific 'info power altivec' command to display
just the Altivec registers. (I am not sure that the word 'power' is
the best choice, maybe simply 'ppc' or 'powerpc' is better). This way
the command as just a specific powerpc info command, w/o it being a
generic info command avaliable on every platform.
If there is no kernel support for ptrace to handle the AltiVec
registers, they will display as 0's.
The little drawback is that such registers will be displayed any time
gdb's architecture is 'powerpc:common' or 'powerpc:7400'. The first
case is the architecture gdb defaults to when run on a ppc machine,
because the multiarch mechanism cannot determine the nature of the
executable file. To be clearer, there is no way for gdb to know that
the architecture is meant to be a ppc7400 based on executable
information provided by BFD (unlike for Mips and Sh). So, gdb will
always start and *stay* with a powerpc:common architecture selected,
unless the user explicitly sets the architecture to be
'powerpc:7400'. This impossibility to auto detect the architecture is
what prompted me to have Altivec defined anyway for the default
arch. [Hopefully this deficiency will be rectified soon].
The patch below includes the patch previously submitted:
http://sources.redhat.com/ml/gdb-patches/2001-11/msg00447.html
The first Changelog is just for the most recent change set. I included
the older one for easy reference. I would like to commit these in 2
separate passes, the same way they were submitted.
I tested this on AIX4.3, on a Linux-ppc with Altivec kernel support,
and on a Linux-ppx w/o Altivec kernel support.
Elena
2001-11-28 Elena Zannoni <ezannoni@redhat.com>
* Makefile.in (rs6000-tdep.o): Add dependency on parser-defs.h.
* config/powerpc/nm-linux.h (FETCH_INFERIOR_REGISTERS): Define.
* rs6000-tdep.c: Include parser-defs.h.
(struct gdbarch_tdep): Moved from here to ppc-tdep.h.
(rs6000_register_virtual_type): Rewrite, including hangling of
AltiVec regs type.
(altivec_register_p): New function.
(rs6000_do_altivec_registers): New function.
(rs6000_altivec_registers_info): New function.
(rs6000_do_registers_info): New function.
(R16): Define.
(PPC_ALTIVEC_REGS): Define.
(registers_powerpc): Add AltiVec registers.
(registers_7400): Define.
(variants): Add 7400 machine.
(rs6000_gdbarch_init): Set the numbers of AltiVec registers.
Initialize gdbarch_do)_registers_info.
(rs6000_info_power_command): New function.
(info_power_cmdlist): New static variable.
(_initialize_rs6000_tdep): Add new 'info power altivec' command.
* rs6000-nat.c (fetch_register): Don't error out unless the
register number is really bogus.
* ppc-tdep.h (struct gdbarch_tdep): Moved here from rs6000-tdep.c.
Add altivec regnum fields.
(altivec_register_p): Export.
* ppc-linux-nat.c (ppc_ptrace_cannot_fetch_store_register): New
function.
(ppc_register_u_addr): Add handling of AltiVec registers.
(fetch_register): New function.
(fetch_altivec_register): New function.
(fetch_ppc_registers): New function.
(fetch_altivec_registers): New function.
(fetch_inferior_registers): New function.
(store_register): New function.
(store_altivec_register): New function.
(store_ppc_registers): New function.
(store_altivec_registers): New function.
(store_inferior_registers): New function.
[PREVIOUS CHANGELOG]
2001-11-26 Elena Zannoni <ezannoni@redhat.com>
* Makefile.in (ppc-linux-nat.o): Add dependency on ppc-tdep.h.
* ppc-tdep.h (PPC_GPLAST_REGNUM): Define.
* ppc-linux-nat.c: Include ppc-tdep.h.
(ppc_register_u_addr): Don't use the static array regmap[],
dynamically define the mapping instead.
(supply_gregset): Ditto.
(fill_gregset): Ditto.
(COPY_REG): Delete macro defintion.
(regmap): Delete array.
Index: Makefile.in
===================================================================
RCS file: /cvs/uberbaum/gdb/Makefile.in,v
retrieving revision 1.130
diff -u -p -r1.130 Makefile.in
--- Makefile.in 2001/11/18 05:09:26 1.130
+++ Makefile.in 2001/11/28 23:26:05
@@ -1818,7 +1818,7 @@ ppc-bdm.o: ppc-bdm.c $(defs_h) $(gdbcore
$(objfiles_h) $(gdb_stabs_h) $(serial_h) ocd.h $(regcache_h)
ppc-linux-nat.o: ppc-linux-nat.c $(defs_h) $(gdbcore_h) $(frame_h) \
- $(inferior_h) $(target_h) $(regcache_h)
+ $(inferior_h) $(target_h) $(regcache_h) ppc-tdep.h
ppc-linux-tdep.o: ppc-linux-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
$(target_h) ppc-tdep.h $(regcache_h) $(value_h)
@@ -1972,7 +1972,7 @@ rs6000-nat.o: rs6000-nat.c $(bfd_h) $(de
$(gdb_stabs_h) $(regcache_h)
rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
- $(target_h) ppc-tdep.h $(regcache_h) $(value_h)
+ $(target_h) ppc-tdep.h $(regcache_h) $(value_h) $(parser_defs_h)
s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \
$(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) \
Index: ppc-linux-nat.c
===================================================================
RCS file: /cvs/uberbaum/gdb/ppc-linux-nat.c,v
retrieving revision 1.10
diff -u -p -r1.10 ppc-linux-nat.c
--- ppc-linux-nat.c 2001/11/20 16:35:24 1.10
+++ ppc-linux-nat.c 2001/11/28 23:26:16
@@ -32,34 +32,341 @@
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/procfs.h>
+#include <sys/ptrace.h>
/* Prototypes for supply_gregset etc. */
#include "gregset.h"
+#include "ppc-tdep.h"
+#ifndef PT_READ_U
+#define PT_READ_U PTRACE_PEEKUSR
+#endif
+#ifndef PT_WRITE_U
+#define PT_WRITE_U PTRACE_POKEUSR
+#endif
+
+/* Default the type of the ptrace transfer to int. */
+#ifndef PTRACE_XFER_TYPE
+#define PTRACE_XFER_TYPE int
+#endif
+
+/* AltiVec regs are not always supported by the kernel. We need to fake them,
+ and let the ptrace requests fail. */
+#ifndef PT_VR0
+#define PT_VR0 (PT_FPSCR + 1)
+#endif
+#ifndef PT_VR31
+#define PT_VR31 (PT_VR0 + 4*31)
+#endif
+#ifndef PT_VRCR
+#define PT_VRCR (PT_VR0 + 4*32)
+#endif
+#ifndef PT_VRSAVE
+#define PT_VRSAVE (PT_VR0 + 4*33)
+#endif
+
int
kernel_u_size (void)
{
return (sizeof (struct user));
}
-static int regmap[] =
-{PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
- PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
- PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
- PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
- PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
- PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
- PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
- PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
- PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ};
+/* *INDENT-OFF* */
+/* registers layout, as presented by the ptrace interface:
+PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
+PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
+PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
+PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
+PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
+PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
+PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
+PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
+PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ */
+/* *INDENT_ON * */
int
-ppc_register_u_addr (int ustart, int regnum)
+ppc_register_u_addr (int ustart, int regno)
+{
+ int u_addr = -1;
+
+ /* General purpose registers occupy 1 slot each in the buffer */
+ if (regno >= PPC_GP0_REGNUM && regno <= PPC_GPLAST_REGNUM )
+ u_addr = (ustart + (PT_R0 + regno) * 4);
+
+ /* Floating point regs: 2 slots each */
+ if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM)
+ u_addr = (ustart + (PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4);
+
+ /* Altivec registers: 4 slots each. */
+ if (altivec_register_p (regno))
+ u_addr = (ustart + (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4);
+
+ /* UISA special purpose registers: 1 slot each */
+ if (regno == PC_REGNUM)
+ u_addr = ustart + PT_NIP * 4;
+ if (regno == PPC_LR_REGNUM)
+ u_addr = ustart + PT_LNK * 4;
+ if (regno == PPC_CR_REGNUM)
+ u_addr = ustart + PT_CCR * 4;
+ if (regno == PPC_XER_REGNUM)
+ u_addr = ustart + PT_XER * 4;
+ if (regno == PPC_CTR_REGNUM)
+ u_addr = ustart + PT_CTR * 4;
+ if (regno == PPC_MQ_REGNUM)
+ u_addr = ustart + PT_MQ * 4;
+ if (regno == PPC_PS_REGNUM)
+ u_addr = ustart + PT_MSR * 4;
+
+ return u_addr;
+}
+
+static int
+ppc_ptrace_cannot_fetch_store_register (int regno)
+{
+ return (ppc_register_u_addr (0, regno) == -1);
+}
+
+static void
+fetch_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ unsigned int offset; /* Offset of registers within the u area. */
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int tid;
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ {
+ memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ if (regaddr < 0)
+ return;
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ sprintf (mess, "reading register %s (#%d)",
+ REGISTER_NAME (regno), regno);
+ perror_with_name (mess);
+ }
+ }
+ supply_register (regno, buf);
+}
+
+static void
+fetch_altivec_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ int i;
+ unsigned int offset; /* Offset of registers within the u area. */
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int tid;
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ {
+ memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+ }
+ supply_register (regno, buf);
+}
+
+static void
+fetch_ppc_registers (void)
+{
+ int last_register;
+ int i;
+
+ last_register = PPC_MQ_REGNUM;
+ for (i = 0; i <= last_register; i++)
+ fetch_register (i);
+}
+
+static void
+fetch_altivec_registers (void)
+{
+ int i;
+
+ for (i = 0;
+ i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
+ - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
+ i++)
+ fetch_altivec_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
+}
+
+/* Fetch registers from the child process. Fetch all registers if
+ regno == -1, otherwise fetch all general registers or all floating
+ point registers depending upon the value of regno. */
+
+void
+fetch_inferior_registers (int regno)
+{
+ if (regno == -1)
+ {
+ fetch_ppc_registers ();
+ fetch_altivec_registers ();
+ }
+ else
+ {
+ if (altivec_register_p (regno))
+ fetch_altivec_register (regno);
+ else
+ fetch_register (regno);
+ }
+}
+
+/* Store one register. */
+static void
+store_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ unsigned int offset; /* Offset of registers within the u area. */
+ int tid;
+ char *buf = alloca (MAX_REGISTER_RAW_SIZE);
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ {
+ return;
+ }
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ regcache_collect (regno, buf);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
+ *(PTRACE_XFER_TYPE *) & buf[i]);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ sprintf (mess, "writing register %s (#%d)",
+ REGISTER_NAME (regno), regno);
+ perror_with_name (mess);
+ }
+ }
+}
+
+static void
+store_altivec_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ unsigned int offset; /* Offset of registers within the u area. */
+ int tid;
+ char *buf = alloca (MAX_REGISTER_RAW_SIZE);
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ return;
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ regcache_collect (regno, buf);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
+ *(PTRACE_XFER_TYPE *) & buf[i]);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ return;
+ }
+}
+
+static void
+store_ppc_registers (void)
+{
+ int last_register;
+ int i;
+
+ last_register = PPC_MQ_REGNUM;
+ for (i = 0; i <= last_register; i++)
+ store_register (i);
+}
+
+static void
+store_altivec_registers (void)
{
- return (ustart + 4 * regmap[regnum]);
+ int i;
+
+ for (i = 0;
+ i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
+ - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
+ i++)
+ store_altivec_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
}
void
+store_inferior_registers (int regno)
+{
+ if (regno >= 0)
+ {
+ if (altivec_register_p (regno))
+ store_altivec_register (regno);
+ else
+ store_register (regno);
+ }
+ else
+ {
+ store_ppc_registers ();
+ store_altivec_registers ();
+ }
+}
+
+void
supply_gregset (gdb_gregset_t *gregsetp)
{
int regi;
@@ -68,8 +375,13 @@ supply_gregset (gdb_gregset_t *gregsetp)
for (regi = 0; regi < 32; regi++)
supply_register (regi, (char *) (regp + regi));
- for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
- supply_register (regi, (char *) (regp + regmap[regi]));
+ supply_register (PC_REGNUM, (char *) (regp + PT_NIP));
+ supply_register (PPC_LR_REGNUM, (char *) (regp + PT_LNK));
+ supply_register (PPC_CR_REGNUM, (char *) (regp + PT_CCR));
+ supply_register (PPC_XER_REGNUM, (char *) (regp + PT_XER));
+ supply_register (PPC_CTR_REGNUM, (char *) (regp + PT_CTR));
+ supply_register (PPC_MQ_REGNUM, (char *) (regp + PT_MQ));
+ supply_register (PPC_PS_REGNUM, (char *) (regp + PT_MSR));
}
void
@@ -78,19 +390,26 @@ fill_gregset (gdb_gregset_t *gregsetp, i
int regi;
elf_greg_t *regp = (elf_greg_t *) gregsetp;
-#define COPY_REG(_idx_,_regi_) \
- if ((regno == -1) || regno == _regi_) \
- regcache_collect (_regi_, regp + _idx_)
-
for (regi = 0; regi < 32; regi++)
{
- COPY_REG (regmap[regi], regi);
+ if ((regno == -1) || regno == regi)
+ regcache_collect (regi, regp + PT_R0 + regi);
}
- for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
- {
- COPY_REG (regmap[regi], regi);
- }
+ if ((regno == -1) || regno == PC_REGNUM)
+ regcache_collect (PC_REGNUM, regp + PT_NIP);
+ if ((regno == -1) || regno == PPC_LR_REGNUM)
+ regcache_collect (PPC_LR_REGNUM, regp + PT_LNK);
+ if ((regno == -1) || regno == PPC_CR_REGNUM)
+ regcache_collect (PPC_CR_REGNUM, regp + PT_CCR);
+ if ((regno == -1) || regno == PPC_XER_REGNUM)
+ regcache_collect (PPC_XER_REGNUM, regp + PT_XER);
+ if ((regno == -1) || regno == PPC_CTR_REGNUM)
+ regcache_collect (PPC_CTR_REGNUM, regp + PT_CTR);
+ if ((regno == -1) || regno == PPC_MQ_REGNUM)
+ regcache_collect (PPC_MQ_REGNUM, regp + PT_MQ);
+ if ((regno == -1) || regno == PPC_PS_REGNUM)
+ regcache_collect (PPC_PS_REGNUM, regp + PT_MSR);
}
void
Index: ppc-tdep.h
===================================================================
RCS file: /cvs/uberbaum/gdb/ppc-tdep.h,v
retrieving revision 1.2
diff -u -p -r1.2 ppc-tdep.h
--- ppc-tdep.h 2001/11/01 01:07:35 1.2
+++ ppc-tdep.h 2001/11/29 00:18:11
@@ -42,10 +42,24 @@ void rs6000_init_extra_frame_info (int f
int rs6000_frameless_function_invocation (struct frame_info *);
void rs6000_frame_init_saved_regs (struct frame_info *);
CORE_ADDR rs6000_frame_chain (struct frame_info *);
+int altivec_register_p (int regno);
+/* Private data that this module attaches to struct gdbarch. */
+
+struct gdbarch_tdep
+ {
+ int wordsize; /* size in bytes of fixed-point word */
+ int osabi; /* OS / ABI from ELF header */
+ int *regoff; /* byte offsets in register arrays */
+ const struct reg *regs; /* from current variant */
+ int first_altivec_regnum;
+ int last_altivec_regnum;
+ };
+
/* Some important register numbers. */
#define PPC_GP0_REGNUM 0 /* GPR register 0 */
+#define PPC_GPLAST_REGNUM 31 /* GPR register 31 */
#define PPC_TOC_REGNUM 2 /* TOC register */
#define PPC_PS_REGNUM 65 /* Processor (or machine) status (%msr) */
#define PPC_CR_REGNUM 66 /* Condition register */
Index: rs6000-nat.c
===================================================================
RCS file: /cvs/uberbaum/gdb/rs6000-nat.c,v
retrieving revision 1.17
diff -u -p -r1.17 rs6000-nat.c
--- rs6000-nat.c 2001/05/04 04:15:27 1.17
+++ rs6000-nat.c 2001/11/28 23:26:17
@@ -206,9 +206,12 @@ fetch_register (int regno)
/* Bogus register number. */
else if (regno > LAST_UISA_SP_REGNUM)
- fprintf_unfiltered (gdb_stderr,
- "gdb error: register no %d not implemented.\n",
- regno);
+ {
+ if (regno >= NUM_REGS)
+ fprintf_unfiltered (gdb_stderr,
+ "gdb error: register no %d not implemented.\n",
+ regno);
+ }
/* Fixed-point registers. */
else
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/uberbaum/gdb/rs6000-tdep.c,v
retrieving revision 1.28
diff -u -p -r1.28 rs6000-tdep.c
--- rs6000-tdep.c 2001/10/21 17:19:37 1.28
+++ rs6000-tdep.c 2001/11/28 23:26:19
@@ -33,6 +33,7 @@
#include "regcache.h"
#include "doublest.h"
#include "value.h"
+#include "parser-defs.h"
#include "bfd/libbfd.h" /* for bfd_default_set_arch_mach */
#include "coff/internal.h" /* for libcoff.h */
@@ -81,16 +82,6 @@ struct reg
unsigned char fpr; /* whether register is floating-point */
};
-/* Private data that this module attaches to struct gdbarch. */
-
-struct gdbarch_tdep
- {
- int wordsize; /* size in bytes of fixed-point word */
- int osabi; /* OS / ABI from ELF header */
- int *regoff; /* byte offsets in register arrays */
- const struct reg *regs; /* from current variant */
- };
-
/* Return the current architecture's gdbarch_tdep structure. */
#define TDEP gdbarch_tdep (current_gdbarch)
@@ -1552,9 +1543,24 @@ rs6000_register_virtual_type (int n)
struct gdbarch_tdep *tdep = TDEP;
const struct reg *reg = tdep->regs + n;
- return reg->fpr ? builtin_type_double :
- regsize (reg, tdep->wordsize) == 8 ? builtin_type_int64 :
- builtin_type_int32;
+ if (reg->fpr)
+ return builtin_type_double;
+ else
+ {
+ int size = regsize (reg, tdep->wordsize);
+ switch (size)
+ {
+ case 8:
+ return builtin_type_int64;
+ break;
+ case 16:
+ return builtin_type_int128;
+ break;
+ default:
+ return builtin_type_int32;
+ break;
+ }
+ }
}
/* For the PowerPC, it appears that the debug info marks float parameters as
@@ -1613,6 +1619,192 @@ rs6000_register_convert_to_raw (struct t
memcpy (to, from, REGISTER_RAW_SIZE (n));
}
+int
+altivec_register_p (int regno)
+{
+ if (gdbarch_tdep (current_gdbarch)->first_altivec_regnum < 0
+ || gdbarch_tdep (current_gdbarch)->last_altivec_regnum < 0)
+ return 0;
+ else
+ return (regno >= gdbarch_tdep (current_gdbarch)->first_altivec_regnum
+ && regno <= gdbarch_tdep (current_gdbarch)->last_altivec_regnum);
+}
+
+static void
+rs6000_do_altivec_registers (int regnum)
+{
+ int i;
+ char *raw_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE);
+ char *virtual_buffer = (char*) alloca (MAX_REGISTER_VIRTUAL_SIZE);
+
+ for (i = gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
+ i <= gdbarch_tdep (current_gdbarch)->last_altivec_regnum; i++)
+ {
+ /* If we want just one reg, check that this is the one we want. */
+ if (regnum != -1 && i != regnum)
+ continue;
+
+ /* If the register name is empty, it is undefined for this
+ processor, so don't display anything. */
+ if (REGISTER_NAME (i) == NULL || *(REGISTER_NAME (i)) == '\0')
+ continue;
+
+ fputs_filtered (REGISTER_NAME (i), gdb_stdout);
+ print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), gdb_stdout);
+
+ /* Get the data in raw format. */
+ if (read_relative_register_raw_bytes (i, raw_buffer))
+ {
+ printf_filtered ("*value not available*\n");
+ continue;
+ }
+
+ /* Convert raw data to virtual format if necessary. */
+ if (REGISTER_CONVERTIBLE (i))
+ REGISTER_CONVERT_TO_VIRTUAL (i, REGISTER_VIRTUAL_TYPE (i),
+ raw_buffer, virtual_buffer);
+ else
+ memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (i));
+
+ /* Print as integer in hex only. */
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 'x', 1, 0, Val_pretty_default);
+ printf_filtered ("\n");
+ }
+}
+
+static void
+rs6000_altivec_registers_info (char *addr_exp, int from_tty)
+{
+ int regnum, numregs;
+ register char *end;
+
+ if (!target_has_registers)
+ error ("The program has no registers now.");
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+
+ if (!addr_exp)
+ {
+ rs6000_do_altivec_registers (-1);
+ return;
+ }
+
+ numregs = NUM_REGS + NUM_PSEUDO_REGS;
+ do
+ {
+ if (addr_exp[0] == '$')
+ addr_exp++;
+ end = addr_exp;
+ while (*end != '\0' && *end != ' ' && *end != '\t')
+ ++end;
+
+ regnum = target_map_name_to_register (addr_exp, end - addr_exp);
+ if (regnum < 0)
+ {
+ regnum = numregs;
+ if (*addr_exp >= '0' && *addr_exp <= '9')
+ regnum = atoi (addr_exp); /* Take a number */
+ if (regnum >= numregs) /* Bad name, or bad number */
+ error ("%.*s: invalid register", end - addr_exp, addr_exp);
+ }
+
+ rs6000_do_altivec_registers (regnum);
+
+ addr_exp = end;
+ while (*addr_exp == ' ' || *addr_exp == '\t')
+ ++addr_exp;
+ }
+ while (*addr_exp != '\0');
+}
+
+static void
+rs6000_do_registers_info (int regnum, int fpregs)
+{
+ register int i;
+ int numregs = NUM_REGS + NUM_PSEUDO_REGS;
+ char *raw_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE);
+ char *virtual_buffer = (char*) alloca (MAX_REGISTER_VIRTUAL_SIZE);
+
+ for (i = 0; i < numregs; i++)
+ {
+ /* Decide between printing all regs, nonfloat regs, or specific reg. */
+ if (regnum == -1)
+ {
+ if ((TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT && !fpregs)
+ || (altivec_register_p (i) && !fpregs))
+ continue;
+ }
+ else
+ {
+ if (i != regnum)
+ continue;
+ }
+
+ /* If the register name is empty, it is undefined for this
+ processor, so don't display anything. */
+ if (REGISTER_NAME (i) == NULL || *(REGISTER_NAME (i)) == '\0')
+ continue;
+
+ fputs_filtered (REGISTER_NAME (i), gdb_stdout);
+ print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), gdb_stdout);
+
+ /* Get the data in raw format. */
+ if (read_relative_register_raw_bytes (i, raw_buffer))
+ {
+ printf_filtered ("*value not available*\n");
+ continue;
+ }
+
+ /* Convert raw data to virtual format if necessary. */
+ if (REGISTER_CONVERTIBLE (i))
+ REGISTER_CONVERT_TO_VIRTUAL (i, REGISTER_VIRTUAL_TYPE (i),
+ raw_buffer, virtual_buffer);
+ else
+ memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (i));
+
+ /* If virtual format is floating, print it that way, and in raw hex. */
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT)
+ {
+ register int j;
+
+#ifdef INVALID_FLOAT
+ if (INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
+ printf_filtered ("<invalid float>");
+ else
+#endif
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
+
+ printf_filtered ("\t(raw 0x");
+ for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
+ {
+ register int idx = TARGET_BYTE_ORDER == BIG_ENDIAN ? j
+ : REGISTER_RAW_SIZE (i) - 1 - j;
+ printf_filtered ("%02x", (unsigned char) raw_buffer[idx]);
+ }
+ printf_filtered (")");
+ }
+ else
+ {
+ /* Print as integer in hex and in decimal. */
+ if (!altivec_register_p (i))
+ {
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 'x', 1, 0, Val_pretty_default);
+ printf_filtered ("\t");
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
+ }
+ else
+ /* Print as integer in hex only. */
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 'x', 1, 0, Val_pretty_default);
+ }
+ printf_filtered ("\n");
+ }
+}
+
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function.
@@ -1752,6 +1944,10 @@ rs6000_convert_from_func_ptr_addr (CORE_
systems. */
#define R8(name) { STR(name), 8, 8, 0 }
+/* Return a struct reg defining register NAME that's 128 bits on all
+ systems. */
+#define R16(name) { STR(name), 16, 16, 0 }
+
/* Return a struct reg defining floating-point register NAME. */
#define F(name) { STR(name), 8, 8, 1 }
@@ -1802,6 +1998,14 @@ rs6000_convert_from_func_ptr_addr (CORE_
/* 112 */ R(srr0), R(srr1), R(tbl), R(tbu), \
/* 116 */ R4(dec), R(dabr), R4(ear)
+/* AltiVec registers */
+#define PPC_ALTIVEC_REGS \
+ /*119*/R16(vr0), R16(vr1), R16(vr2), R16(vr3), R16(vr4), R16(vr5), R16(vr6), R16(vr7), \
+ /*127*/R16(vr8), R16(vr9), R16(vr10),R16(vr11),R16(vr12),R16(vr13),R16(vr14),R16(vr15), \
+ /*135*/R16(vr16),R16(vr17),R16(vr18),R16(vr19),R16(vr20),R16(vr21),R16(vr22),R16(vr23), \
+ /*143*/R16(vr24),R16(vr25),R16(vr26),R16(vr27),R16(vr28),R16(vr29),R16(vr30),R16(vr31), \
+ /*151*/R4(vscr), R4(vrsave)
+
/* IBM POWER (pre-PowerPC) architecture, user-level view. We only cover
user-level SPR's. */
static const struct reg registers_power[] =
@@ -1815,7 +2019,8 @@ static const struct reg registers_power[
static const struct reg registers_powerpc[] =
{
COMMON_UISA_REGS,
- PPC_UISA_SPRS
+ PPC_UISA_SPRS,
+ PPC_ALTIVEC_REGS
};
/* IBM PowerPC 403. */
@@ -1946,6 +2151,21 @@ static const struct reg registers_750[]
};
+/* Motorola PowerPC 7400. */
+static const struct reg registers_7400[] =
+{
+ /* gpr0-gpr31, fpr0-fpr31 */
+ COMMON_UISA_REGS,
+ /* ctr, xre, lr, cr */
+ PPC_UISA_SPRS,
+ /* sr0-sr15 */
+ PPC_SEGMENT_REGS,
+ PPC_OEA_SPRS,
+ /* vr0-vr31, vrsave, vscr */
+ PPC_ALTIVEC_REGS
+ /* FIXME? Add more registers? */
+};
+
/* Information about a particular processor variant. */
struct variant
@@ -2005,6 +2225,8 @@ static const struct variant variants[] =
bfd_mach_ppc_860, num_registers (registers_860), registers_860},
{"750", "Motorola/IBM PowerPC 750 or 740", bfd_arch_powerpc,
bfd_mach_ppc_750, num_registers (registers_750), registers_750},
+ {"7400", "Motorola/IBM PowerPC 7400 (G4)", bfd_arch_powerpc,
+ bfd_mach_ppc_7400, num_registers (registers_7400), registers_7400},
/* FIXME: I haven't checked the register sets of the following. */
{"620", "Motorola PowerPC 620", bfd_arch_powerpc,
@@ -2235,6 +2457,23 @@ rs6000_gdbarch_init (struct gdbarch_info
v = find_variant_by_name (power ? "power" : "powerpc");
tdep->regs = v->regs;
+ if (v->arch == bfd_arch_powerpc)
+ switch (v->mach)
+ {
+ case bfd_mach_ppc:
+ tdep->first_altivec_regnum = 71;
+ tdep->last_altivec_regnum = 104;
+ break;
+ case bfd_mach_ppc_7400:
+ tdep->first_altivec_regnum = 119;
+ tdep->last_altivec_regnum = 153;
+ break;
+ default:
+ tdep->first_altivec_regnum = -1;
+ tdep->last_altivec_regnum = -1;
+ break;
+ }
+
/* Calculate byte offsets in raw register array. */
tdep->regoff = xmalloc (v->nregs * sizeof (int));
for (i = off = 0; i < v->nregs; i++)
@@ -2263,6 +2502,7 @@ rs6000_gdbarch_init (struct gdbarch_info
set_gdbarch_register_virtual_size (gdbarch, rs6000_register_virtual_size);
set_gdbarch_max_register_virtual_size (gdbarch, 8);
set_gdbarch_register_virtual_type (gdbarch, rs6000_register_virtual_type);
+ set_gdbarch_do_registers_info (gdbarch, rs6000_do_registers_info);
set_gdbarch_ptr_bit (gdbarch, wordsize * TARGET_CHAR_BIT);
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
@@ -2359,6 +2599,14 @@ rs6000_gdbarch_init (struct gdbarch_info
return gdbarch;
}
+static struct cmd_list_element *info_power_cmdlist = NULL;
+
+static void
+rs6000_info_power_command (char *args, int from_tty)
+{
+ help_list (info_power_cmdlist, "info power ", class_info, gdb_stdout);
+}
+
/* Initialization code. */
void
@@ -2366,4 +2614,14 @@ _initialize_rs6000_tdep (void)
{
register_gdbarch_init (bfd_arch_rs6000, rs6000_gdbarch_init);
register_gdbarch_init (bfd_arch_powerpc, rs6000_gdbarch_init);
+
+ /* Add root prefix command for "info power" commands */
+ add_prefix_cmd ("power", class_info, rs6000_info_power_command,
+ "Various POWERPC info specific commands.",
+ &info_power_cmdlist, "info power ", 0, &infolist);
+
+ add_cmd ("altivec", class_info, rs6000_altivec_registers_info,
+ "Display the contents of the AltiVec registers.",
+ &info_power_cmdlist);
+
}
Index: config/powerpc/nm-linux.h
===================================================================
RCS file: /cvs/uberbaum/gdb/config/powerpc/nm-linux.h,v
retrieving revision 1.9
diff -u -p -r1.9 nm-linux.h
--- nm-linux.h 2001/11/20 16:36:44 1.9
+++ nm-linux.h 2001/11/28 23:26:20
@@ -30,6 +30,8 @@ extern int kernel_u_size (void);
#define U_REGS_OFFSET 0
+#define FETCH_INFERIOR_REGISTERS
+
extern int ppc_register_u_addr (int, int);
#define REGISTER_U_ADDR(addr, blockend, regno) \
(addr) = ppc_register_u_addr ((blockend),(regno));
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-28 18:33 ` Daniel Jacobowitz
@ 2001-11-18 13:40 ` Daniel Jacobowitz
0 siblings, 0 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-18 13:40 UTC (permalink / raw)
To: gdb-patches
On Wed, Nov 28, 2001 at 09:15:35PM -0500, Elena Zannoni wrote:
>
> AltiVec registers are 32 128-bit wide registers found on the G4
> powerpc processor family. This patch adds some initial support for
> such registers to gdb on a linux ppc platform.
>
> The Altivec registers are not displayed in a normal 'info reg' command
> output. They are shown (like fp regs) if one says 'info all' instead.
> Furthermore I added a specific 'info power altivec' command to display
> just the Altivec registers. (I am not sure that the word 'power' is
> the best choice, maybe simply 'ppc' or 'powerpc' is better). This way
> the command as just a specific powerpc info command, w/o it being a
> generic info command avaliable on every platform.
Use 'powerpc', please? 'power' is something quite different, and will
work as an abbreviation for powerpc anyway.
> If there is no kernel support for ptrace to handle the AltiVec
> registers, they will display as 0's.
>
> The little drawback is that such registers will be displayed any time
> gdb's architecture is 'powerpc:common' or 'powerpc:7400'. The first
> case is the architecture gdb defaults to when run on a ppc machine,
> because the multiarch mechanism cannot determine the nature of the
> executable file. To be clearer, there is no way for gdb to know that
> the architecture is meant to be a ppc7400 based on executable
> information provided by BFD (unlike for Mips and Sh). So, gdb will
> always start and *stay* with a powerpc:common architecture selected,
> unless the user explicitly sets the architecture to be
> 'powerpc:7400'. This impossibility to auto detect the architecture is
> what prompted me to have Altivec defined anyway for the default
> arch. [Hopefully this deficiency will be rectified soon].
Hopefully. I'd say this wasn't too big of a caveat for now, though,
and I and Andrew both seem to have ideas in this direction.
Other than that, I've got no real comments. Looks pretty good. There
are a number of very similar functions involved in the fetching/storing
that I'm a little unhappy with, but that seems to be about par for GDB.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-28 18:09 [RFA] W.I.P. AltiVec ppc registers support Elena Zannoni
2001-11-18 13:27 ` Elena Zannoni
@ 2001-11-18 14:11 ` Daniel Jacobowitz
2001-11-19 12:59 ` Andrew Cagney
` (2 more replies)
2001-11-28 18:33 ` Daniel Jacobowitz
2001-11-29 10:40 ` Kevin Buettner
3 siblings, 3 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-18 14:11 UTC (permalink / raw)
To: gdb-patches
On Wed, Nov 28, 2001 at 09:15:35PM -0500, Elena Zannoni wrote:
>
> AltiVec registers are 32 128-bit wide registers found on the G4
> powerpc processor family. This patch adds some initial support for
> such registers to gdb on a linux ppc platform.
>
> The Altivec registers are not displayed in a normal 'info reg' command
> output. They are shown (like fp regs) if one says 'info all' instead.
> Furthermore I added a specific 'info power altivec' command to display
> just the Altivec registers. (I am not sure that the word 'power' is
> the best choice, maybe simply 'ppc' or 'powerpc' is better). This way
> the command as just a specific powerpc info command, w/o it being a
> generic info command avaliable on every platform.
>
> If there is no kernel support for ptrace to handle the AltiVec
> registers, they will display as 0's.
Wait, I knew I was forgetting something important.
There is no kernel support for this feature in any public PowerPC
kernel tree, and to my knowledge there has been no suggested patch for
it on any of the public LinuxPPC forums. As such, the interface to it
is still up in the air. I've discussed this with other kernel folk at
various times, and the general consensus is that, instead of adding
them to the user area and using PEEKUSR, someone should simply
implement PTRACE_GETFPXREGS (perhaps just PTRACE_GETXREGS, as the FP
does not really apply, but consistency...). We almost never want to
fetch just one altivec register, excepting maybe VRSAVE, and GETFPXREGS
takes negligibly more time than a single PEEKUSR call.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-18 14:11 ` Daniel Jacobowitz
@ 2001-11-19 12:59 ` Andrew Cagney
2001-11-29 9:04 ` Andrew Cagney
2001-11-29 13:10 ` Daniel Jacobowitz
2001-11-28 22:27 ` Daniel Jacobowitz
2001-12-02 10:28 ` Elena Zannoni
2 siblings, 2 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-19 12:59 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
>
> Wait, I knew I was forgetting something important.
>
> There is no kernel support for this feature in any public PowerPC
> kernel tree, and to my knowledge there has been no suggested patch for
> it on any of the public LinuxPPC forums. As such, the interface to it
> is still up in the air. I've discussed this with other kernel folk at
> various times, and the general consensus is that, instead of adding
> them to the user area and using PEEKUSR, someone should simply
> implement PTRACE_GETFPXREGS (perhaps just PTRACE_GETXREGS, as the FP
> does not really apply, but consistency...). We almost never want to
> fetch just one altivec register, excepting maybe VRSAVE, and GETFPXREGS
> takes negligibly more time than a single PEEKUSR call.
So if the tweek to ppc-linux-nat.c that does the register fetch was
omitted, it would be ok?
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 10:40 ` Kevin Buettner
@ 2001-11-19 15:15 ` Kevin Buettner
2001-11-19 18:51 ` Elena Zannoni
1 sibling, 0 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-19 15:15 UTC (permalink / raw)
To: Elena Zannoni, gdb-patches
On Nov 28, 9:15pm, Elena Zannoni wrote:
> The first Changelog is just for the most recent change set. I included
> the older one for easy reference.
Thanks for doing this.
> I tested this on AIX4.3, on a Linux-ppc with Altivec kernel support,
> and on a Linux-ppx w/o Altivec kernel support.
Good.
Now, for my comments...
First, regarding the AltiVec ptrace() support in the Linux/PPC
kernel... Have the necessary patches been submitted to some public
mailing list? If so, I'd be willing to let the ptrace related bits go
in even if they haven't been agreed upon by the kernel developers. We
can always make adjustments to GDB later on after the kernel folks
have hashed out how they want to do things. OTOH, I'm extremely
reluctant approve any changes to GDB based on kernel patches which
haven't at least been posted for commentary to some public list.
Regarding the implementation...
> +/* AltiVec regs are not always supported by the kernel. We need to fake them,
> + and let the ptrace requests fail. */
> +#ifndef PT_VR0
> +#define PT_VR0 (PT_FPSCR + 1)
> +#endif
> +#ifndef PT_VR31
> +#define PT_VR31 (PT_VR0 + 4*31)
> +#endif
> +#ifndef PT_VRCR
> +#define PT_VRCR (PT_VR0 + 4*32)
> +#endif
> +#ifndef PT_VRSAVE
> +#define PT_VRSAVE (PT_VR0 + 4*33)
> +#endif
I don't think it's a good idea to provide fake PT_ constants,
especially since the kernel folks haven't agreed upon using PEEKUSER /
POKEUSER for accessing the AltiVec registers. Also, in the interim,
it could happen that someone else will come up with a different ptrace
extension (perhaps involving hardware watchpoints?) that uses
constants at some of the offsets used by your fake AltiVec registers.
If this were to happen, gdb could potentially write these registers
with unpredictable consequences.
The PT_V0 constant is the only constant used in the above defines and
it's only used in one place (in ppc_register_u_addr). Rather than
using the above #defines, might I suggest that instead of doing:
/* Altivec registers: 4 slots each. */
if (altivec_register_p (regno))
u_addr = (ustart + (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4);
you instead do:
/* Altivec registers: 4 slots each. */
if (altivec_register_p (regno))
{
#ifdef PT_VR0
u_addr = (ustart + (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4);
#else
u_addr = -1;
#endif
}
The #else clause isn't really necessary because you already initialize
u_addr to -1 at the outset.
The other advantage to doing things this way is that you'll no longer
need a separate fetch_altivec_register() function which differs from
fetch_register() only in that it doesn't print a message when ptrace()
produces an error. (And likewise for store_register() /
store_altivec_register().)
....
Regarding...
> -static int regmap[] =
[etc]
from your previous patch, I've decided that while the code ends up being
more verbose, it is easier to read and understand what's going on. So
I'm approving your previous patch. (I'll send out a separate approval
message if you wish.)
With regard to
> Index: config/powerpc/nm-linux.h
[...]
> +#define FETCH_INFERIOR_REGISTERS
I think this is a good thing. It *might not* be strictly necessary
for adding AltiVec support via PEEKUSER / POKEUSER, but it does give
us more control. Also doing this allows us to clean up the code in other
ways. E.g, the following bit from config/powerpc/nm-linux.h can be
removed:
> extern int ppc_register_u_addr (int, int);
> #define REGISTER_U_ADDR(addr, blockend, regno) \
> (addr) = ppc_register_u_addr ((blockend),(regno));
This in turn means that ppc_register_u_addr() can be made static
and that the ``ustart'' parameter can be removed. All calls to
register_addr() (in your new code) in ppc-linux-nat.c should be
changed to invoke ppc_register_u_addr() directly.
....
Your changes to rs6000-tdep.c and ppc-tdep.h look fine to me.
Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 13:10 ` Daniel Jacobowitz
@ 2001-11-19 16:00 ` Daniel Jacobowitz
2001-11-29 13:34 ` Kevin Buettner
1 sibling, 0 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-19 16:00 UTC (permalink / raw)
To: gdb-patches
On Thu, Nov 29, 2001 at 12:04:22PM -0500, Andrew Cagney wrote:
> >
> >Wait, I knew I was forgetting something important.
> >
> >There is no kernel support for this feature in any public PowerPC
> >kernel tree, and to my knowledge there has been no suggested patch for
> >it on any of the public LinuxPPC forums. As such, the interface to it
> >is still up in the air. I've discussed this with other kernel folk at
> >various times, and the general consensus is that, instead of adding
> >them to the user area and using PEEKUSR, someone should simply
> >implement PTRACE_GETFPXREGS (perhaps just PTRACE_GETXREGS, as the FP
> >does not really apply, but consistency...). We almost never want to
> >fetch just one altivec register, excepting maybe VRSAVE, and GETFPXREGS
> >takes negligibly more time than a single PEEKUSR call.
>
> So if the tweek to ppc-linux-nat.c that does the register fetch was
> omitted, it would be ok?
It would be (somewhat trivial, but) OK, yes. I have nothing against
the implementation, just the interface.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 13:34 ` Kevin Buettner
@ 2001-11-19 16:42 ` Kevin Buettner
2001-11-29 14:11 ` Kevin Buettner
1 sibling, 0 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-19 16:42 UTC (permalink / raw)
To: Daniel Jacobowitz, gdb-patches
On Nov 29, 4:09pm, Daniel Jacobowitz wrote:
> On Thu, Nov 29, 2001 at 12:04:22PM -0500, Andrew Cagney wrote:
> > >
> > >Wait, I knew I was forgetting something important.
> > >
> > >There is no kernel support for this feature in any public PowerPC
> > >kernel tree, and to my knowledge there has been no suggested patch for
> > >it on any of the public LinuxPPC forums. As such, the interface to it
> > >is still up in the air. I've discussed this with other kernel folk at
> > >various times, and the general consensus is that, instead of adding
> > >them to the user area and using PEEKUSR, someone should simply
> > >implement PTRACE_GETFPXREGS (perhaps just PTRACE_GETXREGS, as the FP
> > >does not really apply, but consistency...). We almost never want to
> > >fetch just one altivec register, excepting maybe VRSAVE, and GETFPXREGS
> > >takes negligibly more time than a single PEEKUSR call.
> >
> > So if the tweek to ppc-linux-nat.c that does the register fetch was
> > omitted, it would be ok?
>
> It would be (somewhat trivial, but) OK, yes. I have nothing against
> the implementation, just the interface.
If Elena makes the changes that I have in mind, the AltiVec specific
code which affects the interface will collapse down to 5 lines or so.
Of course, if PTRACE_GETFPXREGS (or the like) ends up being used,
ppc-linux-nat.c need to be substantially rewritten anyway. But the
point is that the five lines (or so) that I have in mind can then just
be deleted.
Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 10:40 ` Kevin Buettner
2001-11-19 15:15 ` Kevin Buettner
@ 2001-11-19 18:51 ` Elena Zannoni
2001-11-29 13:53 ` Elena Zannoni
2001-11-29 14:21 ` Kevin Buettner
1 sibling, 2 replies; 63+ messages in thread
From: Elena Zannoni @ 2001-11-19 18:51 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
Kevin Buettner writes:
> On Nov 28, 9:15pm, Elena Zannoni wrote:
>
> > The first Changelog is just for the most recent change set. I included
> > the older one for easy reference.
>
> Thanks for doing this.
>
> > I tested this on AIX4.3, on a Linux-ppc with Altivec kernel support,
> > and on a Linux-ppx w/o Altivec kernel support.
>
> Good.
>
> Now, for my comments...
>
> First, regarding the AltiVec ptrace() support in the Linux/PPC
> kernel... Have the necessary patches been submitted to some public
> mailing list? If so, I'd be willing to let the ptrace related bits go
> in even if they haven't been agreed upon by the kernel developers. We
> can always make adjustments to GDB later on after the kernel folks
> have hashed out how they want to do things. OTOH, I'm extremely
> reluctant approve any changes to GDB based on kernel patches which
> haven't at least been posted for commentary to some public list.
No :-( I am going hopefully to sort this out very soon.
>
> Regarding the implementation...
>
> > +/* AltiVec regs are not always supported by the kernel. We need to fake them,
> > + and let the ptrace requests fail. */
> > +#ifndef PT_VR0
> > +#define PT_VR0 (PT_FPSCR + 1)
> > +#endif
> > +#ifndef PT_VR31
> > +#define PT_VR31 (PT_VR0 + 4*31)
> > +#endif
> > +#ifndef PT_VRCR
> > +#define PT_VRCR (PT_VR0 + 4*32)
> > +#endif
> > +#ifndef PT_VRSAVE
> > +#define PT_VRSAVE (PT_VR0 + 4*33)
> > +#endif
>
> I don't think it's a good idea to provide fake PT_ constants,
> especially since the kernel folks haven't agreed upon using PEEKUSER /
> POKEUSER for accessing the AltiVec registers. Also, in the interim,
> it could happen that someone else will come up with a different ptrace
> extension (perhaps involving hardware watchpoints?) that uses
> constants at some of the offsets used by your fake AltiVec registers.
> If this were to happen, gdb could potentially write these registers
> with unpredictable consequences.
>
> The PT_V0 constant is the only constant used in the above defines and
> it's only used in one place (in ppc_register_u_addr). Rather than
> using the above #defines, might I suggest that instead of doing:
>
> /* Altivec registers: 4 slots each. */
> if (altivec_register_p (regno))
> u_addr = (ustart + (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4);
>
> you instead do:
>
> /* Altivec registers: 4 slots each. */
> if (altivec_register_p (regno))
> {
> #ifdef PT_VR0
> u_addr = (ustart + (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4);
> #else
> u_addr = -1;
> #endif
> }
>
> The #else clause isn't really necessary because you already initialize
> u_addr to -1 at the outset.
>
> The other advantage to doing things this way is that you'll no longer
> need a separate fetch_altivec_register() function which differs from
> fetch_register() only in that it doesn't print a message when ptrace()
> produces an error. (And likewise for store_register() /
> store_altivec_register().)
>
Oh, right, I don't use anything but PT_VR0 now (I did in ohter
versions of the patch, and forgot to erase them). It indeed seems
cleaner doing like you say. I also came up with a configure patch but
that seemed less flexible.
> ....
>
> Regarding...
>
> > -static int regmap[] =
> [etc]
>
> from your previous patch, I've decided that while the code ends up being
> more verbose, it is easier to read and understand what's going on. So
> I'm approving your previous patch. (I'll send out a separate approval
> message if you wish.)
>
Thanks, please, since that is a separate thread.
> With regard to
>
> > Index: config/powerpc/nm-linux.h
> [...]
> > +#define FETCH_INFERIOR_REGISTERS
>
> I think this is a good thing. It *might not* be strictly necessary
> for adding AltiVec support via PEEKUSER / POKEUSER, but it does give
> us more control. Also doing this allows us to clean up the code in other
> ways. E.g, the following bit from config/powerpc/nm-linux.h can be
> removed:
>
> > extern int ppc_register_u_addr (int, int);
> > #define REGISTER_U_ADDR(addr, blockend, regno) \
> > (addr) = ppc_register_u_addr ((blockend),(regno));
>
> This in turn means that ppc_register_u_addr() can be made static
> and that the ``ustart'' parameter can be removed. All calls to
> register_addr() (in your new code) in ppc-linux-nat.c should be
> changed to invoke ppc_register_u_addr() directly.
>
Unfortunately not. I thought the same, until I remembered about core
file debugging. That function is called by fetch_core_registers() in
core-aout.c.
> ....
>
> Your changes to rs6000-tdep.c and ppc-tdep.h look fine to me.
>
OK.
> Kevin
Elena
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 14:11 ` Kevin Buettner
@ 2001-11-19 22:22 ` Kevin Buettner
2001-11-29 14:27 ` Elena Zannoni
1 sibling, 0 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-19 22:22 UTC (permalink / raw)
To: gdb-patches
On Nov 29, 2:32pm, Kevin Buettner wrote:
> If Elena makes the changes that I have in mind,...
> code which affects the interface will collapse down to 5 lines or so.
> Of course, if PTRACE_GETFPXREGS (or the like) ends up being used,
> ppc-linux-nat.c need to be substantially rewritten anyway. But the
> point is that the five lines (or so) that I have in mind can then just
> be deleted.
It occurred to me that it might help Elena more if I provided a
patch with what I had in mind. See below. (Completely untested.)
Anyway, the five lines that I refer to above is this part:
+#ifdef PT_VR0
+ u_addr = (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4;
+#else
+ u_addr = -1;
+#endif
Index: ppc-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-nat.c,v
retrieving revision 1.10
diff -u -p -r1.10 ppc-linux-nat.c
--- ppc-linux-nat.c 2001/11/20 16:35:24 1.10
+++ ppc-linux-nat.c 2001/11/29 22:05:26
@@ -32,31 +32,243 @@
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/procfs.h>
+#include <sys/ptrace.h>
/* Prototypes for supply_gregset etc. */
#include "gregset.h"
+#include "ppc-tdep.h"
+/* Default the type of the ptrace transfer to int. */
+#ifndef PTRACE_XFER_TYPE
+#define PTRACE_XFER_TYPE long
+#endif
+
int
kernel_u_size (void)
{
return (sizeof (struct user));
}
+
+/* *INDENT-OFF* */
+/* registers layout, as presented by the ptrace interface:
+PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
+PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
+PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
+PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
+PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
+PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
+PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
+PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
+PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ */
+/* *INDENT_ON * */
+
+static int
+ppc_register_u_addr (int regno)
+{
+ int u_addr = -1;
+
+ /* General purpose registers occupy 1 slot each in the buffer */
+ if (regno >= PPC_GP0_REGNUM && regno <= PPC_GPLAST_REGNUM )
+ u_addr = (PT_R0 + regno) * 4;
+
+ /* Floating point regs: 2 slots each */
+ if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM)
+ u_addr = (PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4;
+
+ /* Altivec registers: 4 slots each. */
+ if (altivec_register_p (regno))
+ {
+#ifdef PT_VR0
+ u_addr = (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4;
+#else
+ u_addr = -1;
+#endif
+ }
+
+ /* UISA special purpose registers: 1 slot each */
+ if (regno == PC_REGNUM)
+ u_addr = PT_NIP * 4;
+ if (regno == PPC_LR_REGNUM)
+ u_addr = PT_LNK * 4;
+ if (regno == PPC_CR_REGNUM)
+ u_addr = PT_CCR * 4;
+ if (regno == PPC_XER_REGNUM)
+ u_addr = PT_XER * 4;
+ if (regno == PPC_CTR_REGNUM)
+ u_addr = PT_CTR * 4;
+ if (regno == PPC_MQ_REGNUM)
+ u_addr = PT_MQ * 4;
+ if (regno == PPC_PS_REGNUM)
+ u_addr = PT_MSR * 4;
+
+ return u_addr;
+}
+
+static int
+ppc_ptrace_cannot_fetch_store_register (int regno)
+{
+ return (ppc_register_u_addr (regno) == -1);
+}
+
+static void
+fetch_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int tid;
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ {
+ memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ regaddr = ppc_register_u_addr (regno);
+ if (regaddr < 0)
+ return;
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PTRACE_PEEKUSR, tid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ sprintf (mess, "reading register %s (#%d)",
+ REGISTER_NAME (regno), regno);
+ perror_with_name (mess);
+ }
+ }
+ supply_register (regno, buf);
+}
+
+static void
+fetch_ppc_registers (void)
+{
+ int last_register;
+ int i;
+
+ last_register = PPC_MQ_REGNUM;
+ for (i = 0; i <= last_register; i++)
+ fetch_register (i);
+}
+
+static void
+fetch_altivec_registers (void)
+{
+ int i;
+
+ for (i = 0;
+ i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
+ - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
+ i++)
+ fetch_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
+}
+
+/* Fetch registers from the child process. Fetch all registers if
+ regno == -1, otherwise fetch all general registers or all floating
+ point registers depending upon the value of regno. */
+
+void
+fetch_inferior_registers (int regno)
+{
+ if (regno == -1)
+ {
+ fetch_ppc_registers ();
+ fetch_altivec_registers ();
+ }
+ else
+ {
+ if (altivec_register_p (regno))
+ fetch_altivec_register (regno);
+ else
+ fetch_register (regno);
+ }
+}
+
+/* Store one register. */
+static void
+store_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ int tid;
+ char *buf = alloca (MAX_REGISTER_RAW_SIZE);
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ {
+ return;
+ }
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ regaddr = ppc_register_u_addr (regno);
+ regcache_collect (regno, buf);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PTRACE_POKEUSR, tid, (PTRACE_ARG3_TYPE) regaddr,
+ *(PTRACE_XFER_TYPE *) & buf[i]);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ sprintf (mess, "writing register %s (#%d)",
+ REGISTER_NAME (regno), regno);
+ perror_with_name (mess);
+ }
+ }
+}
+
+static void
+store_ppc_registers (void)
+{
+ int last_register;
+ int i;
+
+ last_register = PPC_MQ_REGNUM;
+ for (i = 0; i <= last_register; i++)
+ store_register (i);
+}
+
+static void
+store_altivec_registers (void)
+{
+ int i;
-static int regmap[] =
-{PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
- PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
- PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
- PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
- PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
- PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
- PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
- PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
- PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ};
+ for (i = 0;
+ i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
+ - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
+ i++)
+ store_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
+}
-int
-ppc_register_u_addr (int ustart, int regnum)
+void
+store_inferior_registers (int regno)
{
- return (ustart + 4 * regmap[regnum]);
+ if (regno >= 0)
+ {
+ if (altivec_register_p (regno))
+ store_altivec_register (regno);
+ else
+ store_register (regno);
+ }
+ else
+ {
+ store_ppc_registers ();
+ store_altivec_registers ();
+ }
}
void
@@ -68,8 +280,13 @@ supply_gregset (gdb_gregset_t *gregsetp)
for (regi = 0; regi < 32; regi++)
supply_register (regi, (char *) (regp + regi));
- for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
- supply_register (regi, (char *) (regp + regmap[regi]));
+ supply_register (PC_REGNUM, (char *) (regp + PT_NIP));
+ supply_register (PPC_LR_REGNUM, (char *) (regp + PT_LNK));
+ supply_register (PPC_CR_REGNUM, (char *) (regp + PT_CCR));
+ supply_register (PPC_XER_REGNUM, (char *) (regp + PT_XER));
+ supply_register (PPC_CTR_REGNUM, (char *) (regp + PT_CTR));
+ supply_register (PPC_MQ_REGNUM, (char *) (regp + PT_MQ));
+ supply_register (PPC_PS_REGNUM, (char *) (regp + PT_MSR));
}
void
@@ -78,19 +295,26 @@ fill_gregset (gdb_gregset_t *gregsetp, i
int regi;
elf_greg_t *regp = (elf_greg_t *) gregsetp;
-#define COPY_REG(_idx_,_regi_) \
- if ((regno == -1) || regno == _regi_) \
- regcache_collect (_regi_, regp + _idx_)
-
for (regi = 0; regi < 32; regi++)
{
- COPY_REG (regmap[regi], regi);
+ if ((regno == -1) || regno == regi)
+ regcache_collect (regi, regp + PT_R0 + regi);
}
- for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
- {
- COPY_REG (regmap[regi], regi);
- }
+ if ((regno == -1) || regno == PC_REGNUM)
+ regcache_collect (PC_REGNUM, regp + PT_NIP);
+ if ((regno == -1) || regno == PPC_LR_REGNUM)
+ regcache_collect (PPC_LR_REGNUM, regp + PT_LNK);
+ if ((regno == -1) || regno == PPC_CR_REGNUM)
+ regcache_collect (PPC_CR_REGNUM, regp + PT_CCR);
+ if ((regno == -1) || regno == PPC_XER_REGNUM)
+ regcache_collect (PPC_XER_REGNUM, regp + PT_XER);
+ if ((regno == -1) || regno == PPC_CTR_REGNUM)
+ regcache_collect (PPC_CTR_REGNUM, regp + PT_CTR);
+ if ((regno == -1) || regno == PPC_MQ_REGNUM)
+ regcache_collect (PPC_MQ_REGNUM, regp + PT_MQ);
+ if ((regno == -1) || regno == PPC_PS_REGNUM)
+ regcache_collect (PPC_PS_REGNUM, regp + PT_MSR);
}
void
Index: config/powerpc/nm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/powerpc/nm-linux.h,v
retrieving revision 1.9
diff -u -p -r1.9 nm-linux.h
--- nm-linux.h 2001/11/20 16:36:44 1.9
+++ nm-linux.h 2001/11/29 22:05:32
@@ -23,15 +23,6 @@ Foundation, Inc., 675 Mass Ave, Cambridg
#define NM_LINUX_H
-/* Return sizeof user struct to callers in less machine dependent routines */
-
-#define KERNEL_U_SIZE kernel_u_size()
-extern int kernel_u_size (void);
-
-#define U_REGS_OFFSET 0
-
-extern int ppc_register_u_addr (int, int);
-#define REGISTER_U_ADDR(addr, blockend, regno) \
- (addr) = ppc_register_u_addr ((blockend),(regno));
+#define FETCH_INFERIOR_REGISTERS
#endif /* #ifndef NM_LINUX_H */
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 14:21 ` Kevin Buettner
@ 2001-11-19 22:53 ` Kevin Buettner
2001-11-29 14:42 ` Elena Zannoni
2001-11-29 14:47 ` Daniel Jacobowitz
2 siblings, 0 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-19 22:53 UTC (permalink / raw)
To: Daniel Jacobowitz, Elena Zannoni; +Cc: gdb-patches
On Nov 29, 4:59pm, Elena Zannoni wrote:
> > With regard to
> >
> > > Index: config/powerpc/nm-linux.h
> > [...]
> > > +#define FETCH_INFERIOR_REGISTERS
> >
> > I think this is a good thing. It *might not* be strictly necessary
> > for adding AltiVec support via PEEKUSER / POKEUSER, but it does give
> > us more control. Also doing this allows us to clean up the code in other
> > ways. E.g, the following bit from config/powerpc/nm-linux.h can be
> > removed:
> >
> > > extern int ppc_register_u_addr (int, int);
> > > #define REGISTER_U_ADDR(addr, blockend, regno) \
> > > (addr) = ppc_register_u_addr ((blockend),(regno));
> >
> > This in turn means that ppc_register_u_addr() can be made static
> > and that the ``ustart'' parameter can be removed. All calls to
> > register_addr() (in your new code) in ppc-linux-nat.c should be
> > changed to invoke ppc_register_u_addr() directly.
> >
>
> Unfortunately not. I thought the same, until I remembered about core
> file debugging. That function is called by fetch_core_registers() in
> core-aout.c.
Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
core-regset.c instead?
Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 14:27 ` Elena Zannoni
@ 2001-11-19 23:55 ` Elena Zannoni
0 siblings, 0 replies; 63+ messages in thread
From: Elena Zannoni @ 2001-11-19 23:55 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches
Kevin Buettner writes:
> On Nov 29, 2:32pm, Kevin Buettner wrote:
>
> > If Elena makes the changes that I have in mind,...
> > code which affects the interface will collapse down to 5 lines or so.
> > Of course, if PTRACE_GETFPXREGS (or the like) ends up being used,
> > ppc-linux-nat.c need to be substantially rewritten anyway. But the
> > point is that the five lines (or so) that I have in mind can then just
> > be deleted.
>
> It occurred to me that it might help Elena more if I provided a
> patch with what I had in mind. See below. (Completely untested.)
I am not that helpless :-)
Let me wait a bit on this until the ptrace issue is clarified somewhat.
Elena
>
> Anyway, the five lines that I refer to above is this part:
>
> +#ifdef PT_VR0
> + u_addr = (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4;
> +#else
> + u_addr = -1;
> +#endif
>
>
> Index: ppc-linux-nat.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/ppc-linux-nat.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 ppc-linux-nat.c
> --- ppc-linux-nat.c 2001/11/20 16:35:24 1.10
> +++ ppc-linux-nat.c 2001/11/29 22:05:26
> @@ -32,31 +32,243 @@
> #include <sys/wait.h>
> #include <fcntl.h>
> #include <sys/procfs.h>
> +#include <sys/ptrace.h>
>
> /* Prototypes for supply_gregset etc. */
> #include "gregset.h"
> +#include "ppc-tdep.h"
>
> +/* Default the type of the ptrace transfer to int. */
> +#ifndef PTRACE_XFER_TYPE
> +#define PTRACE_XFER_TYPE long
> +#endif
> +
> int
> kernel_u_size (void)
> {
> return (sizeof (struct user));
> }
> +
> +/* *INDENT-OFF* */
> +/* registers layout, as presented by the ptrace interface:
> +PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
> +PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
> +PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
> +PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
> +PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
> +PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
> +PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
> +PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
> +PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ */
> +/* *INDENT_ON * */
> +
> +static int
> +ppc_register_u_addr (int regno)
> +{
> + int u_addr = -1;
> +
> + /* General purpose registers occupy 1 slot each in the buffer */
> + if (regno >= PPC_GP0_REGNUM && regno <= PPC_GPLAST_REGNUM )
> + u_addr = (PT_R0 + regno) * 4;
> +
> + /* Floating point regs: 2 slots each */
> + if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM)
> + u_addr = (PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4;
> +
> + /* Altivec registers: 4 slots each. */
> + if (altivec_register_p (regno))
> + {
> +#ifdef PT_VR0
> + u_addr = (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4;
> +#else
> + u_addr = -1;
> +#endif
> + }
> +
> + /* UISA special purpose registers: 1 slot each */
> + if (regno == PC_REGNUM)
> + u_addr = PT_NIP * 4;
> + if (regno == PPC_LR_REGNUM)
> + u_addr = PT_LNK * 4;
> + if (regno == PPC_CR_REGNUM)
> + u_addr = PT_CCR * 4;
> + if (regno == PPC_XER_REGNUM)
> + u_addr = PT_XER * 4;
> + if (regno == PPC_CTR_REGNUM)
> + u_addr = PT_CTR * 4;
> + if (regno == PPC_MQ_REGNUM)
> + u_addr = PT_MQ * 4;
> + if (regno == PPC_PS_REGNUM)
> + u_addr = PT_MSR * 4;
> +
> + return u_addr;
> +}
> +
> +static int
> +ppc_ptrace_cannot_fetch_store_register (int regno)
> +{
> + return (ppc_register_u_addr (regno) == -1);
> +}
> +
> +static void
> +fetch_register (int regno)
> +{
> + /* This isn't really an address. But ptrace thinks of it as one. */
> + CORE_ADDR regaddr;
> + char mess[128]; /* For messages */
> + register int i;
> + char buf[MAX_REGISTER_RAW_SIZE];
> + int tid;
> +
> + if (ppc_ptrace_cannot_fetch_store_register (regno))
> + {
> + memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
> + supply_register (regno, buf);
> + return;
> + }
> +
> + /* Overload thread id onto process id */
> + if ((tid = TIDGET (inferior_ptid)) == 0)
> + tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
> +
> + regaddr = ppc_register_u_addr (regno);
> + if (regaddr < 0)
> + return;
> + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
> + {
> + errno = 0;
> + *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PTRACE_PEEKUSR, tid,
> + (PTRACE_ARG3_TYPE) regaddr, 0);
> + regaddr += sizeof (PTRACE_XFER_TYPE);
> + if (errno != 0)
> + {
> + sprintf (mess, "reading register %s (#%d)",
> + REGISTER_NAME (regno), regno);
> + perror_with_name (mess);
> + }
> + }
> + supply_register (regno, buf);
> +}
> +
> +static void
> +fetch_ppc_registers (void)
> +{
> + int last_register;
> + int i;
> +
> + last_register = PPC_MQ_REGNUM;
> + for (i = 0; i <= last_register; i++)
> + fetch_register (i);
> +}
> +
> +static void
> +fetch_altivec_registers (void)
> +{
> + int i;
> +
> + for (i = 0;
> + i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
> + - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
> + i++)
> + fetch_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
> +}
> +
> +/* Fetch registers from the child process. Fetch all registers if
> + regno == -1, otherwise fetch all general registers or all floating
> + point registers depending upon the value of regno. */
> +
> +void
> +fetch_inferior_registers (int regno)
> +{
> + if (regno == -1)
> + {
> + fetch_ppc_registers ();
> + fetch_altivec_registers ();
> + }
> + else
> + {
> + if (altivec_register_p (regno))
> + fetch_altivec_register (regno);
> + else
> + fetch_register (regno);
> + }
> +}
> +
> +/* Store one register. */
> +static void
> +store_register (int regno)
> +{
> + /* This isn't really an address. But ptrace thinks of it as one. */
> + CORE_ADDR regaddr;
> + char mess[128]; /* For messages */
> + register int i;
> + int tid;
> + char *buf = alloca (MAX_REGISTER_RAW_SIZE);
> +
> + if (ppc_ptrace_cannot_fetch_store_register (regno))
> + {
> + return;
> + }
> +
> + /* Overload thread id onto process id */
> + if ((tid = TIDGET (inferior_ptid)) == 0)
> + tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
> +
> + regaddr = ppc_register_u_addr (regno);
> + regcache_collect (regno, buf);
> + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
> + {
> + errno = 0;
> + ptrace (PTRACE_POKEUSR, tid, (PTRACE_ARG3_TYPE) regaddr,
> + *(PTRACE_XFER_TYPE *) & buf[i]);
> + regaddr += sizeof (PTRACE_XFER_TYPE);
> + if (errno != 0)
> + {
> + sprintf (mess, "writing register %s (#%d)",
> + REGISTER_NAME (regno), regno);
> + perror_with_name (mess);
> + }
> + }
> +}
> +
> +static void
> +store_ppc_registers (void)
> +{
> + int last_register;
> + int i;
> +
> + last_register = PPC_MQ_REGNUM;
> + for (i = 0; i <= last_register; i++)
> + store_register (i);
> +}
> +
> +static void
> +store_altivec_registers (void)
> +{
> + int i;
>
> -static int regmap[] =
> -{PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
> - PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
> - PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
> - PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
> - PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
> - PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
> - PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
> - PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
> - PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ};
> + for (i = 0;
> + i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
> + - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
> + i++)
> + store_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
> +}
>
> -int
> -ppc_register_u_addr (int ustart, int regnum)
> +void
> +store_inferior_registers (int regno)
> {
> - return (ustart + 4 * regmap[regnum]);
> + if (regno >= 0)
> + {
> + if (altivec_register_p (regno))
> + store_altivec_register (regno);
> + else
> + store_register (regno);
> + }
> + else
> + {
> + store_ppc_registers ();
> + store_altivec_registers ();
> + }
> }
>
> void
> @@ -68,8 +280,13 @@ supply_gregset (gdb_gregset_t *gregsetp)
> for (regi = 0; regi < 32; regi++)
> supply_register (regi, (char *) (regp + regi));
>
> - for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
> - supply_register (regi, (char *) (regp + regmap[regi]));
> + supply_register (PC_REGNUM, (char *) (regp + PT_NIP));
> + supply_register (PPC_LR_REGNUM, (char *) (regp + PT_LNK));
> + supply_register (PPC_CR_REGNUM, (char *) (regp + PT_CCR));
> + supply_register (PPC_XER_REGNUM, (char *) (regp + PT_XER));
> + supply_register (PPC_CTR_REGNUM, (char *) (regp + PT_CTR));
> + supply_register (PPC_MQ_REGNUM, (char *) (regp + PT_MQ));
> + supply_register (PPC_PS_REGNUM, (char *) (regp + PT_MSR));
> }
>
> void
> @@ -78,19 +295,26 @@ fill_gregset (gdb_gregset_t *gregsetp, i
> int regi;
> elf_greg_t *regp = (elf_greg_t *) gregsetp;
>
> -#define COPY_REG(_idx_,_regi_) \
> - if ((regno == -1) || regno == _regi_) \
> - regcache_collect (_regi_, regp + _idx_)
> -
> for (regi = 0; regi < 32; regi++)
> {
> - COPY_REG (regmap[regi], regi);
> + if ((regno == -1) || regno == regi)
> + regcache_collect (regi, regp + PT_R0 + regi);
> }
>
> - for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
> - {
> - COPY_REG (regmap[regi], regi);
> - }
> + if ((regno == -1) || regno == PC_REGNUM)
> + regcache_collect (PC_REGNUM, regp + PT_NIP);
> + if ((regno == -1) || regno == PPC_LR_REGNUM)
> + regcache_collect (PPC_LR_REGNUM, regp + PT_LNK);
> + if ((regno == -1) || regno == PPC_CR_REGNUM)
> + regcache_collect (PPC_CR_REGNUM, regp + PT_CCR);
> + if ((regno == -1) || regno == PPC_XER_REGNUM)
> + regcache_collect (PPC_XER_REGNUM, regp + PT_XER);
> + if ((regno == -1) || regno == PPC_CTR_REGNUM)
> + regcache_collect (PPC_CTR_REGNUM, regp + PT_CTR);
> + if ((regno == -1) || regno == PPC_MQ_REGNUM)
> + regcache_collect (PPC_MQ_REGNUM, regp + PT_MQ);
> + if ((regno == -1) || regno == PPC_PS_REGNUM)
> + regcache_collect (PPC_PS_REGNUM, regp + PT_MSR);
> }
>
> void
> Index: config/powerpc/nm-linux.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/config/powerpc/nm-linux.h,v
> retrieving revision 1.9
> diff -u -p -r1.9 nm-linux.h
> --- nm-linux.h 2001/11/20 16:36:44 1.9
> +++ nm-linux.h 2001/11/29 22:05:32
> @@ -23,15 +23,6 @@ Foundation, Inc., 675 Mass Ave, Cambridg
>
> #define NM_LINUX_H
>
> -/* Return sizeof user struct to callers in less machine dependent routines */
> -
> -#define KERNEL_U_SIZE kernel_u_size()
> -extern int kernel_u_size (void);
> -
> -#define U_REGS_OFFSET 0
> -
> -extern int ppc_register_u_addr (int, int);
> -#define REGISTER_U_ADDR(addr, blockend, regno) \
> - (addr) = ppc_register_u_addr ((blockend),(regno));
> +#define FETCH_INFERIOR_REGISTERS
>
> #endif /* #ifndef NM_LINUX_H */
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 14:47 ` Daniel Jacobowitz
@ 2001-11-20 8:37 ` Daniel Jacobowitz
2001-11-20 9:07 ` Kevin Buettner
2001-12-20 10:02 ` Elena Zannoni
2 siblings, 0 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-20 8:37 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 03:20:00PM -0700, Kevin Buettner wrote:
> On Nov 29, 4:59pm, Elena Zannoni wrote:
>
> > > With regard to
> > >
> > > > Index: config/powerpc/nm-linux.h
> > > [...]
> > > > +#define FETCH_INFERIOR_REGISTERS
> > >
> > > I think this is a good thing. It *might not* be strictly necessary
> > > for adding AltiVec support via PEEKUSER / POKEUSER, but it does give
> > > us more control. Also doing this allows us to clean up the code in other
> > > ways. E.g, the following bit from config/powerpc/nm-linux.h can be
> > > removed:
> > >
> > > > extern int ppc_register_u_addr (int, int);
> > > > #define REGISTER_U_ADDR(addr, blockend, regno) \
> > > > (addr) = ppc_register_u_addr ((blockend),(regno));
> > >
> > > This in turn means that ppc_register_u_addr() can be made static
> > > and that the ``ustart'' parameter can be removed. All calls to
> > > register_addr() (in your new code) in ppc-linux-nat.c should be
> > > changed to invoke ppc_register_u_addr() directly.
> > >
> >
> > Unfortunately not. I thought the same, until I remembered about core
> > file debugging. That function is called by fetch_core_registers() in
> > core-aout.c.
>
> Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> core-regset.c instead?
I'd like to kill our use of core-aout.c. Linux/PPC never used a.out
cores, but unfortunately core-aout.c defines register_addr () as a
wrapper for REGISTER_U_ADDR. The last time I tried to remove
core-aout.c from a platform I got bitten.
I think, now that we are defining FETCH_INFERIOR_REGISTERS, we can do
without it - infptrace was the only big consumer I see remaining. So
we might be OK without using core-aout.c at all now.
My still-unsubmitted cross-core patches for PowerPC remove
core-regset.o also, and very unpleasantly turn ppc-linux-nat.c into a
target-dependant rather than native-dependant file, so that we can grub
through the gregsets by hand. If you've got a better idea I'd love to
hear it :) It will be made somewhat easier by the destruction of
regmap[].
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 14:42 ` Elena Zannoni
@ 2001-11-20 8:37 ` Elena Zannoni
2001-11-29 15:03 ` Andrew Cagney
1 sibling, 0 replies; 63+ messages in thread
From: Elena Zannoni @ 2001-11-20 8:37 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Daniel Jacobowitz, Elena Zannoni, gdb-patches
Kevin Buettner writes:
> On Nov 29, 4:59pm, Elena Zannoni wrote:
>
> > > With regard to
> > >
> > > > Index: config/powerpc/nm-linux.h
> > > [...]
> > > > +#define FETCH_INFERIOR_REGISTERS
> > >
> > > I think this is a good thing. It *might not* be strictly necessary
> > > for adding AltiVec support via PEEKUSER / POKEUSER, but it does give
> > > us more control. Also doing this allows us to clean up the code in other
> > > ways. E.g, the following bit from config/powerpc/nm-linux.h can be
> > > removed:
> > >
> > > > extern int ppc_register_u_addr (int, int);
> > > > #define REGISTER_U_ADDR(addr, blockend, regno) \
> > > > (addr) = ppc_register_u_addr ((blockend),(regno));
> > >
> > > This in turn means that ppc_register_u_addr() can be made static
> > > and that the ``ustart'' parameter can be removed. All calls to
> > > register_addr() (in your new code) in ppc-linux-nat.c should be
> > > changed to invoke ppc_register_u_addr() directly.
> > >
> >
> > Unfortunately not. I thought the same, until I remembered about core
> > file debugging. That function is called by fetch_core_registers() in
> > core-aout.c.
>
> Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> core-regset.c instead?
>
Whoops, yes, you are right. False alarm.
Elena
> Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 15:03 ` Andrew Cagney
@ 2001-11-20 8:54 ` Andrew Cagney
2001-11-29 16:27 ` Kevin Buettner
1 sibling, 0 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-20 8:54 UTC (permalink / raw)
To: Elena Zannoni; +Cc: Kevin Buettner, Daniel Jacobowitz, gdb-patches
>> Unfortunately not. I thought the same, until I remembered about core
> > > file debugging. That function is called by fetch_core_registers() in
> > > core-aout.c.
> > > Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> > Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> > core-regset.c instead?
> > Whoops, yes, you are right. False alarm.
So just the core code needs to have a hard-wired (non native header) way
of unpacking Altivec registers (if they are found?)?
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 14:47 ` Daniel Jacobowitz
2001-11-20 8:37 ` Daniel Jacobowitz
@ 2001-11-20 9:07 ` Kevin Buettner
2001-11-20 9:08 ` Andrew Cagney
` (2 more replies)
2001-12-20 10:02 ` Elena Zannoni
2 siblings, 3 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-20 9:07 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Elena Zannoni, gdb-patches
On Nov 29, 5:46pm, Daniel Jacobowitz wrote:
> > Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> > Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> > core-regset.c instead?
>
> I'd like to kill our use of core-aout.c. Linux/PPC never used a.out
> cores, but unfortunately core-aout.c defines register_addr () as a
> wrapper for REGISTER_U_ADDR. The last time I tried to remove
> core-aout.c from a platform I got bitten.
>
> I think, now that we are defining FETCH_INFERIOR_REGISTERS, we can do
> without it - infptrace was the only big consumer I see remaining. So
> we might be OK without using core-aout.c at all now.
That's what I was hoping. Maybe Elena could try it out and let us know?
> My still-unsubmitted cross-core patches for PowerPC remove
> core-regset.o also, and very unpleasantly turn ppc-linux-nat.c into a
> target-dependant rather than native-dependant file, so that we can grub
> through the gregsets by hand. If you've got a better idea I'd love to
> hear it :) It will be made somewhat easier by the destruction of
> regmap[].
I haven't seen your patches, but I imagine you have a table of
constants or some such that represent offsets and sizes of members in
the regsets? (I.e, something similar to what I did for SVR4 shared
library offsets.) If that's the approach, then the only real problem I
have with it is accurately generating (and maintaining) the tables.
The SVR4 shared library tables are compact enough to easily generate
by hand. The regset data is quite a lot larger and I would think
you'd want to generate this data through more automatic means. (I.e,
via a program that you'd compile and and then run on the target.)
Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-20 9:07 ` Kevin Buettner
@ 2001-11-20 9:08 ` Andrew Cagney
2001-11-29 15:33 ` Andrew Cagney
2001-11-29 15:15 ` Kevin Buettner
2001-11-29 15:38 ` Daniel Jacobowitz
2 siblings, 1 reply; 63+ messages in thread
From: Andrew Cagney @ 2001-11-20 9:08 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Daniel Jacobowitz, Elena Zannoni, gdb-patches
>
> I haven't seen your patches, but I imagine you have a table of
> constants or some such that represent offsets and sizes of members in
> the regsets? (I.e, something similar to what I did for SVR4 shared
> library offsets.) If that's the approach, then the only real problem I
> have with it is accurately generating (and maintaining) the tables.
> The SVR4 shared library tables are compact enough to easily generate
> by hand. The regset data is quite a lot larger and I would think
> you'd want to generate this data through more automatic means. (I.e,
> via a program that you'd compile and and then run on the target.)
Isn't the situtation with core files identical to shlibs? If the layout
changed then an old GDB couldn't debug new core files and a new GDB
couldn't debug old core files. To avoid this, people do stuff like put
new register sets into new sections.
enjoy,
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 15:38 ` Daniel Jacobowitz
@ 2001-11-20 9:13 ` Daniel Jacobowitz
2001-11-20 10:09 ` Kevin Buettner
1 sibling, 0 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-20 9:13 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 04:12:29PM -0700, Kevin Buettner wrote:
> > My still-unsubmitted cross-core patches for PowerPC remove
> > core-regset.o also, and very unpleasantly turn ppc-linux-nat.c into a
> > target-dependant rather than native-dependant file, so that we can grub
> > through the gregsets by hand. If you've got a better idea I'd love to
> > hear it :) It will be made somewhat easier by the destruction of
> > regmap[].
>
> I haven't seen your patches, but I imagine you have a table of
> constants or some such that represent offsets and sizes of members in
> the regsets? (I.e, something similar to what I did for SVR4 shared
> library offsets.) If that's the approach, then the only real problem I
> have with it is accurately generating (and maintaining) the tables.
> The SVR4 shared library tables are compact enough to easily generate
> by hand. The regset data is quite a lot larger and I would think
> you'd want to generate this data through more automatic means. (I.e,
> via a program that you'd compile and and then run on the target.)
Nothing that abstracted. I copy the necessary type definitions and
constants from target headers; they are "relatively" guaranteed never
to change. It's a mess.
There's no point abstracting it any further, I think; the SVR4 code
needs to get at shared library offsets, but only supply_gregset needs
to get at the regsets and that is already target-specific.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 15:38 ` Daniel Jacobowitz
2001-11-20 9:13 ` Daniel Jacobowitz
@ 2001-11-20 10:09 ` Kevin Buettner
2001-11-29 15:47 ` Kevin Buettner
` (2 more replies)
1 sibling, 3 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-20 10:09 UTC (permalink / raw)
To: Daniel Jacobowitz, Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
On Nov 29, 6:37pm, Daniel Jacobowitz wrote:
> On Thu, Nov 29, 2001 at 04:12:29PM -0700, Kevin Buettner wrote:
> > > My still-unsubmitted cross-core patches for PowerPC remove
> > > core-regset.o also, and very unpleasantly turn ppc-linux-nat.c into a
> > > target-dependant rather than native-dependant file, so that we can grub
> > > through the gregsets by hand. If you've got a better idea I'd love to
> > > hear it :) It will be made somewhat easier by the destruction of
> > > regmap[].
> >
> > I haven't seen your patches, but I imagine you have a table of
> > constants or some such that represent offsets and sizes of members in
> > the regsets? (I.e, something similar to what I did for SVR4 shared
> > library offsets.) If that's the approach, then the only real problem I
> > have with it is accurately generating (and maintaining) the tables.
> > The SVR4 shared library tables are compact enough to easily generate
> > by hand. The regset data is quite a lot larger and I would think
> > you'd want to generate this data through more automatic means. (I.e,
> > via a program that you'd compile and and then run on the target.)
>
> Nothing that abstracted. I copy the necessary type definitions and
> constants from target headers; they are "relatively" guaranteed never
> to change. It's a mess.
How does the "cross" part of it work then? Won't the sizes of the
fundamental types, struct alignment, etc. change depending upon
which host you compile it on?
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 15:58 ` Andrew Cagney
@ 2001-11-20 10:59 ` Andrew Cagney
0 siblings, 0 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-20 10:59 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Daniel Jacobowitz, Elena Zannoni, gdb-patches
>> Nothing that abstracted. I copy the necessary type definitions and
>> constants from target headers; they are "relatively" guaranteed never
>> to change. It's a mess.
>
>
> How does the "cross" part of it work then? Won't the sizes of the
> fundamental types, struct alignment, etc. change depending upon
> which host you compile it on?
Um, isn't this exactly the same problem as for shared libraries? There
the target stuff is described/coded in a host independant way.
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 15:59 ` Daniel Jacobowitz
@ 2001-11-20 11:07 ` Daniel Jacobowitz
2001-11-29 16:17 ` Andrew Cagney
1 sibling, 0 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-20 11:07 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 04:45:27PM -0700, Kevin Buettner wrote:
> On Nov 29, 6:37pm, Daniel Jacobowitz wrote:
>
> > On Thu, Nov 29, 2001 at 04:12:29PM -0700, Kevin Buettner wrote:
> > > > My still-unsubmitted cross-core patches for PowerPC remove
> > > > core-regset.o also, and very unpleasantly turn ppc-linux-nat.c into a
> > > > target-dependant rather than native-dependant file, so that we can grub
> > > > through the gregsets by hand. If you've got a better idea I'd love to
> > > > hear it :) It will be made somewhat easier by the destruction of
> > > > regmap[].
> > >
> > > I haven't seen your patches, but I imagine you have a table of
> > > constants or some such that represent offsets and sizes of members in
> > > the regsets? (I.e, something similar to what I did for SVR4 shared
> > > library offsets.) If that's the approach, then the only real problem I
> > > have with it is accurately generating (and maintaining) the tables.
> > > The SVR4 shared library tables are compact enough to easily generate
> > > by hand. The regset data is quite a lot larger and I would think
> > > you'd want to generate this data through more automatic means. (I.e,
> > > via a program that you'd compile and and then run on the target.)
> >
> > Nothing that abstracted. I copy the necessary type definitions and
> > constants from target headers; they are "relatively" guaranteed never
> > to change. It's a mess.
>
> How does the "cross" part of it work then? Won't the sizes of the
> fundamental types, struct alignment, etc. change depending upon
> which host you compile it on?
How does it work? Badly.
The types look like this right now:
+typedef unsigned char elf_greg_t[4];
+typedef unsigned char elf_fpreg_t[8];
+typedef struct {
+ unsigned char u[16];
+} __attribute((aligned(16))) __uint128_t;
+/* Altivec registers */
+typedef __uint128_t elf_vrreg_t;
Barring the GCC extension to get __uint128_t aligned, which I don't
actually need for anything, I can do what I need to with these; I use
explicitly target alignment. No platform other than (IIRC) x86 is
broken enough to require the tdep to do computation on elf_greg_t's
while fetching them.
The current version also has a _ppc_pt_regs struct which contains only
unsigned longs; but the only thing it's doing there is providing struct
user, and the only thing that cares is the kernel_u_size function, and
the only reason that's there is because it was quicker at the time for
me to copy struct user than figure out the constant :)
Arrays of arrays of unsigned char have no alignment issues.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 16:17 ` Andrew Cagney
@ 2001-11-20 11:17 ` Andrew Cagney
2001-11-20 17:52 ` Daniel Jacobowitz
1 sibling, 0 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-20 11:17 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kevin Buettner, Elena Zannoni, gdb-patches
>> How does the "cross" part of it work then? Won't the sizes of the
>> fundamental types, struct alignment, etc. change depending upon
>> which host you compile it on?
>
>
> How does it work? Badly.
>
> The types look like this right now:
>
> +typedef unsigned char elf_greg_t[4];
> +typedef unsigned char elf_fpreg_t[8];
> +typedef struct {
> + unsigned char u[16];
> +} __attribute((aligned(16))) __uint128_t;
> +/* Altivec registers */
> +typedef __uint128_t elf_vrreg_t;
Hmm, Kevin did have good reason to be concerned. That is wrong.
Mechanisms similar to shlib et.al. should be used.
BTW, where did this buffer layout come from?
Andrew
> Barring the GCC extension to get __uint128_t aligned, which I don't
> actually need for anything, I can do what I need to with these; I use
> explicitly target alignment. No platform other than (IIRC) x86 is
> broken enough to require the tdep to do computation on elf_greg_t's
> while fetching them.
>
> The current version also has a _ppc_pt_regs struct which contains only
> unsigned longs; but the only thing it's doing there is providing struct
> user, and the only thing that cares is the kernel_u_size function, and
> the only reason that's there is because it was quicker at the time for
> me to copy struct user than figure out the constant :)
>
> Arrays of arrays of unsigned char have no alignment issues.
>
>
>
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 16:27 ` Kevin Buettner
@ 2001-11-20 16:00 ` Kevin Buettner
2001-11-20 16:14 ` Andrew Cagney
2001-11-29 16:36 ` Elena Zannoni
2 siblings, 0 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-20 16:00 UTC (permalink / raw)
To: Andrew Cagney, Elena Zannoni
Cc: Kevin Buettner, Daniel Jacobowitz, gdb-patches
On Nov 29, 6:03pm, Andrew Cagney wrote:
> >> Unfortunately not. I thought the same, until I remembered about core
> > > > file debugging. That function is called by fetch_core_registers() in
> > > > core-aout.c.
> > > > Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> > > Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> > > core-regset.c instead?
> > > Whoops, yes, you are right. False alarm.
>
> So just the core code needs to have a hard-wired (non native header) way
> of unpacking Altivec registers (if they are found?)?
I'm guessing we'll end up having to add fetch_core_registers() and
company to ppc-linux-nat.c. That way neither core-regset.c nor
core-aout.c will be used for a native Linux/PPC build. (See
fetch_core_registers() in i386-linux-nat.c as an example.)
Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 16:36 ` Elena Zannoni
@ 2001-11-20 16:10 ` Elena Zannoni
2001-11-29 17:40 ` Daniel Jacobowitz
1 sibling, 0 replies; 63+ messages in thread
From: Elena Zannoni @ 2001-11-20 16:10 UTC (permalink / raw)
To: Kevin Buettner
Cc: Andrew Cagney, Elena Zannoni, Daniel Jacobowitz, gdb-patches
Kevin Buettner writes:
> On Nov 29, 6:03pm, Andrew Cagney wrote:
>
> > >> Unfortunately not. I thought the same, until I remembered about core
> > > > > file debugging. That function is called by fetch_core_registers() in
> > > > > core-aout.c.
> > > > > Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> > > > Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> > > > core-regset.c instead?
> > > > Whoops, yes, you are right. False alarm.
> >
> > So just the core code needs to have a hard-wired (non native header) way
> > of unpacking Altivec registers (if they are found?)?
>
> I'm guessing we'll end up having to add fetch_core_registers() and
> company to ppc-linux-nat.c. That way neither core-regset.c nor
> core-aout.c will be used for a native Linux/PPC build. (See
> fetch_core_registers() in i386-linux-nat.c as an example.)
cross core file support: is that a concern?
Side bar: there is something interesting about the way the corelow.c
file gets the registers sections from a core file. It looks for .reg
(gregs), .reg2 (fpregs), and .reg-xfp (extended-floating point x86
only(?)). Seems like I'll have to add a fetch section call for a
.reg-altivec (or whatever it will be called, it's not produced
yet). But that's in common code. I don't like it. This
get_core_registers() will have to be overwritten too, maybe.
Elena
>
> Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 16:27 ` Kevin Buettner
2001-11-20 16:00 ` Kevin Buettner
@ 2001-11-20 16:14 ` Andrew Cagney
2001-11-21 3:33 ` Daniel Jacobowitz
2001-11-29 16:43 ` Andrew Cagney
2001-11-29 16:36 ` Elena Zannoni
2 siblings, 2 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-20 16:14 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, Daniel Jacobowitz, gdb-patches
>> So just the core code needs to have a hard-wired (non native header) way
>> of unpacking Altivec registers (if they are found?)?
>
>
> I'm guessing we'll end up having to add fetch_core_registers() and
> company to ppc-linux-nat.c. That way neither core-regset.c nor
> core-aout.c will be used for a native Linux/PPC build. (See
> fetch_core_registers() in i386-linux-nat.c as an example.)
No. The core stuff would need to be kicked out of *-nat.c and into
*-core.c and/or *-greg.c and/or ??? The packing/unpacking of a reg-set
is technically only target dependant - debugging a core file from an
embedded target.
Daniel, how are the changes you were eluding to comming along?
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 16:17 ` Andrew Cagney
2001-11-20 11:17 ` Andrew Cagney
@ 2001-11-20 17:52 ` Daniel Jacobowitz
2001-11-29 17:39 ` Daniel Jacobowitz
2001-11-29 18:20 ` Andrew Cagney
1 sibling, 2 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-20 17:52 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 07:17:56PM -0500, Andrew Cagney wrote:
> >>How does the "cross" part of it work then? Won't the sizes of the
> >>fundamental types, struct alignment, etc. change depending upon
> >>which host you compile it on?
> >
> >
> >How does it work? Badly.
> >
> >The types look like this right now:
> >
> >+typedef unsigned char elf_greg_t[4];
> >+typedef unsigned char elf_fpreg_t[8];
> >+typedef struct {
> >+ unsigned char u[16];
> >+} __attribute((aligned(16))) __uint128_t;
> >+/* Altivec registers */
> >+typedef __uint128_t elf_vrreg_t;
>
> Hmm, Kevin did have good reason to be concerned. That is wrong.
> Mechanisms similar to shlib et.al. should be used.
What is wrong with it?
I agree that it is messy, but it is completely correct. I know of no
platform with 8-bit bytes stupid enough to do this any way other than
the way I intend.
> BTW, where did this buffer layout come from?
Eh? It's the layout of a ppc/linux elf_gregset_t.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 17:40 ` Daniel Jacobowitz
@ 2001-11-20 18:00 ` Daniel Jacobowitz
0 siblings, 0 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-20 18:00 UTC (permalink / raw)
To: Elena Zannoni; +Cc: Kevin Buettner, Andrew Cagney, gdb-patches
On Thu, Nov 29, 2001 at 07:42:51PM -0500, Elena Zannoni wrote:
> Kevin Buettner writes:
> > On Nov 29, 6:03pm, Andrew Cagney wrote:
> >
> > > >> Unfortunately not. I thought the same, until I remembered about core
> > > > > > file debugging. That function is called by fetch_core_registers() in
> > > > > > core-aout.c.
> > > > > > Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> > > > > Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> > > > > core-regset.c instead?
> > > > > Whoops, yes, you are right. False alarm.
> > >
> > > So just the core code needs to have a hard-wired (non native header) way
> > > of unpacking Altivec registers (if they are found?)?
> >
> > I'm guessing we'll end up having to add fetch_core_registers() and
> > company to ppc-linux-nat.c. That way neither core-regset.c nor
> > core-aout.c will be used for a native Linux/PPC build. (See
> > fetch_core_registers() in i386-linux-nat.c as an example.)
>
> cross core file support: is that a concern?
For me, at least, it is. I should take this as motivation and finish
the cross core patches. I'm a little behind on them.
> Side bar: there is something interesting about the way the corelow.c
> file gets the registers sections from a core file. It looks for .reg
> (gregs), .reg2 (fpregs), and .reg-xfp (extended-floating point x86
> only(?)). Seems like I'll have to add a fetch section call for a
> .reg-altivec (or whatever it will be called, it's not produced
> yet). But that's in common code. I don't like it. This
> get_core_registers() will have to be overwritten too, maybe.
I'd rather make it support fetching arbitrary sections. I have the
design for this in mind already; I'll get back to you on it as soon as
I can (probably next week).
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-20 16:14 ` Andrew Cagney
@ 2001-11-21 3:33 ` Daniel Jacobowitz
2001-11-29 17:41 ` Daniel Jacobowitz
2001-11-29 16:43 ` Andrew Cagney
1 sibling, 1 reply; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-21 3:33 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 07:43:56PM -0500, Andrew Cagney wrote:
> >>So just the core code needs to have a hard-wired (non native header) way
> >>of unpacking Altivec registers (if they are found?)?
> >
> >
> >I'm guessing we'll end up having to add fetch_core_registers() and
> >company to ppc-linux-nat.c. That way neither core-regset.c nor
> >core-aout.c will be used for a native Linux/PPC build. (See
> >fetch_core_registers() in i386-linux-nat.c as an example.)
>
> No. The core stuff would need to be kicked out of *-nat.c and into
> *-core.c and/or *-greg.c and/or ??? The packing/unpacking of a reg-set
> is technically only target dependant - debugging a core file from an
> embedded target.
>
> Daniel, how are the changes you were eluding to comming along?
Back burner to C++. When I have polished off the v3 ABI stuff I'll be
back to this thread.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 18:20 ` Andrew Cagney
@ 2001-11-21 4:10 ` Andrew Cagney
2001-11-29 22:36 ` Daniel Jacobowitz
1 sibling, 0 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-21 4:10 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kevin Buettner, Elena Zannoni, gdb-patches
>> >
>> >
>> >How does it work? Badly.
>> >
>> >The types look like this right now:
>> >
>> >+typedef unsigned char elf_greg_t[4];
>> >+typedef unsigned char elf_fpreg_t[8];
>> >+typedef struct {
>> >+ unsigned char u[16];
>> >+} __attribute((aligned(16))) __uint128_t;
>> >+/* Altivec registers */
>> >+typedef __uint128_t elf_vrreg_t;
>
>>
>> Hmm, Kevin did have good reason to be concerned. That is wrong.
>> Mechanisms similar to shlib et.al. should be used.
>
>
> What is wrong with it?
>
> I agree that it is messy, but it is completely correct. I know of no
> platform with 8-bit bytes stupid enough to do this any way other than
> the way I intend.
Several things come to mind: the __attribute() - there are alignment
independant functions for packing/unpacking/copying stuff; the
__unint128_t is is a name in system space.
The shlib code does this by describing the actual layout using a very
thin interface (like how remote.c unpacks the g-packet) so host issues
aren't a problem (but yes, it would be a suprise to find one that didn't
have 8 bit chars).
The other way of doing this is more like C++ where it creates a ``struct
type'' to describe the structure exactly how the target sees it.
enjoy,
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 22:36 ` Daniel Jacobowitz
@ 2001-11-21 5:56 ` Daniel Jacobowitz
0 siblings, 0 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-21 5:56 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 09:20:52PM -0500, Andrew Cagney wrote:
> >>>
> >>>
> >>>How does it work? Badly.
> >>>
> >>>The types look like this right now:
> >>>
> >>>+typedef unsigned char elf_greg_t[4];
> >>>+typedef unsigned char elf_fpreg_t[8];
> >>>+typedef struct {
> >>>+ unsigned char u[16];
> >>>+} __attribute((aligned(16))) __uint128_t;
> >>>+/* Altivec registers */
> >>>+typedef __uint128_t elf_vrreg_t;
> >
> >>
> >>Hmm, Kevin did have good reason to be concerned. That is wrong.
> >>Mechanisms similar to shlib et.al. should be used.
> >
> >
> >What is wrong with it?
> >
> >I agree that it is messy, but it is completely correct. I know of no
> >platform with 8-bit bytes stupid enough to do this any way other than
> >the way I intend.
>
> Several things come to mind: the __attribute() - there are alignment
> independant functions for packing/unpacking/copying stuff; the
> __unint128_t is is a name in system space.
>
> The shlib code does this by describing the actual layout using a very
> thin interface (like how remote.c unpacks the g-packet) so host issues
> aren't a problem (but yes, it would be a suprise to find one that didn't
> have 8 bit chars).
>
> The other way of doing this is more like C++ where it creates a ``struct
> type'' to describe the structure exactly how the target sees it.
The __attribute__ and __uint128_t are both, as I said further down the
message, are both unused :) The remainder of it is fine, AFAICT.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* [RFA] W.I.P. AltiVec ppc registers support.
@ 2001-11-28 18:09 Elena Zannoni
2001-11-18 13:27 ` Elena Zannoni
` (3 more replies)
0 siblings, 4 replies; 63+ messages in thread
From: Elena Zannoni @ 2001-11-28 18:09 UTC (permalink / raw)
To: gdb-patches
AltiVec registers are 32 128-bit wide registers found on the G4
powerpc processor family. This patch adds some initial support for
such registers to gdb on a linux ppc platform.
The Altivec registers are not displayed in a normal 'info reg' command
output. They are shown (like fp regs) if one says 'info all' instead.
Furthermore I added a specific 'info power altivec' command to display
just the Altivec registers. (I am not sure that the word 'power' is
the best choice, maybe simply 'ppc' or 'powerpc' is better). This way
the command as just a specific powerpc info command, w/o it being a
generic info command avaliable on every platform.
If there is no kernel support for ptrace to handle the AltiVec
registers, they will display as 0's.
The little drawback is that such registers will be displayed any time
gdb's architecture is 'powerpc:common' or 'powerpc:7400'. The first
case is the architecture gdb defaults to when run on a ppc machine,
because the multiarch mechanism cannot determine the nature of the
executable file. To be clearer, there is no way for gdb to know that
the architecture is meant to be a ppc7400 based on executable
information provided by BFD (unlike for Mips and Sh). So, gdb will
always start and *stay* with a powerpc:common architecture selected,
unless the user explicitly sets the architecture to be
'powerpc:7400'. This impossibility to auto detect the architecture is
what prompted me to have Altivec defined anyway for the default
arch. [Hopefully this deficiency will be rectified soon].
The patch below includes the patch previously submitted:
http://sources.redhat.com/ml/gdb-patches/2001-11/msg00447.html
The first Changelog is just for the most recent change set. I included
the older one for easy reference. I would like to commit these in 2
separate passes, the same way they were submitted.
I tested this on AIX4.3, on a Linux-ppc with Altivec kernel support,
and on a Linux-ppx w/o Altivec kernel support.
Elena
2001-11-28 Elena Zannoni <ezannoni@redhat.com>
* Makefile.in (rs6000-tdep.o): Add dependency on parser-defs.h.
* config/powerpc/nm-linux.h (FETCH_INFERIOR_REGISTERS): Define.
* rs6000-tdep.c: Include parser-defs.h.
(struct gdbarch_tdep): Moved from here to ppc-tdep.h.
(rs6000_register_virtual_type): Rewrite, including hangling of
AltiVec regs type.
(altivec_register_p): New function.
(rs6000_do_altivec_registers): New function.
(rs6000_altivec_registers_info): New function.
(rs6000_do_registers_info): New function.
(R16): Define.
(PPC_ALTIVEC_REGS): Define.
(registers_powerpc): Add AltiVec registers.
(registers_7400): Define.
(variants): Add 7400 machine.
(rs6000_gdbarch_init): Set the numbers of AltiVec registers.
Initialize gdbarch_do)_registers_info.
(rs6000_info_power_command): New function.
(info_power_cmdlist): New static variable.
(_initialize_rs6000_tdep): Add new 'info power altivec' command.
* rs6000-nat.c (fetch_register): Don't error out unless the
register number is really bogus.
* ppc-tdep.h (struct gdbarch_tdep): Moved here from rs6000-tdep.c.
Add altivec regnum fields.
(altivec_register_p): Export.
* ppc-linux-nat.c (ppc_ptrace_cannot_fetch_store_register): New
function.
(ppc_register_u_addr): Add handling of AltiVec registers.
(fetch_register): New function.
(fetch_altivec_register): New function.
(fetch_ppc_registers): New function.
(fetch_altivec_registers): New function.
(fetch_inferior_registers): New function.
(store_register): New function.
(store_altivec_register): New function.
(store_ppc_registers): New function.
(store_altivec_registers): New function.
(store_inferior_registers): New function.
[PREVIOUS CHANGELOG]
2001-11-26 Elena Zannoni <ezannoni@redhat.com>
* Makefile.in (ppc-linux-nat.o): Add dependency on ppc-tdep.h.
* ppc-tdep.h (PPC_GPLAST_REGNUM): Define.
* ppc-linux-nat.c: Include ppc-tdep.h.
(ppc_register_u_addr): Don't use the static array regmap[],
dynamically define the mapping instead.
(supply_gregset): Ditto.
(fill_gregset): Ditto.
(COPY_REG): Delete macro defintion.
(regmap): Delete array.
Index: Makefile.in
===================================================================
RCS file: /cvs/uberbaum/gdb/Makefile.in,v
retrieving revision 1.130
diff -u -p -r1.130 Makefile.in
--- Makefile.in 2001/11/18 05:09:26 1.130
+++ Makefile.in 2001/11/28 23:26:05
@@ -1818,7 +1818,7 @@ ppc-bdm.o: ppc-bdm.c $(defs_h) $(gdbcore
$(objfiles_h) $(gdb_stabs_h) $(serial_h) ocd.h $(regcache_h)
ppc-linux-nat.o: ppc-linux-nat.c $(defs_h) $(gdbcore_h) $(frame_h) \
- $(inferior_h) $(target_h) $(regcache_h)
+ $(inferior_h) $(target_h) $(regcache_h) ppc-tdep.h
ppc-linux-tdep.o: ppc-linux-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
$(target_h) ppc-tdep.h $(regcache_h) $(value_h)
@@ -1972,7 +1972,7 @@ rs6000-nat.o: rs6000-nat.c $(bfd_h) $(de
$(gdb_stabs_h) $(regcache_h)
rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
- $(target_h) ppc-tdep.h $(regcache_h) $(value_h)
+ $(target_h) ppc-tdep.h $(regcache_h) $(value_h) $(parser_defs_h)
s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \
$(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) \
Index: ppc-linux-nat.c
===================================================================
RCS file: /cvs/uberbaum/gdb/ppc-linux-nat.c,v
retrieving revision 1.10
diff -u -p -r1.10 ppc-linux-nat.c
--- ppc-linux-nat.c 2001/11/20 16:35:24 1.10
+++ ppc-linux-nat.c 2001/11/28 23:26:16
@@ -32,34 +32,341 @@
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/procfs.h>
+#include <sys/ptrace.h>
/* Prototypes for supply_gregset etc. */
#include "gregset.h"
+#include "ppc-tdep.h"
+#ifndef PT_READ_U
+#define PT_READ_U PTRACE_PEEKUSR
+#endif
+#ifndef PT_WRITE_U
+#define PT_WRITE_U PTRACE_POKEUSR
+#endif
+
+/* Default the type of the ptrace transfer to int. */
+#ifndef PTRACE_XFER_TYPE
+#define PTRACE_XFER_TYPE int
+#endif
+
+/* AltiVec regs are not always supported by the kernel. We need to fake them,
+ and let the ptrace requests fail. */
+#ifndef PT_VR0
+#define PT_VR0 (PT_FPSCR + 1)
+#endif
+#ifndef PT_VR31
+#define PT_VR31 (PT_VR0 + 4*31)
+#endif
+#ifndef PT_VRCR
+#define PT_VRCR (PT_VR0 + 4*32)
+#endif
+#ifndef PT_VRSAVE
+#define PT_VRSAVE (PT_VR0 + 4*33)
+#endif
+
int
kernel_u_size (void)
{
return (sizeof (struct user));
}
-static int regmap[] =
-{PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
- PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
- PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
- PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
- PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
- PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
- PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
- PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
- PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ};
+/* *INDENT-OFF* */
+/* registers layout, as presented by the ptrace interface:
+PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
+PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
+PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
+PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
+PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
+PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
+PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
+PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
+PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ */
+/* *INDENT_ON * */
int
-ppc_register_u_addr (int ustart, int regnum)
+ppc_register_u_addr (int ustart, int regno)
+{
+ int u_addr = -1;
+
+ /* General purpose registers occupy 1 slot each in the buffer */
+ if (regno >= PPC_GP0_REGNUM && regno <= PPC_GPLAST_REGNUM )
+ u_addr = (ustart + (PT_R0 + regno) * 4);
+
+ /* Floating point regs: 2 slots each */
+ if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM)
+ u_addr = (ustart + (PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4);
+
+ /* Altivec registers: 4 slots each. */
+ if (altivec_register_p (regno))
+ u_addr = (ustart + (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4);
+
+ /* UISA special purpose registers: 1 slot each */
+ if (regno == PC_REGNUM)
+ u_addr = ustart + PT_NIP * 4;
+ if (regno == PPC_LR_REGNUM)
+ u_addr = ustart + PT_LNK * 4;
+ if (regno == PPC_CR_REGNUM)
+ u_addr = ustart + PT_CCR * 4;
+ if (regno == PPC_XER_REGNUM)
+ u_addr = ustart + PT_XER * 4;
+ if (regno == PPC_CTR_REGNUM)
+ u_addr = ustart + PT_CTR * 4;
+ if (regno == PPC_MQ_REGNUM)
+ u_addr = ustart + PT_MQ * 4;
+ if (regno == PPC_PS_REGNUM)
+ u_addr = ustart + PT_MSR * 4;
+
+ return u_addr;
+}
+
+static int
+ppc_ptrace_cannot_fetch_store_register (int regno)
+{
+ return (ppc_register_u_addr (0, regno) == -1);
+}
+
+static void
+fetch_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ unsigned int offset; /* Offset of registers within the u area. */
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int tid;
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ {
+ memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ if (regaddr < 0)
+ return;
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ sprintf (mess, "reading register %s (#%d)",
+ REGISTER_NAME (regno), regno);
+ perror_with_name (mess);
+ }
+ }
+ supply_register (regno, buf);
+}
+
+static void
+fetch_altivec_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ int i;
+ unsigned int offset; /* Offset of registers within the u area. */
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int tid;
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ {
+ memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+ }
+ supply_register (regno, buf);
+}
+
+static void
+fetch_ppc_registers (void)
+{
+ int last_register;
+ int i;
+
+ last_register = PPC_MQ_REGNUM;
+ for (i = 0; i <= last_register; i++)
+ fetch_register (i);
+}
+
+static void
+fetch_altivec_registers (void)
+{
+ int i;
+
+ for (i = 0;
+ i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
+ - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
+ i++)
+ fetch_altivec_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
+}
+
+/* Fetch registers from the child process. Fetch all registers if
+ regno == -1, otherwise fetch all general registers or all floating
+ point registers depending upon the value of regno. */
+
+void
+fetch_inferior_registers (int regno)
+{
+ if (regno == -1)
+ {
+ fetch_ppc_registers ();
+ fetch_altivec_registers ();
+ }
+ else
+ {
+ if (altivec_register_p (regno))
+ fetch_altivec_register (regno);
+ else
+ fetch_register (regno);
+ }
+}
+
+/* Store one register. */
+static void
+store_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ unsigned int offset; /* Offset of registers within the u area. */
+ int tid;
+ char *buf = alloca (MAX_REGISTER_RAW_SIZE);
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ {
+ return;
+ }
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ regcache_collect (regno, buf);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
+ *(PTRACE_XFER_TYPE *) & buf[i]);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ sprintf (mess, "writing register %s (#%d)",
+ REGISTER_NAME (regno), regno);
+ perror_with_name (mess);
+ }
+ }
+}
+
+static void
+store_altivec_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ unsigned int offset; /* Offset of registers within the u area. */
+ int tid;
+ char *buf = alloca (MAX_REGISTER_RAW_SIZE);
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ return;
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ regcache_collect (regno, buf);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
+ *(PTRACE_XFER_TYPE *) & buf[i]);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ return;
+ }
+}
+
+static void
+store_ppc_registers (void)
+{
+ int last_register;
+ int i;
+
+ last_register = PPC_MQ_REGNUM;
+ for (i = 0; i <= last_register; i++)
+ store_register (i);
+}
+
+static void
+store_altivec_registers (void)
{
- return (ustart + 4 * regmap[regnum]);
+ int i;
+
+ for (i = 0;
+ i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
+ - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
+ i++)
+ store_altivec_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
}
void
+store_inferior_registers (int regno)
+{
+ if (regno >= 0)
+ {
+ if (altivec_register_p (regno))
+ store_altivec_register (regno);
+ else
+ store_register (regno);
+ }
+ else
+ {
+ store_ppc_registers ();
+ store_altivec_registers ();
+ }
+}
+
+void
supply_gregset (gdb_gregset_t *gregsetp)
{
int regi;
@@ -68,8 +375,13 @@ supply_gregset (gdb_gregset_t *gregsetp)
for (regi = 0; regi < 32; regi++)
supply_register (regi, (char *) (regp + regi));
- for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
- supply_register (regi, (char *) (regp + regmap[regi]));
+ supply_register (PC_REGNUM, (char *) (regp + PT_NIP));
+ supply_register (PPC_LR_REGNUM, (char *) (regp + PT_LNK));
+ supply_register (PPC_CR_REGNUM, (char *) (regp + PT_CCR));
+ supply_register (PPC_XER_REGNUM, (char *) (regp + PT_XER));
+ supply_register (PPC_CTR_REGNUM, (char *) (regp + PT_CTR));
+ supply_register (PPC_MQ_REGNUM, (char *) (regp + PT_MQ));
+ supply_register (PPC_PS_REGNUM, (char *) (regp + PT_MSR));
}
void
@@ -78,19 +390,26 @@ fill_gregset (gdb_gregset_t *gregsetp, i
int regi;
elf_greg_t *regp = (elf_greg_t *) gregsetp;
-#define COPY_REG(_idx_,_regi_) \
- if ((regno == -1) || regno == _regi_) \
- regcache_collect (_regi_, regp + _idx_)
-
for (regi = 0; regi < 32; regi++)
{
- COPY_REG (regmap[regi], regi);
+ if ((regno == -1) || regno == regi)
+ regcache_collect (regi, regp + PT_R0 + regi);
}
- for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
- {
- COPY_REG (regmap[regi], regi);
- }
+ if ((regno == -1) || regno == PC_REGNUM)
+ regcache_collect (PC_REGNUM, regp + PT_NIP);
+ if ((regno == -1) || regno == PPC_LR_REGNUM)
+ regcache_collect (PPC_LR_REGNUM, regp + PT_LNK);
+ if ((regno == -1) || regno == PPC_CR_REGNUM)
+ regcache_collect (PPC_CR_REGNUM, regp + PT_CCR);
+ if ((regno == -1) || regno == PPC_XER_REGNUM)
+ regcache_collect (PPC_XER_REGNUM, regp + PT_XER);
+ if ((regno == -1) || regno == PPC_CTR_REGNUM)
+ regcache_collect (PPC_CTR_REGNUM, regp + PT_CTR);
+ if ((regno == -1) || regno == PPC_MQ_REGNUM)
+ regcache_collect (PPC_MQ_REGNUM, regp + PT_MQ);
+ if ((regno == -1) || regno == PPC_PS_REGNUM)
+ regcache_collect (PPC_PS_REGNUM, regp + PT_MSR);
}
void
Index: ppc-tdep.h
===================================================================
RCS file: /cvs/uberbaum/gdb/ppc-tdep.h,v
retrieving revision 1.2
diff -u -p -r1.2 ppc-tdep.h
--- ppc-tdep.h 2001/11/01 01:07:35 1.2
+++ ppc-tdep.h 2001/11/29 00:18:11
@@ -42,10 +42,24 @@ void rs6000_init_extra_frame_info (int f
int rs6000_frameless_function_invocation (struct frame_info *);
void rs6000_frame_init_saved_regs (struct frame_info *);
CORE_ADDR rs6000_frame_chain (struct frame_info *);
+int altivec_register_p (int regno);
+/* Private data that this module attaches to struct gdbarch. */
+
+struct gdbarch_tdep
+ {
+ int wordsize; /* size in bytes of fixed-point word */
+ int osabi; /* OS / ABI from ELF header */
+ int *regoff; /* byte offsets in register arrays */
+ const struct reg *regs; /* from current variant */
+ int first_altivec_regnum;
+ int last_altivec_regnum;
+ };
+
/* Some important register numbers. */
#define PPC_GP0_REGNUM 0 /* GPR register 0 */
+#define PPC_GPLAST_REGNUM 31 /* GPR register 31 */
#define PPC_TOC_REGNUM 2 /* TOC register */
#define PPC_PS_REGNUM 65 /* Processor (or machine) status (%msr) */
#define PPC_CR_REGNUM 66 /* Condition register */
Index: rs6000-nat.c
===================================================================
RCS file: /cvs/uberbaum/gdb/rs6000-nat.c,v
retrieving revision 1.17
diff -u -p -r1.17 rs6000-nat.c
--- rs6000-nat.c 2001/05/04 04:15:27 1.17
+++ rs6000-nat.c 2001/11/28 23:26:17
@@ -206,9 +206,12 @@ fetch_register (int regno)
/* Bogus register number. */
else if (regno > LAST_UISA_SP_REGNUM)
- fprintf_unfiltered (gdb_stderr,
- "gdb error: register no %d not implemented.\n",
- regno);
+ {
+ if (regno >= NUM_REGS)
+ fprintf_unfiltered (gdb_stderr,
+ "gdb error: register no %d not implemented.\n",
+ regno);
+ }
/* Fixed-point registers. */
else
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/uberbaum/gdb/rs6000-tdep.c,v
retrieving revision 1.28
diff -u -p -r1.28 rs6000-tdep.c
--- rs6000-tdep.c 2001/10/21 17:19:37 1.28
+++ rs6000-tdep.c 2001/11/28 23:26:19
@@ -33,6 +33,7 @@
#include "regcache.h"
#include "doublest.h"
#include "value.h"
+#include "parser-defs.h"
#include "bfd/libbfd.h" /* for bfd_default_set_arch_mach */
#include "coff/internal.h" /* for libcoff.h */
@@ -81,16 +82,6 @@ struct reg
unsigned char fpr; /* whether register is floating-point */
};
-/* Private data that this module attaches to struct gdbarch. */
-
-struct gdbarch_tdep
- {
- int wordsize; /* size in bytes of fixed-point word */
- int osabi; /* OS / ABI from ELF header */
- int *regoff; /* byte offsets in register arrays */
- const struct reg *regs; /* from current variant */
- };
-
/* Return the current architecture's gdbarch_tdep structure. */
#define TDEP gdbarch_tdep (current_gdbarch)
@@ -1552,9 +1543,24 @@ rs6000_register_virtual_type (int n)
struct gdbarch_tdep *tdep = TDEP;
const struct reg *reg = tdep->regs + n;
- return reg->fpr ? builtin_type_double :
- regsize (reg, tdep->wordsize) == 8 ? builtin_type_int64 :
- builtin_type_int32;
+ if (reg->fpr)
+ return builtin_type_double;
+ else
+ {
+ int size = regsize (reg, tdep->wordsize);
+ switch (size)
+ {
+ case 8:
+ return builtin_type_int64;
+ break;
+ case 16:
+ return builtin_type_int128;
+ break;
+ default:
+ return builtin_type_int32;
+ break;
+ }
+ }
}
/* For the PowerPC, it appears that the debug info marks float parameters as
@@ -1613,6 +1619,192 @@ rs6000_register_convert_to_raw (struct t
memcpy (to, from, REGISTER_RAW_SIZE (n));
}
+int
+altivec_register_p (int regno)
+{
+ if (gdbarch_tdep (current_gdbarch)->first_altivec_regnum < 0
+ || gdbarch_tdep (current_gdbarch)->last_altivec_regnum < 0)
+ return 0;
+ else
+ return (regno >= gdbarch_tdep (current_gdbarch)->first_altivec_regnum
+ && regno <= gdbarch_tdep (current_gdbarch)->last_altivec_regnum);
+}
+
+static void
+rs6000_do_altivec_registers (int regnum)
+{
+ int i;
+ char *raw_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE);
+ char *virtual_buffer = (char*) alloca (MAX_REGISTER_VIRTUAL_SIZE);
+
+ for (i = gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
+ i <= gdbarch_tdep (current_gdbarch)->last_altivec_regnum; i++)
+ {
+ /* If we want just one reg, check that this is the one we want. */
+ if (regnum != -1 && i != regnum)
+ continue;
+
+ /* If the register name is empty, it is undefined for this
+ processor, so don't display anything. */
+ if (REGISTER_NAME (i) == NULL || *(REGISTER_NAME (i)) == '\0')
+ continue;
+
+ fputs_filtered (REGISTER_NAME (i), gdb_stdout);
+ print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), gdb_stdout);
+
+ /* Get the data in raw format. */
+ if (read_relative_register_raw_bytes (i, raw_buffer))
+ {
+ printf_filtered ("*value not available*\n");
+ continue;
+ }
+
+ /* Convert raw data to virtual format if necessary. */
+ if (REGISTER_CONVERTIBLE (i))
+ REGISTER_CONVERT_TO_VIRTUAL (i, REGISTER_VIRTUAL_TYPE (i),
+ raw_buffer, virtual_buffer);
+ else
+ memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (i));
+
+ /* Print as integer in hex only. */
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 'x', 1, 0, Val_pretty_default);
+ printf_filtered ("\n");
+ }
+}
+
+static void
+rs6000_altivec_registers_info (char *addr_exp, int from_tty)
+{
+ int regnum, numregs;
+ register char *end;
+
+ if (!target_has_registers)
+ error ("The program has no registers now.");
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+
+ if (!addr_exp)
+ {
+ rs6000_do_altivec_registers (-1);
+ return;
+ }
+
+ numregs = NUM_REGS + NUM_PSEUDO_REGS;
+ do
+ {
+ if (addr_exp[0] == '$')
+ addr_exp++;
+ end = addr_exp;
+ while (*end != '\0' && *end != ' ' && *end != '\t')
+ ++end;
+
+ regnum = target_map_name_to_register (addr_exp, end - addr_exp);
+ if (regnum < 0)
+ {
+ regnum = numregs;
+ if (*addr_exp >= '0' && *addr_exp <= '9')
+ regnum = atoi (addr_exp); /* Take a number */
+ if (regnum >= numregs) /* Bad name, or bad number */
+ error ("%.*s: invalid register", end - addr_exp, addr_exp);
+ }
+
+ rs6000_do_altivec_registers (regnum);
+
+ addr_exp = end;
+ while (*addr_exp == ' ' || *addr_exp == '\t')
+ ++addr_exp;
+ }
+ while (*addr_exp != '\0');
+}
+
+static void
+rs6000_do_registers_info (int regnum, int fpregs)
+{
+ register int i;
+ int numregs = NUM_REGS + NUM_PSEUDO_REGS;
+ char *raw_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE);
+ char *virtual_buffer = (char*) alloca (MAX_REGISTER_VIRTUAL_SIZE);
+
+ for (i = 0; i < numregs; i++)
+ {
+ /* Decide between printing all regs, nonfloat regs, or specific reg. */
+ if (regnum == -1)
+ {
+ if ((TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT && !fpregs)
+ || (altivec_register_p (i) && !fpregs))
+ continue;
+ }
+ else
+ {
+ if (i != regnum)
+ continue;
+ }
+
+ /* If the register name is empty, it is undefined for this
+ processor, so don't display anything. */
+ if (REGISTER_NAME (i) == NULL || *(REGISTER_NAME (i)) == '\0')
+ continue;
+
+ fputs_filtered (REGISTER_NAME (i), gdb_stdout);
+ print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), gdb_stdout);
+
+ /* Get the data in raw format. */
+ if (read_relative_register_raw_bytes (i, raw_buffer))
+ {
+ printf_filtered ("*value not available*\n");
+ continue;
+ }
+
+ /* Convert raw data to virtual format if necessary. */
+ if (REGISTER_CONVERTIBLE (i))
+ REGISTER_CONVERT_TO_VIRTUAL (i, REGISTER_VIRTUAL_TYPE (i),
+ raw_buffer, virtual_buffer);
+ else
+ memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (i));
+
+ /* If virtual format is floating, print it that way, and in raw hex. */
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT)
+ {
+ register int j;
+
+#ifdef INVALID_FLOAT
+ if (INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
+ printf_filtered ("<invalid float>");
+ else
+#endif
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
+
+ printf_filtered ("\t(raw 0x");
+ for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
+ {
+ register int idx = TARGET_BYTE_ORDER == BIG_ENDIAN ? j
+ : REGISTER_RAW_SIZE (i) - 1 - j;
+ printf_filtered ("%02x", (unsigned char) raw_buffer[idx]);
+ }
+ printf_filtered (")");
+ }
+ else
+ {
+ /* Print as integer in hex and in decimal. */
+ if (!altivec_register_p (i))
+ {
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 'x', 1, 0, Val_pretty_default);
+ printf_filtered ("\t");
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
+ }
+ else
+ /* Print as integer in hex only. */
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 'x', 1, 0, Val_pretty_default);
+ }
+ printf_filtered ("\n");
+ }
+}
+
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function.
@@ -1752,6 +1944,10 @@ rs6000_convert_from_func_ptr_addr (CORE_
systems. */
#define R8(name) { STR(name), 8, 8, 0 }
+/* Return a struct reg defining register NAME that's 128 bits on all
+ systems. */
+#define R16(name) { STR(name), 16, 16, 0 }
+
/* Return a struct reg defining floating-point register NAME. */
#define F(name) { STR(name), 8, 8, 1 }
@@ -1802,6 +1998,14 @@ rs6000_convert_from_func_ptr_addr (CORE_
/* 112 */ R(srr0), R(srr1), R(tbl), R(tbu), \
/* 116 */ R4(dec), R(dabr), R4(ear)
+/* AltiVec registers */
+#define PPC_ALTIVEC_REGS \
+ /*119*/R16(vr0), R16(vr1), R16(vr2), R16(vr3), R16(vr4), R16(vr5), R16(vr6), R16(vr7), \
+ /*127*/R16(vr8), R16(vr9), R16(vr10),R16(vr11),R16(vr12),R16(vr13),R16(vr14),R16(vr15), \
+ /*135*/R16(vr16),R16(vr17),R16(vr18),R16(vr19),R16(vr20),R16(vr21),R16(vr22),R16(vr23), \
+ /*143*/R16(vr24),R16(vr25),R16(vr26),R16(vr27),R16(vr28),R16(vr29),R16(vr30),R16(vr31), \
+ /*151*/R4(vscr), R4(vrsave)
+
/* IBM POWER (pre-PowerPC) architecture, user-level view. We only cover
user-level SPR's. */
static const struct reg registers_power[] =
@@ -1815,7 +2019,8 @@ static const struct reg registers_power[
static const struct reg registers_powerpc[] =
{
COMMON_UISA_REGS,
- PPC_UISA_SPRS
+ PPC_UISA_SPRS,
+ PPC_ALTIVEC_REGS
};
/* IBM PowerPC 403. */
@@ -1946,6 +2151,21 @@ static const struct reg registers_750[]
};
+/* Motorola PowerPC 7400. */
+static const struct reg registers_7400[] =
+{
+ /* gpr0-gpr31, fpr0-fpr31 */
+ COMMON_UISA_REGS,
+ /* ctr, xre, lr, cr */
+ PPC_UISA_SPRS,
+ /* sr0-sr15 */
+ PPC_SEGMENT_REGS,
+ PPC_OEA_SPRS,
+ /* vr0-vr31, vrsave, vscr */
+ PPC_ALTIVEC_REGS
+ /* FIXME? Add more registers? */
+};
+
/* Information about a particular processor variant. */
struct variant
@@ -2005,6 +2225,8 @@ static const struct variant variants[] =
bfd_mach_ppc_860, num_registers (registers_860), registers_860},
{"750", "Motorola/IBM PowerPC 750 or 740", bfd_arch_powerpc,
bfd_mach_ppc_750, num_registers (registers_750), registers_750},
+ {"7400", "Motorola/IBM PowerPC 7400 (G4)", bfd_arch_powerpc,
+ bfd_mach_ppc_7400, num_registers (registers_7400), registers_7400},
/* FIXME: I haven't checked the register sets of the following. */
{"620", "Motorola PowerPC 620", bfd_arch_powerpc,
@@ -2235,6 +2457,23 @@ rs6000_gdbarch_init (struct gdbarch_info
v = find_variant_by_name (power ? "power" : "powerpc");
tdep->regs = v->regs;
+ if (v->arch == bfd_arch_powerpc)
+ switch (v->mach)
+ {
+ case bfd_mach_ppc:
+ tdep->first_altivec_regnum = 71;
+ tdep->last_altivec_regnum = 104;
+ break;
+ case bfd_mach_ppc_7400:
+ tdep->first_altivec_regnum = 119;
+ tdep->last_altivec_regnum = 153;
+ break;
+ default:
+ tdep->first_altivec_regnum = -1;
+ tdep->last_altivec_regnum = -1;
+ break;
+ }
+
/* Calculate byte offsets in raw register array. */
tdep->regoff = xmalloc (v->nregs * sizeof (int));
for (i = off = 0; i < v->nregs; i++)
@@ -2263,6 +2502,7 @@ rs6000_gdbarch_init (struct gdbarch_info
set_gdbarch_register_virtual_size (gdbarch, rs6000_register_virtual_size);
set_gdbarch_max_register_virtual_size (gdbarch, 8);
set_gdbarch_register_virtual_type (gdbarch, rs6000_register_virtual_type);
+ set_gdbarch_do_registers_info (gdbarch, rs6000_do_registers_info);
set_gdbarch_ptr_bit (gdbarch, wordsize * TARGET_CHAR_BIT);
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
@@ -2359,6 +2599,14 @@ rs6000_gdbarch_init (struct gdbarch_info
return gdbarch;
}
+static struct cmd_list_element *info_power_cmdlist = NULL;
+
+static void
+rs6000_info_power_command (char *args, int from_tty)
+{
+ help_list (info_power_cmdlist, "info power ", class_info, gdb_stdout);
+}
+
/* Initialization code. */
void
@@ -2366,4 +2614,14 @@ _initialize_rs6000_tdep (void)
{
register_gdbarch_init (bfd_arch_rs6000, rs6000_gdbarch_init);
register_gdbarch_init (bfd_arch_powerpc, rs6000_gdbarch_init);
+
+ /* Add root prefix command for "info power" commands */
+ add_prefix_cmd ("power", class_info, rs6000_info_power_command,
+ "Various POWERPC info specific commands.",
+ &info_power_cmdlist, "info power ", 0, &infolist);
+
+ add_cmd ("altivec", class_info, rs6000_altivec_registers_info,
+ "Display the contents of the AltiVec registers.",
+ &info_power_cmdlist);
+
}
Index: config/powerpc/nm-linux.h
===================================================================
RCS file: /cvs/uberbaum/gdb/config/powerpc/nm-linux.h,v
retrieving revision 1.9
diff -u -p -r1.9 nm-linux.h
--- nm-linux.h 2001/11/20 16:36:44 1.9
+++ nm-linux.h 2001/11/28 23:26:20
@@ -30,6 +30,8 @@ extern int kernel_u_size (void);
#define U_REGS_OFFSET 0
+#define FETCH_INFERIOR_REGISTERS
+
extern int ppc_register_u_addr (int, int);
#define REGISTER_U_ADDR(addr, blockend, regno) \
(addr) = ppc_register_u_addr ((blockend),(regno));
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-28 18:09 [RFA] W.I.P. AltiVec ppc registers support Elena Zannoni
2001-11-18 13:27 ` Elena Zannoni
2001-11-18 14:11 ` Daniel Jacobowitz
@ 2001-11-28 18:33 ` Daniel Jacobowitz
2001-11-18 13:40 ` Daniel Jacobowitz
2001-11-29 10:40 ` Kevin Buettner
3 siblings, 1 reply; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-28 18:33 UTC (permalink / raw)
To: gdb-patches
On Wed, Nov 28, 2001 at 09:15:35PM -0500, Elena Zannoni wrote:
>
> AltiVec registers are 32 128-bit wide registers found on the G4
> powerpc processor family. This patch adds some initial support for
> such registers to gdb on a linux ppc platform.
>
> The Altivec registers are not displayed in a normal 'info reg' command
> output. They are shown (like fp regs) if one says 'info all' instead.
> Furthermore I added a specific 'info power altivec' command to display
> just the Altivec registers. (I am not sure that the word 'power' is
> the best choice, maybe simply 'ppc' or 'powerpc' is better). This way
> the command as just a specific powerpc info command, w/o it being a
> generic info command avaliable on every platform.
Use 'powerpc', please? 'power' is something quite different, and will
work as an abbreviation for powerpc anyway.
> If there is no kernel support for ptrace to handle the AltiVec
> registers, they will display as 0's.
>
> The little drawback is that such registers will be displayed any time
> gdb's architecture is 'powerpc:common' or 'powerpc:7400'. The first
> case is the architecture gdb defaults to when run on a ppc machine,
> because the multiarch mechanism cannot determine the nature of the
> executable file. To be clearer, there is no way for gdb to know that
> the architecture is meant to be a ppc7400 based on executable
> information provided by BFD (unlike for Mips and Sh). So, gdb will
> always start and *stay* with a powerpc:common architecture selected,
> unless the user explicitly sets the architecture to be
> 'powerpc:7400'. This impossibility to auto detect the architecture is
> what prompted me to have Altivec defined anyway for the default
> arch. [Hopefully this deficiency will be rectified soon].
Hopefully. I'd say this wasn't too big of a caveat for now, though,
and I and Andrew both seem to have ideas in this direction.
Other than that, I've got no real comments. Looks pretty good. There
are a number of very similar functions involved in the fetching/storing
that I'm a little unhappy with, but that seems to be about par for GDB.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-18 14:11 ` Daniel Jacobowitz
2001-11-19 12:59 ` Andrew Cagney
@ 2001-11-28 22:27 ` Daniel Jacobowitz
2001-12-02 10:28 ` Elena Zannoni
2 siblings, 0 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-28 22:27 UTC (permalink / raw)
To: gdb-patches
On Wed, Nov 28, 2001 at 09:15:35PM -0500, Elena Zannoni wrote:
>
> AltiVec registers are 32 128-bit wide registers found on the G4
> powerpc processor family. This patch adds some initial support for
> such registers to gdb on a linux ppc platform.
>
> The Altivec registers are not displayed in a normal 'info reg' command
> output. They are shown (like fp regs) if one says 'info all' instead.
> Furthermore I added a specific 'info power altivec' command to display
> just the Altivec registers. (I am not sure that the word 'power' is
> the best choice, maybe simply 'ppc' or 'powerpc' is better). This way
> the command as just a specific powerpc info command, w/o it being a
> generic info command avaliable on every platform.
>
> If there is no kernel support for ptrace to handle the AltiVec
> registers, they will display as 0's.
Wait, I knew I was forgetting something important.
There is no kernel support for this feature in any public PowerPC
kernel tree, and to my knowledge there has been no suggested patch for
it on any of the public LinuxPPC forums. As such, the interface to it
is still up in the air. I've discussed this with other kernel folk at
various times, and the general consensus is that, instead of adding
them to the user area and using PEEKUSR, someone should simply
implement PTRACE_GETFPXREGS (perhaps just PTRACE_GETXREGS, as the FP
does not really apply, but consistency...). We almost never want to
fetch just one altivec register, excepting maybe VRSAVE, and GETFPXREGS
takes negligibly more time than a single PEEKUSR call.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-19 12:59 ` Andrew Cagney
@ 2001-11-29 9:04 ` Andrew Cagney
2001-11-29 13:10 ` Daniel Jacobowitz
1 sibling, 0 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-29 9:04 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
>
> Wait, I knew I was forgetting something important.
>
> There is no kernel support for this feature in any public PowerPC
> kernel tree, and to my knowledge there has been no suggested patch for
> it on any of the public LinuxPPC forums. As such, the interface to it
> is still up in the air. I've discussed this with other kernel folk at
> various times, and the general consensus is that, instead of adding
> them to the user area and using PEEKUSR, someone should simply
> implement PTRACE_GETFPXREGS (perhaps just PTRACE_GETXREGS, as the FP
> does not really apply, but consistency...). We almost never want to
> fetch just one altivec register, excepting maybe VRSAVE, and GETFPXREGS
> takes negligibly more time than a single PEEKUSR call.
So if the tweek to ppc-linux-nat.c that does the register fetch was
omitted, it would be ok?
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-28 18:09 [RFA] W.I.P. AltiVec ppc registers support Elena Zannoni
` (2 preceding siblings ...)
2001-11-28 18:33 ` Daniel Jacobowitz
@ 2001-11-29 10:40 ` Kevin Buettner
2001-11-19 15:15 ` Kevin Buettner
2001-11-19 18:51 ` Elena Zannoni
3 siblings, 2 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-29 10:40 UTC (permalink / raw)
To: Elena Zannoni, gdb-patches
On Nov 28, 9:15pm, Elena Zannoni wrote:
> The first Changelog is just for the most recent change set. I included
> the older one for easy reference.
Thanks for doing this.
> I tested this on AIX4.3, on a Linux-ppc with Altivec kernel support,
> and on a Linux-ppx w/o Altivec kernel support.
Good.
Now, for my comments...
First, regarding the AltiVec ptrace() support in the Linux/PPC
kernel... Have the necessary patches been submitted to some public
mailing list? If so, I'd be willing to let the ptrace related bits go
in even if they haven't been agreed upon by the kernel developers. We
can always make adjustments to GDB later on after the kernel folks
have hashed out how they want to do things. OTOH, I'm extremely
reluctant approve any changes to GDB based on kernel patches which
haven't at least been posted for commentary to some public list.
Regarding the implementation...
> +/* AltiVec regs are not always supported by the kernel. We need to fake them,
> + and let the ptrace requests fail. */
> +#ifndef PT_VR0
> +#define PT_VR0 (PT_FPSCR + 1)
> +#endif
> +#ifndef PT_VR31
> +#define PT_VR31 (PT_VR0 + 4*31)
> +#endif
> +#ifndef PT_VRCR
> +#define PT_VRCR (PT_VR0 + 4*32)
> +#endif
> +#ifndef PT_VRSAVE
> +#define PT_VRSAVE (PT_VR0 + 4*33)
> +#endif
I don't think it's a good idea to provide fake PT_ constants,
especially since the kernel folks haven't agreed upon using PEEKUSER /
POKEUSER for accessing the AltiVec registers. Also, in the interim,
it could happen that someone else will come up with a different ptrace
extension (perhaps involving hardware watchpoints?) that uses
constants at some of the offsets used by your fake AltiVec registers.
If this were to happen, gdb could potentially write these registers
with unpredictable consequences.
The PT_V0 constant is the only constant used in the above defines and
it's only used in one place (in ppc_register_u_addr). Rather than
using the above #defines, might I suggest that instead of doing:
/* Altivec registers: 4 slots each. */
if (altivec_register_p (regno))
u_addr = (ustart + (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4);
you instead do:
/* Altivec registers: 4 slots each. */
if (altivec_register_p (regno))
{
#ifdef PT_VR0
u_addr = (ustart + (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4);
#else
u_addr = -1;
#endif
}
The #else clause isn't really necessary because you already initialize
u_addr to -1 at the outset.
The other advantage to doing things this way is that you'll no longer
need a separate fetch_altivec_register() function which differs from
fetch_register() only in that it doesn't print a message when ptrace()
produces an error. (And likewise for store_register() /
store_altivec_register().)
....
Regarding...
> -static int regmap[] =
[etc]
from your previous patch, I've decided that while the code ends up being
more verbose, it is easier to read and understand what's going on. So
I'm approving your previous patch. (I'll send out a separate approval
message if you wish.)
With regard to
> Index: config/powerpc/nm-linux.h
[...]
> +#define FETCH_INFERIOR_REGISTERS
I think this is a good thing. It *might not* be strictly necessary
for adding AltiVec support via PEEKUSER / POKEUSER, but it does give
us more control. Also doing this allows us to clean up the code in other
ways. E.g, the following bit from config/powerpc/nm-linux.h can be
removed:
> extern int ppc_register_u_addr (int, int);
> #define REGISTER_U_ADDR(addr, blockend, regno) \
> (addr) = ppc_register_u_addr ((blockend),(regno));
This in turn means that ppc_register_u_addr() can be made static
and that the ``ustart'' parameter can be removed. All calls to
register_addr() (in your new code) in ppc-linux-nat.c should be
changed to invoke ppc_register_u_addr() directly.
....
Your changes to rs6000-tdep.c and ppc-tdep.h look fine to me.
Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-19 12:59 ` Andrew Cagney
2001-11-29 9:04 ` Andrew Cagney
@ 2001-11-29 13:10 ` Daniel Jacobowitz
2001-11-19 16:00 ` Daniel Jacobowitz
2001-11-29 13:34 ` Kevin Buettner
1 sibling, 2 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-29 13:10 UTC (permalink / raw)
To: gdb-patches
On Thu, Nov 29, 2001 at 12:04:22PM -0500, Andrew Cagney wrote:
> >
> >Wait, I knew I was forgetting something important.
> >
> >There is no kernel support for this feature in any public PowerPC
> >kernel tree, and to my knowledge there has been no suggested patch for
> >it on any of the public LinuxPPC forums. As such, the interface to it
> >is still up in the air. I've discussed this with other kernel folk at
> >various times, and the general consensus is that, instead of adding
> >them to the user area and using PEEKUSR, someone should simply
> >implement PTRACE_GETFPXREGS (perhaps just PTRACE_GETXREGS, as the FP
> >does not really apply, but consistency...). We almost never want to
> >fetch just one altivec register, excepting maybe VRSAVE, and GETFPXREGS
> >takes negligibly more time than a single PEEKUSR call.
>
> So if the tweek to ppc-linux-nat.c that does the register fetch was
> omitted, it would be ok?
It would be (somewhat trivial, but) OK, yes. I have nothing against
the implementation, just the interface.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 13:10 ` Daniel Jacobowitz
2001-11-19 16:00 ` Daniel Jacobowitz
@ 2001-11-29 13:34 ` Kevin Buettner
2001-11-19 16:42 ` Kevin Buettner
2001-11-29 14:11 ` Kevin Buettner
1 sibling, 2 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-29 13:34 UTC (permalink / raw)
To: Daniel Jacobowitz, gdb-patches
On Nov 29, 4:09pm, Daniel Jacobowitz wrote:
> On Thu, Nov 29, 2001 at 12:04:22PM -0500, Andrew Cagney wrote:
> > >
> > >Wait, I knew I was forgetting something important.
> > >
> > >There is no kernel support for this feature in any public PowerPC
> > >kernel tree, and to my knowledge there has been no suggested patch for
> > >it on any of the public LinuxPPC forums. As such, the interface to it
> > >is still up in the air. I've discussed this with other kernel folk at
> > >various times, and the general consensus is that, instead of adding
> > >them to the user area and using PEEKUSR, someone should simply
> > >implement PTRACE_GETFPXREGS (perhaps just PTRACE_GETXREGS, as the FP
> > >does not really apply, but consistency...). We almost never want to
> > >fetch just one altivec register, excepting maybe VRSAVE, and GETFPXREGS
> > >takes negligibly more time than a single PEEKUSR call.
> >
> > So if the tweek to ppc-linux-nat.c that does the register fetch was
> > omitted, it would be ok?
>
> It would be (somewhat trivial, but) OK, yes. I have nothing against
> the implementation, just the interface.
If Elena makes the changes that I have in mind, the AltiVec specific
code which affects the interface will collapse down to 5 lines or so.
Of course, if PTRACE_GETFPXREGS (or the like) ends up being used,
ppc-linux-nat.c need to be substantially rewritten anyway. But the
point is that the five lines (or so) that I have in mind can then just
be deleted.
Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-19 18:51 ` Elena Zannoni
@ 2001-11-29 13:53 ` Elena Zannoni
2001-11-29 14:21 ` Kevin Buettner
1 sibling, 0 replies; 63+ messages in thread
From: Elena Zannoni @ 2001-11-29 13:53 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
Kevin Buettner writes:
> On Nov 28, 9:15pm, Elena Zannoni wrote:
>
> > The first Changelog is just for the most recent change set. I included
> > the older one for easy reference.
>
> Thanks for doing this.
>
> > I tested this on AIX4.3, on a Linux-ppc with Altivec kernel support,
> > and on a Linux-ppx w/o Altivec kernel support.
>
> Good.
>
> Now, for my comments...
>
> First, regarding the AltiVec ptrace() support in the Linux/PPC
> kernel... Have the necessary patches been submitted to some public
> mailing list? If so, I'd be willing to let the ptrace related bits go
> in even if they haven't been agreed upon by the kernel developers. We
> can always make adjustments to GDB later on after the kernel folks
> have hashed out how they want to do things. OTOH, I'm extremely
> reluctant approve any changes to GDB based on kernel patches which
> haven't at least been posted for commentary to some public list.
No :-( I am going hopefully to sort this out very soon.
>
> Regarding the implementation...
>
> > +/* AltiVec regs are not always supported by the kernel. We need to fake them,
> > + and let the ptrace requests fail. */
> > +#ifndef PT_VR0
> > +#define PT_VR0 (PT_FPSCR + 1)
> > +#endif
> > +#ifndef PT_VR31
> > +#define PT_VR31 (PT_VR0 + 4*31)
> > +#endif
> > +#ifndef PT_VRCR
> > +#define PT_VRCR (PT_VR0 + 4*32)
> > +#endif
> > +#ifndef PT_VRSAVE
> > +#define PT_VRSAVE (PT_VR0 + 4*33)
> > +#endif
>
> I don't think it's a good idea to provide fake PT_ constants,
> especially since the kernel folks haven't agreed upon using PEEKUSER /
> POKEUSER for accessing the AltiVec registers. Also, in the interim,
> it could happen that someone else will come up with a different ptrace
> extension (perhaps involving hardware watchpoints?) that uses
> constants at some of the offsets used by your fake AltiVec registers.
> If this were to happen, gdb could potentially write these registers
> with unpredictable consequences.
>
> The PT_V0 constant is the only constant used in the above defines and
> it's only used in one place (in ppc_register_u_addr). Rather than
> using the above #defines, might I suggest that instead of doing:
>
> /* Altivec registers: 4 slots each. */
> if (altivec_register_p (regno))
> u_addr = (ustart + (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4);
>
> you instead do:
>
> /* Altivec registers: 4 slots each. */
> if (altivec_register_p (regno))
> {
> #ifdef PT_VR0
> u_addr = (ustart + (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4);
> #else
> u_addr = -1;
> #endif
> }
>
> The #else clause isn't really necessary because you already initialize
> u_addr to -1 at the outset.
>
> The other advantage to doing things this way is that you'll no longer
> need a separate fetch_altivec_register() function which differs from
> fetch_register() only in that it doesn't print a message when ptrace()
> produces an error. (And likewise for store_register() /
> store_altivec_register().)
>
Oh, right, I don't use anything but PT_VR0 now (I did in ohter
versions of the patch, and forgot to erase them). It indeed seems
cleaner doing like you say. I also came up with a configure patch but
that seemed less flexible.
> ....
>
> Regarding...
>
> > -static int regmap[] =
> [etc]
>
> from your previous patch, I've decided that while the code ends up being
> more verbose, it is easier to read and understand what's going on. So
> I'm approving your previous patch. (I'll send out a separate approval
> message if you wish.)
>
Thanks, please, since that is a separate thread.
> With regard to
>
> > Index: config/powerpc/nm-linux.h
> [...]
> > +#define FETCH_INFERIOR_REGISTERS
>
> I think this is a good thing. It *might not* be strictly necessary
> for adding AltiVec support via PEEKUSER / POKEUSER, but it does give
> us more control. Also doing this allows us to clean up the code in other
> ways. E.g, the following bit from config/powerpc/nm-linux.h can be
> removed:
>
> > extern int ppc_register_u_addr (int, int);
> > #define REGISTER_U_ADDR(addr, blockend, regno) \
> > (addr) = ppc_register_u_addr ((blockend),(regno));
>
> This in turn means that ppc_register_u_addr() can be made static
> and that the ``ustart'' parameter can be removed. All calls to
> register_addr() (in your new code) in ppc-linux-nat.c should be
> changed to invoke ppc_register_u_addr() directly.
>
Unfortunately not. I thought the same, until I remembered about core
file debugging. That function is called by fetch_core_registers() in
core-aout.c.
> ....
>
> Your changes to rs6000-tdep.c and ppc-tdep.h look fine to me.
>
OK.
> Kevin
Elena
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 13:34 ` Kevin Buettner
2001-11-19 16:42 ` Kevin Buettner
@ 2001-11-29 14:11 ` Kevin Buettner
2001-11-19 22:22 ` Kevin Buettner
2001-11-29 14:27 ` Elena Zannoni
1 sibling, 2 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-29 14:11 UTC (permalink / raw)
To: gdb-patches
On Nov 29, 2:32pm, Kevin Buettner wrote:
> If Elena makes the changes that I have in mind,...
> code which affects the interface will collapse down to 5 lines or so.
> Of course, if PTRACE_GETFPXREGS (or the like) ends up being used,
> ppc-linux-nat.c need to be substantially rewritten anyway. But the
> point is that the five lines (or so) that I have in mind can then just
> be deleted.
It occurred to me that it might help Elena more if I provided a
patch with what I had in mind. See below. (Completely untested.)
Anyway, the five lines that I refer to above is this part:
+#ifdef PT_VR0
+ u_addr = (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4;
+#else
+ u_addr = -1;
+#endif
Index: ppc-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-nat.c,v
retrieving revision 1.10
diff -u -p -r1.10 ppc-linux-nat.c
--- ppc-linux-nat.c 2001/11/20 16:35:24 1.10
+++ ppc-linux-nat.c 2001/11/29 22:05:26
@@ -32,31 +32,243 @@
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/procfs.h>
+#include <sys/ptrace.h>
/* Prototypes for supply_gregset etc. */
#include "gregset.h"
+#include "ppc-tdep.h"
+/* Default the type of the ptrace transfer to int. */
+#ifndef PTRACE_XFER_TYPE
+#define PTRACE_XFER_TYPE long
+#endif
+
int
kernel_u_size (void)
{
return (sizeof (struct user));
}
+
+/* *INDENT-OFF* */
+/* registers layout, as presented by the ptrace interface:
+PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
+PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
+PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
+PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
+PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
+PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
+PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
+PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
+PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ */
+/* *INDENT_ON * */
+
+static int
+ppc_register_u_addr (int regno)
+{
+ int u_addr = -1;
+
+ /* General purpose registers occupy 1 slot each in the buffer */
+ if (regno >= PPC_GP0_REGNUM && regno <= PPC_GPLAST_REGNUM )
+ u_addr = (PT_R0 + regno) * 4;
+
+ /* Floating point regs: 2 slots each */
+ if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM)
+ u_addr = (PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4;
+
+ /* Altivec registers: 4 slots each. */
+ if (altivec_register_p (regno))
+ {
+#ifdef PT_VR0
+ u_addr = (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4;
+#else
+ u_addr = -1;
+#endif
+ }
+
+ /* UISA special purpose registers: 1 slot each */
+ if (regno == PC_REGNUM)
+ u_addr = PT_NIP * 4;
+ if (regno == PPC_LR_REGNUM)
+ u_addr = PT_LNK * 4;
+ if (regno == PPC_CR_REGNUM)
+ u_addr = PT_CCR * 4;
+ if (regno == PPC_XER_REGNUM)
+ u_addr = PT_XER * 4;
+ if (regno == PPC_CTR_REGNUM)
+ u_addr = PT_CTR * 4;
+ if (regno == PPC_MQ_REGNUM)
+ u_addr = PT_MQ * 4;
+ if (regno == PPC_PS_REGNUM)
+ u_addr = PT_MSR * 4;
+
+ return u_addr;
+}
+
+static int
+ppc_ptrace_cannot_fetch_store_register (int regno)
+{
+ return (ppc_register_u_addr (regno) == -1);
+}
+
+static void
+fetch_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int tid;
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ {
+ memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ regaddr = ppc_register_u_addr (regno);
+ if (regaddr < 0)
+ return;
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PTRACE_PEEKUSR, tid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ sprintf (mess, "reading register %s (#%d)",
+ REGISTER_NAME (regno), regno);
+ perror_with_name (mess);
+ }
+ }
+ supply_register (regno, buf);
+}
+
+static void
+fetch_ppc_registers (void)
+{
+ int last_register;
+ int i;
+
+ last_register = PPC_MQ_REGNUM;
+ for (i = 0; i <= last_register; i++)
+ fetch_register (i);
+}
+
+static void
+fetch_altivec_registers (void)
+{
+ int i;
+
+ for (i = 0;
+ i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
+ - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
+ i++)
+ fetch_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
+}
+
+/* Fetch registers from the child process. Fetch all registers if
+ regno == -1, otherwise fetch all general registers or all floating
+ point registers depending upon the value of regno. */
+
+void
+fetch_inferior_registers (int regno)
+{
+ if (regno == -1)
+ {
+ fetch_ppc_registers ();
+ fetch_altivec_registers ();
+ }
+ else
+ {
+ if (altivec_register_p (regno))
+ fetch_altivec_register (regno);
+ else
+ fetch_register (regno);
+ }
+}
+
+/* Store one register. */
+static void
+store_register (int regno)
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ int tid;
+ char *buf = alloca (MAX_REGISTER_RAW_SIZE);
+
+ if (ppc_ptrace_cannot_fetch_store_register (regno))
+ {
+ return;
+ }
+
+ /* Overload thread id onto process id */
+ if ((tid = TIDGET (inferior_ptid)) == 0)
+ tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
+
+ regaddr = ppc_register_u_addr (regno);
+ regcache_collect (regno, buf);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PTRACE_POKEUSR, tid, (PTRACE_ARG3_TYPE) regaddr,
+ *(PTRACE_XFER_TYPE *) & buf[i]);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ sprintf (mess, "writing register %s (#%d)",
+ REGISTER_NAME (regno), regno);
+ perror_with_name (mess);
+ }
+ }
+}
+
+static void
+store_ppc_registers (void)
+{
+ int last_register;
+ int i;
+
+ last_register = PPC_MQ_REGNUM;
+ for (i = 0; i <= last_register; i++)
+ store_register (i);
+}
+
+static void
+store_altivec_registers (void)
+{
+ int i;
-static int regmap[] =
-{PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
- PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
- PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
- PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
- PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
- PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
- PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
- PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
- PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ};
+ for (i = 0;
+ i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
+ - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
+ i++)
+ store_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
+}
-int
-ppc_register_u_addr (int ustart, int regnum)
+void
+store_inferior_registers (int regno)
{
- return (ustart + 4 * regmap[regnum]);
+ if (regno >= 0)
+ {
+ if (altivec_register_p (regno))
+ store_altivec_register (regno);
+ else
+ store_register (regno);
+ }
+ else
+ {
+ store_ppc_registers ();
+ store_altivec_registers ();
+ }
}
void
@@ -68,8 +280,13 @@ supply_gregset (gdb_gregset_t *gregsetp)
for (regi = 0; regi < 32; regi++)
supply_register (regi, (char *) (regp + regi));
- for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
- supply_register (regi, (char *) (regp + regmap[regi]));
+ supply_register (PC_REGNUM, (char *) (regp + PT_NIP));
+ supply_register (PPC_LR_REGNUM, (char *) (regp + PT_LNK));
+ supply_register (PPC_CR_REGNUM, (char *) (regp + PT_CCR));
+ supply_register (PPC_XER_REGNUM, (char *) (regp + PT_XER));
+ supply_register (PPC_CTR_REGNUM, (char *) (regp + PT_CTR));
+ supply_register (PPC_MQ_REGNUM, (char *) (regp + PT_MQ));
+ supply_register (PPC_PS_REGNUM, (char *) (regp + PT_MSR));
}
void
@@ -78,19 +295,26 @@ fill_gregset (gdb_gregset_t *gregsetp, i
int regi;
elf_greg_t *regp = (elf_greg_t *) gregsetp;
-#define COPY_REG(_idx_,_regi_) \
- if ((regno == -1) || regno == _regi_) \
- regcache_collect (_regi_, regp + _idx_)
-
for (regi = 0; regi < 32; regi++)
{
- COPY_REG (regmap[regi], regi);
+ if ((regno == -1) || regno == regi)
+ regcache_collect (regi, regp + PT_R0 + regi);
}
- for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
- {
- COPY_REG (regmap[regi], regi);
- }
+ if ((regno == -1) || regno == PC_REGNUM)
+ regcache_collect (PC_REGNUM, regp + PT_NIP);
+ if ((regno == -1) || regno == PPC_LR_REGNUM)
+ regcache_collect (PPC_LR_REGNUM, regp + PT_LNK);
+ if ((regno == -1) || regno == PPC_CR_REGNUM)
+ regcache_collect (PPC_CR_REGNUM, regp + PT_CCR);
+ if ((regno == -1) || regno == PPC_XER_REGNUM)
+ regcache_collect (PPC_XER_REGNUM, regp + PT_XER);
+ if ((regno == -1) || regno == PPC_CTR_REGNUM)
+ regcache_collect (PPC_CTR_REGNUM, regp + PT_CTR);
+ if ((regno == -1) || regno == PPC_MQ_REGNUM)
+ regcache_collect (PPC_MQ_REGNUM, regp + PT_MQ);
+ if ((regno == -1) || regno == PPC_PS_REGNUM)
+ regcache_collect (PPC_PS_REGNUM, regp + PT_MSR);
}
void
Index: config/powerpc/nm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/powerpc/nm-linux.h,v
retrieving revision 1.9
diff -u -p -r1.9 nm-linux.h
--- nm-linux.h 2001/11/20 16:36:44 1.9
+++ nm-linux.h 2001/11/29 22:05:32
@@ -23,15 +23,6 @@ Foundation, Inc., 675 Mass Ave, Cambridg
#define NM_LINUX_H
-/* Return sizeof user struct to callers in less machine dependent routines */
-
-#define KERNEL_U_SIZE kernel_u_size()
-extern int kernel_u_size (void);
-
-#define U_REGS_OFFSET 0
-
-extern int ppc_register_u_addr (int, int);
-#define REGISTER_U_ADDR(addr, blockend, regno) \
- (addr) = ppc_register_u_addr ((blockend),(regno));
+#define FETCH_INFERIOR_REGISTERS
#endif /* #ifndef NM_LINUX_H */
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-19 18:51 ` Elena Zannoni
2001-11-29 13:53 ` Elena Zannoni
@ 2001-11-29 14:21 ` Kevin Buettner
2001-11-19 22:53 ` Kevin Buettner
` (2 more replies)
1 sibling, 3 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-29 14:21 UTC (permalink / raw)
To: Daniel Jacobowitz, Elena Zannoni; +Cc: gdb-patches
On Nov 29, 4:59pm, Elena Zannoni wrote:
> > With regard to
> >
> > > Index: config/powerpc/nm-linux.h
> > [...]
> > > +#define FETCH_INFERIOR_REGISTERS
> >
> > I think this is a good thing. It *might not* be strictly necessary
> > for adding AltiVec support via PEEKUSER / POKEUSER, but it does give
> > us more control. Also doing this allows us to clean up the code in other
> > ways. E.g, the following bit from config/powerpc/nm-linux.h can be
> > removed:
> >
> > > extern int ppc_register_u_addr (int, int);
> > > #define REGISTER_U_ADDR(addr, blockend, regno) \
> > > (addr) = ppc_register_u_addr ((blockend),(regno));
> >
> > This in turn means that ppc_register_u_addr() can be made static
> > and that the ``ustart'' parameter can be removed. All calls to
> > register_addr() (in your new code) in ppc-linux-nat.c should be
> > changed to invoke ppc_register_u_addr() directly.
> >
>
> Unfortunately not. I thought the same, until I remembered about core
> file debugging. That function is called by fetch_core_registers() in
> core-aout.c.
Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
core-regset.c instead?
Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 14:11 ` Kevin Buettner
2001-11-19 22:22 ` Kevin Buettner
@ 2001-11-29 14:27 ` Elena Zannoni
2001-11-19 23:55 ` Elena Zannoni
1 sibling, 1 reply; 63+ messages in thread
From: Elena Zannoni @ 2001-11-29 14:27 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches
Kevin Buettner writes:
> On Nov 29, 2:32pm, Kevin Buettner wrote:
>
> > If Elena makes the changes that I have in mind,...
> > code which affects the interface will collapse down to 5 lines or so.
> > Of course, if PTRACE_GETFPXREGS (or the like) ends up being used,
> > ppc-linux-nat.c need to be substantially rewritten anyway. But the
> > point is that the five lines (or so) that I have in mind can then just
> > be deleted.
>
> It occurred to me that it might help Elena more if I provided a
> patch with what I had in mind. See below. (Completely untested.)
I am not that helpless :-)
Let me wait a bit on this until the ptrace issue is clarified somewhat.
Elena
>
> Anyway, the five lines that I refer to above is this part:
>
> +#ifdef PT_VR0
> + u_addr = (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4;
> +#else
> + u_addr = -1;
> +#endif
>
>
> Index: ppc-linux-nat.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/ppc-linux-nat.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 ppc-linux-nat.c
> --- ppc-linux-nat.c 2001/11/20 16:35:24 1.10
> +++ ppc-linux-nat.c 2001/11/29 22:05:26
> @@ -32,31 +32,243 @@
> #include <sys/wait.h>
> #include <fcntl.h>
> #include <sys/procfs.h>
> +#include <sys/ptrace.h>
>
> /* Prototypes for supply_gregset etc. */
> #include "gregset.h"
> +#include "ppc-tdep.h"
>
> +/* Default the type of the ptrace transfer to int. */
> +#ifndef PTRACE_XFER_TYPE
> +#define PTRACE_XFER_TYPE long
> +#endif
> +
> int
> kernel_u_size (void)
> {
> return (sizeof (struct user));
> }
> +
> +/* *INDENT-OFF* */
> +/* registers layout, as presented by the ptrace interface:
> +PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
> +PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
> +PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
> +PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
> +PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
> +PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
> +PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
> +PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
> +PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ */
> +/* *INDENT_ON * */
> +
> +static int
> +ppc_register_u_addr (int regno)
> +{
> + int u_addr = -1;
> +
> + /* General purpose registers occupy 1 slot each in the buffer */
> + if (regno >= PPC_GP0_REGNUM && regno <= PPC_GPLAST_REGNUM )
> + u_addr = (PT_R0 + regno) * 4;
> +
> + /* Floating point regs: 2 slots each */
> + if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM)
> + u_addr = (PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4;
> +
> + /* Altivec registers: 4 slots each. */
> + if (altivec_register_p (regno))
> + {
> +#ifdef PT_VR0
> + u_addr = (PT_VR0 + (regno - gdbarch_tdep (current_gdbarch)->first_altivec_regnum) * 4) * 4;
> +#else
> + u_addr = -1;
> +#endif
> + }
> +
> + /* UISA special purpose registers: 1 slot each */
> + if (regno == PC_REGNUM)
> + u_addr = PT_NIP * 4;
> + if (regno == PPC_LR_REGNUM)
> + u_addr = PT_LNK * 4;
> + if (regno == PPC_CR_REGNUM)
> + u_addr = PT_CCR * 4;
> + if (regno == PPC_XER_REGNUM)
> + u_addr = PT_XER * 4;
> + if (regno == PPC_CTR_REGNUM)
> + u_addr = PT_CTR * 4;
> + if (regno == PPC_MQ_REGNUM)
> + u_addr = PT_MQ * 4;
> + if (regno == PPC_PS_REGNUM)
> + u_addr = PT_MSR * 4;
> +
> + return u_addr;
> +}
> +
> +static int
> +ppc_ptrace_cannot_fetch_store_register (int regno)
> +{
> + return (ppc_register_u_addr (regno) == -1);
> +}
> +
> +static void
> +fetch_register (int regno)
> +{
> + /* This isn't really an address. But ptrace thinks of it as one. */
> + CORE_ADDR regaddr;
> + char mess[128]; /* For messages */
> + register int i;
> + char buf[MAX_REGISTER_RAW_SIZE];
> + int tid;
> +
> + if (ppc_ptrace_cannot_fetch_store_register (regno))
> + {
> + memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
> + supply_register (regno, buf);
> + return;
> + }
> +
> + /* Overload thread id onto process id */
> + if ((tid = TIDGET (inferior_ptid)) == 0)
> + tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
> +
> + regaddr = ppc_register_u_addr (regno);
> + if (regaddr < 0)
> + return;
> + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
> + {
> + errno = 0;
> + *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PTRACE_PEEKUSR, tid,
> + (PTRACE_ARG3_TYPE) regaddr, 0);
> + regaddr += sizeof (PTRACE_XFER_TYPE);
> + if (errno != 0)
> + {
> + sprintf (mess, "reading register %s (#%d)",
> + REGISTER_NAME (regno), regno);
> + perror_with_name (mess);
> + }
> + }
> + supply_register (regno, buf);
> +}
> +
> +static void
> +fetch_ppc_registers (void)
> +{
> + int last_register;
> + int i;
> +
> + last_register = PPC_MQ_REGNUM;
> + for (i = 0; i <= last_register; i++)
> + fetch_register (i);
> +}
> +
> +static void
> +fetch_altivec_registers (void)
> +{
> + int i;
> +
> + for (i = 0;
> + i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
> + - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
> + i++)
> + fetch_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
> +}
> +
> +/* Fetch registers from the child process. Fetch all registers if
> + regno == -1, otherwise fetch all general registers or all floating
> + point registers depending upon the value of regno. */
> +
> +void
> +fetch_inferior_registers (int regno)
> +{
> + if (regno == -1)
> + {
> + fetch_ppc_registers ();
> + fetch_altivec_registers ();
> + }
> + else
> + {
> + if (altivec_register_p (regno))
> + fetch_altivec_register (regno);
> + else
> + fetch_register (regno);
> + }
> +}
> +
> +/* Store one register. */
> +static void
> +store_register (int regno)
> +{
> + /* This isn't really an address. But ptrace thinks of it as one. */
> + CORE_ADDR regaddr;
> + char mess[128]; /* For messages */
> + register int i;
> + int tid;
> + char *buf = alloca (MAX_REGISTER_RAW_SIZE);
> +
> + if (ppc_ptrace_cannot_fetch_store_register (regno))
> + {
> + return;
> + }
> +
> + /* Overload thread id onto process id */
> + if ((tid = TIDGET (inferior_ptid)) == 0)
> + tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
> +
> + regaddr = ppc_register_u_addr (regno);
> + regcache_collect (regno, buf);
> + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
> + {
> + errno = 0;
> + ptrace (PTRACE_POKEUSR, tid, (PTRACE_ARG3_TYPE) regaddr,
> + *(PTRACE_XFER_TYPE *) & buf[i]);
> + regaddr += sizeof (PTRACE_XFER_TYPE);
> + if (errno != 0)
> + {
> + sprintf (mess, "writing register %s (#%d)",
> + REGISTER_NAME (regno), regno);
> + perror_with_name (mess);
> + }
> + }
> +}
> +
> +static void
> +store_ppc_registers (void)
> +{
> + int last_register;
> + int i;
> +
> + last_register = PPC_MQ_REGNUM;
> + for (i = 0; i <= last_register; i++)
> + store_register (i);
> +}
> +
> +static void
> +store_altivec_registers (void)
> +{
> + int i;
>
> -static int regmap[] =
> -{PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
> - PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
> - PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
> - PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
> - PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
> - PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
> - PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
> - PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
> - PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ};
> + for (i = 0;
> + i < gdbarch_tdep (current_gdbarch)->last_altivec_regnum
> + - gdbarch_tdep (current_gdbarch)->first_altivec_regnum;
> + i++)
> + store_register (gdbarch_tdep (current_gdbarch)->first_altivec_regnum + i);
> +}
>
> -int
> -ppc_register_u_addr (int ustart, int regnum)
> +void
> +store_inferior_registers (int regno)
> {
> - return (ustart + 4 * regmap[regnum]);
> + if (regno >= 0)
> + {
> + if (altivec_register_p (regno))
> + store_altivec_register (regno);
> + else
> + store_register (regno);
> + }
> + else
> + {
> + store_ppc_registers ();
> + store_altivec_registers ();
> + }
> }
>
> void
> @@ -68,8 +280,13 @@ supply_gregset (gdb_gregset_t *gregsetp)
> for (regi = 0; regi < 32; regi++)
> supply_register (regi, (char *) (regp + regi));
>
> - for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
> - supply_register (regi, (char *) (regp + regmap[regi]));
> + supply_register (PC_REGNUM, (char *) (regp + PT_NIP));
> + supply_register (PPC_LR_REGNUM, (char *) (regp + PT_LNK));
> + supply_register (PPC_CR_REGNUM, (char *) (regp + PT_CCR));
> + supply_register (PPC_XER_REGNUM, (char *) (regp + PT_XER));
> + supply_register (PPC_CTR_REGNUM, (char *) (regp + PT_CTR));
> + supply_register (PPC_MQ_REGNUM, (char *) (regp + PT_MQ));
> + supply_register (PPC_PS_REGNUM, (char *) (regp + PT_MSR));
> }
>
> void
> @@ -78,19 +295,26 @@ fill_gregset (gdb_gregset_t *gregsetp, i
> int regi;
> elf_greg_t *regp = (elf_greg_t *) gregsetp;
>
> -#define COPY_REG(_idx_,_regi_) \
> - if ((regno == -1) || regno == _regi_) \
> - regcache_collect (_regi_, regp + _idx_)
> -
> for (regi = 0; regi < 32; regi++)
> {
> - COPY_REG (regmap[regi], regi);
> + if ((regno == -1) || regno == regi)
> + regcache_collect (regi, regp + PT_R0 + regi);
> }
>
> - for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
> - {
> - COPY_REG (regmap[regi], regi);
> - }
> + if ((regno == -1) || regno == PC_REGNUM)
> + regcache_collect (PC_REGNUM, regp + PT_NIP);
> + if ((regno == -1) || regno == PPC_LR_REGNUM)
> + regcache_collect (PPC_LR_REGNUM, regp + PT_LNK);
> + if ((regno == -1) || regno == PPC_CR_REGNUM)
> + regcache_collect (PPC_CR_REGNUM, regp + PT_CCR);
> + if ((regno == -1) || regno == PPC_XER_REGNUM)
> + regcache_collect (PPC_XER_REGNUM, regp + PT_XER);
> + if ((regno == -1) || regno == PPC_CTR_REGNUM)
> + regcache_collect (PPC_CTR_REGNUM, regp + PT_CTR);
> + if ((regno == -1) || regno == PPC_MQ_REGNUM)
> + regcache_collect (PPC_MQ_REGNUM, regp + PT_MQ);
> + if ((regno == -1) || regno == PPC_PS_REGNUM)
> + regcache_collect (PPC_PS_REGNUM, regp + PT_MSR);
> }
>
> void
> Index: config/powerpc/nm-linux.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/config/powerpc/nm-linux.h,v
> retrieving revision 1.9
> diff -u -p -r1.9 nm-linux.h
> --- nm-linux.h 2001/11/20 16:36:44 1.9
> +++ nm-linux.h 2001/11/29 22:05:32
> @@ -23,15 +23,6 @@ Foundation, Inc., 675 Mass Ave, Cambridg
>
> #define NM_LINUX_H
>
> -/* Return sizeof user struct to callers in less machine dependent routines */
> -
> -#define KERNEL_U_SIZE kernel_u_size()
> -extern int kernel_u_size (void);
> -
> -#define U_REGS_OFFSET 0
> -
> -extern int ppc_register_u_addr (int, int);
> -#define REGISTER_U_ADDR(addr, blockend, regno) \
> - (addr) = ppc_register_u_addr ((blockend),(regno));
> +#define FETCH_INFERIOR_REGISTERS
>
> #endif /* #ifndef NM_LINUX_H */
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 14:21 ` Kevin Buettner
2001-11-19 22:53 ` Kevin Buettner
@ 2001-11-29 14:42 ` Elena Zannoni
2001-11-20 8:37 ` Elena Zannoni
2001-11-29 15:03 ` Andrew Cagney
2001-11-29 14:47 ` Daniel Jacobowitz
2 siblings, 2 replies; 63+ messages in thread
From: Elena Zannoni @ 2001-11-29 14:42 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Daniel Jacobowitz, Elena Zannoni, gdb-patches
Kevin Buettner writes:
> On Nov 29, 4:59pm, Elena Zannoni wrote:
>
> > > With regard to
> > >
> > > > Index: config/powerpc/nm-linux.h
> > > [...]
> > > > +#define FETCH_INFERIOR_REGISTERS
> > >
> > > I think this is a good thing. It *might not* be strictly necessary
> > > for adding AltiVec support via PEEKUSER / POKEUSER, but it does give
> > > us more control. Also doing this allows us to clean up the code in other
> > > ways. E.g, the following bit from config/powerpc/nm-linux.h can be
> > > removed:
> > >
> > > > extern int ppc_register_u_addr (int, int);
> > > > #define REGISTER_U_ADDR(addr, blockend, regno) \
> > > > (addr) = ppc_register_u_addr ((blockend),(regno));
> > >
> > > This in turn means that ppc_register_u_addr() can be made static
> > > and that the ``ustart'' parameter can be removed. All calls to
> > > register_addr() (in your new code) in ppc-linux-nat.c should be
> > > changed to invoke ppc_register_u_addr() directly.
> > >
> >
> > Unfortunately not. I thought the same, until I remembered about core
> > file debugging. That function is called by fetch_core_registers() in
> > core-aout.c.
>
> Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> core-regset.c instead?
>
Whoops, yes, you are right. False alarm.
Elena
> Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 14:21 ` Kevin Buettner
2001-11-19 22:53 ` Kevin Buettner
2001-11-29 14:42 ` Elena Zannoni
@ 2001-11-29 14:47 ` Daniel Jacobowitz
2001-11-20 8:37 ` Daniel Jacobowitz
` (2 more replies)
2 siblings, 3 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-29 14:47 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 03:20:00PM -0700, Kevin Buettner wrote:
> On Nov 29, 4:59pm, Elena Zannoni wrote:
>
> > > With regard to
> > >
> > > > Index: config/powerpc/nm-linux.h
> > > [...]
> > > > +#define FETCH_INFERIOR_REGISTERS
> > >
> > > I think this is a good thing. It *might not* be strictly necessary
> > > for adding AltiVec support via PEEKUSER / POKEUSER, but it does give
> > > us more control. Also doing this allows us to clean up the code in other
> > > ways. E.g, the following bit from config/powerpc/nm-linux.h can be
> > > removed:
> > >
> > > > extern int ppc_register_u_addr (int, int);
> > > > #define REGISTER_U_ADDR(addr, blockend, regno) \
> > > > (addr) = ppc_register_u_addr ((blockend),(regno));
> > >
> > > This in turn means that ppc_register_u_addr() can be made static
> > > and that the ``ustart'' parameter can be removed. All calls to
> > > register_addr() (in your new code) in ppc-linux-nat.c should be
> > > changed to invoke ppc_register_u_addr() directly.
> > >
> >
> > Unfortunately not. I thought the same, until I remembered about core
> > file debugging. That function is called by fetch_core_registers() in
> > core-aout.c.
>
> Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> core-regset.c instead?
I'd like to kill our use of core-aout.c. Linux/PPC never used a.out
cores, but unfortunately core-aout.c defines register_addr () as a
wrapper for REGISTER_U_ADDR. The last time I tried to remove
core-aout.c from a platform I got bitten.
I think, now that we are defining FETCH_INFERIOR_REGISTERS, we can do
without it - infptrace was the only big consumer I see remaining. So
we might be OK without using core-aout.c at all now.
My still-unsubmitted cross-core patches for PowerPC remove
core-regset.o also, and very unpleasantly turn ppc-linux-nat.c into a
target-dependant rather than native-dependant file, so that we can grub
through the gregsets by hand. If you've got a better idea I'd love to
hear it :) It will be made somewhat easier by the destruction of
regmap[].
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 14:42 ` Elena Zannoni
2001-11-20 8:37 ` Elena Zannoni
@ 2001-11-29 15:03 ` Andrew Cagney
2001-11-20 8:54 ` Andrew Cagney
2001-11-29 16:27 ` Kevin Buettner
1 sibling, 2 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-29 15:03 UTC (permalink / raw)
To: Elena Zannoni; +Cc: Kevin Buettner, Daniel Jacobowitz, gdb-patches
>> Unfortunately not. I thought the same, until I remembered about core
> > > file debugging. That function is called by fetch_core_registers() in
> > > core-aout.c.
> > > Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> > Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> > core-regset.c instead?
> > Whoops, yes, you are right. False alarm.
So just the core code needs to have a hard-wired (non native header) way
of unpacking Altivec registers (if they are found?)?
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-20 9:07 ` Kevin Buettner
2001-11-20 9:08 ` Andrew Cagney
@ 2001-11-29 15:15 ` Kevin Buettner
2001-11-29 15:38 ` Daniel Jacobowitz
2 siblings, 0 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-29 15:15 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Elena Zannoni, gdb-patches
On Nov 29, 5:46pm, Daniel Jacobowitz wrote:
> > Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> > Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> > core-regset.c instead?
>
> I'd like to kill our use of core-aout.c. Linux/PPC never used a.out
> cores, but unfortunately core-aout.c defines register_addr () as a
> wrapper for REGISTER_U_ADDR. The last time I tried to remove
> core-aout.c from a platform I got bitten.
>
> I think, now that we are defining FETCH_INFERIOR_REGISTERS, we can do
> without it - infptrace was the only big consumer I see remaining. So
> we might be OK without using core-aout.c at all now.
That's what I was hoping. Maybe Elena could try it out and let us know?
> My still-unsubmitted cross-core patches for PowerPC remove
> core-regset.o also, and very unpleasantly turn ppc-linux-nat.c into a
> target-dependant rather than native-dependant file, so that we can grub
> through the gregsets by hand. If you've got a better idea I'd love to
> hear it :) It will be made somewhat easier by the destruction of
> regmap[].
I haven't seen your patches, but I imagine you have a table of
constants or some such that represent offsets and sizes of members in
the regsets? (I.e, something similar to what I did for SVR4 shared
library offsets.) If that's the approach, then the only real problem I
have with it is accurately generating (and maintaining) the tables.
The SVR4 shared library tables are compact enough to easily generate
by hand. The regset data is quite a lot larger and I would think
you'd want to generate this data through more automatic means. (I.e,
via a program that you'd compile and and then run on the target.)
Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-20 9:08 ` Andrew Cagney
@ 2001-11-29 15:33 ` Andrew Cagney
0 siblings, 0 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-29 15:33 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Daniel Jacobowitz, Elena Zannoni, gdb-patches
>
> I haven't seen your patches, but I imagine you have a table of
> constants or some such that represent offsets and sizes of members in
> the regsets? (I.e, something similar to what I did for SVR4 shared
> library offsets.) If that's the approach, then the only real problem I
> have with it is accurately generating (and maintaining) the tables.
> The SVR4 shared library tables are compact enough to easily generate
> by hand. The regset data is quite a lot larger and I would think
> you'd want to generate this data through more automatic means. (I.e,
> via a program that you'd compile and and then run on the target.)
Isn't the situtation with core files identical to shlibs? If the layout
changed then an old GDB couldn't debug new core files and a new GDB
couldn't debug old core files. To avoid this, people do stuff like put
new register sets into new sections.
enjoy,
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-20 9:07 ` Kevin Buettner
2001-11-20 9:08 ` Andrew Cagney
2001-11-29 15:15 ` Kevin Buettner
@ 2001-11-29 15:38 ` Daniel Jacobowitz
2001-11-20 9:13 ` Daniel Jacobowitz
2001-11-20 10:09 ` Kevin Buettner
2 siblings, 2 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-29 15:38 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 04:12:29PM -0700, Kevin Buettner wrote:
> > My still-unsubmitted cross-core patches for PowerPC remove
> > core-regset.o also, and very unpleasantly turn ppc-linux-nat.c into a
> > target-dependant rather than native-dependant file, so that we can grub
> > through the gregsets by hand. If you've got a better idea I'd love to
> > hear it :) It will be made somewhat easier by the destruction of
> > regmap[].
>
> I haven't seen your patches, but I imagine you have a table of
> constants or some such that represent offsets and sizes of members in
> the regsets? (I.e, something similar to what I did for SVR4 shared
> library offsets.) If that's the approach, then the only real problem I
> have with it is accurately generating (and maintaining) the tables.
> The SVR4 shared library tables are compact enough to easily generate
> by hand. The regset data is quite a lot larger and I would think
> you'd want to generate this data through more automatic means. (I.e,
> via a program that you'd compile and and then run on the target.)
Nothing that abstracted. I copy the necessary type definitions and
constants from target headers; they are "relatively" guaranteed never
to change. It's a mess.
There's no point abstracting it any further, I think; the SVR4 code
needs to get at shared library offsets, but only supply_gregset needs
to get at the regsets and that is already target-specific.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-20 10:09 ` Kevin Buettner
@ 2001-11-29 15:47 ` Kevin Buettner
2001-11-29 15:58 ` Andrew Cagney
2001-11-29 15:59 ` Daniel Jacobowitz
2 siblings, 0 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-29 15:47 UTC (permalink / raw)
To: Daniel Jacobowitz, Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
On Nov 29, 6:37pm, Daniel Jacobowitz wrote:
> On Thu, Nov 29, 2001 at 04:12:29PM -0700, Kevin Buettner wrote:
> > > My still-unsubmitted cross-core patches for PowerPC remove
> > > core-regset.o also, and very unpleasantly turn ppc-linux-nat.c into a
> > > target-dependant rather than native-dependant file, so that we can grub
> > > through the gregsets by hand. If you've got a better idea I'd love to
> > > hear it :) It will be made somewhat easier by the destruction of
> > > regmap[].
> >
> > I haven't seen your patches, but I imagine you have a table of
> > constants or some such that represent offsets and sizes of members in
> > the regsets? (I.e, something similar to what I did for SVR4 shared
> > library offsets.) If that's the approach, then the only real problem I
> > have with it is accurately generating (and maintaining) the tables.
> > The SVR4 shared library tables are compact enough to easily generate
> > by hand. The regset data is quite a lot larger and I would think
> > you'd want to generate this data through more automatic means. (I.e,
> > via a program that you'd compile and and then run on the target.)
>
> Nothing that abstracted. I copy the necessary type definitions and
> constants from target headers; they are "relatively" guaranteed never
> to change. It's a mess.
How does the "cross" part of it work then? Won't the sizes of the
fundamental types, struct alignment, etc. change depending upon
which host you compile it on?
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-20 10:09 ` Kevin Buettner
2001-11-29 15:47 ` Kevin Buettner
@ 2001-11-29 15:58 ` Andrew Cagney
2001-11-20 10:59 ` Andrew Cagney
2001-11-29 15:59 ` Daniel Jacobowitz
2 siblings, 1 reply; 63+ messages in thread
From: Andrew Cagney @ 2001-11-29 15:58 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Daniel Jacobowitz, Elena Zannoni, gdb-patches
>> Nothing that abstracted. I copy the necessary type definitions and
>> constants from target headers; they are "relatively" guaranteed never
>> to change. It's a mess.
>
>
> How does the "cross" part of it work then? Won't the sizes of the
> fundamental types, struct alignment, etc. change depending upon
> which host you compile it on?
Um, isn't this exactly the same problem as for shared libraries? There
the target stuff is described/coded in a host independant way.
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-20 10:09 ` Kevin Buettner
2001-11-29 15:47 ` Kevin Buettner
2001-11-29 15:58 ` Andrew Cagney
@ 2001-11-29 15:59 ` Daniel Jacobowitz
2001-11-20 11:07 ` Daniel Jacobowitz
2001-11-29 16:17 ` Andrew Cagney
2 siblings, 2 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-29 15:59 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 04:45:27PM -0700, Kevin Buettner wrote:
> On Nov 29, 6:37pm, Daniel Jacobowitz wrote:
>
> > On Thu, Nov 29, 2001 at 04:12:29PM -0700, Kevin Buettner wrote:
> > > > My still-unsubmitted cross-core patches for PowerPC remove
> > > > core-regset.o also, and very unpleasantly turn ppc-linux-nat.c into a
> > > > target-dependant rather than native-dependant file, so that we can grub
> > > > through the gregsets by hand. If you've got a better idea I'd love to
> > > > hear it :) It will be made somewhat easier by the destruction of
> > > > regmap[].
> > >
> > > I haven't seen your patches, but I imagine you have a table of
> > > constants or some such that represent offsets and sizes of members in
> > > the regsets? (I.e, something similar to what I did for SVR4 shared
> > > library offsets.) If that's the approach, then the only real problem I
> > > have with it is accurately generating (and maintaining) the tables.
> > > The SVR4 shared library tables are compact enough to easily generate
> > > by hand. The regset data is quite a lot larger and I would think
> > > you'd want to generate this data through more automatic means. (I.e,
> > > via a program that you'd compile and and then run on the target.)
> >
> > Nothing that abstracted. I copy the necessary type definitions and
> > constants from target headers; they are "relatively" guaranteed never
> > to change. It's a mess.
>
> How does the "cross" part of it work then? Won't the sizes of the
> fundamental types, struct alignment, etc. change depending upon
> which host you compile it on?
How does it work? Badly.
The types look like this right now:
+typedef unsigned char elf_greg_t[4];
+typedef unsigned char elf_fpreg_t[8];
+typedef struct {
+ unsigned char u[16];
+} __attribute((aligned(16))) __uint128_t;
+/* Altivec registers */
+typedef __uint128_t elf_vrreg_t;
Barring the GCC extension to get __uint128_t aligned, which I don't
actually need for anything, I can do what I need to with these; I use
explicitly target alignment. No platform other than (IIRC) x86 is
broken enough to require the tdep to do computation on elf_greg_t's
while fetching them.
The current version also has a _ppc_pt_regs struct which contains only
unsigned longs; but the only thing it's doing there is providing struct
user, and the only thing that cares is the kernel_u_size function, and
the only reason that's there is because it was quicker at the time for
me to copy struct user than figure out the constant :)
Arrays of arrays of unsigned char have no alignment issues.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 15:59 ` Daniel Jacobowitz
2001-11-20 11:07 ` Daniel Jacobowitz
@ 2001-11-29 16:17 ` Andrew Cagney
2001-11-20 11:17 ` Andrew Cagney
2001-11-20 17:52 ` Daniel Jacobowitz
1 sibling, 2 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-29 16:17 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kevin Buettner, Elena Zannoni, gdb-patches
>> How does the "cross" part of it work then? Won't the sizes of the
>> fundamental types, struct alignment, etc. change depending upon
>> which host you compile it on?
>
>
> How does it work? Badly.
>
> The types look like this right now:
>
> +typedef unsigned char elf_greg_t[4];
> +typedef unsigned char elf_fpreg_t[8];
> +typedef struct {
> + unsigned char u[16];
> +} __attribute((aligned(16))) __uint128_t;
> +/* Altivec registers */
> +typedef __uint128_t elf_vrreg_t;
Hmm, Kevin did have good reason to be concerned. That is wrong.
Mechanisms similar to shlib et.al. should be used.
BTW, where did this buffer layout come from?
Andrew
> Barring the GCC extension to get __uint128_t aligned, which I don't
> actually need for anything, I can do what I need to with these; I use
> explicitly target alignment. No platform other than (IIRC) x86 is
> broken enough to require the tdep to do computation on elf_greg_t's
> while fetching them.
>
> The current version also has a _ppc_pt_regs struct which contains only
> unsigned longs; but the only thing it's doing there is providing struct
> user, and the only thing that cares is the kernel_u_size function, and
> the only reason that's there is because it was quicker at the time for
> me to copy struct user than figure out the constant :)
>
> Arrays of arrays of unsigned char have no alignment issues.
>
>
>
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 15:03 ` Andrew Cagney
2001-11-20 8:54 ` Andrew Cagney
@ 2001-11-29 16:27 ` Kevin Buettner
2001-11-20 16:00 ` Kevin Buettner
` (2 more replies)
1 sibling, 3 replies; 63+ messages in thread
From: Kevin Buettner @ 2001-11-29 16:27 UTC (permalink / raw)
To: Andrew Cagney, Elena Zannoni
Cc: Kevin Buettner, Daniel Jacobowitz, gdb-patches
On Nov 29, 6:03pm, Andrew Cagney wrote:
> >> Unfortunately not. I thought the same, until I remembered about core
> > > > file debugging. That function is called by fetch_core_registers() in
> > > > core-aout.c.
> > > > Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> > > Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> > > core-regset.c instead?
> > > Whoops, yes, you are right. False alarm.
>
> So just the core code needs to have a hard-wired (non native header) way
> of unpacking Altivec registers (if they are found?)?
I'm guessing we'll end up having to add fetch_core_registers() and
company to ppc-linux-nat.c. That way neither core-regset.c nor
core-aout.c will be used for a native Linux/PPC build. (See
fetch_core_registers() in i386-linux-nat.c as an example.)
Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 16:27 ` Kevin Buettner
2001-11-20 16:00 ` Kevin Buettner
2001-11-20 16:14 ` Andrew Cagney
@ 2001-11-29 16:36 ` Elena Zannoni
2001-11-20 16:10 ` Elena Zannoni
2001-11-29 17:40 ` Daniel Jacobowitz
2 siblings, 2 replies; 63+ messages in thread
From: Elena Zannoni @ 2001-11-29 16:36 UTC (permalink / raw)
To: Kevin Buettner
Cc: Andrew Cagney, Elena Zannoni, Daniel Jacobowitz, gdb-patches
Kevin Buettner writes:
> On Nov 29, 6:03pm, Andrew Cagney wrote:
>
> > >> Unfortunately not. I thought the same, until I remembered about core
> > > > > file debugging. That function is called by fetch_core_registers() in
> > > > > core-aout.c.
> > > > > Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> > > > Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> > > > core-regset.c instead?
> > > > Whoops, yes, you are right. False alarm.
> >
> > So just the core code needs to have a hard-wired (non native header) way
> > of unpacking Altivec registers (if they are found?)?
>
> I'm guessing we'll end up having to add fetch_core_registers() and
> company to ppc-linux-nat.c. That way neither core-regset.c nor
> core-aout.c will be used for a native Linux/PPC build. (See
> fetch_core_registers() in i386-linux-nat.c as an example.)
cross core file support: is that a concern?
Side bar: there is something interesting about the way the corelow.c
file gets the registers sections from a core file. It looks for .reg
(gregs), .reg2 (fpregs), and .reg-xfp (extended-floating point x86
only(?)). Seems like I'll have to add a fetch section call for a
.reg-altivec (or whatever it will be called, it's not produced
yet). But that's in common code. I don't like it. This
get_core_registers() will have to be overwritten too, maybe.
Elena
>
> Kevin
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-20 16:14 ` Andrew Cagney
2001-11-21 3:33 ` Daniel Jacobowitz
@ 2001-11-29 16:43 ` Andrew Cagney
1 sibling, 0 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-29 16:43 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, Daniel Jacobowitz, gdb-patches
>> So just the core code needs to have a hard-wired (non native header) way
>> of unpacking Altivec registers (if they are found?)?
>
>
> I'm guessing we'll end up having to add fetch_core_registers() and
> company to ppc-linux-nat.c. That way neither core-regset.c nor
> core-aout.c will be used for a native Linux/PPC build. (See
> fetch_core_registers() in i386-linux-nat.c as an example.)
No. The core stuff would need to be kicked out of *-nat.c and into
*-core.c and/or *-greg.c and/or ??? The packing/unpacking of a reg-set
is technically only target dependant - debugging a core file from an
embedded target.
Daniel, how are the changes you were eluding to comming along?
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-20 17:52 ` Daniel Jacobowitz
@ 2001-11-29 17:39 ` Daniel Jacobowitz
2001-11-29 18:20 ` Andrew Cagney
1 sibling, 0 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-29 17:39 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 07:17:56PM -0500, Andrew Cagney wrote:
> >>How does the "cross" part of it work then? Won't the sizes of the
> >>fundamental types, struct alignment, etc. change depending upon
> >>which host you compile it on?
> >
> >
> >How does it work? Badly.
> >
> >The types look like this right now:
> >
> >+typedef unsigned char elf_greg_t[4];
> >+typedef unsigned char elf_fpreg_t[8];
> >+typedef struct {
> >+ unsigned char u[16];
> >+} __attribute((aligned(16))) __uint128_t;
> >+/* Altivec registers */
> >+typedef __uint128_t elf_vrreg_t;
>
> Hmm, Kevin did have good reason to be concerned. That is wrong.
> Mechanisms similar to shlib et.al. should be used.
What is wrong with it?
I agree that it is messy, but it is completely correct. I know of no
platform with 8-bit bytes stupid enough to do this any way other than
the way I intend.
> BTW, where did this buffer layout come from?
Eh? It's the layout of a ppc/linux elf_gregset_t.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 16:36 ` Elena Zannoni
2001-11-20 16:10 ` Elena Zannoni
@ 2001-11-29 17:40 ` Daniel Jacobowitz
2001-11-20 18:00 ` Daniel Jacobowitz
1 sibling, 1 reply; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-29 17:40 UTC (permalink / raw)
To: Elena Zannoni; +Cc: Kevin Buettner, Andrew Cagney, gdb-patches
On Thu, Nov 29, 2001 at 07:42:51PM -0500, Elena Zannoni wrote:
> Kevin Buettner writes:
> > On Nov 29, 6:03pm, Andrew Cagney wrote:
> >
> > > >> Unfortunately not. I thought the same, until I remembered about core
> > > > > > file debugging. That function is called by fetch_core_registers() in
> > > > > > core-aout.c.
> > > > > > Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> > > > > Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> > > > > core-regset.c instead?
> > > > > Whoops, yes, you are right. False alarm.
> > >
> > > So just the core code needs to have a hard-wired (non native header) way
> > > of unpacking Altivec registers (if they are found?)?
> >
> > I'm guessing we'll end up having to add fetch_core_registers() and
> > company to ppc-linux-nat.c. That way neither core-regset.c nor
> > core-aout.c will be used for a native Linux/PPC build. (See
> > fetch_core_registers() in i386-linux-nat.c as an example.)
>
> cross core file support: is that a concern?
For me, at least, it is. I should take this as motivation and finish
the cross core patches. I'm a little behind on them.
> Side bar: there is something interesting about the way the corelow.c
> file gets the registers sections from a core file. It looks for .reg
> (gregs), .reg2 (fpregs), and .reg-xfp (extended-floating point x86
> only(?)). Seems like I'll have to add a fetch section call for a
> .reg-altivec (or whatever it will be called, it's not produced
> yet). But that's in common code. I don't like it. This
> get_core_registers() will have to be overwritten too, maybe.
I'd rather make it support fetching arbitrary sections. I have the
design for this in mind already; I'll get back to you on it as soon as
I can (probably next week).
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-21 3:33 ` Daniel Jacobowitz
@ 2001-11-29 17:41 ` Daniel Jacobowitz
0 siblings, 0 replies; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-29 17:41 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 07:43:56PM -0500, Andrew Cagney wrote:
> >>So just the core code needs to have a hard-wired (non native header) way
> >>of unpacking Altivec registers (if they are found?)?
> >
> >
> >I'm guessing we'll end up having to add fetch_core_registers() and
> >company to ppc-linux-nat.c. That way neither core-regset.c nor
> >core-aout.c will be used for a native Linux/PPC build. (See
> >fetch_core_registers() in i386-linux-nat.c as an example.)
>
> No. The core stuff would need to be kicked out of *-nat.c and into
> *-core.c and/or *-greg.c and/or ??? The packing/unpacking of a reg-set
> is technically only target dependant - debugging a core file from an
> embedded target.
>
> Daniel, how are the changes you were eluding to comming along?
Back burner to C++. When I have polished off the v3 ABI stuff I'll be
back to this thread.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-20 17:52 ` Daniel Jacobowitz
2001-11-29 17:39 ` Daniel Jacobowitz
@ 2001-11-29 18:20 ` Andrew Cagney
2001-11-21 4:10 ` Andrew Cagney
2001-11-29 22:36 ` Daniel Jacobowitz
1 sibling, 2 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-11-29 18:20 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kevin Buettner, Elena Zannoni, gdb-patches
>> >
>> >
>> >How does it work? Badly.
>> >
>> >The types look like this right now:
>> >
>> >+typedef unsigned char elf_greg_t[4];
>> >+typedef unsigned char elf_fpreg_t[8];
>> >+typedef struct {
>> >+ unsigned char u[16];
>> >+} __attribute((aligned(16))) __uint128_t;
>> >+/* Altivec registers */
>> >+typedef __uint128_t elf_vrreg_t;
>
>>
>> Hmm, Kevin did have good reason to be concerned. That is wrong.
>> Mechanisms similar to shlib et.al. should be used.
>
>
> What is wrong with it?
>
> I agree that it is messy, but it is completely correct. I know of no
> platform with 8-bit bytes stupid enough to do this any way other than
> the way I intend.
Several things come to mind: the __attribute() - there are alignment
independant functions for packing/unpacking/copying stuff; the
__unint128_t is is a name in system space.
The shlib code does this by describing the actual layout using a very
thin interface (like how remote.c unpacks the g-packet) so host issues
aren't a problem (but yes, it would be a suprise to find one that didn't
have 8 bit chars).
The other way of doing this is more like C++ where it creates a ``struct
type'' to describe the structure exactly how the target sees it.
enjoy,
Andrew
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 18:20 ` Andrew Cagney
2001-11-21 4:10 ` Andrew Cagney
@ 2001-11-29 22:36 ` Daniel Jacobowitz
2001-11-21 5:56 ` Daniel Jacobowitz
1 sibling, 1 reply; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-11-29 22:36 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, Elena Zannoni, gdb-patches
On Thu, Nov 29, 2001 at 09:20:52PM -0500, Andrew Cagney wrote:
> >>>
> >>>
> >>>How does it work? Badly.
> >>>
> >>>The types look like this right now:
> >>>
> >>>+typedef unsigned char elf_greg_t[4];
> >>>+typedef unsigned char elf_fpreg_t[8];
> >>>+typedef struct {
> >>>+ unsigned char u[16];
> >>>+} __attribute((aligned(16))) __uint128_t;
> >>>+/* Altivec registers */
> >>>+typedef __uint128_t elf_vrreg_t;
> >
> >>
> >>Hmm, Kevin did have good reason to be concerned. That is wrong.
> >>Mechanisms similar to shlib et.al. should be used.
> >
> >
> >What is wrong with it?
> >
> >I agree that it is messy, but it is completely correct. I know of no
> >platform with 8-bit bytes stupid enough to do this any way other than
> >the way I intend.
>
> Several things come to mind: the __attribute() - there are alignment
> independant functions for packing/unpacking/copying stuff; the
> __unint128_t is is a name in system space.
>
> The shlib code does this by describing the actual layout using a very
> thin interface (like how remote.c unpacks the g-packet) so host issues
> aren't a problem (but yes, it would be a suprise to find one that didn't
> have 8 bit chars).
>
> The other way of doing this is more like C++ where it creates a ``struct
> type'' to describe the structure exactly how the target sees it.
The __attribute__ and __uint128_t are both, as I said further down the
message, are both unused :) The remainder of it is fine, AFAICT.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-18 14:11 ` Daniel Jacobowitz
2001-11-19 12:59 ` Andrew Cagney
2001-11-28 22:27 ` Daniel Jacobowitz
@ 2001-12-02 10:28 ` Elena Zannoni
2001-12-02 12:19 ` Andrew Cagney
2001-12-02 14:59 ` Daniel Jacobowitz
2 siblings, 2 replies; 63+ messages in thread
From: Elena Zannoni @ 2001-12-02 10:28 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
Daniel Jacobowitz writes:
> On Wed, Nov 28, 2001 at 09:15:35PM -0500, Elena Zannoni wrote:
> >
> > AltiVec registers are 32 128-bit wide registers found on the G4
> > powerpc processor family. This patch adds some initial support for
> > such registers to gdb on a linux ppc platform.
> >
> > The Altivec registers are not displayed in a normal 'info reg' command
> > output. They are shown (like fp regs) if one says 'info all' instead.
> > Furthermore I added a specific 'info power altivec' command to display
> > just the Altivec registers. (I am not sure that the word 'power' is
> > the best choice, maybe simply 'ppc' or 'powerpc' is better). This way
> > the command as just a specific powerpc info command, w/o it being a
> > generic info command avaliable on every platform.
> >
> > If there is no kernel support for ptrace to handle the AltiVec
> > registers, they will display as 0's.
>
> Wait, I knew I was forgetting something important.
>
> There is no kernel support for this feature in any public PowerPC
> kernel tree, and to my knowledge there has been no suggested patch for
> it on any of the public LinuxPPC forums. As such, the interface to it
> is still up in the air. I've discussed this with other kernel folk at
> various times, and the general consensus is that, instead of adding
> them to the user area and using PEEKUSR, someone should simply
> implement PTRACE_GETFPXREGS (perhaps just PTRACE_GETXREGS, as the FP
> does not really apply, but consistency...). We almost never want to
> fetch just one altivec register, excepting maybe VRSAVE, and GETFPXREGS
> takes negligibly more time than a single PEEKUSR call.
Hold on, I looked at the altivec.org and at the linuxppc.org mailing
lists.
There is actually a patch posted at the beginning of September to
which you replied at some stage. And this patch is similar to the one
I have used for implementing GDB altivec support.
The version of the patch I have was provided by Motorola, and they are
about to submit it publicly. The patch is virtually identical to the
one posted on linuxppc.org except for the definition of PT_VR0 which
in the latter is (errouneously) made to be aligned on 128-bits. So
for the patch I have PT_VR0 is simply PT_FPSCR + 1, not 128.
My gdb implementation works also for machines w/o altivec ptrace
support, because in that case the ptrace call just errors out and that
condition is detected (I am talking about my original patch, w/o the
changes that Kevin suggested). This was one objection to the kernel
patch that I've seen raised on the linuxppc list.
The thread subject is "AltiVec aware ptrace for Linux"
http://lists.linuxppc.org/linuxppc-dev/200109/msg00029.html
and the original postings are on
http://www.altivec.org/emailgroup
follow the email archive link at the bottom of the page (this archive
is a total pain to look through).
Elena
>
> --
> Daniel Jacobowitz Carnegie Mellon University
> MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-12-02 10:28 ` Elena Zannoni
@ 2001-12-02 12:19 ` Andrew Cagney
2001-12-02 14:59 ` Daniel Jacobowitz
1 sibling, 0 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-12-02 12:19 UTC (permalink / raw)
To: Elena Zannoni; +Cc: Daniel Jacobowitz, gdb-patches
> There is actually a patch posted at the beginning of September to
> which you replied at some stage. And this patch is similar to the one
> I have used for implementing GDB altivec support.
>
> The version of the patch I have was provided by Motorola, and they are
> about to submit it publicly. The patch is virtually identical to the
> one posted on linuxppc.org except for the definition of PT_VR0 which
> in the latter is (errouneously) made to be aligned on 128-bits. So
> for the patch I have PT_VR0 is simply PT_FPSCR + 1, not 128.
>
> My gdb implementation works also for machines w/o altivec ptrace
> support, because in that case the ptrace call just errors out and that
> condition is detected (I am talking about my original patch, w/o the
> changes that Kevin suggested). This was one objection to the kernel
> patch that I've seen raised on the linuxppc list.
>
> The thread subject is "AltiVec aware ptrace for Linux"
>
> http://lists.linuxppc.org/linuxppc-dev/200109/msg00029.html
>
> and the original postings are on
>
> http://www.altivec.org/emailgroup follow the email archive link at the bottom of the page (this archive
> is a total pain to look through).
Nah, lets be honest, the web interface SUX - reminds us how lucky we are
with sources.redhat.com :-) Adding to this, it looks like the altivec
forum list rejects posts from people not on that list. To understand
the thread, you will need to read both lists and even then there appear
to be gaps. (You also want the thread ``AltiVec aware ptrace for
Linux'' and not the thread ``AltiVec aware version of ptrace for Linux''
on that server). Arrg.
Anyway, looks like the cat is out the bag!
While the published draft extension to PT_*USER might sux, it is rapidly
turning into a (poorly defined?) defacto standard. The extension is
also definitly consistent with the current interface and, as you
indicate, and contrary to several comments, does scale to support these
rumored AltiVec2 registers that people keep refering to.
Any reason why GDB shouldn't support the draft PT_*USER now and the
proposed (but non-existant) PT_*REGS later?
enjoy,
Andrew
``The good thing about standards is that you've got so many to choose
from.''
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-12-02 10:28 ` Elena Zannoni
2001-12-02 12:19 ` Andrew Cagney
@ 2001-12-02 14:59 ` Daniel Jacobowitz
2001-12-02 22:25 ` Andrew Cagney
1 sibling, 1 reply; 63+ messages in thread
From: Daniel Jacobowitz @ 2001-12-02 14:59 UTC (permalink / raw)
To: Elena Zannoni; +Cc: gdb-patches
On Sun, Dec 02, 2001 at 01:34:16PM -0500, Elena Zannoni wrote:
> Hold on, I looked at the altivec.org and at the linuxppc.org mailing
> lists.
>
> There is actually a patch posted at the beginning of September to
> which you replied at some stage. And this patch is similar to the one
> I have used for implementing GDB altivec support.
OK, my memory failed me; I remembered someone describing it but not
that they had posted a patch. Sorry.
> The version of the patch I have was provided by Motorola, and they are
> about to submit it publicly. The patch is virtually identical to the
> one posted on linuxppc.org except for the definition of PT_VR0 which
> in the latter is (errouneously) made to be aligned on 128-bits. So
> for the patch I have PT_VR0 is simply PT_FPSCR + 1, not 128.
>
> My gdb implementation works also for machines w/o altivec ptrace
> support, because in that case the ptrace call just errors out and that
> condition is detected (I am talking about my original patch, w/o the
> changes that Kevin suggested). This was one objection to the kernel
> patch that I've seen raised on the linuxppc list.
Franz' comments completely account for mine in his reply:
http://lists.linuxppc.org/linuxppc-dev/200109/msg00045.html
No one ever answered him publicly, AFAIK. He also told me privately
that he could not contribute code easily because of his relationship
with Caltech.
If Motorola's patch is accepted, I've no objection to this going in
as-is. If Paul chooses to hold out for a different interface, of
course, I'd rather it didn't.
--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-12-02 14:59 ` Daniel Jacobowitz
@ 2001-12-02 22:25 ` Andrew Cagney
0 siblings, 0 replies; 63+ messages in thread
From: Andrew Cagney @ 2001-12-02 22:25 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Elena Zannoni, gdb-patches
> Franz' comments completely account for mine in his reply:
> http://lists.linuxppc.org/linuxppc-dev/200109/msg00045.html
>
> No one ever answered him publicly, AFAIK. He also told me privately
> that he could not contribute code easily because of his relationship
> with Caltech.
Have a careful look at the altivec.org list. There are several replies.
The contributor couldn't contribute publically to GDB but could suggest
a patch to Linux/PPC.
enjoy,
Andrew
PS: This is why GDB's mailing lists are ``open'' - they accept cross
posts from anyone that appears vaguely reasonable.
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [RFA] W.I.P. AltiVec ppc registers support.
2001-11-29 14:47 ` Daniel Jacobowitz
2001-11-20 8:37 ` Daniel Jacobowitz
2001-11-20 9:07 ` Kevin Buettner
@ 2001-12-20 10:02 ` Elena Zannoni
2 siblings, 0 replies; 63+ messages in thread
From: Elena Zannoni @ 2001-12-20 10:02 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kevin Buettner, Elena Zannoni, gdb-patches
Daniel Jacobowitz writes:
> > > Unfortunately not. I thought the same, until I remembered about core
> > > file debugging. That function is called by fetch_core_registers() in
> > > core-aout.c.
> >
> > Hmm... I wonder if Linux/PPC even needs this function in core-aout.c.
> > Daniel J. is the expert on this stuff. Daniel, doesn't Linux/PPC use
> > core-regset.c instead?
>
> I'd like to kill our use of core-aout.c. Linux/PPC never used a.out
> cores, but unfortunately core-aout.c defines register_addr () as a
> wrapper for REGISTER_U_ADDR. The last time I tried to remove
> core-aout.c from a platform I got bitten.
>
> I think, now that we are defining FETCH_INFERIOR_REGISTERS, we can do
> without it - infptrace was the only big consumer I see remaining. So
> we might be OK without using core-aout.c at all now.
Going back to this topic.... Yes, core-aout.c is not needed if we
localize the fetch registers stuff to ppc-linux-nat.c. Turns out I was
getting errors killing the REGISTER_U_ADDR macro because I hadn't
removed core-aout.o from the makefile fragment.
I am in the process of testing a patch to just do this.
I'll submit it shortly.
Elena
> My still-unsubmitted cross-core patches for PowerPC remove
> core-regset.o also, and very unpleasantly turn ppc-linux-nat.c into a
> target-dependant rather than native-dependant file, so that we can grub
> through the gregsets by hand. If you've got a better idea I'd love to
> hear it :) It will be made somewhat easier by the destruction of
> regmap[].
>
>
> --
> Daniel Jacobowitz Carnegie Mellon University
> MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 63+ messages in thread
end of thread, other threads:[~2001-12-20 18:02 UTC | newest]
Thread overview: 63+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-11-28 18:09 [RFA] W.I.P. AltiVec ppc registers support Elena Zannoni
2001-11-18 13:27 ` Elena Zannoni
2001-11-18 14:11 ` Daniel Jacobowitz
2001-11-19 12:59 ` Andrew Cagney
2001-11-29 9:04 ` Andrew Cagney
2001-11-29 13:10 ` Daniel Jacobowitz
2001-11-19 16:00 ` Daniel Jacobowitz
2001-11-29 13:34 ` Kevin Buettner
2001-11-19 16:42 ` Kevin Buettner
2001-11-29 14:11 ` Kevin Buettner
2001-11-19 22:22 ` Kevin Buettner
2001-11-29 14:27 ` Elena Zannoni
2001-11-19 23:55 ` Elena Zannoni
2001-11-28 22:27 ` Daniel Jacobowitz
2001-12-02 10:28 ` Elena Zannoni
2001-12-02 12:19 ` Andrew Cagney
2001-12-02 14:59 ` Daniel Jacobowitz
2001-12-02 22:25 ` Andrew Cagney
2001-11-28 18:33 ` Daniel Jacobowitz
2001-11-18 13:40 ` Daniel Jacobowitz
2001-11-29 10:40 ` Kevin Buettner
2001-11-19 15:15 ` Kevin Buettner
2001-11-19 18:51 ` Elena Zannoni
2001-11-29 13:53 ` Elena Zannoni
2001-11-29 14:21 ` Kevin Buettner
2001-11-19 22:53 ` Kevin Buettner
2001-11-29 14:42 ` Elena Zannoni
2001-11-20 8:37 ` Elena Zannoni
2001-11-29 15:03 ` Andrew Cagney
2001-11-20 8:54 ` Andrew Cagney
2001-11-29 16:27 ` Kevin Buettner
2001-11-20 16:00 ` Kevin Buettner
2001-11-20 16:14 ` Andrew Cagney
2001-11-21 3:33 ` Daniel Jacobowitz
2001-11-29 17:41 ` Daniel Jacobowitz
2001-11-29 16:43 ` Andrew Cagney
2001-11-29 16:36 ` Elena Zannoni
2001-11-20 16:10 ` Elena Zannoni
2001-11-29 17:40 ` Daniel Jacobowitz
2001-11-20 18:00 ` Daniel Jacobowitz
2001-11-29 14:47 ` Daniel Jacobowitz
2001-11-20 8:37 ` Daniel Jacobowitz
2001-11-20 9:07 ` Kevin Buettner
2001-11-20 9:08 ` Andrew Cagney
2001-11-29 15:33 ` Andrew Cagney
2001-11-29 15:15 ` Kevin Buettner
2001-11-29 15:38 ` Daniel Jacobowitz
2001-11-20 9:13 ` Daniel Jacobowitz
2001-11-20 10:09 ` Kevin Buettner
2001-11-29 15:47 ` Kevin Buettner
2001-11-29 15:58 ` Andrew Cagney
2001-11-20 10:59 ` Andrew Cagney
2001-11-29 15:59 ` Daniel Jacobowitz
2001-11-20 11:07 ` Daniel Jacobowitz
2001-11-29 16:17 ` Andrew Cagney
2001-11-20 11:17 ` Andrew Cagney
2001-11-20 17:52 ` Daniel Jacobowitz
2001-11-29 17:39 ` Daniel Jacobowitz
2001-11-29 18:20 ` Andrew Cagney
2001-11-21 4:10 ` Andrew Cagney
2001-11-29 22:36 ` Daniel Jacobowitz
2001-11-21 5:56 ` Daniel Jacobowitz
2001-12-20 10:02 ` Elena Zannoni
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox