397 lines
8 KiB
C++
397 lines
8 KiB
C++
|
/* GNU/Linux/IA64 specific low level interface, for the remote server for GDB.
|
||
|
Copyright (C) 1995-2022 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 "linux-low.h"
|
||
|
|
||
|
#ifdef HAVE_SYS_REG_H
|
||
|
#include <sys/reg.h>
|
||
|
#endif
|
||
|
|
||
|
/* Linux target op definitions for the IA64 architecture. */
|
||
|
|
||
|
class ia64_target : public linux_process_target
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
const regs_info *get_regs_info () override;
|
||
|
|
||
|
const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
|
||
|
|
||
|
protected:
|
||
|
|
||
|
void low_arch_setup () override;
|
||
|
|
||
|
bool low_cannot_fetch_register (int regno) override;
|
||
|
|
||
|
bool low_cannot_store_register (int regno) override;
|
||
|
|
||
|
bool low_fetch_register (regcache *regcache, int regno) override;
|
||
|
|
||
|
bool low_breakpoint_at (CORE_ADDR pc) override;
|
||
|
};
|
||
|
|
||
|
/* The singleton target ops object. */
|
||
|
|
||
|
static ia64_target the_ia64_target;
|
||
|
|
||
|
const gdb_byte *
|
||
|
ia64_target::sw_breakpoint_from_kind (int kind, int *size)
|
||
|
{
|
||
|
gdb_assert_not_reached ("target op sw_breakpoint_from_kind is not "
|
||
|
"implemented by this target");
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
ia64_target::low_breakpoint_at (CORE_ADDR pc)
|
||
|
{
|
||
|
gdb_assert_not_reached ("linux target op low_breakpoint_at is not "
|
||
|
"implemented by this target");
|
||
|
}
|
||
|
|
||
|
/* Defined in auto-generated file reg-ia64.c. */
|
||
|
void init_registers_ia64 (void);
|
||
|
extern const struct target_desc *tdesc_ia64;
|
||
|
|
||
|
#define ia64_num_regs 462
|
||
|
|
||
|
#include <asm/ptrace_offsets.h>
|
||
|
|
||
|
static int ia64_regmap[] =
|
||
|
{
|
||
|
/* general registers */
|
||
|
-1, /* gr0 not available; i.e, it's always zero */
|
||
|
PT_R1,
|
||
|
PT_R2,
|
||
|
PT_R3,
|
||
|
PT_R4,
|
||
|
PT_R5,
|
||
|
PT_R6,
|
||
|
PT_R7,
|
||
|
PT_R8,
|
||
|
PT_R9,
|
||
|
PT_R10,
|
||
|
PT_R11,
|
||
|
PT_R12,
|
||
|
PT_R13,
|
||
|
PT_R14,
|
||
|
PT_R15,
|
||
|
PT_R16,
|
||
|
PT_R17,
|
||
|
PT_R18,
|
||
|
PT_R19,
|
||
|
PT_R20,
|
||
|
PT_R21,
|
||
|
PT_R22,
|
||
|
PT_R23,
|
||
|
PT_R24,
|
||
|
PT_R25,
|
||
|
PT_R26,
|
||
|
PT_R27,
|
||
|
PT_R28,
|
||
|
PT_R29,
|
||
|
PT_R30,
|
||
|
PT_R31,
|
||
|
/* gr32 through gr127 not directly available via the ptrace interface */
|
||
|
-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,
|
||
|
-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,
|
||
|
-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,
|
||
|
/* Floating point registers */
|
||
|
-1, -1, /* f0 and f1 not available (f0 is +0.0 and f1 is +1.0) */
|
||
|
PT_F2,
|
||
|
PT_F3,
|
||
|
PT_F4,
|
||
|
PT_F5,
|
||
|
PT_F6,
|
||
|
PT_F7,
|
||
|
PT_F8,
|
||
|
PT_F9,
|
||
|
PT_F10,
|
||
|
PT_F11,
|
||
|
PT_F12,
|
||
|
PT_F13,
|
||
|
PT_F14,
|
||
|
PT_F15,
|
||
|
PT_F16,
|
||
|
PT_F17,
|
||
|
PT_F18,
|
||
|
PT_F19,
|
||
|
PT_F20,
|
||
|
PT_F21,
|
||
|
PT_F22,
|
||
|
PT_F23,
|
||
|
PT_F24,
|
||
|
PT_F25,
|
||
|
PT_F26,
|
||
|
PT_F27,
|
||
|
PT_F28,
|
||
|
PT_F29,
|
||
|
PT_F30,
|
||
|
PT_F31,
|
||
|
PT_F32,
|
||
|
PT_F33,
|
||
|
PT_F34,
|
||
|
PT_F35,
|
||
|
PT_F36,
|
||
|
PT_F37,
|
||
|
PT_F38,
|
||
|
PT_F39,
|
||
|
PT_F40,
|
||
|
PT_F41,
|
||
|
PT_F42,
|
||
|
PT_F43,
|
||
|
PT_F44,
|
||
|
PT_F45,
|
||
|
PT_F46,
|
||
|
PT_F47,
|
||
|
PT_F48,
|
||
|
PT_F49,
|
||
|
PT_F50,
|
||
|
PT_F51,
|
||
|
PT_F52,
|
||
|
PT_F53,
|
||
|
PT_F54,
|
||
|
PT_F55,
|
||
|
PT_F56,
|
||
|
PT_F57,
|
||
|
PT_F58,
|
||
|
PT_F59,
|
||
|
PT_F60,
|
||
|
PT_F61,
|
||
|
PT_F62,
|
||
|
PT_F63,
|
||
|
PT_F64,
|
||
|
PT_F65,
|
||
|
PT_F66,
|
||
|
PT_F67,
|
||
|
PT_F68,
|
||
|
PT_F69,
|
||
|
PT_F70,
|
||
|
PT_F71,
|
||
|
PT_F72,
|
||
|
PT_F73,
|
||
|
PT_F74,
|
||
|
PT_F75,
|
||
|
PT_F76,
|
||
|
PT_F77,
|
||
|
PT_F78,
|
||
|
PT_F79,
|
||
|
PT_F80,
|
||
|
PT_F81,
|
||
|
PT_F82,
|
||
|
PT_F83,
|
||
|
PT_F84,
|
||
|
PT_F85,
|
||
|
PT_F86,
|
||
|
PT_F87,
|
||
|
PT_F88,
|
||
|
PT_F89,
|
||
|
PT_F90,
|
||
|
PT_F91,
|
||
|
PT_F92,
|
||
|
PT_F93,
|
||
|
PT_F94,
|
||
|
PT_F95,
|
||
|
PT_F96,
|
||
|
PT_F97,
|
||
|
PT_F98,
|
||
|
PT_F99,
|
||
|
PT_F100,
|
||
|
PT_F101,
|
||
|
PT_F102,
|
||
|
PT_F103,
|
||
|
PT_F104,
|
||
|
PT_F105,
|
||
|
PT_F106,
|
||
|
PT_F107,
|
||
|
PT_F108,
|
||
|
PT_F109,
|
||
|
PT_F110,
|
||
|
PT_F111,
|
||
|
PT_F112,
|
||
|
PT_F113,
|
||
|
PT_F114,
|
||
|
PT_F115,
|
||
|
PT_F116,
|
||
|
PT_F117,
|
||
|
PT_F118,
|
||
|
PT_F119,
|
||
|
PT_F120,
|
||
|
PT_F121,
|
||
|
PT_F122,
|
||
|
PT_F123,
|
||
|
PT_F124,
|
||
|
PT_F125,
|
||
|
PT_F126,
|
||
|
PT_F127,
|
||
|
/* predicate registers - we don't fetch these individually */
|
||
|
-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,
|
||
|
-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,
|
||
|
/* branch registers */
|
||
|
PT_B0,
|
||
|
PT_B1,
|
||
|
PT_B2,
|
||
|
PT_B3,
|
||
|
PT_B4,
|
||
|
PT_B5,
|
||
|
PT_B6,
|
||
|
PT_B7,
|
||
|
/* virtual frame pointer and virtual return address pointer */
|
||
|
-1, -1,
|
||
|
/* other registers */
|
||
|
PT_PR,
|
||
|
PT_CR_IIP, /* ip */
|
||
|
PT_CR_IPSR, /* psr */
|
||
|
PT_CFM, /* cfm */
|
||
|
/* kernel registers not visible via ptrace interface (?) */
|
||
|
-1, -1, -1, -1, -1, -1, -1, -1,
|
||
|
/* hole */
|
||
|
-1, -1, -1, -1, -1, -1, -1, -1,
|
||
|
PT_AR_RSC,
|
||
|
PT_AR_BSP,
|
||
|
PT_AR_BSPSTORE,
|
||
|
PT_AR_RNAT,
|
||
|
-1,
|
||
|
-1, /* Not available: FCR, IA32 floating control register */
|
||
|
-1, -1,
|
||
|
-1, /* Not available: EFLAG */
|
||
|
-1, /* Not available: CSD */
|
||
|
-1, /* Not available: SSD */
|
||
|
-1, /* Not available: CFLG */
|
||
|
-1, /* Not available: FSR */
|
||
|
-1, /* Not available: FIR */
|
||
|
-1, /* Not available: FDR */
|
||
|
-1,
|
||
|
PT_AR_CCV,
|
||
|
-1, -1, -1,
|
||
|
PT_AR_UNAT,
|
||
|
-1, -1, -1,
|
||
|
PT_AR_FPSR,
|
||
|
-1, -1, -1,
|
||
|
-1, /* Not available: ITC */
|
||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
|
PT_AR_PFS,
|
||
|
PT_AR_LC,
|
||
|
PT_AR_EC,
|
||
|
-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, -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,
|
||
|
};
|
||
|
|
||
|
bool
|
||
|
ia64_target::low_cannot_store_register (int regno)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
ia64_target::low_cannot_fetch_register (int regno)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* GDB register numbers. */
|
||
|
#define IA64_GR0_REGNUM 0
|
||
|
#define IA64_FR0_REGNUM 128
|
||
|
#define IA64_FR1_REGNUM 129
|
||
|
|
||
|
bool
|
||
|
ia64_target::low_fetch_register (regcache *regcache, int regnum)
|
||
|
{
|
||
|
/* r0 cannot be fetched but is always zero. */
|
||
|
if (regnum == IA64_GR0_REGNUM)
|
||
|
{
|
||
|
const gdb_byte zero[8] = { 0 };
|
||
|
|
||
|
gdb_assert (sizeof (zero) == register_size (regcache->tdesc, regnum));
|
||
|
supply_register (regcache, regnum, zero);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/* fr0 cannot be fetched but is always zero. */
|
||
|
if (regnum == IA64_FR0_REGNUM)
|
||
|
{
|
||
|
const gdb_byte f_zero[16] = { 0 };
|
||
|
|
||
|
gdb_assert (sizeof (f_zero) == register_size (regcache->tdesc, regnum));
|
||
|
supply_register (regcache, regnum, f_zero);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/* fr1 cannot be fetched but is always one (1.0). */
|
||
|
if (regnum == IA64_FR1_REGNUM)
|
||
|
{
|
||
|
const gdb_byte f_one[16] =
|
||
|
{ 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 };
|
||
|
|
||
|
gdb_assert (sizeof (f_one) == register_size (regcache->tdesc, regnum));
|
||
|
supply_register (regcache, regnum, f_one);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
static struct usrregs_info ia64_usrregs_info =
|
||
|
{
|
||
|
ia64_num_regs,
|
||
|
ia64_regmap,
|
||
|
};
|
||
|
|
||
|
static struct regs_info myregs_info =
|
||
|
{
|
||
|
NULL, /* regset_bitmap */
|
||
|
&ia64_usrregs_info
|
||
|
};
|
||
|
|
||
|
const regs_info *
|
||
|
ia64_target::get_regs_info ()
|
||
|
{
|
||
|
return &myregs_info;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ia64_target::low_arch_setup ()
|
||
|
{
|
||
|
current_process ()->tdesc = tdesc_ia64;
|
||
|
}
|
||
|
|
||
|
/* The linux target ops object. */
|
||
|
|
||
|
linux_process_target *the_linux_target = &the_ia64_target;
|
||
|
|
||
|
void
|
||
|
initialize_low_arch (void)
|
||
|
{
|
||
|
init_registers_ia64 ();
|
||
|
}
|