This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[rfc] Fix inferior calls during interrupted system calls on PowerPC


Hello,

PowerPC still suffers from a problem that was fixed on other
platforms a while ago: if GDB wants to perform an inferior
call while the inferior is blocked in an (interrupted) system
call, the Linux kernel gets confused.

With recent kernel versions (>= 2.6.23 I think), it is possible
to correctly handle this situation using a similar approach to
what is currently done on i386: there, GDB informs the kernel
that it wants to do an inferior call by writing to the "special"
ORIG_EAX register -- this causes the kernel to not attempt to
"restart" the system call.  After the inferior call is finished,
the original contents of ORIG_EAX are restored.

On PowerPC, the same mechanism is possible, except that there
are two registers that need to be restored, ORIG_R3 and TRAP.
When initiating an inferior call, only TRAP has to be reset.

The patch below implements this by adding two new registers,
ORIG_R3 and TRAP to the PowerPC Linux register sets.  As these
are only available on Linux, I've added two new XML features
powerpc-linux32 and powerpc-linux64 that include these new
registers.

Native code in ppc-linux-nat.c will register that it supports
those by returning the appropriate feature from ppc_linux_read_description.

Similarly, the new ppc_linux_core_read_description routine will
handle Linux core files.

gdbserver is switched to always use powerpc-linux32/64 instead
of powerpc-32/64.  This still leaves the new registers out on
any non-AltiVec platforms.  I guess for powerpc-e500 we could
create a similar powerpc-linuxe500 feature, if this is required.
I'm not sure how to handle the default (non-AltiVec, non-SPE)
case which does not yet use XML.  Simply adding registers to 
the .dat files is probably not a good idea as it might break
old GDBs that connect to the new gdbserver ...

Any suggestion how we should handle that?  Any other comments
on this approach are welcome ...

Note that the patch below assumes that the AltiVec auto-detection
patch is already applied.

Tested on powerpc-linux and powerpc64-linux, both natively and
using a local gdbserver.  Fixes all interrupt.exp failures.

Bye,
Ulrich


ChangeLog:

	* ppc-tdep.h (struct ppc_reg_offsets): New members
	orig_r3_offset and trap_offset.
	(struct gdbarch_tdep): New members ppc_orig_r3_regnum
	and ppc_trap_regnum.
	(PPC_ORIG_R3_REGNUM, PPC_TRAP_REGNUM): New enum members.
	(tdesc_powerpc_linux32, tdesc_powerpc_linux64): Declare.

	* rs6000-tdep.c: Include features/rs6000/powerpc-linux32.c
	and features/rs6000/powerpc-linux64.c.
	(ppc_greg_offset): Handle orig_r3 and trap.
	(ppc_supply_gregset, ppu_collect_gregset): Likewise.
	(rs6000_gdbarch_init): Handle org.gnu.gdb.power.linux feature.
	Set up ppc_orig_r3_regnum and ppc_trap_regnum tdep entries.
	(_initialize_rs6000_tdep): Call initialize_tdesc_powerpc_linux32
	and initialize_tdesc_powerpc_linux64
	
	* ppc-linux-tdep.c (ppc32_linux_reg_offsets): Initialize
	orig_r3_offset and trap_offset fields.
	(ppc64_linux_reg_offsets): Likewise.
	(ppc_linux_write_pc): New function.
	(ppc_linux_core_read_description): New function.
	(ppc_linux_init_abi): Install them.

	* ppcnbsd-tdep.c (_initialize_ppcnbsd_tdep): Initialize
	ppcnbsd_reg_offsets.orig_r3_offset and
	ppcnbsd_reg_offsets.trap_offset.
	* ppcobsd-tdep.c (_initialize_ppcobsd_tdep): Initialize
	ppcobsd_reg_offsets.orig_r3_offset and
	ppcobsd_reg_offsets.trap_offset.
	* rs6000-aix-tdep.c (rs6000_aix32_reg_offsets): Initialize
	orig_r3_offset and trap_offset fields.
	(rs6000_aix64_reg_offsets): Likewise.

	* ppc-linux-nat.c (PT_ORIG_R3, PT_TRAP): Define if necessary.
	(ppc_register_u_addr): Handle orig_r3 and trap.
	(fetch_ppc_registers, store_ppc_registers, store_register): Likewise.
	(ppc_linux_read_description): Return tdesc_powerpc_linux32 or
	tdesc_powerpc_linux64 as appropriate.

	* features/Makefile (WHICH): Use rs6000/powerpc-linux32 instead
	of rs6000/powerpc-32 and rs6000/powerpc-linux64 instead of
	rs6000/powerpc-64.  Update -expedite variables accordingly.

	* features/rs6000/powerpc-linux32.xml: New file.
	* features/rs6000/powerpc-linux64.xml: New file.
	* features/rs6000/powerpc-linux32.c: New (generated) file.
	* features/rs6000/powerpc-linux64.c: New (generated) file.

	* regformats/rs6000/powerpc-32.dat: Remove.
	* regformats/rs6000/powerpc-64.dat: Remove.
	* regformats/rs6000/powerpc-linux32.dat: New (generated) file.
	* regformats/rs6000/powerpc-linux64.dat: New (generated) file.
	

gdbserver/ChangeLog:

	* Makefile.in: Replace powerpc-32 by powerpc-linux32 and 
	powerpc-64 by powerpc-linux64 throughout.
	* configure.srv: Likewise.

	* linux-ppc-low.c (init_registers_powerpc_32): Replace by ...
	(init_registers_powerpc_linux32): ... this new declaration.
	(init_registers_powerpc_64): Replace by ...
	(init_registers_powerpc_linux64): ... this new declaration.
	(ppc_linux_num_regs): New define.
	(PT_ORIG_R3, PT_TRAP): Define if necessary.
	(ppc_regmap, ppc_regmap_e500): Add values for orig_r3 and trap.
	(ppc_cannot_store_register): Handle orig_r3 and trap.
	(ppc_arch_setup): Update init_registers_... calls.  Re-set
	the_low_target.num_regs to the appropriate value for the
	register set that is installed.
	(ppc_fill_gregset): Handle orig_r3 and trap.


diff -urNp gdb-orig/gdb/features/Makefile gdb-head/gdb/features/Makefile
--- gdb-orig/gdb/features/Makefile	2008-03-27 00:52:45.999423395 +0100
+++ gdb-head/gdb/features/Makefile	2008-03-27 00:05:36.388145909 +0100
@@ -32,15 +32,15 @@
 #   make GDB=/path/to/gdb XMLTOC="xml files" cfiles
 
 WHICH = arm-with-iwmmxt mips-linux mips64-linux \
-	rs6000/powerpc-32 rs6000/powerpc-e500 rs6000/powerpc-64
+	rs6000/powerpc-linux32 rs6000/powerpc-e500 rs6000/powerpc-linux64
 
 # Record which registers should be sent to GDB by default after stop.
 arm-with-iwmmxt-expedite = r11,sp,pc
 mips-linux-expedite = r29,pc
 mips64-linux-expedite = r29,pc
-rs6000/powerpc-32-expedite = r1,pc
+rs6000/powerpc-linux32-expedite = r1,pc
 rs6000/powerpc-e500-expedite = r1,pc
-rs6000/powerpc-64-expedite = r1,pc
+rs6000/powerpc-linux64-expedite = r1,pc
 
 XSLTPROC = xsltproc
 outdir = ../regformats
diff -urNp gdb-orig/gdb/features/rs6000/powerpc-linux32.c gdb-head/gdb/features/rs6000/powerpc-linux32.c
--- gdb-orig/gdb/features/rs6000/powerpc-linux32.c	1970-01-01 01:00:00.000000000 +0100
+++ gdb-head/gdb/features/rs6000/powerpc-linux32.c	2008-03-27 00:05:36.394145047 +0100
@@ -0,0 +1,168 @@
+/* THIS FILE IS GENERATED.  Original: powerpc-linux32.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_powerpc_linux32;
+static void
+initialize_tdesc_powerpc_linux32 (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "pc", 64, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "msr", 65, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "cr", 66, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "lr", 67, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "ctr", 68, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "xer", 69, 1, NULL, 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.fpu");
+  tdesc_create_reg (feature, "f0", 32, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 33, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 34, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 35, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 36, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 37, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 38, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f16", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f17", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f18", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f19", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f20", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f21", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f22", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f23", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f24", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f25", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f26", 58, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f27", 59, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f28", 60, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f29", 61, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f30", 62, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f31", 63, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fpscr", 70, 1, "float", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux");
+  tdesc_create_reg (feature, "orig_r3", 71, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "trap", 72, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.altivec");
+  field_type = tdesc_named_type (feature, "ieee_single");
+  type = init_vector_type (field_type, 4);
+  TYPE_NAME (type) = xstrdup ("v4f");
+  tdesc_record_type (feature, type);
+
+  field_type = tdesc_named_type (feature, "int32");
+  type = init_vector_type (field_type, 4);
+  TYPE_NAME (type) = xstrdup ("v4i32");
+  tdesc_record_type (feature, type);
+
+  field_type = tdesc_named_type (feature, "int16");
+  type = init_vector_type (field_type, 8);
+  TYPE_NAME (type) = xstrdup ("v8i16");
+  tdesc_record_type (feature, type);
+
+  field_type = tdesc_named_type (feature, "int8");
+  type = init_vector_type (field_type, 16);
+  TYPE_NAME (type) = xstrdup ("v16i8");
+  tdesc_record_type (feature, type);
+
+  type = init_composite_type (NULL, TYPE_CODE_UNION);
+  TYPE_NAME (type) = xstrdup ("vec128");
+  field_type = tdesc_named_type (feature, "uint128");
+  append_composite_type_field (type, xstrdup ("uint128"), field_type);
+  field_type = tdesc_named_type (feature, "v4f");
+  append_composite_type_field (type, xstrdup ("v4_float"), field_type);
+  field_type = tdesc_named_type (feature, "v4i32");
+  append_composite_type_field (type, xstrdup ("v4_int32"), field_type);
+  field_type = tdesc_named_type (feature, "v8i16");
+  append_composite_type_field (type, xstrdup ("v8_int16"), field_type);
+  field_type = tdesc_named_type (feature, "v16i8");
+  append_composite_type_field (type, xstrdup ("v16_int8"), field_type);
+  TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
+  tdesc_record_type (feature, type);
+
+  tdesc_create_reg (feature, "vr0", 73, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr1", 74, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr2", 75, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr3", 76, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr4", 77, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr5", 78, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr6", 79, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr7", 80, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr8", 81, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr9", 82, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr10", 83, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr11", 84, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr12", 85, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr13", 86, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr14", 87, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr15", 88, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr16", 89, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr17", 90, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr18", 91, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr19", 92, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr20", 93, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr21", 94, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr22", 95, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr23", 96, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr24", 97, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr25", 98, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr26", 99, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr27", 100, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr28", 101, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr29", 102, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr30", 103, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr31", 104, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vscr", 105, 1, "vector", 32, "int");
+  tdesc_create_reg (feature, "vrsave", 106, 1, "vector", 32, "int");
+
+  tdesc_powerpc_linux32 = result;
+}
diff -urNp gdb-orig/gdb/features/rs6000/powerpc-linux32.xml gdb-head/gdb/features/rs6000/powerpc-linux32.xml
--- gdb-orig/gdb/features/rs6000/powerpc-linux32.xml	1970-01-01 01:00:00.000000000 +0100
+++ gdb-head/gdb/features/rs6000/powerpc-linux32.xml	2008-03-27 00:05:36.397144616 +0100
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!-- PowerPC UISA - a PPC processor as viewed by user-level code.  A UISA-only
+     view of the PowerPC.  Includes Linux-only special "registers".  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>powerpc:common</architecture>
+  <xi:include href="power-core.xml"/>
+  <xi:include href="power-fpu.xml"/>
+  <feature name="org.gnu.gdb.power.linux">
+    <reg name="orig_r3" bitsize="32"/>
+    <reg name="trap" bitsize="32"/>
+  </feature>
+  <xi:include href="power-altivec.xml"/>
+</target>
diff -urNp gdb-orig/gdb/features/rs6000/powerpc-linux64.c gdb-head/gdb/features/rs6000/powerpc-linux64.c
--- gdb-orig/gdb/features/rs6000/powerpc-linux64.c	1970-01-01 01:00:00.000000000 +0100
+++ gdb-head/gdb/features/rs6000/powerpc-linux64.c	2008-03-27 00:05:36.403143754 +0100
@@ -0,0 +1,168 @@
+/* THIS FILE IS GENERATED.  Original: powerpc-linux64.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_powerpc_linux64;
+static void
+initialize_tdesc_powerpc_linux64 (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "pc", 64, 1, NULL, 64, "code_ptr");
+  tdesc_create_reg (feature, "msr", 65, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "cr", 66, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "lr", 67, 1, NULL, 64, "code_ptr");
+  tdesc_create_reg (feature, "ctr", 68, 1, NULL, 64, "uint64");
+  tdesc_create_reg (feature, "xer", 69, 1, NULL, 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.fpu");
+  tdesc_create_reg (feature, "f0", 32, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 33, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 34, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 35, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 36, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 37, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 38, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f16", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f17", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f18", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f19", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f20", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f21", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f22", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f23", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f24", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f25", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f26", 58, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f27", 59, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f28", 60, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f29", 61, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f30", 62, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f31", 63, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fpscr", 70, 1, "float", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux");
+  tdesc_create_reg (feature, "orig_r3", 71, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "trap", 72, 1, NULL, 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.altivec");
+  field_type = tdesc_named_type (feature, "ieee_single");
+  type = init_vector_type (field_type, 4);
+  TYPE_NAME (type) = xstrdup ("v4f");
+  tdesc_record_type (feature, type);
+
+  field_type = tdesc_named_type (feature, "int32");
+  type = init_vector_type (field_type, 4);
+  TYPE_NAME (type) = xstrdup ("v4i32");
+  tdesc_record_type (feature, type);
+
+  field_type = tdesc_named_type (feature, "int16");
+  type = init_vector_type (field_type, 8);
+  TYPE_NAME (type) = xstrdup ("v8i16");
+  tdesc_record_type (feature, type);
+
+  field_type = tdesc_named_type (feature, "int8");
+  type = init_vector_type (field_type, 16);
+  TYPE_NAME (type) = xstrdup ("v16i8");
+  tdesc_record_type (feature, type);
+
+  type = init_composite_type (NULL, TYPE_CODE_UNION);
+  TYPE_NAME (type) = xstrdup ("vec128");
+  field_type = tdesc_named_type (feature, "uint128");
+  append_composite_type_field (type, xstrdup ("uint128"), field_type);
+  field_type = tdesc_named_type (feature, "v4f");
+  append_composite_type_field (type, xstrdup ("v4_float"), field_type);
+  field_type = tdesc_named_type (feature, "v4i32");
+  append_composite_type_field (type, xstrdup ("v4_int32"), field_type);
+  field_type = tdesc_named_type (feature, "v8i16");
+  append_composite_type_field (type, xstrdup ("v8_int16"), field_type);
+  field_type = tdesc_named_type (feature, "v16i8");
+  append_composite_type_field (type, xstrdup ("v16_int8"), field_type);
+  TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
+  tdesc_record_type (feature, type);
+
+  tdesc_create_reg (feature, "vr0", 73, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr1", 74, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr2", 75, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr3", 76, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr4", 77, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr5", 78, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr6", 79, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr7", 80, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr8", 81, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr9", 82, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr10", 83, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr11", 84, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr12", 85, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr13", 86, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr14", 87, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr15", 88, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr16", 89, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr17", 90, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr18", 91, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr19", 92, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr20", 93, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr21", 94, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr22", 95, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr23", 96, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr24", 97, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr25", 98, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr26", 99, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr27", 100, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr28", 101, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr29", 102, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr30", 103, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vr31", 104, 1, NULL, 128, "vec128");
+  tdesc_create_reg (feature, "vscr", 105, 1, "vector", 32, "int");
+  tdesc_create_reg (feature, "vrsave", 106, 1, "vector", 32, "int");
+
+  tdesc_powerpc_linux64 = result;
+}
diff -urNp gdb-orig/gdb/features/rs6000/powerpc-linux64.xml gdb-head/gdb/features/rs6000/powerpc-linux64.xml
--- gdb-orig/gdb/features/rs6000/powerpc-linux64.xml	1970-01-01 01:00:00.000000000 +0100
+++ gdb-head/gdb/features/rs6000/powerpc-linux64.xml	2008-03-27 00:05:36.407143180 +0100
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!-- PowerPC UISA - a PPC processor as viewed by user-level code.  A UISA-only
+     view of the PowerPC.  Includes Linux-only special "registers".   -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>powerpc:common64</architecture>
+  <xi:include href="power64-core.xml"/>
+  <xi:include href="power-fpu.xml"/>
+  <feature name="org.gnu.gdb.power.linux">
+    <reg name="orig_r3" bitsize="64"/>
+    <reg name="trap" bitsize="64"/>
+  </feature>
+  <xi:include href="power-altivec.xml"/>
+</target>
diff -urNp gdb-orig/gdb/gdbserver/configure.srv gdb-head/gdb/gdbserver/configure.srv
--- gdb-orig/gdb/gdbserver/configure.srv	2008-03-27 00:52:46.033418513 +0100
+++ gdb-head/gdb/gdbserver/configure.srv	2008-03-27 00:05:36.411142605 +0100
@@ -106,22 +106,22 @@ case "${target}" in
 			srv_linux_usrregs=yes
 			srv_linux_thread_db=yes
 			;;
-  powerpc64-*-linux*)	srv_regobj="reg-ppc.o powerpc-32.o"
-			srv_regobj="${srv_regobj} reg-ppc64.o powerpc-64.o"
+  powerpc64-*-linux*)	srv_regobj="reg-ppc.o powerpc-linux32.o"
+			srv_regobj="${srv_regobj} reg-ppc64.o powerpc-linux64.o"
 			srv_tgtobj="linux-low.o linux-ppc-low.o"
-			srv_xmlfiles="rs6000/powerpc-32.xml"
+			srv_xmlfiles="rs6000/powerpc-linux32.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/power-altivec.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/power-core.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/power-fpu.xml"
-			srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-64.xml"
+			srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-linux64.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/power64-core.xml"
 			srv_linux_usrregs=yes
 			srv_linux_regsets=yes
 			srv_linux_thread_db=yes
 			;;
-  powerpc-*-linux*)	srv_regobj="reg-ppc.o powerpc-32.o powerpc-e500.o"
+  powerpc-*-linux*)	srv_regobj="reg-ppc.o powerpc-linux32.o powerpc-e500.o"
 			srv_tgtobj="linux-low.o linux-ppc-low.o"
-			srv_xmlfiles="rs6000/powerpc-32.xml"
+			srv_xmlfiles="rs6000/powerpc-linux32.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/power-altivec.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/power-core.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/power-fpu.xml"
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-03-27 00:52:46.038417795 +0100
+++ gdb-head/gdb/gdbserver/linux-ppc-low.c	2008-03-27 01:09:50.319804230 +0100
@@ -33,16 +33,25 @@ static unsigned long ppc_hwcap;
 
 /* Defined in auto-generated file reg-ppc.c.  */
 void init_registers_ppc (void);
-/* Defined in auto-generated file powerpc-32.c.  */
-void init_registers_powerpc_32 (void);
+/* Defined in auto-generated file powerpc-linux32.c.  */
+void init_registers_powerpc_linux32 (void);
 /* Defined in auto-generated file powerpc-e500.c.  */
 void init_registers_powerpc_e500 (void);
 /* Defined in auto-generated file reg-ppc64.c.  */
 void init_registers_ppc64 (void);
-/* Defined in auto-generated file powerpc-64.c.  */
-void init_registers_powerpc_64 (void);
+/* Defined in auto-generated file powerpc-linux64.c.  */
+void init_registers_powerpc_linux64 (void);
 
 #define ppc_num_regs 71
+#define ppc_linux_num_regs 73
+
+/* This sometimes isn't defined.  */
+#ifndef PT_ORIG_R3
+#define PT_ORIG_R3 34
+#endif
+#ifndef PT_TRAP
+#define PT_TRAP 40
+#endif
 
 #ifdef __powerpc64__
 /* We use a constant for FPSCR instead of PT_FPSCR, because
@@ -65,7 +74,9 @@ static int ppc_regmap[] =
   PT_FPR0*8+192,  PT_FPR0*8+200,  PT_FPR0*8+208,  PT_FPR0*8+216,
   PT_FPR0*8+224,  PT_FPR0*8+232,  PT_FPR0*8+240,  PT_FPR0*8+248,
   PT_NIP * 8,    PT_MSR * 8,    PT_CCR * 8,    PT_LNK * 8,
-  PT_CTR * 8,    PT_XER * 8,    PT_FPR0*8 + 256 };
+  PT_CTR * 8,    PT_XER * 8,    PT_FPR0*8 + 256,
+  PT_ORIG_R3 * 8, PT_TRAP * 8
+ };
 #else
 /* Currently, don't check/send MQ.  */
 static int ppc_regmap[] =
@@ -86,7 +97,8 @@ static int ppc_regmap[] =
   PT_FPR0*4+192,  PT_FPR0*4+200,  PT_FPR0*4+208,  PT_FPR0*4+216,
   PT_FPR0*4+224,  PT_FPR0*4+232,  PT_FPR0*4+240,  PT_FPR0*4+248,
   PT_NIP * 4,    PT_MSR * 4,    PT_CCR * 4,    PT_LNK * 4,
-  PT_CTR * 4,    PT_XER * 4,    PT_FPSCR * 4
+  PT_CTR * 4,    PT_XER * 4,    PT_FPSCR * 4,
+  PT_ORIG_R3 * 4, PT_TRAP * 4
  };
 
 static int ppc_regmap_e500[] =
@@ -107,7 +119,8 @@ static int ppc_regmap_e500[] =
   -1,            -1,            -1,            -1,
   -1,            -1,            -1,            -1,
   PT_NIP * 4,    PT_MSR * 4,    PT_CCR * 4,    PT_LNK * 4,
-  PT_CTR * 4,    PT_XER * 4,    -1
+  PT_CTR * 4,    PT_XER * 4,    -1,
+  PT_ORIG_R3 * 4, PT_TRAP * 4
  };
 #endif
 
@@ -120,6 +133,11 @@ ppc_cannot_store_register (int regno)
     return 2;
 #endif
 
+  /* Some kernels do not allow us to store orig_r3 or trap.  */
+  if (regno == find_regno ("orig_r3")
+      || regno == find_regno ("trap"))
+    return 2;
+
   return 0;
 }
 
@@ -227,6 +245,7 @@ ppc_arch_setup (void)
      AltiVec registers.  This is required to make sure the
      collect_register call below does not fail.  */
   init_registers_ppc64 ();
+  the_low_target.num_regs = ppc_num_regs;
   ppc_hwcap = 0;
 
   /* Only if the high bit of the MSR is set, we actually have
@@ -236,7 +255,10 @@ ppc_arch_setup (void)
     {
       ppc_get_hwcap (&ppc_hwcap);
       if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
-	init_registers_powerpc_64 ();
+	{
+	  init_registers_powerpc_linux64 ();
+	  the_low_target.num_regs = ppc_linux_num_regs;
+	}
 
       return;
     }
@@ -244,10 +266,14 @@ ppc_arch_setup (void)
 
   /* OK, we have a 32-bit inferior.  */
   init_registers_ppc ();
+  the_low_target.num_regs = ppc_num_regs;
 
   ppc_get_hwcap (&ppc_hwcap);
   if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
-    init_registers_powerpc_32 ();
+    {
+      init_registers_powerpc_linux32 ();
+      the_low_target.num_regs = ppc_linux_num_regs;
+    }
 
   /* On 32-bit machines, check for SPE registers.
      Set the low target's regmap field as appropriately.  */
@@ -292,6 +318,9 @@ static void ppc_fill_gregset (void *buf)
 
   for (i = 64; i < 70; i++)
     ppc_collect_ptrace_register (i, (char *) buf + ppc_regmap[i]);
+
+  for (i = 71; i < 73; i++)
+    ppc_collect_ptrace_register (i, (char *) buf + ppc_regmap[i]);
 }
 
 #ifndef PTRACE_GETVRREGS
diff -urNp gdb-orig/gdb/gdbserver/Makefile.in gdb-head/gdb/gdbserver/Makefile.in
--- gdb-orig/gdb/gdbserver/Makefile.in	2008-03-27 00:52:46.044416934 +0100
+++ gdb-head/gdb/gdbserver/Makefile.in	2008-03-27 00:05:36.421141169 +0100
@@ -220,7 +220,7 @@ clean:
 	rm -f reg-ppc.c reg-sh.c reg-spu.c reg-x86-64.c reg-i386-linux.c
 	rm -f reg-cris.c reg-crisv32.c reg-x86-64-linux.c reg-xtensa.c
 	rm -f arm-with-iwmmxt.c mips-linux.c mips64-linux.c
-	rm -f powerpc-32.c powerpc-64.c powerpc-e500.c
+	rm -f powerpc-linux32.c powerpc-linux64.c powerpc-e500.c
 	rm -f xml-builtin.c stamp-xml
 
 maintainer-clean realclean distclean: clean
@@ -361,15 +361,15 @@ reg-ppc.c : $(srcdir)/../regformats/reg-
 reg-ppc64.o : reg-ppc64.c $(regdef_h)
 reg-ppc64.c : $(srcdir)/../regformats/reg-ppc64.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-ppc64.dat reg-ppc64.c
-powerpc-32.o : powerpc-32.c $(regdef_h)
-powerpc-32.c : $(srcdir)/../regformats/rs6000/powerpc-32.dat $(regdat_sh)
-	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-32.dat powerpc-32.c
+powerpc-linux32.o : powerpc-linux32.c $(regdef_h)
+powerpc-linux32.c : $(srcdir)/../regformats/rs6000/powerpc-linux32.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-linux32.dat powerpc-linux32.c
 powerpc-e500.o : powerpc-e500.c $(regdef_h)
 powerpc-e500.c : $(srcdir)/../regformats/rs6000/powerpc-e500.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-e500.dat powerpc-e500.c
-powerpc-64.o : powerpc-64.c $(regdef_h)
-powerpc-64.c : $(srcdir)/../regformats/rs6000/powerpc-64.dat $(regdat_sh)
-	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-64.dat powerpc-64.c
+powerpc-linux64.o : powerpc-linux64.c $(regdef_h)
+powerpc-linux64.c : $(srcdir)/../regformats/rs6000/powerpc-linux64.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-linux64.dat powerpc-linux64.c
 reg-s390.o : reg-s390.c $(regdef_h)
 reg-s390.c : $(srcdir)/../regformats/reg-s390.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-s390.dat reg-s390.c
diff -urNp gdb-orig/gdb/ppc-linux-nat.c gdb-head/gdb/ppc-linux-nat.c
--- gdb-orig/gdb/ppc-linux-nat.c	2008-03-27 00:52:46.050416072 +0100
+++ gdb-head/gdb/ppc-linux-nat.c	2008-03-27 00:05:36.427140307 +0100
@@ -43,6 +43,14 @@
 #include "gregset.h"
 #include "ppc-tdep.h"
 
+/* This sometimes isn't defined.  */
+#ifndef PT_ORIG_R3
+#define PT_ORIG_R3 34
+#endif
+#ifndef PT_TRAP
+#define PT_TRAP 40
+#endif
+
 /* Glibc's headers don't define PTRACE_GETVRREGS so we cannot use a
    configure time check.  Some older glibc's (for instance 2.2.1)
    don't have a specific powerpc version of ptrace.h, and fall back on
@@ -200,6 +208,10 @@ ppc_register_u_addr (struct gdbarch *gdb
 #endif
   if (regno == tdep->ppc_ps_regnum)
     u_addr = PT_MSR * wordsize;
+  if (regno == tdep->ppc_orig_r3_regnum)
+    u_addr = PT_ORIG_R3 * wordsize;
+  if (regno == tdep->ppc_trap_regnum)
+    u_addr = PT_TRAP * wordsize;
   if (tdep->ppc_fpscr_regnum >= 0
       && regno == tdep->ppc_fpscr_regnum)
     {
@@ -476,6 +488,10 @@ fetch_ppc_registers (struct regcache *re
     fetch_register (regcache, tid, tdep->ppc_xer_regnum);
   if (tdep->ppc_mq_regnum != -1)
     fetch_register (regcache, tid, tdep->ppc_mq_regnum);
+  if (tdep->ppc_orig_r3_regnum != -1)
+    fetch_register (regcache, tid, tdep->ppc_orig_r3_regnum);
+  if (tdep->ppc_trap_regnum != -1)
+    fetch_register (regcache, tid, tdep->ppc_trap_regnum);
   if (tdep->ppc_fpscr_regnum != -1)
     fetch_register (regcache, tid, tdep->ppc_fpscr_regnum);
   if (have_ptrace_getvrregs)
@@ -676,9 +692,12 @@ store_register (const struct regcache *r
       regaddr += sizeof (long);
 
       if (errno == EIO 
-          && regno == tdep->ppc_fpscr_regnum)
+          && (regno == tdep->ppc_fpscr_regnum
+	      || regno == tdep->ppc_orig_r3_regnum
+	      || regno == tdep->ppc_trap_regnum))
 	{
-	  /* Some older kernel versions don't allow fpscr to be written.  */
+	  /* Some older kernel versions don't allow fpscr, orig_r3
+	     or trap to be written.  */
 	  continue;
 	}
 
@@ -763,6 +782,10 @@ store_ppc_registers (const struct regcac
     store_register (regcache, tid, tdep->ppc_xer_regnum);
   if (tdep->ppc_mq_regnum != -1)
     store_register (regcache, tid, tdep->ppc_mq_regnum);
+  if (tdep->ppc_orig_r3_regnum != -1)
+    store_register (regcache, tid, tdep->ppc_orig_r3_regnum);
+  if (tdep->ppc_trap_regnum != -1)
+    store_register (regcache, tid, tdep->ppc_trap_regnum);
   if (tdep->ppc_fpscr_regnum != -1)
     store_register (regcache, tid, tdep->ppc_fpscr_regnum);
   if (have_ptrace_getvrregs)
@@ -964,16 +987,31 @@ ppc_linux_read_description (struct targe
         return tdesc_powerpc_e500;
       else
         {
-          /* EIO means that the PTRACE_GETEVRREGS request isn't supported.  */
-          if (errno == EIO)
-	    return NULL;
-	  else
-            /* Anything else needs to be reported.  */
+          /* EIO means that the PTRACE_GETEVRREGS request isn't supported.
+	     Anything else needs to be reported.  */
+          if (errno != EIO)
             perror_with_name (_("Unable to fetch SPE registers"));
 	}
     }
 
-  return NULL;
+  /* Check for 64-bit inferior process.  This is the case when the host is
+     64-bit, and in addition the top bit of the MSR register is set.  */
+#ifdef __powerpc64__
+  {
+    long msr;
+
+    int tid = TIDGET (inferior_ptid);
+    if (tid == 0)
+      tid = PIDGET (inferior_ptid);
+
+    errno = 0;
+    msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
+    if (errno == 0 && msr < 0)
+      return tdesc_powerpc_linux64;
+  }
+#endif
+
+  return tdesc_powerpc_linux32;
 }
 
 void _initialize_ppc_linux_nat (void);
diff -urNp gdb-orig/gdb/ppc-linux-tdep.c gdb-head/gdb/ppc-linux-tdep.c
--- gdb-orig/gdb/ppc-linux-tdep.c	2008-03-27 00:52:46.093409899 +0100
+++ gdb-head/gdb/ppc-linux-tdep.c	2008-03-27 00:05:36.471133987 +0100
@@ -656,7 +656,11 @@ static const struct ppc_reg_offsets ppc3
     /* AltiVec registers.  */
     /* .vr0_offset = */ 0,
     /* .vscr_offset = */ 512 + 12,
-    /* .vrsave_offset = */ 528
+    /* .vrsave_offset = */ 528,
+
+    /* Linux-specific registers.  */
+    /* .orig_r3_offset = */ 136,
+    /* .trap_offset = */ 160
   };
 
 static const struct ppc_reg_offsets ppc64_linux_reg_offsets =
@@ -681,7 +685,11 @@ static const struct ppc_reg_offsets ppc6
     /* AltiVec registers.  */
     /* .vr0_offset = */ 0,
     /* .vscr_offset = */ 512 + 12,
-    /* .vrsave_offset = */ 528
+    /* .vrsave_offset = */ 528,
+
+    /* Linux-specific registers.  */
+    /* .orig_r3_offset = */ 272,
+    /* .trap_offset = */ 320
   };
 
 static const struct regset ppc32_linux_gregset = {
@@ -895,6 +903,50 @@ static struct tramp_frame ppc64_linux_si
   ppc64_linux_sighandler_cache_init
 };
 
+
+static void
+ppc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  regcache_cooked_write_unsigned (regcache, gdbarch_pc_regnum (gdbarch), pc);
+
+  /* Set special TRAP register to -1 to prevent the kernel from
+     messing with the PC we just installed, if we happen to be
+     within an interrupted system call that the kernel wants to
+     restart.
+
+     Note that after we return from the dummy call, the TRAP and
+     ORIG_R3 registers will be automatically restored, and the
+     kernel continues to restart the system call at this point.  */
+  regcache_cooked_write_unsigned (regcache, tdep->ppc_trap_regnum, -1);
+}
+
+
+static const struct target_desc *
+ppc_linux_core_read_description (struct gdbarch *gdbarch,
+				 struct target_ops *target,
+				 bfd *abfd)
+{
+  asection *section = bfd_get_section_by_name (abfd, ".reg");
+  if (! section)
+    return NULL;
+
+  switch (bfd_section_size (abfd, section))
+    {
+    case 48 * 4:
+      return tdesc_powerpc_linux32;
+
+    case 48 * 8:
+      return tdesc_powerpc_linux64;
+
+    default:
+      return NULL;
+    }
+}
+
+
 static void
 ppc_linux_init_abi (struct gdbarch_info info,
                     struct gdbarch *gdbarch)
@@ -914,6 +966,9 @@ ppc_linux_init_abi (struct gdbarch_info 
   set_gdbarch_convert_from_func_ptr_addr
     (gdbarch, ppc_linux_convert_from_func_ptr_addr);
 
+  /* Handle inferior calls during interrupted system calls.  */
+  set_gdbarch_write_pc (gdbarch, ppc_linux_write_pc);
+
   if (tdep->wordsize == 4)
     {
       /* Until November 2001, gcc did not comply with the 32 bit SysV
@@ -951,6 +1006,7 @@ ppc_linux_init_abi (struct gdbarch_info 
       tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sighandler_tramp_frame);
     }
   set_gdbarch_regset_from_core_section (gdbarch, ppc_linux_regset_from_core_section);
+  set_gdbarch_core_read_description (gdbarch, ppc_linux_core_read_description);
 
   /* Enable TLS support.  */
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
diff -urNp gdb-orig/gdb/ppcnbsd-tdep.c gdb-head/gdb/ppcnbsd-tdep.c
--- gdb-orig/gdb/ppcnbsd-tdep.c	2008-03-27 00:52:46.098409181 +0100
+++ gdb-head/gdb/ppcnbsd-tdep.c	2008-03-27 00:05:36.513127954 +0100
@@ -231,5 +231,9 @@ _initialize_ppcnbsd_tdep (void)
       ppcnbsd_reg_offsets.vr0_offset = 0;
       ppcnbsd_reg_offsets.vrsave_offset = 512;
       ppcnbsd_reg_offsets.vscr_offset = 524;
+
+      /* Linux-specific registers.  */
+      ppcnbsd_reg_offsets.orig_r3_offset = -1;
+      ppcnbsd_reg_offsets.trap_offset = -1;
     }
 }
diff -urNp gdb-orig/gdb/ppcobsd-tdep.c gdb-head/gdb/ppcobsd-tdep.c
--- gdb-orig/gdb/ppcobsd-tdep.c	2008-03-27 00:52:46.102408607 +0100
+++ gdb-head/gdb/ppcobsd-tdep.c	2008-03-27 00:05:36.517127379 +0100
@@ -325,6 +325,10 @@ _initialize_ppcobsd_tdep (void)
       ppcobsd_reg_offsets.vr0_offset = 0;
       ppcobsd_reg_offsets.vscr_offset = 512;
       ppcobsd_reg_offsets.vrsave_offset = 520;
+
+      /* Linux-specific registers.  */
+      ppcobsd_reg_offsets.orig_r3_offset = -1;
+      ppcobsd_reg_offsets.trap_offset = -1;
     }
 
   if (ppcobsd_fpreg_offsets.fpscr_offset == 0)
diff -urNp gdb-orig/gdb/ppc-tdep.h gdb-head/gdb/ppc-tdep.h
--- gdb-orig/gdb/ppc-tdep.h	2008-03-27 00:52:46.107407889 +0100
+++ gdb-head/gdb/ppc-tdep.h	2008-03-27 00:05:36.522126661 +0100
@@ -102,6 +102,10 @@ struct ppc_reg_offsets
   int vr0_offset;
   int vscr_offset;
   int vrsave_offset;
+
+  /* Linux-specific registers.  Size in gpr_size.  */
+  int orig_r3_offset;
+  int trap_offset;
 };
 
 /* Supply register REGNUM in the general-purpose register set REGSET
@@ -194,6 +198,10 @@ struct gdbarch_tdep
     /* Multiplier-Quotient Register (older POWER architectures only).  */
     int ppc_mq_regnum;
 
+    /* Linux-specific registers.  */
+    int ppc_orig_r3_regnum;	/* GPR3 at syscall entry.  */
+    int ppc_trap_regnum;	/* Syscall trap code.  */
+
     /* Altivec registers.  */
     int ppc_vr0_regnum;		/* First AltiVec register */
     int ppc_vrsave_regnum;	/* Last AltiVec register */
@@ -255,6 +263,8 @@ enum {
   PPC_VR0_REGNUM = 106,
   PPC_VSCR_REGNUM = 138,
   PPC_VRSAVE_REGNUM = 139,
+  PPC_ORIG_R3_REGNUM = 140,
+  PPC_TRAP_REGNUM = 141,
   PPC_NUM_REGS
 };
 
@@ -265,6 +275,8 @@ enum {
 /* Estimate for the maximum number of instrctions in a function epilogue.  */
 #define PPC_MAX_EPILOGUE_INSTRUCTIONS  52
 
+extern struct target_desc *tdesc_powerpc_linux32;
+extern struct target_desc *tdesc_powerpc_linux64;
 extern struct target_desc *tdesc_powerpc_e500;
 
 #endif /* ppc-tdep.h */
diff -urNp gdb-orig/gdb/regformats/rs6000/powerpc-32.dat gdb-head/gdb/regformats/rs6000/powerpc-32.dat
--- gdb-orig/gdb/regformats/rs6000/powerpc-32.dat	2008-03-27 00:52:46.111407315 +0100
+++ gdb-head/gdb/regformats/rs6000/powerpc-32.dat	1970-01-01 01:00:00.000000000 +0100
@@ -1,109 +0,0 @@
-# DO NOT EDIT: generated from rs6000/powerpc-32.xml
-name:powerpc_32
-xmltarget:powerpc-32.xml
-expedite:r1,pc
-32:r0
-32:r1
-32:r2
-32:r3
-32:r4
-32:r5
-32:r6
-32:r7
-32:r8
-32:r9
-32:r10
-32:r11
-32:r12
-32:r13
-32:r14
-32:r15
-32:r16
-32:r17
-32:r18
-32:r19
-32:r20
-32:r21
-32:r22
-32:r23
-32:r24
-32:r25
-32:r26
-32:r27
-32:r28
-32:r29
-32:r30
-32:r31
-64:f0
-64:f1
-64:f2
-64:f3
-64:f4
-64:f5
-64:f6
-64:f7
-64:f8
-64:f9
-64:f10
-64:f11
-64:f12
-64:f13
-64:f14
-64:f15
-64:f16
-64:f17
-64:f18
-64:f19
-64:f20
-64:f21
-64:f22
-64:f23
-64:f24
-64:f25
-64:f26
-64:f27
-64:f28
-64:f29
-64:f30
-64:f31
-32:pc
-32:msr
-32:cr
-32:lr
-32:ctr
-32:xer
-32:fpscr
-128:vr0
-128:vr1
-128:vr2
-128:vr3
-128:vr4
-128:vr5
-128:vr6
-128:vr7
-128:vr8
-128:vr9
-128:vr10
-128:vr11
-128:vr12
-128:vr13
-128:vr14
-128:vr15
-128:vr16
-128:vr17
-128:vr18
-128:vr19
-128:vr20
-128:vr21
-128:vr22
-128:vr23
-128:vr24
-128:vr25
-128:vr26
-128:vr27
-128:vr28
-128:vr29
-128:vr30
-128:vr31
-32:vscr
-32:vrsave
diff -urNp gdb-orig/gdb/regformats/rs6000/powerpc-64.dat gdb-head/gdb/regformats/rs6000/powerpc-64.dat
--- gdb-orig/gdb/regformats/rs6000/powerpc-64.dat	2008-03-27 00:52:46.115406740 +0100
+++ gdb-head/gdb/regformats/rs6000/powerpc-64.dat	1970-01-01 01:00:00.000000000 +0100
@@ -1,109 +0,0 @@
-# DO NOT EDIT: generated from rs6000/powerpc-64.xml
-name:powerpc_64
-xmltarget:powerpc-64.xml
-expedite:r1,pc
-64:r0
-64:r1
-64:r2
-64:r3
-64:r4
-64:r5
-64:r6
-64:r7
-64:r8
-64:r9
-64:r10
-64:r11
-64:r12
-64:r13
-64:r14
-64:r15
-64:r16
-64:r17
-64:r18
-64:r19
-64:r20
-64:r21
-64:r22
-64:r23
-64:r24
-64:r25
-64:r26
-64:r27
-64:r28
-64:r29
-64:r30
-64:r31
-64:f0
-64:f1
-64:f2
-64:f3
-64:f4
-64:f5
-64:f6
-64:f7
-64:f8
-64:f9
-64:f10
-64:f11
-64:f12
-64:f13
-64:f14
-64:f15
-64:f16
-64:f17
-64:f18
-64:f19
-64:f20
-64:f21
-64:f22
-64:f23
-64:f24
-64:f25
-64:f26
-64:f27
-64:f28
-64:f29
-64:f30
-64:f31
-64:pc
-64:msr
-32:cr
-64:lr
-64:ctr
-32:xer
-32:fpscr
-128:vr0
-128:vr1
-128:vr2
-128:vr3
-128:vr4
-128:vr5
-128:vr6
-128:vr7
-128:vr8
-128:vr9
-128:vr10
-128:vr11
-128:vr12
-128:vr13
-128:vr14
-128:vr15
-128:vr16
-128:vr17
-128:vr18
-128:vr19
-128:vr20
-128:vr21
-128:vr22
-128:vr23
-128:vr24
-128:vr25
-128:vr26
-128:vr27
-128:vr28
-128:vr29
-128:vr30
-128:vr31
-32:vscr
-32:vrsave
diff -urNp gdb-orig/gdb/regformats/rs6000/powerpc-linux32.dat gdb-head/gdb/regformats/rs6000/powerpc-linux32.dat
--- gdb-orig/gdb/regformats/rs6000/powerpc-linux32.dat	1970-01-01 01:00:00.000000000 +0100
+++ gdb-head/gdb/regformats/rs6000/powerpc-linux32.dat	2008-03-27 00:06:24.245584875 +0100
@@ -0,0 +1,111 @@
+# DO NOT EDIT: generated from rs6000/powerpc-linux32.xml
+name:powerpc_linux32
+xmltarget:powerpc-linux32.xml
+expedite:r1,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:r16
+32:r17
+32:r18
+32:r19
+32:r20
+32:r21
+32:r22
+32:r23
+32:r24
+32:r25
+32:r26
+32:r27
+32:r28
+32:r29
+32:r30
+32:r31
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+64:f16
+64:f17
+64:f18
+64:f19
+64:f20
+64:f21
+64:f22
+64:f23
+64:f24
+64:f25
+64:f26
+64:f27
+64:f28
+64:f29
+64:f30
+64:f31
+32:pc
+32:msr
+32:cr
+32:lr
+32:ctr
+32:xer
+32:fpscr
+32:orig_r3
+32:trap
+128:vr0
+128:vr1
+128:vr2
+128:vr3
+128:vr4
+128:vr5
+128:vr6
+128:vr7
+128:vr8
+128:vr9
+128:vr10
+128:vr11
+128:vr12
+128:vr13
+128:vr14
+128:vr15
+128:vr16
+128:vr17
+128:vr18
+128:vr19
+128:vr20
+128:vr21
+128:vr22
+128:vr23
+128:vr24
+128:vr25
+128:vr26
+128:vr27
+128:vr28
+128:vr29
+128:vr30
+128:vr31
+32:vscr
+32:vrsave
diff -urNp gdb-orig/gdb/regformats/rs6000/powerpc-linux64.dat gdb-head/gdb/regformats/rs6000/powerpc-linux64.dat
--- gdb-orig/gdb/regformats/rs6000/powerpc-linux64.dat	1970-01-01 01:00:00.000000000 +0100
+++ gdb-head/gdb/regformats/rs6000/powerpc-linux64.dat	2008-03-27 00:06:24.357568787 +0100
@@ -0,0 +1,111 @@
+# DO NOT EDIT: generated from rs6000/powerpc-linux64.xml
+name:powerpc_linux64
+xmltarget:powerpc-linux64.xml
+expedite:r1,pc
+64:r0
+64:r1
+64:r2
+64:r3
+64:r4
+64:r5
+64:r6
+64:r7
+64:r8
+64:r9
+64:r10
+64:r11
+64:r12
+64:r13
+64:r14
+64:r15
+64:r16
+64:r17
+64:r18
+64:r19
+64:r20
+64:r21
+64:r22
+64:r23
+64:r24
+64:r25
+64:r26
+64:r27
+64:r28
+64:r29
+64:r30
+64:r31
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+64:f16
+64:f17
+64:f18
+64:f19
+64:f20
+64:f21
+64:f22
+64:f23
+64:f24
+64:f25
+64:f26
+64:f27
+64:f28
+64:f29
+64:f30
+64:f31
+64:pc
+64:msr
+32:cr
+64:lr
+64:ctr
+32:xer
+32:fpscr
+64:orig_r3
+64:trap
+128:vr0
+128:vr1
+128:vr2
+128:vr3
+128:vr4
+128:vr5
+128:vr6
+128:vr7
+128:vr8
+128:vr9
+128:vr10
+128:vr11
+128:vr12
+128:vr13
+128:vr14
+128:vr15
+128:vr16
+128:vr17
+128:vr18
+128:vr19
+128:vr20
+128:vr21
+128:vr22
+128:vr23
+128:vr24
+128:vr25
+128:vr26
+128:vr27
+128:vr28
+128:vr29
+128:vr30
+128:vr31
+32:vscr
+32:vrsave
diff -urNp gdb-orig/gdb/rs6000-aix-tdep.c gdb-head/gdb/rs6000-aix-tdep.c
--- gdb-orig/gdb/rs6000-aix-tdep.c	2008-03-27 00:52:46.126405161 +0100
+++ gdb-head/gdb/rs6000-aix-tdep.c	2008-03-27 00:05:52.840308201 +0100
@@ -52,7 +52,11 @@ static struct ppc_reg_offsets rs6000_aix
   /* AltiVec registers.  */
   -1, /* vr0_offset */
   -1, /* vscr_offset */
-  -1 /* vrsave_offset */
+  -1, /* vrsave_offset */
+
+  /* Linux-specific registers.  */
+  -1, /* orig_r3_offset */
+  -1 /* trap_offset */
 };
 
 static struct ppc_reg_offsets rs6000_aix64_reg_offsets =
@@ -77,7 +81,11 @@ static struct ppc_reg_offsets rs6000_aix
   /* AltiVec registers.  */
   -1, /* vr0_offset */
   -1, /* vscr_offset */
-  -1 /* vrsave_offset */
+  -1, /* vrsave_offset */
+
+  /* Linux-specific registers.  */
+  -1, /* orig_r3_offset */
+  -1 /* trap_offset */
 };
 
 
diff -urNp gdb-orig/gdb/rs6000-tdep.c gdb-head/gdb/rs6000-tdep.c
--- gdb-orig/gdb/rs6000-tdep.c	2008-03-27 00:52:46.138403438 +0100
+++ gdb-head/gdb/rs6000-tdep.c	2008-03-27 00:05:52.852306477 +0100
@@ -64,6 +64,7 @@
 #include "rs6000-tdep.h"
 
 #include "features/rs6000/powerpc-32.c"
+#include "features/rs6000/powerpc-linux32.c"
 #include "features/rs6000/powerpc-403.c"
 #include "features/rs6000/powerpc-403gc.c"
 #include "features/rs6000/powerpc-505.c"
@@ -72,6 +73,7 @@
 #include "features/rs6000/powerpc-603.c"
 #include "features/rs6000/powerpc-604.c"
 #include "features/rs6000/powerpc-64.c"
+#include "features/rs6000/powerpc-linux64.c"
 #include "features/rs6000/powerpc-7400.c"
 #include "features/rs6000/powerpc-750.c"
 #include "features/rs6000/powerpc-860.c"
@@ -448,6 +450,12 @@ ppc_greg_offset (struct gdbarch *gdbarch
   if (regnum == tdep->ppc_ctr_regnum)
     return offsets->ctr_offset;
 
+  if (regnum == tdep->ppc_orig_r3_regnum)
+    return offsets->orig_r3_offset;
+
+  if (regnum == tdep->ppc_trap_regnum)
+    return offsets->trap_offset;
+
   *regsize = offsets->xr_size;
   if (regnum == tdep->ppc_cr_regnum)
     return offsets->cr_offset;
@@ -526,6 +534,10 @@ ppc_supply_gregset (const struct regset 
 		      gregs, offsets->lr_offset, gpr_size);
       ppc_supply_reg (regcache, tdep->ppc_ctr_regnum,
 		      gregs, offsets->ctr_offset, gpr_size);
+      ppc_supply_reg (regcache, tdep->ppc_orig_r3_regnum,
+		      gregs, offsets->orig_r3_offset, gpr_size);
+      ppc_supply_reg (regcache, tdep->ppc_trap_regnum,
+		      gregs, offsets->trap_offset, gpr_size);
       ppc_supply_reg (regcache, tdep->ppc_cr_regnum,
 		      gregs, offsets->cr_offset, offsets->xr_size);
       ppc_supply_reg (regcache, tdep->ppc_xer_regnum,
@@ -654,6 +666,10 @@ ppc_collect_gregset (const struct regset
 		       gregs, offsets->lr_offset, gpr_size);
       ppc_collect_reg (regcache, tdep->ppc_ctr_regnum,
 		       gregs, offsets->ctr_offset, gpr_size);
+      ppc_collect_reg (regcache, tdep->ppc_orig_r3_regnum,
+		       gregs, offsets->orig_r3_offset, gpr_size);
+      ppc_collect_reg (regcache, tdep->ppc_trap_regnum,
+		       gregs, offsets->trap_offset, gpr_size);
       ppc_collect_reg (regcache, tdep->ppc_cr_regnum,
 		       gregs, offsets->cr_offset, offsets->xr_size);
       ppc_collect_reg (regcache, tdep->ppc_xer_regnum,
@@ -3267,6 +3283,7 @@ rs6000_gdbarch_init (struct gdbarch_info
   int soft_float;
   enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global;
   int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0;
+  int have_linux_regs = 0;
   int tdesc_wordsize = -1;
   const struct target_desc *tdesc = info.target_desc;
   struct tdesc_arch_data *tdesc_data = NULL;
@@ -3415,6 +3432,26 @@ rs6000_gdbarch_init (struct gdbarch_info
 	wordsize = tdesc_wordsize;
 
       feature = tdesc_find_feature (tdesc,
+				    "org.gnu.gdb.power.linux");
+      if (feature != NULL)
+	{
+	  valid_p = 1;
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      PPC_ORIG_R3_REGNUM, "orig_r3");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      PPC_TRAP_REGNUM, "trap");
+
+	  if (!valid_p)
+	    {
+	      tdesc_data_cleanup (tdesc_data);
+	      return NULL;
+	    }
+	  have_linux_regs = 1;
+	}
+      else
+	have_linux_regs = 0;
+
+      feature = tdesc_find_feature (tdesc,
 				    "org.gnu.gdb.power.fpu");
       if (feature != NULL)
 	{
@@ -3657,6 +3694,9 @@ rs6000_gdbarch_init (struct gdbarch_info
   tdep->ppc_xer_regnum = PPC_XER_REGNUM;
   tdep->ppc_mq_regnum = have_mq ? PPC_MQ_REGNUM : -1;
 
+  tdep->ppc_orig_r3_regnum = have_linux_regs ? PPC_ORIG_R3_REGNUM : -1;
+  tdep->ppc_trap_regnum = have_linux_regs ? PPC_TRAP_REGNUM : -1;
+
   tdep->ppc_fp0_regnum = have_fpu ? PPC_F0_REGNUM : -1;
   tdep->ppc_fpscr_regnum = have_fpu ? PPC_FPSCR_REGNUM : -1;
   tdep->ppc_vr0_regnum = have_altivec ? PPC_VR0_REGNUM : -1;
@@ -3923,6 +3963,7 @@ _initialize_rs6000_tdep (void)
 
   /* Initialize the standard target descriptions.  */
   initialize_tdesc_powerpc_32 ();
+  initialize_tdesc_powerpc_linux32 ();
   initialize_tdesc_powerpc_403 ();
   initialize_tdesc_powerpc_403gc ();
   initialize_tdesc_powerpc_505 ();
@@ -3931,6 +3972,7 @@ _initialize_rs6000_tdep (void)
   initialize_tdesc_powerpc_603 ();
   initialize_tdesc_powerpc_604 ();
   initialize_tdesc_powerpc_64 ();
+  initialize_tdesc_powerpc_linux64 ();
   initialize_tdesc_powerpc_7400 ();
   initialize_tdesc_powerpc_750 ();
   initialize_tdesc_powerpc_860 ();
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]