2004-10-11 Orjan Friberg <orjanf@axis.com>

* cris-tdep.c (cris_sigtramp_start, cris_rt_sigtramp_start)
	(cris_sigcontext_addr, cris_sigtramp_frame_unwind_cache)
	(cris_sigtramp_frame_this_id, cris_sigtramp_frame_prev_register)
	(cris_sigtramp_frame_sniffer): New functions.
	(cris_gdbarch_init): Hook in signal trampoline unwinder.
	(cris_dwarf2_reg_to_regnum, cris_dwarf2_frame_init_reg): New functions.
	(cris_gdbarch_init): Hook in Dwarf-2 unwinder.
	(struct gdbarch_tdep, set_cris_dwarf2_cfi, cris_dump_tdep)
	(cris_gdbarch_init, _initialize_cris_tdep): Add CRIS Dwarf-2 CFI usage
	command.
	(cris_version_update): Remove, replace with ...
	(set_cris_version): New function.
	(struct gdbarch_tdep, cris_mode, cris_mode_update)
	(cris_cannot_store_register, cris_dump_tdep, cris_gdbarch_init)
	(_initialize_cris_tdep): Remove CRIS mode command.
	(cris_fpless_backtrace, _initialize_cris_tdep): Remove CRIS command for
	framepointer-less backtrace.
	(cris_scan_prologue): Fix prologue scanning limit.
	(cris_register_type): Update to reflect actual registers.
	(cris_register_bytes_ok) Remove.
	(cris_gdbarch_init): Remove support for CRIS v8 and v9. Remove
	set_gdbarch_deprecated_register_size,
	set_gdbarch_deprecated_register_byte, set_gdbarch_register_bytes_ok.
This commit is contained in:
Orjan Friberg
2004-10-11 15:02:20 +00:00
parent 563f4125b7
commit a5f6c8f5a8
2 changed files with 376 additions and 373 deletions

View File

@ -1,3 +1,29 @@
2004-10-11 Orjan Friberg <orjanf@axis.com>
* cris-tdep.c (cris_sigtramp_start, cris_rt_sigtramp_start)
(cris_sigcontext_addr, cris_sigtramp_frame_unwind_cache)
(cris_sigtramp_frame_this_id, cris_sigtramp_frame_prev_register)
(cris_sigtramp_frame_sniffer): New functions.
(cris_gdbarch_init): Hook in signal trampoline unwinder.
(cris_dwarf2_reg_to_regnum, cris_dwarf2_frame_init_reg): New functions.
(cris_gdbarch_init): Hook in Dwarf-2 unwinder.
(struct gdbarch_tdep, set_cris_dwarf2_cfi, cris_dump_tdep)
(cris_gdbarch_init, _initialize_cris_tdep): Add CRIS Dwarf-2 CFI usage
command.
(cris_version_update): Remove, replace with ...
(set_cris_version): New function.
(struct gdbarch_tdep, cris_mode, cris_mode_update)
(cris_cannot_store_register, cris_dump_tdep, cris_gdbarch_init)
(_initialize_cris_tdep): Remove CRIS mode command.
(cris_fpless_backtrace, _initialize_cris_tdep): Remove
cris-fpless-backtrace command.
(cris_scan_prologue): Fix prologue scanning limit.
(cris_register_type): Update to reflect actual registers.
(cris_register_bytes_ok) Remove.
(cris_gdbarch_init): Remove support for CRIS v8 and v9.
Remove set_gdbarch_deprecated_register_size,
set_gdbarch_deprecated_register_byte, set_gdbarch_register_bytes_ok.
2004-10-10 Andrew Cagney <cagney@gnu.org> 2004-10-10 Andrew Cagney <cagney@gnu.org>
* ada-lang.c (lim_warning): Add ATTR_FORMAT prototype and FIXME * ada-lang.c (lim_warning): Add ATTR_FORMAT prototype and FIXME

View File

@ -42,12 +42,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* To get entry_point_address. */ /* To get entry_point_address. */
#include "objfiles.h" #include "objfiles.h"
#include "solib.h" /* Support for shared libraries. */ #include "solib.h" /* Support for shared libraries. */
#include "solib-svr4.h" /* For struct link_map_offsets. */ #include "solib-svr4.h" /* For struct link_map_offsets. */
#include "gdb_string.h" #include "gdb_string.h"
#include "dis-asm.h" #include "dis-asm.h"
enum cris_num_regs enum cris_num_regs
{ {
/* There are no floating point registers. Used in gdbserver low-linux.c. */ /* There are no floating point registers. Used in gdbserver low-linux.c. */
@ -108,32 +107,19 @@ extern const struct cris_spec_reg cris_spec_regs[];
/* CRIS version, set via the user command 'set cris-version'. Affects /* CRIS version, set via the user command 'set cris-version'. Affects
register names and sizes.*/ register names and sizes.*/
static int usr_cmd_cris_version; static unsigned int usr_cmd_cris_version;
/* Indicates whether to trust the above variable. */ /* Indicates whether to trust the above variable. */
static int usr_cmd_cris_version_valid = 0; static int usr_cmd_cris_version_valid = 0;
/* CRIS mode, set via the user command 'set cris-mode'. Affects availability /* Whether to make use of Dwarf-2 CFI (default on). */
of some registers. */ static int usr_cmd_cris_dwarf2_cfi = 1;
static const char *usr_cmd_cris_mode;
/* Indicates whether to trust the above variable. */
static int usr_cmd_cris_mode_valid = 0;
static const char CRIS_MODE_USER[] = "CRIS_MODE_USER";
static const char CRIS_MODE_SUPERVISOR[] = "CRIS_MODE_SUPERVISOR";
static const char *cris_mode_enums[] =
{
CRIS_MODE_USER,
CRIS_MODE_SUPERVISOR,
0
};
/* CRIS architecture specific information. */ /* CRIS architecture specific information. */
struct gdbarch_tdep struct gdbarch_tdep
{ {
int cris_version; unsigned int cris_version;
const char *cris_mode; int cris_dwarf2_cfi;
}; };
/* Functions for accessing target dependent data. */ /* Functions for accessing target dependent data. */
@ -144,10 +130,121 @@ cris_version (void)
return (gdbarch_tdep (current_gdbarch)->cris_version); return (gdbarch_tdep (current_gdbarch)->cris_version);
} }
static const char * /* Sigtramp identification code copied from i386-linux-tdep.c. */
cris_mode (void)
#define SIGTRAMP_INSN0 0x9c5f /* movu.w 0xXX, $r9 */
#define SIGTRAMP_OFFSET0 0
#define SIGTRAMP_INSN1 0xe93d /* break 13 */
#define SIGTRAMP_OFFSET1 4
static const unsigned short sigtramp_code[] =
{ {
return (gdbarch_tdep (current_gdbarch)->cris_mode); SIGTRAMP_INSN0, 0x0077, /* movu.w $0x77, $r9 */
SIGTRAMP_INSN1 /* break 13 */
};
#define SIGTRAMP_LEN (sizeof sigtramp_code)
/* Note: same length as normal sigtramp code. */
static const unsigned short rt_sigtramp_code[] =
{
SIGTRAMP_INSN0, 0x00ad, /* movu.w $0xad, $r9 */
SIGTRAMP_INSN1 /* break 13 */
};
/* If PC is in a sigtramp routine, return the address of the start of
the routine. Otherwise, return 0. */
static CORE_ADDR
cris_sigtramp_start (struct frame_info *next_frame)
{
CORE_ADDR pc = frame_pc_unwind (next_frame);
unsigned short buf[SIGTRAMP_LEN];
if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
return 0;
if (buf[0] != SIGTRAMP_INSN0)
{
if (buf[0] != SIGTRAMP_INSN1)
return 0;
pc -= SIGTRAMP_OFFSET1;
if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
return 0;
}
if (memcmp (buf, sigtramp_code, SIGTRAMP_LEN) != 0)
return 0;
return pc;
}
/* If PC is in a RT sigtramp routine, return the address of the start of
the routine. Otherwise, return 0. */
static CORE_ADDR
cris_rt_sigtramp_start (struct frame_info *next_frame)
{
CORE_ADDR pc = frame_pc_unwind (next_frame);
unsigned short buf[SIGTRAMP_LEN];
if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
return 0;
if (buf[0] != SIGTRAMP_INSN0)
{
if (buf[0] != SIGTRAMP_INSN1)
return 0;
pc -= SIGTRAMP_OFFSET1;
if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
return 0;
}
if (memcmp (buf, rt_sigtramp_code, SIGTRAMP_LEN) != 0)
return 0;
return pc;
}
/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
routine, return the address of the associated sigcontext structure. */
static CORE_ADDR
cris_sigcontext_addr (struct frame_info *next_frame)
{
CORE_ADDR pc;
CORE_ADDR sp;
char buf[4];
frame_unwind_register (next_frame, SP_REGNUM, buf);
sp = extract_unsigned_integer (buf, 4);
/* Look for normal sigtramp frame first. */
pc = cris_sigtramp_start (next_frame);
if (pc)
{
/* struct signal_frame (arch/cris/kernel/signal.c) contains
struct sigcontext as its first member, meaning the SP points to
it already. */
return sp;
}
pc = cris_rt_sigtramp_start (next_frame);
if (pc)
{
/* struct rt_signal_frame (arch/cris/kernel/signal.c) contains
a struct ucontext, which in turn contains a struct sigcontext.
Magic digging:
4 + 4 + 128 to struct ucontext, then
4 + 4 + 12 to struct sigcontext. */
return (sp + 156);
}
error ("Couldn't recognize signal trampoline.");
return 0;
} }
struct cris_unwind_cache struct cris_unwind_cache
@ -173,6 +270,111 @@ struct cris_unwind_cache
struct trad_frame_saved_reg *saved_regs; struct trad_frame_saved_reg *saved_regs;
}; };
static struct cris_unwind_cache *
cris_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
void **this_cache)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
struct cris_unwind_cache *info;
CORE_ADDR pc;
CORE_ADDR sp;
CORE_ADDR addr;
char buf[4];
int i;
if ((*this_cache))
return (*this_cache);
info = FRAME_OBSTACK_ZALLOC (struct cris_unwind_cache);
(*this_cache) = info;
info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
/* Zero all fields. */
info->prev_sp = 0;
info->base = 0;
info->size = 0;
info->sp_offset = 0;
info->r8_offset = 0;
info->uses_frame = 0;
info->return_pc = 0;
info->leaf_function = 0;
frame_unwind_register (next_frame, SP_REGNUM, buf);
info->base = extract_unsigned_integer (buf, 4);
addr = cris_sigcontext_addr (next_frame);
/* Layout of the sigcontext struct:
struct sigcontext {
struct pt_regs regs;
unsigned long oldmask;
unsigned long usp;
}; */
/* R0 to R13 are stored in reverse order at offset (2 * 4) in
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[DCCR_REGNUM].addr = addr + (17 * 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
though since that will mean that the backtrace will show a PC different
from what is shown when stopped. */
info->saved_regs[IRP_REGNUM].addr = addr + (19 * 4);
info->saved_regs[PC_REGNUM] = info->saved_regs[IRP_REGNUM];
info->saved_regs[SP_REGNUM].addr = addr + (24 * 4);
return info;
}
static void
cris_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache,
struct frame_id *this_id)
{
struct cris_unwind_cache *cache =
cris_sigtramp_frame_unwind_cache (next_frame, this_cache);
(*this_id) = frame_id_build (cache->base, frame_pc_unwind (next_frame));
}
/* Forward declaration. */
static void cris_frame_prev_register (struct frame_info *next_frame,
void **this_prologue_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, void *bufferp);
static void
cris_sigtramp_frame_prev_register (struct frame_info *next_frame,
void **this_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, void *valuep)
{
/* Make sure we've initialized the cache. */
cris_sigtramp_frame_unwind_cache (next_frame, this_cache);
cris_frame_prev_register (next_frame, this_cache, regnum,
optimizedp, lvalp, addrp, realnump, valuep);
}
static const struct frame_unwind cris_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
cris_sigtramp_frame_this_id,
cris_sigtramp_frame_prev_register
};
static const struct frame_unwind *
cris_sigtramp_frame_sniffer (struct frame_info *next_frame)
{
if (cris_sigtramp_start (next_frame)
|| cris_rt_sigtramp_start (next_frame))
return &cris_sigtramp_frame_unwind;
return NULL;
}
/* 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
@ -345,11 +547,11 @@ static struct gdbarch *cris_gdbarch_init (struct gdbarch_info,
static void cris_dump_tdep (struct gdbarch *, struct ui_file *); static void cris_dump_tdep (struct gdbarch *, struct ui_file *);
static void cris_version_update (char *ignore_args, int from_tty, static void set_cris_version (char *ignore_args, int from_tty,
struct cmd_list_element *c); struct cmd_list_element *c);
static void cris_mode_update (char *ignore_args, int from_tty, static void set_cris_dwarf2_cfi (char *ignore_args, int from_tty,
struct cmd_list_element *c); struct cmd_list_element *c);
static CORE_ADDR cris_scan_prologue (CORE_ADDR pc, static CORE_ADDR cris_scan_prologue (CORE_ADDR pc,
struct frame_info *next_frame, struct frame_info *next_frame,
@ -362,9 +564,8 @@ static CORE_ADDR cris_unwind_sp (struct gdbarch *gdbarch,
struct frame_info *next_frame); struct frame_info *next_frame);
/* When arguments must be pushed onto the stack, they go on in reverse /* When arguments must be pushed onto the stack, they go on in reverse
order. The below implements a FILO (stack) to do this. */ order. The below implements a FILO (stack) to do this.
Copied from d10v-tdep.c. */
/* Borrowed from d10v-tdep.c. */
struct stack_item struct stack_item
{ {
@ -399,7 +600,7 @@ pop_stack_item (struct stack_item *si)
the saved registers of frame described by FRAME_INFO. This the saved registers of frame described by FRAME_INFO. This
includes special registers such as pc and fp saved in special ways includes special registers such as pc and fp saved in special ways
in the stack frame. sp is even more special: the address we return in the stack frame. sp is even more special: the address we return
for it IS the sp for the next frame. */ for it IS the sp for the next frame. */
struct cris_unwind_cache * struct cris_unwind_cache *
cris_frame_unwind_cache (struct frame_info *next_frame, cris_frame_unwind_cache (struct frame_info *next_frame,
@ -531,7 +732,7 @@ cris_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct stack_item *si = NULL; struct stack_item *si = NULL;
/* Push the return address. */ /* Push the return address. */
regcache_cooked_write_unsigned (regcache, SRP_REGNUM, bp_addr); regcache_cooked_write_unsigned (regcache, SRP_REGNUM, bp_addr);
/* Are we returning a value using a structure return or a normal value /* Are we returning a value using a structure return or a normal value
@ -767,7 +968,7 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame,
limit = next_frame ? frame_pc_unwind (next_frame) : pc + 64; limit = next_frame ? frame_pc_unwind (next_frame) : pc + 64;
/* Find the prologue instructions. */ /* Find the prologue instructions. */
while (pc < limit) while (pc > 0 && pc < limit)
{ {
insn = read_memory_unsigned_integer (pc, 2); insn = read_memory_unsigned_integer (pc, 2);
pc += 2; pc += 2;
@ -1169,13 +1370,8 @@ cris_cannot_store_register (int regno)
/* Writing has no effect. */ /* Writing has no effect. */
return 1; return 1;
else if (cris_mode () == CRIS_MODE_USER) /* IBR, BAR, BRP and IRP are read-only in user mode. Let the debug
{ agent decide whether they are writable. */
if (regno == IBR_REGNUM || regno == BAR_REGNUM || regno == BRP_REGNUM
|| regno == IRP_REGNUM)
/* Read-only in user mode. */
return 1;
}
return 0; return 0;
} }
@ -1202,7 +1398,7 @@ cris_register_offset (int regno)
} }
else else
{ {
/* Invalid register. */ /* Invalid register. */
return -1; return -1;
} }
} }
@ -1213,33 +1409,21 @@ cris_register_offset (int regno)
static struct type * static struct type *
cris_register_type (struct gdbarch *gdbarch, int regno) cris_register_type (struct gdbarch *gdbarch, int regno)
{ {
if (regno == SP_REGNUM || regno == PC_REGNUM if (regno == PC_REGNUM)
|| (regno > P8_REGNUM && regno < USP_REGNUM)) return builtin_type_void_func_ptr;
{ else if (regno == SP_REGNUM || regno == CRIS_FP_REGNUM)
/* SP, PC, IBR, IRP, SRP, BAR, DCCR, BRP */ return builtin_type_void_data_ptr;
return lookup_pointer_type (builtin_type_void); else if ((regno >= 0 && regno < SP_REGNUM)
} || (regno >= MOF_REGNUM && regno <= USP_REGNUM))
else if (regno == P8_REGNUM || regno == USP_REGNUM /* Note: R8 taken care of previous clause. */
|| (regno >= 0 && regno < SP_REGNUM)) return builtin_type_uint32;
{ else if (regno >= P4_REGNUM && regno <= CCR_REGNUM)
/* R0 - R13, P8, P15 */ return builtin_type_uint16;
return builtin_type_unsigned_long; else if (regno >= P0_REGNUM && regno <= VR_REGNUM)
} return builtin_type_uint8;
else if (regno > P3_REGNUM && regno < P8_REGNUM)
{
/* P4, CCR, DCR0, DCR1 */
return builtin_type_unsigned_short;
}
else if (regno > PC_REGNUM && regno < P4_REGNUM)
{
/* P0, P1, P2, P3 */
return builtin_type_unsigned_char;
}
else else
{ /* Invalid (unimplemented) register. */
/* Invalid register. */ return builtin_type_int0;
return builtin_type_void;
}
} }
/* 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
@ -1317,10 +1501,49 @@ cris_register_name (int regno)
} }
} }
/* Convert DWARF register number REG to the appropriate register
number used by GDB. */
static int static int
cris_register_bytes_ok (long bytes) cris_dwarf2_reg_to_regnum (int reg)
{ {
return (bytes == deprecated_register_bytes ()); /* We need to re-map a couple of registers (SRP is 16 in Dwarf-2 register
numbering, MOF is 18).
Adapted from gcc/config/cris/cris.h. */
static int cris_dwarf_regmap[] = {
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15,
27, -1, -1, -1,
-1, -1, -1, 23,
-1, -1, -1, 27,
-1, -1, -1, -1
};
int regnum = -1;
if (reg >= 0 && reg < ARRAY_SIZE (cris_dwarf_regmap))
regnum = cris_dwarf_regmap[reg];
if (regnum == -1)
warning ("Unmapped DWARF Register #%d encountered\n", reg);
return regnum;
}
/* DWARF-2 frame support. */
static void
cris_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
struct dwarf2_frame_state_reg *reg)
{
/* The return address column. */
if (regnum == PC_REGNUM)
reg->how = DWARF2_FRAME_REG_RA;
/* The call frame address. */
else if (regnum == SP_REGNUM)
reg->how = DWARF2_FRAME_REG_CFA;
} }
/* Extract from an array regbuf containing the raw register state a function /* Extract from an array regbuf containing the raw register state a function
@ -1596,6 +1819,7 @@ cris_software_single_step (enum target_signal ignore, int insert_breakpoints)
if (status == -1) if (status == -1)
{ {
/* Could not find a target. FIXME: Should do something. */ /* Could not find a target. FIXME: Should do something. */
warning ("cris_software_single_step: unable to find step target");
} }
else else
{ {
@ -3312,7 +3536,7 @@ cris_delayed_get_disassembler (bfd_vma addr, struct disassemble_info *info)
disassembler, even when there is no BFD. Does something like disassembler, even when there is no BFD. Does something like
"gdb; target remote; disassmeble *0x123" work? */ "gdb; target remote; disassmeble *0x123" work? */
gdb_assert (exec_bfd != NULL); gdb_assert (exec_bfd != NULL);
print_insn = cris_get_disassembler (exec_bfd); print_insn = cris_get_disassembler (exec_bfd);
gdb_assert (print_insn != NULL); gdb_assert (print_insn != NULL);
return print_insn (addr, info); return print_insn (addr, info);
} }
@ -3423,230 +3647,37 @@ cris_linux_svr4_fetch_link_map_offsets (void)
return lmp; return lmp;
} }
static void
cris_fpless_backtrace (char *noargs, int from_tty)
{
/* Points at the instruction after the jsr (except when in innermost frame
where it points at the original pc). */
CORE_ADDR pc = 0;
/* Temporary variable, used for parsing from the start of the function that
the pc is in, up to the pc. */
CORE_ADDR tmp_pc = 0;
CORE_ADDR sp = 0;
/* Information about current frame. */
struct symtab_and_line sal;
char* func_name;
/* Present instruction. */
unsigned short insn;
/* Next instruction, lookahead. */
unsigned short insn_next;
/* This is to store the offset between sp at start of function and until we
reach push srp (if any). */
int sp_add_later = 0;
int push_srp_found = 0;
int val = 0;
/* Frame counter. */
int frame = 0;
/* For the innermost frame, we want to look at srp in case it's a leaf
function (since there's no push srp in that case). */
int innermost_frame = 1;
deprecated_read_register_gen (PC_REGNUM, (char *) &pc);
deprecated_read_register_gen (SP_REGNUM, (char *) &sp);
/* We make an explicit return when we can't find an outer frame. */
while (1)
{
/* Get file name and line number. */
sal = find_pc_line (pc, 0);
/* Get function name. */
find_pc_partial_function (pc, &func_name, (CORE_ADDR *) NULL,
(CORE_ADDR *) NULL);
/* Print information about current frame. */
printf_unfiltered ("#%i 0x%08lx in %s", frame++, pc, func_name);
if (sal.symtab)
{
printf_unfiltered (" at %s:%i", sal.symtab->filename, sal.line);
}
printf_unfiltered ("\n");
/* Get the start address of this function. */
tmp_pc = get_pc_function_start (pc);
/* Mini parser, only meant to find push sp and sub ...,sp from the start
of the function, up to the pc. */
while (tmp_pc < pc)
{
insn = read_memory_unsigned_integer (tmp_pc, sizeof (short));
tmp_pc += sizeof (short);
if (insn == 0xE1FC)
{
/* push <reg> 32 bit instruction */
insn_next = read_memory_unsigned_integer (tmp_pc,
sizeof (short));
tmp_pc += sizeof (short);
/* Recognize srp. */
if (insn_next == 0xBE7E)
{
/* For subsequent (not this one though) push or sub which
affects sp, adjust sp immediately. */
push_srp_found = 1;
/* Note: this will break if we ever encounter a
push vr (1 byte) or push ccr (2 bytes). */
sp_add_later += 4;
}
else
{
/* Some other register was pushed. */
if (push_srp_found)
{
sp += 4;
}
else
{
sp_add_later += 4;
}
}
}
else if (cris_get_operand2 (insn) == SP_REGNUM
&& cris_get_mode (insn) == 0x0000
&& cris_get_opcode (insn) == 0x000A)
{
/* subq <val>,sp */
val = cris_get_quick_value (insn);
if (push_srp_found)
{
sp += val;
}
else
{
sp_add_later += val;
}
}
else if (cris_get_operand2 (insn) == SP_REGNUM
/* Autoincrement addressing mode. */
&& cris_get_mode (insn) == 0x0003
/* Opcode. */
&& ((insn) & 0x03E0) >> 5 == 0x0004)
{
/* subu <val>,sp */
val = get_data_from_address (&insn, tmp_pc);
if (push_srp_found)
{
sp += val;
}
else
{
sp_add_later += val;
}
}
else if (cris_get_operand2 (insn) == SP_REGNUM
&& ((insn & 0x0F00) >> 8) == 0x0001
&& (cris_get_signed_offset (insn) < 0))
{
/* Immediate byte offset addressing prefix word with sp as base
register. Used for CRIS v8 i.e. ETRAX 100 and newer if <val>
is between 64 and 128.
movem r<regsave>,[sp=sp-<val>] */
val = -cris_get_signed_offset (insn);
insn_next = read_memory_unsigned_integer (tmp_pc,
sizeof (short));
tmp_pc += sizeof (short);
if (cris_get_mode (insn_next) == PREFIX_ASSIGN_MODE
&& cris_get_opcode (insn_next) == 0x000F
&& cris_get_size (insn_next) == 0x0003
&& cris_get_operand1 (insn_next) == SP_REGNUM)
{
if (push_srp_found)
{
sp += val;
}
else
{
sp_add_later += val;
}
}
}
}
if (push_srp_found)
{
/* Reset flag. */
push_srp_found = 0;
/* sp should now point at where srp is stored on the stack. Update
the pc to the srp. */
pc = read_memory_unsigned_integer (sp, 4);
}
else if (innermost_frame)
{
/* We couldn't find a push srp in the prologue, so this must be
a leaf function, and thus we use the srp register directly.
This should happen at most once, for the innermost function. */
deprecated_read_register_gen (SRP_REGNUM, (char *) &pc);
}
else
{
/* Couldn't find an outer frame. */
return;
}
/* Reset flag. (In case the innermost frame wasn't a leaf, we don't
want to look at the srp register later either). */
innermost_frame = 0;
/* Now, add the offset for everything up to, and including push srp,
that was held back during the prologue parsing. */
sp += sp_add_later;
sp_add_later = 0;
}
}
extern initialize_file_ftype _initialize_cris_tdep; /* -Wmissing-prototypes */ extern initialize_file_ftype _initialize_cris_tdep; /* -Wmissing-prototypes */
void void
_initialize_cris_tdep (void) _initialize_cris_tdep (void)
{ {
static struct cmd_list_element *cris_set_cmdlist;
static struct cmd_list_element *cris_show_cmdlist;
struct cmd_list_element *c; struct cmd_list_element *c;
gdbarch_register (bfd_arch_cris, cris_gdbarch_init, cris_dump_tdep); gdbarch_register (bfd_arch_cris, cris_gdbarch_init, cris_dump_tdep);
/* CRIS-specific user-commands. */ /* CRIS-specific user-commands. */
c = add_set_cmd ("cris-version", class_support, var_integer, add_setshow_uinteger_cmd ("cris-version", class_support,
(char *) &usr_cmd_cris_version, &usr_cmd_cris_version,
"Set the current CRIS version.", &setlist); "Set the current CRIS version.",
set_cmd_sfunc (c, cris_version_update); "Show the current CRIS version.",
deprecated_add_show_from_set (c, &showlist); "Set if autodetection fails.",
"Current CRIS version is %s.",
set_cris_version, NULL,
&setlist, &showlist);
c = add_set_enum_cmd ("cris-mode", class_support, cris_mode_enums, add_setshow_boolean_cmd ("cris-dwarf2-cfi", class_support,
&usr_cmd_cris_mode, &usr_cmd_cris_dwarf2_cfi,
"Set the current CRIS mode.", &setlist); "Set the usage of Dwarf-2 CFI for CRIS.",
set_cmd_sfunc (c, cris_mode_update); "Show the usage of Dwarf-2 CFI for CRIS.",
deprecated_add_show_from_set (c, &showlist); "Set to \"off\" if using gcc-cris < R59.",
"Usage of Dwarf-2 CFI for CRIS is %d.",
set_cris_dwarf2_cfi, NULL,
&setlist, &showlist);
c = add_cmd ("cris-fpless-backtrace", class_support, cris_fpless_backtrace,
"Display call chain using the subroutine return pointer.\n"
"Note that this displays the address after the jump to the "
"subroutine.", &cmdlist);
deprecated_add_core_fns (&cris_elf_core_fns);
} }
/* Prints out all target specific values. */ /* Prints out all target specific values. */
@ -3659,65 +3690,37 @@ cris_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
{ {
fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_version = %i\n", fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_version = %i\n",
tdep->cris_version); tdep->cris_version);
fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_mode = %s\n", fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_dwarf2_cfi = %i\n",
tdep->cris_mode); tdep->cris_dwarf2_cfi);
} }
} }
static void static void
cris_version_update (char *ignore_args, int from_tty, set_cris_version (char *ignore_args, int from_tty,
struct cmd_list_element *c) struct cmd_list_element *c)
{ {
struct gdbarch_info info; struct gdbarch_info info;
/* NOTE: cagney/2002-03-17: The deprecated_add_show_from_set() usr_cmd_cris_version_valid = 1;
function clones the set command passed as a parameter. The clone
operation will include (BUG?) any ``set'' command callback, if
present. Commands like ``info set'' call all the ``show''
command callbacks. Unfortunately, for ``show'' commands cloned
from ``set'', this includes callbacks belonging to ``set''
commands. Making this worse, this only occures if
deprecated_add_show_from_set() is called after add_cmd_sfunc()
(BUG?). */
/* From here on, trust the user's CRIS version setting. */
if (cmd_type (c) == set_cmd)
{
usr_cmd_cris_version_valid = 1;
/* Update the current architecture, if needed. */ /* Update the current architecture, if needed. */
gdbarch_info_init (&info); gdbarch_info_init (&info);
if (!gdbarch_update_p (info)) if (!gdbarch_update_p (info))
internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture."); internal_error (__FILE__, __LINE__,
} "cris_gdbarch_update: failed to update architecture.");
} }
static void static void
cris_mode_update (char *ignore_args, int from_tty, set_cris_dwarf2_cfi (char *ignore_args, int from_tty,
struct cmd_list_element *c) struct cmd_list_element *c)
{ {
struct gdbarch_info info; struct gdbarch_info info;
/* NOTE: cagney/2002-03-17: The deprecated_add_show_from_set()
function clones the set command passed as a parameter. The clone
operation will include (BUG?) any ``set'' command callback, if
present. Commands like ``info set'' call all the ``show''
command callbacks. Unfortunately, for ``show'' commands cloned
from ``set'', this includes callbacks belonging to ``set''
commands. Making this worse, this only occures if
deprecated_add_show_from_set() is called after add_cmd_sfunc()
(BUG?). */
/* From here on, trust the user's CRIS mode setting. */ /* Update the current architecture, if needed. */
if (cmd_type (c) == set_cmd) gdbarch_info_init (&info);
{ if (!gdbarch_update_p (info))
usr_cmd_cris_mode_valid = 1; internal_error (__FILE__, __LINE__,
"cris_gdbarch_update: failed to update architecture.");
/* Update the current architecture, if needed. */
gdbarch_info_init (&info);
if (!gdbarch_update_p (info))
internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture.");
}
} }
static struct gdbarch * static struct gdbarch *
@ -3726,8 +3729,6 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
struct gdbarch *gdbarch; struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep; struct gdbarch_tdep *tdep;
int cris_version; int cris_version;
const char *cris_mode;
int register_bytes;
if (usr_cmd_cris_version_valid) if (usr_cmd_cris_version_valid)
{ {
@ -3740,26 +3741,8 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
cris_version = 10; cris_version = 10;
} }
if (usr_cmd_cris_mode_valid)
{
/* Trust the user's CRIS mode setting. */
cris_mode = usr_cmd_cris_mode;
}
else if (cris_version == 10)
{
/* Assume CRIS version 10 is in user mode. */
cris_mode = CRIS_MODE_USER;
}
else
{
/* Strictly speaking, older CRIS version don't have a supervisor mode,
but we regard its only mode as supervisor mode. */
cris_mode = CRIS_MODE_SUPERVISOR;
}
/* Make the current settings visible to the user. */ /* Make the current settings visible to the user. */
usr_cmd_cris_version = cris_version; usr_cmd_cris_version = cris_version;
usr_cmd_cris_mode = cris_mode;
/* Find a candidate among the list of pre-declared architectures. Both /* Find a candidate among the list of pre-declared architectures. Both
CRIS version and ABI must match. */ CRIS version and ABI must match. */
@ -3767,8 +3750,10 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
arches != NULL; arches != NULL;
arches = gdbarch_list_lookup_by_info (arches->next, &info)) arches = gdbarch_list_lookup_by_info (arches->next, &info))
{ {
if ((gdbarch_tdep (arches->gdbarch)->cris_version == cris_version) if ((gdbarch_tdep (arches->gdbarch)->cris_version
&& (gdbarch_tdep (arches->gdbarch)->cris_mode == cris_mode)) == usr_cmd_cris_version)
&& (gdbarch_tdep (arches->gdbarch)->cris_dwarf2_cfi
== usr_cmd_cris_dwarf2_cfi))
return arches->gdbarch; return arches->gdbarch;
} }
@ -3776,8 +3761,8 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep)); tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep); gdbarch = gdbarch_alloc (&info, tdep);
tdep->cris_version = cris_version; tdep->cris_version = usr_cmd_cris_version;
tdep->cris_mode = cris_mode; tdep->cris_dwarf2_cfi = usr_cmd_cris_dwarf2_cfi;
/* INIT shall ensure that the INFO.BYTE_ORDER is non-zero. */ /* INIT shall ensure that the INFO.BYTE_ORDER is non-zero. */
switch (info.byte_order) switch (info.byte_order)
@ -3804,16 +3789,11 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_sp_regnum (gdbarch, 14); set_gdbarch_sp_regnum (gdbarch, 14);
set_gdbarch_pc_regnum (gdbarch, 15); set_gdbarch_pc_regnum (gdbarch, 15);
set_gdbarch_register_name (gdbarch, cris_register_name); 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_deprecated_register_size (gdbarch, 4);
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_register_bytes_ok (gdbarch, cris_register_bytes_ok);
set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register); set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register);
set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register); set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register);
@ -3827,33 +3807,23 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
case 1: case 1:
case 2: case 2:
case 3: case 3:
/* Support for these may be added later. */
internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unsupported CRIS version");
break;
case 8: case 8:
case 9: case 9:
/* CRIS v8 and v9, a.k.a. ETRAX 100. General registers R0 - R15 /* Old versions; not supported. */
(32 bits), special registers P0 - P1 (8 bits), P4 - P5 (16 bits), internal_error (__FILE__, __LINE__,
and P8 - P14 (32 bits). */ "cris_gdbarch_init: unsupported CRIS version");
register_bytes = (16 * 4) + (2 * 1) + (2 * 2) + (7 * 4);
break; break;
case 10: case 10:
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. */
register_bytes = (16 * 4) + (2 * 1) + (2 * 2) + (9 * 4);
break; break;
default: default:
internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown CRIS version"); internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown CRIS version");
} }
/* Returns the register offset for the first byte of register regno's space
in the saved register state. */
set_gdbarch_deprecated_register_byte (gdbarch, cris_register_offset);
set_gdbarch_register_type (gdbarch, cris_register_type); set_gdbarch_register_type (gdbarch, cris_register_type);
/* Dummy frame functions. */ /* Dummy frame functions. */
@ -3873,9 +3843,16 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_unwind_sp (gdbarch, cris_unwind_sp); set_gdbarch_unwind_sp (gdbarch, cris_unwind_sp);
set_gdbarch_unwind_dummy_id (gdbarch, cris_unwind_dummy_id); set_gdbarch_unwind_dummy_id (gdbarch, cris_unwind_dummy_id);
/* FIXME: Hook in the DWARF CFI frame unwinder. if (tdep->cris_dwarf2_cfi == 1)
frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer); {
*/ /* Hook in the Dwarf-2 frame sniffer. */
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, cris_dwarf2_reg_to_regnum);
dwarf2_frame_set_init_reg (gdbarch, cris_dwarf2_frame_init_reg);
frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
}
frame_unwind_append_sniffer (gdbarch, cris_sigtramp_frame_sniffer);
frame_unwind_append_sniffer (gdbarch, cris_frame_sniffer); frame_unwind_append_sniffer (gdbarch, cris_frame_sniffer);
frame_base_set_default (gdbarch, &cris_frame_base); frame_base_set_default (gdbarch, &cris_frame_base);