/* PPC GNU/Linux native support.
- Copyright (C) 1988-2020 Free Software Foundation, Inc.
+ Copyright (C) 1988-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "arch/ppc-linux-tdesc.h"
#include "nat/ppc-linux.h"
#include "linux-tdep.h"
+#include "expop.h"
/* Similarly for the hardware watchpoint support. These requests are used
when the PowerPC HWDEBUG ptrace interface is not available. */
#define PPC_DEBUG_FEATURE_DATA_BP_DAWR 0x10
#endif /* PPC_DEBUG_FEATURE_DATA_BP_DAWR */
+/* Feature defined on Linux kernel v5.1: Second watchpoint support. */
+#ifndef PPC_DEBUG_FEATURE_DATA_BP_ARCH_31
+#define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31 0x20
+#endif /* PPC_DEBUG_FEATURE_DATA_BP_ARCH_31 */
+
/* The version of the PowerPC HWDEBUG kernel interface that we will use, if
available. */
#define PPC_DEBUG_CURRENT_VERSION 1
ppc_register_u_addr (struct gdbarch *gdbarch, int regno)
{
int u_addr = -1;
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* NOTE: cagney/2003-11-25: This is the word size used by the ptrace
interface, and not the wordsize of the program's ABI. */
int wordsize = sizeof (long);
fetch_spe_register (struct regcache *regcache, int tid, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
struct gdb_evrregset_t evrregs;
gdb_assert (sizeof (evrregs.evr[0])
fetch_register (struct regcache *regcache, int tid, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* This isn't really an address. But ptrace thinks of it as one. */
CORE_ADDR regaddr = ppc_register_u_addr (gdbarch, regno);
int bytes_transferred;
fetch_gp_regs (struct regcache *regcache, int tid)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int i;
if (have_ptrace_getsetregs)
fetch_fp_regs (struct regcache *regcache, int tid)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int i;
if (have_ptrace_getsetfpregs)
fetch_ppc_registers (struct regcache *regcache, int tid)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
fetch_gp_regs (regcache, tid);
if (tdep->ppc_fp0_regnum >= 0)
store_spe_register (const struct regcache *regcache, int tid, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
struct gdb_evrregset_t evrregs;
gdb_assert (sizeof (evrregs.evr[0])
store_register (const struct regcache *regcache, int tid, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* This isn't really an address. But ptrace thinks of it as one. */
CORE_ADDR regaddr = ppc_register_u_addr (gdbarch, regno);
int i;
store_gp_regs (const struct regcache *regcache, int tid, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int i;
if (have_ptrace_getsetregs)
store_fp_regs (const struct regcache *regcache, int tid, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int i;
if (have_ptrace_getsetfpregs)
store_ppc_registers (const struct regcache *regcache, int tid)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
store_gp_regs (regcache, tid, -1);
if (tdep->ppc_fp0_regnum >= 0)
const struct target_desc *
ppc_linux_nat_target::read_description ()
{
- int tid = inferior_ptid.lwp ();
- if (tid == 0)
- tid = inferior_ptid.pid ();
+ int tid = inferior_ptid.pid ();
if (have_ptrace_getsetevrregs)
{
features.wordsize = ppc_linux_target_wordsize (tid);
- CORE_ADDR hwcap = linux_get_hwcap (current_top_target ());
- CORE_ADDR hwcap2 = linux_get_hwcap2 (current_top_target ());
+ CORE_ADDR hwcap = linux_get_hwcap (current_inferior ()->top_target ());
+ CORE_ADDR hwcap2 = linux_get_hwcap2 (current_inferior ()->top_target ());
if (have_ptrace_getsetvsxregs
&& (hwcap & PPC_FEATURE_HAS_VSX))
watchpoints. */
if (m_dreg_interface.hwdebug_p ())
{
- int region_size;
const struct ppc_debug_info &hwdebug_info = (m_dreg_interface
.hwdebug_info ());
+ int region_size = hwdebug_info.data_bp_alignment;
+ int region_align = region_size;
/* Embedded DAC-based processors, like the PowerPC 440 have ranged
watchpoints and can watch any access within an arbitrary memory
takes two hardware watchpoints though. */
if (len > 1
&& hwdebug_info.features & PPC_DEBUG_FEATURE_DATA_BP_RANGE
- && linux_get_hwcap (current_top_target ()) & PPC_FEATURE_BOOKE)
+ && (linux_get_hwcap (current_inferior ()->top_target ())
+ & PPC_FEATURE_BOOKE))
return 2;
/* Check if the processor provides DAWR interface. */
if (hwdebug_info.features & PPC_DEBUG_FEATURE_DATA_BP_DAWR)
- /* DAWR interface allows to watch up to 512 byte wide ranges which
- can't cross a 512 byte boundary. */
- region_size = 512;
- else
- region_size = hwdebug_info.data_bp_alignment;
+ {
+ /* DAWR interface allows to watch up to 512 byte wide ranges. */
+ region_size = 512;
+ /* DAWR interface allows to watch up to 512 byte wide ranges which
+ can't cross a 512 byte bondary on machines that doesn't have a
+ second DAWR (P9 or less). */
+ if (!(hwdebug_info.features & PPC_DEBUG_FEATURE_DATA_BP_ARCH_31))
+ region_align = 512;
+ }
/* Server processors provide one hardware watchpoint and addr+len should
fall in the watchable region provided by the ptrace interface. */
- if (region_size
- && (addr + len > (addr & ~(region_size - 1)) + region_size))
+ if (region_align
+ && (addr + len > (addr & ~(region_align - 1)) + region_size))
return 0;
}
/* addr+len must fall in the 8 byte watchable region for DABR-based
{
gdb_assert (m_dreg_interface.debugreg_p ());
- if (((linux_get_hwcap (current_top_target ()) & PPC_FEATURE_BOOKE)
+ if (((linux_get_hwcap (current_inferior ()->top_target ())
+ & PPC_FEATURE_BOOKE)
&& (addr + len) > (addr & ~3) + 4)
|| (addr + len) > (addr & ~7) + 8)
return 0;
struct expression *cond,
CORE_ADDR *data_value, int *len)
{
- int pc = 1, num_accesses_left, num_accesses_right;
+ int num_accesses_left, num_accesses_right;
struct value *left_val, *right_val;
std::vector<value_ref_ptr> left_chain, right_chain;
- if (cond->elts[0].opcode != BINOP_EQUAL)
+ expr::equal_operation *eqop
+ = dynamic_cast<expr::equal_operation *> (cond->op.get ());
+ if (eqop == nullptr)
return 0;
+ expr::operation *lhs = eqop->get_lhs ();
+ expr::operation *rhs = eqop->get_rhs ();
- fetch_subexp_value (cond, &pc, &left_val, NULL, &left_chain, 0);
+ fetch_subexp_value (cond, lhs, &left_val, NULL, &left_chain, false);
num_accesses_left = num_memory_accesses (left_chain);
if (left_val == NULL || num_accesses_left < 0)
return 0;
- fetch_subexp_value (cond, &pc, &right_val, NULL, &right_chain, 0);
+ fetch_subexp_value (cond, rhs, &right_val, NULL, &right_chain, false);
num_accesses_right = num_memory_accesses (right_chain);
if (right_val == NULL || num_accesses_right < 0)
long wp_value;
long read_mode, write_mode;
- if (linux_get_hwcap (current_top_target ()) & PPC_FEATURE_BOOKE)
+ if (linux_get_hwcap (current_inferior ()->top_target ())
+ & PPC_FEATURE_BOOKE)
{
/* PowerPC 440 requires only the read/write flags to be passed
to the kernel. */
int mask;
if (m_dreg_interface.hwdebug_p ()
- && linux_get_hwcap (current_top_target ()) & PPC_FEATURE_BOOKE)
+ && (linux_get_hwcap (current_inferior ()->top_target ())
+ & PPC_FEATURE_BOOKE))
return start <= addr && start + length >= addr;
- else if (linux_get_hwcap (current_top_target ()) & PPC_FEATURE_BOOKE)
+ else if (linux_get_hwcap (current_inferior ()->top_target ())
+ & PPC_FEATURE_BOOKE)
mask = 3;
else
mask = 7;