X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fcris-tdep.c;h=c0b814cab448b42700e0e53ea77af56bc01cad6c;hb=71983bf85183974ba732682672cada50528b441d;hp=ef315a685b8ce6758d16582fb52143925b2adf14;hpb=8a3fe4f86c51d363e10efed1046ebcbdc853ae99;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c index ef315a685b..c0b814cab4 100644 --- a/gdb/cris-tdep.c +++ b/gdb/cris-tdep.c @@ -1,26 +1,25 @@ /* Target dependent code for CRIS, for GDB, the GNU debugger. - Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, - Inc. + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. Contributed by Axis Communications AB. Written by Hendrik Ruijter, Stefan Andersson, and Orjan Friberg. -This file is part of GDB. + This file is part of GDB. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include "defs.h" #include "frame.h" @@ -44,7 +43,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "objfiles.h" #include "solib.h" /* Support for shared libraries. */ -#include "solib-svr4.h" /* For struct link_map_offsets. */ +#include "solib-svr4.h" #include "gdb_string.h" #include "dis-asm.h" @@ -73,8 +72,8 @@ enum cris_num_regs ARG2_REGNUM Contains the second parameter to a function. ARG3_REGNUM Contains the third parameter to a function. ARG4_REGNUM Contains the fourth parameter to a function. Rest on stack. - SP_REGNUM Contains address of top of stack. - PC_REGNUM Contains address of next instruction. + gdbarch_sp_regnum Contains address of top of stack. + gdbarch_pc_regnum Contains address of next instruction. SRP_REGNUM Subroutine return pointer register. BRP_REGNUM Breakpoint return pointer register. */ @@ -146,19 +145,32 @@ enum cris_regnums 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 unsigned int usr_cmd_cris_version; + register names and sizes. */ +static int usr_cmd_cris_version; /* Indicates whether to trust the above variable. */ static int usr_cmd_cris_version_valid = 0; +static const char cris_mode_normal[] = "normal"; +static const char cris_mode_guru[] = "guru"; +static const char *cris_modes[] = { + cris_mode_normal, + cris_mode_guru, + 0 +}; + +/* CRIS mode, set via the user command 'set cris-mode'. Affects + type of break instruction among other things. */ +static const char *usr_cmd_cris_mode = cris_mode_normal; + /* 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 { - unsigned int cris_version; + int cris_version; + const char *cris_mode; int cris_dwarf2_cfi; }; @@ -170,6 +182,12 @@ cris_version (void) return (gdbarch_tdep (current_gdbarch)->cris_version); } +static const char * +cris_mode (void) +{ + return (gdbarch_tdep (current_gdbarch)->cris_mode); +} + /* Sigtramp identification code copied from i386-linux-tdep.c. */ #define SIGTRAMP_INSN0 0x9c5f /* movu.w 0xXX, $r9 */ @@ -200,14 +218,14 @@ static CORE_ADDR cris_sigtramp_start (struct frame_info *next_frame) { CORE_ADDR pc = frame_pc_unwind (next_frame); - unsigned short buf[SIGTRAMP_LEN]; + gdb_byte buf[SIGTRAMP_LEN]; if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN)) return 0; - if (buf[0] != SIGTRAMP_INSN0) + if (((buf[1] << 8) + buf[0]) != SIGTRAMP_INSN0) { - if (buf[0] != SIGTRAMP_INSN1) + if (((buf[1] << 8) + buf[0]) != SIGTRAMP_INSN1) return 0; pc -= SIGTRAMP_OFFSET1; @@ -228,14 +246,14 @@ static CORE_ADDR cris_rt_sigtramp_start (struct frame_info *next_frame) { CORE_ADDR pc = frame_pc_unwind (next_frame); - unsigned short buf[SIGTRAMP_LEN]; + gdb_byte buf[SIGTRAMP_LEN]; if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN)) return 0; - if (buf[0] != SIGTRAMP_INSN0) + if (((buf[1] << 8) + buf[0]) != SIGTRAMP_INSN0) { - if (buf[0] != SIGTRAMP_INSN1) + if (((buf[1] << 8) + buf[0]) != SIGTRAMP_INSN1) return 0; pc -= SIGTRAMP_OFFSET1; @@ -259,7 +277,8 @@ cris_sigcontext_addr (struct frame_info *next_frame) CORE_ADDR sp; char buf[4]; - frame_unwind_register (next_frame, SP_REGNUM, buf); + frame_unwind_register (next_frame, + gdbarch_sp_regnum (get_frame_arch (next_frame)), buf); sp = extract_unsigned_integer (buf, 4); /* Look for normal sigtramp frame first. */ @@ -314,7 +333,8 @@ 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 gdbarch *gdbarch = get_frame_arch (next_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); struct cris_unwind_cache *info; CORE_ADDR pc; CORE_ADDR sp; @@ -339,7 +359,7 @@ cris_sigtramp_frame_unwind_cache (struct frame_info *next_frame, info->return_pc = 0; info->leaf_function = 0; - frame_unwind_register (next_frame, SP_REGNUM, buf); + frame_unwind_register (next_frame, gdbarch_sp_regnum (gdbarch), buf); info->base = extract_unsigned_integer (buf, 4); addr = cris_sigcontext_addr (next_frame); @@ -365,8 +385,9 @@ cris_sigtramp_frame_unwind_cache (struct frame_info *next_frame, 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); + info->saved_regs[gdbarch_pc_regnum (gdbarch)] + = info->saved_regs[IRP_REGNUM]; + info->saved_regs[gdbarch_sp_regnum (gdbarch)].addr = addr + (24 * 4); } else { @@ -393,9 +414,11 @@ cris_sigtramp_frame_unwind_cache (struct frame_info *next_frame, 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[gdbarch_pc_regnum (gdbarch)] + = info->saved_regs[ERP_REGNUM]; - info->saved_regs[SP_REGNUM].addr = addr + (25 * 4); + info->saved_regs[gdbarch_sp_regnum (gdbarch)].addr + = addr + (25 * 4); } return info; @@ -416,13 +439,13 @@ 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); + int *realnump, gdb_byte *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) + int *realnump, gdb_byte *valuep) { /* Make sure we've initialized the cache. */ cris_sigtramp_frame_unwind_cache (next_frame, this_cache); @@ -451,12 +474,20 @@ int crisv32_single_step_through_delay (struct gdbarch *gdbarch, struct frame_info *this_frame) { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ULONGEST erp; int ret = 0; char buf[4]; - frame_unwind_register (this_frame, ERP_REGNUM, buf); + if (cris_mode () == cris_mode_guru) + { + frame_unwind_register (this_frame, NRP_REGNUM, buf); + } + else + { + frame_unwind_register (this_frame, ERP_REGNUM, buf); + } + erp = extract_unsigned_integer (buf, 4); if (erp & 0x1) @@ -507,7 +538,7 @@ CORE_ADDR cris_stopped_data_address (void) { CORE_ADDR eda; - eda = read_register (EDA_REGNUM); + eda = get_frame_register_unsigned (get_current_frame (), EDA_REGNUM); return eda; } @@ -530,15 +561,6 @@ struct instruction_environment int disable_interrupt; } inst_env_type; -/* Save old breakpoints in order to restore the state before a single_step. - At most, two breakpoints will have to be remembered. */ -typedef -char binsn_quantum[BREAKPOINT_MAX]; -static binsn_quantum break_mem[2]; -static CORE_ADDR next_pc = 0; -static CORE_ADDR branch_target_address = 0; -static unsigned char branch_break_inserted = 0; - /* Machine-dependencies in CRIS for opcodes. */ /* Instruction sizes. */ @@ -687,6 +709,9 @@ static void cris_dump_tdep (struct gdbarch *, struct ui_file *); static void set_cris_version (char *ignore_args, int from_tty, struct cmd_list_element *c); +static void set_cris_mode (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); @@ -694,6 +719,10 @@ static CORE_ADDR cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, struct cris_unwind_cache *info); +static CORE_ADDR crisv32_scan_prologue (CORE_ADDR pc, + struct frame_info *next_frame, + struct cris_unwind_cache *info); + static CORE_ADDR cris_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame); @@ -765,7 +794,12 @@ cris_frame_unwind_cache (struct frame_info *next_frame, info->leaf_function = 0; /* Prologue analysis does the rest... */ - cris_scan_prologue (frame_func_unwind (next_frame), next_frame, info); + if (cris_version () == 32) + crisv32_scan_prologue (frame_func_unwind (next_frame, NORMAL_FRAME), + next_frame, info); + else + cris_scan_prologue (frame_func_unwind (next_frame, NORMAL_FRAME), + next_frame, info); return info; } @@ -785,7 +819,7 @@ cris_frame_this_id (struct frame_info *next_frame, struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* Hopefully the prologue analysis either correctly determined the frame's base (which is the SP from the previous frame), or set @@ -804,7 +838,7 @@ 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) + int *realnump, gdb_byte *bufferp) { struct cris_unwind_cache *info = cris_frame_unwind_cache (next_frame, this_prologue_cache); @@ -834,10 +868,11 @@ cris_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) static CORE_ADDR cris_push_dummy_code (struct gdbarch *gdbarch, - CORE_ADDR sp, CORE_ADDR funaddr, int using_gcc, + CORE_ADDR sp, CORE_ADDR funaddr, struct value **args, int nargs, struct type *value_type, - CORE_ADDR *real_pc, CORE_ADDR *bp_addr) + CORE_ADDR *real_pc, CORE_ADDR *bp_addr, + struct regcache *regcache) { /* Allocate space sufficient for a breakpoint. */ sp = (sp - 4) & ~3; @@ -903,8 +938,7 @@ cris_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* 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); + regcache_cooked_write (regcache, argreg, val); argreg++; val += 4; } @@ -917,8 +951,7 @@ cris_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { if (argreg <= ARG4_REGNUM) { - regcache_cooked_write_unsigned (regcache, argreg, - *(unsigned long *) val); + regcache_cooked_write (regcache, argreg, val); argreg++; val += 4; } @@ -933,8 +966,22 @@ cris_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } else if (len > (2 * 4)) { - /* FIXME */ - internal_error (__FILE__, __LINE__, "We don't do this"); + /* Data passed by reference. Push copy of data onto stack + and pass pointer to this copy as argument. */ + sp = (sp - len) & ~3; + write_memory (sp, val, len); + + if (argreg <= ARG4_REGNUM) + { + regcache_cooked_write_unsigned (regcache, argreg, sp); + argreg++; + } + else + { + gdb_byte buf[4]; + store_unsigned_integer (buf, 4, sp); + si = push_stack_item (si, buf, 4); + } } else { @@ -954,12 +1001,13 @@ cris_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } /* Finally, update the SP register. */ - regcache_cooked_write_unsigned (regcache, SP_REGNUM, sp); + regcache_cooked_write_unsigned (regcache, gdbarch_sp_regnum (gdbarch), sp); return sp; } -static const struct frame_unwind cris_frame_unwind = { +static const struct frame_unwind cris_frame_unwind = +{ NORMAL_FRAME, cris_frame_this_id, cris_frame_prev_register @@ -979,7 +1027,8 @@ cris_frame_base_address (struct frame_info *next_frame, void **this_cache) return info->base; } -static const struct frame_base cris_frame_base = { +static const struct frame_base cris_frame_base = +{ &cris_frame_unwind, cris_frame_base_address, cris_frame_base_address, @@ -1066,6 +1115,7 @@ static CORE_ADDR cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, struct cris_unwind_cache *info) { + struct gdbarch *gdbarch = get_frame_arch (next_frame); /* Present instruction. */ unsigned short insn; @@ -1146,7 +1196,7 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, } continue; } - else if (cris_get_operand2 (insn) == SP_REGNUM + else if (cris_get_operand2 (insn) == gdbarch_sp_regnum (gdbarch) && cris_get_mode (insn) == 0x0000 && cris_get_opcode (insn) == 0x000A) { @@ -1159,12 +1209,12 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, else if (cris_get_mode (insn) == 0x0002 && cris_get_opcode (insn) == 0x000F && cris_get_size (insn) == 0x0003 - && cris_get_operand1 (insn) == SP_REGNUM) + && cris_get_operand1 (insn) == gdbarch_sp_regnum (gdbarch)) { /* movem r,[sp] */ regsave = cris_get_operand2 (insn); } - else if (cris_get_operand2 (insn) == SP_REGNUM + else if (cris_get_operand2 (insn) == gdbarch_sp_regnum (gdbarch) && ((insn & 0x0F00) >> 8) == 0x0001 && (cris_get_signed_offset (insn) < 0)) { @@ -1181,7 +1231,8 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, 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) + && cris_get_operand1 (insn_next) == gdbarch_sp_regnum + (gdbarch)) { regsave = cris_get_operand2 (insn_next); } @@ -1223,7 +1274,7 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, insn_next = read_memory_unsigned_integer (pc, 2); pc += 2; regno = cris_get_operand2 (insn_next); - if ((regno >= 0 && regno < SP_REGNUM) + if ((regno >= 0 && regno < gdbarch_sp_regnum (gdbarch)) && cris_get_mode (insn_next) == PREFIX_OFFSET_MODE && cris_get_opcode (insn_next) == 0x000F) { @@ -1247,7 +1298,7 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, insn_next = read_memory_unsigned_integer (pc, 2); pc += 2; regno = cris_get_operand2 (insn_next); - if ((regno >= 0 && regno < SP_REGNUM) + if ((regno >= 0 && regno < gdbarch_sp_regnum (gdbarch)) && cris_get_mode (insn_next) == PREFIX_OFFSET_MODE && cris_get_opcode (insn_next) == 0x0009 && cris_get_operand1 (insn_next) == regno) @@ -1287,8 +1338,7 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, /* 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); + this_base = frame_unwind_register_unsigned (next_frame, CRIS_FP_REGNUM); info->base = this_base; info->saved_regs[CRIS_FP_REGNUM].addr = info->base; @@ -1301,7 +1351,8 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, 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); + this_base = frame_unwind_register_unsigned (next_frame, + gdbarch_sp_regnum (gdbarch)); info->base = this_base; info->prev_sp = info->base + info->size; } @@ -1320,7 +1371,8 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, /* 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); + trad_frame_set_value (info->saved_regs, + gdbarch_sp_regnum (gdbarch), info->prev_sp); if (!info->leaf_function) { @@ -1338,7 +1390,47 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, } /* The PC is found in SRP (the actual register or located on the stack). */ - info->saved_regs[PC_REGNUM] = info->saved_regs[SRP_REGNUM]; + info->saved_regs[gdbarch_pc_regnum (gdbarch)] + = info->saved_regs[SRP_REGNUM]; + + return pc; +} + +static CORE_ADDR +crisv32_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame, + struct cris_unwind_cache *info) +{ + struct gdbarch *gdbarch = get_frame_arch (next_frame); + ULONGEST this_base; + + /* Unlike the CRISv10 prologue scanner (cris_scan_prologue), this is not + meant to be a full-fledged prologue scanner. It is only needed for + the cases where we end up in code always lacking DWARF-2 CFI, notably: + + * PLT stubs (library calls) + * call dummys + * signal trampolines + + For those cases, it is assumed that there is no actual prologue; that + the stack pointer is not adjusted, and (as a consequence) the return + address is not pushed onto the stack. */ + + /* 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; + } + + /* The SP is assumed to be unaltered. */ + this_base = frame_unwind_register_unsigned (next_frame, + gdbarch_sp_regnum (gdbarch)); + info->base = this_base; + info->prev_sp = this_base; + + /* The PC is assumed to be found in SRP. */ + info->saved_regs[gdbarch_pc_regnum (gdbarch)] + = info->saved_regs[SRP_REGNUM]; return pc; } @@ -1365,7 +1457,11 @@ cris_skip_prologue (CORE_ADDR pc) return sal.end; } - pc_after_prologue = cris_scan_prologue (pc, NULL, NULL); + if (cris_version () == 32) + pc_after_prologue = crisv32_scan_prologue (pc, NULL, NULL); + else + pc_after_prologue = cris_scan_prologue (pc, NULL, NULL); + return pc_after_prologue; } @@ -1373,7 +1469,8 @@ 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); + pc = frame_unwind_register_unsigned (next_frame, + gdbarch_pc_regnum (gdbarch)); return pc; } @@ -1381,7 +1478,8 @@ 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); + sp = frame_unwind_register_unsigned (next_frame, + gdbarch_sp_regnum (gdbarch)); return sp; } @@ -1392,12 +1490,16 @@ cris_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) the breakpoint should be inserted. */ static const unsigned char * -cris_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) +cris_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr) { - static unsigned char break_insn[] = {0x38, 0xe9}; + static unsigned char break8_insn[] = {0x38, 0xe9}; + static unsigned char break15_insn[] = {0x3f, 0xe9}; *lenptr = 2; - return break_insn; + if (cris_mode () == cris_mode_guru) + return break15_insn; + else + return break8_insn; } /* Returns 1 if spec_reg is applicable to the current gdbarch's CRIS version, @@ -1472,7 +1574,8 @@ cris_register_size (int regno) /* Special register not applicable to this CRIS version. */ return 0; } - else if (regno >= PC_REGNUM && regno < NUM_REGS) + else if (regno >= gdbarch_pc_regnum (current_gdbarch) + && regno < gdbarch_num_regs (current_gdbarch)) { /* This will apply to CRISv32 only where there are additional registers after the special registers (pseudo PC and support registers). */ @@ -1487,9 +1590,9 @@ cris_register_size (int regno) for unimplemented (size 0) and non-existant registers. */ static int -cris_cannot_fetch_register (int regno) +cris_cannot_fetch_register (struct gdbarch *gdbarch, int regno) { - return ((regno < 0 || regno >= NUM_REGS) + return ((regno < 0 || regno >= gdbarch_num_regs (gdbarch)) || (cris_register_size (regno) == 0)); } @@ -1497,7 +1600,7 @@ cris_cannot_fetch_register (int regno) reasons. */ static int -cris_cannot_store_register (int regno) +cris_cannot_store_register (struct gdbarch *gdbarch, int regno) { /* There are three kinds of registers we refuse to write to. 1. Those that not implemented. @@ -1505,7 +1608,9 @@ cris_cannot_store_register (int regno) 3. Those registers to which a write has no effect. */ - if (regno < 0 || regno >= NUM_REGS || cris_register_size (regno) == 0) + if (regno < 0 + || regno >= gdbarch_num_regs (gdbarch) + || cris_register_size (regno) == 0) /* Not implemented. */ return 1; @@ -1527,9 +1632,9 @@ cris_cannot_store_register (int regno) for unimplemented (size 0) and non-existant registers. */ static int -crisv32_cannot_fetch_register (int regno) +crisv32_cannot_fetch_register (struct gdbarch *gdbarch, int regno) { - return ((regno < 0 || regno >= NUM_REGS) + return ((regno < 0 || regno >= gdbarch_num_regs (gdbarch)) || (cris_register_size (regno) == 0)); } @@ -1537,7 +1642,7 @@ crisv32_cannot_fetch_register (int regno) reasons. */ static int -crisv32_cannot_store_register (int regno) +crisv32_cannot_store_register (struct gdbarch *gdbarch, int regno) { /* There are three kinds of registers we refuse to write to. 1. Those that not implemented. @@ -1545,7 +1650,9 @@ crisv32_cannot_store_register (int regno) 3. Those registers to which a write has no effect. */ - if (regno < 0 || regno >= NUM_REGS || cris_register_size (regno) == 0) + if (regno < 0 + || regno >= gdbarch_num_regs (gdbarch) + || cris_register_size (regno) == 0) /* Not implemented. */ return 1; @@ -1569,11 +1676,12 @@ crisv32_cannot_store_register (int regno) static struct type * cris_register_type (struct gdbarch *gdbarch, int regno) { - if (regno == PC_REGNUM) + if (regno == gdbarch_pc_regnum (gdbarch)) return builtin_type_void_func_ptr; - else if (regno == SP_REGNUM || regno == CRIS_FP_REGNUM) + else if (regno == gdbarch_sp_regnum (gdbarch) + || regno == CRIS_FP_REGNUM) return builtin_type_void_data_ptr; - else if ((regno >= 0 && regno < SP_REGNUM) + else if ((regno >= 0 && regno < gdbarch_sp_regnum (gdbarch)) || (regno >= MOF_REGNUM && regno <= USP_REGNUM)) /* Note: R8 taken care of previous clause. */ return builtin_type_uint32; @@ -1589,9 +1697,10 @@ cris_register_type (struct gdbarch *gdbarch, int regno) static struct type * crisv32_register_type (struct gdbarch *gdbarch, int regno) { - if (regno == PC_REGNUM) + if (regno == gdbarch_pc_regnum (gdbarch)) return builtin_type_void_func_ptr; - else if (regno == SP_REGNUM || regno == CRIS_FP_REGNUM) + else if (regno == gdbarch_sp_regnum (gdbarch) + || regno == CRIS_FP_REGNUM) return builtin_type_void_data_ptr; else if ((regno >= 0 && regno <= ACR_REGNUM) || (regno >= EXS_REGNUM && regno <= SPC_REGNUM) @@ -1669,7 +1778,7 @@ cris_special_register_name (int regno) } static const char * -cris_register_name (int regno) +cris_register_name (struct gdbarch *gdbarch, int regno) { static char *cris_genreg_names[] = { "r0", "r1", "r2", "r3", \ @@ -1682,7 +1791,7 @@ cris_register_name (int regno) /* General register. */ return cris_genreg_names[regno]; } - else if (regno >= NUM_GENREGS && regno < NUM_REGS) + else if (regno >= NUM_GENREGS && regno < gdbarch_num_regs (gdbarch)) { return cris_special_register_name (regno); } @@ -1694,7 +1803,7 @@ cris_register_name (int regno) } static const char * -crisv32_register_name (int regno) +crisv32_register_name (struct gdbarch *gdbarch, int regno) { static char *crisv32_genreg_names[] = { "r0", "r1", "r2", "r3", \ @@ -1719,7 +1828,7 @@ crisv32_register_name (int regno) { return cris_special_register_name (regno); } - else if (regno == PC_REGNUM) + else if (regno == gdbarch_pc_regnum (gdbarch)) { return "pc"; } @@ -1738,7 +1847,7 @@ crisv32_register_name (int regno) number used by GDB. */ static int -cris_dwarf2_reg_to_regnum (int reg) +cris_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int reg) { /* We need to re-map a couple of registers (SRP is 16 in Dwarf-2 register numbering, MOF is 18). @@ -1768,14 +1877,15 @@ cris_dwarf2_reg_to_regnum (int reg) static void cris_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, - struct dwarf2_frame_state_reg *reg) + struct dwarf2_frame_state_reg *reg, + struct frame_info *next_frame) { /* The return address column. */ - if (regnum == PC_REGNUM) + if (regnum == gdbarch_pc_regnum (gdbarch)) reg->how = DWARF2_FRAME_REG_RA; /* The call frame address. */ - else if (regnum == SP_REGNUM) + else if (regnum == gdbarch_sp_regnum (gdbarch)) reg->how = DWARF2_FRAME_REG_CFA; } @@ -1814,8 +1924,8 @@ cris_extract_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention cris_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, void *readbuf, - const void *writebuf) + struct regcache *regcache, gdb_byte *readbuf, + const gdb_byte *writebuf) { if (TYPE_CODE (type) == TYPE_CODE_STRUCT || TYPE_CODE (type) == TYPE_CODE_UNION @@ -1832,18 +1942,6 @@ cris_return_value (struct gdbarch *gdbarch, struct type *type, 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 instruction. It stems from cris_constraint, found in cris-dis.c. */ @@ -1977,21 +2075,24 @@ find_cris_op (unsigned short insn, inst_env_type *inst_env) actually an internal error. */ static int -find_step_target (inst_env_type *inst_env) +find_step_target (struct frame_info *frame, inst_env_type *inst_env) { int i; int offset; unsigned short insn; + struct gdbarch *gdbarch = get_frame_arch (frame); /* Create a local register image and set the initial state. */ for (i = 0; i < NUM_GENREGS; i++) { - inst_env->reg[i] = (unsigned long) read_register (i); + inst_env->reg[i] = + (unsigned long) get_frame_register_unsigned (frame, i); } offset = NUM_GENREGS; for (i = 0; i < NUM_SPECREGS; i++) { - inst_env->preg[i] = (unsigned long) read_register (offset + i); + inst_env->preg[i] = + (unsigned long) get_frame_register_unsigned (frame, offset + i); } inst_env->branch_found = 0; inst_env->slot_needed = 0; @@ -2005,7 +2106,8 @@ find_step_target (inst_env_type *inst_env) do { /* Read an instruction from the client. */ - insn = read_memory_unsigned_integer (inst_env->reg[PC_REGNUM], 2); + insn = read_memory_unsigned_integer + (inst_env->reg[gdbarch_pc_regnum (gdbarch)], 2); /* If the instruction is not in a delay slot the new content of the PC is [PC] + 2. If the instruction is in a delay slot it is not @@ -2014,12 +2116,13 @@ find_step_target (inst_env_type *inst_env) Just make sure it is a valid instruction. */ if (!inst_env->delay_slot_pc_active) { - inst_env->reg[PC_REGNUM] += 2; + inst_env->reg[gdbarch_pc_regnum (gdbarch)] += 2; } else { inst_env->delay_slot_pc_active = 0; - inst_env->reg[PC_REGNUM] = inst_env->delay_slot_pc; + inst_env->reg[gdbarch_pc_regnum (gdbarch)] + = inst_env->delay_slot_pc; } /* Analyse the present instruction. */ i = find_cris_op (insn, inst_env); @@ -2041,48 +2144,37 @@ 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. */ -static void -cris_software_single_step (enum target_signal ignore, int insert_breakpoints) +static int +cris_software_single_step (struct frame_info *frame) { inst_env_type inst_env; - - if (insert_breakpoints) + + /* Analyse the present instruction environment and insert + breakpoints. */ + int status = find_step_target (frame, &inst_env); + if (status == -1) { - /* Analyse the present instruction environment and insert - breakpoints. */ - int status = find_step_target (&inst_env); - if (status == -1) - { - /* 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 - { - /* Insert at most two breakpoints. One for the next PC content - and possibly another one for a branch, jump, etc. */ - next_pc = (CORE_ADDR) inst_env.reg[PC_REGNUM]; - target_insert_breakpoint (next_pc, break_mem[0]); - if (inst_env.branch_found - && (CORE_ADDR) inst_env.branch_break_address != next_pc) - { - branch_target_address = - (CORE_ADDR) inst_env.branch_break_address; - target_insert_breakpoint (branch_target_address, break_mem[1]); - branch_break_inserted = 1; - } - } + /* 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 { - /* Remove breakpoints. */ - target_remove_breakpoint (next_pc, break_mem[0]); - if (branch_break_inserted) - { - target_remove_breakpoint (branch_target_address, break_mem[1]); - branch_break_inserted = 0; - } + /* Insert at most two breakpoints. One for the next PC content + and possibly another one for a branch, jump, etc. */ + CORE_ADDR next_pc = + (CORE_ADDR) inst_env.reg[gdbarch_pc_regnum (get_frame_arch (frame))]; + insert_single_step_breakpoint (next_pc); + if (inst_env.branch_found + && (CORE_ADDR) inst_env.branch_break_address != next_pc) + { + CORE_ADDR branch_target_address + = (CORE_ADDR) inst_env.branch_break_address; + insert_single_step_breakpoint (branch_target_address); + } } + + return 1; } /* Calculates the prefix value for quick offset addressing mode. */ @@ -3790,9 +3882,10 @@ typedef elf_greg_t crisv32_elf_gregset_t[CRISV32_ELF_NGREG]; /* Unpack an elf_gregset_t into GDB's register cache. */ static void -supply_gregset (elf_gregset_t *gregsetp) +cris_supply_gregset (struct regcache *regcache, elf_gregset_t *gregsetp) { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int i; elf_greg_t *regp = *gregsetp; static char zerobuf[4] = {0}; @@ -3801,7 +3894,7 @@ 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++) { - regcache_raw_supply (current_regcache, i, (char *)®p[i]); + regcache_raw_supply (regcache, i, (char *)®p[i]); } if (tdep->cris_version == 32) @@ -3809,7 +3902,7 @@ supply_gregset (elf_gregset_t *gregsetp) /* 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, + regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch), (char *)®p[ERP_REGNUM]); if (*(char *)®p[ERP_REGNUM] & 0x1) @@ -3821,7 +3914,8 @@ supply_gregset (elf_gregset_t *gregsetp) regsets, until multi-arch core support is ready. */ static void -fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, +fetch_core_registers (struct regcache *regcache, + char *core_reg_sect, unsigned core_reg_size, int which, CORE_ADDR reg_addr) { elf_gregset_t gregset; @@ -3837,7 +3931,7 @@ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, else { memcpy (&gregset, core_reg_sect, sizeof (gregset)); - supply_gregset (&gregset); + cris_supply_gregset (regcache, &gregset); } default: @@ -3857,50 +3951,6 @@ static struct core_fns cris_elf_core_fns = NULL /* next */ }; -/* Fetch (and possibly build) an appropriate link_map_offsets - structure for native GNU/Linux CRIS targets using the struct - offsets defined in link.h (but without actual reference to that - file). - - This makes it possible to access GNU/Linux CRIS shared libraries - from a GDB that was not built on an GNU/Linux CRIS host (for cross - debugging). - - See gdb/solib-svr4.h for an explanation of these fields. */ - -static struct link_map_offsets * -cris_linux_svr4_fetch_link_map_offsets (void) -{ - static struct link_map_offsets lmo; - static struct link_map_offsets *lmp = NULL; - - if (lmp == NULL) - { - lmp = &lmo; - - lmo.r_debug_size = 8; /* The actual size is 20 bytes, but - this is all we need. */ - lmo.r_map_offset = 4; - lmo.r_map_size = 4; - - lmo.link_map_size = 20; - - lmo.l_addr_offset = 0; - lmo.l_addr_size = 4; - - lmo.l_name_offset = 4; - lmo.l_name_size = 4; - - lmo.l_next_offset = 12; - lmo.l_next_size = 4; - - lmo.l_prev_offset = 16; - lmo.l_prev_size = 4; - } - - return lmp; -} - extern initialize_file_ftype _initialize_cris_tdep; /* -Wmissing-prototypes */ void @@ -3916,20 +3966,33 @@ _initialize_cris_tdep (void) /* CRIS-specific user-commands. */ 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.", - NULL, /* PRINT: Current CRIS version is %s. */ - set_cris_version, NULL, + _("Set the current CRIS version."), + _("Show the current CRIS version."), + _("\ +Set to 10 for CRISv10 or 32 for CRISv32 if autodetection fails.\n\ +Defaults to 10. "), + set_cris_version, + NULL, /* FIXME: i18n: Current CRIS version is %s. */ &setlist, &showlist); + + add_setshow_enum_cmd ("cris-mode", class_support, + cris_modes, &usr_cmd_cris_mode, + _("Set the current CRIS mode."), + _("Show the current CRIS mode."), + _("\ +Set to CRIS_MODE_GURU when debugging in guru mode.\n\ +Makes GDB use the NRP register instead of the ERP register in certain cases."), + set_cris_mode, + NULL, /* FIXME: i18n: Current CRIS version is %s. */ + &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.", - NULL, /* PRINT: Usage of Dwarf-2 CFI for CRIS is %d. */ - set_cris_dwarf2_cfi, NULL, + _("Set the usage of Dwarf-2 CFI for CRIS."), + _("Show the usage of Dwarf-2 CFI for CRIS."), + _("Set this to \"off\" if using gcc-cris < R59."), + set_cris_dwarf2_cfi, + NULL, /* FIXME: i18n: Usage of Dwarf-2 CFI for CRIS is %d. */ &setlist, &showlist); deprecated_add_core_fns (&cris_elf_core_fns); @@ -3940,11 +4003,13 @@ _initialize_cris_tdep (void) static void cris_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file) { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (tdep != NULL) { fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_version = %i\n", tdep->cris_version); + fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_mode = %s\n", + tdep->cris_mode); fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_dwarf2_cfi = %i\n", tdep->cris_dwarf2_cfi); } @@ -3958,6 +4023,19 @@ set_cris_version (char *ignore_args, int from_tty, 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 +set_cris_mode (char *ignore_args, int from_tty, + struct cmd_list_element *c) +{ + struct gdbarch_info info; + /* Update the current architecture, if needed. */ gdbarch_info_init (&info); if (!gdbarch_update_p (info)) @@ -3975,7 +4053,7 @@ set_cris_dwarf2_cfi (char *ignore_args, int from_tty, gdbarch_info_init (&info); if (!gdbarch_update_p (info)) internal_error (__FILE__, __LINE__, - "cris_gdbarch_update: failed to update architecture."); + _("cris_gdbarch_update: failed to update architecture.")); } static struct gdbarch * @@ -4003,14 +4081,15 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Make the current settings visible to the user. */ usr_cmd_cris_version = cris_version; - /* Find a candidate among the list of pre-declared architectures. Both - CRIS version and ABI must match. */ + /* Find a candidate among the list of pre-declared architectures. */ for (arches = gdbarch_list_lookup_by_info (arches, &info); arches != NULL; arches = gdbarch_list_lookup_by_info (arches->next, &info)) { if ((gdbarch_tdep (arches->gdbarch)->cris_version == usr_cmd_cris_version) + && (gdbarch_tdep (arches->gdbarch)->cris_mode + == usr_cmd_cris_mode) && (gdbarch_tdep (arches->gdbarch)->cris_dwarf2_cfi == usr_cmd_cris_dwarf2_cfi)) return arches->gdbarch; @@ -4021,6 +4100,7 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) gdbarch = gdbarch_alloc (&info, tdep); tdep->cris_version = usr_cmd_cris_version; + tdep->cris_mode = usr_cmd_cris_mode; tdep->cris_dwarf2_cfi = usr_cmd_cris_dwarf2_cfi; /* INIT shall ensure that the INFO.BYTE_ORDER is non-zero. */ @@ -4031,17 +4111,14 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) break; case BFD_ENDIAN_BIG: - internal_error (__FILE__, __LINE__, "cris_gdbarch_init: big endian byte order in info"); + internal_error (__FILE__, __LINE__, _("cris_gdbarch_init: big endian byte order in info")); break; default: - internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown byte order in info"); + internal_error (__FILE__, __LINE__, _("cris_gdbarch_init: unknown byte order in info")); } 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); set_gdbarch_sp_regnum (gdbarch, 14); @@ -4050,13 +4127,13 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) register is. */ set_gdbarch_double_bit (gdbarch, 64); - /* The default definition of a long double is 2 * TARGET_DOUBLE_BIT, + /* The default definition of a long double is 2 * gdbarch_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 - cris_register_size at this point, since it relies on current_gdbarch + cris_register_size at this point, since it relies on gdbarch being set. */ switch (tdep->cris_version) { @@ -4068,7 +4145,7 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) case 9: /* Old versions; not supported. */ internal_error (__FILE__, __LINE__, - "cris_gdbarch_init: unsupported CRIS version"); + _("cris_gdbarch_init: unsupported CRIS version")); break; case 10: @@ -4110,7 +4187,7 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) default: internal_error (__FILE__, __LINE__, - "cris_gdbarch_init: unknown CRIS version"); + _("cris_gdbarch_init: unknown CRIS version")); } /* Dummy frame functions (shared between CRISv10 and CRISv32 since they @@ -4137,14 +4214,16 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer); } - frame_unwind_append_sniffer (gdbarch, cris_sigtramp_frame_sniffer); + if (tdep->cris_mode != cris_mode_guru) + { + frame_unwind_append_sniffer (gdbarch, cris_sigtramp_frame_sniffer); + } frame_unwind_append_sniffer (gdbarch, cris_frame_sniffer); frame_base_set_default (gdbarch, &cris_frame_base); - /* Use target_specific function to define link map offsets. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, cris_linux_svr4_fetch_link_map_offsets); + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_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