+static int
+ppc_linux_check_watch_resources (int type, int cnt, int ot)
+{
+ int tid;
+ ptid_t ptid = inferior_ptid;
+
+ /* DABR (data address breakpoint register) is optional for PPC variants.
+ Some variants have one DABR, others have none. So CNT can't be larger
+ than 1. */
+ if (cnt > 1)
+ return 0;
+
+ /* We need to know whether ptrace supports PTRACE_SET_DEBUGREG and whether
+ the target has DABR. If either answer is no, the ptrace call will
+ return -1. Fail in that case. */
+ tid = TIDGET (ptid);
+ if (tid == 0)
+ tid = PIDGET (ptid);
+
+ if (ptrace (PTRACE_SET_DEBUGREG, tid, 0, 0) == -1)
+ return 0;
+ return 1;
+}
+
+static int
+ppc_linux_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
+{
+ /* Handle sub-8-byte quantities. */
+ if (len <= 0)
+ return 0;
+
+ /* addr+len must fall in the 8 byte watchable region. */
+ if ((addr + len) > (addr & ~7) + 8)
+ return 0;
+
+ return 1;
+}
+
+/* The cached DABR value, to install in new threads. */
+static long saved_dabr_value;
+
+/* Set a watchpoint of type TYPE at address ADDR. */
+static int
+ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
+{
+ struct lwp_info *lp;
+ ptid_t ptid;
+ long dabr_value;
+
+ dabr_value = addr & ~7;
+ switch (rw)
+ {
+ case hw_read:
+ /* Set read and translate bits. */
+ dabr_value |= 5;
+ break;
+ case hw_write:
+ /* Set write and translate bits. */
+ dabr_value |= 6;
+ break;
+ case hw_access:
+ /* Set read, write and translate bits. */
+ dabr_value |= 7;
+ break;
+ }
+
+ saved_dabr_value = dabr_value;
+
+ ALL_LWPS (lp, ptid)
+ if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw)
+{
+ struct lwp_info *lp;
+ ptid_t ptid;
+ long dabr_value = 0;
+
+ saved_dabr_value = 0;
+ ALL_LWPS (lp, ptid)
+ if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value) < 0)
+ return -1;
+ return 0;
+}
+
+static void
+ppc_linux_new_thread (ptid_t ptid)
+{
+ ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value);
+}
+
+static int
+ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
+{
+ struct siginfo *siginfo_p;
+
+ siginfo_p = linux_nat_get_siginfo (inferior_ptid);
+
+ if (siginfo_p->si_signo != SIGTRAP
+ || (siginfo_p->si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
+ return 0;
+
+ *addr_p = (CORE_ADDR) (uintptr_t) siginfo_p->si_addr;
+ return 1;
+}
+
+static int
+ppc_linux_stopped_by_watchpoint (void)
+{
+ CORE_ADDR addr;
+ return ppc_linux_stopped_data_address (¤t_target, &addr);
+}
+
+static int
+ppc_linux_watchpoint_addr_within_range (struct target_ops *target,
+ CORE_ADDR addr,
+ CORE_ADDR start, int length)
+{
+ addr &= ~7;
+ /* Check whether [start, start+length-1] intersects [addr, addr+7]. */
+ return start <= addr + 7 && start + length - 1 >= addr;
+}
+
+static void
+ppc_linux_store_inferior_registers (struct regcache *regcache, int regno)