X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Frx-tdep.c;h=45cc8b453564c7b3562693ead03120d2a868d10c;hb=cedfc77485dbb566619dc1e2d729ce0a70d1a4ad;hp=de9eec634829068d77987031569d4e3c6ba2af68;hpb=fd60dc691fb51f108b1e74025e4a2751dced8d32;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/rx-tdep.c b/gdb/rx-tdep.c index de9eec6348..45cc8b4535 100644 --- a/gdb/rx-tdep.c +++ b/gdb/rx-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for the Renesas RX for GDB, the GNU debugger. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008-2019 Free Software Foundation, Inc. Contributed by Red Hat, Inc. @@ -33,9 +33,14 @@ #include "value.h" #include "gdbcore.h" #include "dwarf2-frame.h" +#include "remote.h" +#include "target-descriptions.h" #include "elf/rx.h" #include "elf-bfd.h" +#include + +#include "features/rx.c" /* Certain important register numbers. */ enum @@ -45,21 +50,43 @@ enum RX_R4_REGNUM = 4, RX_FP_REGNUM = 6, RX_R15_REGNUM = 15, + RX_USP_REGNUM = 16, + RX_PSW_REGNUM = 18, RX_PC_REGNUM = 19, + RX_BPSW_REGNUM = 21, + RX_BPC_REGNUM = 22, + RX_FPSW_REGNUM = 24, RX_ACC_REGNUM = 25, RX_NUM_REGS = 26 }; +/* RX frame types. */ +enum rx_frame_type { + RX_FRAME_TYPE_NORMAL, + RX_FRAME_TYPE_EXCEPTION, + RX_FRAME_TYPE_FAST_INTERRUPT +}; + /* Architecture specific data. */ struct gdbarch_tdep { /* The ELF header flags specify the multilib used. */ int elf_flags; + + /* Type of PSW and BPSW. */ + struct type *rx_psw_type; + + /* Type of FPSW. */ + struct type *rx_fpsw_type; }; /* This structure holds the results of a prologue analysis. */ struct rx_prologue { + /* Frame type, either a normal frame or one of two types of exception + frames. */ + enum rx_frame_type frame_type; + /* The offset from the frame base to the stack pointer --- always zero or negative. @@ -91,57 +118,17 @@ struct rx_prologue int reg_offset[RX_NUM_REGS]; }; -/* Implement the "register_name" gdbarch method. */ -static const char * -rx_register_name (struct gdbarch *gdbarch, int regnr) -{ - static const char *const reg_names[] = { - "r0", - "r1", - "r2", - "r3", - "r4", - "r5", - "r6", - "r7", - "r8", - "r9", - "r10", - "r11", - "r12", - "r13", - "r14", - "r15", - "usp", - "isp", - "psw", - "pc", - "intb", - "bpsw", - "bpc", - "fintv", - "fpsw", - "acc" - }; - - return reg_names[regnr]; -} - -/* Implement the "register_type" gdbarch method. */ -static struct type * -rx_register_type (struct gdbarch *gdbarch, int reg_nr) -{ - if (reg_nr == RX_PC_REGNUM) - return builtin_type (gdbarch)->builtin_func_ptr; - else if (reg_nr == RX_ACC_REGNUM) - return builtin_type (gdbarch)->builtin_unsigned_long_long; - else - return builtin_type (gdbarch)->builtin_unsigned_long; -} +/* RX register names */ +static const char *const rx_register_names[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "usp", "isp", "psw", "pc", "intb", "bpsw","bpc","fintv", + "fpsw", "acc", +}; /* Function for finding saved registers in a 'struct pv_area'; this - function is passed to pv_area_scan. + function is passed to pv_area::scan. If VALUE is a saved register, ADDR says it was saved at a constant offset from the frame base, and SIZE indicates that the whole @@ -154,7 +141,7 @@ check_for_saved (void *result_untyped, pv_t addr, CORE_ADDR size, pv_t value) if (value.kind == pvk_register && value.k == 0 && pv_is_register (addr, RX_SP_REGNUM) - && size == register_size (target_gdbarch, value.reg)) + && size == register_size (target_gdbarch (), value.reg)) result->reg_offset[value.reg] = addr.k; } @@ -172,11 +159,12 @@ struct rx_get_opcode_byte_handle static int rx_get_opcode_byte (void *handle) { - struct rx_get_opcode_byte_handle *opcdata = handle; + struct rx_get_opcode_byte_handle *opcdata + = (struct rx_get_opcode_byte_handle *) handle; int status; gdb_byte byte; - status = target_read_memory (opcdata->pc, &byte, 1); + status = target_read_code (opcdata->pc, &byte, 1); if (status == 0) { opcdata->pc += 1; @@ -188,31 +176,53 @@ rx_get_opcode_byte (void *handle) /* Analyze a prologue starting at START_PC, going no further than LIMIT_PC. Fill in RESULT as appropriate. */ + static void -rx_analyze_prologue (CORE_ADDR start_pc, - CORE_ADDR limit_pc, struct rx_prologue *result) +rx_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc, + enum rx_frame_type frame_type, + struct rx_prologue *result) { CORE_ADDR pc, next_pc; int rn; pv_t reg[RX_NUM_REGS]; - struct pv_area *stack; - struct cleanup *back_to; CORE_ADDR after_last_frame_setup_insn = start_pc; memset (result, 0, sizeof (*result)); + result->frame_type = frame_type; + for (rn = 0; rn < RX_NUM_REGS; rn++) { reg[rn] = pv_register (rn, 0); result->reg_offset[rn] = 1; } - stack = make_pv_area (RX_SP_REGNUM, gdbarch_addr_bit (target_gdbarch)); - back_to = make_cleanup_free_pv_area (stack); + pv_area stack (RX_SP_REGNUM, gdbarch_addr_bit (target_gdbarch ())); + + if (frame_type == RX_FRAME_TYPE_FAST_INTERRUPT) + { + /* This code won't do anything useful at present, but this is + what happens for fast interrupts. */ + reg[RX_BPSW_REGNUM] = reg[RX_PSW_REGNUM]; + reg[RX_BPC_REGNUM] = reg[RX_PC_REGNUM]; + } + else + { + /* When an exception occurs, the PSW is saved to the interrupt stack + first. */ + if (frame_type == RX_FRAME_TYPE_EXCEPTION) + { + reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4); + stack.store (reg[RX_SP_REGNUM], 4, reg[RX_PSW_REGNUM]); + } + + /* The call instruction (or an exception/interrupt) has saved the return + address on the stack. */ + reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4); + stack.store (reg[RX_SP_REGNUM], 4, reg[RX_PC_REGNUM]); + + } - /* The call instruction has saved the return address on the stack. */ - reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4); - pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[RX_PC_REGNUM]); pc = start_pc; while (pc < limit_pc) @@ -238,7 +248,7 @@ rx_analyze_prologue (CORE_ADDR start_pc, for (r = r2; r >= r1; r--) { reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4); - pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[r]); + stack.store (reg[RX_SP_REGNUM], 4, reg[r]); } after_last_frame_setup_insn = next_pc; } @@ -265,7 +275,7 @@ rx_analyze_prologue (CORE_ADDR start_pc, rsrc = opc.op[1].reg; reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4); - pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[rsrc]); + stack.store (reg[RX_SP_REGNUM], 4, reg[rsrc]); after_last_frame_setup_insn = next_pc; } else if (opc.id == RXO_add /* add #const, rsrc, rdst */ @@ -296,7 +306,6 @@ rx_analyze_prologue (CORE_ADDR start_pc, } else if (opc.id == RXO_branch && opc.op[0].type == RX_Operand_Immediate - && opc.op[1].type == RX_Operand_Condition && next_pc < opc.op[0].addend) { /* When a loop appears as the first statement of a function @@ -342,11 +351,9 @@ rx_analyze_prologue (CORE_ADDR start_pc, } /* Record where all the registers were saved. */ - pv_area_scan (stack, check_for_saved, (void *) result); + stack.scan (check_for_saved, (void *) result); result->prologue_end = after_last_frame_setup_insn; - - do_cleanups (back_to); } @@ -354,7 +361,7 @@ rx_analyze_prologue (CORE_ADDR start_pc, static CORE_ADDR rx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { - char *name; + const char *name; CORE_ADDR func_addr, func_end; struct rx_prologue p; @@ -362,7 +369,9 @@ rx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) if (!find_pc_partial_function (pc, &name, &func_addr, &func_end)) return pc; - rx_analyze_prologue (pc, func_end, &p); + /* The frame type doesn't matter here, since we only care about + where the prologue ends. We'll use RX_FRAME_TYPE_NORMAL. */ + rx_analyze_prologue (pc, func_end, RX_FRAME_TYPE_NORMAL, &p); return p.prologue_end; } @@ -370,8 +379,10 @@ rx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) associated function if there is not cache entry as specified by THIS_PROLOGUE_CACHE. Save the decoded prologue in the cache and return that struct as the value of this function. */ + static struct rx_prologue * rx_analyze_frame_prologue (struct frame_info *this_frame, + enum rx_frame_type frame_type, void **this_prologue_cache) { if (!*this_prologue_cache) @@ -388,19 +399,76 @@ rx_analyze_frame_prologue (struct frame_info *this_frame, if (!func_start) stop_addr = func_start; - rx_analyze_prologue (func_start, stop_addr, *this_prologue_cache); + rx_analyze_prologue (func_start, stop_addr, frame_type, + (struct rx_prologue *) *this_prologue_cache); } - return *this_prologue_cache; + return (struct rx_prologue *) *this_prologue_cache; } +/* Determine type of frame by scanning the function for a return + instruction. */ + +static enum rx_frame_type +rx_frame_type (struct frame_info *this_frame, void **this_cache) +{ + const char *name; + CORE_ADDR pc, start_pc, lim_pc; + int bytes_read; + struct rx_get_opcode_byte_handle opcode_handle; + RX_Opcode_Decoded opc; + + gdb_assert (this_cache != NULL); + + /* If we have a cached value, return it. */ + + if (*this_cache != NULL) + { + struct rx_prologue *p = (struct rx_prologue *) *this_cache; + + return p->frame_type; + } + + /* No cached value; scan the function. The frame type is cached in + rx_analyze_prologue / rx_analyze_frame_prologue. */ + + pc = get_frame_pc (this_frame); + + /* Attempt to find the last address in the function. If it cannot + be determined, set the limit to be a short ways past the frame's + pc. */ + if (!find_pc_partial_function (pc, &name, &start_pc, &lim_pc)) + lim_pc = pc + 20; + + while (pc < lim_pc) + { + opcode_handle.pc = pc; + bytes_read = rx_decode_opcode (pc, &opc, rx_get_opcode_byte, + &opcode_handle); + + if (bytes_read <= 0 || opc.id == RXO_rts) + return RX_FRAME_TYPE_NORMAL; + else if (opc.id == RXO_rtfi) + return RX_FRAME_TYPE_FAST_INTERRUPT; + else if (opc.id == RXO_rte) + return RX_FRAME_TYPE_EXCEPTION; + + pc += bytes_read; + } + + return RX_FRAME_TYPE_NORMAL; +} + + /* Given the next frame and a prologue cache, return this frame's base. */ + static CORE_ADDR -rx_frame_base (struct frame_info *this_frame, void **this_prologue_cache) +rx_frame_base (struct frame_info *this_frame, void **this_cache) { + enum rx_frame_type frame_type = rx_frame_type (this_frame, this_cache); struct rx_prologue *p - = rx_analyze_frame_prologue (this_frame, this_prologue_cache); + = rx_analyze_frame_prologue (this_frame, frame_type, this_cache); /* In functions that use alloca, the distance between the stack pointer and the frame base varies dynamically, so we can't use @@ -421,81 +489,174 @@ rx_frame_base (struct frame_info *this_frame, void **this_prologue_cache) } /* Implement the "frame_this_id" method for unwinding frames. */ + static void -rx_frame_this_id (struct frame_info *this_frame, - void **this_prologue_cache, struct frame_id *this_id) +rx_frame_this_id (struct frame_info *this_frame, void **this_cache, + struct frame_id *this_id) { - *this_id = frame_id_build (rx_frame_base (this_frame, this_prologue_cache), + *this_id = frame_id_build (rx_frame_base (this_frame, this_cache), get_frame_func (this_frame)); } /* Implement the "frame_prev_register" method for unwinding frames. */ + static struct value * -rx_frame_prev_register (struct frame_info *this_frame, - void **this_prologue_cache, int regnum) +rx_frame_prev_register (struct frame_info *this_frame, void **this_cache, + int regnum) { + enum rx_frame_type frame_type = rx_frame_type (this_frame, this_cache); struct rx_prologue *p - = rx_analyze_frame_prologue (this_frame, this_prologue_cache); - CORE_ADDR frame_base = rx_frame_base (this_frame, this_prologue_cache); - int reg_size = register_size (get_frame_arch (this_frame), regnum); + = rx_analyze_frame_prologue (this_frame, frame_type, this_cache); + CORE_ADDR frame_base = rx_frame_base (this_frame, this_cache); if (regnum == RX_SP_REGNUM) - return frame_unwind_got_constant (this_frame, regnum, frame_base); + { + if (frame_type == RX_FRAME_TYPE_EXCEPTION) + { + struct value *psw_val; + CORE_ADDR psw; + + psw_val = rx_frame_prev_register (this_frame, this_cache, + RX_PSW_REGNUM); + psw = extract_unsigned_integer (value_contents_all (psw_val), 4, + gdbarch_byte_order ( + get_frame_arch (this_frame))); + + if ((psw & 0x20000 /* U bit */) != 0) + return rx_frame_prev_register (this_frame, this_cache, + RX_USP_REGNUM); + + /* Fall through for the case where U bit is zero. */ + } + + return frame_unwind_got_constant (this_frame, regnum, frame_base); + } + + if (frame_type == RX_FRAME_TYPE_FAST_INTERRUPT) + { + if (regnum == RX_PC_REGNUM) + return rx_frame_prev_register (this_frame, this_cache, + RX_BPC_REGNUM); + if (regnum == RX_PSW_REGNUM) + return rx_frame_prev_register (this_frame, this_cache, + RX_BPSW_REGNUM); + } /* If prologue analysis says we saved this register somewhere, return a description of the stack slot holding it. */ - else if (p->reg_offset[regnum] != 1) + if (p->reg_offset[regnum] != 1) return frame_unwind_got_memory (this_frame, regnum, frame_base + p->reg_offset[regnum]); /* Otherwise, presume we haven't changed the value of this register, and get it from the next frame. */ - else - return frame_unwind_got_register (this_frame, regnum, regnum); + return frame_unwind_got_register (this_frame, regnum, regnum); } -static const struct frame_unwind rx_frame_unwind = { - NORMAL_FRAME, - rx_frame_this_id, - rx_frame_prev_register, - NULL, - default_frame_sniffer -}; +/* Return TRUE if the frame indicated by FRAME_TYPE is a normal frame. */ -/* Implement the "unwind_pc" gdbarch method. */ -static CORE_ADDR -rx_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame) +static int +normal_frame_p (enum rx_frame_type frame_type) { - ULONGEST pc; + return (frame_type == RX_FRAME_TYPE_NORMAL); +} + +/* Return TRUE if the frame indicated by FRAME_TYPE is an exception + frame. */ - pc = frame_unwind_register_unsigned (this_frame, RX_PC_REGNUM); - return pc; +static int +exception_frame_p (enum rx_frame_type frame_type) +{ + return (frame_type == RX_FRAME_TYPE_EXCEPTION + || frame_type == RX_FRAME_TYPE_FAST_INTERRUPT); } -/* Implement the "unwind_sp" gdbarch method. */ -static CORE_ADDR -rx_unwind_sp (struct gdbarch *gdbarch, struct frame_info *this_frame) +/* Common code used by both normal and exception frame sniffers. */ + +static int +rx_frame_sniffer_common (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache, + int (*sniff_p)(enum rx_frame_type) ) { - ULONGEST sp; + gdb_assert (this_cache != NULL); + + if (*this_cache == NULL) + { + enum rx_frame_type frame_type = rx_frame_type (this_frame, this_cache); + + if (sniff_p (frame_type)) + { + /* The call below will fill in the cache, including the frame + type. */ + (void) rx_analyze_frame_prologue (this_frame, frame_type, this_cache); + + return 1; + } + else + return 0; + } + else + { + struct rx_prologue *p = (struct rx_prologue *) *this_cache; + + return sniff_p (p->frame_type); + } +} - sp = frame_unwind_register_unsigned (this_frame, RX_SP_REGNUM); - return sp; +/* Frame sniffer for normal (non-exception) frames. */ + +static int +rx_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache) +{ + return rx_frame_sniffer_common (self, this_frame, this_cache, + normal_frame_p); } -/* Implement the "dummy_id" gdbarch method. */ -static struct frame_id -rx_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) +/* Frame sniffer for exception frames. */ + +static int +rx_exception_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache) { - return - frame_id_build (get_frame_register_unsigned (this_frame, RX_SP_REGNUM), - get_frame_pc (this_frame)); + return rx_frame_sniffer_common (self, this_frame, this_cache, + exception_frame_p); } +/* Data structure for normal code using instruction-based prologue + analyzer. */ + +static const struct frame_unwind rx_frame_unwind = { + NORMAL_FRAME, + default_frame_unwind_stop_reason, + rx_frame_this_id, + rx_frame_prev_register, + NULL, + rx_frame_sniffer +}; + +/* Data structure for exception code using instruction-based prologue + analyzer. */ + +static const struct frame_unwind rx_exception_unwind = { + /* SIGTRAMP_FRAME could be used here, but backtraces are less informative. */ + NORMAL_FRAME, + default_frame_unwind_stop_reason, + rx_frame_this_id, + rx_frame_prev_register, + NULL, + rx_exception_sniffer +}; + /* Implement the "push_dummy_call" gdbarch method. */ static CORE_ADDR rx_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, + struct value **args, CORE_ADDR sp, + function_call_return_method return_method, CORE_ADDR struct_addr) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); @@ -541,7 +702,7 @@ rx_push_dummy_call (struct gdbarch *gdbarch, struct value *function, sp = align_down (sp - sp_off, 4); sp_off = 0; - if (struct_return) + if (return_method == return_method_struct) { struct type *return_type = TYPE_TARGET_TYPE (func_type); @@ -565,7 +726,8 @@ rx_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct type *arg_type = check_typedef (value_type (arg)); ULONGEST arg_size = TYPE_LENGTH (arg_type); - if (i == 0 && struct_addr != 0 && !struct_return + if (i == 0 && struct_addr != 0 + && return_method != return_method_struct && TYPE_CODE (arg_type) == TYPE_CODE_PTR && extract_unsigned_integer (arg_bits, 4, byte_order) == struct_addr) @@ -578,7 +740,8 @@ rx_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct_addr); } else if (TYPE_CODE (arg_type) != TYPE_CODE_STRUCT - && TYPE_CODE (arg_type) != TYPE_CODE_UNION) + && TYPE_CODE (arg_type) != TYPE_CODE_UNION + && arg_size <= 8) { /* Argument is a scalar. */ if (arg_size == 8) @@ -661,7 +824,7 @@ rx_push_dummy_call (struct gdbarch *gdbarch, struct value *function, && arg_size <= 4 * (RX_R4_REGNUM - arg_reg + 1) && arg_size % 4 == 0) { - int len = min (arg_size, 4); + int len = std::min (arg_size, (ULONGEST) 4); if (write_pass) regcache_cooked_write_unsigned (regcache, arg_reg, @@ -702,7 +865,7 @@ rx_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Implement the "return_value" gdbarch method. */ static enum return_value_convention rx_return_value (struct gdbarch *gdbarch, - struct type *func_type, + struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) @@ -724,7 +887,7 @@ rx_return_value (struct gdbarch *gdbarch, while (valtype_len > 0) { - int len = min (valtype_len, 4); + int len = std::min (valtype_len, (ULONGEST) 4); regcache_cooked_read_unsigned (regcache, argreg, &u); store_unsigned_integer (readbuf + offset, len, byte_order, u); @@ -742,7 +905,7 @@ rx_return_value (struct gdbarch *gdbarch, while (valtype_len > 0) { - int len = min (valtype_len, 4); + int len = std::min (valtype_len, (ULONGEST) 4); u = extract_unsigned_integer (writebuf + offset, len, byte_order); regcache_cooked_write_unsigned (regcache, argreg, u); @@ -755,13 +918,23 @@ rx_return_value (struct gdbarch *gdbarch, return RETURN_VALUE_REGISTER_CONVENTION; } -/* Implement the "breakpoint_from_pc" gdbarch method. */ -const gdb_byte * -rx_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr) +constexpr gdb_byte rx_break_insn[] = { 0x00 }; + +typedef BP_MANIPULATION (rx_break_insn) rx_breakpoint; + +/* Implement the dwarf_reg_to_regnum" gdbarch method. */ + +static int +rx_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) { - static gdb_byte breakpoint[] = { 0x00 }; - *lenptr = sizeof breakpoint; - return breakpoint; + if (0 <= reg && reg <= 15) + return reg; + else if (reg == 16) + return RX_PSW_REGNUM; + else if (reg == 17) + return RX_PC_REGNUM; + else + return -1; } /* Allocate and initialize a gdbarch object. */ @@ -771,6 +944,8 @@ rx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) struct gdbarch *gdbarch; struct gdbarch_tdep *tdep; int elf_flags; + struct tdesc_arch_data *tdesc_data = NULL; + const struct target_desc *tdesc = info.target_desc; /* Extract the elf_flags if available. */ if (info.abfd != NULL @@ -792,28 +967,50 @@ rx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) return arches->gdbarch; } - /* None found, create a new architecture from the information - provided. */ - tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep)); + if (tdesc == NULL) + tdesc = tdesc_rx; + + /* Check any target description for validity. */ + if (tdesc_has_registers (tdesc)) + { + const struct tdesc_feature *feature; + bool valid_p = true; + + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.rx.core"); + + if (feature != NULL) + { + tdesc_data = tdesc_data_alloc (); + for (int i = 0; i < RX_NUM_REGS; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, i, + rx_register_names[i]); + } + + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + return NULL; + } + } + + gdb_assert(tdesc_data != NULL); + + tdep = XCNEW (struct gdbarch_tdep); gdbarch = gdbarch_alloc (&info, tdep); tdep->elf_flags = elf_flags; set_gdbarch_num_regs (gdbarch, RX_NUM_REGS); + tdesc_use_registers (gdbarch, tdesc, tdesc_data); + set_gdbarch_num_pseudo_regs (gdbarch, 0); - set_gdbarch_register_name (gdbarch, rx_register_name); - set_gdbarch_register_type (gdbarch, rx_register_type); set_gdbarch_pc_regnum (gdbarch, RX_PC_REGNUM); set_gdbarch_sp_regnum (gdbarch, RX_SP_REGNUM); set_gdbarch_inner_than (gdbarch, core_addr_lessthan); set_gdbarch_decr_pc_after_break (gdbarch, 1); - set_gdbarch_breakpoint_from_pc (gdbarch, rx_breakpoint_from_pc); + set_gdbarch_breakpoint_kind_from_pc (gdbarch, rx_breakpoint::kind_from_pc); + set_gdbarch_sw_breakpoint_from_kind (gdbarch, rx_breakpoint::bp_from_kind); set_gdbarch_skip_prologue (gdbarch, rx_skip_prologue); - set_gdbarch_print_insn (gdbarch, print_insn_rx); - - set_gdbarch_unwind_pc (gdbarch, rx_unwind_pc); - set_gdbarch_unwind_sp (gdbarch, rx_unwind_sp); - /* Target builtin data types. */ set_gdbarch_char_signed (gdbarch, 0); set_gdbarch_short_bit (gdbarch, 16); @@ -823,6 +1020,7 @@ rx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_ptr_bit (gdbarch, 32); set_gdbarch_float_bit (gdbarch, 32); set_gdbarch_float_format (gdbarch, floatformats_ieee_single); + if (elf_flags & E_FLAG_RX_64BIT_DOUBLES) { set_gdbarch_double_bit (gdbarch, 64); @@ -838,18 +1036,16 @@ rx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_long_double_format (gdbarch, floatformats_ieee_single); } + /* DWARF register mapping. */ + set_gdbarch_dwarf2_reg_to_regnum (gdbarch, rx_dwarf_reg_to_regnum); + /* Frame unwinding. */ -#if 0 - /* Note: The test results are better with the dwarf2 unwinder disabled, - so it's turned off for now. */ + frame_unwind_append_unwinder (gdbarch, &rx_exception_unwind); dwarf2_append_unwinders (gdbarch); -#endif frame_unwind_append_unwinder (gdbarch, &rx_frame_unwind); - /* Methods for saving / extracting a dummy frame's ID. - The ID's stack address must match the SP value returned by - PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos. */ - set_gdbarch_dummy_id (gdbarch, rx_dummy_id); + /* Methods setting up a dummy call, and extracting the return value from + a call. */ set_gdbarch_push_dummy_call (gdbarch, rx_push_dummy_call); set_gdbarch_return_value (gdbarch, rx_return_value); @@ -860,8 +1056,10 @@ rx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } /* Register the above initialization routine. */ + void _initialize_rx_tdep (void) { register_gdbarch_init (bfd_arch_rx, rx_gdbarch_init); + initialize_tdesc_rx (); }