+ perror_with_name (_("Unable to store AltiVec register"));
+}
+
+/* Assuming TID referrs to an SPE process, set the top halves of TID's
+ general-purpose registers and its SPE-specific registers to the
+ values in EVRREGSET. If we don't support PTRACE_SETEVRREGS, do
+ nothing.
+
+ All the logic to deal with whether or not the PTRACE_GETEVRREGS and
+ PTRACE_SETEVRREGS requests are supported is isolated here, and in
+ get_spe_registers. */
+static void
+set_spe_registers (int tid, struct gdb_evrregset_t *evrregset)
+{
+ if (have_ptrace_getsetevrregs)
+ {
+ if (ptrace (PTRACE_SETEVRREGS, tid, 0, evrregset) >= 0)
+ return;
+ else
+ {
+ /* EIO means that the PTRACE_SETEVRREGS request isn't
+ supported; we fail silently, and don't try the call
+ again. */
+ if (errno == EIO)
+ have_ptrace_getsetevrregs = 0;
+ else
+ /* Anything else needs to be reported. */
+ perror_with_name (_("Unable to set SPE registers"));
+ }
+ }
+}
+
+/* Write GDB's value for the SPE-specific raw register REGNO to TID.
+ If REGNO is -1, write the values of all the SPE-specific
+ registers. */
+static void
+store_spe_register (int tid, int regno)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdb_evrregset_t evrregs;
+
+ gdb_assert (sizeof (evrregs.evr[0])
+ == register_size (current_gdbarch, tdep->ppc_ev0_upper_regnum));
+ gdb_assert (sizeof (evrregs.acc)
+ == register_size (current_gdbarch, tdep->ppc_acc_regnum));
+ gdb_assert (sizeof (evrregs.spefscr)
+ == register_size (current_gdbarch, tdep->ppc_spefscr_regnum));
+
+ if (regno == -1)
+ /* Since we're going to write out every register, the code below
+ should store to every field of evrregs; if that doesn't happen,
+ make it obvious by initializing it with suspicious values. */
+ memset (&evrregs, 42, sizeof (evrregs));
+ else
+ /* We can only read and write the entire EVR register set at a
+ time, so to write just a single register, we do a
+ read-modify-write maneuver. */
+ get_spe_registers (tid, &evrregs);
+
+ if (regno == -1)
+ {
+ int i;
+
+ for (i = 0; i < ppc_num_gprs; i++)
+ regcache_raw_collect (current_regcache,
+ tdep->ppc_ev0_upper_regnum + i,
+ &evrregs.evr[i]);
+ }
+ else if (tdep->ppc_ev0_upper_regnum <= regno
+ && regno < tdep->ppc_ev0_upper_regnum + ppc_num_gprs)
+ regcache_raw_collect (current_regcache, regno,
+ &evrregs.evr[regno - tdep->ppc_ev0_upper_regnum]);
+
+ if (regno == -1
+ || regno == tdep->ppc_acc_regnum)
+ regcache_raw_collect (current_regcache,
+ tdep->ppc_acc_regnum,
+ &evrregs.acc);
+
+ if (regno == -1
+ || regno == tdep->ppc_spefscr_regnum)
+ regcache_raw_collect (current_regcache,
+ tdep->ppc_spefscr_regnum,
+ &evrregs.spefscr);
+
+ /* Write back the modified register set. */
+ set_spe_registers (tid, &evrregs);