+ regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr);
+
+ *addr_p = (CORE_ADDR)siginfo_p->si_addr;
+ return 1;
+}
+
+static int
+ia64_linux_stopped_by_watchpoint (void)
+{
+ CORE_ADDR addr;
+ return ia64_linux_stopped_data_address (¤t_target, &addr);
+}
+
+static int
+ia64_linux_can_use_hw_breakpoint (int type, int cnt, int othertype)
+{
+ return 1;
+}
+
+
+/* Fetch register REGNUM from the inferior. */
+
+static void
+ia64_linux_fetch_register (struct regcache *regcache, int regnum)
+{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ CORE_ADDR addr;
+ size_t size;
+ PTRACE_TYPE_RET *buf;
+ int pid, i;
+
+ if (ia64_cannot_fetch_register (gdbarch, regnum))
+ {
+ regcache_raw_supply (regcache, regnum, NULL);
+ return;
+ }
+
+ /* Cater for systems like GNU/Linux, that implement threads as
+ separate processes. */
+ pid = ptid_get_lwp (inferior_ptid);
+ if (pid == 0)
+ pid = ptid_get_pid (inferior_ptid);
+
+ /* This isn't really an address, but ptrace thinks of it as one. */
+ addr = ia64_register_addr (gdbarch, regnum);
+ size = register_size (gdbarch, regnum);
+
+ gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
+ buf = alloca (size);
+
+ /* Read the register contents from the inferior a chunk at a time. */
+ for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
+ {
+ errno = 0;
+ buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)addr, 0);
+ if (errno != 0)
+ error (_("Couldn't read register %s (#%d): %s."),
+ gdbarch_register_name (gdbarch, regnum),
+ regnum, safe_strerror (errno));
+
+ addr += sizeof (PTRACE_TYPE_RET);
+ }
+ regcache_raw_supply (regcache, regnum, buf);
+}
+
+/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
+ for all registers. */
+
+static void
+ia64_linux_fetch_registers (struct target_ops *ops,
+ struct regcache *regcache, int regnum)
+{
+ if (regnum == -1)
+ for (regnum = 0;
+ regnum < gdbarch_num_regs (get_regcache_arch (regcache));
+ regnum++)
+ ia64_linux_fetch_register (regcache, regnum);
+ else
+ ia64_linux_fetch_register (regcache, regnum);
+}
+
+/* Store register REGNUM into the inferior. */
+
+static void
+ia64_linux_store_register (const struct regcache *regcache, int regnum)
+{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ CORE_ADDR addr;
+ size_t size;
+ PTRACE_TYPE_RET *buf;
+ int pid, i;
+
+ if (ia64_cannot_store_register (gdbarch, regnum))
+ return;
+
+ /* Cater for systems like GNU/Linux, that implement threads as
+ separate processes. */
+ pid = ptid_get_lwp (inferior_ptid);
+ if (pid == 0)
+ pid = ptid_get_pid (inferior_ptid);
+
+ /* This isn't really an address, but ptrace thinks of it as one. */
+ addr = ia64_register_addr (gdbarch, regnum);
+ size = register_size (gdbarch, regnum);
+
+ gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
+ buf = alloca (size);
+
+ /* Write the register contents into the inferior a chunk at a time. */
+ regcache_raw_collect (regcache, regnum, buf);
+ for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)addr, buf[i]);
+ if (errno != 0)
+ error (_("Couldn't write register %s (#%d): %s."),
+ gdbarch_register_name (gdbarch, regnum),
+ regnum, safe_strerror (errno));
+
+ addr += sizeof (PTRACE_TYPE_RET);
+ }
+}
+
+/* Store register REGNUM back into the inferior. If REGNUM is -1, do
+ this for all registers. */
+
+static void
+ia64_linux_store_registers (struct target_ops *ops,
+ struct regcache *regcache, int regnum)
+{
+ if (regnum == -1)
+ for (regnum = 0;
+ regnum < gdbarch_num_regs (get_regcache_arch (regcache));
+ regnum++)
+ ia64_linux_store_register (regcache, regnum);
+ else
+ ia64_linux_store_register (regcache, regnum);
+}
+
+
+static LONGEST (*super_xfer_partial) (struct target_ops *, enum target_object,
+ const char *, gdb_byte *, const gdb_byte *,
+ ULONGEST, LONGEST);
+
+static LONGEST
+ia64_linux_xfer_partial (struct target_ops *ops,
+ enum target_object object,
+ const char *annex,
+ gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST offset, LONGEST len)
+{
+ if (object == TARGET_OBJECT_UNWIND_TABLE && writebuf == NULL && offset == 0)
+ return syscall (__NR_getunwind, readbuf, len);
+
+ return super_xfer_partial (ops, object, annex, readbuf, writebuf,
+ offset, len);
+}
+
+void _initialize_ia64_linux_nat (void);
+
+void
+_initialize_ia64_linux_nat (void)
+{
+ struct target_ops *t;
+
+ /* Fill in the generic GNU/Linux methods. */
+ t = linux_target ();
+
+ /* Override the default fetch/store register routines. */
+ t->to_fetch_registers = ia64_linux_fetch_registers;
+ t->to_store_registers = ia64_linux_store_registers;
+
+ /* Override the default to_xfer_partial. */
+ super_xfer_partial = t->to_xfer_partial;
+ t->to_xfer_partial = ia64_linux_xfer_partial;
+
+ /* Override watchpoint routines. */
+
+ /* The IA-64 architecture can step over a watch point (without triggering
+ it again) if the "dd" (data debug fault disable) bit in the processor
+ status word is set.
+
+ This PSR bit is set in ia64_linux_stopped_by_watchpoint when the
+ code there has determined that a hardware watchpoint has indeed
+ been hit. The CPU will then be able to execute one instruction
+ without triggering a watchpoint. */
+
+ t->to_have_steppable_watchpoint = 1;
+ t->to_can_use_hw_breakpoint = ia64_linux_can_use_hw_breakpoint;
+ t->to_stopped_by_watchpoint = ia64_linux_stopped_by_watchpoint;
+ t->to_stopped_data_address = ia64_linux_stopped_data_address;
+ t->to_insert_watchpoint = ia64_linux_insert_watchpoint;
+ t->to_remove_watchpoint = ia64_linux_remove_watchpoint;