X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fcris-tdep.c;h=84f94029960733b9e4f2b6b1939f87f3fce9a13b;hb=4754a64e16a0afde77699cd300487822b46e8247;hp=ff2d6d22abf99375f655dab4834d20b974086bba;hpb=b1e29e332aca04fd8b4b795d1c2ee1eb8fa7ba42;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c index ff2d6d22ab..84f9402996 100644 --- a/gdb/cris-tdep.c +++ b/gdb/cris-tdep.c @@ -1,5 +1,7 @@ /* Target dependent code for CRIS, for GDB, the GNU debugger. - Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Contributed by Axis Communications AB. Written by Hendrik Ruijter, Stefan Andersson, and Orjan Friberg. @@ -21,6 +23,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "defs.h" #include "frame.h" +#include "frame-unwind.h" +#include "frame-base.h" +#include "trad-frame.h" +#include "dwarf2-frame.h" #include "symtab.h" #include "inferior.h" #include "gdbtypes.h" @@ -31,14 +37,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "opcode/cris.h" #include "arch-utils.h" #include "regcache.h" +#include "gdb_assert.h" /* To get entry_point_address. */ -#include "symfile.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 "gdb_string.h" - +#include "dis-asm.h" enum cris_num_regs { @@ -49,11 +56,16 @@ enum cris_num_regs NUM_GENREGS = 16, /* 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. - DEPRECATED_FP_REGNUM Contains address of executing stack frame. + CRIS_FP_REGNUM Contains address of executing stack frame. STR_REGNUM Contains the address of structure return values. RET_REGNUM Contains the return value when shorter than or equal to 32 bits ARG1_REGNUM Contains the first parameter to a function. @@ -65,13 +77,12 @@ enum cris_num_regs SRP_REGNUM Subroutine return pointer register. BRP_REGNUM Breakpoint return pointer register. */ -/* DEPRECATED_FP_REGNUM = 8, SP_REGNUM = 14, and PC_REGNUM = 15 have - been incorporated into the multi-arch framework. */ - enum cris_regnums { /* 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, + /* ABI related registers. */ STR_REGNUM = 9, RET_REGNUM = 10, ARG1_REGNUM = 10, @@ -79,79 +90,75 @@ enum cris_regnums ARG3_REGNUM = 12, ARG4_REGNUM = 13, - /* Enums with respect to the special registers, some of which may not be - applicable to all CRIS versions. */ - P0_REGNUM = 16, + /* Registers which happen to be common. */ VR_REGNUM = 17, - P2_REGNUM = 18, - P3_REGNUM = 19, + MOF_REGNUM = 23, + SRP_REGNUM = 27, + + /* CRISv10 et. al. specific registers. */ + P0_REGNUM = 16, P4_REGNUM = 20, CCR_REGNUM = 21, - MOF_REGNUM = 23, P8_REGNUM = 24, IBR_REGNUM = 25, IRP_REGNUM = 26, - SRP_REGNUM = 27, BAR_REGNUM = 28, DCCR_REGNUM = 29, 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[]; /* 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 -}; - -/* CRIS ABI, set via the user command 'set cris-abi'. - There are two flavours: - 1. Original ABI with 32-bit doubles, where arguments <= 4 bytes are - passed by value. - 2. New ABI with 64-bit doubles, where arguments <= 8 bytes are passed by - value. */ -static const char *usr_cmd_cris_abi; - -/* Indicates whether to trust the above variable. */ -static int usr_cmd_cris_abi_valid = 0; - -/* These variables are strings instead of enums to make them usable as - parameters to add_set_enum_cmd. */ -static const char CRIS_ABI_ORIGINAL[] = "CRIS_ABI_ORIGINAL"; -static const char CRIS_ABI_V2[] = "CRIS_ABI_V2"; -static const char CRIS_ABI_SYMBOL[] = ".$CRIS_ABI_V2"; -static const char *cris_abi_enums[] = -{ - CRIS_ABI_ORIGINAL, - CRIS_ABI_V2, - 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; - const char *cris_abi; + unsigned int cris_version; + int cris_dwarf2_cfi; }; /* Functions for accessing target dependent data. */ @@ -162,28 +169,349 @@ 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[] = +{ + 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) { - return (gdbarch_tdep (current_gdbarch)->cris_mode); + 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; } -static const char * -cris_abi (void) +/* 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) { - return (gdbarch_tdep (current_gdbarch)->cris_abi); + 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; } -/* For saving call-clobbered contents in R9 when returning structs. */ -static CORE_ADDR struct_return_address; +/* 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 frame_extra_info +struct cris_unwind_cache { + /* The previous frame's inner most stack address. Used as this + frame ID's stack_addr. */ + CORE_ADDR prev_sp; + /* The frame's base, optionally used by the high-level debug info. */ + CORE_ADDR base; + int size; + /* How far the SP and r8 (FP) have been offset from the start of + the stack frame (as defined by the previous frame's stack + pointer). */ + LONGEST sp_offset; + LONGEST r8_offset; + int uses_frame; + + /* From old frame_extra_info struct. */ CORE_ADDR return_pc; int leaf_function; + + /* Table indicating the location of each and every register. */ + 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; + }; */ + + if (tdep->cris_version == 10) + { + /* 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); + } + 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; +} + +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; +} + +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. */ + typedef struct instruction_environment { @@ -291,18 +619,6 @@ cris_get_operand1 (unsigned short insn) /* Additional functions in order to handle opcodes. */ -static int -cris_get_wide_opcode (unsigned short insn) -{ - return ((insn & 0x03E0) >> 5); -} - -static int -cris_get_short_size (unsigned short insn) -{ - return ((insn & 0x0010) >> 4); -} - static int cris_get_quick_value (unsigned short insn) { @@ -327,12 +643,6 @@ cris_get_asr_shift_steps (unsigned long value) return (value & 0x3F); } -static int -cris_get_asr_quick_shift_steps (unsigned short insn) -{ - return (insn & 0x1F); -} - static int cris_get_clear_size (unsigned short insn) { @@ -368,179 +678,471 @@ cris_get_signed_offset (unsigned short insn) inst_env. */ static void cris_gdb_func (enum cris_op_type, unsigned short, inst_env_type *); -static CORE_ADDR cris_skip_prologue_main (CORE_ADDR pc, int frameless_p); - static struct gdbarch *cris_gdbarch_init (struct gdbarch_info, struct gdbarch_list *); -static int cris_delayed_get_disassembler (bfd_vma, disassemble_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 void cris_abi_update (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, + struct cris_unwind_cache *info); -static CORE_ADDR bfd_lookup_symbol (bfd *, const char *); +static CORE_ADDR cris_unwind_pc (struct gdbarch *gdbarch, + struct frame_info *next_frame); -/* Frames information. The definition of the struct frame_info is +static CORE_ADDR cris_unwind_sp (struct gdbarch *gdbarch, + struct frame_info *next_frame); - CORE_ADDR frame - CORE_ADDR pc - enum frame_type type; - CORE_ADDR return_pc - int leaf_function +/* When arguments must be pushed onto the stack, they go on in reverse + order. The below implements a FILO (stack) to do this. + Copied from d10v-tdep.c. */ - If the compilation option -fno-omit-frame-pointer is present the - variable frame will be set to the content of R8 which is the frame - pointer register. +struct stack_item +{ + int len; + struct stack_item *prev; + void *data; +}; - The variable pc contains the address where execution is performed - in the present frame. The innermost frame contains the current content - of the register PC. All other frames contain the content of the - register PC in the next frame. +static struct stack_item * +push_stack_item (struct stack_item *prev, void *contents, int len) +{ + struct stack_item *si; + si = xmalloc (sizeof (struct stack_item)); + si->data = xmalloc (len); + si->len = len; + si->prev = prev; + memcpy (si->data, contents, len); + return si; +} - The variable `type' indicates the frame's type: normal, SIGTRAMP - (associated with a signal handler), dummy (associated with a dummy - frame). +static struct stack_item * +pop_stack_item (struct stack_item *si) +{ + struct stack_item *dead = si; + si = si->prev; + xfree (dead->data); + xfree (dead); + return si; +} - The variable return_pc contains the address where execution should be - resumed when the present frame has finished, the return address. +/* Put here the code to store, into fi->saved_regs, the addresses of + 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. */ - The variable leaf_function is 1 if the return address is in the register - SRP, and 0 if it is on the stack. +struct cris_unwind_cache * +cris_frame_unwind_cache (struct frame_info *next_frame, + void **this_prologue_cache) +{ + CORE_ADDR pc; + struct cris_unwind_cache *info; + int i; - Prologue instructions C-code. - The prologue may consist of (-fno-omit-frame-pointer) - 1) 2) - push srp - push r8 push r8 - move.d sp,r8 move.d sp,r8 - subq X,sp subq X,sp - movem rY,[sp] movem rY,[sp] - move.S rZ,[r8-U] move.S rZ,[r8-U] + if ((*this_prologue_cache)) + return (*this_prologue_cache); - where 1 is a non-terminal function, and 2 is a leaf-function. + info = FRAME_OBSTACK_ZALLOC (struct cris_unwind_cache); + (*this_prologue_cache) = info; + info->saved_regs = trad_frame_alloc_saved_regs (next_frame); - Note that this assumption is extremely brittle, and will break at the - slightest change in GCC's prologue. + /* 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; - If local variables are declared or register contents are saved on stack - the subq-instruction will be present with X as the number of bytes - needed for storage. The reshuffle with respect to r8 may be performed - with any size S (b, w, d) and any of the general registers Z={0..13}. - The offset U should be representable by a signed 8-bit value in all cases. - Thus, the prefix word is assumed to be immediate byte offset mode followed - by another word containing the instruction. + /* Prologue analysis does the rest... */ + cris_scan_prologue (frame_func_unwind (next_frame), next_frame, info); - Degenerate cases: - 3) - push r8 - move.d sp,r8 - move.d r8,sp - pop r8 + return info; +} - Prologue instructions C++-code. - Case 1) and 2) in the C-code may be followed by +/* Given a GDB frame, determine the address of the calling function's + frame. This will be used to create a new GDB frame struct. */ - move.d r10,rS ; this - move.d r11,rT ; P1 - move.d r12,rU ; P2 - move.d r13,rV ; P3 - move.S [r8+U],rZ ; P4 +static void +cris_frame_this_id (struct frame_info *next_frame, + void **this_prologue_cache, + struct frame_id *this_id) +{ + struct cris_unwind_cache *info + = cris_frame_unwind_cache (next_frame, this_prologue_cache); + CORE_ADDR base; + CORE_ADDR func; + struct frame_id id; + + /* The FUNC is easy. */ + func = frame_func_unwind (next_frame); + + /* Hopefully the prologue analysis either correctly determined the + frame's base (which is the SP from the previous frame), or set + that base to "NULL". */ + base = info->prev_sp; + if (base == 0) + return; - if any of the call parameters are stored. The host expects these - instructions to be executed in order to get the call parameters right. */ + id = frame_id_build (base, func); -/* Examine the prologue of a function. The variable ip is the address of - the first instruction of the prologue. The variable limit is the address - of the first instruction after the prologue. The variable fi contains the - information in struct frame_info. The variable frameless_p controls whether - the entire prologue is examined (0) or just enough instructions to - determine that it is a prologue (1). */ + (*this_id) = id; +} -CORE_ADDR -cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi, - int frameless_p) +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) { - /* Present instruction. */ - unsigned short insn; + struct cris_unwind_cache *info + = cris_frame_unwind_cache (next_frame, this_prologue_cache); + trad_frame_get_prev_register (next_frame, info->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, bufferp); +} - /* Next instruction, lookahead. */ - unsigned short insn_next; - int regno; +/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that + dummy frame. The frame ID's base needs to match the TOS value + saved by save_dummy_frame_tos(), and the PC match the dummy frame's + breakpoint. */ - /* Is there a push fp? */ - int have_fp; +static struct frame_id +cris_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + return frame_id_build (cris_unwind_sp (gdbarch, next_frame), + frame_pc_unwind (next_frame)); +} - /* Number of byte on stack used for local variables and movem. */ - int val; +static CORE_ADDR +cris_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) +{ + /* Align to the size of an instruction (so that they can safely be + pushed onto the stack). */ + return sp & ~3; +} - /* Highest register number in a movem. */ - int regsave; +static CORE_ADDR +cris_push_dummy_code (struct gdbarch *gdbarch, + CORE_ADDR sp, CORE_ADDR funaddr, int using_gcc, + struct value **args, int nargs, + struct type *value_type, + CORE_ADDR *real_pc, CORE_ADDR *bp_addr) +{ + /* Allocate space sufficient for a breakpoint. */ + sp = (sp - 4) & ~3; + /* Store the address of that breakpoint */ + *bp_addr = sp; + /* CRIS always starts the call at the callee's entry point. */ + *real_pc = funaddr; + return sp; +} - /* move.d r,rS */ - short source_register; +static CORE_ADDR +cris_push_dummy_call (struct gdbarch *gdbarch, struct value *function, + struct regcache *regcache, CORE_ADDR bp_addr, + int nargs, struct value **args, CORE_ADDR sp, + int struct_return, CORE_ADDR struct_addr) +{ + int stack_alloc; + int stack_offset; + int argreg; + int argnum; - /* This frame is with respect to a leaf until a push srp is found. */ - get_frame_extra_info (fi)->leaf_function = 1; + CORE_ADDR regval; + + /* The function's arguments and memory allocated by gdb for the arguments to + point at reside in separate areas on the stack. + Both frame pointers grow toward higher addresses. */ + CORE_ADDR fp_arg; + CORE_ADDR fp_mem; + + struct stack_item *si = NULL; + + /* 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 + return? struct_addr is the address of the reserved space for the return + structure to be written on the stack. */ + if (struct_return) + { + regcache_cooked_write_unsigned (regcache, STR_REGNUM, struct_addr); + } + + /* Now load as many as possible of the first arguments into registers, + and push the rest onto the stack. */ + argreg = ARG1_REGNUM; + stack_offset = 0; + + for (argnum = 0; argnum < nargs; argnum++) + { + int len; + char *val; + int reg_demand; + int i; + + len = TYPE_LENGTH (value_type (args[argnum])); + val = (char *) VALUE_CONTENTS (args[argnum]); + + /* How may registers worth of storage do we need for this argument? */ + reg_demand = (len / 4) + (len % 4 != 0 ? 1 : 0); + + if (len <= (2 * 4) && (argreg + reg_demand - 1 <= ARG4_REGNUM)) + { + /* Data passed by value. Fits in available register(s). */ + for (i = 0; i < reg_demand; i++) + { + regcache_cooked_write_unsigned (regcache, argreg, + *(unsigned long *) val); + argreg++; + val += 4; + } + } + else if (len <= (2 * 4) && argreg <= ARG4_REGNUM) + { + /* Data passed by value. Does not fit in available register(s). + Use the register(s) first, then the stack. */ + for (i = 0; i < reg_demand; i++) + { + if (argreg <= ARG4_REGNUM) + { + regcache_cooked_write_unsigned (regcache, argreg, + *(unsigned long *) val); + argreg++; + val += 4; + } + else + { + /* Push item for later so that pushed arguments + come in the right order. */ + si = push_stack_item (si, val, 4); + val += 4; + } + } + } + else if (len > (2 * 4)) + { + /* FIXME */ + internal_error (__FILE__, __LINE__, "We don't do this"); + } + else + { + /* Data passed by value. No available registers. Put it on + the stack. */ + si = push_stack_item (si, val, len); + } + } + + while (si) + { + /* fp_arg must be word-aligned (i.e., don't += len) to match + the function prologue. */ + sp = (sp - si->len) & ~3; + write_memory (sp, si->data, si->len); + si = pop_stack_item (si); + } + + /* Finally, update the SP register. */ + regcache_cooked_write_unsigned (regcache, SP_REGNUM, sp); + + return sp; +} + +static const struct frame_unwind cris_frame_unwind = { + NORMAL_FRAME, + cris_frame_this_id, + cris_frame_prev_register +}; + +const struct frame_unwind * +cris_frame_sniffer (struct frame_info *next_frame) +{ + return &cris_frame_unwind; +} + +static CORE_ADDR +cris_frame_base_address (struct frame_info *next_frame, void **this_cache) +{ + struct cris_unwind_cache *info + = cris_frame_unwind_cache (next_frame, this_cache); + return info->base; +} + +static const struct frame_base cris_frame_base = { + &cris_frame_unwind, + cris_frame_base_address, + cris_frame_base_address, + cris_frame_base_address +}; + +/* Frames information. The definition of the struct frame_info is + + CORE_ADDR frame + CORE_ADDR pc + enum frame_type type; + CORE_ADDR return_pc + int leaf_function + + If the compilation option -fno-omit-frame-pointer is present the + variable frame will be set to the content of R8 which is the frame + pointer register. + + The variable pc contains the address where execution is performed + in the present frame. The innermost frame contains the current content + of the register PC. All other frames contain the content of the + register PC in the next frame. + + 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. + + The variable leaf_function is 1 if the return address is in the register + SRP, and 0 if it is on the stack. + + Prologue instructions C-code. + The prologue may consist of (-fno-omit-frame-pointer) + 1) 2) + push srp + push r8 push r8 + move.d sp,r8 move.d sp,r8 + subq X,sp subq X,sp + movem rY,[sp] movem rY,[sp] + move.S rZ,[r8-U] move.S rZ,[r8-U] + + where 1 is a non-terminal function, and 2 is a leaf-function. + + Note that this assumption is extremely brittle, and will break at the + slightest change in GCC's prologue. + + If local variables are declared or register contents are saved on stack + the subq-instruction will be present with X as the number of bytes + needed for storage. The reshuffle with respect to r8 may be performed + with any size S (b, w, d) and any of the general registers Z={0..13}. + The offset U should be representable by a signed 8-bit value in all cases. + Thus, the prefix word is assumed to be immediate byte offset mode followed + by another word containing the instruction. + + Degenerate cases: + 3) + push r8 + move.d sp,r8 + move.d r8,sp + pop r8 + + Prologue instructions C++-code. + Case 1) and 2) in the C-code may be followed by + + move.d r10,rS ; this + move.d r11,rT ; P1 + move.d r12,rU ; P2 + move.d r13,rV ; P3 + move.S [r8+U],rZ ; P4 + + if any of the call parameters are stored. The host expects these + instructions to be executed in order to get the call parameters right. */ + +/* Examine the prologue of a function. The variable ip is the address of + the first instruction of the prologue. The variable limit is the address + of the first instruction after the prologue. The variable fi contains the + information in struct frame_info. The variable frameless_p controls whether + the entire prologue is examined (0) or just enough instructions to + determine that it is a prologue (1). */ + +static CORE_ADDR +cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, + struct cris_unwind_cache *info) +{ + /* Present instruction. */ + unsigned short insn; + + /* Next instruction, lookahead. */ + unsigned short insn_next; + int regno; + + /* Is there a push fp? */ + int have_fp; + + /* Number of byte on stack used for local variables and movem. */ + int val; + + /* Highest register number in a movem. */ + int regsave; - /* This frame is without the FP until a push fp is found. */ - have_fp = 0; + /* move.d r,rS */ + short source_register; + + /* Scan limit. */ + int limit; + + /* This frame is with respect to a leaf until a push srp is found. */ + if (info) + { + info->leaf_function = 1; + } /* Assume nothing on stack. */ val = 0; regsave = -1; - /* No information about register contents so far. */ + /* If we were called without a next_frame, that means we were called + from cris_skip_prologue which already tried to find the end of the + prologue through the symbol information. 64 instructions past current + pc is arbitrarily chosen, but at least it means we'll stop eventually. */ + limit = next_frame ? frame_pc_unwind (next_frame) : pc + 64; - /* We only want to know the end of the prologue when fi->saved_regs == 0. - When the saved registers are allocated full information is required. */ - if (get_frame_saved_regs (fi)) - { - for (regno = 0; regno < NUM_REGS; regno++) - get_frame_saved_regs (fi)[regno] = 0; - } - /* Find the prologue instructions. */ - do + while (pc > 0 && pc < limit) { - insn = read_memory_unsigned_integer (ip, sizeof (short)); - ip += sizeof (short); + insn = read_memory_unsigned_integer (pc, 2); + pc += 2; if (insn == 0xE1FC) { /* push 32 bit instruction */ - insn_next = read_memory_unsigned_integer (ip, sizeof (short)); - ip += sizeof (short); + insn_next = read_memory_unsigned_integer (pc, 2); + pc += 2; regno = cris_get_operand2 (insn_next); - + if (info) + { + info->sp_offset += 4; + } /* 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; - } - get_frame_extra_info (fi)->leaf_function = 0; + if (info) + { + info->leaf_function = 0; + } } - else if (regno == DEPRECATED_FP_REGNUM) + else if (insn_next == 0x8FEE) { - have_fp = 1; + /* push $r8 */ + if (info) + { + info->r8_offset = info->sp_offset; + } } } else if (insn == 0x866E) { /* move.d sp,r8 */ - if (frameless_p) - { - return ip; - } + if (info) + { + info->uses_frame = 1; + } continue; } else if (cris_get_operand2 (insn) == SP_REGNUM @@ -548,7 +1150,10 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi, && cris_get_opcode (insn) == 0x000A) { /* subq ,sp */ - val = cris_get_quick_value (insn); + if (info) + { + info->sp_offset += cris_get_quick_value (insn); + } } else if (cris_get_mode (insn) == 0x0002 && cris_get_opcode (insn) == 0x000F @@ -556,10 +1161,6 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi, && cris_get_operand1 (insn) == SP_REGNUM) { /* movem r,[sp] */ - if (frameless_p) - { - return ip; - } regsave = cris_get_operand2 (insn); } else if (cris_get_operand2 (insn) == SP_REGNUM @@ -570,24 +1171,23 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi, register. Used for CRIS v8 i.e. ETRAX 100 and newer if is between 64 and 128. movem r,[sp=sp-] */ - val = -cris_get_signed_offset (insn); - insn_next = read_memory_unsigned_integer (ip, sizeof (short)); - ip += sizeof (short); + if (info) + { + info->sp_offset += -cris_get_signed_offset (insn); + } + insn_next = read_memory_unsigned_integer (pc, 2); + pc += 2; 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 (frameless_p) - { - return ip; - } regsave = cris_get_operand2 (insn_next); } else { /* The prologue ended before the limit was reached. */ - ip -= 2 * sizeof (short); + pc -= 4; break; } } @@ -596,10 +1196,6 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi, && cris_get_size (insn) == 0x0002) { /* move.d r<10..13>,r<0..15> */ - if (frameless_p) - { - return ip; - } source_register = cris_get_operand1 (insn); /* FIXME? In the glibc solibs, the prologue might contain something @@ -612,19 +1208,19 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi, if (source_register < ARG1_REGNUM || source_register > ARG4_REGNUM) { /* The prologue ended before the limit was reached. */ - ip -= sizeof (short); + pc -= 2; break; } } - else if (cris_get_operand2 (insn) == DEPRECATED_FP_REGNUM + else if (cris_get_operand2 (insn) == CRIS_FP_REGNUM /* The size is a fixed-size. */ && ((insn & 0x0F00) >> 8) == 0x0001 /* A negative offset. */ && (cris_get_signed_offset (insn) < 0)) { /* move.S rZ,[r8-U] (?) */ - insn_next = read_memory_unsigned_integer (ip, sizeof (short)); - ip += sizeof (short); + insn_next = read_memory_unsigned_integer (pc, 2); + pc += 2; regno = cris_get_operand2 (insn_next); if ((regno >= 0 && regno < SP_REGNUM) && cris_get_mode (insn_next) == PREFIX_OFFSET_MODE @@ -636,19 +1232,19 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi, else { /* The prologue ended before the limit was reached. */ - ip -= 2 * sizeof (short); + pc -= 4; break; } } - else if (cris_get_operand2 (insn) == DEPRECATED_FP_REGNUM + else if (cris_get_operand2 (insn) == CRIS_FP_REGNUM /* The size is a fixed-size. */ && ((insn & 0x0F00) >> 8) == 0x0001 /* A positive offset. */ && (cris_get_signed_offset (insn) > 0)) { /* move.S [r8+U],rZ (?) */ - insn_next = read_memory_unsigned_integer (ip, sizeof (short)); - ip += sizeof (short); + insn_next = read_memory_unsigned_integer (pc, 2); + pc += 2; regno = cris_get_operand2 (insn_next); if ((regno >= 0 && regno < SP_REGNUM) && cris_get_mode (insn_next) == PREFIX_OFFSET_MODE @@ -661,109 +1257,140 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi, else { /* The prologue ended before the limit was reached. */ - ip -= 2 * sizeof (short); + pc -= 4; break; } } else { /* The prologue ended before the limit was reached. */ - ip -= sizeof (short); + pc -= 2; break; } } - while (ip < limit); - /* We only want to know the end of the prologue when - fi->saved_regs == 0. */ - if (!get_frame_saved_regs (fi)) - return ip; + /* We only want to know the end of the prologue when next_frame and info + are NULL (called from cris_skip_prologue i.e.). */ + if (next_frame == NULL && info == NULL) + { + return pc; + } + + info->size = info->sp_offset; - if (have_fp) + /* Compute the previous frame's stack pointer (which is also the + frame's ID's stack address), and this frame's base pointer. */ + if (info->uses_frame) { - get_frame_saved_regs (fi)[DEPRECATED_FP_REGNUM] = get_frame_base (fi); - - /* Calculate the addresses. */ - for (regno = regsave; regno >= 0; regno--) - { - get_frame_saved_regs (fi)[regno] = get_frame_base (fi) - val; - val -= 4; - } - if (get_frame_extra_info (fi)->leaf_function) - { - /* Set the register SP to contain the stack pointer of - the caller. */ - get_frame_saved_regs (fi)[SP_REGNUM] = get_frame_base (fi) + 4; - } - else - { - /* Set the register SP to contain the stack pointer of - the caller. */ - get_frame_saved_regs (fi)[SP_REGNUM] = get_frame_base (fi) + 8; + ULONGEST this_base; + /* The SP was moved to the FP. This indicates that a new frame + was created. Get THIS frame's FP value by unwinding it from + the next frame. */ + frame_unwind_unsigned_register (next_frame, CRIS_FP_REGNUM, + &this_base); + info->base = this_base; + info->saved_regs[CRIS_FP_REGNUM].addr = info->base; + + /* The FP points at the last saved register. Adjust the FP back + to before the first saved register giving the SP. */ + info->prev_sp = info->base + info->r8_offset; + } + else + { + ULONGEST this_base; + /* Assume that the FP is this frame's SP but with that pushed + stack space added back. */ + frame_unwind_unsigned_register (next_frame, SP_REGNUM, &this_base); + info->base = this_base; + info->prev_sp = info->base + info->size; + } - /* Set the register SRP to contain the return address of - the caller. */ - get_frame_saved_regs (fi)[SRP_REGNUM] = get_frame_base (fi) + 4; - } + /* Calculate the addresses for the saved registers on the stack. */ + /* FIXME: The address calculation should really be done on the fly while + we're analyzing the prologue (we only hold one regsave value as it is + now). */ + val = info->sp_offset; + + for (regno = regsave; regno >= 0; regno--) + { + info->saved_regs[regno].addr = info->base + info->r8_offset - val; + val -= 4; } - return ip; -} -/* Advance pc beyond any function entry prologue instructions at pc - to reach some "real" code. */ + /* The previous frame's SP needed to be computed. Save the computed + value. */ + trad_frame_set_value (info->saved_regs, SP_REGNUM, info->prev_sp); -CORE_ADDR -cris_skip_prologue (CORE_ADDR pc) -{ - return cris_skip_prologue_main (pc, 0); -} + if (!info->leaf_function) + { + /* SRP saved on the stack. But where? */ + if (info->r8_offset == 0) + { + /* R8 not pushed yet. */ + info->saved_regs[SRP_REGNUM].addr = info->base; + } + else + { + /* R8 pushed, but SP may or may not be moved to R8 yet. */ + info->saved_regs[SRP_REGNUM].addr = info->base + 4; + } + } -/* As cris_skip_prologue, but stops as soon as it knows that the function - has a frame. Its result is equal to its input pc if the function is - frameless, unequal otherwise. */ + /* The PC is found in SRP (the actual register or located on the stack). */ + info->saved_regs[PC_REGNUM] = info->saved_regs[SRP_REGNUM]; -CORE_ADDR -cris_skip_prologue_frameless_p (CORE_ADDR pc) -{ - return cris_skip_prologue_main (pc, 1); + return pc; } +/* Advance pc beyond any function entry prologue instructions at pc + to reach some "real" code. */ + /* Given a PC value corresponding to the start of a function, return the PC of the first instruction after the function prologue. */ -CORE_ADDR -cris_skip_prologue_main (CORE_ADDR pc, int frameless_p) +static CORE_ADDR +cris_skip_prologue (CORE_ADDR pc) { - struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); - struct frame_info *fi; - struct symtab_and_line sal = find_pc_line (pc, 0); - int best_limit; + CORE_ADDR func_addr, func_end; + struct symtab_and_line sal; CORE_ADDR pc_after_prologue; - /* frame_info now contains dynamic memory. Since fi is a dummy - here, I don't bother allocating memory for saved_regs. */ - fi = deprecated_frame_xmalloc_with_cleanup (0, sizeof (struct frame_extra_info)); - - /* If there is no symbol information then sal.end == 0, and we end up - examining only the first instruction in the function prologue. - Exaggerating the limit seems to be harmless. */ - if (sal.end > 0) - best_limit = sal.end; - else - best_limit = pc + 100; + /* If we have line debugging information, then the end of the prologue + should the first assembly instruction of the first source line. */ + if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) + { + sal = find_pc_line (func_addr, 0); + if (sal.end > 0 && sal.end < func_end) + return sal.end; + } - pc_after_prologue = cris_examine (pc, best_limit, fi, frameless_p); - do_cleanups (old_chain); + pc_after_prologue = cris_scan_prologue (pc, NULL, NULL); return pc_after_prologue; } +static CORE_ADDR +cris_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + ULONGEST pc; + frame_unwind_unsigned_register (next_frame, PC_REGNUM, &pc); + return pc; +} + +static CORE_ADDR +cris_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + ULONGEST sp; + frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp); + return sp; +} + /* Use the program counter to determine the contents and size of a breakpoint instruction. It returns a pointer to a string of bytes that encode a breakpoint instruction, stores the length of the string to *lenptr, and adjusts pcptr (if necessary) to point to the actual memory location where the breakpoint should be inserted. */ -const unsigned char * +static const unsigned char * cris_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) { static unsigned char break_insn[] = {0x38, 0xe9}; @@ -772,19 +1399,10 @@ cris_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) return break_insn; } -/* Returns the register SRP (subroutine return pointer) which must contain - the content of the register PC after a function call. */ - -static CORE_ADDR -cris_saved_pc_after_call (struct frame_info *frame) -{ - return read_register (SRP_REGNUM); -} - /* Returns 1 if spec_reg is applicable to the current gdbarch's CRIS version, 0 otherwise. */ -int +static int cris_spec_reg_applicable (struct cris_spec_reg spec_reg) { int version = cris_version (); @@ -796,9 +1414,6 @@ cris_spec_reg_applicable (struct cris_spec_reg spec_reg) case cris_ver_warning: /* Indeterminate/obsolete. */ return 0; - case cris_ver_sim: - /* Simulator only. */ - return 0; case cris_ver_v0_3: return (version >= 0 && version <= 3); case cris_ver_v3p: @@ -807,8 +1422,18 @@ cris_spec_reg_applicable (struct cris_spec_reg spec_reg) return (version == 8 || version == 9); case cris_ver_v8p: 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: return (version >= 10); + case cris_ver_v32p: + return (version >= 32); default: /* Invalid cris version. */ return 0; @@ -818,9 +1443,10 @@ cris_spec_reg_applicable (struct cris_spec_reg spec_reg) /* Returns the register size in unit byte. Returns 0 for an unimplemented register, -1 for an invalid register. */ -int +static int cris_register_size (int regno) { + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); int i; int spec_regno; @@ -829,15 +1455,13 @@ cris_register_size (int regno) /* General registers (R0 - R15) are 32 bits. */ 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. Adjust regno accordingly. */ spec_regno = regno - NUM_GENREGS; - /* The entries in cris_spec_regs are stored in register number order, - which means we can shortcut into the array when searching it. */ - for (i = spec_regno; cris_spec_regs[i].name != NULL; i++) + 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])) @@ -847,17 +1471,21 @@ cris_register_size (int regno) /* Special register not applicable to this CRIS version. */ return 0; } - else + else if (regno >= PC_REGNUM && regno < NUM_REGS) { - /* Invalid register. */ - return -1; + /* This will apply to CRISv32 only where there are additional registers + 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 for unimplemented (size 0) and non-existant registers. */ -int +static int cris_cannot_fetch_register (int regno) { return ((regno < 0 || regno >= NUM_REGS) @@ -867,7 +1495,7 @@ cris_cannot_fetch_register (int regno) /* Nonzero if regno should not be written to the target, for various reasons. */ -int +static int cris_cannot_store_register (int regno) { /* There are three kinds of registers we refuse to write to. @@ -888,116 +1516,158 @@ 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; } -/* Returns the register offset for the first byte of register regno's space - in the saved register state. Returns -1 for an invalid or unimplemented - register. */ +/* Nonzero if regno should not be fetched from the target. This is the case + for unimplemented (size 0) and non-existant registers. */ -int -cris_register_offset (int regno) +static int +crisv32_cannot_fetch_register (int regno) { - int i; - int reg_size; - int offset = 0; + 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. */ - if (regno >= 0 && regno < NUM_REGS) - { - /* FIXME: The offsets should be cached and calculated only once, - when the architecture being debugged has changed. */ - for (i = 0; i < regno; i++) - offset += cris_register_size (i); - - return offset; - } - else - { - /* Invalid register. */ - return -1; - } + return 0; } /* Return the GDB type (defined in gdbtypes.c) for the "standard" data type of data in register regno. */ -struct type * -cris_register_virtual_type (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 (unimplemented) register. */ + 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 register. */ - return builtin_type_void; + /* 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 of the value to be stored. */ -/* In the original CRIS ABI, R10 is used to store return values. */ +/* In the CRIS ABI, R10 and R11 are used to store return values. */ -void -cris_abi_original_store_return_value (struct type *type, char *valbuf) +static void +cris_store_return_value (struct type *type, struct regcache *regcache, + const void *valbuf) { + ULONGEST val; int len = TYPE_LENGTH (type); - if (len <= DEPRECATED_REGISTER_SIZE) - deprecated_write_register_bytes (REGISTER_BYTE (RET_REGNUM), valbuf, len); + if (len <= 4) + { + /* Put the return value in R10. */ + val = extract_unsigned_integer (valbuf, len); + regcache_cooked_write_unsigned (regcache, ARG1_REGNUM, val); + } + else if (len <= 8) + { + /* Put the return value in R10 and R11. */ + val = extract_unsigned_integer (valbuf, 4); + regcache_cooked_write_unsigned (regcache, ARG1_REGNUM, val); + val = extract_unsigned_integer ((char *)valbuf + 4, len - 4); + regcache_cooked_write_unsigned (regcache, ARG2_REGNUM, val); + } else - internal_error (__FILE__, __LINE__, "cris_abi_original_store_return_value: type length too large."); + error ("cris_store_return_value: type length too large."); } -/* In the CRIS ABI V2, R10 and R11 are used to store return values. */ +/* Return the name of register regno as a string. Return NULL for an invalid or + unimplemented register. */ -void -cris_abi_v2_store_return_value (struct type *type, char *valbuf) +static const char * +cris_special_register_name (int regno) { - int len = TYPE_LENGTH (type); + int spec_regno; + int i; + + /* Special register (R16 - R31). cris_spec_regs is zero-based. + Adjust regno accordingly. */ + spec_regno = regno - NUM_GENREGS; - if (len <= 2 * DEPRECATED_REGISTER_SIZE) + /* Assume nothing about the layout of the cris_spec_regs struct + when searching. */ + for (i = 0; cris_spec_regs[i].name != NULL; i++) { - /* Note that this works since R10 and R11 are consecutive registers. */ - deprecated_write_register_bytes (REGISTER_BYTE (RET_REGNUM), valbuf, - len); + 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; } - else - internal_error (__FILE__, __LINE__, "cris_abi_v2_store_return_value: type length too large."); + /* Special register not applicable to this CRIS version. */ + return NULL; } -/* Return the name of register regno as a string. Return NULL for an invalid or - unimplemented register. */ - -const char * +static const char * cris_register_name (int regno) { static char *cris_genreg_names[] = @@ -1006,9 +1676,6 @@ cris_register_name (int regno) "r8", "r9", "r10", "r11", \ "r12", "r13", "sp", "pc" }; - int i; - int spec_regno; - if (regno >= 0 && regno < NUM_GENREGS) { /* General register. */ @@ -1016,21 +1683,7 @@ cris_register_name (int regno) } else if (regno >= NUM_GENREGS && regno < NUM_REGS) { - /* Special register (R16 - R31). cris_spec_regs is zero-based. - Adjust regno accordingly. */ - spec_regno = regno - NUM_GENREGS; - - /* The entries in cris_spec_regs are stored in register number order, - 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 cris_special_register_name (regno); } else { @@ -1039,542 +1692,155 @@ cris_register_name (int regno) } } -int -cris_register_bytes_ok (long bytes) -{ - return (bytes == REGISTER_BYTES); -} - -/* Extract from an array regbuf containing the raw register state a function - return value of type type, and copy that, in virtual format, into - valbuf. */ - -/* In the original CRIS ABI, R10 is used to return values. */ - -void -cris_abi_original_extract_return_value (struct type *type, char *regbuf, - char *valbuf) -{ - int len = TYPE_LENGTH (type); - - if (len <= DEPRECATED_REGISTER_SIZE) - memcpy (valbuf, regbuf + REGISTER_BYTE (RET_REGNUM), len); - else - internal_error (__FILE__, __LINE__, "cris_abi_original_extract_return_value: type length too large"); -} - -/* In the CRIS ABI V2, R10 and R11 are used to store return values. */ - -void -cris_abi_v2_extract_return_value (struct type *type, char *regbuf, - char *valbuf) -{ - int len = TYPE_LENGTH (type); - - if (len <= 2 * DEPRECATED_REGISTER_SIZE) - memcpy (valbuf, regbuf + REGISTER_BYTE (RET_REGNUM), len); - else - internal_error (__FILE__, __LINE__, "cris_abi_v2_extract_return_value: type length too large"); -} - -/* Store the address of the place in which to copy the structure the - subroutine will return. In the CRIS ABI, R9 is used in order to pass - the address of the allocated area where a structure return value must - be stored. R9 is call-clobbered, which means we must save it here for - later use. */ - -void -cris_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) -{ - write_register (STR_REGNUM, addr); - struct_return_address = addr; -} - -/* Extract from regbuf the address where a function should return a - structure value. It's not there in the CRIS ABI, so we must do it another - way. */ - -CORE_ADDR -cris_extract_struct_value_address (char *regbuf) -{ - return struct_return_address; -} - -/* Returns 1 if a value of the given type being returned from a function - must have space allocated for it on the stack. gcc_p is true if the - function being considered is known to have been compiled by GCC. - In the CRIS ABI, structure return values are passed to the called - function by reference in register R9 to a caller-allocated area, so - this is always true. */ - -int -cris_use_struct_convention (int gcc_p, struct type *type) -{ - return 1; -} - -/* Returns 1 if the given type will be passed by pointer rather than - directly. */ - -/* In the original CRIS ABI, arguments shorter than or equal to 32 bits are - passed by value. */ - -int -cris_abi_original_reg_struct_has_addr (int gcc_p, struct type *type) -{ - return (TYPE_LENGTH (type) > 4); -} - -/* In the CRIS ABI V2, arguments shorter than or equal to 64 bits are passed - by value. */ - -int -cris_abi_v2_reg_struct_has_addr (int gcc_p, struct type *type) -{ - return (TYPE_LENGTH (type) > 8); -} - -/* Returns 1 if the function invocation represented by fi does not have a - stack frame associated with it. Otherwise return 0. */ - -int -cris_frameless_function_invocation (struct frame_info *fi) -{ - if ((get_frame_type (fi) == SIGTRAMP_FRAME)) - return 0; - else - return frameless_look_for_prologue (fi); -} - -/* See frame.h. Determines the address of all registers in the - current stack frame storing each in frame->saved_regs. Space for - frame->saved_regs shall be allocated by - DEPRECATED_FRAME_INIT_SAVED_REGS using frame_saved_regs_zalloc. */ - -void -cris_frame_init_saved_regs (struct frame_info *fi) +static const char * +crisv32_register_name (int regno) { - CORE_ADDR ip; - struct symtab_and_line sal; - int best_limit; - char *dummy_regs = deprecated_generic_find_dummy_frame (get_frame_pc (fi), - get_frame_base (fi)); - - /* Examine the entire prologue. */ - register int frameless_p = 0; - - /* Has this frame's registers already been initialized? */ - if (get_frame_saved_regs (fi)) - return; - - frame_saved_regs_zalloc (fi); - - if (dummy_regs) - { - /* I don't see this ever happening, considering the context in which - cris_frame_init_saved_regs is called (always when we're not in - a dummy frame). */ - memcpy (get_frame_saved_regs (fi), dummy_regs, SIZEOF_FRAME_SAVED_REGS); - } - else - { - ip = get_frame_func (fi); - sal = find_pc_line (ip, 0); - - /* If there is no symbol information then sal.end == 0, and we end up - examining only the first instruction in the function prologue. - Exaggerating the limit seems to be harmless. */ - if (sal.end > 0) - best_limit = sal.end; - else - best_limit = ip + 100; - - cris_examine (ip, best_limit, fi, frameless_p); - } -} - -/* Initialises the extra frame information at the creation of a new frame. - The inparameter fromleaf is 0 when the call is from create_new_frame. - When the call is from get_prev_frame_info, fromleaf is determined by - cris_frameless_function_invocation. */ + 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" + }; -void -cris_init_extra_frame_info (int fromleaf, struct frame_info *fi) -{ - if (get_next_frame (fi)) + if (regno >= 0 && regno < NUM_GENREGS) { - /* Called from get_prev_frame. */ - deprecated_update_frame_pc_hack (fi, DEPRECATED_FRAME_SAVED_PC (get_next_frame (fi))); - } - - frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info)); - - get_frame_extra_info (fi)->return_pc = 0; - get_frame_extra_info (fi)->leaf_function = 0; - - if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), - get_frame_base (fi), - get_frame_base (fi))) - { - /* We need to setup fi->frame here because call_function_by_hand - gets it wrong by assuming it's always FP. */ - deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi), SP_REGNUM)); - get_frame_extra_info (fi)->return_pc = - deprecated_read_register_dummy (get_frame_pc (fi), - get_frame_base (fi), PC_REGNUM); - - /* FIXME: Is this necessarily true? */ - get_frame_extra_info (fi)->leaf_function = 0; + /* General register. */ + return crisv32_genreg_names[regno]; } - else + else if (regno >= NUM_GENREGS && regno < (NUM_GENREGS + NUM_SPECREGS)) { - cris_frame_init_saved_regs (fi); - - /* Check fromleaf/frameless_function_invocation. (FIXME) */ - - if (get_frame_saved_regs (fi)[SRP_REGNUM] != 0) - { - /* SRP was saved on the stack; non-leaf function. */ - get_frame_extra_info (fi)->return_pc = - read_memory_integer (get_frame_saved_regs (fi)[SRP_REGNUM], - REGISTER_RAW_SIZE (SRP_REGNUM)); - } - else - { - /* SRP is still in a register; leaf function. */ - get_frame_extra_info (fi)->return_pc = read_register (SRP_REGNUM); - /* FIXME: Should leaf_function be set to 1 here? */ - get_frame_extra_info (fi)->leaf_function = 1; - } + return cris_special_register_name (regno); } -} - -/* Return the content of the frame pointer in the present frame. In other - words, determine the address of the calling function's frame. */ - -CORE_ADDR -cris_frame_chain (struct frame_info *fi) -{ - if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), - get_frame_base (fi), - get_frame_base (fi))) + else if (regno == PC_REGNUM) { - return get_frame_base (fi); + return "pc"; } - else if (!inside_entry_file (get_frame_pc (fi))) + else if (regno >= S0_REGNUM && regno <= S15_REGNUM) { - return read_memory_unsigned_integer (get_frame_base (fi), 4); + return crisv32_sreg_names[regno - S0_REGNUM]; } else { - return 0; + /* Invalid register. */ + return NULL; } } -/* Return the saved PC (which equals the return address) of this frame. */ +/* Convert DWARF register number REG to the appropriate register + number used by GDB. */ -CORE_ADDR -cris_frame_saved_pc (struct frame_info *fi) +static int +cris_dwarf2_reg_to_regnum (int reg) { - return get_frame_extra_info (fi)->return_pc; + /* 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; } -/* Setup the function arguments for calling a function in the inferior. */ - -CORE_ADDR -cris_abi_original_push_arguments (int nargs, struct value **args, - CORE_ADDR sp, int struct_return, - CORE_ADDR struct_addr) -{ - int stack_alloc; - int stack_offset; - int argreg; - int argnum; - struct type *type; - int len; - CORE_ADDR regval; - char *val; - - /* Data and parameters reside in different areas on the stack. - Both frame pointers grow toward higher addresses. */ - CORE_ADDR fp_params; - CORE_ADDR fp_data; - - /* Are we returning a value using a structure return or a normal value - return? struct_addr is the address of the reserved space for the return - structure to be written on the stack. */ - if (struct_return) - { - write_register (STR_REGNUM, struct_addr); - } - - /* Make sure there's space on the stack. Allocate space for data and a - parameter to refer to that data. */ - for (argnum = 0, stack_alloc = 0; argnum < nargs; argnum++) - stack_alloc += (TYPE_LENGTH (VALUE_TYPE (args[argnum])) + DEPRECATED_REGISTER_SIZE); - sp -= stack_alloc; - /* We may over-allocate a little here, but that won't hurt anything. */ - - /* Initialize stack frame pointers. */ - fp_params = sp; - fp_data = sp + (nargs * DEPRECATED_REGISTER_SIZE); - - /* Now load as many as possible of the first arguments into - registers, and push the rest onto the stack. */ - argreg = ARG1_REGNUM; - stack_offset = 0; - - for (argnum = 0; argnum < nargs; argnum++) - { - type = VALUE_TYPE (args[argnum]); - len = TYPE_LENGTH (type); - val = (char *) VALUE_CONTENTS (args[argnum]); - - if (len <= DEPRECATED_REGISTER_SIZE && argreg <= ARG4_REGNUM) - { - /* Data fits in a register; put it in the first available - register. */ - write_register (argreg, *(unsigned long *) val); - argreg++; - } - else if (len > DEPRECATED_REGISTER_SIZE && argreg <= ARG4_REGNUM) - { - /* Data does not fit in register; pass it on the stack and - put its address in the first available register. */ - write_memory (fp_data, val, len); - write_register (argreg, fp_data); - fp_data += len; - argreg++; - } - else if (len > DEPRECATED_REGISTER_SIZE) - { - /* Data does not fit in register; put both data and - parameter on the stack. */ - write_memory (fp_data, val, len); - write_memory (fp_params, (char *) (&fp_data), DEPRECATED_REGISTER_SIZE); - fp_data += len; - fp_params += DEPRECATED_REGISTER_SIZE; - } - else - { - /* Data fits in a register, but we are out of registers; - put the parameter on the stack. */ - write_memory (fp_params, val, DEPRECATED_REGISTER_SIZE); - fp_params += DEPRECATED_REGISTER_SIZE; - } - } - - return sp; -} +/* DWARF-2 frame support. */ -CORE_ADDR -cris_abi_v2_push_arguments (int nargs, struct value **args, CORE_ADDR sp, - int struct_return, CORE_ADDR struct_addr) +static void +cris_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, + struct dwarf2_frame_state_reg *reg) { - int stack_alloc; - int stack_offset; - int argreg; - int argnum; - - CORE_ADDR regval; - - /* The function's arguments and memory allocated by gdb for the arguments to - point at reside in separate areas on the stack. - Both frame pointers grow toward higher addresses. */ - CORE_ADDR fp_arg; - CORE_ADDR fp_mem; - - /* Are we returning a value using a structure return or a normal value - return? struct_addr is the address of the reserved space for the return - structure to be written on the stack. */ - if (struct_return) - { - write_register (STR_REGNUM, struct_addr); - } - - /* Allocate enough to keep things word-aligned on both parts of the - stack. */ - stack_alloc = 0; - for (argnum = 0; argnum < nargs; argnum++) - { - int len; - int reg_demand; - - len = TYPE_LENGTH (VALUE_TYPE (args[argnum])); - reg_demand = (len / DEPRECATED_REGISTER_SIZE) + (len % DEPRECATED_REGISTER_SIZE != 0 ? 1 : 0); - - /* reg_demand * DEPRECATED_REGISTER_SIZE is the amount of memory - we might need to allocate for this argument. 2 * - DEPRECATED_REGISTER_SIZE is the amount of stack space we - might need to pass the argument itself (either by value or by - reference). */ - stack_alloc += (reg_demand * DEPRECATED_REGISTER_SIZE + 2 * DEPRECATED_REGISTER_SIZE); - } - sp -= stack_alloc; - /* We may over-allocate a little here, but that won't hurt anything. */ - - /* Initialize frame pointers. */ - fp_arg = sp; - fp_mem = sp + (nargs * (2 * DEPRECATED_REGISTER_SIZE)); - - /* Now load as many as possible of the first arguments into registers, - and push the rest onto the stack. */ - argreg = ARG1_REGNUM; - stack_offset = 0; - - for (argnum = 0; argnum < nargs; argnum++) - { - int len; - char *val; - int reg_demand; - int i; - - len = TYPE_LENGTH (VALUE_TYPE (args[argnum])); - val = (char *) VALUE_CONTENTS (args[argnum]); - - /* How may registers worth of storage do we need for this argument? */ - reg_demand = (len / DEPRECATED_REGISTER_SIZE) + (len % DEPRECATED_REGISTER_SIZE != 0 ? 1 : 0); - - if (len <= (2 * DEPRECATED_REGISTER_SIZE) - && (argreg + reg_demand - 1 <= ARG4_REGNUM)) - { - /* Data passed by value. Fits in available register(s). */ - for (i = 0; i < reg_demand; i++) - { - write_register (argreg, *(unsigned long *) val); - argreg++; - val += DEPRECATED_REGISTER_SIZE; - } - } - else if (len <= (2 * DEPRECATED_REGISTER_SIZE) && argreg <= ARG4_REGNUM) - { - /* Data passed by value. Does not fit in available register(s). - Use the register(s) first, then the stack. */ - for (i = 0; i < reg_demand; i++) - { - if (argreg <= ARG4_REGNUM) - { - write_register (argreg, *(unsigned long *) val); - argreg++; - val += DEPRECATED_REGISTER_SIZE; - } - else - { - /* I guess this memory write could write the - remaining data all at once instead of in - DEPRECATED_REGISTER_SIZE chunks. */ - write_memory (fp_arg, val, DEPRECATED_REGISTER_SIZE); - fp_arg += DEPRECATED_REGISTER_SIZE; - val += DEPRECATED_REGISTER_SIZE; - } - } - } - else if (len > (2 * DEPRECATED_REGISTER_SIZE)) - { - /* Data passed by reference. Put it on the stack. */ - write_memory (fp_mem, val, len); - write_memory (fp_arg, (char *) (&fp_mem), DEPRECATED_REGISTER_SIZE); - - /* fp_mem need not be word-aligned since it's just a chunk of - memory being pointed at. That is, += len would do. */ - fp_mem += reg_demand * DEPRECATED_REGISTER_SIZE; - fp_arg += DEPRECATED_REGISTER_SIZE; - } - else - { - /* Data passed by value. No available registers. Put it on - the stack. */ - write_memory (fp_arg, val, len); - - /* fp_arg must be word-aligned (i.e., don't += len) to match - the function prologue. */ - fp_arg += reg_demand * DEPRECATED_REGISTER_SIZE; - } - } + /* The return address column. */ + if (regnum == PC_REGNUM) + reg->how = DWARF2_FRAME_REG_RA; - return sp; + /* The call frame address. */ + else if (regnum == SP_REGNUM) + reg->how = DWARF2_FRAME_REG_CFA; } -/* Never put the return address on the stack. The register SRP is pushed - by the called function unless it is a leaf-function. Due to the BRP - register the PC will change when continue is sent. */ - -CORE_ADDR -cris_push_return_address (CORE_ADDR pc, CORE_ADDR sp) -{ - write_register (SRP_REGNUM, CALL_DUMMY_ADDRESS ()); - return sp; -} +/* Extract from an array regbuf containing the raw register state a function + return value of type type, and copy that, in virtual format, into + valbuf. */ -/* Restore the machine to the state it had before the current frame - was created. Discard the innermost frame from the stack and restore - all saved registers. */ +/* In the CRIS ABI, R10 and R11 are used to store return values. */ -void -cris_pop_frame (void) +static void +cris_extract_return_value (struct type *type, struct regcache *regcache, + void *valbuf) { - register struct frame_info *fi = get_current_frame (); - register int regno; - register int stack_offset = 0; + ULONGEST val; + int len = TYPE_LENGTH (type); - if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), - get_frame_base (fi), - get_frame_base (fi))) + if (len <= 4) { - /* This happens when we hit a breakpoint set at the entry point, - when returning from a dummy frame. */ - generic_pop_dummy_frame (); - } - else - { - cris_frame_init_saved_regs (fi); - - /* For each register, the address of where it was saved on entry to - the frame now lies in fi->saved_regs[regno], or zero if it was not - saved. This includes special registers such as PC and FP saved in - special ways in the stack frame. The SP_REGNUM is even more - special, the address here is the SP for the next frame, not the - address where the SP was saved. */ - - /* Restore general registers R0 - R7. They were pushed on the stack - after SP was saved. */ - for (regno = 0; regno < DEPRECATED_FP_REGNUM; regno++) - { - if (get_frame_saved_regs (fi)[regno]) - { - write_register (regno, - read_memory_integer (get_frame_saved_regs (fi)[regno], 4)); - } - } - - if (get_frame_saved_regs (fi)[DEPRECATED_FP_REGNUM]) - { - /* Pop the frame pointer (R8). It was pushed before SP - was saved. */ - write_register (DEPRECATED_FP_REGNUM, - read_memory_integer (get_frame_saved_regs (fi)[DEPRECATED_FP_REGNUM], 4)); - stack_offset += 4; - - /* Not a leaf function. */ - if (get_frame_saved_regs (fi)[SRP_REGNUM]) - { - /* SRP was pushed before SP was saved. */ - stack_offset += 4; - } - - /* Restore the SP and adjust for R8 and (possibly) SRP. */ - write_register (SP_REGNUM, get_frame_saved_regs (fi)[DEPRECATED_FP_REGNUM] + stack_offset); - } - else - { - /* Currently, we can't get the correct info into fi->saved_regs - without a frame pointer. */ - } - - /* Restore the PC. */ - write_register (PC_REGNUM, get_frame_extra_info (fi)->return_pc); + /* Get the return value from R10. */ + regcache_cooked_read_unsigned (regcache, ARG1_REGNUM, &val); + store_unsigned_integer (valbuf, len, val); } - flush_cached_frames (); + else if (len <= 8) + { + /* Get the return value from R10 and R11. */ + regcache_cooked_read_unsigned (regcache, ARG1_REGNUM, &val); + store_unsigned_integer (valbuf, 4, val); + regcache_cooked_read_unsigned (regcache, ARG2_REGNUM, &val); + store_unsigned_integer ((char *)valbuf + 4, len - 4, val); + } + else + error ("cris_extract_return_value: type length too large"); +} + +/* Handle the CRIS return value convention. */ + +static enum return_value_convention +cris_return_value (struct gdbarch *gdbarch, struct type *type, + struct regcache *regcache, void *readbuf, + const void *writebuf) +{ + if (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION + || TYPE_LENGTH (type) > 8) + /* Structs, unions, and anything larger than 8 bytes (2 registers) + goes on the stack. */ + return RETURN_VALUE_STRUCT_CONVENTION; + + if (readbuf) + cris_extract_return_value (type, regcache, readbuf); + if (writebuf) + cris_store_return_value (type, regcache, writebuf); + + return RETURN_VALUE_REGISTER_CONVENTION; +} + +/* Returns 1 if the given type will be passed by pointer rather than + directly. */ + +/* In the CRIS ABI, arguments shorter than or equal to 64 bits are passed + by value. */ + +static int +cris_reg_struct_has_addr (int gcc_p, struct type *type) +{ + return (TYPE_LENGTH (type) > 8); } /* Calculates a value that measures how good inst_args constraints an @@ -1681,7 +1947,9 @@ find_cris_op (unsigned short insn, inst_env_type *inst_env) for (i = 0; cris_opcodes[i].name != NULL; i++) { 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); if (level_of_match >= 0) @@ -1772,7 +2040,7 @@ find_step_target (inst_env_type *inst_env) digs through the opcodes in order to find all possible targets. Either one ordinary target or two targets for branches may be found. */ -void +static void cris_software_single_step (enum target_signal ignore, int insert_breakpoints) { inst_env_type inst_env; @@ -1784,7 +2052,9 @@ cris_software_single_step (enum target_signal ignore, int insert_breakpoints) int status = find_step_target (&inst_env); if (status == -1) { - /* Could not find a target. FIXME: Should do something. */ + /* Could not find a target. Things are likely to go downhill + from here. */ + warning ("CRIS software single step could not find a step target."); } else { @@ -1816,7 +2086,7 @@ cris_software_single_step (enum target_signal ignore, int insert_breakpoints) /* Calculates the prefix value for quick offset addressing mode. */ -void +static void quick_mode_bdap_prefix (unsigned short inst, inst_env_type *inst_env) { /* It's invalid to be in a delay slot. You can't have a prefix to this @@ -1840,7 +2110,7 @@ quick_mode_bdap_prefix (unsigned short inst, inst_env_type *inst_env) from the size of the operation. The PC is always kept aligned on even word addresses. */ -void +static void process_autoincrement (int size, unsigned short inst, inst_env_type *inst_env) { if (size == INST_BYTE_SIZE) @@ -1871,12 +2141,13 @@ process_autoincrement (int size, unsigned short inst, inst_env_type *inst_env) /* Just a forward declaration. */ -unsigned long get_data_from_address (unsigned short *inst, CORE_ADDR address); +static unsigned long get_data_from_address (unsigned short *inst, + CORE_ADDR address); /* Calculates the prefix value for the general case of offset addressing mode. */ -void +static void bdap_prefix (unsigned short inst, inst_env_type *inst_env) { @@ -1912,7 +2183,7 @@ bdap_prefix (unsigned short inst, inst_env_type *inst_env) /* Calculates the prefix value for the index addressing mode. */ -void +static void biap_prefix (unsigned short inst, inst_env_type *inst_env) { /* It's invalid to be in a delay slot. I can't see that it's possible to @@ -1947,7 +2218,7 @@ biap_prefix (unsigned short inst, inst_env_type *inst_env) /* Calculates the prefix value for the double indirect addressing mode. */ -void +static void dip_prefix (unsigned short inst, inst_env_type *inst_env) { @@ -1980,7 +2251,7 @@ dip_prefix (unsigned short inst, inst_env_type *inst_env) /* Finds the destination for a branch with 8-bits offset. */ -void +static void eight_bit_offset_branch_op (unsigned short inst, inst_env_type *inst_env) { @@ -2017,7 +2288,7 @@ eight_bit_offset_branch_op (unsigned short inst, inst_env_type *inst_env) /* Finds the destination for a branch with 16-bits offset. */ -void +static void sixteen_bit_offset_branch_op (unsigned short inst, inst_env_type *inst_env) { short offset; @@ -2048,7 +2319,7 @@ sixteen_bit_offset_branch_op (unsigned short inst, inst_env_type *inst_env) /* Handles the ABS instruction. */ -void +static void abs_op (unsigned short inst, inst_env_type *inst_env) { @@ -2090,7 +2361,7 @@ abs_op (unsigned short inst, inst_env_type *inst_env) /* Handles the ADDI instruction. */ -void +static void addi_op (unsigned short inst, inst_env_type *inst_env) { /* It's invalid to have the PC as base register. And ADDI can't have @@ -2109,7 +2380,7 @@ addi_op (unsigned short inst, inst_env_type *inst_env) /* Handles the ASR instruction. */ -void +static void asr_op (unsigned short inst, inst_env_type *inst_env) { int shift_steps; @@ -2186,7 +2457,7 @@ asr_op (unsigned short inst, inst_env_type *inst_env) /* Handles the ASRQ instruction. */ -void +static void asrq_op (unsigned short inst, inst_env_type *inst_env) { @@ -2233,7 +2504,7 @@ asrq_op (unsigned short inst, inst_env_type *inst_env) /* Handles the AX, EI and SETF instruction. */ -void +static void ax_ei_setf_op (unsigned short inst, inst_env_type *inst_env) { if (inst_env->prefix_found) @@ -2259,7 +2530,7 @@ ax_ei_setf_op (unsigned short inst, inst_env_type *inst_env) register. Note that check_assign assumes that the caller has checked that there is a prefix to this instruction. The mode check depends on this. */ -void +static void check_assign (unsigned short inst, inst_env_type *inst_env) { /* Check if it's an assign addressing mode. */ @@ -2272,7 +2543,7 @@ check_assign (unsigned short inst, inst_env_type *inst_env) /* Handles the 2-operand BOUND instruction. */ -void +static void two_operand_bound_op (unsigned short inst, inst_env_type *inst_env) { /* It's invalid to have the PC as the index operand. */ @@ -2305,7 +2576,7 @@ two_operand_bound_op (unsigned short inst, inst_env_type *inst_env) /* Handles the 3-operand BOUND instruction. */ -void +static void three_operand_bound_op (unsigned short inst, inst_env_type *inst_env) { /* It's an error if we haven't got a prefix. And it's also an error @@ -2323,7 +2594,7 @@ three_operand_bound_op (unsigned short inst, inst_env_type *inst_env) /* Clears the status flags in inst_env. */ -void +static void btst_nop_op (unsigned short inst, inst_env_type *inst_env) { /* It's an error if we have got a prefix. */ @@ -2341,7 +2612,7 @@ btst_nop_op (unsigned short inst, inst_env_type *inst_env) /* Clears the status flags in inst_env. */ -void +static void clearf_di_op (unsigned short inst, inst_env_type *inst_env) { /* It's an error if we have got a prefix. */ @@ -2359,7 +2630,7 @@ clearf_di_op (unsigned short inst, inst_env_type *inst_env) /* Handles the CLEAR instruction if it's in register mode. */ -void +static void reg_mode_clear_op (unsigned short inst, inst_env_type *inst_env) { /* Check if the target is the PC. */ @@ -2396,7 +2667,7 @@ reg_mode_clear_op (unsigned short inst, inst_env_type *inst_env) /* Handles the TEST instruction if it's in register mode. */ -void +static void reg_mode_test_op (unsigned short inst, inst_env_type *inst_env) { /* It's an error if we have got a prefix. */ @@ -2415,7 +2686,7 @@ reg_mode_test_op (unsigned short inst, inst_env_type *inst_env) /* Handles the CLEAR and TEST instruction if the instruction isn't in register mode. */ -void +static void none_reg_mode_clear_test_op (unsigned short inst, inst_env_type *inst_env) { /* Check if we are in a prefix mode. */ @@ -2440,7 +2711,7 @@ none_reg_mode_clear_test_op (unsigned short inst, inst_env_type *inst_env) /* Checks that the PC isn't the destination register or the instructions has a prefix. */ -void +static void dstep_logshift_mstep_neg_not_op (unsigned short inst, inst_env_type *inst_env) { /* It's invalid to have the PC as the destination. The instruction can't @@ -2459,7 +2730,7 @@ dstep_logshift_mstep_neg_not_op (unsigned short inst, inst_env_type *inst_env) /* Checks that the instruction doesn't have a prefix. */ -void +static void break_op (unsigned short inst, inst_env_type *inst_env) { /* The instruction can't have a prefix. */ @@ -2478,7 +2749,7 @@ break_op (unsigned short inst, inst_env_type *inst_env) /* Checks that the PC isn't the destination register and that the instruction doesn't have a prefix. */ -void +static void scc_op (unsigned short inst, inst_env_type *inst_env) { /* It's invalid to have the PC as the destination. The instruction can't @@ -2497,7 +2768,7 @@ scc_op (unsigned short inst, inst_env_type *inst_env) /* Handles the register mode JUMP instruction. */ -void +static void reg_mode_jump_op (unsigned short inst, inst_env_type *inst_env) { /* It's invalid to do a JUMP in a delay slot. The mode is register, so @@ -2518,7 +2789,8 @@ reg_mode_jump_op (unsigned short inst, inst_env_type *inst_env) /* Handles the JUMP instruction for all modes except register. */ -void none_reg_mode_jump_op (unsigned short inst, inst_env_type *inst_env) +static void +none_reg_mode_jump_op (unsigned short inst, inst_env_type *inst_env) { unsigned long newpc; CORE_ADDR address; @@ -2562,7 +2834,7 @@ void none_reg_mode_jump_op (unsigned short inst, inst_env_type *inst_env) /* Handles moves to special registers (aka P-register) for all modes. */ -void +static void move_to_preg_op (unsigned short inst, inst_env_type *inst_env) { if (inst_env->prefix_found) @@ -2617,7 +2889,7 @@ move_to_preg_op (unsigned short inst, inst_env_type *inst_env) /* Handles moves from special registers (aka P-register) for all modes except register. */ -void +static void none_reg_mode_move_from_preg_op (unsigned short inst, inst_env_type *inst_env) { if (inst_env->prefix_found) @@ -2672,7 +2944,7 @@ none_reg_mode_move_from_preg_op (unsigned short inst, inst_env_type *inst_env) /* Handles moves from special registers (aka P-register) when the mode is register. */ -void +static void reg_mode_move_from_preg_op (unsigned short inst, inst_env_type *inst_env) { /* Register mode move from special register can't have a prefix. */ @@ -2707,7 +2979,7 @@ reg_mode_move_from_preg_op (unsigned short inst, inst_env_type *inst_env) /* Handles the MOVEM from memory to general register instruction. */ -void +static void move_mem_to_reg_movem_op (unsigned short inst, inst_env_type *inst_env) { if (inst_env->prefix_found) @@ -2764,7 +3036,7 @@ move_mem_to_reg_movem_op (unsigned short inst, inst_env_type *inst_env) /* Handles the MOVEM to memory from general register instruction. */ -void +static void move_reg_to_mem_movem_op (unsigned short inst, inst_env_type *inst_env) { if (inst_env->prefix_found) @@ -2800,67 +3072,10 @@ move_reg_to_mem_movem_op (unsigned short inst, inst_env_type *inst_env) inst_env->disable_interrupt = 0; } -/* Handles the pop instruction to a general register. - POP is a assembler macro for MOVE.D [SP+], Rd. */ - -void -reg_pop_op (unsigned short inst, inst_env_type *inst_env) -{ - /* POP can't have a prefix. */ - if (inst_env->prefix_found) - { - inst_env->invalid = 1; - return; - } - if (cris_get_operand2 (inst) == REG_PC) - { - /* It's invalid to change the PC in a delay slot. */ - if (inst_env->slot_needed) - { - inst_env->invalid = 1; - return; - } - inst_env->reg[REG_PC] = - read_memory_unsigned_integer (inst_env->reg[REG_SP], 4); - } - inst_env->slot_needed = 0; - inst_env->prefix_found = 0; - inst_env->xflag_found = 0; - inst_env->disable_interrupt = 0; -} - -/* Handles moves from register to memory. */ - -void -move_reg_to_mem_index_inc_op (unsigned short inst, inst_env_type *inst_env) -{ - /* Check if we have a prefix. */ - if (inst_env->prefix_found) - { - /* The only thing that can change the PC is an assign. */ - check_assign (inst, inst_env); - } - else if ((cris_get_operand1 (inst) == REG_PC) - && (cris_get_mode (inst) == AUTOINC_MODE)) - { - /* It's invalid to change the PC in a delay slot. */ - if (inst_env->slot_needed) - { - inst_env->invalid = 1; - return; - } - process_autoincrement (cris_get_size (inst), inst, inst_env); - } - inst_env->slot_needed = 0; - inst_env->prefix_found = 0; - inst_env->xflag_found = 0; - inst_env->disable_interrupt = 0; -} - /* Handles the intructions that's not yet implemented, by setting inst_env->invalid to true. */ -void +static void not_implemented_op (unsigned short inst, inst_env_type *inst_env) { inst_env->invalid = 1; @@ -2868,7 +3083,7 @@ not_implemented_op (unsigned short inst, inst_env_type *inst_env) /* Handles the XOR instruction. */ -void +static void xor_op (unsigned short inst, inst_env_type *inst_env) { /* XOR can't have a prefix. */ @@ -2897,7 +3112,7 @@ xor_op (unsigned short inst, inst_env_type *inst_env) /* Handles the MULS instruction. */ -void +static void muls_op (unsigned short inst, inst_env_type *inst_env) { /* MULS/U can't have a prefix. */ @@ -2921,7 +3136,7 @@ muls_op (unsigned short inst, inst_env_type *inst_env) /* Handles the MULU instruction. */ -void +static void mulu_op (unsigned short inst, inst_env_type *inst_env) { /* MULS/U can't have a prefix. */ @@ -2946,7 +3161,7 @@ mulu_op (unsigned short inst, inst_env_type *inst_env) /* Calculate the result of the instruction for ADD, SUB, CMP AND, OR and MOVE. The MOVE instruction is the move from source to register. */ -void +static void add_sub_cmp_and_or_move_action (unsigned short inst, inst_env_type *inst_env, unsigned long source1, unsigned long source2) { @@ -3028,7 +3243,7 @@ add_sub_cmp_and_or_move_action (unsigned short inst, inst_env_type *inst_env, is zero extend then the value is extended with zero. If instead the mode is signed extend the sign bit of the value is taken into consideration. */ -unsigned long +static unsigned long do_sign_or_zero_extend (unsigned long value, unsigned short *inst) { /* The size can be either byte or word, check which one it is. @@ -3066,7 +3281,7 @@ do_sign_or_zero_extend (unsigned long value, unsigned short *inst) /* Handles the register mode for the ADD, SUB, CMP, AND, OR and MOVE instruction. The MOVE instruction is the move from source to register. */ -void +static void reg_mode_add_sub_cmp_and_or_move_op (unsigned short inst, inst_env_type *inst_env) { @@ -3111,7 +3326,7 @@ reg_mode_add_sub_cmp_and_or_move_op (unsigned short inst, the size of the operation. If the instruction is a zero or signed extend instruction, the size field is changed in instruction. */ -unsigned long +static unsigned long get_data_from_address (unsigned short *inst, CORE_ADDR address) { int size = cris_get_size (*inst); @@ -3139,7 +3354,7 @@ get_data_from_address (unsigned short *inst, CORE_ADDR address) /* Handles the assign addresing mode for the ADD, SUB, CMP, AND, OR and MOVE instructions. The MOVE instruction is the move from source to register. */ -void +static void handle_prefix_assign_mode_for_aritm_op (unsigned short inst, inst_env_type *inst_env) { @@ -3168,7 +3383,7 @@ handle_prefix_assign_mode_for_aritm_op (unsigned short inst, OR instructions. Note that for this to work as expected, the calling function must have made sure that there is a prefix to this instruction. */ -void +static void three_operand_add_sub_cmp_and_or_op (unsigned short inst, inst_env_type *inst_env) { @@ -3196,7 +3411,7 @@ three_operand_add_sub_cmp_and_or_op (unsigned short inst, /* Handles the index addresing mode for the ADD, SUB, CMP, AND, OR and MOVE instructions. The MOVE instruction is the move from source to register. */ -void +static void handle_prefix_index_mode_for_aritm_op (unsigned short inst, inst_env_type *inst_env) { @@ -3224,7 +3439,7 @@ handle_prefix_index_mode_for_aritm_op (unsigned short inst, CMP, AND OR and MOVE instruction. The MOVE instruction is the move from source to register. */ -void +static void handle_inc_and_index_mode_for_aritm_op (unsigned short inst, inst_env_type *inst_env) { @@ -3274,7 +3489,7 @@ handle_inc_and_index_mode_for_aritm_op (unsigned short inst, /* Handles the two-operand addressing mode, all modes except register, for the ADD, SUB CMP, AND and OR instruction. */ -void +static void none_reg_mode_add_sub_cmp_and_or_move_op (unsigned short inst, inst_env_type *inst_env) { @@ -3303,7 +3518,7 @@ none_reg_mode_add_sub_cmp_and_or_move_op (unsigned short inst, /* Handles the quick addressing mode for the ADD and SUB instruction. */ -void +static void quick_mode_add_sub_op (unsigned short inst, inst_env_type *inst_env) { unsigned long operand1; @@ -3343,7 +3558,7 @@ quick_mode_add_sub_op (unsigned short inst, inst_env_type *inst_env) /* Handles the quick addressing mode for the CMP, AND and OR instruction. */ -void +static void quick_mode_and_cmp_move_or_op (unsigned short inst, inst_env_type *inst_env) { unsigned long operand1; @@ -3389,8 +3604,9 @@ quick_mode_and_cmp_move_or_op (unsigned short inst, inst_env_type *inst_env) /* Translate op_type to a function and call it. */ -static void cris_gdb_func (enum cris_op_type op_type, unsigned short inst, - inst_env_type *inst_env) +static void +cris_gdb_func (enum cris_op_type op_type, unsigned short inst, + inst_env_type *inst_env) { switch (op_type) { @@ -3548,23 +3764,34 @@ static void cris_gdb_func (enum cris_op_type op_type, unsigned short inst, exec_bfd has been set. */ static int -cris_delayed_get_disassembler (bfd_vma addr, disassemble_info *info) +cris_delayed_get_disassembler (bfd_vma addr, struct disassemble_info *info) { - deprecated_tm_print_insn = cris_get_disassembler (exec_bfd); - return TARGET_PRINT_INSN (addr, info); + int (*print_insn) (bfd_vma addr, struct disassemble_info *info); + /* FIXME: cagney/2003-08-27: It should be possible to select a CRIS + 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); + gdb_assert (print_insn != NULL); + return print_insn (addr, info); } /* Copied from . */ typedef unsigned long elf_greg_t; /* Same as user_regs_struct struct in . */ -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. */ -void +static void supply_gregset (elf_gregset_t *gregsetp) { + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); int i; elf_greg_t *regp = *gregsetp; static char zerobuf[4] = {0}; @@ -3573,7 +3800,19 @@ supply_gregset (elf_gregset_t *gregsetp) 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]); + 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"); } } @@ -3589,7 +3828,8 @@ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, switch (which) { 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"); } @@ -3627,7 +3867,7 @@ static struct core_fns cris_elf_core_fns = See gdb/solib-svr4.h for an explanation of these fields. */ -struct link_map_offsets * +static struct link_map_offsets * cris_linux_svr4_fetch_link_map_offsets (void) { static struct link_map_offsets lmo; @@ -3660,237 +3900,38 @@ 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 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 ,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 ,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 - is between 64 and 128. - movem r,[sp=sp-] */ - 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); - /* Used in disassembly. */ - deprecated_tm_print_insn = cris_delayed_get_disassembler; - /* 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); - 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); - 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); - 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); + 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); + 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); + + deprecated_add_core_fns (&cris_elf_core_fns); } /* Prints out all target specific values. */ @@ -3903,129 +3944,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_abi = %s\n", - tdep->cris_abi); - + 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 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 (cmd_type (c) == set_cmd) - { - 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."); - } -} - -static void -cris_mode_update (char *ignore_args, int from_tty, - struct cmd_list_element *c) -{ - struct gdbarch_info info; + usr_cmd_cris_version_valid = 1; - /* 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 (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 void -cris_abi_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 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 (cmd_type (c) == set_cmd) - { - usr_cmd_cris_abi_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."); - } -} - -/* Copied from pa64solib.c, with a couple of minor changes. */ - -static CORE_ADDR -bfd_lookup_symbol (bfd *abfd, const char *symname) -{ - unsigned int storage_needed; - asymbol *sym; - asymbol **symbol_table; - unsigned int number_of_symbols; - unsigned int i; - struct cleanup *back_to; - CORE_ADDR symaddr = 0; - - storage_needed = bfd_get_symtab_upper_bound (abfd); - - if (storage_needed > 0) - { - symbol_table = (asymbol **) xmalloc (storage_needed); - back_to = make_cleanup (free, symbol_table); - number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); - for (i = 0; i < number_of_symbols; i++) - { - sym = *symbol_table++; - if (!strcmp (sym->name, symname)) - { - /* Bfd symbols are section relative. */ - symaddr = sym->value + sym->section->vma; - break; - } - } - do_cleanups (back_to); - } - return (symaddr); + /* 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 * @@ -4034,84 +3983,24 @@ 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; - const char *cris_abi; - CORE_ADDR cris_abi_sym = 0; - int register_bytes; if (usr_cmd_cris_version_valid) { /* Trust the user's CRIS version setting. */ cris_version = usr_cmd_cris_version; } - else - { - /* Assume it's 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; - } - - if (usr_cmd_cris_abi_valid) - { - /* Trust the user's ABI setting. */ - cris_abi = usr_cmd_cris_abi; - } - else if (info.abfd) - { - if (bfd_get_flavour (info.abfd) == bfd_target_elf_flavour) - { - /* An elf target uses the new ABI. */ - cris_abi = CRIS_ABI_V2; - } - else if (bfd_get_flavour (info.abfd) == bfd_target_aout_flavour) - { - /* An a.out target may use either ABI. Look for hints in the - symbol table. */ - cris_abi_sym = bfd_lookup_symbol (info.abfd, CRIS_ABI_SYMBOL); - cris_abi = cris_abi_sym ? CRIS_ABI_V2 : CRIS_ABI_ORIGINAL; - } - else - { - /* Unknown bfd flavour. Assume it's the new ABI. */ - cris_abi = CRIS_ABI_V2; - } - } - else if (arches != NULL) + else if (info.abfd && bfd_get_mach (info.abfd) == bfd_mach_cris_v32) { - /* 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; + cris_version = 32; } else { - /* No bfd, and no previously selected architecture available. - Assume it's the new ABI. */ - cris_abi = CRIS_ABI_V2; + /* Assume it's CRIS version 10. */ + cris_version = 10; } /* Make the current settings visible to the user. */ usr_cmd_cris_version = cris_version; - usr_cmd_cris_mode = cris_mode; - usr_cmd_cris_abi = cris_abi; /* Find a candidate among the list of pre-declared architectures. Both CRIS version and ABI must match. */ @@ -4119,9 +4008,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) - && (gdbarch_tdep (arches->gdbarch)->cris_abi == cris_abi)) + 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; } @@ -4129,13 +4019,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); - /* 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; + 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) @@ -4152,55 +4037,21 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown byte order in info"); } - /* Initialize the ABI dependent things. */ - if (tdep->cris_abi == CRIS_ABI_ORIGINAL) - { - set_gdbarch_double_bit (gdbarch, 32); - set_gdbarch_deprecated_push_arguments (gdbarch, cris_abi_original_push_arguments); - set_gdbarch_deprecated_store_return_value (gdbarch, - cris_abi_original_store_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); - } - else if (tdep->cris_abi == CRIS_ABI_V2) - { - set_gdbarch_double_bit (gdbarch, 64); - set_gdbarch_deprecated_push_arguments (gdbarch, cris_abi_v2_push_arguments); - 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); - } - else - internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown CRIS ABI"); + set_gdbarch_return_value (gdbarch, cris_return_value); + set_gdbarch_deprecated_reg_struct_has_addr (gdbarch, + cris_reg_struct_has_addr); + set_gdbarch_deprecated_use_struct_convention (gdbarch, always_use_struct_convention); - /* 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); - - /* 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_deprecated_fp_regnum (gdbarch, 8); - 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_RAW_SIZE is the real way to know how big a register is. */ - set_gdbarch_deprecated_register_size (gdbarch, 4); - - /* NEW */ - set_gdbarch_register_bytes_ok (gdbarch, cris_register_bytes_ok); - set_gdbarch_software_single_step (gdbarch, cris_software_single_step); - - - set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register); - set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register); + /* 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); + /* 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); /* 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 @@ -4212,110 +4063,92 @@ 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); + 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; - default: - internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown CRIS version"); - } + 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_register_bytes (gdbarch, register_bytes); + set_gdbarch_cannot_store_register + (gdbarch, crisv32_cannot_store_register); + set_gdbarch_cannot_fetch_register + (gdbarch, crisv32_cannot_fetch_register); - /* Returns the register offset for the first byte of register regno's space - in the saved register state. */ - set_gdbarch_register_byte (gdbarch, cris_register_offset); - - /* The length of the registers in the actual machine representation. */ - set_gdbarch_register_raw_size (gdbarch, cris_register_size); - - /* The largest value REGISTER_RAW_SIZE can have. */ - set_gdbarch_deprecated_max_register_raw_size (gdbarch, 32); - - /* The length of the registers in the program's representation. */ - set_gdbarch_register_virtual_size (gdbarch, cris_register_size); - - /* The largest value REGISTER_VIRTUAL_SIZE can have. */ - set_gdbarch_deprecated_max_register_virtual_size (gdbarch, 32); + set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1); - set_gdbarch_register_virtual_type (gdbarch, cris_register_virtual_type); - - /* Use generic dummy frames. */ - - /* Read all about dummy frames in blockframe.c. */ - 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_deprecated_call_dummy_words (gdbarch, 0); - set_gdbarch_deprecated_sizeof_call_dummy_words (gdbarch, 0); - - set_gdbarch_deprecated_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_single_step_through_delay + (gdbarch, crisv32_single_step_through_delay); - set_gdbarch_deprecated_push_return_address (gdbarch, cris_push_return_address); - set_gdbarch_deprecated_pop_frame (gdbarch, cris_pop_frame); + break; - set_gdbarch_deprecated_store_struct_return (gdbarch, cris_store_struct_return); - set_gdbarch_deprecated_extract_struct_value_address - (gdbarch, cris_extract_struct_value_address); - set_gdbarch_use_struct_convention (gdbarch, cris_use_struct_convention); + default: + internal_error (__FILE__, __LINE__, + "cris_gdbarch_init: unknown CRIS version"); + } - set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, cris_frame_init_saved_regs); - set_gdbarch_deprecated_init_extra_frame_info (gdbarch, cris_init_extra_frame_info); + /* Dummy frame functions (shared between CRISv10 and CRISv32 since they + have the same ABI). */ + set_gdbarch_push_dummy_code (gdbarch, cris_push_dummy_code); + set_gdbarch_push_dummy_call (gdbarch, cris_push_dummy_call); + set_gdbarch_frame_align (gdbarch, cris_frame_align); set_gdbarch_skip_prologue (gdbarch, cris_skip_prologue); - set_gdbarch_prologue_frameless_p (gdbarch, generic_prologue_frameless_p); /* The stack grows downward. */ set_gdbarch_inner_than (gdbarch, core_addr_lessthan); set_gdbarch_breakpoint_from_pc (gdbarch, cris_breakpoint_from_pc); - /* The PC must not be decremented after a breakpoint. (The breakpoint - handler takes care of that.) */ - set_gdbarch_decr_pc_after_break (gdbarch, 0); - - /* Offset from address of function to start of its code. */ - set_gdbarch_function_start_offset (gdbarch, 0); - - /* The number of bytes at the start of arglist that are not really args, - 0 in the CRIS ABI. */ - set_gdbarch_frame_args_skip (gdbarch, 0); - set_gdbarch_frameless_function_invocation - (gdbarch, cris_frameless_function_invocation); - set_gdbarch_deprecated_frame_chain (gdbarch, cris_frame_chain); + set_gdbarch_unwind_pc (gdbarch, cris_unwind_pc); + set_gdbarch_unwind_sp (gdbarch, cris_unwind_sp); + set_gdbarch_unwind_dummy_id (gdbarch, cris_unwind_dummy_id); - set_gdbarch_deprecated_frame_saved_pc (gdbarch, cris_frame_saved_pc); - set_gdbarch_deprecated_saved_pc_after_call (gdbarch, cris_saved_pc_after_call); + 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); + } - 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); + frame_unwind_append_sniffer (gdbarch, cris_sigtramp_frame_sniffer); - /* Should be using push_dummy_call. */ - set_gdbarch_deprecated_dummy_write_sp (gdbarch, generic_target_write_sp); + frame_unwind_append_sniffer (gdbarch, cris_frame_sniffer); + frame_base_set_default (gdbarch, &cris_frame_base); /* Use target_specific function to define link map offsets. */ set_solib_svr4_fetch_link_map_offsets (gdbarch, cris_linux_svr4_fetch_link_map_offsets); + /* FIXME: cagney/2003-08-27: It should be possible to select a CRIS + disassembler, even when there is no BFD. Does something like + "gdb; target remote; disassmeble *0x123" work? */ + set_gdbarch_print_insn (gdbarch, cris_delayed_get_disassembler); + return gdbarch; }