[rfc][3/3] gdbserver bi-arch for ppc: enable bi-arch support

Ulrich Weigand
2008-02-08T01:11:47Z

Hello,

this patch finally enables bi-arch ppc support. It follows the same
pattern as the s390 variant by providing a ppc_arch_setup routine that
does a run-time check whether the inferior is 64-bit and installs the
appropriate init_registers_... routine.

Like on s390, adaptations to ppc_get_pc/ppc_set_pc and ppc_fill_gregset
were necessary to deal with varying register sizes.

Tested on ppc-linux and on ppc64-linux (both with -m64 and -m32) in
a native gdbserver test setup, no regressions.

Bye,
Ulrich

ChangeLog:

* configure.srv [powerpc64-*-linux*]: Add all files mentioned for
powerpc-*-linux* to srv_regobj and reg_xmlfiles.
* linux-ppc-low.c (ppc_get_pc): Support bi-arch operation.
(ppc_set_pc): Likewise.
(ppc_arch_setup): New function.
(ppc_fill_gregset): Call ppc_collect_ptrace_register instead
of collect_register.
(the_low_target): Use ppc_arch_setup as arch_setup initializer.

diff -urNp gdb-orig/gdb/gdbserver/configure.srv gdb-head/gdb/gdbserver/configure.srv
--- gdb-orig/gdb/gdbserver/configure.srv 2008-02-07 23:55:15.932772349 +0100
+++ gdb-head/gdb/gdbserver/configure.srv 2008-02-07 22:06:35.448385574 +0100
@@ -106,12 +106,17 @@ case "${target}" in
srv_linux_usrregs=yes
srv_linux_thread_db=yes
;;
- powerpc64-*-linux*) srv_regobj="reg-ppc64.o powerpc-64.o"
+ powerpc64-*-linux*) srv_regobj="reg-ppc.o powerpc-32.o powerpc-e500.o"
+ srv_regobj="${srv_regobj} reg-ppc64.o powerpc-64.o"
srv_tgtobj="linux-low.o linux-ppc-low.o"
- srv_xmlfiles="rs6000/powerpc-64.xml"
+ srv_xmlfiles="rs6000/powerpc-32.xml"
srv_xmlfiles="${srv_xmlfiles} rs6000/power-altivec.xml"
- srv_xmlfiles="${srv_xmlfiles} rs6000/power64-core.xml"
+ srv_xmlfiles="${srv_xmlfiles} rs6000/power-core.xml"
srv_xmlfiles="${srv_xmlfiles} rs6000/power-fpu.xml"
+ srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-e500.xml"
+ srv_xmlfiles="${srv_xmlfiles} rs6000/power-spe.xml"
+ srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-64.xml"
+ srv_xmlfiles="${srv_xmlfiles} rs6000/power64-core.xml"
srv_linux_usrregs=yes
srv_linux_regsets=yes
srv_linux_thread_db=yes
diff -urNp gdb-orig/gdb/gdbserver/linux-ppc-low.c gdb-head/gdb/gdbserver/linux-ppc-low.c
--- gdb-orig/gdb/gdbserver/linux-ppc-low.c 2008-02-07 23:55:15.940771196 +0100
+++ gdb-head/gdb/gdbserver/linux-ppc-low.c 2008-02-07 23:56:26.898314713 +0100
@@ -138,18 +138,69 @@ ppc_supply_ptrace_register (int regno, c
static CORE_ADDR
ppc_get_pc (void)
{
- unsigned long pc;
-
- collect_register_by_name ("pc", &pc);
- return (CORE_ADDR) pc;
+ if (register_size (0) == 4)
+ {
+ unsigned int pc;
+ collect_register_by_name ("pc", &pc);
+ return (CORE_ADDR) pc;
+ }
+ else
+ {
+ unsigned long pc;
+ collect_register_by_name ("pc", &pc);
+ return (CORE_ADDR) pc;
+ }
}

static void
ppc_set_pc (CORE_ADDR pc)
{
- unsigned long newpc = pc;
+ if (register_size (0) == 4)
+ {
+ unsigned int newpc = pc;
+ supply_register_by_name ("pc", &newpc);
+ }
+ else
+ {
+ unsigned long newpc = pc;
+ supply_register_by_name ("pc", &newpc);
+ }
+}

- supply_register_by_name ("pc", &newpc);
+static void
+ppc_arch_setup (void)
+{
+#ifdef __powerpc64__
+ long msr;
+
+ /* On a 64-bit host, assume 64-bit inferior process. */
+#ifdef __ALTIVEC__
+ init_registers_powerpc_64 ();
+#else
+ init_registers_ppc64 ();
+#endif
+
+ /* Only if the high bit of the MSR is set, we actually have
+ a 64-bit inferior. */
+#ifdef __ALTIVEC__
+ collect_register_by_name ("msr", &msr);
+#else
+ collect_register_by_name ("ps", &msr);
+#endif
+ if (msr < 0)
+ return;
+#endif
+
+ /* OK, we have a 32-bit inferior. */
+#ifdef __ALTIVEC__
+ init_registers_powerpc_32 ();
+#else
+#ifdef __SPE__
+ init_registers_powerpc_e500 ();
+#else
+ init_registers_ppc ();
+#endif
+#endif
}

/* Correct in either endianness.
@@ -179,10 +230,10 @@ static void ppc_fill_gregset (void *buf)
int i;

for (i = 0; i < 32; i++)
- collect_register (i, (char *) buf + ppc_regmap[i]);
+ ppc_collect_ptrace_register (i, (char *) buf + ppc_regmap[i]);

for (i = 64; i < 70; i++)
- collect_register (i, (char *) buf + ppc_regmap[i]);
+ ppc_collect_ptrace_register (i, (char *) buf + ppc_regmap[i]);
}

#ifdef __ALTIVEC__
@@ -285,23 +336,7 @@ struct regset_info target_regsets[] = {
};

struct linux_target_ops the_low_target = {
-#ifdef __powerpc64__
-#ifdef __ALTIVEC__
- init_registers_powerpc_64,
-#else
- init_registers_ppc64,
-#endif
-#else
-#ifdef __ALTIVEC__
- init_registers_powerpc_32,
-#else
-#ifdef __SPE__
- init_registers_powerpc_e500,
-#else
- init_registers_ppc,
-#endif
-#endif
-#endif
+ ppc_arch_setup,
ppc_num_regs,
ppc_regmap,
ppc_cannot_fetch_register,
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com