Re: [PATCH 2/3 v2] Process record support for PowerPC

Wei-cheng Wang
2014-12-06T18:00:24Z

2014-12-06 Wei-cheng Wang <cole945@gmail.com>

* configure.tgt (powerpc*-*-linux): A linux-record.o to
gdb_target_obs.
(ppc_linux_record_tdep, ppc64_linux_record_tdep) New for linux syscal
record.
(ppc_canonicalize_syscall, ppc_linux_syscall_record,
ppc_linux_record_signal, ppc_init_linux_record_tdep): New functions.
(ppc_linux_init_abi): Set process_record, process_record_signal.
* ppc-tdep.h: Add ppc_syscall_record and ppc_linux_record_tdep to
gdbarch_tdep.
(ppc_process_record): New declaration.
* rs6000-tdep.c: (ppc_record_vsr, ppc_process_record_op4,
ppc_process_record_op19, ppc_process_record_op31,
ppc_process_record_op59, ppc_process_record_op60,
ppc_process_record_op63, ppc_process_record): New functions.

Changelog for testsuite

2014-12-06 Wei-cheng Wang <cole945@gmail.com>

* lib/gdb.exp: supports_process_record): Return true for
powerpc*-*-linux* (supports_reverse): Likewise.

---
gdb/configure.tgt | 3 +-
gdb/ppc-linux-tdep.c | 401 +++++++++++
gdb/ppc-tdep.h | 7 +
gdb/rs6000-tdep.c | 1668 +++++++++++++++++++++++++++++++++++++++++++++
gdb/testsuite/lib/gdb.exp | 6 +-
5 files changed, 2082 insertions(+), 3 deletions(-)

diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 1d7f54b..ae77efe 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -434,7 +434,8 @@ powerpc*-*-linux*)
ppc64-tdep.o solib-svr4.o solib-spu.o \
spu-multiarch.o \
glibc-tdep.o symfile-mem.o linux-tdep.o \
- ravenscar-thread.o ppc-ravenscar-thread.o"
+ ravenscar-thread.o ppc-ravenscar-thread.o \
+ linux-record.o "
gdb_sim=../sim/ppc/libsim.a
build_gdbserver=yes
;;
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index a997869..0a2afa7 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -49,6 +49,8 @@
#include "spu-tdep.h"
#include "xml-syscall.h"
#include "linux-tdep.h"
+#include "linux-record.h"
+#include "record-full.h"

#include "stap-probe.h"
#include "ax.h"
@@ -764,6 +766,165 @@ ppc_linux_get_syscall_number (struct gdbarch *gdbarch,
return ret;
}

+/* PPC process record-replay */
+
+struct linux_record_tdep ppc_linux_record_tdep;
+struct linux_record_tdep ppc64_linux_record_tdep;
+
+static enum gdb_syscall
+ppc_canonicalize_syscall (int syscall)
+{
+ /* See arch/powerpc/include/uapi/asm/unistd.h */
+
+ if (syscall <= 165)
+ return syscall;
+ else if (syscall >= 167 && syscall <= 190) /* Skip query_module 166 */
+ return syscall + 1;
+ else if (syscall >= 192 && syscall <= 197) /* mmap2 */
+ return syscall;
+ else if (syscall == 208) /* tkill */
+ return gdb_sys_tkill;
+ else if (syscall >= 207 && syscall <= 220) /* gettid */
+ return syscall + 224 - 207;
+ else if (syscall >= 234 && syscall <= 239) /* exit_group */
+ return syscall + 252 - 234;
+ else if (syscall >= 240 && syscall <=248) /* timer_create */
+ return syscall += 259 - 240;
+ else if (syscall >= 250 && syscall <=251) /* tgkill */
+ return syscall + 270 - 250;
+ else if (syscall == 336)
+ return gdb_sys_recv;
+ else if (syscall == 337)
+ return gdb_sys_recvfrom;
+ else if (syscall == 342)
+ return gdb_sys_recvmsg;
+ return -1;
+}
+
+static int
+ppc_linux_syscall_record (struct regcache *regcache)
+{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ULONGEST scnum;
+ enum gdb_syscall syscall_gdb;
+ int ret;
+ int i;
+
+ regcache_raw_read_unsigned (regcache, tdep->ppc_gp0_regnum, &scnum);
+ syscall_gdb = ppc_canonicalize_syscall (scnum);
+
+ if (syscall_gdb < 0)
+ {
+ printf_unfiltered (_("Process record and replay target doesn't "
+ "support syscall number %d\n"), (int) scnum);
+ return 0;
+ }
+
+ if (syscall_gdb == gdb_sys_sigreturn
+ || syscall_gdb == gdb_sys_rt_sigreturn)
+ {
+ int i, j;
+ int regsets[] = { tdep->ppc_gp0_regnum,
+ tdep->ppc_fp0_regnum,
+ tdep->ppc_vr0_regnum,
+ tdep->ppc_vsr0_upper_regnum };
+
+ for (j = 0; j < 4; j++)
+ {
+ if (regsets[j] == -1)
+ continue;
+ for (i = 0; i < 32; i++)
+ {
+ if (record_full_arch_list_add_reg (regcache, regsets[j] + i))
+ return -1;
+ }
+ }
+
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum))
+ return -1;
+
+ return 0;
+ }
+
+ ret = record_linux_system_call (syscall_gdb, regcache,
+ tdep->ppc_linux_record_tdep);
+ if (ret != 0)
+ return ret;
+
+ /* Record registers clobbered during syscall. */
+ for (i = 3; i <= 12; i++)
+ {
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + i))
+ return -1;
+ }
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + 0))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum))
+ return -1;
+
+ return 0;
+}
+
+static int
+ppc_linux_record_signal (struct gdbarch *gdbarch, struct regcache *regcache,
+ enum gdb_signal signal)
+{
+ /* See handle_rt_signal64 in arch/powerpc/kernel/signal_64.c
+ handle_rt_signal32 in arch/powerpc/kernel/signal_32.c
+ arch/powerpc/include/asm/ptrace.h
+ for details. */
+ const int SIGNAL_FRAMESIZE = 128;
+ const int sizeof_rt_sigframe = 1440 * 2 + 8 * 2 + 4 * 6 + 8 + 8 + 128 + 512;
+ ULONGEST sp;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int i;
+
+ for (i = 3; i <= 6; i++)
+ {
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + i))
+ return -1;
+ }
+ if (tdep->wordsize == 8
+ && record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + 12))
+ return -1;
+
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, gdbarch_pc_regnum (gdbarch)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, gdbarch_sp_regnum (gdbarch)))
+ return -1;
+
+ /* Record the change in the stack.
+ frame-size = sizeof (struct rt_sigframe) + SIGNAL_FRAMESIZE */
+ regcache_raw_read_unsigned (regcache, gdbarch_sp_regnum (gdbarch), &sp);
+ sp -= SIGNAL_FRAMESIZE;
+ sp -= sizeof_rt_sigframe;
+
+ if (record_full_arch_list_add_mem (sp, SIGNAL_FRAMESIZE + sizeof_rt_sigframe))
+ return -1;
+
+ if (record_full_arch_list_add_end ())
+ return -1;
+
+ return 0;
+}
+
static void
ppc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
@@ -1234,6 +1395,235 @@ static const struct frame_unwind ppu2spu_unwind = {
ppu2spu_prev_arch,
};

+/* Initialize linux_record_tdep if not initialized yet. */
+
+static void
+ppc_init_linux_record_tdep (struct gdbarch *gdbarch,
+ struct linux_record_tdep *record_tdep)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ /* These values are the size of the type that will be used in a system
+ call. They are obtained from Linux Kernel source. */
+
+ if (tdep->wordsize == 8 && record_tdep->size_pointer == 0)
+ {
+ record_tdep->size_pointer = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
+ record_tdep->size__old_kernel_stat = 32;
+ record_tdep->size_tms = 32;
+ record_tdep->size_loff_t = 8;
+ record_tdep->size_flock = 32;
+ record_tdep->size_oldold_utsname = 45;
+ record_tdep->size_ustat = 32;
+ record_tdep->size_old_sigaction = 152;
+ record_tdep->size_old_sigset_t = 128;
+ record_tdep->size_rlimit = 16;
+ record_tdep->size_rusage = 144;
+ record_tdep->size_timeval = 16;
+ record_tdep->size_timezone = 8;
+ record_tdep->size_old_gid_t = 4;
+ record_tdep->size_old_uid_t = 4;
+ record_tdep->size_fd_set = 128;
+ record_tdep->size_dirent = 280;
+ record_tdep->size_dirent64 = 280;
+ record_tdep->size_statfs = 120;
+ record_tdep->size_statfs64 = 120;
+ record_tdep->size_sockaddr = 16;
+ record_tdep->size_int = gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT;
+ record_tdep->size_long = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
+ record_tdep->size_ulong = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
+ record_tdep->size_msghdr = 56;
+ record_tdep->size_itimerval = 32;
+ record_tdep->size_stat = 144;
+ record_tdep->size_old_utsname = 325;
+ record_tdep->size_sysinfo = 112;
+ record_tdep->size_msqid_ds = 120;
+ record_tdep->size_shmid_ds = 112;
+ record_tdep->size_new_utsname = 390;
+ record_tdep->size_timex = 208;
+ record_tdep->size_mem_dqinfo = 24;
+ record_tdep->size_if_dqblk = 72;
+ record_tdep->size_fs_quota_stat = 80;
+ record_tdep->size_timespec = 16;
+ record_tdep->size_pollfd = 8;
+ record_tdep->size_NFS_FHSIZE = 32;
+ record_tdep->size_knfsd_fh = 132;
+ record_tdep->size_TASK_COMM_LEN = 32;
+ record_tdep->size_sigaction = 152;
+ record_tdep->size_sigset_t = 128;
+ record_tdep->size_siginfo_t = 128;
+ record_tdep->size_cap_user_data_t = 8;
+ record_tdep->size_stack_t = 24;
+ record_tdep->size_off_t = 8;
+ record_tdep->size_stat64 = 104;
+ record_tdep->size_gid_t = 4;
+ record_tdep->size_uid_t = 4;
+ record_tdep->size_PAGE_SIZE = 0x10000; /* 64KB */
+ record_tdep->size_flock64 = 32;
+ record_tdep->size_io_event = 32;
+ record_tdep->size_iocb = 64;
+ record_tdep->size_epoll_event = 16;
+ record_tdep->size_itimerspec = 32;
+ record_tdep->size_mq_attr = 64;
+ record_tdep->size_siginfo = 128;
+ record_tdep->size_termios = 44;
+ record_tdep->size_pid_t = 4;
+ record_tdep->size_winsize = 8;
+ record_tdep->size_serial_struct = 72;
+ record_tdep->size_serial_icounter_struct = 80;
+ record_tdep->size_size_t = 8;
+ record_tdep->size_iovec = 16;
+ }
+ else if (tdep->wordsize == 4 && record_tdep->size_pointer == 0)
+ {
+ record_tdep->size_pointer = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
+ record_tdep->size__old_kernel_stat = 32;
+ record_tdep->size_tms = 16;
+ record_tdep->size_loff_t = 8;
+ record_tdep->size_flock = 16;
+ record_tdep->size_oldold_utsname = 45;
+ record_tdep->size_ustat = 20;
+ record_tdep->size_old_sigaction = 152;
+ record_tdep->size_old_sigset_t = 128;
+ record_tdep->size_rlimit = 8;
+ record_tdep->size_rusage = 72;
+ record_tdep->size_timeval = 8;
+ record_tdep->size_timezone = 8;
+ record_tdep->size_old_gid_t = 4;
+ record_tdep->size_old_uid_t = 4;
+ record_tdep->size_fd_set = 128;
+ record_tdep->size_dirent = 268;
+ record_tdep->size_dirent64 = 280;
+ record_tdep->size_statfs = 64;
+ record_tdep->size_statfs64 = 88;
+ record_tdep->size_sockaddr = 16;
+ record_tdep->size_int = gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT;
+ record_tdep->size_long = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
+ record_tdep->size_ulong = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
+ record_tdep->size_msghdr = 28;
+ record_tdep->size_itimerval = 16;
+ record_tdep->size_stat = 88;
+ record_tdep->size_old_utsname = 325;
+ record_tdep->size_sysinfo = 64;
+ record_tdep->size_msqid_ds = 68;
+ record_tdep->size_shmid_ds = 60;
+ record_tdep->size_new_utsname = 390;
+ record_tdep->size_timex = 128;
+ record_tdep->size_mem_dqinfo = 24;
+ record_tdep->size_if_dqblk = 72;
+ record_tdep->size_fs_quota_stat = 80;
+ record_tdep->size_timespec = 8;
+ record_tdep->size_pollfd = 8;
+ record_tdep->size_NFS_FHSIZE = 32;
+ record_tdep->size_knfsd_fh = 132;
+ record_tdep->size_TASK_COMM_LEN = 32;
+ record_tdep->size_sigaction = 140;
+ record_tdep->size_sigset_t = 128;
+ record_tdep->size_siginfo_t = 128;
+ record_tdep->size_cap_user_data_t = 4;
+ record_tdep->size_stack_t = 12;
+ record_tdep->size_off_t = 4;
+ record_tdep->size_stat64 = 104;
+ record_tdep->size_gid_t = 4;
+ record_tdep->size_uid_t = 4;
+ record_tdep->size_PAGE_SIZE = 0x10000; /* 64KB */
+ record_tdep->size_flock64 = 32;
+ record_tdep->size_io_event = 32;
+ record_tdep->size_iocb = 64;
+ record_tdep->size_epoll_event = 16;
+ record_tdep->size_itimerspec = 16;
+ record_tdep->size_mq_attr = 32;
+ record_tdep->size_siginfo = 128;
+ record_tdep->size_termios = 44;
+ record_tdep->size_pid_t = 4;
+ record_tdep->size_winsize = 8;
+ record_tdep->size_serial_struct = 60;
+ record_tdep->size_serial_icounter_struct = 80;
+ record_tdep->size_size_t = 4;
+ record_tdep->size_iovec = 8;
+ }
+ else
+ {
+ /* RECORD_TDEP had been initialized. */
+ return;
+ }
+
+ /* These values are the second argument of system call "sys_fcntl"
+ and "sys_fcntl64". They are obtained from Linux Kernel source. */
+ record_tdep->fcntl_F_GETLK = 5;
+ record_tdep->fcntl_F_GETLK64 = 12;
+ record_tdep->fcntl_F_SETLK64 = 13;
+ record_tdep->fcntl_F_SETLKW64 = 14;
+
+ record_tdep->arg1 = PPC_R0_REGNUM + 3;
+ record_tdep->arg2 = PPC_R0_REGNUM + 4;
+ record_tdep->arg3 = PPC_R0_REGNUM + 5;
+ record_tdep->arg4 = PPC_R0_REGNUM + 6;
+ record_tdep->arg5 = PPC_R0_REGNUM + 7;
+ record_tdep->arg6 = PPC_R0_REGNUM + 8;
+
+ /* These values are the second argument of system call "sys_ioctl".
+ They are obtained from Linux Kernel source.
+ See arch/powerpc/include/uapi/asm/ioctls.h. */
+ record_tdep->ioctl_TCGETS = 0x403c7413;
+ record_tdep->ioctl_TCSETS = 0x803c7414;
+ record_tdep->ioctl_TCSETSW = 0x803c7415;
+ record_tdep->ioctl_TCSETSF = 0x803c7416;
+ record_tdep->ioctl_TCGETA = 0x40147417;
+ record_tdep->ioctl_TCSETA = 0x80147418;
+ record_tdep->ioctl_TCSETAW = 0x80147419;
+ record_tdep->ioctl_TCSETAF = 0x8014741c;
+ record_tdep->ioctl_TCSBRK = 0x2000741d;
+ record_tdep->ioctl_TCXONC = 0x2000741e;
+ record_tdep->ioctl_TCFLSH = 0x2000741f;
+ record_tdep->ioctl_TIOCEXCL = 0x540c;
+ record_tdep->ioctl_TIOCNXCL = 0x540d;
+ record_tdep->ioctl_TIOCSCTTY = 0x540e;
+ record_tdep->ioctl_TIOCGPGRP = 0x40047477;
+ record_tdep->ioctl_TIOCSPGRP = 0x80047476;
+ record_tdep->ioctl_TIOCOUTQ = 0x40047473;
+ record_tdep->ioctl_TIOCSTI = 0x5412;
+ record_tdep->ioctl_TIOCGWINSZ = 0x40087468;
+ record_tdep->ioctl_TIOCSWINSZ = 0x80087467;
+ record_tdep->ioctl_TIOCMGET = 0x5415;
+ record_tdep->ioctl_TIOCMBIS = 0x5416;
+ record_tdep->ioctl_TIOCMBIC = 0x5417;
+ record_tdep->ioctl_TIOCMSET = 0x5418;
+ record_tdep->ioctl_TIOCGSOFTCAR = 0x5419;
+ record_tdep->ioctl_TIOCSSOFTCAR = 0x541a;
+ record_tdep->ioctl_FIONREAD = 0x4004667f;
+ record_tdep->ioctl_TIOCINQ = 0x4004667f;
+ record_tdep->ioctl_TIOCLINUX = 0x541c;
+ record_tdep->ioctl_TIOCCONS = 0x541d;
+ record_tdep->ioctl_TIOCGSERIAL = 0x541e;
+ record_tdep->ioctl_TIOCSSERIAL = 0x541f;
+ record_tdep->ioctl_TIOCPKT = 0x5420;
+ record_tdep->ioctl_FIONBIO = 0x8004667e;
+ record_tdep->ioctl_TIOCNOTTY = 0x5422;
+ record_tdep->ioctl_TIOCSETD = 0x5423;
+ record_tdep->ioctl_TIOCGETD = 0x5424;
+ record_tdep->ioctl_TCSBRKP = 0x5425;
+ record_tdep->ioctl_TIOCSBRK = 0x5427;
+ record_tdep->ioctl_TIOCCBRK = 0x5428;
+ record_tdep->ioctl_TIOCGSID = 0x5429;
+ record_tdep->ioctl_TIOCGPTN = 0x40045430;
+ record_tdep->ioctl_TIOCSPTLCK = 0x80045431;
+ record_tdep->ioctl_FIONCLEX = 0x20006602;
+ record_tdep->ioctl_FIOCLEX = 0x20006601;
+ record_tdep->ioctl_FIOASYNC = 0x8004667d;
+ record_tdep->ioctl_TIOCSERCONFIG = 0x5453;
+ record_tdep->ioctl_TIOCSERGWILD = 0x5454;
+ record_tdep->ioctl_TIOCSERSWILD = 0x5455;
+ record_tdep->ioctl_TIOCGLCKTRMIOS = 0x5456;
+ record_tdep->ioctl_TIOCSLCKTRMIOS = 0x5457;
+ record_tdep->ioctl_TIOCSERGSTRUCT = 0x5458;
+ record_tdep->ioctl_TIOCSERGETLSR = 0x5459;
+ record_tdep->ioctl_TIOCSERGETMULTI = 0x545a;
+ record_tdep->ioctl_TIOCSERSETMULTI = 0x545b;
+ record_tdep->ioctl_TIOCMIWAIT = 0x545c;
+ record_tdep->ioctl_TIOCGICOUNT = 0x545d;
+ record_tdep->ioctl_FIOQSIZE = 0x40086680;
+}

static void
ppc_linux_init_abi (struct gdbarch_info info,
@@ -1414,6 +1804,17 @@ ppc_linux_init_abi (struct gdbarch_info info,
}

set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
+
+ /* Support reverse debugging. */
+ set_gdbarch_process_record (gdbarch, ppc_process_record);
+ set_gdbarch_process_record_signal (gdbarch, ppc_linux_record_signal);
+ tdep->ppc_syscall_record = ppc_linux_syscall_record;
+ if (tdep->wordsize == 8)
+ tdep->ppc_linux_record_tdep = &ppc64_linux_record_tdep;
+ else if (tdep->wordsize == 4)
+ tdep->ppc_linux_record_tdep = &ppc_linux_record_tdep;
+
+ ppc_init_linux_record_tdep (gdbarch, tdep->ppc_linux_record_tdep);
}

/* Provide a prototype to silence -Wmissing-prototypes. */
diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h
index 08554ff..81e11a4 100644
--- a/gdb/ppc-tdep.h
+++ b/gdb/ppc-tdep.h
@@ -25,6 +25,7 @@ struct frame_info;
struct value;
struct regcache;
struct type;
+struct linux_record_tdep;

/* From ppc-sysv-tdep.c ... */
enum return_value_convention ppc_sysv_abi_return_value (struct gdbarch *gdbarch,
@@ -259,6 +260,9 @@ struct gdbarch_tdep
/* ISA-specific types. */
struct type *ppc_builtin_type_vec64;
struct type *ppc_builtin_type_vec128;
+
+ int (*ppc_syscall_record) (struct regcache *regcache);
+ struct linux_record_tdep *ppc_linux_record_tdep;
};

@@ -318,6 +322,9 @@ extern CORE_ADDR ppc_insn_d_field (unsigned int insn);

extern CORE_ADDR ppc_insn_ds_field (unsigned int insn);

+extern int ppc_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
+
/* Instruction size. */
#define PPC_INSN_SIZE 4

diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 32e1a7b..98ab01c 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -40,6 +40,8 @@
#include "dwarf2-frame.h"
#include "target-descriptions.h"
#include "user-regs.h"
+#include "record-full.h"
+#include "auxv.h"

#include "libbfd.h" /* for bfd_default_set_arch_mach */
#include "coff/internal.h" /* for libcoff.h */
@@ -3633,6 +3635,1672 @@ bfd_uses_spe_extensions (bfd *abfd)
return success;
}

+/* These are macros for parsing instruction fields (I.1.6.28) */
+
+#define PPC_FIELD(value, from, len) \
+ (((value) >> (32 - (from) - (len))) & ((1 << (len)) - 1))
+#define PPC_SEXT(v, bs) \
+ ((((CORE_ADDR) (v) & (((CORE_ADDR) 1 << (bs)) - 1)) \
+ ^ ((CORE_ADDR) 1 << ((bs) - 1))) \
+ - ((CORE_ADDR) 1 << ((bs) - 1)))
+#define PPC_OP6(insn) PPC_FIELD (insn, 0, 6)
+#define PPC_EXTOP(insn) PPC_FIELD (insn, 21, 10)
+#define PPC_RT(insn) PPC_FIELD (insn, 6, 5)
+#define PPC_RS(insn) PPC_FIELD (insn, 6, 5)
+#define PPC_RA(insn) PPC_FIELD (insn, 11, 5)
+#define PPC_RB(insn) PPC_FIELD (insn, 16, 5)
+#define PPC_NB(insn) PPC_FIELD (insn, 16, 5)
+#define PPC_VRT(insn) PPC_FIELD (insn, 6, 5)
+#define PPC_FRT(insn) PPC_FIELD (insn, 6, 5)
+#define PPC_SPR(insn) (PPC_FIELD (insn, 11, 5) \
+ | (PPC_FIELD (insn, 16, 5) << 5))
+#define PPC_BO(insn) PPC_FIELD (insn, 6, 5)
+#define PPC_T(insn) PPC_FIELD (insn, 6, 5)
+#define PPC_D(insn) PPC_SEXT (PPC_FIELD (insn, 16, 16), 16)
+#define PPC_DS(insn) PPC_SEXT (PPC_FIELD (insn, 16, 14), 14)
+#define PPC_BIT(insn,n) ((insn & (1 << (31 - (n)))) ? 1 : 0)
+#define PPC_OE(insn) PPC_BIT (insn, 21)
+#define PPC_RC(insn) PPC_BIT (insn, 31)
+#define PPC_Rc(insn) PPC_BIT (insn, 21)
+#define PPC_LK(insn) PPC_BIT (insn, 31)
+#define PPC_TX(insn) PPC_BIT (insn, 31)
+#define PPC_LEV(insn) PPC_FIELD (insn, 20, 7)
+
+#define PPC_XT(insn) ((PPC_TX (insn) << 5) | PPC_T (insn))
+#define PPC_XER_NB(xer) (xer & 0x7f)
+
+/* Record Vector-Scalar Registers. */
+
+static int
+ppc_record_vsr (struct regcache *regcache, struct gdbarch_tdep *tdep, int vsr)
+{
+ if (vsr < 0 || vsr >= 64)
+ return -1;
+
+ if (vsr >= 32)
+ {
+ if (tdep->ppc_vr0_regnum >= 0)
+ record_full_arch_list_add_reg (regcache, tdep->ppc_vr0_regnum + vsr - 32);
+ }
+ else
+ {
+ if (tdep->ppc_fp0_regnum >= 0)
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fp0_regnum + vsr);
+ if (tdep->ppc_vsr0_upper_regnum >= 0)
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_vsr0_upper_regnum + vsr);
+ }
+
+ return 0;
+}
+
+/* Parse instructions of primary opcode-4. */
+
+static int
+ppc_process_record_op4 (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR addr, uint32_t insn)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int ext = PPC_FIELD (insn, 21, 11);
+
+ if ((ext & 0x3f) == 45)
+ {
+ /* Vector Permute and Exclusive-OR */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_vr0_regnum + PPC_VRT (insn));
+ return 0;
+ }
+
+ switch ((ext & 0x1ff))
+ {
+ /* 5.16 Decimal Integer Arithmetic Instructions */
+ case 1: /* Decimal Add Modulo */
+ case 65: /* Decimal Subtract Modulo */
+
+ /* Bit-21 should be set. */
+ if (!PPC_BIT (insn, 21))
+ break;
+
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_vr0_regnum + PPC_VRT (insn));
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ return 0;
+ }
+
+ /* Bit-21 is used for RC */
+ switch (ext & 0x3ff)
+ {
+ case 6: /* Vector Compare Equal To Unsigned Byte */
+ case 70: /* Vector Compare Equal To Unsigned Halfword */
+ case 134: /* Vector Compare Equal To Unsigned Word */
+ case 199: /* Vector Compare Equal To Unsigned Doubleword */
+ case 774: /* Vector Compare Greater Than Signed Byte */
+ case 838: /* Vector Compare Greater Than Signed Halfword */
+ case 902: /* Vector Compare Greater Than Signed Word */
+ case 967: /* Vector Compare Greater Than Signed Doubleword */
+ case 518: /* Vector Compare Greater Than Unsigned Byte */
+ case 646: /* Vector Compare Greater Than Unsigned Word */
+ case 582: /* Vector Compare Greater Than Unsigned Halfword */
+ case 711: /* Vector Compare Greater Than Unsigned Doubleword */
+ case 966: /* Vector Compare Bounds Single-Precision */
+ case 198: /* Vector Compare Equal To Single-Precision */
+ case 454: /* Vector Compare Greater Than or Equal To Single-Precision */
+ case 710: /* Vector Compare Greater Than Single-Precision */
+ if (PPC_Rc (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_vr0_regnum + PPC_VRT (insn));
+ return 0;
+ }
+
+ switch (ext)
+ {
+ case 142: /* Vector Pack Unsigned Halfword Unsigned Saturate */
+ case 206: /* Vector Pack Unsigned Word Unsigned Saturate */
+ case 270: /* Vector Pack Signed Halfword Unsigned Saturate */
+ case 334: /* Vector Pack Signed Word Unsigned Saturate */
+ case 398: /* Vector Pack Signed Halfword Signed Saturate */
+ case 462: /* Vector Pack Signed Word Signed Saturate */
+ case 1230: /* Vector Pack Unsigned Doubleword Unsigned Saturate */
+ case 1358: /* Vector Pack Signed Doubleword Unsigned Saturate */
+ case 1486: /* Vector Pack Signed Doubleword Signed Saturate */
+ case 512: /* Vector Add Unsigned Byte Saturate */
+ case 576: /* Vector Add Unsigned Halfword Saturate */
+ case 640: /* Vector Add Unsigned Word Saturate */
+ case 768: /* Vector Add Signed Byte Saturate */
+ case 832: /* Vector Add Signed Halfword Saturate */
+ case 896: /* Vector Add Signed Word Saturate */
+ case 1536: /* Vector Subtract Unsigned Byte Saturate */
+ case 1600: /* Vector Subtract Unsigned Halfword Saturate */
+ case 1664: /* Vector Subtract Unsigned Word Saturate */
+ case 1792: /* Vector Subtract Signed Byte Saturate */
+ case 1856: /* Vector Subtract Signed Halfword Saturate */
+ case 1920: /* Vector Subtract Signed Word Saturate */
+ case 32: /* Vector Multiply-High-Add Signed Halfword Saturate */
+ case 33: /* Vector Multiply-High-Round-Add Signed Halfword Saturate */
+ case 39: /* Vector Multiply-Sum Unsigned Halfword Saturate */
+ case 41: /* Vector Multiply-Sum Signed Halfword Saturate */
+ case 1544: /* Vector Sum across Quarter Unsigned Byte Saturate */
+ case 1800: /* Vector Sum across Quarter Signed Byte Saturate */
+ case 1608: /* Vector Sum across Quarter Signed Halfword Saturate */
+ case 1672: /* Vector Sum across Half Signed Word Saturate */
+ case 1928: /* Vector Sum across Signed Word Saturate */
+ case 970: /* Vector Convert To Signed Fixed-Point Word Saturate */
+ case 906: /* Vector Convert To Unsigned Fixed-Point Word Saturate */
+ record_full_arch_list_add_reg (regcache, PPC_VSCR_REGNUM);
+ /* FALL-THROUGH */
+ case 12: /* Vector Merge High Byte */
+ case 14: /* Vector Pack Unsigned Halfword Unsigned Modulo */
+ case 42: /* Vector Select */
+ case 43: /* Vector Permute */
+ case 76: /* Vector Merge High Halfword */
+ case 78: /* Vector Pack Unsigned Word Unsigned Modulo */
+ case 140: /* Vector Merge High Word */
+ case 268: /* Vector Merge Low Byte */
+ case 332: /* Vector Merge Low Halfword */
+ case 396: /* Vector Merge Low Word */
+ case 526: /* Vector Unpack High Signed Byte */
+ case 590: /* Vector Unpack High Signed Halfword */
+ case 654: /* Vector Unpack Low Signed Byte */
+ case 718: /* Vector Unpack Low Signed Halfword */
+ case 782: /* Vector Pack Pixel */
+ case 846: /* Vector Unpack High Pixel */
+ case 974: /* Vector Unpack Low Pixel */
+ case 1102: /* Vector Pack Unsigned Doubleword Unsigned Modulo */
+ case 1614: /* Vector Unpack High Signed Word */
+ case 1676: /* Vector Merge Odd Word */
+ case 1742: /* Vector Unpack Low Signed Word */
+ case 1932: /* Vector Merge Even Word */
+ case 524: /* Vector Splat Byte */
+ case 588: /* Vector Splat Halfword */
+ case 652: /* Vector Splat Word */
+ case 780: /* Vector Splat Immediate Signed Byte */
+ case 844: /* Vector Splat Immediate Signed Halfword */
+ case 908: /* Vector Splat Immediate Signed Word */
+ case 44: /* Vector Shift Left Double by Octet Immediate */
+ case 452: /* Vector Shift Left */
+ case 708: /* Vector Shift Right */
+ case 1036: /* Vector Shift Left by Octet */
+ case 1100: /* Vector Shift Right by Octet */
+ case 60: /* Vector Add Extended Unsigned Quadword Modulo */
+ case 61: /* Vector Add Extended & write Carry Unsigned Quadword */
+ case 62: /* Vector Subtract Extended Unsigned Quadword Modulo */
+ case 63: /* Vector Subtract Extended & write Carry Unsigned Quadword */
+ case 0: /* Vector Add Unsigned Byte Modulo */
+ case 64: /* Vector Add Unsigned Halfword Modulo */
+ case 128: /* Vector Add Unsigned Word Modulo */
+ case 192: /* Vector Add Unsigned Doubleword Modulo */
+ case 256: /* Vector Add Unsigned Quadword Modulo */
+ case 320: /* Vector Add & write Carry Unsigned Quadword */
+ case 384: /* Vector Add and Write Carry-Out Unsigned Word */
+ case 8: /* Vector Multiply Odd Unsigned Byte */
+ case 72: /* Vector Multiply Odd Unsigned Halfword */
+ case 136: /* Vector Multiply Odd Unsigned Word */
+ case 264: /* Vector Multiply Odd Signed Byte */
+ case 328: /* Vector Multiply Odd Signed Halfword */
+ case 392: /* Vector Multiply Odd Signed Word */
+ case 520: /* Vector Multiply Even Unsigned Byte */
+ case 584: /* Vector Multiply Even Unsigned Halfword */
+ case 648: /* Vector Multiply Even Unsigned Word */
+ case 776: /* Vector Multiply Even Signed Byte */
+ case 840: /* Vector Multiply Even Signed Halfword */
+ case 904: /* Vector Multiply Even Signed Word */
+ case 137: /* Vector Multiply Unsigned Word Modulo */
+ case 1024: /* Vector Subtract Unsigned Byte Modulo */
+ case 1088: /* Vector Subtract Unsigned Halfword Modulo */
+ case 1152: /* Vector Subtract Unsigned Word Modulo */
+ case 1216: /* Vector Subtract Unsigned Doubleword Modulo */
+ case 1280: /* Vector Subtract Unsigned Quadword Modulo */
+ case 1344: /* Vector Subtract & write Carry Unsigned Quadword */
+ case 1408: /* Vector Subtract and Write Carry-Out Unsigned Word */
+ case 34: /* Vector Multiply-Low-Add Unsigned Halfword Modulo */
+ case 36: /* Vector Multiply-Sum Unsigned Byte Modulo */
+ case 37: /* Vector Multiply-Sum Mixed Byte Modulo */
+ case 38: /* Vector Multiply-Sum Unsigned Halfword Modulo */
+ case 40: /* Vector Multiply-Sum Signed Halfword Modulo */
+ case 1282: /* Vector Average Signed Byte */
+ case 1346: /* Vector Average Signed Halfword */
+ case 1410: /* Vector Average Signed Word */
+ case 1026: /* Vector Average Unsigned Byte */
+ case 1090: /* Vector Average Unsigned Halfword */
+ case 1154: /* Vector Average Unsigned Word */
+ case 258: /* Vector Maximum Signed Byte */
+ case 322: /* Vector Maximum Signed Halfword */
+ case 386: /* Vector Maximum Signed Word */
+ case 450: /* Vector Maximum Signed Doubleword */
+ case 2: /* Vector Maximum Unsigned Byte */
+ case 66: /* Vector Maximum Unsigned Halfword */
+ case 130: /* Vector Maximum Unsigned Word */
+ case 194: /* Vector Maximum Unsigned Doubleword */
+ case 770: /* Vector Minimum Signed Byte */
+ case 834: /* Vector Minimum Signed Halfword */
+ case 898: /* Vector Minimum Signed Word */
+ case 962: /* Vector Minimum Signed Doubleword */
+ case 514: /* Vector Minimum Unsigned Byte */
+ case 578: /* Vector Minimum Unsigned Halfword */
+ case 642: /* Vector Minimum Unsigned Word */
+ case 706: /* Vector Minimum Unsigned Doubleword */
+ case 1028: /* Vector Logical AND */
+ case 1668: /* Vector Logical Equivalent */
+ case 1092: /* Vector Logical AND with Complement */
+ case 1412: /* Vector Logical NAND */
+ case 1348: /* Vector Logical OR with Complement */
+ case 1156: /* Vector Logical OR */
+ case 1284: /* Vector Logical NOR */
+ case 1220: /* Vector Logical XOR */
+ case 4: /* Vector Rotate Left Byte */
+ case 132: /* Vector Rotate Left Word VX-form */
+ case 68: /* Vector Rotate Left Halfword */
+ case 196: /* Vector Rotate Left Doubleword */
+ case 260: /* Vector Shift Left Byte */
+ case 388: /* Vector Shift Left Word */
+ case 324: /* Vector Shift Left Halfword */
+ case 1476: /* Vector Shift Left Doubleword */
+ case 516: /* Vector Shift Right Byte */
+ case 644: /* Vector Shift Right Word */
+ case 580: /* Vector Shift Right Halfword */
+ case 1732: /* Vector Shift Right Doubleword */
+ case 772: /* Vector Shift Right Algebraic Byte */
+ case 900: /* Vector Shift Right Algebraic Word */
+ case 836: /* Vector Shift Right Algebraic Halfword */
+ case 964: /* Vector Shift Right Algebraic Doubleword */
+ case 10: /* Vector Add Single-Precision */
+ case 74: /* Vector Subtract Single-Precision */
+ case 46: /* Vector Multiply-Add Single-Precision */
+ case 47: /* Vector Negative Multiply-Subtract Single-Precision */
+ case 1034: /* Vector Maximum Single-Precision */
+ case 1098: /* Vector Minimum Single-Precision */
+ case 842: /* Vector Convert From Signed Fixed-Point Word */
+ case 778: /* Vector Convert From Unsigned Fixed-Point Word */
+ case 714: /* Vector Round to Single-Precision Integer toward -Infinity */
+ case 522: /* Vector Round to Single-Precision Integer Nearest */
+ case 650: /* Vector Round to Single-Precision Integer toward +Infinity */
+ case 586: /* Vector Round to Single-Precision Integer toward Zero */
+ case 394: /* Vector 2 Raised to the Exponent Estimate Floating-Point */
+ case 458: /* Vector Log Base 2 Estimate Floating-Point */
+ case 266: /* Vector Reciprocal Estimate Single-Precision */
+ case 330: /* Vector Reciprocal Square Root Estimate Single-Precision */
+ case 1288: /* Vector AES Cipher */
+ case 1289: /* Vector AES Cipher Last */
+ case 1352: /* Vector AES Inverse Cipher */
+ case 1353: /* Vector AES Inverse Cipher Last */
+ case 1480: /* Vector AES SubBytes */
+ case 1730: /* Vector SHA-512 Sigma Doubleword */
+ case 1666: /* Vector SHA-256 Sigma Word */
+ case 1032: /* Vector Polynomial Multiply-Sum Byte */
+ case 1160: /* Vector Polynomial Multiply-Sum Word */
+ case 1096: /* Vector Polynomial Multiply-Sum Halfword */
+ case 1224: /* Vector Polynomial Multiply-Sum Doubleword */
+ case 1292: /* Vector Gather Bits by Bytes by Doubleword */
+ case 1794: /* Vector Count Leading Zeros Byte */
+ case 1858: /* Vector Count Leading Zeros Halfword */
+ case 1922: /* Vector Count Leading Zeros Word */
+ case 1986: /* Vector Count Leading Zeros Doubleword */
+ case 1795: /* Vector Population Count Byte */
+ case 1859: /* Vector Population Count Halfword */
+ case 1923: /* Vector Population Count Word */
+ case 1987: /* Vector Population Count Doubleword */
+ case 1356: /* Vector Bit Permute Quadword */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_vr0_regnum + PPC_VRT (insn));
+ return 0;
+
+ case 1604: /* Move To Vector Status and Control Register */
+ record_full_arch_list_add_reg (regcache, PPC_VSCR_REGNUM);
+ return 0;
+ case 1540: /* Move From Vector Status and Control Register */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_vr0_regnum + PPC_VRT (insn));
+ return 0;
+ }
+
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
+ "%08x at %08lx, 4-%d.\n", insn, addr, ext);
+ return -1;
+}
+
+/* Parse instructions of primary opcode-19. */
+
+static int
+ppc_process_record_op19 (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR addr, uint32_t insn)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int ext = PPC_EXTOP (insn);
+
+ switch (ext)
+ {
+ case 0: /* Move Condition Register Field */
+ case 33: /* Condition Register NOR */
+ case 129: /* Condition Register AND with Complement */
+ case 193: /* Condition Register XOR */
+ case 225: /* Condition Register NAND */
+ case 257: /* Condition Register AND */
+ case 289: /* Condition Register Equivalent */
+ case 417: /* Condition Register OR with Complement */
+ case 449: /* Condition Register OR */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ return 0;
+
+ case 16: /* Branch Conditional */
+ case 560: /* Branch Conditional to Branch Target Address Register */
+ if ((PPC_BO (insn) & 0x4) == 0)
+ record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum);
+ /* FALL-THROUGH */
+ case 528: /* Branch Conditional to Count Register */
+ if (PPC_LK (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum);
+ return 0;
+
+ case 150: /* Instruction Synchronize */
+ /* Do nothing. */
+ return 0;
+ }
+
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
+ "%08x at %08lx, 19-%d.\n", insn, addr, ext);
+ return -1;
+}
+
+/* Parse instructions of primary opcode-31. */
+
+static int
+ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR addr, uint32_t insn)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int ext = PPC_EXTOP (insn);
+ int tmp, nr, nb, i;
+ CORE_ADDR at_dcsz, ea = 0;
+ ULONGEST rb, ra, xer;
+ int size = 0;
+
+ /* These instructions have OE bit. */
+ switch (ext & 0x1ff)
+ {
+ /* These write RT and XER. Update CR if RC is set. */
+ case 8: /* Subtract from carrying */
+ case 10: /* Add carrying */
+ case 136: /* Subtract from extended */
+ case 138: /* Add extended */
+ case 200: /* Subtract from zero extended */
+ case 202: /* Add to zero extended */
+ case 232: /* Subtract from minus one extended */
+ case 234: /* Add to minus one extended */
+ /* CA is always altered, but SO/OV are only altered when OE=1.
+ In any case, XER is always altered. */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ return 0;
+
+ /* These write RT. Update CR if RC is set and update XER if OE is set. */
+ case 40: /* Subtract from */
+ case 104: /* Negate */
+ case 233: /* Multiply low doubleword */
+ case 235: /* Multiply low word */
+ case 266: /* Add */
+ case 393: /* Divide Doubleword Extended Unsigned */
+ case 395: /* Divide Word Extended Unsigned */
+ case 425: /* Divide Doubleword Extended */
+ case 427: /* Divide Word Extended */
+ case 457: /* Divide Doubleword Unsigned */
+ case 459: /* Divide Word Unsigned */
+ case 489: /* Divide Doubleword */
+ case 491: /* Divide Word */
+ if (PPC_OE (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+ /* FALL-THROUGH */
+ case 9: /* Multiply High Doubleword Unsigned */
+ case 11: /* Multiply High Word Unsigned */
+ case 73: /* Multiply High Doubleword */
+ case 75: /* Multiply High Word */
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ return 0;
+ }
+
+ if ((ext & 0x1f) == 15)
+ {
+ /* Integer Select. bit[16:20] is used for BC. */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ return 0;
+ }
+
+ switch (ext)
+ {
+ case 78: /* Determine Leftmost Zero Byte */
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ return 0;
+
+ /* These only write RT. */
+ case 19: /* Move from condition register */
+ /* Move From One Condition Register Field */
+ case 74: /* Add and Generate Sixes */
+ case 74 | 0x200: /* Add and Generate Sixes (bit-21 dont-care) */
+ case 302: /* Move From Branch History Rolling Buffer */
+ case 339: /* Move From Special Purpose Register */
+ case 371: /* Move From Time Base [Phased-Out] */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ return 0;
+
+ /* These only write to RA. */
+ case 51: /* Move From VSR Doubleword */
+ case 115: /* Move From VSR Word and Zero */
+ case 122: /* Population count bytes */
+ case 378: /* Population count words */
+ case 506: /* Population count doublewords */
+ case 154: /* Parity Word */
+ case 186: /* Parity Doubleword */
+ case 252: /* Bit Permute Doubleword */
+ case 282: /* Convert Declets To Binary Coded Decimal */
+ case 314: /* Convert Binary Coded Decimal To Declets */
+ case 508: /* Compare bytes */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ return 0;
+
+ /* These write CR and optional RA. */
+ case 792: /* Shift Right Algebraic Word */
+ case 794: /* Shift Right Algebraic Doubleword */
+ case 824: /* Shift Right Algebraic Word Immediate */
+ case 826: /* Shift Right Algebraic Doubleword Immediate (413) */
+ case 826 | 1: /* Shift Right Algebraic Doubleword Immediate (413) */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ /* FALL-THROUGH */
+ case 0: /* Compare */
+ case 32: /* Compare logical */
+ case 144: /* Move To Condition Register Fields */
+ /* Move To One Condition Register Field */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ return 0;
+
+ /* These write to RT. Update RA if 'update indexed.' */
+ case 53: /* Load Doubleword with Update Indexed */
+ case 119: /* Load Byte and Zero with Update Indexed */
+ case 311: /* Load Halfword and Zero with Update Indexed */
+ case 55: /* Load Word and Zero with Update Indexed */
+ case 375: /* Load Halfword Algebraic with Update Indexed */
+ case 373: /* Load Word Algebraic with Update Indexed */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ /* FALL-THROUGH */
+ case 21: /* Load Doubleword Indexed */
+ case 52: /* Load Byte And Reserve Indexed */
+ case 116: /* Load Halfword And Reserve Indexed */
+ case 20: /* Load Word And Reserve Indexed */
+ case 84: /* Load Doubleword And Reserve Indexed */
+ case 87: /* Load Byte and Zero Indexed */
+ case 279: /* Load Halfword and Zero Indexed */
+ case 23: /* Load Word and Zero Indexed */
+ case 343: /* Load Halfword Algebraic Indexed */
+ case 341: /* Load Word Algebraic Indexed */
+ case 790: /* Load Halfword Byte-Reverse Indexed */
+ case 534: /* Load Word Byte-Reverse Indexed */
+ case 532: /* Load Doubleword Byte-Reverse Indexed */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ return 0;
+
+ case 597: /* Load String Word Immediate */
+ case 533: /* Load String Word Indexed */
+ if (ext == 597)
+ {
+ nr = PPC_NB (insn);
+ if (nr == 0)
+ nr = 32;
+ }
+ else
+ {
+ regcache_raw_read_unsigned (regcache, tdep->ppc_xer_regnum, &xer);
+ nr = PPC_XER_NB (xer);
+ }
+
+ nr = (nr + 3) >> 2;
+
+ /* If n=0, the contents of register RT are undefined. */
+ if (nr == 0)
+ nr = 1;
+
+ for (i = 0; i < nr; i++)
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum
+ + ((PPC_RT (insn) + i) & 0x1f));
+ return 0;
+
+ case 276: /* Load Quadword And Reserve Indexed */
+ tmp = tdep->ppc_gp0_regnum + (PPC_RT (insn) & ~1);
+ record_full_arch_list_add_reg (regcache, tmp);
+ record_full_arch_list_add_reg (regcache, tmp + 1);
+ return 0;
+
+ /* These write VRT. */
+ case 6: /* Load Vector for Shift Left Indexed */
+ case 38: /* Load Vector for Shift Right Indexed */
+ case 7: /* Load Vector Element Byte Indexed */
+ case 39: /* Load Vector Element Halfword Indexed */
+ case 71: /* Load Vector Element Word Indexed */
+ case 103: /* Load Vector Indexed */
+ case 359: /* Load Vector Indexed LRU */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_vr0_regnum + PPC_VRT (insn));
+ return 0;
+
+ /* These write FRT. Update RA if 'update indexed.' */
+ case 567: /* Load Floating-Point Single with Update Indexed */
+ case 631: /* Load Floating-Point Double with Update Indexed */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ /* FALL-THROUGH */
+ case 535: /* Load Floating-Point Single Indexed */
+ case 599: /* Load Floating-Point Double Indexed */
+ case 855: /* Load Floating-Point as Integer Word Algebraic Indexed */
+ case 887: /* Load Floating-Point as Integer Word and Zero Indexed */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ return 0;
+
+ case 791: /* Load Floating-Point Double Pair Indexed */
+ tmp = tdep->ppc_fp0_regnum + (PPC_FRT (insn) & ~1);
+ record_full_arch_list_add_reg (regcache, tmp);
+ record_full_arch_list_add_reg (regcache, tmp + 1);
+ return 0;
+
+ case 179: /* Move To VSR Doubleword */
+ case 211: /* Move To VSR Word Algebraic */
+ case 243: /* Move To VSR Word and Zero */
+ case 588: /* Load VSX Scalar Doubleword Indexed */
+ case 524: /* Load VSX Scalar Single-Precision Indexed */
+ case 76: /* Load VSX Scalar as Integer Word Algebraic Indexed */
+ case 12: /* Load VSX Scalar as Integer Word and Zero Indexed */
+ case 844: /* Load VSX Vector Doubleword*2 Indexed */
+ case 332: /* Load VSX Vector Doubleword & Splat Indexed */
+ case 780: /* Load VSX Vector Word*4 Indexed */
+ ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+ return 0;
+
+ /* These write RA. Update CR if RC is set. */
+ case 24: /* Shift Left Word */
+ case 26: /* Count Leading Zeros Word */
+ case 27: /* Shift Left Doubleword */
+ case 28: /* AND */
+ case 58: /* Count Leading Zeros Doubleword */
+ case 60: /* AND with Complement */
+ case 124: /* NOR */
+ case 284: /* Equivalent */
+ case 316: /* XOR */
+ case 476: /* NAND */
+ case 412: /* OR with Complement */
+ case 444: /* OR */
+ case 536: /* Shift Right Word */
+ case 539: /* Shift Right Doubleword */
+ case 922: /* Extend Sign Halfword */
+ case 954: /* Extend Sign Byte */
+ case 986: /* Extend Sign Word */
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ return 0;
+
+ /* Store memory. */
+ case 181: /* Store Doubleword with Update Indexed */
+ case 183: /* Store Word with Update Indexed */
+ case 247: /* Store Byte with Update Indexed */
+ case 439: /* Store Half Word with Update Indexed */
+ case 695: /* Store Floating-Point Single with Update Indexed */
+ case 759: /* Store Floating-Point Double with Update Indexed */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ /* FALL-THROUGH */
+ case 135: /* Store Vector Element Byte Indexed */
+ case 167: /* Store Vector Element Halfword Indexed */
+ case 199: /* Store Vector Element Word Indexed */
+ case 231: /* Store Vector Indexed */
+ case 487: /* Store Vector Indexed LRU */
+ case 716: /* Store VSX Scalar Doubleword Indexed */
+ case 140: /* Store VSX Scalar as Integer Word Indexed */
+ case 652: /* Store VSX Scalar Single-Precision Indexed */
+ case 972: /* Store VSX Vector Doubleword*2 Indexed */
+ case 908: /* Store VSX Vector Word*4 Indexed */
+ case 149: /* Store Doubleword Indexed */
+ case 151: /* Store Word Indexed */
+ case 215: /* Store Byte Indexed */
+ case 407: /* Store Half Word Indexed */
+ case 694: /* Store Byte Conditional Indexed */
+ case 726: /* Store Halfword Conditional Indexed */
+ case 150: /* Store Word Conditional Indexed */
+ case 214: /* Store Doubleword Conditional Indexed */
+ case 182: /* Store Quadword Conditional Indexed */
+ case 662: /* Store Word Byte-Reverse Indexed */
+ case 918: /* Store Halfword Byte-Reverse Indexed */
+ case 660: /* Store Doubleword Byte-Reverse Indexed */
+ case 663: /* Store Floating-Point Single Indexed */
+ case 727: /* Store Floating-Point Double Indexed */
+ case 919: /* Store Floating-Point Double Pair Indexed */
+ case 983: /* Store Floating-Point as Integer Word Indexed */
+ if (ext == 694 || ext == 726 || ext == 150 || ext == 214 || ext == 182)
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+
+ ra = 0;
+ if (PPC_RA (insn) != 0)
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn), &ra);
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + PPC_RB (insn), &rb);
+ ea = ra + rb;
+
+ switch (ext)
+ {
+ case 183: /* Store Word with Update Indexed */
+ case 199: /* Store Vector Element Word Indexed */
+ case 140: /* Store VSX Scalar as Integer Word Indexed */
+ case 652: /* Store VSX Scalar Single-Precision Indexed */
+ case 151: /* Store Word Indexed */
+ case 150: /* Store Word Conditional Indexed */
+ case 662: /* Store Word Byte-Reverse Indexed */
+ case 663: /* Store Floating-Point Single Indexed */
+ case 695: /* Store Floating-Point Single with Update Indexed */
+ case 983: /* Store Floating-Point as Integer Word Indexed */
+ size = 4;
+ break;
+ case 247: /* Store Byte with Update Indexed */
+ case 135: /* Store Vector Element Byte Indexed */
+ case 215: /* Store Byte Indexed */
+ case 694: /* Store Byte Conditional Indexed */
+ size = 1;
+ break;
+ case 439: /* Store Halfword with Update Indexed */
+ case 167: /* Store Vector Element Halfword Indexed */
+ case 407: /* Store Halfword Indexed */
+ case 726: /* Store Halfword Conditional Indexed */
+ case 918: /* Store Halfword Byte-Reverse Indexed */
+ size = 2;
+ break;
+ case 181: /* Store Doubleword with Update Indexed */
+ case 716: /* Store VSX Scalar Doubleword Indexed */
+ case 149: /* Store Doubleword Indexed */
+ case 214: /* Store Doubleword Conditional Indexed */
+ case 660: /* Store Doubleword Byte-Reverse Indexed */
+ case 727: /* Store Floating-Point Double Indexed */
+ case 759: /* Store Floating-Point Double with Update Indexed */
+ size = 8;
+ break;
+ case 972: /* Store VSX Vector Doubleword*2 Indexed */
+ case 908: /* Store VSX Vector Word*4 Indexed */
+ case 182: /* Store Quadword Conditional Indexed */
+ case 231: /* Store Vector Indexed */
+ case 487: /* Store Vector Indexed LRU */
+ case 919: /* Store Floating-Point Double Pair Indexed */
+ size = 16;
+ break;
+ default:
+ gdb_assert (0);
+ }
+
+ /* Align address for Store Vector instructions. */
+ switch (ext)
+ {
+ case 167: /* Store Vector Element Halfword Indexed */
+ addr = addr & ~0x1ULL;
+ break;
+
+ case 199: /* Store Vector Element Word Indexed */
+ addr = addr & ~0x3ULL;
+ break;
+
+ case 231: /* Store Vector Indexed */
+ case 487: /* Store Vector Indexed LRU */
+ addr = addr & ~0xfULL;
+ break;
+ }
+
+ record_full_arch_list_add_mem (addr, size);
+ return 0;
+
+ case 725: /* Store String Word Immediate */
+ ra = 0;
+ if (PPC_RA (insn) != 0)
+ regcache_raw_read_unsigned (regcache, tdep->ppc_xer_regnum, &ra);
+ ea += ra;
+
+ nb = PPC_NB (insn);
+ if (nb == 0)
+ nb = 32;
+
+ record_full_arch_list_add_mem (ea, nb);
+
+ return 0;
+
+ case 661: /* Store String Word Indexed */
+ ra = 0;
+ if (PPC_RA (insn) != 0)
+ regcache_raw_read_unsigned (regcache, tdep->ppc_xer_regnum, &ra);
+ ea += ra;
+
+ regcache_raw_read_unsigned (regcache, tdep->ppc_xer_regnum, &xer);
+ nb = PPC_XER_NB (xer);
+
+ if (nb != 0)
+ {
+ regcache_raw_read_unsigned (regcache, tdep->ppc_xer_regnum, &rb);
+ ea += rb;
+ record_full_arch_list_add_mem (ea, nb);
+ }
+
+ return 0;
+
+ case 467: /* Move To Special Purpose Register */
+ switch (PPC_SPR (insn))
+ {
+ case 1: /* XER */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+ return 0;
+ case 8: /* LR */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum);
+ return 0;
+ case 9: /* CTR */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum);
+ return 0;
+ case 256: /* VRSAVE */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_vrsave_regnum);
+ return 0;
+ }
+
+ goto UNKNOWN_OP;
+
+ case 147: /* Move To Split Little Endian */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_ps_regnum);
+ return 0;
+
+ case 512: /* Move to Condition Register from XER */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+ return 0;
+
+ case 4: /* Trap Word */
+ case 68: /* Trap Doubleword */
+ case 430: /* Clear BHRB */
+ case 598: /* Synchronize */
+ case 62: /* Wait for Interrupt */
+ case 22: /* Instruction Cache Block Touch */
+ case 854: /* Enforce In-order Execution of I/O */
+ case 246: /* Data Cache Block Touch for Store */
+ case 54: /* Data Cache Block Store */
+ case 86: /* Data Cache Block Flush */
+ case 278: /* Data Cache Block Touch */
+ case 758: /* Data Cache Block Allocate */
+ case 982: /* Instruction Cache Block Invalidate */
+ return 0;
+
+ case 654: /* Transaction Begin */
+ case 686: /* Transaction End */
+ case 718: /* Transaction Check */
+ case 750: /* Transaction Suspend or Resume */
+ case 782: /* Transaction Abort Word Conditional */
+ case 814: /* Transaction Abort Doubleword Conditional */
+ case 846: /* Transaction Abort Word Conditional Immediate */
+ case 878: /* Transaction Abort Doubleword Conditional Immediate */
+ case 910: /* Transaction Abort */
+ fprintf_unfiltered (gdb_stdlog, "Cannot record Transaction instructions. "
+ "%08x at %08lx, 31-%d.\n", insn, addr, ext);
+ return -1;
+
+ case 1014: /* Data Cache Block set to Zero */
+ if (target_auxv_search (&current_target, AT_DCACHEBSIZE, &at_dcsz) <= 0
+ || at_dcsz == 0)
+ at_dcsz = 128; /* Assume 128-byte cache line size (POWER8) */
+
+ if (PPC_RA (insn) != 0)
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn), &ra);
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + PPC_RB (insn), &rb);
+ ea = (ra + rb) & ~((ULONGEST) (at_dcsz - 1));
+ record_full_arch_list_add_mem (ea, at_dcsz);
+ return 0;
+ }
+
+UNKNOWN_OP:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
+ "%08x at %08lx, 31-%d.\n", insn, addr, ext);
+ return -1;
+}
+
+/* Parse instructions of primary opcode-59. */
+
+static int
+ppc_process_record_op59 (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR addr, uint32_t insn)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int ext = PPC_EXTOP (insn);
+
+ switch (ext & 0x1f)
+ {
+ case 18: /* Floating Divide */
+ case 20: /* Floating Subtract */
+ case 21: /* Floating Add */
+ case 22: /* Floating Square Root */
+ case 24: /* Floating Reciprocal Estimate */
+ case 25: /* Floating Multiply */
+ case 26: /* Floating Reciprocal Square Root Estimate */
+ case 28: /* Floating Multiply-Subtract */
+ case 29: /* Floating Multiply-Add */
+ case 30: /* Floating Negative Multiply-Subtract */
+ case 31: /* Floating Negative Multiply-Add */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+
+ return 0;
+ }
+
+ switch (ext)
+ {
+ case 2: /* DFP Add */
+ case 3: /* DFP Quantize */
+ case 34: /* DFP Multiply */
+ case 35: /* DFP Reround */
+ case 67: /* DFP Quantize Immediate */
+ case 99: /* DFP Round To FP Integer With Inexact */
+ case 227: /* DFP Round To FP Integer Without Inexact */
+ case 258: /* DFP Convert To DFP Long! */
+ case 290: /* DFP Convert To Fixed */
+ case 514: /* DFP Subtract */
+ case 546: /* DFP Divide */
+ case 770: /* DFP Round To DFP Short! */
+ case 802: /* DFP Convert From Fixed */
+ case 834: /* DFP Encode BCD To DPD */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ /* FALL-THROUGH */
+ case 130: /* DFP Compare Ordered */
+ case 162: /* DFP Test Exponent */
+ case 194: /* DFP Test Data Class */
+ case 226: /* DFP Test Data Group */
+ case 642: /* DFP Compare Unordered */
+ case 674: /* DFP Test Significance */
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ return 0;
+
+ case 66: /* DFP Shift Significand Left Immediate */
+ case 98: /* DFP Shift Significand Right Immediate */
+ case 322: /* DFP Decode DPD To BCD */
+ case 354: /* DFP Extract Biased Exponent */
+ case 866: /* DFP Insert Biased Exponent */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ return 0;
+
+ case 846: /* Floating Convert From Integer Doubleword Single */
+ case 974: /* Floating Convert From Integer Doubleword Unsigned
+ Single */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+
+ return 0;
+ }
+
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
+ "%08x at %08lx, 59-%d.\n", insn, addr, ext);
+ return -1;
+}
+
+/* Parse instructions of primary opcode-60. */
+
+static int
+ppc_process_record_op60 (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR addr, uint32_t insn)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int ext = PPC_EXTOP (insn);
+ int tmp;
+
+ switch (ext >> 2)
+ {
+ case 0: /* VSX Scalar Add Single-Precision */
+ case 32: /* VSX Scalar Add Double-Precision */
+ case 24: /* VSX Scalar Divide Single-Precision */
+ case 56: /* VSX Scalar Divide Double-Precision */
+ case 176: /* VSX Scalar Copy Sign Double-Precision */
+ case 33: /* VSX Scalar Multiply-Add Double-Precision */
+ case 41: /* ditto */
+ case 1: /* VSX Scalar Multiply-Add Single-Precision */
+ case 9: /* ditto */
+ case 160: /* VSX Scalar Maximum Double-Precision */
+ case 168: /* VSX Scalar Minimum Double-Precision */
+ case 49: /* VSX Scalar Multiply-Subtract Double-Precision */
+ case 57: /* ditto */
+ case 17: /* VSX Scalar Multiply-Subtract Single-Precision */
+ case 25: /* ditto */
+ case 48: /* VSX Scalar Multiply Double-Precision */
+ case 16: /* VSX Scalar Multiply Single-Precision */
+ case 161: /* VSX Scalar Negative Multiply-Add Double-Precision */
+ case 169: /* ditto */
+ case 129: /* VSX Scalar Negative Multiply-Add Single-Precision */
+ case 137: /* ditto */
+ case 177: /* VSX Scalar Negative Multiply-Subtract Double-Precision */
+ case 185: /* ditto */
+ case 145: /* VSX Scalar Negative Multiply-Subtract Single-Precision */
+ case 153: /* ditto */
+ case 40: /* VSX Scalar Subtract Double-Precision */
+ case 8: /* VSX Scalar Subtract Single-Precision */
+ case 61: /* VSX Scalar Test for software Divide Double-Precision */
+ case 96: /* VSX Vector Add Double-Precision */
+ case 64: /* VSX Vector Add Single-Precision */
+ case 240: /* VSX Vector Copy Sign Double-Precision */
+ case 208: /* VSX Vector Copy Sign Single-Precision */
+ case 120: /* VSX Vector Divide Double-Precision */
+ case 88: /* VSX Vector Divide Single-Precision */
+ case 97: /* VSX Vector Multiply-Add Double-Precision */
+ case 105: /* ditto */
+ case 65: /* VSX Vector Multiply-Add Single-Precision */
+ case 73: /* ditto */
+ case 224: /* VSX Vector Maximum Double-Precision */
+ case 192: /* VSX Vector Maximum Single-Precision */
+ case 232: /* VSX Vector Minimum Double-Precision */
+ case 200: /* VSX Vector Minimum Single-Precision */
+ case 113: /* VSX Vector Multiply-Subtract Double-Precision */
+ case 121: /* ditto */
+ case 81: /* VSX Vector Multiply-Subtract Single-Precision */
+ case 89: /* ditto */
+ case 112: /* VSX Vector Multiply Double-Precision */
+ case 80: /* VSX Vector Multiply Single-Precision */
+ case 225: /* VSX Vector Negative Multiply-Add Double-Precision */
+ case 233: /* ditto */
+ case 193: /* VSX Vector Negative Multiply-Add Single-Precision */
+ case 201: /* ditto */
+ case 241: /* VSX Vector Negative Multiply-Subtract Double-Precision */
+ case 249: /* ditto */
+ case 209: /* VSX Vector Negative Multiply-Subtract Single-Precision */
+ case 217: /* ditto */
+ case 104: /* VSX Vector Subtract Double-Precision */
+ case 72: /* VSX Vector Subtract Single-Precision */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ case 130: /* VSX Logical AND */
+ case 138: /* VSX Logical AND with Complement */
+ case 186: /* VSX Logical Equivalence */
+ case 178: /* VSX Logical NAND */
+ case 170: /* VSX Logical OR with Complement */
+ case 162: /* VSX Logical NOR */
+ case 146: /* VSX Logical OR */
+ case 154: /* VSX Logical XOR */
+ case 18: /* VSX Merge High Word */
+ case 50: /* VSX Merge Low Word */
+ case 10: /* VSX Permute Doubleword Immediate (DM=0) */
+ case 10 | 0x20: /* VSX Permute Doubleword Immediate (DM=1) */
+ case 10 | 0x40: /* VSX Permute Doubleword Immediate (DM=2) */
+ case 10 | 0x60: /* VSX Permute Doubleword Immediate (DM=3) */
+ case 2: /* VSX Shift Left Double by Word Immediate (SHW=0) */
+ case 2 | 0x20: /* VSX Shift Left Double by Word Immediate (SHW=1) */
+ case 2 | 0x40: /* VSX Shift Left Double by Word Immediate (SHW=2) */
+ case 2 | 0x60: /* VSX Shift Left Double by Word Immediate (SHW=3) */
+ ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+ return 0;
+
+ case 125: /* VSX Vector Test for software Divide Double-Precision */
+ case 93: /* VSX Vector Test for software Divide Single-Precision */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ return 0;
+
+ case 35: /* VSX Scalar Compare Unordered Double-Precision */
+ case 43: /* VSX Scalar Compare Ordered Double-Precision */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ return 0;
+ }
+
+ switch ((ext >> 2) & 0x7f) /* Mask out Rc-bit. */
+ {
+ case 99: /* VSX Vector Compare Equal To Double-Precision */
+ case 67: /* VSX Vector Compare Equal To Single-Precision */
+ case 115: /* VSX Vector Compare Greater Than or
+ Equal To Double-Precision */
+ case 83: /* VSX Vector Compare Greater Than or
+ Equal To Single-Precision */
+ case 107: /* VSX Vector Compare Greater Than Double-Precision */
+ case 75: /* VSX Vector Compare Greater Than Single-Precision */
+ if (PPC_Rc (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+ return 0;
+ }
+
+ switch (ext >> 1)
+ {
+ case 265: /* VSX Scalar round Double-Precision to
+ Single-Precision and Convert to
+ Single-Precision format */
+ case 344: /* VSX Scalar truncate Double-Precision to
+ Integer and Convert to Signed Integer
+ Doubleword format with Saturate */
+ case 88: /* VSX Scalar truncate Double-Precision to
+ Integer and Convert to Signed Integer Word
+ Format with Saturate */
+ case 328: /* VSX Scalar truncate Double-Precision integer
+ and Convert to Unsigned Integer Doubleword
+ Format with Saturate */
+ case 72: /* VSX Scalar truncate Double-Precision to
+ Integer and Convert to Unsigned Integer Word
+ Format with Saturate */
+ case 329: /* VSX Scalar Convert Single-Precision to
+ Double-Precision format */
+ case 376: /* VSX Scalar Convert Signed Integer
+ Doubleword to floating-point format and
+ Round to Double-Precision format */
+ case 312: /* VSX Scalar Convert Signed Integer
+ Doubleword to floating-point format and
+ round to Single-Precision */
+ case 360: /* VSX Scalar Convert Unsigned Integer
+ Doubleword to floating-point format and
+ Round to Double-Precision format */
+ case 296: /* VSX Scalar Convert Unsigned Integer
+ Doubleword to floating-point format and
+ Round to Single-Precision */
+ case 73: /* VSX Scalar Round to Double-Precision Integer
+ Using Round to Nearest Away */
+ case 107: /* VSX Scalar Round to Double-Precision Integer
+ Exact using Current rounding mode */
+ case 121: /* VSX Scalar Round to Double-Precision Integer
+ Using Round toward -Infinity */
+ case 105: /* VSX Scalar Round to Double-Precision Integer
+ Using Round toward +Infinity */
+ case 89: /* VSX Scalar Round to Double-Precision Integer
+ Using Round toward Zero */
+ case 90: /* VSX Scalar Reciprocal Estimate Double-Precision */
+ case 26: /* VSX Scalar Reciprocal Estimate Single-Precision */
+ case 281: /* VSX Scalar Round to Single-Precision */
+ case 74: /* VSX Scalar Reciprocal Square Root Estimate
+ Double-Precision */
+ case 10: /* VSX Scalar Reciprocal Square Root Estimate
+ Single-Precision */
+ case 75: /* VSX Scalar Square Root Double-Precision */
+ case 11: /* VSX Scalar Square Root Single-Precision */
+ case 393: /* VSX Vector round Double-Precision to
+ Single-Precision and Convert to
+ Single-Precision format */
+ case 472: /* VSX Vector truncate Double-Precision to
+ Integer and Convert to Signed Integer
+ Doubleword format with Saturate */
+ case 216: /* VSX Vector truncate Double-Precision to
+ Integer and Convert to Signed Integer Word
+ Format with Saturate */
+ case 456: /* VSX Vector truncate Double-Precision to
+ Integer and Convert to Unsigned Integer
+ Doubleword format with Saturate */
+ case 200: /* VSX Vector truncate Double-Precision to
+ Integer and Convert to Unsigned Integer Word
+ Format with Saturate */
+ case 457: /* VSX Vector Convert Single-Precision to
+ Double-Precision format */
+ case 408: /* VSX Vector truncate Single-Precision to
+ Integer and Convert to Signed Integer
+ Doubleword format with Saturate */
+ case 152: /* VSX Vector truncate Single-Precision to
+ Integer and Convert to Signed Integer Word
+ Format with Saturate */
+ case 392: /* VSX Vector truncate Single-Precision to
+ Integer and Convert to Unsigned Integer
+ Doubleword format with Saturate */
+ case 136: /* VSX Vector truncate Single-Precision to
+ Integer and Convert to Unsigned Integer Word
+ Format with Saturate */
+ case 504: /* VSX Vector Convert and round Signed Integer
+ Doubleword to Double-Precision format */
+ case 440: /* VSX Vector Convert and round Signed Integer
+ Doubleword to Single-Precision format */
+ case 248: /* VSX Vector Convert Signed Integer Word to
+ Double-Precision format */
+ case 184: /* VSX Vector Convert and round Signed Integer
+ Word to Single-Precision format */
+ case 488: /* VSX Vector Convert and round Unsigned
+ Integer Doubleword to Double-Precision format */
+ case 424: /* VSX Vector Convert and round Unsigned
+ Integer Doubleword to Single-Precision format */
+ case 232: /* VSX Vector Convert and round Unsigned
+ Integer Word to Double-Precision format */
+ case 168: /* VSX Vector Convert and round Unsigned
+ Integer Word to Single-Precision format */
+ case 201: /* VSX Vector Round to Double-Precision
+ Integer using round to Nearest Away */
+ case 235: /* VSX Vector Round to Double-Precision
+ Integer Exact using Current rounding mode */
+ case 249: /* VSX Vector Round to Double-Precision
+ Integer using round toward -Infinity */
+ case 233: /* VSX Vector Round to Double-Precision
+ Integer using round toward +Infinity */
+ case 217: /* VSX Vector Round to Double-Precision
+ Integer using round toward Zero */
+ case 218: /* VSX Vector Reciprocal Estimate Double-Precision */
+ case 154: /* VSX Vector Reciprocal Estimate Single-Precision */
+ case 137: /* VSX Vector Round to Single-Precision Integer
+ Using Round to Nearest Away */
+ case 171: /* VSX Vector Round to Single-Precision Integer
+ Exact Using Current rounding mode */
+ case 185: /* VSX Vector Round to Single-Precision Integer
+ Using Round toward -Infinity */
+ case 169: /* VSX Vector Round to Single-Precision Integer
+ Using Round toward +Infinity */
+ case 153: /* VSX Vector Round to Single-Precision Integer
+ Using round toward Zero */
+ case 202: /* VSX Vector Reciprocal Square Root Estimate
+ Double-Precision */
+ case 138: /* VSX Vector Reciprocal Square Root Estimate
+ Single-Precision */
+ case 203: /* VSX Vector Square Root Double-Precision */
+ case 139: /* VSX Vector Square Root Single-Precision */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ case 345: /* VSX Scalar Absolute Value Double-Precision */
+ case 267: /* VSX Scalar Convert Scalar Single-Precision to
+ Vector Single-Precision format Non-signalling */
+ case 331: /* VSX Scalar Convert Single-Precision to
+ Double-Precision format Non-signalling */
+ case 361: /* VSX Scalar Negative Absolute Value Double-Precision */
+ case 377: /* VSX Scalar Negate Double-Precision */
+ case 473: /* VSX Vector Absolute Value Double-Precision */
+ case 409: /* VSX Vector Absolute Value Single-Precision */
+ case 489: /* VSX Vector Negative Absolute Value Double-Precision */
+ case 425: /* VSX Vector Negative Absolute Value Single-Precision */
+ case 505: /* VSX Vector Negate Double-Precision */
+ case 441: /* VSX Vector Negate Single-Precision */
+ case 164: /* VSX Splat Word */
+ ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+ return 0;
+
+ case 106: /* VSX Scalar Test for software Square Root
+ Double-Precision */
+ case 234: /* VSX Vector Test for software Square Root
+ Double-Precision */
+ case 170: /* VSX Vector Test for software Square Root
+ Single-Precision */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ return 0;
+ }
+
+ if (((ext >> 3) & 0x3) == 3) /* VSX Select */
+ {
+ ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+ return 0;
+ }
+
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
+ "%08x at %08lx, 60-%d.\n", insn, addr, ext);
+ return -1;
+}
+
+/* Parse instructions of primary opcode-63. */
+
+static int
+ppc_process_record_op63 (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR addr, uint32_t insn)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int ext = PPC_EXTOP (insn);
+ int tmp;
+
+ switch (ext & 0x1f)
+ {
+ case 18: /* Floating Divide */
+ case 20: /* Floating Subtract */
+ case 21: /* Floating Add */
+ case 22: /* Floating Square Root */
+ case 24: /* Floating Reciprocal Estimate */
+ case 25: /* Floating Multiply */
+ case 26: /* Floating Reciprocal Square Root Estimate */
+ case 28: /* Floating Multiply-Subtract */
+ case 29: /* Floating Multiply-Add */
+ case 30: /* Floating Negative Multiply-Subtract */
+ case 31: /* Floating Negative Multiply-Add */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ return 0;
+ }
+
+ switch (ext)
+ {
+ case 2: /* DFP Add Quad */
+ case 3: /* DFP Quantize Quad */
+ case 34: /* DFP Multiply Quad */
+ case 35: /* DFP Reround Quad */
+ case 67: /* DFP Quantize Immediate Quad */
+ case 99: /* DFP Round To FP Integer With Inexact Quad */
+ case 227: /* DFP Round To FP Integer Without Inexact Quad */
+ case 258: /* DFP Convert To DFP Extended Quad */
+ case 514: /* DFP Subtract Quad */
+ case 546: /* DFP Divide Quad */
+ case 770: /* DFP Round To DFP Long Quad */
+ case 802: /* DFP Convert From Fixed Quad */
+ case 834: /* DFP Encode BCD To DPD Quad */
+ tmp = tdep->ppc_fp0_regnum + (PPC_FRT (insn) & ~1);
+ record_full_arch_list_add_reg (regcache, tmp);
+ record_full_arch_list_add_reg (regcache, tmp + 1);
+ /* FALL-THROUGH */
+ case 130: /* DFP Compare Ordered Quad */
+ case 162: /* DFP Test Exponent Quad */
+ case 194: /* DFP Test Data Class Quad */
+ case 226: /* DFP Test Data Group Quad */
+ case 642: /* DFP Compare Unordered Quad */
+ case 674: /* DFP Test Significance Quad */
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ return 0;
+
+ case 66: /* DFP Shift Significand Left Immediate Quad */
+ case 98: /* DFP Shift Significand Right Immediate Quad */
+ case 322: /* DFP Decode DPD To BCD Quad */
+ case 866: /* DFP Insert Biased Exponent Quad */
+ tmp = tdep->ppc_fp0_regnum + (PPC_FRT (insn) & ~1);
+ record_full_arch_list_add_reg (regcache, tmp);
+ record_full_arch_list_add_reg (regcache, tmp + 1);
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ return 0;
+
+ case 290: /* DFP Convert To Fixed Quad */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ break;
+
+ case 354: /* DFP Extract Biased Exponent Quad */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ return 0;
+
+ case 12: /* Floating Round to Single-Precision */
+ case 14: /* Floating Convert To Integer Word */
+ case 15: /* Floating Convert To Integer Word
+ with round toward Zero */
+ case 142: /* Floating Convert To Integer Word Unsigned */
+ case 143: /* Floating Convert To Integer Word Unsigned
+ with round toward Zero */
+ case 392: /* Floating Round to Integer Nearest */
+ case 424: /* Floating Round to Integer Toward Zero */
+ case 456: /* Floating Round to Integer Plus */
+ case 488: /* Floating Round to Integer Minus */
+ case 814: /* Floating Convert To Integer Doubleword */
+ case 815: /* Floating Convert To Integer Doubleword
+ with round toward Zero */
+ case 846: /* Floating Convert From Integer Doubleword */
+ case 942: /* Floating Convert To Integer Doubleword Unsigned */
+ case 943: /* Floating Convert To Integer Doubleword Unsigned
+ with round toward Zero */
+ case 974: /* Floating Convert From Integer Doubleword Unsigned */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ return 0;
+
+ case 8: /* Floating Copy Sign */
+ case 40: /* Floating Negate */
+ case 72: /* Floating Move Register */
+ case 136: /* Floating Negative Absolute Value */
+ case 264: /* Floating Absolute Value */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ return 0;
+
+
+ case 23: /* Floating Select */
+ case 583: /* Move From FPSCR */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ /* FALL-THROUGH */
+ case 838: /* Floating Merge Odd Word */
+ case 966: /* Floating Merge Even Word */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ return 0;
+
+ case 38: /* Move To FPSCR Bit 1 */
+ case 70: /* Move To FPSCR Bit 0 */
+ case 134: /* Move To FPSCR Field Immediate */
+ case 711: /* Move To FPSCR Fields */
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ break;
+
+ case 0: /* Floating Compare Unordered */
+ case 32: /* Floating Compare Ordered */
+ case 64: /* Move to Condition Register from FPSCR */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ /* FALL-THROUGH */
+ case 128: /* Floating Test for software Divide */
+ case 160: /* Floating Test for software Square Root */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ return 0;
+
+ }
+
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
+ "%08x at %08lx, 59-%d.\n", insn, addr, ext);
+ return -1;
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to "record_arch_list".
+ Return -1 if something wrong. */
+
+int
+ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR addr)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t insn;
+ int op6, tmp, i;
+
+ insn = read_memory_unsigned_integer (addr, 4, byte_order);
+ op6 = PPC_OP6 (insn);
+
+ switch (op6)
+ {
+ case 2: /* Trap Doubleword Immediate */
+ case 3: /* Trap Word Immediate */
+ /* Do nothing. */
+ break;
+
+ case 4:
+ if (ppc_process_record_op4 (gdbarch, regcache, addr, insn) != 0)
+ return -1;
+ break;
+
+ case 17: /* System call */
+ if (PPC_LEV (insn) != 0)
+ goto UNKNOWN_OP;
+
+ if (tdep->ppc_syscall_record != NULL)
+ {
+ if (tdep->ppc_syscall_record (regcache) != 0)
+ return -1;
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ break;
+
+ case 7: /* Multiply Low Immediate */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ break;
+
+ case 8: /* Subtract From Immediate Carrying */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ break;
+
+ case 10: /* Compare Logical Immediate */
+ case 11: /* Compare Immediate */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ break;
+
+ case 13: /* Add Immediate Carrying and Record */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ /* FALL-THROUGH */
+ case 12: /* Add Immediate Carrying */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+ /* FALL-THROUGH */
+ case 14: /* Add Immediate */
+ case 15: /* Add Immediate Shifted */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ break;
+
+ case 16: /* Branch Conditional */
+ if ((PPC_BO (insn) & 0x4) == 0)
+ record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum);
+ /* FALL-THROUGH */
+ case 18: /* Branch */
+ if (PPC_LK (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum);
+ break;
+
+ case 19:
+ if (ppc_process_record_op19 (gdbarch, regcache, addr, insn) != 0)
+ return -1;
+ break;
+
+ case 20: /* Rotate Left Word Immediate then Mask Insert */
+ case 21: /* Rotate Left Word Immediate then AND with Mask */
+ case 23: /* Rotate Left Word then AND with Mask */
+ case 30: /* Rotate Left Doubleword Immediate then Clear Left */
+ /* Rotate Left Doubleword Immediate then Clear Right */
+ /* Rotate Left Doubleword Immediate then Clear */
+ /* Rotate Left Doubleword then Clear Left */
+ /* Rotate Left Doubleword then Clear Right */
+ /* Rotate Left Doubleword Immediate then Mask Insert */
+ if (PPC_RC (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ break;
+
+ case 28: /* AND Immediate */
+ case 29: /* AND Immediate Shifted */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ /* FALL-THROUGH */
+ case 24: /* OR Immediate */
+ case 25: /* OR Immediate Shifted */
+ case 26: /* XOR Immediate */
+ case 27: /* XOR Immediate Shifted */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ break;
+
+ case 31:
+ if (ppc_process_record_op31 (gdbarch, regcache, addr, insn) != 0)
+ return -1;
+ break;
+
+ case 33: /* Load Word and Zero with Update */
+ case 35: /* Load Byte and Zero with Update */
+ case 41: /* Load Halfword and Zero with Update */
+ case 43: /* Load Halfword Algebraic with Update */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ /* FALL-THROUGH */
+ case 32: /* Load Word and Zero */
+ case 34: /* Load Byte and Zero */
+ case 40: /* Load Halfword and Zero */
+ case 42: /* Load Halfword Algebraic */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ break;
+
+ case 46: /* Load Multiple Word */
+ for (i = PPC_RT (insn); i < 32; i++)
+ record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + i);
+ break;
+
+ case 56: /* Load Quadword */
+ if (PPC_FIELD (insn, 30, 2) != 0)
+ goto UNKNOWN_OP;
+ tmp = tdep->ppc_gp0_regnum + (PPC_RT (insn) & ~1);
+ record_full_arch_list_add_reg (regcache, tmp);
+ record_full_arch_list_add_reg (regcache, tmp + 1);
+ break;
+
+ case 49: /* Load Floating-Point Single with Update */
+ case 51: /* Load Floating-Point Double with Update */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ /* FALL-THROUGH */
+ case 48: /* Load Floating-Point Single */
+ case 50: /* Load Floating-Point Double */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum + PPC_FRT (insn));
+ break;
+
+ case 47: /* Store Multiple Word */
+ {
+ ULONGEST addr = 0;
+
+ if (PPC_RA (insn) != 0)
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn),
+ &addr);
+
+ addr += PPC_D (insn);
+ record_full_arch_list_add_mem (addr, 4 * (32 - PPC_RS (insn)));
+ }
+ break;
+
+ case 37: /* Store Word with Update */
+ case 39: /* Store Byte with Update */
+ case 45: /* Store Halfword with Update */
+ case 53: /* Store Floating-Point Single with Update */
+ case 55: /* Store Floating-Point Double with Update */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ /* FALL-THROUGH */
+ case 36: /* Store Word */
+ case 38: /* Store Byte */
+ case 44: /* Store Halfword */
+ case 52: /* Store Floating-Point Single */
+ case 54: /* Store Floating-Point Double */
+ {
+ ULONGEST addr = 0;
+ int size = -1;
+
+ if (PPC_RA (insn) != 0)
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn),
+ &addr);
+ addr += PPC_D (insn);
+
+ if (op6 == 36 || op6 == 37 || op6 == 52 || op6 == 53)
+ size = 4;
+ else if (op6 == 54 || op6 == 55)
+ size = 8;
+ else if (op6 == 44 || op6 == 45)
+ size = 2;
+ else if (op6 == 38 || op6 == 39)
+ size = 1;
+ else
+ gdb_assert (0);
+
+ record_full_arch_list_add_mem (addr, size);
+ }
+ break;
+
+ case 57: /* Load Floating-Point Double Pair */
+ if (PPC_FIELD (insn, 30, 2) != 0)
+ goto UNKNOWN_OP;
+ tmp = tdep->ppc_fp0_regnum + (PPC_RT (insn) & ~1);
+ record_full_arch_list_add_reg (regcache, tmp);
+ record_full_arch_list_add_reg (regcache, tmp + 1);
+ break;
+
+ case 58: /* Load Doubleword */
+ /* Load Doubleword with Update */
+ /* Load Word Algebraic */
+ if (PPC_FIELD (insn, 30, 2) > 2)
+ goto UNKNOWN_OP;
+
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ if (PPC_BIT (insn, 31))
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn));
+ break;
+
+ case 59:
+ if (ppc_process_record_op59 (gdbarch, regcache, addr, insn) != 0)
+ return -1;
+ break;
+
+ case 60:
+ if (ppc_process_record_op60 (gdbarch, regcache, addr, insn) != 0)
+ return -1;
+ break;
+
+ case 61: /* Store Floating-Point Double Pair */
+ case 62: /* Store Doubleword */
+ /* Store Doubleword with Update */
+ /* Store Quadword with Update */
+ {
+ ULONGEST addr = 0;
+ int size;
+ int sub2 = PPC_FIELD (insn, 30, 2);
+
+ if ((op6 == 61 && sub2 != 0) || (op6 == 62 && sub2 > 2))
+ goto UNKNOWN_OP;
+
+ if (PPC_RA (insn) != 0)
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn),
+ &addr);
+
+ size = ((op6 == 61) || sub2 == 2) ? 16 : 8;
+
+ addr += PPC_DS (insn) << 2;
+ record_full_arch_list_add_mem (addr, size);
+
+ if (op6 == 62 && sub2 == 1)
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum +
+ PPC_RA (insn));
+
+ break;
+ }
+
+ case 63:
+ if (ppc_process_record_op63 (gdbarch, regcache, addr, insn) != 0)
+ return -1;
+ break;
+
+ default:
+UNKNOWN_OP:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record "
+ "%08x at %08lx, %d.\n", insn, addr, op6);
+ return -1;
+ }
+
+ if (record_full_arch_list_add_reg (regcache, PPC_PC_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_end ())
+ return -1;
+ return 0;
+}
+
/* Initialize the current architecture based on INFO. If possible, re-use an
architecture from ARCHES, which is a list of architectures already created
during this debugging session.
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 2c79bc1..c1ccb60 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -1881,7 +1881,8 @@ proc supports_process_record {} {
}

if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"]
- || [istarget "i\[34567\]86-*-linux*"] } {
+ || [istarget "i\[34567\]86-*-linux*"]
+ || [istarget "powerpc*-*-linux*"] } {
return 1
}

@@ -1897,7 +1898,8 @@ proc supports_reverse {} {
}

if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"]
- || [istarget "i\[34567\]86-*-linux*"] } {
+ || [istarget "i\[34567\]86-*-linux*"]
+ || [istarget "powerpc*-*-linux*"] } {
return 1
}

--
1.9.1