From patchwork Tue Nov 18 16:27:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wei-cheng, Wang" X-Patchwork-Id: 3787 Received: (qmail 25466 invoked by alias); 18 Nov 2014 16:27:57 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 25457 invoked by uid 89); 18 Nov 2014 16:27:56 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=3.9 required=5.0 tests=BAYES_50, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, KAM_STOCKGEN, RCVD_IN_DNSWL_LOW, SPF_PASS, UNSUBSCRIBE_BODY autolearn=no version=3.3.2 X-HELO: mail-pa0-f47.google.com Received: from mail-pa0-f47.google.com (HELO mail-pa0-f47.google.com) (209.85.220.47) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 18 Nov 2014 16:27:50 +0000 Received: by mail-pa0-f47.google.com with SMTP id kq14so5930223pab.20 for ; Tue, 18 Nov 2014 08:27:48 -0800 (PST) X-Received: by 10.66.235.135 with SMTP id um7mr38309012pac.94.1416328067929; Tue, 18 Nov 2014 08:27:47 -0800 (PST) Received: from [192.168.2.3] ([123.110.214.155]) by mx.google.com with ESMTPSA id hy15sm12291570pad.11.2014.11.18.08.27.45 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 18 Nov 2014 08:27:47 -0800 (PST) Message-ID: <546B7380.4050703@gmail.com> Date: Wed, 19 Nov 2014 00:27:44 +0800 From: "Wei-cheng, Wang" User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 MIME-Version: 1.0 To: uweigand@de.ibm.com, gdb-patches@sourceware.org CC: dje.gcc@gmail.com, green@moxielogic.com Subject: [PATCH] Process record support for PowerPC Hi, This patch is process record support for PowerPC * Tested with Advance Toolchain 8.0 ppc64 - 2326 pass, no fail * 26 fails if tested with ppc64le, due to local entry optimization. Breakpoints set on the very beginning of functions may not be hit when reverse-continue. * Support reverse-step over subroutine without debug info * Record/reverse syscall/signal * Support reverse-step through solib trampoline And these instructions are handled * All main opcode * opcode 31 -- Privileged instructions are listed, but not handled. Shoule I just remote them? * opcode 59 and 63 (Decimal Floating-Point and Floating-point) * opcode 4 (Only [vector] instructions are handled.) * opcode 19 (Only conditional and branch instruction.) SPE, Embedded, LMA, VSX and privileged instructions are not handled. Wei-cheng --- gdb/configure.tgt | 3 +- gdb/ppc-linux-tdep.c | 353 +++++++ gdb/ppc-tdep.h | 5 + gdb/rs6000-tdep.c | 1516 ++++++++++++++++++++++++++++++- gdb/testsuite/lib/gdb.exp | 6 +- 6 files changed, 1881 insertions(+), 7 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..608081c 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -49,6 +49,9 @@ #include "spu-tdep.h" #include "xml-syscall.h" #include "linux-tdep.h" +#include "linux-record.h" +#include "record-full.h" +#include "infrun.h" #include "stap-probe.h" #include "ax.h" @@ -298,6 +301,23 @@ powerpc_linux_in_dynsym_resolve_code (CORE_ADDR pc) || strcmp (MSYMBOL_LINKAGE_NAME (sym.minsym), "__glink_PLTresolve") == 0)) return 1; + else if (sym.minsym != NULL && execution_direction == EXEC_REVERSE) + { + /* When reverse stepping, gdb needs to know whether PC lies in + the dynamic symbol resolve code, so it can keep going until + reaching some user code. + Using insns-match-pattern is not suitable, because we had to + look both ahead and behind to check where we are in the middle + of one of trampline sequences. */ +#define SUBSTRCMP(sym, stub) (memcmp (sym + 8, stub, sizeof (stub) - 1) == 0) + if (SUBSTRCMP (MSYMBOL_LINKAGE_NAME (sym.minsym), ".plt_call.")) + return 1; + if (SUBSTRCMP (MSYMBOL_LINKAGE_NAME (sym.minsym), ".plt_branch.")) + return 1; + if (SUBSTRCMP (MSYMBOL_LINKAGE_NAME (sym.minsym), ".plt_branch_r2off.")) + return 1; +#undef SUBSTRCMP + } return 0; } @@ -764,6 +784,165 @@ ppc_linux_get_syscall_number (struct gdbarch *gdbarch, return ret; } +/* PPC process record-replay */ + +struct linux_record_tdep ppc_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; +} + +/* Record all registers but PC register for process-record. */ + +static int +ppc_all_but_pc_registers_record (struct regcache *regcache) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int i; + + for (i = 0; i < 32; 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_cr_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_ctr_regnum)) + return -1; + + return 0; +} + +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; + + 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) + { + if (ppc_all_but_pc_registers_record (regcache)) + return -1; + return 0; + } + + ret = record_linux_system_call (syscall_gdb, regcache, + &ppc_linux_record_tdep); + if (ret != 0) + return ret; + + /* Record registers clobbered during syscall. */ + 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_gp0_regnum + 3)) + return -1; + if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + 4)) + return -1; + if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + 5)) + return -1; + if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + 6)) + return -1; + if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + 7)) + return -1; + if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + 8)) + return -1; + if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + 9)) + return -1; + if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + 10)) + return -1; + if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + 11)) + return -1; + if (record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + 12)) + 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 +ppc64_linux_record_signal (struct gdbarch *gdbarch, + struct regcache *regcache, + enum gdb_signal signal) +{ + /* See arch/powerpc/kernel/signal_64.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); + + if (ppc_all_but_pc_registers_record (regcache)) + return -1; + + if (record_full_arch_list_add_reg (regcache, gdbarch_pc_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) { @@ -1345,6 +1524,15 @@ ppc_linux_init_abi (struct gdbarch_info info, set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_lp64_fetch_link_map_offsets); + if (powerpc_so_ops.in_dynsym_resolve_code == NULL) + { + powerpc_so_ops = svr4_so_ops; + /* Override dynamic resolve function. */ + powerpc_so_ops.in_dynsym_resolve_code = + powerpc_linux_in_dynsym_resolve_code; + } + set_solib_ops (gdbarch, &powerpc_so_ops); + /* Setting the correct XML syscall filename. */ set_xml_syscall_file_name (XML_SYSCALL_FILENAME_PPC64); @@ -1414,6 +1602,171 @@ 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, ppc64_process_record); + set_gdbarch_process_record_signal (gdbarch, ppc64_linux_record_signal); + tdep->syscall_record = ppc_linux_syscall_record; + + /* Initialize the ppc_linux_record_tdep. */ + /* These values are the size of the type that will be used in a system + call. They are obtained from Linux Kernel source. + + See arch/powerpc/include/uapi/asm/ioctls.h. */ + ppc_linux_record_tdep.size_pointer + = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; + ppc_linux_record_tdep.size__old_kernel_stat = 32; + ppc_linux_record_tdep.size_tms = 32; + ppc_linux_record_tdep.size_loff_t = 8; + ppc_linux_record_tdep.size_flock = 32; + ppc_linux_record_tdep.size_oldold_utsname = 45; + ppc_linux_record_tdep.size_ustat = 32; + ppc_linux_record_tdep.size_old_sigaction = 152; + ppc_linux_record_tdep.size_old_sigset_t = 128; + ppc_linux_record_tdep.size_rlimit = 16; + ppc_linux_record_tdep.size_rusage = 144; + ppc_linux_record_tdep.size_timeval = 16; + ppc_linux_record_tdep.size_timezone = 8; + ppc_linux_record_tdep.size_old_gid_t = 2; + ppc_linux_record_tdep.size_old_uid_t = 2; + ppc_linux_record_tdep.size_fd_set = 128; + ppc_linux_record_tdep.size_dirent = 280; + ppc_linux_record_tdep.size_dirent64 = 280; + ppc_linux_record_tdep.size_statfs = 120; + ppc_linux_record_tdep.size_statfs64 = 120; + ppc_linux_record_tdep.size_sockaddr = 16; + ppc_linux_record_tdep.size_int + = gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT; + ppc_linux_record_tdep.size_long + = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT; + ppc_linux_record_tdep.size_ulong + = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT; + ppc_linux_record_tdep.size_msghdr = 56; + ppc_linux_record_tdep.size_itimerval = 32; + ppc_linux_record_tdep.size_stat = 144; + ppc_linux_record_tdep.size_old_utsname = 325; + ppc_linux_record_tdep.size_sysinfo = 112; + ppc_linux_record_tdep.size_msqid_ds = 120; + ppc_linux_record_tdep.size_shmid_ds = 112; + ppc_linux_record_tdep.size_new_utsname = 390; + ppc_linux_record_tdep.size_timex = 208; + ppc_linux_record_tdep.size_mem_dqinfo = 24; + ppc_linux_record_tdep.size_if_dqblk = 72; + ppc_linux_record_tdep.size_fs_quota_stat = 80; + ppc_linux_record_tdep.size_timespec = 16; + ppc_linux_record_tdep.size_pollfd = 8; + ppc_linux_record_tdep.size_NFS_FHSIZE = 32; + ppc_linux_record_tdep.size_knfsd_fh = 132; + ppc_linux_record_tdep.size_TASK_COMM_LEN = 32; + ppc_linux_record_tdep.size_sigaction = 152; + ppc_linux_record_tdep.size_sigset_t = 128; + ppc_linux_record_tdep.size_siginfo_t = 128; + ppc_linux_record_tdep.size_cap_user_data_t = 8; + ppc_linux_record_tdep.size_stack_t = 24; + ppc_linux_record_tdep.size_off_t = 8; + ppc_linux_record_tdep.size_stat64 = 144; + ppc_linux_record_tdep.size_gid_t = 4; + ppc_linux_record_tdep.size_uid_t = 4; + ppc_linux_record_tdep.size_PAGE_SIZE = 4096; + ppc_linux_record_tdep.size_flock64 = 32; + ppc_linux_record_tdep.size_user_desc = 16; + ppc_linux_record_tdep.size_io_event = 32; + ppc_linux_record_tdep.size_iocb = 64; + ppc_linux_record_tdep.size_epoll_event = 12; + ppc_linux_record_tdep.size_itimerspec = 32; + ppc_linux_record_tdep.size_mq_attr = 64; + ppc_linux_record_tdep.size_siginfo = 128; + ppc_linux_record_tdep.size_termios = 60; + ppc_linux_record_tdep.size_termios2 = 44; + ppc_linux_record_tdep.size_pid_t = 4; + ppc_linux_record_tdep.size_winsize = 8; + ppc_linux_record_tdep.size_serial_struct = 72; + ppc_linux_record_tdep.size_serial_icounter_struct = 80; + ppc_linux_record_tdep.size_hayes_esp_config = 12; + ppc_linux_record_tdep.size_size_t = 8; + ppc_linux_record_tdep.size_iovec = 16; + + /* These values are the second argument of system call "sys_fcntl" + and "sys_fcntl64". They are obtained from Linux Kernel source. */ + ppc_linux_record_tdep.fcntl_F_GETLK = 5; + ppc_linux_record_tdep.fcntl_F_GETLK64 = 12; + ppc_linux_record_tdep.fcntl_F_SETLK64 = 13; + ppc_linux_record_tdep.fcntl_F_SETLKW64 = 14; + + ppc_linux_record_tdep.arg1 = PPC_R0_REGNUM + 3; + ppc_linux_record_tdep.arg2 = PPC_R0_REGNUM + 4; + ppc_linux_record_tdep.arg3 = PPC_R0_REGNUM + 5; + ppc_linux_record_tdep.arg4 = PPC_R0_REGNUM + 6; + ppc_linux_record_tdep.arg5 = PPC_R0_REGNUM + 7; + ppc_linux_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. */ + ppc_linux_record_tdep.ioctl_TCGETS = 0x5401; + ppc_linux_record_tdep.ioctl_TCSETS = 0x5402; + ppc_linux_record_tdep.ioctl_TCSETSW = 0x5403; + ppc_linux_record_tdep.ioctl_TCSETSF = 0x5404; + ppc_linux_record_tdep.ioctl_TCGETA = 0x5405; + ppc_linux_record_tdep.ioctl_TCSETA = 0x5406; + ppc_linux_record_tdep.ioctl_TCSETAW = 0x5407; + ppc_linux_record_tdep.ioctl_TCSETAF = 0x5408; + ppc_linux_record_tdep.ioctl_TCSBRK = 0x5409; + ppc_linux_record_tdep.ioctl_TCXONC = 0x540A; + ppc_linux_record_tdep.ioctl_TCFLSH = 0x540B; + ppc_linux_record_tdep.ioctl_TIOCEXCL = 0x540C; + ppc_linux_record_tdep.ioctl_TIOCNXCL = 0x540D; + ppc_linux_record_tdep.ioctl_TIOCSCTTY = 0x540E; + ppc_linux_record_tdep.ioctl_TIOCGPGRP = 0x540F; + ppc_linux_record_tdep.ioctl_TIOCSPGRP = 0x5410; + ppc_linux_record_tdep.ioctl_TIOCOUTQ = 0x5411; + ppc_linux_record_tdep.ioctl_TIOCSTI = 0x5412; + ppc_linux_record_tdep.ioctl_TIOCGWINSZ = 0x5413; + ppc_linux_record_tdep.ioctl_TIOCSWINSZ = 0x5414; + ppc_linux_record_tdep.ioctl_TIOCMGET = 0x5415; + ppc_linux_record_tdep.ioctl_TIOCMBIS = 0x5416; + ppc_linux_record_tdep.ioctl_TIOCMBIC = 0x5417; + ppc_linux_record_tdep.ioctl_TIOCMSET = 0x5418; + ppc_linux_record_tdep.ioctl_TIOCGSOFTCAR = 0x5419; + ppc_linux_record_tdep.ioctl_TIOCSSOFTCAR = 0x541A; + ppc_linux_record_tdep.ioctl_FIONREAD = 0x541B; + ppc_linux_record_tdep.ioctl_TIOCINQ = ppc_linux_record_tdep.ioctl_FIONREAD; + ppc_linux_record_tdep.ioctl_TIOCLINUX = 0x541C; + ppc_linux_record_tdep.ioctl_TIOCCONS = 0x541D; + ppc_linux_record_tdep.ioctl_TIOCGSERIAL = 0x541E; + ppc_linux_record_tdep.ioctl_TIOCSSERIAL = 0x541F; + ppc_linux_record_tdep.ioctl_TIOCPKT = 0x5420; + ppc_linux_record_tdep.ioctl_FIONBIO = 0x5421; + ppc_linux_record_tdep.ioctl_TIOCNOTTY = 0x5422; + ppc_linux_record_tdep.ioctl_TIOCSETD = 0x5423; + ppc_linux_record_tdep.ioctl_TIOCGETD = 0x5424; + ppc_linux_record_tdep.ioctl_TCSBRKP = 0x5425; + ppc_linux_record_tdep.ioctl_TIOCTTYGSTRUCT = 0x5426; + ppc_linux_record_tdep.ioctl_TIOCSBRK = 0x5427; + ppc_linux_record_tdep.ioctl_TIOCCBRK = 0x5428; + ppc_linux_record_tdep.ioctl_TIOCGSID = 0x5429; + ppc_linux_record_tdep.ioctl_TCGETS2 = 0x802c542a; + ppc_linux_record_tdep.ioctl_TCSETS2 = 0x402c542b; + ppc_linux_record_tdep.ioctl_TCSETSW2 = 0x402c542c; + ppc_linux_record_tdep.ioctl_TCSETSF2 = 0x402c542d; + ppc_linux_record_tdep.ioctl_TIOCGPTN = 0x80045430; + ppc_linux_record_tdep.ioctl_TIOCSPTLCK = 0x40045431; + ppc_linux_record_tdep.ioctl_FIONCLEX = 0x5450; + ppc_linux_record_tdep.ioctl_FIOCLEX = 0x5451; + ppc_linux_record_tdep.ioctl_FIOASYNC = 0x5452; + ppc_linux_record_tdep.ioctl_TIOCSERCONFIG = 0x5453; + ppc_linux_record_tdep.ioctl_TIOCSERGWILD = 0x5454; + ppc_linux_record_tdep.ioctl_TIOCSERSWILD = 0x5455; + ppc_linux_record_tdep.ioctl_TIOCGLCKTRMIOS = 0x5456; + ppc_linux_record_tdep.ioctl_TIOCSLCKTRMIOS = 0x5457; + ppc_linux_record_tdep.ioctl_TIOCSERGSTRUCT = 0x5458; + ppc_linux_record_tdep.ioctl_TIOCSERGETLSR = 0x5459; + ppc_linux_record_tdep.ioctl_TIOCSERGETMULTI = 0x545A; + ppc_linux_record_tdep.ioctl_TIOCSERSETMULTI = 0x545B; + ppc_linux_record_tdep.ioctl_TIOCMIWAIT = 0x545C; + ppc_linux_record_tdep.ioctl_TIOCGICOUNT = 0x545D; + ppc_linux_record_tdep.ioctl_TIOCGHAYESESP = 0x545E; + ppc_linux_record_tdep.ioctl_TIOCSHAYESESP = 0x545F; + ppc_linux_record_tdep.ioctl_FIOQSIZE = 0x5460; } /* Provide a prototype to silence -Wmissing-prototypes. */ diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h index 08554ff..437ca8c 100644 --- a/gdb/ppc-tdep.h +++ b/gdb/ppc-tdep.h @@ -259,6 +259,8 @@ struct gdbarch_tdep /* ISA-specific types. */ struct type *ppc_builtin_type_vec64; struct type *ppc_builtin_type_vec128; + + int (* syscall_record) (struct regcache *regcache); }; @@ -318,6 +320,9 @@ extern CORE_ADDR ppc_insn_d_field (unsigned int insn); extern CORE_ADDR ppc_insn_ds_field (unsigned int insn); +extern int ppc64_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 dabf448..4153454 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 */ @@ -872,14 +874,14 @@ insn_changes_sp_or_jumps (unsigned long insn) limit for the size of an epilogue. */ static int -rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +rs6000_in_function_epilogue_frame_p (struct frame_info *curfrm, + struct gdbarch *gdbarch, CORE_ADDR pc) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); bfd_byte insn_buf[PPC_INSN_SIZE]; CORE_ADDR scan_pc, func_start, func_end, epilogue_start, epilogue_end; unsigned long insn; - struct frame_info *curfrm; /* Find the search limits based on function boundaries and hard limit. */ @@ -892,8 +894,6 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) epilogue_end = pc + PPC_MAX_EPILOGUE_INSTRUCTIONS * PPC_INSN_SIZE; if (epilogue_end > func_end) epilogue_end = func_end; - curfrm = get_current_frame (); - /* Scan forward until next 'blr'. */ for (scan_pc = pc; scan_pc < epilogue_end; scan_pc += PPC_INSN_SIZE) @@ -934,6 +934,15 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) return 0; } +/* Implementation of gdbarch_in_function_epilogue_p. */ + +static int +rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + return rs6000_in_function_epilogue_frame_p (get_current_frame (), + gdbarch, pc); +} + /* Get the ith function argument for the current function. */ static CORE_ADDR rs6000_fetch_pointer_argument (struct frame_info *frame, int argi, @@ -3339,6 +3348,89 @@ static const struct frame_unwind rs6000_frame_unwind = NULL, default_frame_sniffer }; + +static struct rs6000_frame_cache * +rs6000_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + volatile struct gdb_exception ex; + struct rs6000_frame_cache *cache; + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + CORE_ADDR sp; + + if (*this_cache) + return *this_cache; + + cache = FRAME_OBSTACK_ZALLOC (struct rs6000_frame_cache); + (*this_cache) = cache; + cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + /* At this point the stack looks as if we just entered the + function, and the return address is stored in LR. */ + CORE_ADDR sp, lr; + + sp = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch)); + lr = get_frame_register_unsigned (this_frame, tdep->ppc_lr_regnum); + + cache->base = sp; + cache->initial_sp = sp; + + trad_frame_set_value (cache->saved_regs, + gdbarch_pc_regnum (gdbarch), lr); + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + + return cache; +} + +static void +rs6000_epilogue_frame_this_id (struct frame_info *this_frame, + void **this_cache, struct frame_id *this_id) +{ + CORE_ADDR pc; + struct rs6000_frame_cache *info = + rs6000_epilogue_frame_cache (this_frame, this_cache); + + pc = get_frame_func (this_frame); + if (info->base == 0) + (*this_id) = frame_id_build_unavailable_stack (pc); + else + (*this_id) = frame_id_build (info->base, pc); +} + +static struct value * +rs6000_epilogue_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct rs6000_frame_cache *info = + rs6000_epilogue_frame_cache (this_frame, this_cache); + return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); +} + +static int +rs6000_epilogue_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) +{ + if (frame_relative_level (this_frame) == 0) + return rs6000_in_function_epilogue_frame_p (this_frame, + get_frame_arch (this_frame), + get_frame_pc (this_frame)); + else + return 0; +} + +static const struct frame_unwind rs6000_epilogue_frame_unwind = +{ + NORMAL_FRAME, + default_frame_unwind_stop_reason, + rs6000_epilogue_frame_this_id, rs6000_epilogue_frame_prev_register, + NULL, + rs6000_epilogue_frame_sniffer +}; static CORE_ADDR @@ -3543,6 +3635,1420 @@ 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_BF(insn) PPC_FIELD (insn, 6, 3) +#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_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, + int size) +{ + 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); + } + else + { + if (tdep->ppc_fp0_regnum >= 0) + record_full_arch_list_add_reg (regcache, tdep->ppc_fp0_regnum + vsr); + if (size > 8 && 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 +ppc64_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) + { + /* 5.8 Vector Permute and Formatting Instructions */ + 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 */ + /* 5.9 Vector Integer Instructions */ + case 512: /* Vector Add Unsigned Byte Saturate */ + case 576: /* Vector Add Unsigned Halfword Saturate */ + case 640: /* Vector Add Unsigned Word Saturate */ + case 786: /* 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 */ + /* 5.10 Vector Floating-Point Instruction Set */ + 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 */ + /* 5.8 Vector Permute and Formatting Instructions */ + 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 */ + /* 5.9 Vector Integer Instructions */ + 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 940: /* 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 864: /* Vector Shift Right Algebraic Doubleword */ + /* 5.10 Vector Floating-Point Instruction Set */ + 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 */ + /* 5.11 Vector Exclusive-OR-based Instructions */ + 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 */ + /* 5.12 Vector Gather Instruction */ + case 1292: /* Vector Gather Bits by Bytes by Doubleword */ + /* 5.13 Vector Count Leading Zeros Instructions */ + 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 */ + /* 5.14 Vector Population Count Instructions */ + case 1795: /* Vector Population Count Byte */ + case 1859: /* Vector Population Count Halfword */ + case 1923: /* Vector Population Count Word */ + case 1987: /* Vector Population Count Doubleword */ + /* 5.15 Vector Bit Permute Instruction */ + case 1356: /* Vector Bit Permute Quadword */ + /* 5.16 Decimal Integer Arithmetic Instructions */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_vr0_regnum + PPC_VRT (insn)); + return 0; + + /* 5.17 Vector Status and Control Register Instructions */ + 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 +ppc64_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) & 0x2) + 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 +ppc64_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, at_icsz, 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 */ + /* 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 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 334: /* Move From Performance Monitor Register */ + case 339: /* Move From Special Purpose Register */ + 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_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 */ + case 853: /* Load Byte and Zero Caching Inhibited Indexed */ + case 821: /* Load Halfword and Zero Caching Inhibited Indexed */ + case 789: /* Load Word and Zero Caching Inhibited Indexed */ + case 885: /* Load Doubleword Caching Inhibited 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); + else + { + regcache_raw_read_unsigned (regcache, tdep->ppc_xer_regnum, &xer); + nr = PPC_XER_NB (xer); + } + + nr = (nr + 3) >> 2; + + 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; + + /* These write VSR of size 8. */ + case 588: /* Load VSX Scalar Doubleword Indexed */ + ppc_record_vsr (regcache, tdep, PPC_XT (insn), 8); + return 0; + + /* These write VSR of size 16. */ + case 179: /* Move To VSR Doubleword */ + case 211: /* Move To VSR Word Algebraic */ + case 243: /* Move To VSR Word and Zero */ + 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), 16); + 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 981: /* Store Byte Caching Inhibited Indexed */ + case 949: /* Store Halfword Caching Inhibited Indexed */ + case 917: /* Store Word Caching Inhibited Indexed */ + case 1013: /* Store Doubleword Caching Inhibited 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 917: /* Store Word Caching Inhibited 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 */ + case 662: /* Store Word Byte-Reverse Indexed */ + case 981: /* Store Byte Caching Inhibited Indexed */ + size = 1; + break; + case 439: /* Store Half Word with Update Indexed */ + case 167: /* Store Vector Element Halfword Indexed */ + case 407: /* Store Half Word Indexed */ + case 726: /* Store Halfword Conditional Indexed */ + case 918: /* Store Halfword Byte-Reverse Indexed */ + case 949: /* Store Halfword Caching Inhibited 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 1013: /* Store Doubleword Caching Inhibited 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; + } + + /* Align address for Store Vector instructions. */ + if ((ext & 0x1f) == 0x7) + { + if ((ext & 0x3) < 3) + addr = (addr >> (ext & 0x3)) << (ext & 0x3); + else + addr = addr & ~0x7ULL; + } + + record_full_arch_list_add_mem (addr, size); + return 0; + + case 725: /* Store String Word Immediate */ + 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; + + if (ext == 725) + nb = PPC_NB (insn); + else + { + regcache_raw_read_unsigned (regcache, tdep->ppc_xer_regnum, &xer); + nb = PPC_XER_NB (xer); + + 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; + } + + 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 */ + return 0; + + case 18: /* TLB Invalidate Local Indexed */ + case 326: /* Data Cache Read */ + case 63: /* Data Cache Block Store by External PID */ + case 127: /* Data Cache Block Flush by External PID */ + case 134: /* Data Cache Block Touch for Store and Lock Set */ + case 166: /* Data Cache Block Touch and Lock Set */ + case 255: /* Data Cache Block Touch for Store by External PID */ + case 319: /* Data Cache Block Touch by External PID */ + case 390: /* Data Cache Block Lock Clear */ + case 422: /* Data Cache Block Lock Query */ + case 454: /* Data Cache Invalidate */ + case 998: /* Instruction Cache Read */ + case 966: /* Instruction Cache Invalidate */ + case 982: /* Instruction Cache Block Invalidate */ + case 198: /* Instruction Cache Block Lock Query */ + case 230: /* Instruction Cache Block Lock Clear */ + case 486: /* Instruction Cache Block Touch and Lock Set */ + case 206: /* Message Send */ + case 238: /* Message Clear */ + case 142: /* Message Send Privileged */ + case 174: /* Message Clear Privileged */ + case 131: /* Write MSR External Enable */ + case 163: /* Write MSR External Enable Immediate */ + case 270: /* Embedded Hypervisor Privilege */ + case 462: /* Move To Performance Monitor Register */ + case 494: /* Move To Thread Management Register */ + case 807: /* Store Vector by External Process ID Indexed */ + case 775: /* Store Vector by External Process ID Indexed LRU */ + case 95: /* Load Byte by External Process ID Indexed */ + case 287: /* Load Halfword by External Process ID Indexed */ + case 31: /* Load Word by External Process ID Indexed */ + case 29: /* Load Doubleword by External Process ID Indexed */ + case 295: /* Load Vector by External Process ID Indexed */ + case 263: /* Load Vector by External Process ID Indexed LRU */ + case 259: /* Move From Device Control Register Indexed */ + case 323: /* Move From Device Control Register */ + case 146: /* Move To Machine State Register */ + case 178: /* Move To Machine State Register Doubleword */ + case 387: /* Move To Device Control Register Indexed */ + case 419: /* Move To Device Control Register User-mode Indexed */ + case 291: /* Move From Device Control Register User-mode Indexed */ + case 451: /* Move To Device Control Register */ + /* Privileged instructions. */ + fprintf_unfiltered (gdb_stdlog, "Cannot record privileged instructions. " + "%08x at %08lx, 31-%d.\n", insn, addr, ext); + return -1; + + 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 */ + case 942: /* Transaction Reclaim */ + case 1006: /* Transaction Recheckpoint */ + 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 (¤t_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 +ppc64_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 +ppc64_process_record_op60 (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR addr, uint32_t insn) +{ + int ext = PPC_EXTOP (insn); + + 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 +ppc64_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 */ + 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 Extended */ + case 290: /* DFP Convert To Fixed */ + case 514: /* DFP Subtract */ + case 546: /* DFP Divide */ + case 770: /* DFP Round To DFP Long */ + case 802: /* DFP Convert From Fixed */ + case 834: /* DFP Encode BCD To DPD */ + 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 */ + 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 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 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 0: /* Floating Compare Unordered */ + case 32: /* Floating Compare Ordered */ + case 38: /* Move To FPSCR Bit 1 */ + case 64: /* Move to Condition Register from FPSCR */ + case 70: /* Move To FPSCR Bit 0 */ + case 134: /* Move To FPSCR Field Immediate */ + case 711: /* Move To FPSCR Fields */ + record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum); + /* FALL-THROUGH */ + case 23: /* Floating Select */ + case 128: /* Floating Test for software Divide */ + case 160: /* Floating Test for software Square Root */ + case 583: /* Move From FPSCR */ + 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 +ppc64_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 (ppc64_process_record_op4 (gdbarch, regcache, addr, insn) != 0) + return -1; + break; + + case 17: /* System call */ + if (tdep->syscall_record != NULL) + { + if (tdep->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) & 0x2) + 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 (ppc64_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 */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum); + break; + + case 24: /* OR Immediate */ + case 25: /* OR Immediate Shifted */ + case 26: /* XOR Immediate */ + case 27: /* XOR Immediate Shifted */ + case 28: /* AND Immediate */ + case 29: /* AND Immediate Shifted */ + record_full_arch_list_add_reg (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn)); + break; + + case 31: + if (ppc64_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 + PPC_RT (insn)); + break; + + case 56: /* Load Quadword */ + 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; + int size; + + if (PPC_RA (insn) != 0) + regcache_raw_read_unsigned (regcache, + tdep->ppc_gp0_regnum + PPC_RA (insn), + &addr); + + addr += PPC_D (insn); + + for (i = PPC_RS (insn); i < 32; i++) + record_full_arch_list_add_mem (addr + i * 4, 4); + } + 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 */ + 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 Doubleword 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 (ppc64_process_record_op59 (gdbarch, regcache, addr, insn) != 0) + return -1; + break; + + case 60: + if (ppc64_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 (ppc64_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. @@ -4154,6 +5660,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) case GDB_OSABI_NETBSD_ELF: case GDB_OSABI_UNKNOWN: set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc); + frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind); frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind); set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id); frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer); @@ -4162,6 +5669,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_believe_pcc_promotion (gdbarch, 1); set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc); + frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind); frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind); set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id); frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer); diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 2c79bc1..77bd462 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 }