/* To get entry_point_address. */
#include "symfile.h"
+#include "solib.h" /* Support for shared libraries. */
+#include "solib-svr4.h" /* For struct link_map_offsets. */
+#include "gdb_string.h"
+
+
enum cris_num_regs
{
/* There are no floating point registers. Used in gdbserver low-linux.c. */
IRP_REGNUM = 26,
SRP_REGNUM = 27,
BAR_REGNUM = 28,
+ DCCR_REGNUM = 29,
BRP_REGNUM = 30,
USP_REGNUM = 31
};
*insn |= 0x20;
}
-static char
+static signed char
cris_get_signed_offset (unsigned short insn)
{
- return ((char) (insn & 0x00FF));
+ return ((signed char) (insn & 0x00FF));
}
/* Calls an op function given the op-type, working on the insn and the
CORE_ADDR frame
CORE_ADDR pc
- int signal_handler_caller
+ enum frame_type type;
CORE_ADDR return_pc
int leaf_function
of the register PC. All other frames contain the content of the
register PC in the next frame.
- The variable signal_handler_caller is non-zero when the frame is
- associated with the call of a signal handler.
+ The variable `type' indicates the frame's type: normal, SIGTRAMP
+ (associated with a signal handler), dummy (associated with a dummy
+ frame).
The variable return_pc contains the address where execution should be
resumed when the present frame has finished, the return address.
insn_next = read_memory_unsigned_integer (ip, sizeof (short));
ip += sizeof (short);
regno = cris_get_operand2 (insn_next);
- if (regno == (SRP_REGNUM - NUM_GENREGS))
+
+ /* This check, meant to recognize srp, used to be regno ==
+ (SRP_REGNUM - NUM_GENREGS), but that covers r11 also. */
+ if (insn_next == 0xBE7E)
{
if (frameless_p)
{
return ip;
}
source_register = cris_get_operand1 (insn);
+
+ /* FIXME? In the glibc solibs, the prologue might contain something
+ like (this example taken from relocate_doit):
+ move.d $pc,$r0
+ sub.d 0xfffef426,$r0
+ which isn't covered by the source_register check below. Question
+ is whether to add a check for this combo, or make better use of
+ the limit variable instead. */
if (source_register < ARG1_REGNUM || source_register > ARG4_REGNUM)
{
/* The prologue ended before the limit was reached. */
if (have_fp)
{
- fi->saved_regs[FP_REGNUM] = FRAME_FP (fi);
+ fi->saved_regs[FP_REGNUM] = get_frame_base (fi);
/* Calculate the addresses. */
for (regno = regsave; regno >= 0; regno--)
{
- fi->saved_regs[regno] = FRAME_FP (fi) - val;
+ fi->saved_regs[regno] = get_frame_base (fi) - val;
val -= 4;
}
if (fi->extra_info->leaf_function)
{
/* Set the register SP to contain the stack pointer of
the caller. */
- fi->saved_regs[SP_REGNUM] = FRAME_FP (fi) + 4;
+ fi->saved_regs[SP_REGNUM] = get_frame_base (fi) + 4;
}
else
{
/* Set the register SP to contain the stack pointer of
the caller. */
- fi->saved_regs[SP_REGNUM] = FRAME_FP (fi) + 8;
+ fi->saved_regs[SP_REGNUM] = get_frame_base (fi) + 8;
/* Set the register SRP to contain the return address of
the caller. */
- fi->saved_regs[SRP_REGNUM] = FRAME_FP (fi) + 4;
+ fi->saved_regs[SRP_REGNUM] = get_frame_base (fi) + 4;
}
}
return ip;
adjusts pcptr (if necessary) to point to the actual memory location where
the breakpoint should be inserted. */
-unsigned char *
+const unsigned char *
cris_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
{
static unsigned char break_insn[] = {0x38, 0xe9};
/* Returns the register SRP (subroutine return pointer) which must contain
the content of the register PC after a function call. */
-CORE_ADDR
-cris_saved_pc_after_call ()
+static CORE_ADDR
+cris_saved_pc_after_call (struct frame_info *frame)
{
return read_register (SRP_REGNUM);
}
int len = TYPE_LENGTH (type);
if (len <= REGISTER_SIZE)
- write_register_bytes (REGISTER_BYTE (RET_REGNUM), valbuf, len);
+ deprecated_write_register_bytes (REGISTER_BYTE (RET_REGNUM), valbuf, len);
else
internal_error (__FILE__, __LINE__, "cris_abi_original_store_return_value: type length too large.");
}
if (len <= 2 * REGISTER_SIZE)
{
/* Note that this works since R10 and R11 are consecutive registers. */
- write_register_bytes (REGISTER_BYTE (RET_REGNUM), valbuf, len);
+ deprecated_write_register_bytes (REGISTER_BYTE (RET_REGNUM), valbuf,
+ len);
}
else
internal_error (__FILE__, __LINE__, "cris_abi_v2_store_return_value: type length too large.");
/* Return the name of register regno as a string. Return NULL for an invalid or
unimplemented register. */
-char *
+const char *
cris_register_name (int regno)
{
static char *cris_genreg_names[] =
int
cris_frameless_function_invocation (struct frame_info *fi)
{
- if (fi->signal_handler_caller)
+ if ((get_frame_type (fi) == SIGTRAMP_FRAME))
return 0;
else
return frameless_look_for_prologue (fi);
CORE_ADDR ip;
struct symtab_and_line sal;
int best_limit;
- char *dummy_regs = generic_find_dummy_frame (fi->pc, fi->frame);
+ char *dummy_regs = deprecated_generic_find_dummy_frame (fi->pc, fi->frame);
/* Examine the entire prologue. */
register int frameless_p = 0;
fi->extra_info->return_pc = 0;
fi->extra_info->leaf_function = 0;
- if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ if (DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
{
/* We need to setup fi->frame here because run_stack_dummy gets it wrong
by assuming it's always FP. */
- fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM);
+ fi->frame = deprecated_read_register_dummy (fi->pc, fi->frame,
+ SP_REGNUM);
fi->extra_info->return_pc =
- generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
+ deprecated_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
/* FIXME: Is this necessarily true? */
fi->extra_info->leaf_function = 0;
CORE_ADDR
cris_frame_chain (struct frame_info *fi)
{
- if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ if (DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
{
return fi->frame;
}
else if (!inside_entry_file (fi->pc))
{
- return read_memory_unsigned_integer (FRAME_FP (fi), 4);
+ return read_memory_unsigned_integer (get_frame_base (fi), 4);
}
else
{
return fi->extra_info->return_pc;
}
-/* Return the address of the argument block for the frame described
- by struct frame_info. */
-
-CORE_ADDR
-cris_frame_args_address (struct frame_info *fi)
-{
- return FRAME_FP (fi);
-}
-
-/* Return the address of the locals block for the frame
- described by struct frame_info. */
-
-CORE_ADDR
-cris_frame_locals_address (struct frame_info *fi)
-{
- return FRAME_FP (fi);
-}
-
/* Setup the function arguments for calling a function in the inferior. */
CORE_ADDR
all saved registers. */
void
-cris_pop_frame ()
+cris_pop_frame (void)
{
register struct frame_info *fi = get_current_frame ();
register int regno;
register int stack_offset = 0;
- if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ if (DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
{
/* This happens when we hit a breakpoint set at the entry point,
when returning from a dummy frame. */
case 'P':
tmp = (insn >> 0xC) & 0xF;
- for (i = 0; i < NUM_SPECREGS; i++)
- /* Since we match four bits, we will give a value of
- 4 - 1 = 3 in a match. If there is a corresponding
- exact match of a special register in another pattern, it
- will get a value of 4, which will be higher. This should
- be correct in that an exact pattern would match better that
- a general pattern.
- Note that there is a reason for not returning zero; the
- pattern for "clear" is partly matched in the bit-pattern
- (the two lower bits must be zero), while the bit-pattern
- for a move from a special register is matched in the
- register constraint.
- This also means we will will have a race condition if
- there is a partly match in three bits in the bit pattern. */
- if (tmp == cris_spec_regs[i].number)
- {
- retval += 3;
- break;
- }
- if (i == NUM_SPECREGS)
+
+ for (i = 0; cris_spec_regs[i].name != NULL; i++)
+ {
+ /* Since we match four bits, we will give a value of
+ 4 - 1 = 3 in a match. If there is a corresponding
+ exact match of a special register in another pattern, it
+ will get a value of 4, which will be higher. This should
+ be correct in that an exact pattern would match better that
+ a general pattern.
+ Note that there is a reason for not returning zero; the
+ pattern for "clear" is partly matched in the bit-pattern
+ (the two lower bits must be zero), while the bit-pattern
+ for a move from a special register is matched in the
+ register constraint.
+ This also means we will will have a race condition if
+ there is a partly match in three bits in the bit pattern. */
+ if (tmp == cris_spec_regs[i].number)
+ {
+ retval += 3;
+ break;
+ }
+ }
+
+ if (cris_spec_regs[i].name == NULL)
return -1;
break;
}
}
}
+/* Just a forward declaration. */
+
+unsigned long
+get_data_from_address (unsigned short *inst, CORE_ADDR address);
+
/* Calculates the prefix value for the general case of offset addressing
mode. */
return;
}
- if (cris_get_mode (inst) == AUTOINC_MODE)
- {
- process_autoincrement (cris_get_size (inst), inst, inst_env);
- }
-
+ /* The calculation of prefix_value used to be after process_autoincrement,
+ but that fails for an instruction such as jsr [$r0+12] which is encoded
+ as 5f0d 0c00 30b9 when compiled with -fpic. Since PC is operand1 it
+ mustn't be incremented until we have read it and what it points at. */
inst_env->prefix_value = inst_env->reg[cris_get_operand2 (inst)];
/* The offset is an indirection of the contents of the operand1 register. */
inst_env->prefix_value +=
- read_memory_integer (inst_env->reg[cris_get_operand1 (inst)], cris_get_size (inst));
+ get_data_from_address (&inst, inst_env->reg[cris_get_operand1 (inst)]);
+ if (cris_get_mode (inst) == AUTOINC_MODE)
+ {
+ process_autoincrement (cris_get_size (inst), inst, inst_env);
+ }
+
/* A prefix doesn't change the xflag_found. But the rest of the flags
need updating. */
inst_env->slot_needed = 0;
inst_env->invalid = 1;
return;
}
- /* The increment depends on the size of the special register.
- Register P0 to P3 has the size byte, register P4 to P7 has the
- size word and register P8 to P15 has the size dword. */
- if (cris_get_operand2 (inst) < 4)
+
+ /* The increment depends on the size of the special register. */
+ if (cris_register_size (cris_get_operand2 (inst)) == 1)
{
process_autoincrement (INST_BYTE_SIZE, inst, inst_env);
}
- if (cris_get_operand2 (inst) < 8)
+ else if (cris_register_size (cris_get_operand2 (inst)) == 2)
{
process_autoincrement (INST_WORD_SIZE, inst, inst_env);
}
inst_env->invalid = 1;
return;
}
- /* The increment depends on the size of the special register.
- Register P0 to P3 has the size byte, register P4 to P7 has
- the size word and register P8 to P15 has the size dword. */
- if (cris_get_operand2 (inst) < 4)
+
+ /* The increment depends on the size of the special register. */
+ if (cris_register_size (cris_get_operand2 (inst)) == 1)
{
process_autoincrement (INST_BYTE_SIZE, inst, inst_env);
}
- if (cris_get_operand2 (inst) < 8)
+ else if (cris_register_size (cris_get_operand2 (inst)) == 2)
{
process_autoincrement (INST_WORD_SIZE, inst, inst_env);
}
return;
}
/* The instruction has the PC as its target register. */
- operand1 = inst_env->reg[operand1];
+ operand1 = inst_env->reg[cris_get_operand1 (inst)];
operand2 = inst_env->reg[REG_PC];
/* Check if it's a extend, signed or zero instruction. */
return TARGET_PRINT_INSN (addr, info);
}
+/* Copied from <asm/elf.h>. */
+typedef unsigned long elf_greg_t;
+
+/* Same as user_regs_struct struct in <asm/user.h>. */
+typedef elf_greg_t elf_gregset_t[35];
+
+/* Unpack an elf_gregset_t into GDB's register cache. */
+
+void
+supply_gregset (elf_gregset_t *gregsetp)
+{
+ int i;
+ elf_greg_t *regp = *gregsetp;
+ static char zerobuf[4] = {0};
+
+ /* The kernel dumps all 32 registers as unsigned longs, but supply_register
+ knows about the actual size of each register so that's no problem. */
+ for (i = 0; i < NUM_GENREGS + NUM_SPECREGS; i++)
+ {
+ supply_register (i, (char *)®p[i]);
+ }
+}
+
+/* Use a local version of this function to get the correct types for
+ regsets, until multi-arch core support is ready. */
+
+static void
+fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
+ int which, CORE_ADDR reg_addr)
+{
+ elf_gregset_t gregset;
+
+ switch (which)
+ {
+ case 0:
+ if (core_reg_size != sizeof (gregset))
+ {
+ warning ("wrong size gregset struct in core file");
+ }
+ else
+ {
+ memcpy (&gregset, core_reg_sect, sizeof (gregset));
+ supply_gregset (&gregset);
+ }
+
+ default:
+ /* We've covered all the kinds of registers we know about here,
+ so this must be something we wouldn't know what to do with
+ anyway. Just ignore it. */
+ break;
+ }
+}
+
+static struct core_fns cris_elf_core_fns =
+{
+ bfd_target_elf_flavour, /* core_flavour */
+ default_check_format, /* check_format */
+ default_core_sniffer, /* core_sniffer */
+ fetch_core_registers, /* core_read_registers */
+ NULL /* next */
+};
+
+/* Fetch (and possibly build) an appropriate link_map_offsets
+ structure for native GNU/Linux CRIS targets using the struct
+ offsets defined in link.h (but without actual reference to that
+ file).
+
+ This makes it possible to access GNU/Linux CRIS shared libraries
+ from a GDB that was not built on an GNU/Linux CRIS host (for cross
+ debugging).
+
+ See gdb/solib-svr4.h for an explanation of these fields. */
+
+struct link_map_offsets *
+cris_linux_svr4_fetch_link_map_offsets (void)
+{
+ static struct link_map_offsets lmo;
+ static struct link_map_offsets *lmp = NULL;
+
+ if (lmp == NULL)
+ {
+ lmp = &lmo;
+
+ lmo.r_debug_size = 8; /* The actual size is 20 bytes, but
+ this is all we need. */
+ lmo.r_map_offset = 4;
+ lmo.r_map_size = 4;
+
+ lmo.link_map_size = 20;
+
+ lmo.l_addr_offset = 0;
+ lmo.l_addr_size = 4;
+
+ lmo.l_name_offset = 4;
+ lmo.l_name_size = 4;
+
+ lmo.l_next_offset = 12;
+ lmo.l_next_size = 4;
+
+ lmo.l_prev_offset = 16;
+ lmo.l_prev_size = 4;
+ }
+
+ 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;
+ }
+}
+
void
_initialize_cris_tdep (void)
{
c = add_set_cmd ("cris-version", class_support, var_integer,
(char *) &usr_cmd_cris_version,
"Set the current CRIS version.", &setlist);
- c->function.sfunc = cris_version_update;
+ set_cmd_sfunc (c, cris_version_update);
add_show_from_set (c, &showlist);
c = add_set_enum_cmd ("cris-mode", class_support, cris_mode_enums,
&usr_cmd_cris_mode,
"Set the current CRIS mode.", &setlist);
- c->function.sfunc = cris_mode_update;
+ set_cmd_sfunc (c, cris_mode_update);
add_show_from_set (c, &showlist);
c = add_set_enum_cmd ("cris-abi", class_support, cris_abi_enums,
&usr_cmd_cris_abi,
"Set the current CRIS ABI version.", &setlist);
- c->function.sfunc = cris_abi_update;
+ set_cmd_sfunc (c, cris_abi_update);
add_show_from_set (c, &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);
+
+ add_core_fns (&cris_elf_core_fns);
+
}
/* Prints out all target specific values. */
{
struct gdbarch_info info;
+ /* NOTE: cagney/2002-03-17: The 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. Unfortunatly, for ``show'' commands cloned from
+ ``set'', this includes callbacks belonging to ``set'' commands.
+ Making this worse, this only occures if add_show_from_set() is
+ called after add_cmd_sfunc() (BUG?). */
+
/* From here on, trust the user's CRIS version setting. */
- if (c->type == set_cmd)
+ if (cmd_type (c) == set_cmd)
{
usr_cmd_cris_version_valid = 1;
/* Update the current architecture, if needed. */
- memset (&info, 0, sizeof info);
+ gdbarch_info_init (&info);
if (!gdbarch_update_p (info))
internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture.");
}
{
struct gdbarch_info info;
+ /* NOTE: cagney/2002-03-17: The 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. Unfortunatly, for ``show'' commands cloned from
+ ``set'', this includes callbacks belonging to ``set'' commands.
+ Making this worse, this only occures if add_show_from_set() is
+ called after add_cmd_sfunc() (BUG?). */
+
/* From here on, trust the user's CRIS mode setting. */
- if (c->type == set_cmd)
+ if (cmd_type (c) == set_cmd)
{
usr_cmd_cris_mode_valid = 1;
/* Update the current architecture, if needed. */
- memset (&info, 0, sizeof info);
+ gdbarch_info_init (&info);
if (!gdbarch_update_p (info))
internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture.");
}
{
struct gdbarch_info info;
+ /* NOTE: cagney/2002-03-17: The 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. Unfortunatly, for ``show'' commands cloned from
+ ``set'', this includes callbacks belonging to ``set'' commands.
+ Making this worse, this only occures if add_show_from_set() is
+ called after add_cmd_sfunc() (BUG?). */
+
/* From here on, trust the user's CRIS ABI setting. */
- if (c->type == set_cmd)
+ if (cmd_type (c) == set_cmd)
{
usr_cmd_cris_abi_valid = 1;
/* Update the current architecture, if needed. */
- memset (&info, 0, sizeof info);
+ gdbarch_info_init (&info);
if (!gdbarch_update_p (info))
internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture.");
}
cris_abi = CRIS_ABI_V2;
}
}
- else if (gdbarch_tdep (current_gdbarch))
+ else if (arches != NULL)
{
- /* No bfd available. Stick with whatever ABI we're currently using.
- (This is to avoid changing the ABI when the user updates the
- architecture with the 'set cris-version' command.) */
- cris_abi = gdbarch_tdep (current_gdbarch)->cris_abi;
+ /* No bfd available. Stick with the ABI from the most recently
+ selected architecture of this same family (the head of arches
+ always points to this). (This is to avoid changing the ABI
+ when the user updates the architecture with the 'set
+ cris-version' command.) */
+ cris_abi = gdbarch_tdep (arches->gdbarch)->cris_abi;
}
else
{
- /* No bfd, and no current architecture available. Assume it's the
- new ABI. */
+ /* No bfd, and no previously selected architecture available.
+ Assume it's the new ABI. */
cris_abi = CRIS_ABI_V2;
}
tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
+ /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
+ ready to unwind the PC first (see frame.c:get_prev_frame()). */
+ set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
+
tdep->cris_version = cris_version;
tdep->cris_mode = cris_mode;
tdep->cris_abi = cris_abi;
/* INIT shall ensure that the INFO.BYTE_ORDER is non-zero. */
switch (info.byte_order)
{
- case LITTLE_ENDIAN:
+ case BFD_ENDIAN_LITTLE:
/* Ok. */
break;
- case BIG_ENDIAN:
+ case BFD_ENDIAN_BIG:
internal_error (__FILE__, __LINE__, "cris_gdbarch_init: big endian byte order in info");
break;
{
set_gdbarch_double_bit (gdbarch, 32);
set_gdbarch_push_arguments (gdbarch, cris_abi_original_push_arguments);
- set_gdbarch_store_return_value (gdbarch,
+ set_gdbarch_deprecated_store_return_value (gdbarch,
cris_abi_original_store_return_value);
- set_gdbarch_extract_return_value
+ set_gdbarch_deprecated_extract_return_value
(gdbarch, cris_abi_original_extract_return_value);
set_gdbarch_reg_struct_has_addr
(gdbarch, cris_abi_original_reg_struct_has_addr);
{
set_gdbarch_double_bit (gdbarch, 64);
set_gdbarch_push_arguments (gdbarch, cris_abi_v2_push_arguments);
- set_gdbarch_store_return_value (gdbarch, cris_abi_v2_store_return_value);
- set_gdbarch_extract_return_value (gdbarch,
- cris_abi_v2_extract_return_value);
+ set_gdbarch_deprecated_store_return_value (gdbarch, cris_abi_v2_store_return_value);
+ set_gdbarch_deprecated_extract_return_value
+ (gdbarch, cris_abi_v2_extract_return_value);
set_gdbarch_reg_struct_has_addr (gdbarch,
cris_abi_v2_reg_struct_has_addr);
}
which means we have to set this explicitly. */
set_gdbarch_long_double_bit (gdbarch, 64);
- /* Floating point is IEEE compatible. */
- set_gdbarch_ieee_float (gdbarch, 1);
-
/* 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_register_virtual_type (gdbarch, cris_register_virtual_type);
/* Use generic dummy frames. */
- set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
/* Where to execute the call in the memory segments. */
- set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
/* Start execution at the beginning of dummy. */
/* Read all about dummy frames in blockframe.c. */
set_gdbarch_call_dummy_length (gdbarch, 0);
- set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
+ set_gdbarch_deprecated_pc_in_call_dummy (gdbarch, deprecated_pc_in_call_dummy_at_entry_point);
/* Defined to 1 to indicate that the target supports inferior function
calls. */
set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
- set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register);
+ set_gdbarch_get_saved_register (gdbarch, deprecated_generic_get_saved_register);
/* No register requires conversion from raw format to virtual format. */
set_gdbarch_register_convertible (gdbarch, generic_register_convertible_not);
set_gdbarch_pop_frame (gdbarch, cris_pop_frame);
set_gdbarch_store_struct_return (gdbarch, cris_store_struct_return);
- set_gdbarch_extract_struct_value_address (gdbarch,
- cris_extract_struct_value_address);
+ set_gdbarch_deprecated_extract_struct_value_address
+ (gdbarch, cris_extract_struct_value_address);
set_gdbarch_use_struct_convention (gdbarch, cris_use_struct_convention);
set_gdbarch_frame_init_saved_regs (gdbarch, cris_frame_init_saved_regs);
set_gdbarch_frame_chain_valid (gdbarch, generic_file_frame_chain_valid);
set_gdbarch_frame_saved_pc (gdbarch, cris_frame_saved_pc);
- set_gdbarch_frame_args_address (gdbarch, cris_frame_args_address);
- set_gdbarch_frame_locals_address (gdbarch, cris_frame_locals_address);
set_gdbarch_saved_pc_after_call (gdbarch, cris_saved_pc_after_call);
set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
/* Helpful for backtracing and returning in a call dummy. */
set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
+ /* Use target_specific function to define link map offsets. */
+ set_solib_svr4_fetch_link_map_offsets
+ (gdbarch, cris_linux_svr4_fetch_link_map_offsets);
+
return gdbarch;
}