+/* Fill GDB's register array with the floating-point register values
+ in *REGP. */
+void
+supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
+{
+ int i;
+ for (i = 0; i < S390_NUM_REGS; i++)
+ if (regmap_fpregset[i] != -1)
+ regcache_raw_supply (regcache, i,
+ (const char *)regp + regmap_fpregset[i]);
+}
+
+/* Fill register REGNO (if it is a general-purpose register) in
+ *REGP with the value in GDB's register array. If REGNO is -1,
+ do this for all registers. */
+void
+fill_fpregset (const struct regcache *regcache, fpregset_t *regp, int regno)
+{
+ int i;
+ for (i = 0; i < S390_NUM_REGS; i++)
+ if (regmap_fpregset[i] != -1)
+ if (regno == -1 || regno == i)
+ regcache_raw_collect (regcache, i,
+ (char *)regp + regmap_fpregset[i]);
+}
+
+/* Find the TID for the current inferior thread to use with ptrace. */
+static int
+s390_inferior_tid (void)
+{
+ /* GNU/Linux LWP ID's are process ID's. */
+ int tid = TIDGET (inferior_ptid);
+ if (tid == 0)
+ tid = PIDGET (inferior_ptid); /* Not a threaded program. */
+
+ return tid;
+}
+
+/* Fetch all general-purpose registers from process/thread TID and
+ store their values in GDB's register cache. */
+static void
+fetch_regs (struct regcache *regcache, int tid)
+{
+ gregset_t regs;
+ ptrace_area parea;
+
+ parea.len = sizeof (regs);
+ parea.process_addr = (addr_t) ®s;
+ parea.kernel_addr = offsetof (struct user_regs_struct, psw);
+ if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
+ perror_with_name (_("Couldn't get registers"));
+
+ supply_gregset (regcache, (const gregset_t *) ®s);
+}
+
+/* Store all valid general-purpose registers in GDB's register cache
+ into the process/thread specified by TID. */
+static void
+store_regs (const struct regcache *regcache, int tid, int regnum)
+{
+ gregset_t regs;
+ ptrace_area parea;
+
+ parea.len = sizeof (regs);
+ parea.process_addr = (addr_t) ®s;
+ parea.kernel_addr = offsetof (struct user_regs_struct, psw);
+ if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
+ perror_with_name (_("Couldn't get registers"));
+
+ fill_gregset (regcache, ®s, regnum);
+
+ if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
+ perror_with_name (_("Couldn't write registers"));
+}
+
+/* Fetch all floating-point registers from process/thread TID and store
+ their values in GDB's register cache. */
+static void
+fetch_fpregs (struct regcache *regcache, int tid)
+{
+ fpregset_t fpregs;
+ ptrace_area parea;
+
+ parea.len = sizeof (fpregs);
+ parea.process_addr = (addr_t) &fpregs;
+ parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
+ if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
+ perror_with_name (_("Couldn't get floating point status"));
+
+ supply_fpregset (regcache, (const fpregset_t *) &fpregs);
+}
+
+/* Store all valid floating-point registers in GDB's register cache
+ into the process/thread specified by TID. */
+static void
+store_fpregs (const struct regcache *regcache, int tid, int regnum)
+{
+ fpregset_t fpregs;
+ ptrace_area parea;
+
+ parea.len = sizeof (fpregs);
+ parea.process_addr = (addr_t) &fpregs;
+ parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
+ if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
+ perror_with_name (_("Couldn't get floating point status"));
+
+ fill_fpregset (regcache, &fpregs, regnum);
+
+ if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
+ perror_with_name (_("Couldn't write floating point status"));
+}
+
+/* Fetch register REGNUM from the child process. If REGNUM is -1, do
+ this for all registers. */
+static void
+s390_linux_fetch_inferior_registers (struct target_ops *ops,
+ struct regcache *regcache, int regnum)
+{
+ int tid = s390_inferior_tid ();
+
+ if (regnum == -1
+ || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
+ fetch_regs (regcache, tid);
+
+ if (regnum == -1
+ || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
+ fetch_fpregs (regcache, tid);
+}
+
+/* Store register REGNUM back into the child process. If REGNUM is
+ -1, do this for all registers. */
+static void
+s390_linux_store_inferior_registers (struct target_ops *ops,
+ struct regcache *regcache, int regnum)
+{
+ int tid = s390_inferior_tid ();
+
+ if (regnum == -1
+ || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
+ store_regs (regcache, tid, regnum);
+
+ if (regnum == -1
+ || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
+ store_fpregs (regcache, tid, regnum);
+}
+
+
+/* Hardware-assisted watchpoint handling. */
+
+/* We maintain a list of all currently active watchpoints in order
+ to properly handle watchpoint removal.
+
+ The only thing we actually need is the total address space area
+ spanned by the watchpoints. */
+