2005-01-26 Orjan Friberg <orjanf@axis.com>
* cris-tdep.c (enum cris_num_regs, enum cris_regnums) (cris_sigtramp_frame_unwind_cache, cris_register_size): Update for CRISv32. (crisv32_single_step_through_delay, cris_can_use_hardware_watchpoint) (cris_region_ok_for_watchpoint, cris_stopped_data_address) (crisv32_cannot_fetch_register, crisv32_cannot_store_register) (crisv32_register_type, cris_special_register_name) (crisv32_register_name): New functions. (cris_spec_reg_applicable): Recognize more versions. (cris_register_name): Update with call to cris_special_register_name. (find_cris_op): Filter out CRISv32 instructions. Tweaked comment and warning when unable to find step target. (CRISV10_ELF_NGREG, CRISV32_ELF_NGREG, crisv32_elf_gregset_t): Define. (supply_gregset): Add struct gdbarch_tdep. Set pseudo-PC register for CRISv32. (fetch_core_registers): Update for CRISv32. (cris_gdbarch_init): Set pc_regnum, register_type, num_regs, register_name, cannot_store_register, cannot_fetch_register, have_nonsteppable_watchpoint, single_step_through_delay for CRISv32.
This commit is contained in:
parent
a7479e7ea1
commit
c600d464c0
2 changed files with 401 additions and 65 deletions
|
@ -1,3 +1,25 @@
|
||||||
|
2005-01-26 Orjan Friberg <orjanf@axis.com>
|
||||||
|
|
||||||
|
* cris-tdep.c (enum cris_num_regs, enum cris_regnums)
|
||||||
|
(cris_sigtramp_frame_unwind_cache, cris_register_size): Update for
|
||||||
|
CRISv32.
|
||||||
|
(crisv32_single_step_through_delay, cris_can_use_hardware_watchpoint)
|
||||||
|
(cris_region_ok_for_watchpoint, cris_stopped_data_address)
|
||||||
|
(crisv32_cannot_fetch_register, crisv32_cannot_store_register)
|
||||||
|
(crisv32_register_type, cris_special_register_name)
|
||||||
|
(crisv32_register_name): New functions.
|
||||||
|
(cris_spec_reg_applicable): Recognize more versions.
|
||||||
|
(cris_register_name): Update with call to cris_special_register_name.
|
||||||
|
(find_cris_op): Filter out CRISv32 instructions. Tweaked comment and
|
||||||
|
warning when unable to find step target.
|
||||||
|
(CRISV10_ELF_NGREG, CRISV32_ELF_NGREG, crisv32_elf_gregset_t): Define.
|
||||||
|
(supply_gregset): Add struct gdbarch_tdep. Set pseudo-PC register for
|
||||||
|
CRISv32.
|
||||||
|
(fetch_core_registers): Update for CRISv32.
|
||||||
|
(cris_gdbarch_init): Set pc_regnum, register_type, num_regs,
|
||||||
|
register_name, cannot_store_register, cannot_fetch_register,
|
||||||
|
have_nonsteppable_watchpoint, single_step_through_delay for CRISv32.
|
||||||
|
|
||||||
2005-01-26 Nick Roberts <nickrob@snap.net.nz>
|
2005-01-26 Nick Roberts <nickrob@snap.net.nz>
|
||||||
|
|
||||||
* interps.c (interpreter_exec_cmd): Use condition,
|
* interps.c (interpreter_exec_cmd): Use condition,
|
||||||
|
|
442
gdb/cris-tdep.c
442
gdb/cris-tdep.c
|
@ -56,7 +56,12 @@ enum cris_num_regs
|
||||||
NUM_GENREGS = 16,
|
NUM_GENREGS = 16,
|
||||||
|
|
||||||
/* There are 16 special registers. */
|
/* There are 16 special registers. */
|
||||||
NUM_SPECREGS = 16
|
NUM_SPECREGS = 16,
|
||||||
|
|
||||||
|
/* CRISv32 has a pseudo PC register, not noted here. */
|
||||||
|
|
||||||
|
/* CRISv32 has 16 support registers. */
|
||||||
|
NUM_SUPPREGS = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Register numbers of various important registers.
|
/* Register numbers of various important registers.
|
||||||
|
@ -75,8 +80,9 @@ enum cris_num_regs
|
||||||
enum cris_regnums
|
enum cris_regnums
|
||||||
{
|
{
|
||||||
/* Enums with respect to the general registers, valid for all
|
/* Enums with respect to the general registers, valid for all
|
||||||
CRIS versions. */
|
CRIS versions. The frame pointer is always in R8. */
|
||||||
CRIS_FP_REGNUM = 8,
|
CRIS_FP_REGNUM = 8,
|
||||||
|
/* ABI related registers. */
|
||||||
STR_REGNUM = 9,
|
STR_REGNUM = 9,
|
||||||
RET_REGNUM = 10,
|
RET_REGNUM = 10,
|
||||||
ARG1_REGNUM = 10,
|
ARG1_REGNUM = 10,
|
||||||
|
@ -84,23 +90,56 @@ enum cris_regnums
|
||||||
ARG3_REGNUM = 12,
|
ARG3_REGNUM = 12,
|
||||||
ARG4_REGNUM = 13,
|
ARG4_REGNUM = 13,
|
||||||
|
|
||||||
/* Enums with respect to the special registers, some of which may not be
|
/* Registers which happen to be common. */
|
||||||
applicable to all CRIS versions. */
|
|
||||||
P0_REGNUM = 16,
|
|
||||||
VR_REGNUM = 17,
|
VR_REGNUM = 17,
|
||||||
P2_REGNUM = 18,
|
MOF_REGNUM = 23,
|
||||||
P3_REGNUM = 19,
|
SRP_REGNUM = 27,
|
||||||
|
|
||||||
|
/* CRISv10 et. al. specific registers. */
|
||||||
|
P0_REGNUM = 16,
|
||||||
P4_REGNUM = 20,
|
P4_REGNUM = 20,
|
||||||
CCR_REGNUM = 21,
|
CCR_REGNUM = 21,
|
||||||
MOF_REGNUM = 23,
|
|
||||||
P8_REGNUM = 24,
|
P8_REGNUM = 24,
|
||||||
IBR_REGNUM = 25,
|
IBR_REGNUM = 25,
|
||||||
IRP_REGNUM = 26,
|
IRP_REGNUM = 26,
|
||||||
SRP_REGNUM = 27,
|
|
||||||
BAR_REGNUM = 28,
|
BAR_REGNUM = 28,
|
||||||
DCCR_REGNUM = 29,
|
DCCR_REGNUM = 29,
|
||||||
BRP_REGNUM = 30,
|
BRP_REGNUM = 30,
|
||||||
USP_REGNUM = 31
|
USP_REGNUM = 31,
|
||||||
|
|
||||||
|
/* CRISv32 specific registers. */
|
||||||
|
ACR_REGNUM = 15,
|
||||||
|
BZ_REGNUM = 16,
|
||||||
|
PID_REGNUM = 18,
|
||||||
|
SRS_REGNUM = 19,
|
||||||
|
WZ_REGNUM = 20,
|
||||||
|
EXS_REGNUM = 21,
|
||||||
|
EDA_REGNUM = 22,
|
||||||
|
DZ_REGNUM = 24,
|
||||||
|
EBP_REGNUM = 25,
|
||||||
|
ERP_REGNUM = 26,
|
||||||
|
NRP_REGNUM = 28,
|
||||||
|
CCS_REGNUM = 29,
|
||||||
|
CRISV32USP_REGNUM = 30, /* Shares name but not number with CRISv10. */
|
||||||
|
SPC_REGNUM = 31,
|
||||||
|
CRISV32PC_REGNUM = 32, /* Shares name but not number with CRISv10. */
|
||||||
|
|
||||||
|
S0_REGNUM = 33,
|
||||||
|
S1_REGNUM = 34,
|
||||||
|
S2_REGNUM = 35,
|
||||||
|
S3_REGNUM = 36,
|
||||||
|
S4_REGNUM = 37,
|
||||||
|
S5_REGNUM = 38,
|
||||||
|
S6_REGNUM = 39,
|
||||||
|
S7_REGNUM = 40,
|
||||||
|
S8_REGNUM = 41,
|
||||||
|
S9_REGNUM = 42,
|
||||||
|
S10_REGNUM = 43,
|
||||||
|
S11_REGNUM = 44,
|
||||||
|
S12_REGNUM = 45,
|
||||||
|
S13_REGNUM = 46,
|
||||||
|
S14_REGNUM = 47,
|
||||||
|
S15_REGNUM = 48,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct cris_spec_reg cris_spec_regs[];
|
extern const struct cris_spec_reg cris_spec_regs[];
|
||||||
|
@ -311,20 +350,52 @@ cris_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
|
||||||
unsigned long usp;
|
unsigned long usp;
|
||||||
}; */
|
}; */
|
||||||
|
|
||||||
/* R0 to R13 are stored in reverse order at offset (2 * 4) in
|
if (tdep->cris_version == 10)
|
||||||
struct pt_regs. */
|
{
|
||||||
for (i = 0; i <= 13; i++)
|
/* R0 to R13 are stored in reverse order at offset (2 * 4) in
|
||||||
info->saved_regs[i].addr = addr + ((15 - i) * 4);
|
struct pt_regs. */
|
||||||
|
for (i = 0; i <= 13; i++)
|
||||||
|
info->saved_regs[i].addr = addr + ((15 - i) * 4);
|
||||||
|
|
||||||
info->saved_regs[MOF_REGNUM].addr = addr + (16 * 4);
|
info->saved_regs[MOF_REGNUM].addr = addr + (16 * 4);
|
||||||
info->saved_regs[DCCR_REGNUM].addr = addr + (17 * 4);
|
info->saved_regs[DCCR_REGNUM].addr = addr + (17 * 4);
|
||||||
info->saved_regs[SRP_REGNUM].addr = addr + (18 * 4);
|
info->saved_regs[SRP_REGNUM].addr = addr + (18 * 4);
|
||||||
/* Note: IRP is off by 2 at this point. There's no point in correcting it
|
/* Note: IRP is off by 2 at this point. There's no point in correcting
|
||||||
though since that will mean that the backtrace will show a PC different
|
it though since that will mean that the backtrace will show a PC
|
||||||
from what is shown when stopped. */
|
different from what is shown when stopped. */
|
||||||
info->saved_regs[IRP_REGNUM].addr = addr + (19 * 4);
|
info->saved_regs[IRP_REGNUM].addr = addr + (19 * 4);
|
||||||
info->saved_regs[PC_REGNUM] = info->saved_regs[IRP_REGNUM];
|
info->saved_regs[PC_REGNUM] = info->saved_regs[IRP_REGNUM];
|
||||||
info->saved_regs[SP_REGNUM].addr = addr + (24 * 4);
|
info->saved_regs[SP_REGNUM].addr = addr + (24 * 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* CRISv32. */
|
||||||
|
/* R0 to R13 are stored in order at offset (1 * 4) in
|
||||||
|
struct pt_regs. */
|
||||||
|
for (i = 0; i <= 13; i++)
|
||||||
|
info->saved_regs[i].addr = addr + ((i + 1) * 4);
|
||||||
|
|
||||||
|
info->saved_regs[ACR_REGNUM].addr = addr + (15 * 4);
|
||||||
|
info->saved_regs[SRS_REGNUM].addr = addr + (16 * 4);
|
||||||
|
info->saved_regs[MOF_REGNUM].addr = addr + (17 * 4);
|
||||||
|
info->saved_regs[SPC_REGNUM].addr = addr + (18 * 4);
|
||||||
|
info->saved_regs[CCS_REGNUM].addr = addr + (19 * 4);
|
||||||
|
info->saved_regs[SRP_REGNUM].addr = addr + (20 * 4);
|
||||||
|
info->saved_regs[ERP_REGNUM].addr = addr + (21 * 4);
|
||||||
|
info->saved_regs[EXS_REGNUM].addr = addr + (22 * 4);
|
||||||
|
info->saved_regs[EDA_REGNUM].addr = addr + (23 * 4);
|
||||||
|
|
||||||
|
/* FIXME: If ERP is in a delay slot at this point then the PC will
|
||||||
|
be wrong at this point. This problem manifests itself in the
|
||||||
|
sigaltstack.exp test case, which occasionally generates FAILs when
|
||||||
|
the signal is received while in a delay slot.
|
||||||
|
|
||||||
|
This could be solved by a couple of read_memory_unsigned_integer and a
|
||||||
|
trad_frame_set_value. */
|
||||||
|
info->saved_regs[PC_REGNUM] = info->saved_regs[ERP_REGNUM];
|
||||||
|
|
||||||
|
info->saved_regs[SP_REGNUM].addr = addr + (25 * 4);
|
||||||
|
}
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -375,7 +446,72 @@ cris_sigtramp_frame_sniffer (struct frame_info *next_frame)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
crisv32_single_step_through_delay (struct gdbarch *gdbarch,
|
||||||
|
struct frame_info *this_frame)
|
||||||
|
{
|
||||||
|
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||||
|
ULONGEST erp;
|
||||||
|
int ret = 0;
|
||||||
|
char buf[4];
|
||||||
|
|
||||||
|
frame_unwind_register (this_frame, ERP_REGNUM, buf);
|
||||||
|
erp = extract_unsigned_integer (buf, 4);
|
||||||
|
|
||||||
|
if (erp & 0x1)
|
||||||
|
{
|
||||||
|
/* In delay slot - check if there's a breakpoint at the preceding
|
||||||
|
instruction. */
|
||||||
|
if (breakpoint_here_p (erp & ~0x1))
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hardware watchpoint support. */
|
||||||
|
|
||||||
|
/* We support 6 hardware data watchpoints, but cannot trigger on execute
|
||||||
|
(any combination of read/write is fine). */
|
||||||
|
|
||||||
|
int
|
||||||
|
cris_can_use_hardware_watchpoint (int type, int count, int other)
|
||||||
|
{
|
||||||
|
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||||
|
|
||||||
|
/* No bookkeeping is done here; it is handled by the remote debug agent. */
|
||||||
|
|
||||||
|
if (tdep->cris_version != 32)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
/* CRISv32: Six data watchpoints, one for instructions. */
|
||||||
|
return (((type == bp_read_watchpoint || type == bp_access_watchpoint
|
||||||
|
|| type == bp_hardware_watchpoint) && count <= 6)
|
||||||
|
|| (type == bp_hardware_breakpoint && count <= 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The CRISv32 hardware data watchpoints work by specifying ranges,
|
||||||
|
which have no alignment or length restrictions. */
|
||||||
|
|
||||||
|
int
|
||||||
|
cris_region_ok_for_watchpoint (CORE_ADDR addr, int len)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the inferior has some watchpoint that triggered, return the
|
||||||
|
address associated with that watchpoint. Otherwise, return
|
||||||
|
zero. */
|
||||||
|
|
||||||
|
CORE_ADDR
|
||||||
|
cris_stopped_data_address (void)
|
||||||
|
{
|
||||||
|
CORE_ADDR eda;
|
||||||
|
eda = read_register (EDA_REGNUM);
|
||||||
|
return eda;
|
||||||
|
}
|
||||||
|
|
||||||
/* The instruction environment needed to find single-step breakpoints. */
|
/* The instruction environment needed to find single-step breakpoints. */
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
struct instruction_environment
|
struct instruction_environment
|
||||||
{
|
{
|
||||||
|
@ -1286,8 +1422,18 @@ cris_spec_reg_applicable (struct cris_spec_reg spec_reg)
|
||||||
return (version == 8 || version == 9);
|
return (version == 8 || version == 9);
|
||||||
case cris_ver_v8p:
|
case cris_ver_v8p:
|
||||||
return (version >= 8);
|
return (version >= 8);
|
||||||
|
case cris_ver_v0_10:
|
||||||
|
return (version >= 0 && version <= 10);
|
||||||
|
case cris_ver_v3_10:
|
||||||
|
return (version >= 3 && version <= 10);
|
||||||
|
case cris_ver_v8_10:
|
||||||
|
return (version >= 8 && version <= 10);
|
||||||
|
case cris_ver_v10:
|
||||||
|
return (version == 10);
|
||||||
case cris_ver_v10p:
|
case cris_ver_v10p:
|
||||||
return (version >= 10);
|
return (version >= 10);
|
||||||
|
case cris_ver_v32p:
|
||||||
|
return (version >= 32);
|
||||||
default:
|
default:
|
||||||
/* Invalid cris version. */
|
/* Invalid cris version. */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1300,6 +1446,7 @@ cris_spec_reg_applicable (struct cris_spec_reg spec_reg)
|
||||||
static int
|
static int
|
||||||
cris_register_size (int regno)
|
cris_register_size (int regno)
|
||||||
{
|
{
|
||||||
|
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||||
int i;
|
int i;
|
||||||
int spec_regno;
|
int spec_regno;
|
||||||
|
|
||||||
|
@ -1308,15 +1455,13 @@ cris_register_size (int regno)
|
||||||
/* General registers (R0 - R15) are 32 bits. */
|
/* General registers (R0 - R15) are 32 bits. */
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
else if (regno >= NUM_GENREGS && regno < NUM_REGS)
|
else if (regno >= NUM_GENREGS && regno < (NUM_GENREGS + NUM_SPECREGS))
|
||||||
{
|
{
|
||||||
/* Special register (R16 - R31). cris_spec_regs is zero-based.
|
/* Special register (R16 - R31). cris_spec_regs is zero-based.
|
||||||
Adjust regno accordingly. */
|
Adjust regno accordingly. */
|
||||||
spec_regno = regno - NUM_GENREGS;
|
spec_regno = regno - NUM_GENREGS;
|
||||||
|
|
||||||
/* The entries in cris_spec_regs are stored in register number order,
|
for (i = 0; cris_spec_regs[i].name != NULL; i++)
|
||||||
which means we can shortcut into the array when searching it. */
|
|
||||||
for (i = spec_regno; cris_spec_regs[i].name != NULL; i++)
|
|
||||||
{
|
{
|
||||||
if (cris_spec_regs[i].number == spec_regno
|
if (cris_spec_regs[i].number == spec_regno
|
||||||
&& cris_spec_reg_applicable (cris_spec_regs[i]))
|
&& cris_spec_reg_applicable (cris_spec_regs[i]))
|
||||||
|
@ -1326,11 +1471,15 @@ cris_register_size (int regno)
|
||||||
/* Special register not applicable to this CRIS version. */
|
/* Special register not applicable to this CRIS version. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else if (regno >= PC_REGNUM && regno < NUM_REGS)
|
||||||
{
|
{
|
||||||
/* Invalid register. */
|
/* This will apply to CRISv32 only where there are additional registers
|
||||||
return -1;
|
after the special registers (pseudo PC and support registers). */
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nonzero if regno should not be fetched from the target. This is the case
|
/* Nonzero if regno should not be fetched from the target. This is the case
|
||||||
|
@ -1373,6 +1522,46 @@ cris_cannot_store_register (int regno)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Nonzero if regno should not be fetched from the target. This is the case
|
||||||
|
for unimplemented (size 0) and non-existant registers. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
crisv32_cannot_fetch_register (int regno)
|
||||||
|
{
|
||||||
|
return ((regno < 0 || regno >= NUM_REGS)
|
||||||
|
|| (cris_register_size (regno) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nonzero if regno should not be written to the target, for various
|
||||||
|
reasons. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
crisv32_cannot_store_register (int regno)
|
||||||
|
{
|
||||||
|
/* There are three kinds of registers we refuse to write to.
|
||||||
|
1. Those that not implemented.
|
||||||
|
2. Those that are read-only (depends on the processor mode).
|
||||||
|
3. Those registers to which a write has no effect.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (regno < 0 || regno >= NUM_REGS || cris_register_size (regno) == 0)
|
||||||
|
/* Not implemented. */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
else if (regno == VR_REGNUM)
|
||||||
|
/* Read-only. */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
else if (regno == BZ_REGNUM || regno == WZ_REGNUM || regno == DZ_REGNUM)
|
||||||
|
/* Writing has no effect. */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Many special registers are read-only in user mode. Let the debug
|
||||||
|
agent decide whether they are writable. */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the GDB type (defined in gdbtypes.c) for the "standard" data type
|
/* Return the GDB type (defined in gdbtypes.c) for the "standard" data type
|
||||||
of data in register regno. */
|
of data in register regno. */
|
||||||
|
|
||||||
|
@ -1396,6 +1585,32 @@ cris_register_type (struct gdbarch *gdbarch, int regno)
|
||||||
return builtin_type_int0;
|
return builtin_type_int0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct type *
|
||||||
|
crisv32_register_type (struct gdbarch *gdbarch, int regno)
|
||||||
|
{
|
||||||
|
if (regno == PC_REGNUM)
|
||||||
|
return builtin_type_void_func_ptr;
|
||||||
|
else if (regno == SP_REGNUM || regno == CRIS_FP_REGNUM)
|
||||||
|
return builtin_type_void_data_ptr;
|
||||||
|
else if ((regno >= 0 && regno <= ACR_REGNUM)
|
||||||
|
|| (regno >= EXS_REGNUM && regno <= SPC_REGNUM)
|
||||||
|
|| (regno == PID_REGNUM)
|
||||||
|
|| (regno >= S0_REGNUM && regno <= S15_REGNUM))
|
||||||
|
/* Note: R8 and SP taken care of by previous clause. */
|
||||||
|
return builtin_type_uint32;
|
||||||
|
else if (regno == WZ_REGNUM)
|
||||||
|
return builtin_type_uint16;
|
||||||
|
else if (regno == BZ_REGNUM || regno == VR_REGNUM || regno == SRS_REGNUM)
|
||||||
|
return builtin_type_uint8;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invalid (unimplemented) register. Should not happen as there are
|
||||||
|
no unimplemented CRISv32 registers. */
|
||||||
|
warning ("crisv32_register_type: unknown regno %d", regno);
|
||||||
|
return builtin_type_int0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Stores a function return value of type type, where valbuf is the address
|
/* Stores a function return value of type type, where valbuf is the address
|
||||||
of the value to be stored. */
|
of the value to be stored. */
|
||||||
|
|
||||||
|
@ -1429,6 +1644,29 @@ cris_store_return_value (struct type *type, struct regcache *regcache,
|
||||||
/* Return the name of register regno as a string. Return NULL for an invalid or
|
/* Return the name of register regno as a string. Return NULL for an invalid or
|
||||||
unimplemented register. */
|
unimplemented register. */
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
cris_special_register_name (int regno)
|
||||||
|
{
|
||||||
|
int spec_regno;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Special register (R16 - R31). cris_spec_regs is zero-based.
|
||||||
|
Adjust regno accordingly. */
|
||||||
|
spec_regno = regno - NUM_GENREGS;
|
||||||
|
|
||||||
|
/* Assume nothing about the layout of the cris_spec_regs struct
|
||||||
|
when searching. */
|
||||||
|
for (i = 0; cris_spec_regs[i].name != NULL; i++)
|
||||||
|
{
|
||||||
|
if (cris_spec_regs[i].number == spec_regno
|
||||||
|
&& cris_spec_reg_applicable (cris_spec_regs[i]))
|
||||||
|
/* Go with the first applicable register. */
|
||||||
|
return cris_spec_regs[i].name;
|
||||||
|
}
|
||||||
|
/* Special register not applicable to this CRIS version. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
cris_register_name (int regno)
|
cris_register_name (int regno)
|
||||||
{
|
{
|
||||||
|
@ -1438,9 +1676,6 @@ cris_register_name (int regno)
|
||||||
"r8", "r9", "r10", "r11", \
|
"r8", "r9", "r10", "r11", \
|
||||||
"r12", "r13", "sp", "pc" };
|
"r12", "r13", "sp", "pc" };
|
||||||
|
|
||||||
int i;
|
|
||||||
int spec_regno;
|
|
||||||
|
|
||||||
if (regno >= 0 && regno < NUM_GENREGS)
|
if (regno >= 0 && regno < NUM_GENREGS)
|
||||||
{
|
{
|
||||||
/* General register. */
|
/* General register. */
|
||||||
|
@ -1448,22 +1683,49 @@ cris_register_name (int regno)
|
||||||
}
|
}
|
||||||
else if (regno >= NUM_GENREGS && regno < NUM_REGS)
|
else if (regno >= NUM_GENREGS && regno < NUM_REGS)
|
||||||
{
|
{
|
||||||
/* Special register (R16 - R31). cris_spec_regs is zero-based.
|
return cris_special_register_name (regno);
|
||||||
Adjust regno accordingly. */
|
}
|
||||||
spec_regno = regno - NUM_GENREGS;
|
else
|
||||||
|
{
|
||||||
/* The entries in cris_spec_regs are stored in register number order,
|
/* Invalid register. */
|
||||||
which means we can shortcut into the array when searching it. */
|
|
||||||
for (i = spec_regno; cris_spec_regs[i].name != NULL; i++)
|
|
||||||
{
|
|
||||||
if (cris_spec_regs[i].number == spec_regno
|
|
||||||
&& cris_spec_reg_applicable (cris_spec_regs[i]))
|
|
||||||
/* Go with the first applicable register. */
|
|
||||||
return cris_spec_regs[i].name;
|
|
||||||
}
|
|
||||||
/* Special register not applicable to this CRIS version. */
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
crisv32_register_name (int regno)
|
||||||
|
{
|
||||||
|
static char *crisv32_genreg_names[] =
|
||||||
|
{ "r0", "r1", "r2", "r3", \
|
||||||
|
"r4", "r5", "r6", "r7", \
|
||||||
|
"r8", "r9", "r10", "r11", \
|
||||||
|
"r12", "r13", "sp", "acr"
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *crisv32_sreg_names[] =
|
||||||
|
{ "s0", "s1", "s2", "s3", \
|
||||||
|
"s4", "s5", "s6", "s7", \
|
||||||
|
"s8", "s9", "s10", "s11", \
|
||||||
|
"s12", "s13", "s14", "s15"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (regno >= 0 && regno < NUM_GENREGS)
|
||||||
|
{
|
||||||
|
/* General register. */
|
||||||
|
return crisv32_genreg_names[regno];
|
||||||
|
}
|
||||||
|
else if (regno >= NUM_GENREGS && regno < (NUM_GENREGS + NUM_SPECREGS))
|
||||||
|
{
|
||||||
|
return cris_special_register_name (regno);
|
||||||
|
}
|
||||||
|
else if (regno == PC_REGNUM)
|
||||||
|
{
|
||||||
|
return "pc";
|
||||||
|
}
|
||||||
|
else if (regno >= S0_REGNUM && regno <= S15_REGNUM)
|
||||||
|
{
|
||||||
|
return crisv32_sreg_names[regno - S0_REGNUM];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Invalid register. */
|
/* Invalid register. */
|
||||||
|
@ -1685,7 +1947,9 @@ find_cris_op (unsigned short insn, inst_env_type *inst_env)
|
||||||
for (i = 0; cris_opcodes[i].name != NULL; i++)
|
for (i = 0; cris_opcodes[i].name != NULL; i++)
|
||||||
{
|
{
|
||||||
if (((cris_opcodes[i].match & insn) == cris_opcodes[i].match)
|
if (((cris_opcodes[i].match & insn) == cris_opcodes[i].match)
|
||||||
&& ((cris_opcodes[i].lose & insn) == 0))
|
&& ((cris_opcodes[i].lose & insn) == 0)
|
||||||
|
/* Only CRISv10 instructions, please. */
|
||||||
|
&& (cris_opcodes[i].applicable_version != cris_ver_v32p))
|
||||||
{
|
{
|
||||||
level_of_match = constraint (insn, cris_opcodes[i].args, inst_env);
|
level_of_match = constraint (insn, cris_opcodes[i].args, inst_env);
|
||||||
if (level_of_match >= 0)
|
if (level_of_match >= 0)
|
||||||
|
@ -1788,8 +2052,9 @@ cris_software_single_step (enum target_signal ignore, int insert_breakpoints)
|
||||||
int status = find_step_target (&inst_env);
|
int status = find_step_target (&inst_env);
|
||||||
if (status == -1)
|
if (status == -1)
|
||||||
{
|
{
|
||||||
/* Could not find a target. FIXME: Should do something. */
|
/* Could not find a target. Things are likely to go downhill
|
||||||
warning ("cris_software_single_step: unable to find step target");
|
from here. */
|
||||||
|
warning ("CRIS software single step could not find a step target.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3515,13 +3780,18 @@ cris_delayed_get_disassembler (bfd_vma addr, struct disassemble_info *info)
|
||||||
typedef unsigned long elf_greg_t;
|
typedef unsigned long elf_greg_t;
|
||||||
|
|
||||||
/* Same as user_regs_struct struct in <asm/user.h>. */
|
/* Same as user_regs_struct struct in <asm/user.h>. */
|
||||||
typedef elf_greg_t elf_gregset_t[35];
|
#define CRISV10_ELF_NGREG 35
|
||||||
|
typedef elf_greg_t elf_gregset_t[CRISV10_ELF_NGREG];
|
||||||
|
|
||||||
|
#define CRISV32_ELF_NGREG 32
|
||||||
|
typedef elf_greg_t crisv32_elf_gregset_t[CRISV32_ELF_NGREG];
|
||||||
|
|
||||||
/* Unpack an elf_gregset_t into GDB's register cache. */
|
/* Unpack an elf_gregset_t into GDB's register cache. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
supply_gregset (elf_gregset_t *gregsetp)
|
supply_gregset (elf_gregset_t *gregsetp)
|
||||||
{
|
{
|
||||||
|
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||||
int i;
|
int i;
|
||||||
elf_greg_t *regp = *gregsetp;
|
elf_greg_t *regp = *gregsetp;
|
||||||
static char zerobuf[4] = {0};
|
static char zerobuf[4] = {0};
|
||||||
|
@ -3532,6 +3802,18 @@ supply_gregset (elf_gregset_t *gregsetp)
|
||||||
{
|
{
|
||||||
regcache_raw_supply (current_regcache, i, (char *)®p[i]);
|
regcache_raw_supply (current_regcache, i, (char *)®p[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tdep->cris_version == 32)
|
||||||
|
{
|
||||||
|
/* Needed to set pseudo-register PC for CRISv32. */
|
||||||
|
/* FIXME: If ERP is in a delay slot at this point then the PC will
|
||||||
|
be wrong. Issue a warning to alert the user. */
|
||||||
|
regcache_raw_supply (current_regcache, PC_REGNUM,
|
||||||
|
(char *)®p[ERP_REGNUM]);
|
||||||
|
|
||||||
|
if (*(char *)®p[ERP_REGNUM] & 0x1)
|
||||||
|
fprintf_unfiltered (gdb_stderr, "Warning: PC in delay slot\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use a local version of this function to get the correct types for
|
/* Use a local version of this function to get the correct types for
|
||||||
|
@ -3546,7 +3828,8 @@ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
|
||||||
switch (which)
|
switch (which)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
if (core_reg_size != sizeof (gregset))
|
if (core_reg_size != sizeof (elf_gregset_t)
|
||||||
|
&& core_reg_size != sizeof (crisv32_elf_gregset_t))
|
||||||
{
|
{
|
||||||
warning ("wrong size gregset struct in core file");
|
warning ("wrong size gregset struct in core file");
|
||||||
}
|
}
|
||||||
|
@ -3706,6 +3989,10 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||||
/* Trust the user's CRIS version setting. */
|
/* Trust the user's CRIS version setting. */
|
||||||
cris_version = usr_cmd_cris_version;
|
cris_version = usr_cmd_cris_version;
|
||||||
}
|
}
|
||||||
|
else if (info.abfd && bfd_get_mach (info.abfd) == bfd_mach_cris_v32)
|
||||||
|
{
|
||||||
|
cris_version = 32;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Assume it's CRIS version 10. */
|
/* Assume it's CRIS version 10. */
|
||||||
|
@ -3755,18 +4042,16 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||||
cris_reg_struct_has_addr);
|
cris_reg_struct_has_addr);
|
||||||
set_gdbarch_deprecated_use_struct_convention (gdbarch, always_use_struct_convention);
|
set_gdbarch_deprecated_use_struct_convention (gdbarch, always_use_struct_convention);
|
||||||
|
|
||||||
/* There are 32 registers (some of which may not be implemented). */
|
|
||||||
set_gdbarch_num_regs (gdbarch, 32);
|
|
||||||
set_gdbarch_sp_regnum (gdbarch, 14);
|
set_gdbarch_sp_regnum (gdbarch, 14);
|
||||||
set_gdbarch_pc_regnum (gdbarch, 15);
|
|
||||||
set_gdbarch_register_name (gdbarch, cris_register_name);
|
/* Length of ordinary registers used in push_word and a few other
|
||||||
|
places. register_size() is the real way to know how big a
|
||||||
|
register is. */
|
||||||
|
|
||||||
set_gdbarch_double_bit (gdbarch, 64);
|
set_gdbarch_double_bit (gdbarch, 64);
|
||||||
/* The default definition of a long double is 2 * TARGET_DOUBLE_BIT,
|
/* The default definition of a long double is 2 * TARGET_DOUBLE_BIT,
|
||||||
which means we have to set this explicitly. */
|
which means we have to set this explicitly. */
|
||||||
set_gdbarch_long_double_bit (gdbarch, 64);
|
set_gdbarch_long_double_bit (gdbarch, 64);
|
||||||
set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register);
|
|
||||||
set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register);
|
|
||||||
|
|
||||||
/* The total amount of space needed to store (in an array called registers)
|
/* The total amount of space needed to store (in an array called registers)
|
||||||
GDB's copy of the machine's register state. Note: We can not use
|
GDB's copy of the machine's register state. Note: We can not use
|
||||||
|
@ -3789,20 +4074,49 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||||
case 11:
|
case 11:
|
||||||
/* CRIS v10 and v11, a.k.a. ETRAX 100LX. In addition to ETRAX 100,
|
/* CRIS v10 and v11, a.k.a. ETRAX 100LX. In addition to ETRAX 100,
|
||||||
P7 (32 bits), and P15 (32 bits) have been implemented. */
|
P7 (32 bits), and P15 (32 bits) have been implemented. */
|
||||||
|
set_gdbarch_pc_regnum (gdbarch, 15);
|
||||||
|
set_gdbarch_register_type (gdbarch, cris_register_type);
|
||||||
|
/* There are 32 registers (some of which may not be implemented). */
|
||||||
|
set_gdbarch_num_regs (gdbarch, 32);
|
||||||
|
set_gdbarch_register_name (gdbarch, cris_register_name);
|
||||||
|
set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register);
|
||||||
|
set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register);
|
||||||
|
|
||||||
|
set_gdbarch_software_single_step (gdbarch, cris_software_single_step);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 32:
|
||||||
|
/* CRIS v32. General registers R0 - R15 (32 bits), special registers
|
||||||
|
P0 - P15 (32 bits) except P0, P1, P3 (8 bits) and P4 (16 bits)
|
||||||
|
and pseudo-register PC (32 bits). */
|
||||||
|
set_gdbarch_pc_regnum (gdbarch, 32);
|
||||||
|
set_gdbarch_register_type (gdbarch, crisv32_register_type);
|
||||||
|
/* 32 registers + pseudo-register PC + 16 support registers. */
|
||||||
|
set_gdbarch_num_regs (gdbarch, 32 + 1 + 16);
|
||||||
|
set_gdbarch_register_name (gdbarch, crisv32_register_name);
|
||||||
|
|
||||||
|
set_gdbarch_cannot_store_register
|
||||||
|
(gdbarch, crisv32_cannot_store_register);
|
||||||
|
set_gdbarch_cannot_fetch_register
|
||||||
|
(gdbarch, crisv32_cannot_fetch_register);
|
||||||
|
|
||||||
|
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
|
||||||
|
|
||||||
|
set_gdbarch_single_step_through_delay
|
||||||
|
(gdbarch, crisv32_single_step_through_delay);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown CRIS version");
|
internal_error (__FILE__, __LINE__,
|
||||||
|
"cris_gdbarch_init: unknown CRIS version");
|
||||||
}
|
}
|
||||||
|
|
||||||
set_gdbarch_register_type (gdbarch, cris_register_type);
|
/* Dummy frame functions (shared between CRISv10 and CRISv32 since they
|
||||||
|
have the same ABI). */
|
||||||
/* Dummy frame functions. */
|
|
||||||
set_gdbarch_push_dummy_code (gdbarch, cris_push_dummy_code);
|
set_gdbarch_push_dummy_code (gdbarch, cris_push_dummy_code);
|
||||||
set_gdbarch_push_dummy_call (gdbarch, cris_push_dummy_call);
|
set_gdbarch_push_dummy_call (gdbarch, cris_push_dummy_call);
|
||||||
set_gdbarch_frame_align (gdbarch, cris_frame_align);
|
set_gdbarch_frame_align (gdbarch, cris_frame_align);
|
||||||
|
|
||||||
set_gdbarch_software_single_step (gdbarch, cris_software_single_step);
|
|
||||||
set_gdbarch_skip_prologue (gdbarch, cris_skip_prologue);
|
set_gdbarch_skip_prologue (gdbarch, cris_skip_prologue);
|
||||||
|
|
||||||
/* The stack grows downward. */
|
/* The stack grows downward. */
|
||||||
|
|
Loading…
Add table
Reference in a new issue