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>
* 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. */
#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 "gdb_string.h"
#include "dis-asm.h"
enum cris_num_regs
{
/* 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
register names and sizes.*/
static int usr_cmd_cris_version;
static unsigned int usr_cmd_cris_version;
/* Indicates whether to trust the above variable. */
static int usr_cmd_cris_version_valid = 0;
/* CRIS mode, set via the user command 'set cris-mode'. Affects availability
of some registers. */
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
};
/* Whether to make use of Dwarf-2 CFI (default on). */
static int usr_cmd_cris_dwarf2_cfi = 1;
/* CRIS architecture specific information. */
struct gdbarch_tdep
{
int cris_version;
const char *cris_mode;
unsigned int cris_version;
int cris_dwarf2_cfi;
};
/* Functions for accessing target dependent data. */
@ -144,10 +130,121 @@ cris_version (void)
return (gdbarch_tdep (current_gdbarch)->cris_version);
}
static const char *
cris_mode (void)
/* Sigtramp identification code copied from i386-linux-tdep.c. */
#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
@ -173,6 +270,111 @@ struct cris_unwind_cache
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. */
typedef
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_version_update (char *ignore_args, int from_tty,
struct cmd_list_element *c);
static void set_cris_version (char *ignore_args, int from_tty,
struct cmd_list_element *c);
static void cris_mode_update (char *ignore_args, int from_tty,
struct cmd_list_element *c);
static void set_cris_dwarf2_cfi (char *ignore_args, int from_tty,
struct cmd_list_element *c);
static CORE_ADDR cris_scan_prologue (CORE_ADDR pc,
struct frame_info *next_frame,
@ -362,9 +564,8 @@ static CORE_ADDR cris_unwind_sp (struct gdbarch *gdbarch,
struct frame_info *next_frame);
/* When arguments must be pushed onto the stack, they go on in reverse
order. The below implements a FILO (stack) to do this. */
/* Borrowed from d10v-tdep.c. */
order. The below implements a FILO (stack) to do this.
Copied from d10v-tdep.c. */
struct stack_item
{
@ -399,7 +600,7 @@ pop_stack_item (struct stack_item *si)
the saved registers of frame described by FRAME_INFO. This
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
for it IS the sp for the next frame. */
for it IS the sp for the next frame. */
struct cris_unwind_cache *
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;
/* Push the return address. */
/* Push the return address. */
regcache_cooked_write_unsigned (regcache, SRP_REGNUM, bp_addr);
/* 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;
/* Find the prologue instructions. */
while (pc < limit)
while (pc > 0 && pc < limit)
{
insn = read_memory_unsigned_integer (pc, 2);
pc += 2;
@ -1169,13 +1370,8 @@ cris_cannot_store_register (int regno)
/* Writing has no effect. */
return 1;
else if (cris_mode () == CRIS_MODE_USER)
{
if (regno == IBR_REGNUM || regno == BAR_REGNUM || regno == BRP_REGNUM
|| regno == IRP_REGNUM)
/* Read-only in user mode. */
return 1;
}
/* IBR, BAR, BRP and IRP are read-only in user mode. Let the debug
agent decide whether they are writable. */
return 0;
}
@ -1202,7 +1398,7 @@ cris_register_offset (int regno)
}
else
{
/* Invalid register. */
/* Invalid register. */
return -1;
}
}
@ -1213,33 +1409,21 @@ cris_register_offset (int regno)
static struct type *
cris_register_type (struct gdbarch *gdbarch, int regno)
{
if (regno == SP_REGNUM || regno == PC_REGNUM
|| (regno > P8_REGNUM && regno < USP_REGNUM))
{
/* SP, PC, IBR, IRP, SRP, BAR, DCCR, BRP */
return lookup_pointer_type (builtin_type_void);
}
else if (regno == P8_REGNUM || regno == USP_REGNUM
|| (regno >= 0 && regno < SP_REGNUM))
{
/* R0 - R13, P8, P15 */
return builtin_type_unsigned_long;
}
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;
}
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 < SP_REGNUM)
|| (regno >= MOF_REGNUM && regno <= USP_REGNUM))
/* Note: R8 taken care of previous clause. */
return builtin_type_uint32;
else if (regno >= P4_REGNUM && regno <= CCR_REGNUM)
return builtin_type_uint16;
else if (regno >= P0_REGNUM && regno <= VR_REGNUM)
return builtin_type_uint8;
else
{
/* Invalid register. */
return builtin_type_void;
}
/* Invalid (unimplemented) register. */
return builtin_type_int0;
}
/* 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
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
@ -1596,6 +1819,7 @@ cris_software_single_step (enum target_signal ignore, int insert_breakpoints)
if (status == -1)
{
/* Could not find a target. FIXME: Should do something. */
warning ("cris_software_single_step: unable to find step target");
}
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
"gdb; target remote; disassmeble *0x123" work? */
gdb_assert (exec_bfd != NULL);
print_insn = cris_get_disassembler (exec_bfd);
print_insn = cris_get_disassembler (exec_bfd);
gdb_assert (print_insn != NULL);
return print_insn (addr, info);
}
@ -3423,230 +3647,37 @@ cris_linux_svr4_fetch_link_map_offsets (void)
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 */
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;
gdbarch_register (bfd_arch_cris, cris_gdbarch_init, cris_dump_tdep);
/* CRIS-specific user-commands. */
c = add_set_cmd ("cris-version", class_support, var_integer,
(char *) &usr_cmd_cris_version,
"Set the current CRIS version.", &setlist);
set_cmd_sfunc (c, cris_version_update);
deprecated_add_show_from_set (c, &showlist);
add_setshow_uinteger_cmd ("cris-version", class_support,
&usr_cmd_cris_version,
"Set the current CRIS version.",
"Show the current CRIS version.",
"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,
&usr_cmd_cris_mode,
"Set the current CRIS mode.", &setlist);
set_cmd_sfunc (c, cris_mode_update);
deprecated_add_show_from_set (c, &showlist);
add_setshow_boolean_cmd ("cris-dwarf2-cfi", class_support,
&usr_cmd_cris_dwarf2_cfi,
"Set the usage of Dwarf-2 CFI for CRIS.",
"Show the usage of Dwarf-2 CFI for CRIS.",
"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. */
@ -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",
tdep->cris_version);
fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_mode = %s\n",
tdep->cris_mode);
fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_dwarf2_cfi = %i\n",
tdep->cris_dwarf2_cfi);
}
}
static void
cris_version_update (char *ignore_args, int from_tty,
struct cmd_list_element *c)
set_cris_version (char *ignore_args, int from_tty,
struct cmd_list_element *c)
{
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 version setting. */
if (cmd_type (c) == set_cmd)
{
usr_cmd_cris_version_valid = 1;
usr_cmd_cris_version_valid = 1;
/* 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.");
}
/* 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 void
cris_mode_update (char *ignore_args, int from_tty,
struct cmd_list_element *c)
set_cris_dwarf2_cfi (char *ignore_args, int from_tty,
struct cmd_list_element *c)
{
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. */
if (cmd_type (c) == set_cmd)
{
usr_cmd_cris_mode_valid = 1;
/* 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.");
}
/* 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 *
@ -3726,8 +3729,6 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
int cris_version;
const char *cris_mode;
int register_bytes;
if (usr_cmd_cris_version_valid)
{
@ -3740,26 +3741,8 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
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. */
usr_cmd_cris_version = cris_version;
usr_cmd_cris_mode = cris_mode;
/* Find a candidate among the list of pre-declared architectures. Both
CRIS version and ABI must match. */
@ -3767,8 +3750,10 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
arches != NULL;
arches = gdbarch_list_lookup_by_info (arches->next, &info))
{
if ((gdbarch_tdep (arches->gdbarch)->cris_version == cris_version)
&& (gdbarch_tdep (arches->gdbarch)->cris_mode == cris_mode))
if ((gdbarch_tdep (arches->gdbarch)->cris_version
== usr_cmd_cris_version)
&& (gdbarch_tdep (arches->gdbarch)->cris_dwarf2_cfi
== usr_cmd_cris_dwarf2_cfi))
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));
gdbarch = gdbarch_alloc (&info, tdep);
tdep->cris_version = cris_version;
tdep->cris_mode = cris_mode;
tdep->cris_version = usr_cmd_cris_version;
tdep->cris_dwarf2_cfi = usr_cmd_cris_dwarf2_cfi;
/* INIT shall ensure that the INFO.BYTE_ORDER is non-zero. */
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_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_deprecated_register_size (gdbarch, 4);
set_gdbarch_double_bit (gdbarch, 64);
/* The default definition of a long double is 2 * TARGET_DOUBLE_BIT,
which means we have to set this explicitly. */
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_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 2:
case 3:
/* Support for these may be added later. */
internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unsupported CRIS version");
break;
case 8:
case 9:
/* CRIS v8 and v9, a.k.a. ETRAX 100. General registers R0 - R15
(32 bits), special registers P0 - P1 (8 bits), P4 - P5 (16 bits),
and P8 - P14 (32 bits). */
register_bytes = (16 * 4) + (2 * 1) + (2 * 2) + (7 * 4);
/* Old versions; not supported. */
internal_error (__FILE__, __LINE__,
"cris_gdbarch_init: unsupported CRIS version");
break;
case 10:
case 11:
/* CRIS v10 and v11, a.k.a. ETRAX 100LX. In addition to ETRAX 100,
P7 (32 bits), and P15 (32 bits) have been implemented. */
register_bytes = (16 * 4) + (2 * 1) + (2 * 2) + (9 * 4);
break;
default:
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);
/* 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_dummy_id (gdbarch, cris_unwind_dummy_id);
/* FIXME: Hook in the DWARF CFI frame unwinder.
frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
*/
if (tdep->cris_dwarf2_cfi == 1)
{
/* 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_base_set_default (gdbarch, &cris_frame_base);