gdbserver: Add powerpc fast tracepoint support.
gdb/gdbserver/ChangeLog: 2016-03-31 Wei-cheng Wang <cole945@gmail.com> Marcin Kościelnicki <koriakin@0x04.net> PR/17221 * Makefile.in: Add powerpc-*-ipa.o * configure.srv: Add ipa_obj for powerpc*-linux. * linux-ppc-ipa.c: New file. * linux-ppc-low.c: Added linux-ppc-tdesc.h, ax.h, tracepoint.h includes. (PPC_FIELD): New macro. (PPC_SEXT): New macro. (PPC_OP6): New macro. (PPC_BO): New macro. (PPC_LI): New macro. (PPC_BD): New macro. (init_registers_*): Move prototype to linux-ppc-tdesc.h. (tdesc_*): Move declaration to linux-ppc-tdesc.h. (ppc_get_hwcap): Rename to ppc_get_auxv and add type parameter. (ppc_get_thread_area): New function. (is_elfv2_inferior): New function. (gen_ds_form): New function. (GEN_STD): New macro. (GEN_STDU): New macro. (GEN_LD): New macro. (GEN_LDU): New macro. (gen_d_form): New function. (GEN_ADDI): New macro. (GEN_ADDIS): New macro. (GEN_LI): New macro. (GEN_LIS): New macro. (GEN_ORI): New macro. (GEN_ORIS): New macro. (GEN_LWZ): New macro. (GEN_STW): New macro. (GEN_STWU): New macro. (gen_xfx_form): New function. (GEN_MFSPR): New macro. (GEN_MTSPR): New macro. (GEN_MFCR): New macro. (GEN_MTCR): New macro. (GEN_SYNC): New macro. (GEN_LWSYNC): New macro. (gen_x_form): New function. (GEN_OR): New macro. (GEN_MR): New macro. (GEN_LWARX): New macro. (GEN_STWCX): New macro. (GEN_CMPW): New macro. (gen_md_form): New function. (GEN_RLDICL): New macro. (GEN_RLDICR): New macro. (gen_i_form): New function. (GEN_B): New macro. (GEN_BL): New macro. (gen_b_form): New function. (GEN_BNE): New macro. (GEN_LOAD): New macro. (GEN_STORE): New macro. (gen_limm): New function. (gen_atomic_xchg): New function. (gen_call): New function. (ppc_relocate_instruction): New function. (ppc_install_fast_tracepoint_jump_pad): New function. (ppc_get_min_fast_tracepoint_insn_len): New function. (ppc_get_ipa_tdesc_idx): New function. (the_low_target): Wire in the new functions. (initialize_low_arch) [!__powerpc64__]: Don'it initialize 64-bit tdescs. * linux-ppc-tdesc.h: New file.
This commit is contained in:
parent
a13c46966d
commit
a2174ba452
6 changed files with 1284 additions and 68 deletions
|
@ -1,3 +1,73 @@
|
|||
2016-03-31 Wei-cheng Wang <cole945@gmail.com>
|
||||
Marcin Kościelnicki <koriakin@0x04.net>
|
||||
|
||||
PR/17221
|
||||
* Makefile.in: Add powerpc-*-ipa.o
|
||||
* configure.srv: Add ipa_obj for powerpc*-linux.
|
||||
* linux-ppc-ipa.c: New file.
|
||||
* linux-ppc-low.c: Added linux-ppc-tdesc.h, ax.h, tracepoint.h
|
||||
includes.
|
||||
(PPC_FIELD): New macro.
|
||||
(PPC_SEXT): New macro.
|
||||
(PPC_OP6): New macro.
|
||||
(PPC_BO): New macro.
|
||||
(PPC_LI): New macro.
|
||||
(PPC_BD): New macro.
|
||||
(init_registers_*): Move prototype to linux-ppc-tdesc.h.
|
||||
(tdesc_*): Move declaration to linux-ppc-tdesc.h.
|
||||
(ppc_get_hwcap): Rename to ppc_get_auxv and add type parameter.
|
||||
(ppc_get_thread_area): New function.
|
||||
(is_elfv2_inferior): New function.
|
||||
(gen_ds_form): New function.
|
||||
(GEN_STD): New macro.
|
||||
(GEN_STDU): New macro.
|
||||
(GEN_LD): New macro.
|
||||
(GEN_LDU): New macro.
|
||||
(gen_d_form): New function.
|
||||
(GEN_ADDI): New macro.
|
||||
(GEN_ADDIS): New macro.
|
||||
(GEN_LI): New macro.
|
||||
(GEN_LIS): New macro.
|
||||
(GEN_ORI): New macro.
|
||||
(GEN_ORIS): New macro.
|
||||
(GEN_LWZ): New macro.
|
||||
(GEN_STW): New macro.
|
||||
(GEN_STWU): New macro.
|
||||
(gen_xfx_form): New function.
|
||||
(GEN_MFSPR): New macro.
|
||||
(GEN_MTSPR): New macro.
|
||||
(GEN_MFCR): New macro.
|
||||
(GEN_MTCR): New macro.
|
||||
(GEN_SYNC): New macro.
|
||||
(GEN_LWSYNC): New macro.
|
||||
(gen_x_form): New function.
|
||||
(GEN_OR): New macro.
|
||||
(GEN_MR): New macro.
|
||||
(GEN_LWARX): New macro.
|
||||
(GEN_STWCX): New macro.
|
||||
(GEN_CMPW): New macro.
|
||||
(gen_md_form): New function.
|
||||
(GEN_RLDICL): New macro.
|
||||
(GEN_RLDICR): New macro.
|
||||
(gen_i_form): New function.
|
||||
(GEN_B): New macro.
|
||||
(GEN_BL): New macro.
|
||||
(gen_b_form): New function.
|
||||
(GEN_BNE): New macro.
|
||||
(GEN_LOAD): New macro.
|
||||
(GEN_STORE): New macro.
|
||||
(gen_limm): New function.
|
||||
(gen_atomic_xchg): New function.
|
||||
(gen_call): New function.
|
||||
(ppc_relocate_instruction): New function.
|
||||
(ppc_install_fast_tracepoint_jump_pad): New function.
|
||||
(ppc_get_min_fast_tracepoint_insn_len): New function.
|
||||
(ppc_get_ipa_tdesc_idx): New function.
|
||||
(the_low_target): Wire in the new functions.
|
||||
(initialize_low_arch) [!__powerpc64__]: Don'it initialize 64-bit
|
||||
tdescs.
|
||||
* linux-ppc-tdesc.h: New file.
|
||||
|
||||
2016-03-31 Marcin Kościelnicki <koriakin@0x04.net>
|
||||
|
||||
* linux-aarch64-ipa.c: Add <sys/mman.h> and <sys/auxv.h> includes.
|
||||
|
|
|
@ -579,6 +579,54 @@ s390x-vx-linux64-ipa.o: s390x-vx-linux64.c
|
|||
s390x-tevx-linux64-ipa.o: s390x-tevx-linux64.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
linux-ppc-ipa.o: linux-ppc-ipa.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-32l-ipa.o: powerpc-32l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-altivec32l-ipa.o: powerpc-altivec32l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-cell32l-ipa.o: powerpc-cell32l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-vsx32l-ipa.o: powerpc-vsx32l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-isa205-32l-ipa.o: powerpc-isa205-32l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-isa205-altivec32l-ipa.o: powerpc-isa205-altivec32l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-isa205-vsx32l-ipa.o: powerpc-isa205-vsx32l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-e500l-ipa.o: powerpc-e500l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-64l-ipa.o: powerpc-64l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-altivec64l-ipa.o: powerpc-altivec64l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-cell64l-ipa.o: powerpc-cell64l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-vsx64l-ipa.o: powerpc-vsx64l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-isa205-64l-ipa.o: powerpc-isa205-64l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-isa205-altivec64l-ipa.o: powerpc-isa205-altivec64l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
powerpc-isa205-vsx64l-ipa.o: powerpc-isa205-vsx64l.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
tdesc-ipa.o: tdesc.c
|
||||
$(IPAGENT_COMPILE) $<
|
||||
$(POSTCOMPILE)
|
||||
|
|
|
@ -31,6 +31,7 @@ srv_amd64_linux_regobj="amd64-linux.o amd64-avx-linux.o amd64-avx512-linux.o amd
|
|||
|
||||
ipa_i386_linux_regobj="i386-linux-ipa.o i386-avx-linux-ipa.o i386-avx512-linux-ipa.o i386-mpx-linux-ipa.o i386-mmx-linux-ipa.o"
|
||||
ipa_amd64_linux_regobj="amd64-linux-ipa.o amd64-avx-linux-ipa.o amd64-avx512-linux-ipa.o amd64-mpx-linux-ipa.o"
|
||||
ipa_ppc_linux_regobj="powerpc-32l-ipa.o powerpc-altivec32l-ipa.o powerpc-cell32l-ipa.o powerpc-vsx32l-ipa.o powerpc-isa205-32l-ipa.o powerpc-isa205-altivec32l-ipa.o powerpc-isa205-vsx32l-ipa.o powerpc-e500l-ipa.o powerpc-64l-ipa.o powerpc-altivec64l-ipa.o powerpc-cell64l-ipa.o powerpc-vsx64l-ipa.o powerpc-isa205-64l-ipa.o powerpc-isa205-altivec64l-ipa.o powerpc-isa205-vsx64l-ipa.o"
|
||||
|
||||
srv_i386_32bit_xmlfiles="i386/32bit-core.xml i386/32bit-sse.xml i386/32bit-avx.xml i386/32bit-avx512.xml i386/32bit-mpx.xml"
|
||||
srv_i386_64bit_xmlfiles="i386/64bit-core.xml i386/64bit-sse.xml i386/64bit-avx.xml i386/64bit-avx512.xml i386/x32-core.xml i386/64bit-mpx.xml"
|
||||
|
@ -258,6 +259,7 @@ case "${target}" in
|
|||
srv_linux_usrregs=yes
|
||||
srv_linux_regsets=yes
|
||||
srv_linux_thread_db=yes
|
||||
ipa_obj="${ipa_ppc_linux_regobj} linux-ppc-ipa.o"
|
||||
;;
|
||||
powerpc-*-lynxos*) srv_regobj="powerpc-32.o"
|
||||
srv_tgtobj="lynx-low.o lynx-ppc-low.o"
|
||||
|
|
245
gdb/gdbserver/linux-ppc-ipa.c
Normal file
245
gdb/gdbserver/linux-ppc-ipa.c
Normal file
|
@ -0,0 +1,245 @@
|
|||
/* GNU/Linux/PowerPC specific low level interface, for the in-process
|
||||
agent library for GDB.
|
||||
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "server.h"
|
||||
#include <sys/mman.h>
|
||||
#include "tracepoint.h"
|
||||
#include "linux-ppc-tdesc.h"
|
||||
#ifdef HAVE_GETAUXVAL
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
|
||||
/* These macros define the position of registers in the buffer collected
|
||||
by the fast tracepoint jump pad. */
|
||||
#define FT_CR_R0 0
|
||||
#define FT_CR_CR 32
|
||||
#define FT_CR_XER 33
|
||||
#define FT_CR_LR 34
|
||||
#define FT_CR_CTR 35
|
||||
#define FT_CR_PC 36
|
||||
#define FT_CR_GPR(n) (FT_CR_R0 + (n))
|
||||
|
||||
static const int ppc_ft_collect_regmap[] = {
|
||||
/* GPRs */
|
||||
FT_CR_GPR (0), FT_CR_GPR (1), FT_CR_GPR (2),
|
||||
FT_CR_GPR (3), FT_CR_GPR (4), FT_CR_GPR (5),
|
||||
FT_CR_GPR (6), FT_CR_GPR (7), FT_CR_GPR (8),
|
||||
FT_CR_GPR (9), FT_CR_GPR (10), FT_CR_GPR (11),
|
||||
FT_CR_GPR (12), FT_CR_GPR (13), FT_CR_GPR (14),
|
||||
FT_CR_GPR (15), FT_CR_GPR (16), FT_CR_GPR (17),
|
||||
FT_CR_GPR (18), FT_CR_GPR (19), FT_CR_GPR (20),
|
||||
FT_CR_GPR (21), FT_CR_GPR (22), FT_CR_GPR (23),
|
||||
FT_CR_GPR (24), FT_CR_GPR (25), FT_CR_GPR (26),
|
||||
FT_CR_GPR (27), FT_CR_GPR (28), FT_CR_GPR (29),
|
||||
FT_CR_GPR (30), FT_CR_GPR (31),
|
||||
/* FPRs - not collected. */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
FT_CR_PC, /* PC */
|
||||
-1, /* MSR */
|
||||
FT_CR_CR, /* CR */
|
||||
FT_CR_LR, /* LR */
|
||||
FT_CR_CTR, /* CTR */
|
||||
FT_CR_XER, /* XER */
|
||||
-1, /* FPSCR */
|
||||
};
|
||||
|
||||
#define PPC_NUM_FT_COLLECT_GREGS \
|
||||
(sizeof (ppc_ft_collect_regmap) / sizeof(ppc_ft_collect_regmap[0]))
|
||||
|
||||
/* Supply registers collected by the fast tracepoint jump pad.
|
||||
BUF is the second argument we pass to gdb_collect in jump pad. */
|
||||
|
||||
void
|
||||
supply_fast_tracepoint_registers (struct regcache *regcache,
|
||||
const unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PPC_NUM_FT_COLLECT_GREGS; i++)
|
||||
{
|
||||
if (ppc_ft_collect_regmap[i] == -1)
|
||||
continue;
|
||||
supply_register (regcache, i,
|
||||
((char *) buf)
|
||||
+ ppc_ft_collect_regmap[i] * sizeof (long));
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the value of register REGNUM. RAW_REGS is collected buffer
|
||||
by jump pad. This function is called by emit_reg. */
|
||||
|
||||
ULONGEST
|
||||
get_raw_reg (const unsigned char *raw_regs, int regnum)
|
||||
{
|
||||
if (regnum >= PPC_NUM_FT_COLLECT_GREGS)
|
||||
return 0;
|
||||
if (ppc_ft_collect_regmap[regnum] == -1)
|
||||
return 0;
|
||||
|
||||
return *(unsigned long *) (raw_regs
|
||||
+ ppc_ft_collect_regmap[regnum] * sizeof (long));
|
||||
}
|
||||
|
||||
/* Allocate buffer for the jump pads. The branch instruction has a reach
|
||||
of +/- 32MiB, and the executable is loaded at 0x10000000 (256MiB).
|
||||
|
||||
64-bit: To maximize the area of executable that can use tracepoints,
|
||||
try allocating at 0x10000000 - size initially, decreasing until we hit
|
||||
a free area.
|
||||
|
||||
32-bit: ld.so loads dynamic libraries right below the executable, so
|
||||
we cannot depend on that area (dynamic libraries can be quite large).
|
||||
Instead, aim right after the executable - at sbrk(0). This will
|
||||
cause future brk to fail, and malloc will fallback to mmap. */
|
||||
|
||||
void *
|
||||
alloc_jump_pad_buffer (size_t size)
|
||||
{
|
||||
#ifdef __powerpc64__
|
||||
uintptr_t addr;
|
||||
uintptr_t exec_base = getauxval (AT_PHDR);
|
||||
int pagesize;
|
||||
void *res;
|
||||
|
||||
if (exec_base == 0)
|
||||
exec_base = 0x10000000;
|
||||
|
||||
pagesize = sysconf (_SC_PAGE_SIZE);
|
||||
if (pagesize == -1)
|
||||
perror_with_name ("sysconf");
|
||||
|
||||
addr = exec_base - size;
|
||||
|
||||
/* size should already be page-aligned, but this can't hurt. */
|
||||
addr &= ~(pagesize - 1);
|
||||
|
||||
/* Search for a free area. If we hit 0, we're out of luck. */
|
||||
for (; addr; addr -= pagesize)
|
||||
{
|
||||
/* No MAP_FIXED - we don't want to zap someone's mapping. */
|
||||
res = mmap ((void *) addr, size,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
/* If we got what we wanted, return. */
|
||||
if ((uintptr_t) res == addr)
|
||||
return res;
|
||||
|
||||
/* If we got a mapping, but at a wrong address, undo it. */
|
||||
if (res != MAP_FAILED)
|
||||
munmap (res, size);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
void *target = sbrk (0);
|
||||
void *res = mmap (target, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
if (res == target)
|
||||
return res;
|
||||
|
||||
if (res != MAP_FAILED)
|
||||
munmap (res, size);
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return target_desc to use for IPA, given the tdesc index passed by
|
||||
gdbserver. */
|
||||
|
||||
const struct target_desc *
|
||||
get_ipa_tdesc (int idx)
|
||||
{
|
||||
switch (idx)
|
||||
{
|
||||
#ifdef __powerpc64__
|
||||
case PPC_TDESC_BASE:
|
||||
return tdesc_powerpc_64l;
|
||||
case PPC_TDESC_ALTIVEC:
|
||||
return tdesc_powerpc_altivec64l;
|
||||
case PPC_TDESC_CELL:
|
||||
return tdesc_powerpc_cell64l;
|
||||
case PPC_TDESC_VSX:
|
||||
return tdesc_powerpc_vsx64l;
|
||||
case PPC_TDESC_ISA205:
|
||||
return tdesc_powerpc_isa205_64l;
|
||||
case PPC_TDESC_ISA205_ALTIVEC:
|
||||
return tdesc_powerpc_isa205_altivec64l;
|
||||
case PPC_TDESC_ISA205_VSX:
|
||||
return tdesc_powerpc_isa205_vsx64l;
|
||||
#else
|
||||
case PPC_TDESC_BASE:
|
||||
return tdesc_powerpc_32l;
|
||||
case PPC_TDESC_ALTIVEC:
|
||||
return tdesc_powerpc_altivec32l;
|
||||
case PPC_TDESC_CELL:
|
||||
return tdesc_powerpc_cell32l;
|
||||
case PPC_TDESC_VSX:
|
||||
return tdesc_powerpc_vsx32l;
|
||||
case PPC_TDESC_ISA205:
|
||||
return tdesc_powerpc_isa205_32l;
|
||||
case PPC_TDESC_ISA205_ALTIVEC:
|
||||
return tdesc_powerpc_isa205_altivec32l;
|
||||
case PPC_TDESC_ISA205_VSX:
|
||||
return tdesc_powerpc_isa205_vsx32l;
|
||||
case PPC_TDESC_E500:
|
||||
return tdesc_powerpc_e500l;
|
||||
#endif
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"unknown ipa tdesc index: %d", idx);
|
||||
#ifdef __powerpc64__
|
||||
return tdesc_powerpc_64l;
|
||||
#else
|
||||
return tdesc_powerpc_32l;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Initialize ipa_tdesc and others. */
|
||||
|
||||
void
|
||||
initialize_low_tracepoint (void)
|
||||
{
|
||||
#ifdef __powerpc64__
|
||||
init_registers_powerpc_64l ();
|
||||
init_registers_powerpc_altivec64l ();
|
||||
init_registers_powerpc_cell64l ();
|
||||
init_registers_powerpc_vsx64l ();
|
||||
init_registers_powerpc_isa205_64l ();
|
||||
init_registers_powerpc_isa205_altivec64l ();
|
||||
init_registers_powerpc_isa205_vsx64l ();
|
||||
#else
|
||||
init_registers_powerpc_32l ();
|
||||
init_registers_powerpc_altivec32l ();
|
||||
init_registers_powerpc_cell32l ();
|
||||
init_registers_powerpc_vsx32l ();
|
||||
init_registers_powerpc_isa205_32l ();
|
||||
init_registers_powerpc_isa205_altivec32l ();
|
||||
init_registers_powerpc_isa205_vsx32l ();
|
||||
init_registers_powerpc_e500l ();
|
||||
#endif
|
||||
}
|
|
@ -24,70 +24,24 @@
|
|||
#include <asm/ptrace.h>
|
||||
|
||||
#include "nat/ppc-linux.h"
|
||||
#include "linux-ppc-tdesc.h"
|
||||
#include "ax.h"
|
||||
#include "tracepoint.h"
|
||||
|
||||
#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_BO(insn) PPC_FIELD (insn, 6, 5)
|
||||
#define PPC_LI(insn) (PPC_SEXT (PPC_FIELD (insn, 6, 24), 24) << 2)
|
||||
#define PPC_BD(insn) (PPC_SEXT (PPC_FIELD (insn, 16, 14), 14) << 2)
|
||||
|
||||
static unsigned long ppc_hwcap;
|
||||
|
||||
|
||||
/* Defined in auto-generated file powerpc-32l.c. */
|
||||
void init_registers_powerpc_32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-altivec32l.c. */
|
||||
void init_registers_powerpc_altivec32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_altivec32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-cell32l.c. */
|
||||
void init_registers_powerpc_cell32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_cell32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-vsx32l.c. */
|
||||
void init_registers_powerpc_vsx32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_vsx32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-32l.c. */
|
||||
void init_registers_powerpc_isa205_32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-altivec32l.c. */
|
||||
void init_registers_powerpc_isa205_altivec32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_altivec32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-vsx32l.c. */
|
||||
void init_registers_powerpc_isa205_vsx32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_vsx32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-e500l.c. */
|
||||
void init_registers_powerpc_e500l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_e500l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-64l.c. */
|
||||
void init_registers_powerpc_64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-altivec64l.c. */
|
||||
void init_registers_powerpc_altivec64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_altivec64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-cell64l.c. */
|
||||
void init_registers_powerpc_cell64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_cell64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-vsx64l.c. */
|
||||
void init_registers_powerpc_vsx64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_vsx64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-64l.c. */
|
||||
void init_registers_powerpc_isa205_64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-altivec64l.c. */
|
||||
void init_registers_powerpc_isa205_altivec64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_altivec64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-vsx64l.c. */
|
||||
void init_registers_powerpc_isa205_vsx64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_vsx64l;
|
||||
|
||||
#define ppc_num_regs 73
|
||||
|
||||
#ifdef __powerpc64__
|
||||
|
@ -342,7 +296,7 @@ ppc_set_pc (struct regcache *regcache, CORE_ADDR pc)
|
|||
|
||||
|
||||
static int
|
||||
ppc_get_hwcap (unsigned long *valp)
|
||||
ppc_get_auxv (unsigned long type, unsigned long *valp)
|
||||
{
|
||||
const struct target_desc *tdesc = current_process ()->tdesc;
|
||||
int wordsize = register_size (tdesc, 0);
|
||||
|
@ -354,7 +308,7 @@ ppc_get_hwcap (unsigned long *valp)
|
|||
if (wordsize == 4)
|
||||
{
|
||||
unsigned int *data_p = (unsigned int *)data;
|
||||
if (data_p[0] == AT_HWCAP)
|
||||
if (data_p[0] == type)
|
||||
{
|
||||
*valp = data_p[1];
|
||||
return 1;
|
||||
|
@ -363,7 +317,7 @@ ppc_get_hwcap (unsigned long *valp)
|
|||
else
|
||||
{
|
||||
unsigned long *data_p = (unsigned long *)data;
|
||||
if (data_p[0] == AT_HWCAP)
|
||||
if (data_p[0] == type)
|
||||
{
|
||||
*valp = data_p[1];
|
||||
return 1;
|
||||
|
@ -680,7 +634,7 @@ ppc_arch_setup (void)
|
|||
free_register_cache (regcache);
|
||||
if (ppc64_64bit_inferior_p (msr))
|
||||
{
|
||||
ppc_get_hwcap (&ppc_hwcap);
|
||||
ppc_get_auxv (AT_HWCAP, &ppc_hwcap);
|
||||
if (ppc_hwcap & PPC_FEATURE_CELL)
|
||||
tdesc = tdesc_powerpc_cell64l;
|
||||
else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
|
||||
|
@ -714,7 +668,7 @@ ppc_arch_setup (void)
|
|||
tdesc = tdesc_powerpc_32l;
|
||||
current_process ()->tdesc = tdesc;
|
||||
|
||||
ppc_get_hwcap (&ppc_hwcap);
|
||||
ppc_get_auxv (AT_HWCAP, &ppc_hwcap);
|
||||
if (ppc_hwcap & PPC_FEATURE_CELL)
|
||||
tdesc = tdesc_powerpc_cell32l;
|
||||
else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
|
||||
|
@ -756,12 +710,804 @@ ppc_arch_setup (void)
|
|||
current_process ()->tdesc = tdesc;
|
||||
}
|
||||
|
||||
/* Implementation of linux_target_ops method "supports_tracepoints". */
|
||||
|
||||
static int
|
||||
ppc_supports_tracepoints (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the thread area address. This is used to recognize which
|
||||
thread is which when tracing with the in-process agent library. We
|
||||
don't read anything from the address, and treat it as opaque; it's
|
||||
the address itself that we assume is unique per-thread. */
|
||||
|
||||
static int
|
||||
ppc_get_thread_area (int lwpid, CORE_ADDR *addr)
|
||||
{
|
||||
struct lwp_info *lwp = find_lwp_pid (pid_to_ptid (lwpid));
|
||||
struct thread_info *thr = get_lwp_thread (lwp);
|
||||
struct regcache *regcache = get_thread_regcache (thr, 1);
|
||||
ULONGEST tp = 0;
|
||||
|
||||
#ifdef __powerpc64__
|
||||
if (register_size (regcache->tdesc, 0) == 8)
|
||||
collect_register_by_name (regcache, "r13", &tp);
|
||||
else
|
||||
#endif
|
||||
collect_register_by_name (regcache, "r2", &tp);
|
||||
|
||||
*addr = tp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __powerpc64__
|
||||
|
||||
/* Older glibc doesn't provide this. */
|
||||
|
||||
#ifndef EF_PPC64_ABI
|
||||
#define EF_PPC64_ABI 3
|
||||
#endif
|
||||
|
||||
/* Returns 1 if inferior is using ELFv2 ABI. Undefined for 32-bit
|
||||
inferiors. */
|
||||
|
||||
static int
|
||||
is_elfv2_inferior (void)
|
||||
{
|
||||
/* To be used as fallback if we're unable to determine the right result -
|
||||
assume inferior uses the same ABI as gdbserver. */
|
||||
#if _CALL_ELF == 2
|
||||
const int def_res = 1;
|
||||
#else
|
||||
const int def_res = 0;
|
||||
#endif
|
||||
unsigned long phdr;
|
||||
Elf64_Ehdr ehdr;
|
||||
|
||||
if (!ppc_get_auxv (AT_PHDR, &phdr))
|
||||
return def_res;
|
||||
|
||||
/* Assume ELF header is at the beginning of the page where program headers
|
||||
are located. If it doesn't look like one, bail. */
|
||||
|
||||
read_inferior_memory (phdr & ~0xfff, (unsigned char *) &ehdr, sizeof ehdr);
|
||||
if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG))
|
||||
return def_res;
|
||||
|
||||
return (ehdr.e_flags & EF_PPC64_ABI) == 2;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Generate a ds-form instruction in BUF and return the number of bytes written
|
||||
|
||||
0 6 11 16 30 32
|
||||
| OPCD | RST | RA | DS |XO| */
|
||||
|
||||
__attribute__((unused)) /* Maybe unused due to conditional compilation. */
|
||||
static int
|
||||
gen_ds_form (uint32_t *buf, int opcd, int rst, int ra, int ds, int xo)
|
||||
{
|
||||
uint32_t insn;
|
||||
|
||||
gdb_assert ((opcd & ~0x3f) == 0);
|
||||
gdb_assert ((rst & ~0x1f) == 0);
|
||||
gdb_assert ((ra & ~0x1f) == 0);
|
||||
gdb_assert ((xo & ~0x3) == 0);
|
||||
|
||||
insn = (rst << 21) | (ra << 16) | (ds & 0xfffc) | (xo & 0x3);
|
||||
*buf = (opcd << 26) | insn;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Followings are frequently used ds-form instructions. */
|
||||
|
||||
#define GEN_STD(buf, rs, ra, offset) gen_ds_form (buf, 62, rs, ra, offset, 0)
|
||||
#define GEN_STDU(buf, rs, ra, offset) gen_ds_form (buf, 62, rs, ra, offset, 1)
|
||||
#define GEN_LD(buf, rt, ra, offset) gen_ds_form (buf, 58, rt, ra, offset, 0)
|
||||
#define GEN_LDU(buf, rt, ra, offset) gen_ds_form (buf, 58, rt, ra, offset, 1)
|
||||
|
||||
/* Generate a d-form instruction in BUF.
|
||||
|
||||
0 6 11 16 32
|
||||
| OPCD | RST | RA | D | */
|
||||
|
||||
static int
|
||||
gen_d_form (uint32_t *buf, int opcd, int rst, int ra, int si)
|
||||
{
|
||||
uint32_t insn;
|
||||
|
||||
gdb_assert ((opcd & ~0x3f) == 0);
|
||||
gdb_assert ((rst & ~0x1f) == 0);
|
||||
gdb_assert ((ra & ~0x1f) == 0);
|
||||
|
||||
insn = (rst << 21) | (ra << 16) | (si & 0xffff);
|
||||
*buf = (opcd << 26) | insn;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Followings are frequently used d-form instructions. */
|
||||
|
||||
#define GEN_ADDI(buf, rt, ra, si) gen_d_form (buf, 14, rt, ra, si)
|
||||
#define GEN_ADDIS(buf, rt, ra, si) gen_d_form (buf, 15, rt, ra, si)
|
||||
#define GEN_LI(buf, rt, si) GEN_ADDI (buf, rt, 0, si)
|
||||
#define GEN_LIS(buf, rt, si) GEN_ADDIS (buf, rt, 0, si)
|
||||
#define GEN_ORI(buf, rt, ra, si) gen_d_form (buf, 24, rt, ra, si)
|
||||
#define GEN_ORIS(buf, rt, ra, si) gen_d_form (buf, 25, rt, ra, si)
|
||||
#define GEN_LWZ(buf, rt, ra, si) gen_d_form (buf, 32, rt, ra, si)
|
||||
#define GEN_STW(buf, rt, ra, si) gen_d_form (buf, 36, rt, ra, si)
|
||||
#define GEN_STWU(buf, rt, ra, si) gen_d_form (buf, 37, rt, ra, si)
|
||||
|
||||
/* Generate a xfx-form instruction in BUF and return the number of bytes
|
||||
written.
|
||||
|
||||
0 6 11 21 31 32
|
||||
| OPCD | RST | RI | XO |/| */
|
||||
|
||||
static int
|
||||
gen_xfx_form (uint32_t *buf, int opcd, int rst, int ri, int xo)
|
||||
{
|
||||
uint32_t insn;
|
||||
unsigned int n = ((ri & 0x1f) << 5) | ((ri >> 5) & 0x1f);
|
||||
|
||||
gdb_assert ((opcd & ~0x3f) == 0);
|
||||
gdb_assert ((rst & ~0x1f) == 0);
|
||||
gdb_assert ((xo & ~0x3ff) == 0);
|
||||
|
||||
insn = (rst << 21) | (n << 11) | (xo << 1);
|
||||
*buf = (opcd << 26) | insn;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Followings are frequently used xfx-form instructions. */
|
||||
|
||||
#define GEN_MFSPR(buf, rt, spr) gen_xfx_form (buf, 31, rt, spr, 339)
|
||||
#define GEN_MTSPR(buf, rt, spr) gen_xfx_form (buf, 31, rt, spr, 467)
|
||||
#define GEN_MFCR(buf, rt) gen_xfx_form (buf, 31, rt, 0, 19)
|
||||
#define GEN_MTCR(buf, rt) gen_xfx_form (buf, 31, rt, 0x3cf, 144)
|
||||
#define GEN_SYNC(buf, L, E) gen_xfx_form (buf, 31, L & 0x3, \
|
||||
E & 0xf, 598)
|
||||
#define GEN_LWSYNC(buf) GEN_SYNC (buf, 1, 0)
|
||||
|
||||
|
||||
/* Generate a x-form instruction in BUF and return the number of bytes written.
|
||||
|
||||
0 6 11 16 21 31 32
|
||||
| OPCD | RST | RA | RB | XO |RC| */
|
||||
|
||||
static int
|
||||
gen_x_form (uint32_t *buf, int opcd, int rst, int ra, int rb, int xo, int rc)
|
||||
{
|
||||
uint32_t insn;
|
||||
|
||||
gdb_assert ((opcd & ~0x3f) == 0);
|
||||
gdb_assert ((rst & ~0x1f) == 0);
|
||||
gdb_assert ((ra & ~0x1f) == 0);
|
||||
gdb_assert ((rb & ~0x1f) == 0);
|
||||
gdb_assert ((xo & ~0x3ff) == 0);
|
||||
gdb_assert ((rc & ~1) == 0);
|
||||
|
||||
insn = (rst << 21) | (ra << 16) | (rb << 11) | (xo << 1) | rc;
|
||||
*buf = (opcd << 26) | insn;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Followings are frequently used x-form instructions. */
|
||||
|
||||
#define GEN_OR(buf, ra, rs, rb) gen_x_form (buf, 31, rs, ra, rb, 444, 0)
|
||||
#define GEN_MR(buf, ra, rs) GEN_OR (buf, ra, rs, rs)
|
||||
#define GEN_LWARX(buf, rt, ra, rb) gen_x_form (buf, 31, rt, ra, rb, 20, 0)
|
||||
#define GEN_STWCX(buf, rs, ra, rb) gen_x_form (buf, 31, rs, ra, rb, 150, 1)
|
||||
/* Assume bf = cr7. */
|
||||
#define GEN_CMPW(buf, ra, rb) gen_x_form (buf, 31, 28, ra, rb, 0, 0)
|
||||
|
||||
|
||||
/* Generate a md-form instruction in BUF and return the number of bytes written.
|
||||
|
||||
0 6 11 16 21 27 30 31 32
|
||||
| OPCD | RS | RA | sh | mb | XO |sh|Rc| */
|
||||
|
||||
static int
|
||||
gen_md_form (uint32_t *buf, int opcd, int rs, int ra, int sh, int mb,
|
||||
int xo, int rc)
|
||||
{
|
||||
uint32_t insn;
|
||||
unsigned int n = ((mb & 0x1f) << 1) | ((mb >> 5) & 0x1);
|
||||
unsigned int sh0_4 = sh & 0x1f;
|
||||
unsigned int sh5 = (sh >> 5) & 1;
|
||||
|
||||
gdb_assert ((opcd & ~0x3f) == 0);
|
||||
gdb_assert ((rs & ~0x1f) == 0);
|
||||
gdb_assert ((ra & ~0x1f) == 0);
|
||||
gdb_assert ((sh & ~0x3f) == 0);
|
||||
gdb_assert ((mb & ~0x3f) == 0);
|
||||
gdb_assert ((xo & ~0x7) == 0);
|
||||
gdb_assert ((rc & ~0x1) == 0);
|
||||
|
||||
insn = (rs << 21) | (ra << 16) | (sh0_4 << 11) | (n << 5)
|
||||
| (sh5 << 1) | (xo << 2) | (rc & 1);
|
||||
*buf = (opcd << 26) | insn;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The following are frequently used md-form instructions. */
|
||||
|
||||
#define GEN_RLDICL(buf, ra, rs ,sh, mb) \
|
||||
gen_md_form (buf, 30, rs, ra, sh, mb, 0, 0)
|
||||
#define GEN_RLDICR(buf, ra, rs ,sh, mb) \
|
||||
gen_md_form (buf, 30, rs, ra, sh, mb, 1, 0)
|
||||
|
||||
/* Generate a i-form instruction in BUF and return the number of bytes written.
|
||||
|
||||
0 6 30 31 32
|
||||
| OPCD | LI |AA|LK| */
|
||||
|
||||
static int
|
||||
gen_i_form (uint32_t *buf, int opcd, int li, int aa, int lk)
|
||||
{
|
||||
uint32_t insn;
|
||||
|
||||
gdb_assert ((opcd & ~0x3f) == 0);
|
||||
|
||||
insn = (li & 0x3fffffc) | (aa & 1) | (lk & 1);
|
||||
*buf = (opcd << 26) | insn;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The following are frequently used i-form instructions. */
|
||||
|
||||
#define GEN_B(buf, li) gen_i_form (buf, 18, li, 0, 0)
|
||||
#define GEN_BL(buf, li) gen_i_form (buf, 18, li, 0, 1)
|
||||
|
||||
/* Generate a b-form instruction in BUF and return the number of bytes written.
|
||||
|
||||
0 6 11 16 30 31 32
|
||||
| OPCD | BO | BI | BD |AA|LK| */
|
||||
|
||||
static int
|
||||
gen_b_form (uint32_t *buf, int opcd, int bo, int bi, int bd,
|
||||
int aa, int lk)
|
||||
{
|
||||
uint32_t insn;
|
||||
|
||||
gdb_assert ((opcd & ~0x3f) == 0);
|
||||
gdb_assert ((bo & ~0x1f) == 0);
|
||||
gdb_assert ((bi & ~0x1f) == 0);
|
||||
|
||||
insn = (bo << 21) | (bi << 16) | (bd & 0xfffc) | (aa & 1) | (lk & 1);
|
||||
*buf = (opcd << 26) | insn;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The following are frequently used b-form instructions. */
|
||||
/* Assume bi = cr7. */
|
||||
#define GEN_BNE(buf, bd) gen_b_form (buf, 16, 0x4, (7 << 2) | 2, bd, 0 ,0)
|
||||
|
||||
/* GEN_LOAD and GEN_STORE generate 64- or 32-bit load/store for ppc64 or ppc32
|
||||
respectively. They are primary used for save/restore GPRs in jump-pad,
|
||||
not used for bytecode compiling. */
|
||||
|
||||
#ifdef __powerpc64__
|
||||
#define GEN_LOAD(buf, rt, ra, si, is_64) (is_64 ? \
|
||||
GEN_LD (buf, rt, ra, si) : \
|
||||
GEN_LWZ (buf, rt, ra, si))
|
||||
#define GEN_STORE(buf, rt, ra, si, is_64) (is_64 ? \
|
||||
GEN_STD (buf, rt, ra, si) : \
|
||||
GEN_STW (buf, rt, ra, si))
|
||||
#else
|
||||
#define GEN_LOAD(buf, rt, ra, si, is_64) GEN_LWZ (buf, rt, ra, si)
|
||||
#define GEN_STORE(buf, rt, ra, si, is_64) GEN_STW (buf, rt, ra, si)
|
||||
#endif
|
||||
|
||||
/* Generate a sequence of instructions to load IMM in the register REG.
|
||||
Write the instructions in BUF and return the number of bytes written. */
|
||||
|
||||
static int
|
||||
gen_limm (uint32_t *buf, int reg, uint64_t imm, int is_64)
|
||||
{
|
||||
uint32_t *p = buf;
|
||||
|
||||
if ((imm + 32768) < 65536)
|
||||
{
|
||||
/* li reg, imm[15:0] */
|
||||
p += GEN_LI (p, reg, imm);
|
||||
}
|
||||
else if ((imm >> 32) == 0)
|
||||
{
|
||||
/* lis reg, imm[31:16]
|
||||
ori reg, reg, imm[15:0]
|
||||
rldicl reg, reg, 0, 32 */
|
||||
p += GEN_LIS (p, reg, (imm >> 16) & 0xffff);
|
||||
if ((imm & 0xffff) != 0)
|
||||
p += GEN_ORI (p, reg, reg, imm & 0xffff);
|
||||
/* Clear upper 32-bit if sign-bit is set. */
|
||||
if (imm & (1u << 31) && is_64)
|
||||
p += GEN_RLDICL (p, reg, reg, 0, 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdb_assert (is_64);
|
||||
/* lis reg, <imm[63:48]>
|
||||
ori reg, reg, <imm[48:32]>
|
||||
rldicr reg, reg, 32, 31
|
||||
oris reg, reg, <imm[31:16]>
|
||||
ori reg, reg, <imm[15:0]> */
|
||||
p += GEN_LIS (p, reg, ((imm >> 48) & 0xffff));
|
||||
if (((imm >> 32) & 0xffff) != 0)
|
||||
p += GEN_ORI (p, reg, reg, ((imm >> 32) & 0xffff));
|
||||
p += GEN_RLDICR (p, reg, reg, 32, 31);
|
||||
if (((imm >> 16) & 0xffff) != 0)
|
||||
p += GEN_ORIS (p, reg, reg, ((imm >> 16) & 0xffff));
|
||||
if ((imm & 0xffff) != 0)
|
||||
p += GEN_ORI (p, reg, reg, (imm & 0xffff));
|
||||
}
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
/* Generate a sequence for atomically exchange at location LOCK.
|
||||
This code sequence clobbers r6, r7, r8. LOCK is the location for
|
||||
the atomic-xchg, OLD_VALUE is expected old value stored in the
|
||||
location, and R_NEW is a register for the new value. */
|
||||
|
||||
static int
|
||||
gen_atomic_xchg (uint32_t *buf, CORE_ADDR lock, int old_value, int r_new,
|
||||
int is_64)
|
||||
{
|
||||
const int r_lock = 6;
|
||||
const int r_old = 7;
|
||||
const int r_tmp = 8;
|
||||
uint32_t *p = buf;
|
||||
|
||||
/*
|
||||
1: lwarx TMP, 0, LOCK
|
||||
cmpwi TMP, OLD
|
||||
bne 1b
|
||||
stwcx. NEW, 0, LOCK
|
||||
bne 1b */
|
||||
|
||||
p += gen_limm (p, r_lock, lock, is_64);
|
||||
p += gen_limm (p, r_old, old_value, is_64);
|
||||
|
||||
p += GEN_LWARX (p, r_tmp, 0, r_lock);
|
||||
p += GEN_CMPW (p, r_tmp, r_old);
|
||||
p += GEN_BNE (p, -8);
|
||||
p += GEN_STWCX (p, r_new, 0, r_lock);
|
||||
p += GEN_BNE (p, -16);
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
/* Generate a sequence of instructions for calling a function
|
||||
at address of FN. Return the number of bytes are written in BUF. */
|
||||
|
||||
static int
|
||||
gen_call (uint32_t *buf, CORE_ADDR fn, int is_64, int is_opd)
|
||||
{
|
||||
uint32_t *p = buf;
|
||||
|
||||
/* Must be called by r12 for caller to calculate TOC address. */
|
||||
p += gen_limm (p, 12, fn, is_64);
|
||||
if (is_opd)
|
||||
{
|
||||
p += GEN_LOAD (p, 11, 12, 16, is_64);
|
||||
p += GEN_LOAD (p, 2, 12, 8, is_64);
|
||||
p += GEN_LOAD (p, 12, 12, 0, is_64);
|
||||
}
|
||||
p += GEN_MTSPR (p, 12, 9); /* mtctr r12 */
|
||||
*p++ = 0x4e800421; /* bctrl */
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
/* Copy the instruction from OLDLOC to *TO, and update *TO to *TO + size
|
||||
of instruction. This function is used to adjust pc-relative instructions
|
||||
when copying. */
|
||||
|
||||
static void
|
||||
ppc_relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
|
||||
{
|
||||
uint32_t insn, op6;
|
||||
long rel, newrel;
|
||||
|
||||
read_inferior_memory (oldloc, (unsigned char *) &insn, 4);
|
||||
op6 = PPC_OP6 (insn);
|
||||
|
||||
if (op6 == 18 && (insn & 2) == 0)
|
||||
{
|
||||
/* branch && AA = 0 */
|
||||
rel = PPC_LI (insn);
|
||||
newrel = (oldloc - *to) + rel;
|
||||
|
||||
/* Out of range. Cannot relocate instruction. */
|
||||
if (newrel >= (1 << 25) || newrel < -(1 << 25))
|
||||
return;
|
||||
|
||||
insn = (insn & ~0x3fffffc) | (newrel & 0x3fffffc);
|
||||
}
|
||||
else if (op6 == 16 && (insn & 2) == 0)
|
||||
{
|
||||
/* conditional branch && AA = 0 */
|
||||
|
||||
/* If the new relocation is too big for even a 26-bit unconditional
|
||||
branch, there is nothing we can do. Just abort.
|
||||
|
||||
Otherwise, if it can be fit in 16-bit conditional branch, just
|
||||
copy the instruction and relocate the address.
|
||||
|
||||
If the it's big for conditional-branch (16-bit), try to invert the
|
||||
condition and jump with 26-bit branch. For example,
|
||||
|
||||
beq .Lgoto
|
||||
INSN1
|
||||
|
||||
=>
|
||||
|
||||
bne 1f (+8)
|
||||
b .Lgoto
|
||||
1:INSN1
|
||||
|
||||
After this transform, we are actually jump from *TO+4 instead of *TO,
|
||||
so check the relocation again because it will be 1-insn farther then
|
||||
before if *TO is after OLDLOC.
|
||||
|
||||
|
||||
For BDNZT (or so) is transformed from
|
||||
|
||||
bdnzt eq, .Lgoto
|
||||
INSN1
|
||||
|
||||
=>
|
||||
|
||||
bdz 1f (+12)
|
||||
bf eq, 1f (+8)
|
||||
b .Lgoto
|
||||
1:INSN1
|
||||
|
||||
See also "BO field encodings". */
|
||||
|
||||
rel = PPC_BD (insn);
|
||||
newrel = (oldloc - *to) + rel;
|
||||
|
||||
if (newrel < (1 << 15) && newrel >= -(1 << 15))
|
||||
insn = (insn & ~0xfffc) | (newrel & 0xfffc);
|
||||
else if ((PPC_BO (insn) & 0x14) == 0x4 || (PPC_BO (insn) & 0x14) == 0x10)
|
||||
{
|
||||
newrel -= 4;
|
||||
|
||||
/* Out of range. Cannot relocate instruction. */
|
||||
if (newrel >= (1 << 25) || newrel < -(1 << 25))
|
||||
return;
|
||||
|
||||
if ((PPC_BO (insn) & 0x14) == 0x4)
|
||||
insn ^= (1 << 24);
|
||||
else if ((PPC_BO (insn) & 0x14) == 0x10)
|
||||
insn ^= (1 << 22);
|
||||
|
||||
/* Jump over the unconditional branch. */
|
||||
insn = (insn & ~0xfffc) | 0x8;
|
||||
write_inferior_memory (*to, (unsigned char *) &insn, 4);
|
||||
*to += 4;
|
||||
|
||||
/* Build a unconditional branch and copy LK bit. */
|
||||
insn = (18 << 26) | (0x3fffffc & newrel) | (insn & 0x3);
|
||||
write_inferior_memory (*to, (unsigned char *) &insn, 4);
|
||||
*to += 4;
|
||||
|
||||
return;
|
||||
}
|
||||
else if ((PPC_BO (insn) & 0x14) == 0)
|
||||
{
|
||||
uint32_t bdnz_insn = (16 << 26) | (0x10 << 21) | 12;
|
||||
uint32_t bf_insn = (16 << 26) | (0x4 << 21) | 8;
|
||||
|
||||
newrel -= 8;
|
||||
|
||||
/* Out of range. Cannot relocate instruction. */
|
||||
if (newrel >= (1 << 25) || newrel < -(1 << 25))
|
||||
return;
|
||||
|
||||
/* Copy BI field. */
|
||||
bf_insn |= (insn & 0x1f0000);
|
||||
|
||||
/* Invert condition. */
|
||||
bdnz_insn |= (insn ^ (1 << 22)) & (1 << 22);
|
||||
bf_insn |= (insn ^ (1 << 24)) & (1 << 24);
|
||||
|
||||
write_inferior_memory (*to, (unsigned char *) &bdnz_insn, 4);
|
||||
*to += 4;
|
||||
write_inferior_memory (*to, (unsigned char *) &bf_insn, 4);
|
||||
*to += 4;
|
||||
|
||||
/* Build a unconditional branch and copy LK bit. */
|
||||
insn = (18 << 26) | (0x3fffffc & newrel) | (insn & 0x3);
|
||||
write_inferior_memory (*to, (unsigned char *) &insn, 4);
|
||||
*to += 4;
|
||||
|
||||
return;
|
||||
}
|
||||
else /* (BO & 0x14) == 0x14, branch always. */
|
||||
{
|
||||
/* Out of range. Cannot relocate instruction. */
|
||||
if (newrel >= (1 << 25) || newrel < -(1 << 25))
|
||||
return;
|
||||
|
||||
/* Build a unconditional branch and copy LK bit. */
|
||||
insn = (18 << 26) | (0x3fffffc & newrel) | (insn & 0x3);
|
||||
write_inferior_memory (*to, (unsigned char *) &insn, 4);
|
||||
*to += 4;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
write_inferior_memory (*to, (unsigned char *) &insn, 4);
|
||||
*to += 4;
|
||||
}
|
||||
|
||||
/* Implement install_fast_tracepoint_jump_pad of target_ops.
|
||||
See target.h for details. */
|
||||
|
||||
static int
|
||||
ppc_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr,
|
||||
CORE_ADDR collector,
|
||||
CORE_ADDR lockaddr,
|
||||
ULONGEST orig_size,
|
||||
CORE_ADDR *jump_entry,
|
||||
CORE_ADDR *trampoline,
|
||||
ULONGEST *trampoline_size,
|
||||
unsigned char *jjump_pad_insn,
|
||||
ULONGEST *jjump_pad_insn_size,
|
||||
CORE_ADDR *adjusted_insn_addr,
|
||||
CORE_ADDR *adjusted_insn_addr_end,
|
||||
char *err)
|
||||
{
|
||||
uint32_t buf[256];
|
||||
uint32_t *p = buf;
|
||||
int j, offset;
|
||||
CORE_ADDR buildaddr = *jump_entry;
|
||||
const CORE_ADDR entryaddr = *jump_entry;
|
||||
int rsz, min_frame, frame_size, tp_reg;
|
||||
#ifdef __powerpc64__
|
||||
struct regcache *regcache = get_thread_regcache (current_thread, 0);
|
||||
int is_64 = register_size (regcache->tdesc, 0) == 8;
|
||||
int is_opd = is_64 && !is_elfv2_inferior ();
|
||||
#else
|
||||
int is_64 = 0, is_opd = 0;
|
||||
#endif
|
||||
|
||||
#ifdef __powerpc64__
|
||||
if (is_64)
|
||||
{
|
||||
/* Minimum frame size is 32 bytes for ELFv2, and 112 bytes for ELFv1. */
|
||||
rsz = 8;
|
||||
min_frame = 112;
|
||||
frame_size = (40 * rsz) + min_frame;
|
||||
tp_reg = 13;
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
rsz = 4;
|
||||
min_frame = 16;
|
||||
frame_size = (40 * rsz) + min_frame;
|
||||
tp_reg = 2;
|
||||
#ifdef __powerpc64__
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Stack frame layout for this jump pad,
|
||||
|
||||
High thread_area (r13/r2) |
|
||||
tpoint - collecting_t obj
|
||||
PC/<tpaddr> | +36
|
||||
CTR | +35
|
||||
LR | +34
|
||||
XER | +33
|
||||
CR | +32
|
||||
R31 |
|
||||
R29 |
|
||||
... |
|
||||
R1 | +1
|
||||
R0 - collected registers
|
||||
... |
|
||||
... |
|
||||
Low Back-chain -
|
||||
|
||||
|
||||
The code flow of this jump pad,
|
||||
|
||||
1. Adjust SP
|
||||
2. Save GPR and SPR
|
||||
3. Prepare argument
|
||||
4. Call gdb_collector
|
||||
5. Restore GPR and SPR
|
||||
6. Restore SP
|
||||
7. Build a jump for back to the program
|
||||
8. Copy/relocate original instruction
|
||||
9. Build a jump for replacing orignal instruction. */
|
||||
|
||||
/* Adjust stack pointer. */
|
||||
if (is_64)
|
||||
p += GEN_STDU (p, 1, 1, -frame_size); /* stdu r1,-frame_size(r1) */
|
||||
else
|
||||
p += GEN_STWU (p, 1, 1, -frame_size); /* stwu r1,-frame_size(r1) */
|
||||
|
||||
/* Store GPRs. Save R1 later, because it had just been modified, but
|
||||
we want the original value. */
|
||||
for (j = 2; j < 32; j++)
|
||||
p += GEN_STORE (p, j, 1, min_frame + j * rsz, is_64);
|
||||
p += GEN_STORE (p, 0, 1, min_frame + 0 * rsz, is_64);
|
||||
/* Set r0 to the original value of r1 before adjusting stack frame,
|
||||
and then save it. */
|
||||
p += GEN_ADDI (p, 0, 1, frame_size);
|
||||
p += GEN_STORE (p, 0, 1, min_frame + 1 * rsz, is_64);
|
||||
|
||||
/* Save CR, XER, LR, and CTR. */
|
||||
p += GEN_MFCR (p, 3); /* mfcr r3 */
|
||||
p += GEN_MFSPR (p, 4, 1); /* mfxer r4 */
|
||||
p += GEN_MFSPR (p, 5, 8); /* mflr r5 */
|
||||
p += GEN_MFSPR (p, 6, 9); /* mfctr r6 */
|
||||
p += GEN_STORE (p, 3, 1, min_frame + 32 * rsz, is_64);/* std r3, 32(r1) */
|
||||
p += GEN_STORE (p, 4, 1, min_frame + 33 * rsz, is_64);/* std r4, 33(r1) */
|
||||
p += GEN_STORE (p, 5, 1, min_frame + 34 * rsz, is_64);/* std r5, 34(r1) */
|
||||
p += GEN_STORE (p, 6, 1, min_frame + 35 * rsz, is_64);/* std r6, 35(r1) */
|
||||
|
||||
/* Save PC<tpaddr> */
|
||||
p += gen_limm (p, 3, tpaddr, is_64);
|
||||
p += GEN_STORE (p, 3, 1, min_frame + 36 * rsz, is_64);
|
||||
|
||||
|
||||
/* Setup arguments to collector. */
|
||||
/* Set r4 to collected registers. */
|
||||
p += GEN_ADDI (p, 4, 1, min_frame);
|
||||
/* Set r3 to TPOINT. */
|
||||
p += gen_limm (p, 3, tpoint, is_64);
|
||||
|
||||
/* Prepare collecting_t object for lock. */
|
||||
p += GEN_STORE (p, 3, 1, min_frame + 37 * rsz, is_64);
|
||||
p += GEN_STORE (p, tp_reg, 1, min_frame + 38 * rsz, is_64);
|
||||
/* Set R5 to collecting object. */
|
||||
p += GEN_ADDI (p, 5, 1, 37 * rsz);
|
||||
|
||||
p += GEN_LWSYNC (p);
|
||||
p += gen_atomic_xchg (p, lockaddr, 0, 5, is_64);
|
||||
p += GEN_LWSYNC (p);
|
||||
|
||||
/* Call to collector. */
|
||||
p += gen_call (p, collector, is_64, is_opd);
|
||||
|
||||
/* Simply write 0 to release the lock. */
|
||||
p += gen_limm (p, 3, lockaddr, is_64);
|
||||
p += gen_limm (p, 4, 0, is_64);
|
||||
p += GEN_LWSYNC (p);
|
||||
p += GEN_STORE (p, 4, 3, 0, is_64);
|
||||
|
||||
/* Restore stack and registers. */
|
||||
p += GEN_LOAD (p, 3, 1, min_frame + 32 * rsz, is_64); /* ld r3, 32(r1) */
|
||||
p += GEN_LOAD (p, 4, 1, min_frame + 33 * rsz, is_64); /* ld r4, 33(r1) */
|
||||
p += GEN_LOAD (p, 5, 1, min_frame + 34 * rsz, is_64); /* ld r5, 34(r1) */
|
||||
p += GEN_LOAD (p, 6, 1, min_frame + 35 * rsz, is_64); /* ld r6, 35(r1) */
|
||||
p += GEN_MTCR (p, 3); /* mtcr r3 */
|
||||
p += GEN_MTSPR (p, 4, 1); /* mtxer r4 */
|
||||
p += GEN_MTSPR (p, 5, 8); /* mtlr r5 */
|
||||
p += GEN_MTSPR (p, 6, 9); /* mtctr r6 */
|
||||
|
||||
/* Restore GPRs. */
|
||||
for (j = 2; j < 32; j++)
|
||||
p += GEN_LOAD (p, j, 1, min_frame + j * rsz, is_64);
|
||||
p += GEN_LOAD (p, 0, 1, min_frame + 0 * rsz, is_64);
|
||||
/* Restore SP. */
|
||||
p += GEN_ADDI (p, 1, 1, frame_size);
|
||||
|
||||
/* Flush instructions to inferior memory. */
|
||||
write_inferior_memory (buildaddr, (unsigned char *) buf, (p - buf) * 4);
|
||||
|
||||
/* Now, insert the original instruction to execute in the jump pad. */
|
||||
*adjusted_insn_addr = buildaddr + (p - buf) * 4;
|
||||
*adjusted_insn_addr_end = *adjusted_insn_addr;
|
||||
ppc_relocate_instruction (adjusted_insn_addr_end, tpaddr);
|
||||
|
||||
/* Verify the relocation size. If should be 4 for normal copy,
|
||||
8 or 12 for some conditional branch. */
|
||||
if ((*adjusted_insn_addr_end - *adjusted_insn_addr == 0)
|
||||
|| (*adjusted_insn_addr_end - *adjusted_insn_addr > 12))
|
||||
{
|
||||
sprintf (err, "E.Unexpected instruction length = %d"
|
||||
"when relocate instruction.",
|
||||
(int) (*adjusted_insn_addr_end - *adjusted_insn_addr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
buildaddr = *adjusted_insn_addr_end;
|
||||
p = buf;
|
||||
/* Finally, write a jump back to the program. */
|
||||
offset = (tpaddr + 4) - buildaddr;
|
||||
if (offset >= (1 << 25) || offset < -(1 << 25))
|
||||
{
|
||||
sprintf (err, "E.Jump back from jump pad too far from tracepoint "
|
||||
"(offset 0x%x > 26-bit).", offset);
|
||||
return 1;
|
||||
}
|
||||
/* b <tpaddr+4> */
|
||||
p += GEN_B (p, offset);
|
||||
write_inferior_memory (buildaddr, (unsigned char *) buf, (p - buf) * 4);
|
||||
*jump_entry = buildaddr + (p - buf) * 4;
|
||||
|
||||
/* The jump pad is now built. Wire in a jump to our jump pad. This
|
||||
is always done last (by our caller actually), so that we can
|
||||
install fast tracepoints with threads running. This relies on
|
||||
the agent's atomic write support. */
|
||||
offset = entryaddr - tpaddr;
|
||||
if (offset >= (1 << 25) || offset < -(1 << 25))
|
||||
{
|
||||
sprintf (err, "E.Jump back from jump pad too far from tracepoint "
|
||||
"(offset 0x%x > 26-bit).", offset);
|
||||
return 1;
|
||||
}
|
||||
/* b <jentry> */
|
||||
GEN_B ((uint32_t *) jjump_pad_insn, offset);
|
||||
*jjump_pad_insn_size = 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the minimum instruction length for installing a tracepoint. */
|
||||
|
||||
static int
|
||||
ppc_get_min_fast_tracepoint_insn_len (void)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
/* Implementation of linux_target_ops method "get_ipa_tdesc_idx". */
|
||||
|
||||
static int
|
||||
ppc_get_ipa_tdesc_idx (void)
|
||||
{
|
||||
struct regcache *regcache = get_thread_regcache (current_thread, 0);
|
||||
const struct target_desc *tdesc = regcache->tdesc;
|
||||
|
||||
#ifdef __powerpc64__
|
||||
if (tdesc == tdesc_powerpc_64l)
|
||||
return PPC_TDESC_BASE;
|
||||
if (tdesc == tdesc_powerpc_altivec64l)
|
||||
return PPC_TDESC_ALTIVEC;
|
||||
if (tdesc == tdesc_powerpc_cell64l)
|
||||
return PPC_TDESC_CELL;
|
||||
if (tdesc == tdesc_powerpc_vsx64l)
|
||||
return PPC_TDESC_VSX;
|
||||
if (tdesc == tdesc_powerpc_isa205_64l)
|
||||
return PPC_TDESC_ISA205;
|
||||
if (tdesc == tdesc_powerpc_isa205_altivec64l)
|
||||
return PPC_TDESC_ISA205_ALTIVEC;
|
||||
if (tdesc == tdesc_powerpc_isa205_vsx64l)
|
||||
return PPC_TDESC_ISA205_VSX;
|
||||
#endif
|
||||
|
||||
if (tdesc == tdesc_powerpc_32l)
|
||||
return PPC_TDESC_BASE;
|
||||
if (tdesc == tdesc_powerpc_altivec32l)
|
||||
return PPC_TDESC_ALTIVEC;
|
||||
if (tdesc == tdesc_powerpc_cell32l)
|
||||
return PPC_TDESC_CELL;
|
||||
if (tdesc == tdesc_powerpc_vsx32l)
|
||||
return PPC_TDESC_VSX;
|
||||
if (tdesc == tdesc_powerpc_isa205_32l)
|
||||
return PPC_TDESC_ISA205;
|
||||
if (tdesc == tdesc_powerpc_isa205_altivec32l)
|
||||
return PPC_TDESC_ISA205_ALTIVEC;
|
||||
if (tdesc == tdesc_powerpc_isa205_vsx32l)
|
||||
return PPC_TDESC_ISA205_VSX;
|
||||
if (tdesc == tdesc_powerpc_e500l)
|
||||
return PPC_TDESC_E500;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct linux_target_ops the_low_target = {
|
||||
ppc_arch_setup,
|
||||
ppc_regs_info,
|
||||
|
@ -789,13 +1535,15 @@ struct linux_target_ops the_low_target = {
|
|||
NULL, /* prepare_to_resume */
|
||||
NULL, /* process_qsupported */
|
||||
ppc_supports_tracepoints,
|
||||
NULL, /* get_thread_area */
|
||||
NULL, /* install_fast_tracepoint_jump_pad */
|
||||
ppc_get_thread_area,
|
||||
ppc_install_fast_tracepoint_jump_pad,
|
||||
NULL, /* emit_ops */
|
||||
NULL, /* get_min_fast_tracepoint_insn_len */
|
||||
ppc_get_min_fast_tracepoint_insn_len,
|
||||
NULL, /* supports_range_stepping */
|
||||
NULL, /* breakpoint_kind_from_current_state */
|
||||
ppc_supports_hardware_single_step,
|
||||
NULL, /* get_syscall_trapinfo */
|
||||
ppc_get_ipa_tdesc_idx,
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -811,6 +1559,7 @@ initialize_low_arch (void)
|
|||
init_registers_powerpc_isa205_altivec32l ();
|
||||
init_registers_powerpc_isa205_vsx32l ();
|
||||
init_registers_powerpc_e500l ();
|
||||
#if __powerpc64__
|
||||
init_registers_powerpc_64l ();
|
||||
init_registers_powerpc_altivec64l ();
|
||||
init_registers_powerpc_cell64l ();
|
||||
|
@ -818,6 +1567,7 @@ initialize_low_arch (void)
|
|||
init_registers_powerpc_isa205_64l ();
|
||||
init_registers_powerpc_isa205_altivec64l ();
|
||||
init_registers_powerpc_isa205_vsx64l ();
|
||||
#endif
|
||||
|
||||
initialize_regsets_info (&ppc_regsets_info);
|
||||
}
|
||||
|
|
101
gdb/gdbserver/linux-ppc-tdesc.h
Normal file
101
gdb/gdbserver/linux-ppc-tdesc.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* Low level support for ppc, shared between gdbserver and IPA.
|
||||
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Note: since IPA obviously knows what ABI it's running on (32 vs 64),
|
||||
it's sufficient to pass only the register set here. This, together with
|
||||
the ABI known at IPA compile time, maps to a tdesc. */
|
||||
|
||||
enum ppc_linux_tdesc {
|
||||
PPC_TDESC_BASE,
|
||||
PPC_TDESC_ALTIVEC,
|
||||
PPC_TDESC_CELL,
|
||||
PPC_TDESC_VSX,
|
||||
PPC_TDESC_ISA205,
|
||||
PPC_TDESC_ISA205_ALTIVEC,
|
||||
PPC_TDESC_ISA205_VSX,
|
||||
PPC_TDESC_E500,
|
||||
};
|
||||
|
||||
#if !defined __powerpc64__ || !defined IN_PROCESS_AGENT
|
||||
|
||||
/* Defined in auto-generated file powerpc-32l.c. */
|
||||
void init_registers_powerpc_32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-altivec32l.c. */
|
||||
void init_registers_powerpc_altivec32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_altivec32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-cell32l.c. */
|
||||
void init_registers_powerpc_cell32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_cell32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-vsx32l.c. */
|
||||
void init_registers_powerpc_vsx32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_vsx32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-32l.c. */
|
||||
void init_registers_powerpc_isa205_32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-altivec32l.c. */
|
||||
void init_registers_powerpc_isa205_altivec32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_altivec32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-vsx32l.c. */
|
||||
void init_registers_powerpc_isa205_vsx32l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_vsx32l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-e500l.c. */
|
||||
void init_registers_powerpc_e500l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_e500l;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined __powerpc64__
|
||||
|
||||
/* Defined in auto-generated file powerpc-64l.c. */
|
||||
void init_registers_powerpc_64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-altivec64l.c. */
|
||||
void init_registers_powerpc_altivec64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_altivec64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-cell64l.c. */
|
||||
void init_registers_powerpc_cell64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_cell64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-vsx64l.c. */
|
||||
void init_registers_powerpc_vsx64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_vsx64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-64l.c. */
|
||||
void init_registers_powerpc_isa205_64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-altivec64l.c. */
|
||||
void init_registers_powerpc_isa205_altivec64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_altivec64l;
|
||||
|
||||
/* Defined in auto-generated file powerpc-isa205-vsx64l.c. */
|
||||
void init_registers_powerpc_isa205_vsx64l (void);
|
||||
extern const struct target_desc *tdesc_powerpc_isa205_vsx64l;
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue