X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fiq2000-tdep.c;h=43a4e7482a01a1505af14d43298c3cd21e996e42;hb=57d87c09a33acdce280f4c9ae4f55b885a5cee99;hp=fcb32d474846ae2aa4fa42757a89517be1e4bc1c;hpb=9b254dd1ce46c19dde1dde5b8d1e22e862dfacce;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/iq2000-tdep.c b/gdb/iq2000-tdep.c index fcb32d4748..43a4e7482a 100644 --- a/gdb/iq2000-tdep.c +++ b/gdb/iq2000-tdep.c @@ -1,7 +1,7 @@ /* Target-dependent code for the IQ2000 architecture, for GDB, the GNU Debugger. - Copyright (C) 2000, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2000-2020 Free Software Foundation, Inc. Contributed by Red Hat. @@ -28,7 +28,6 @@ #include "gdbtypes.h" #include "value.h" #include "dis-asm.h" -#include "gdb_string.h" #include "arch-utils.h" #include "regcache.h" #include "osabi.h" @@ -83,17 +82,20 @@ insn_addr_from_ptr (CORE_ADDR ptr) /* target_pointer to CORE_ADDR. */ } /* Function: pointer_to_address - Convert a target pointer to an address in host (CORE_ADDR) format. */ + Convert a target pointer to an address in host (CORE_ADDR) format. */ static CORE_ADDR -iq2000_pointer_to_address (struct type * type, const gdb_byte * buf) +iq2000_pointer_to_address (struct gdbarch *gdbarch, + struct type * type, const gdb_byte * buf) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type)); - CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type)); + CORE_ADDR addr + = extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order); if (target == TYPE_CODE_FUNC || target == TYPE_CODE_METHOD - || (TYPE_FLAGS (TYPE_TARGET_TYPE (type)) & TYPE_FLAG_CODE_SPACE) != 0) + || TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type))) addr = insn_addr_from_ptr (addr); return addr; @@ -103,13 +105,15 @@ iq2000_pointer_to_address (struct type * type, const gdb_byte * buf) Convert a host-format address (CORE_ADDR) into a target pointer. */ static void -iq2000_address_to_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr) +iq2000_address_to_pointer (struct gdbarch *gdbarch, + struct type *type, gdb_byte *buf, CORE_ADDR addr) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type)); if (target == TYPE_CODE_FUNC || target == TYPE_CODE_METHOD) addr = insn_ptr_from_addr (addr); - store_unsigned_integer (buf, TYPE_LENGTH (type), addr); + store_unsigned_integer (buf, TYPE_LENGTH (type), byte_order, addr); } /* Real register methods: */ @@ -192,16 +196,16 @@ find_last_line_symbol (CORE_ADDR start, CORE_ADDR end, int notcurrent) Returns the address of the first instruction after the prologue. */ static CORE_ADDR -iq2000_scan_prologue (CORE_ADDR scan_start, +iq2000_scan_prologue (struct gdbarch *gdbarch, + CORE_ADDR scan_start, CORE_ADDR scan_end, struct frame_info *fi, struct iq2000_frame_cache *cache) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct symtab_and_line sal; CORE_ADDR pc; CORE_ADDR loop_end; - int found_store_lr = 0; - int found_decr_sp = 0; int srcreg; int tgtreg; signed short offset; @@ -216,6 +220,8 @@ iq2000_scan_prologue (CORE_ADDR scan_start, loop_end = scan_end; if (fi) sal = find_last_line_symbol (scan_start, scan_end, 0); + else + sal.end = 0; /* Avoid GCC false warning. */ } /* Saved registers: @@ -223,7 +229,7 @@ iq2000_scan_prologue (CORE_ADDR scan_start, only later do we compute its actual address. Since the offset can be zero, we must first initialize all the saved regs to minus one (so we can later distinguish - between one that's not saved, and one that's saved at zero). */ + between one that's not saved, and one that's saved at zero). */ for (srcreg = 0; srcreg < E_NUM_REGS; srcreg ++) cache->saved_regs[srcreg] = -1; cache->using_fp = 0; @@ -231,9 +237,9 @@ iq2000_scan_prologue (CORE_ADDR scan_start, for (pc = scan_start; pc < loop_end; pc += 4) { - LONGEST insn = read_memory_unsigned_integer (pc, 4); + LONGEST insn = read_memory_unsigned_integer (pc, 4, byte_order); /* Skip any instructions writing to (sp) or decrementing the - SP. */ + SP. */ if ((insn & 0xffe00000) == 0xac200000) { /* sw using SP/%1 as base. */ @@ -242,16 +248,13 @@ iq2000_scan_prologue (CORE_ADDR scan_start, if (tgtreg >= 0 && tgtreg < E_NUM_REGS) cache->saved_regs[tgtreg] = -((signed short) (insn & 0xffff)); - if (tgtreg == E_LR_REGNUM) - found_store_lr = 1; continue; } if ((insn & 0xffff8000) == 0x20218000) { /* addi %1, %1, -N == addi %sp, %sp, -N */ - /* LEGACY -- from assembly-only port */ - found_decr_sp = 1; + /* LEGACY -- from assembly-only port. */ cache->framesize = -((signed short) (insn & 0xffff)); continue; } @@ -274,7 +277,7 @@ iq2000_scan_prologue (CORE_ADDR scan_start, if (tgtreg == E_SP_REGNUM || tgtreg == E_FP_REGNUM) { - /* "push" to stack (via SP or FP reg) */ + /* "push" to stack (via SP or FP reg). */ if (cache->saved_regs[srcreg] == -1) /* Don't save twice. */ cache->saved_regs[srcreg] = offset; continue; @@ -331,7 +334,7 @@ iq2000_init_frame_cache (struct iq2000_frame_cache *cache) stepped into a function call. */ static CORE_ADDR -iq2000_skip_prologue (CORE_ADDR pc) +iq2000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { CORE_ADDR func_addr = 0 , func_end = 0; @@ -348,7 +351,7 @@ iq2000_skip_prologue (CORE_ADDR pc) /* No useable line symbol. Use prologue parsing method. */ iq2000_init_frame_cache (&cache); - return iq2000_scan_prologue (func_addr, func_end, NULL, &cache); + return iq2000_scan_prologue (gdbarch, func_addr, func_end, NULL, &cache); } /* No function symbol -- just return the PC. */ @@ -356,29 +359,28 @@ iq2000_skip_prologue (CORE_ADDR pc) } static struct iq2000_frame_cache * -iq2000_frame_cache (struct frame_info *next_frame, void **this_cache) +iq2000_frame_cache (struct frame_info *this_frame, void **this_cache) { + struct gdbarch *gdbarch = get_frame_arch (this_frame); struct iq2000_frame_cache *cache; CORE_ADDR current_pc; int i; if (*this_cache) - return *this_cache; + return (struct iq2000_frame_cache *) *this_cache; cache = FRAME_OBSTACK_ZALLOC (struct iq2000_frame_cache); iq2000_init_frame_cache (cache); *this_cache = cache; - cache->base = frame_unwind_register_unsigned (next_frame, E_FP_REGNUM); - //if (cache->base == 0) - //return cache; + cache->base = get_frame_register_unsigned (this_frame, E_FP_REGNUM); - current_pc = frame_pc_unwind (next_frame); + current_pc = get_frame_pc (this_frame); find_pc_partial_function (current_pc, NULL, &cache->pc, NULL); if (cache->pc != 0) - iq2000_scan_prologue (cache->pc, current_pc, next_frame, cache); + iq2000_scan_prologue (gdbarch, cache->pc, current_pc, this_frame, cache); if (!cache->using_fp) - cache->base = frame_unwind_register_unsigned (next_frame, E_SP_REGNUM); + cache->base = get_frame_register_unsigned (this_frame, E_SP_REGNUM); cache->saved_sp = cache->base + cache->framesize; @@ -389,52 +391,32 @@ iq2000_frame_cache (struct frame_info *next_frame, void **this_cache) return cache; } -static void -iq2000_frame_prev_register (struct frame_info *next_frame, void **this_cache, - int regnum, int *optimizedp, - enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, gdb_byte *valuep) +static struct value * +iq2000_frame_prev_register (struct frame_info *this_frame, void **this_cache, + int regnum) { - struct iq2000_frame_cache *cache = iq2000_frame_cache (next_frame, this_cache); + struct iq2000_frame_cache *cache = iq2000_frame_cache (this_frame, + this_cache); + if (regnum == E_SP_REGNUM && cache->saved_sp) - { - *optimizedp = 0; - *lvalp = not_lval; - *addrp = 0; - *realnump = -1; - if (valuep) - store_unsigned_integer (valuep, 4, cache->saved_sp); - return; - } + return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp); if (regnum == E_PC_REGNUM) regnum = E_LR_REGNUM; if (regnum < E_NUM_REGS && cache->saved_regs[regnum] != -1) - { - *optimizedp = 0; - *lvalp = lval_memory; - *addrp = cache->saved_regs[regnum]; - *realnump = -1; - if (valuep) - read_memory (*addrp, valuep, - register_size (get_frame_arch (next_frame), regnum)); - return; - } + return frame_unwind_got_memory (this_frame, regnum, + cache->saved_regs[regnum]); - *optimizedp = 0; - *lvalp = lval_register; - *addrp = 0; - *realnump = regnum; - if (valuep) - frame_unwind_register (next_frame, (*realnump), valuep); + return frame_unwind_got_register (this_frame, regnum, regnum); } static void -iq2000_frame_this_id (struct frame_info *next_frame, void **this_cache, +iq2000_frame_this_id (struct frame_info *this_frame, void **this_cache, struct frame_id *this_id) { - struct iq2000_frame_cache *cache = iq2000_frame_cache (next_frame, this_cache); + struct iq2000_frame_cache *cache = iq2000_frame_cache (this_frame, + this_cache); /* This marks the outermost frame. */ if (cache->base == 0) @@ -445,39 +427,18 @@ iq2000_frame_this_id (struct frame_info *next_frame, void **this_cache, static const struct frame_unwind iq2000_frame_unwind = { NORMAL_FRAME, + default_frame_unwind_stop_reason, iq2000_frame_this_id, - iq2000_frame_prev_register + iq2000_frame_prev_register, + NULL, + default_frame_sniffer }; -static const struct frame_unwind * -iq2000_frame_sniffer (struct frame_info *next_frame) -{ - return &iq2000_frame_unwind; -} - -static CORE_ADDR -iq2000_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) -{ - return frame_unwind_register_unsigned (next_frame, E_SP_REGNUM); -} - -static CORE_ADDR -iq2000_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) -{ - return frame_unwind_register_unsigned (next_frame, E_PC_REGNUM); -} - -static struct frame_id -iq2000_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) -{ - return frame_id_build (iq2000_unwind_sp (gdbarch, next_frame), - frame_pc_unwind (next_frame)); -} - static CORE_ADDR -iq2000_frame_base_address (struct frame_info *next_frame, void **this_cache) +iq2000_frame_base_address (struct frame_info *this_frame, void **this_cache) { - struct iq2000_frame_cache *cache = iq2000_frame_cache (next_frame, this_cache); + struct iq2000_frame_cache *cache = iq2000_frame_cache (this_frame, + this_cache); return cache->base; } @@ -489,18 +450,23 @@ static const struct frame_base iq2000_frame_base = { iq2000_frame_base_address }; -static const unsigned char * -iq2000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, - int *lenptr) +static int +iq2000_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr) { - static const unsigned char big_breakpoint[] = { 0x00, 0x00, 0x00, 0x0d }; - static const unsigned char little_breakpoint[] = { 0x0d, 0x00, 0x00, 0x00 }; - if ((*pcptr & 3) != 0) - error ("breakpoint_from_pc: invalid breakpoint address 0x%lx", + error (_("breakpoint_from_pc: invalid breakpoint address 0x%lx"), (long) *pcptr); - *lenptr = 4; + return 4; +} + +static const gdb_byte * +iq2000_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size) +{ + static const unsigned char big_breakpoint[] = { 0x00, 0x00, 0x00, 0x0d }; + static const unsigned char little_breakpoint[] = { 0x0d, 0x00, 0x00, 0x00 }; + *size = kind; + return (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) ? big_breakpoint : little_breakpoint; } @@ -520,12 +486,12 @@ iq2000_store_return_value (struct type *type, struct regcache *regcache, while (len > 0) { - char buf[4]; + gdb_byte buf[4]; int size = len % 4 ?: 4; memset (buf, 0, 4); memcpy (buf + 4 - size, valbuf, size); - regcache_raw_write (regcache, regno++, buf); + regcache->raw_write (regno++, buf); len -= size; valbuf = ((char *) valbuf) + size; } @@ -552,8 +518,11 @@ iq2000_use_struct_convention (struct type *type) static void iq2000_extract_return_value (struct type *type, struct regcache *regcache, - void *valbuf) + gdb_byte *valbuf) { + struct gdbarch *gdbarch = regcache->arch (); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + /* If the function's return value is 8 bytes or less, it is returned in a register, and if larger than 8 bytes, it is returned in a stack location which is pointed to by the same @@ -574,9 +543,9 @@ iq2000_extract_return_value (struct type *type, struct regcache *regcache, /* By using store_unsigned_integer we avoid having to do anything special for small big-endian values. */ regcache_cooked_read_unsigned (regcache, regno++, &tmp); - store_unsigned_integer (valbuf, size, tmp); + store_unsigned_integer (valbuf, size, byte_order, tmp); len -= size; - valbuf = ((char *) valbuf) + size; + valbuf += size; } } else @@ -591,8 +560,8 @@ iq2000_extract_return_value (struct type *type, struct regcache *regcache, } static enum return_value_convention -iq2000_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +iq2000_return_value (struct gdbarch *gdbarch, struct value *function, + struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { if (iq2000_use_struct_convention (type)) @@ -610,7 +579,7 @@ iq2000_return_value (struct gdbarch *gdbarch, struct type *type, static struct type * iq2000_register_type (struct gdbarch *gdbarch, int regnum) { - return builtin_type_int32; + return builtin_type (gdbarch)->builtin_int32; } static CORE_ADDR @@ -621,7 +590,7 @@ iq2000_frame_align (struct gdbarch *ignore, CORE_ADDR sp) } /* Convenience function to check 8-byte types for being a scalar type - or a struct with only one long long or double member. */ + or a struct with only one long long or double member. */ static int iq2000_pass_8bytetype_by_address (struct type *type) { @@ -649,7 +618,7 @@ iq2000_pass_8bytetype_by_address (struct type *type) if (TYPE_CODE (ftype) == TYPE_CODE_FLT || TYPE_CODE (ftype) == TYPE_CODE_INT) return 0; - /* Everything else, pass by address. */ + /* Everything else, pass by address. */ return 1; } @@ -657,18 +626,22 @@ static CORE_ADDR iq2000_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) + function_call_return_method return_method, + CORE_ADDR struct_addr) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); const bfd_byte *val; bfd_byte buf[4]; struct type *type; int i, argreg, typelen, slacklen; int stackspace = 0; - /* Used to copy struct arguments into the stack. */ + /* Used to copy struct arguments into the stack. */ CORE_ADDR struct_ptr; - /* First determine how much stack space we will need. */ - for (i = 0, argreg = E_1ST_ARGREG + (struct_return != 0); i < nargs; i++) + /* First determine how much stack space we will need. */ + for (i = 0, argreg = E_1ST_ARGREG + (return_method == return_method_struct); + i < nargs; + i++) { type = value_type (args[i]); typelen = TYPE_LENGTH (type); @@ -686,19 +659,19 @@ iq2000_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { /* long long, double, and possibly - structs with a single field of long long or double. */ + structs with a single field of long long or double. */ if (argreg <= E_LAST_ARGREG - 1) { /* 8-byte arg goes into a register pair - (must start with an even-numbered reg) */ + (must start with an even-numbered reg). */ if (((argreg - E_1ST_ARGREG) % 2) != 0) argreg ++; argreg += 2; } else { - argreg = E_LAST_ARGREG + 1; /* no more argregs. */ - /* 8-byte arg goes on stack, must be 8-byte aligned. */ + argreg = E_LAST_ARGREG + 1; /* no more argregs. */ + /* 8-byte arg goes on stack, must be 8-byte aligned. */ stackspace = ((stackspace + 7) & ~7); stackspace += 8; } @@ -707,7 +680,7 @@ iq2000_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { /* Structs are passed as pointer to a copy of the struct. So we need room on the stack for a copy of the struct - plus for the argument pointer. */ + plus for the argument pointer. */ if (argreg <= E_LAST_ARGREG) argreg++; else @@ -718,7 +691,7 @@ iq2000_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } /* Now copy params, in ascending order, into their assigned location - (either in a register or on the stack). */ + (either in a register or on the stack). */ sp -= (sp % 8); /* align */ struct_ptr = sp; @@ -727,9 +700,9 @@ iq2000_push_dummy_call (struct gdbarch *gdbarch, struct value *function, stackspace = 0; argreg = E_1ST_ARGREG; - if (struct_return) + if (return_method == return_method_struct) { - /* A function that returns a struct will consume one argreg to do so. + /* A function that returns a struct will consume one argreg to do so. */ regcache_cooked_write_unsigned (regcache, argreg++, struct_addr); } @@ -741,18 +714,18 @@ iq2000_push_dummy_call (struct gdbarch *gdbarch, struct value *function, val = value_contents (args[i]); if (typelen <= 4) { - /* Char, short, int, float, pointer, and structs <= four bytes. */ + /* Char, short, int, float, pointer, and structs <= four bytes. */ slacklen = (4 - (typelen % 4)) % 4; memset (buf, 0, sizeof (buf)); memcpy (buf + slacklen, val, typelen); if (argreg <= E_LAST_ARGREG) { - /* Passed in a register. */ - regcache_raw_write (regcache, argreg++, buf); + /* Passed in a register. */ + regcache->raw_write (argreg++, buf); } else { - /* Passed on the stack. */ + /* Passed on the stack. */ write_memory (sp + stackspace, buf, 4); stackspace += 4; } @@ -760,20 +733,20 @@ iq2000_push_dummy_call (struct gdbarch *gdbarch, struct value *function, else if (typelen == 8 && !iq2000_pass_8bytetype_by_address (type)) { /* (long long), (double), or struct consisting of - a single (long long) or (double). */ + a single (long long) or (double). */ if (argreg <= E_LAST_ARGREG - 1) { /* 8-byte arg goes into a register pair - (must start with an even-numbered reg) */ + (must start with an even-numbered reg). */ if (((argreg - E_1ST_ARGREG) % 2) != 0) argreg++; - regcache_raw_write (regcache, argreg++, val); - regcache_raw_write (regcache, argreg++, val + 4); + regcache->raw_write (argreg++, val); + regcache->raw_write (argreg++, val + 4); } else { - /* 8-byte arg goes on stack, must be 8-byte aligned. */ - argreg = E_LAST_ARGREG + 1; /* no more argregs. */ + /* 8-byte arg goes on stack, must be 8-byte aligned. */ + argreg = E_LAST_ARGREG + 1; /* no more argregs. */ stackspace = ((stackspace + 7) & ~7); write_memory (sp + stackspace, val, typelen); stackspace += 8; @@ -790,20 +763,20 @@ iq2000_push_dummy_call (struct gdbarch *gdbarch, struct value *function, regcache_cooked_write_unsigned (regcache, argreg++, struct_ptr); else { - store_unsigned_integer (buf, 4, struct_ptr); + store_unsigned_integer (buf, 4, byte_order, struct_ptr); write_memory (sp + stackspace, buf, 4); stackspace += 4; } } } - /* Store return address. */ + /* Store return address. */ regcache_cooked_write_unsigned (regcache, E_LR_REGNUM, bp_addr); /* Update stack pointer. */ regcache_cooked_write_unsigned (regcache, E_SP_REGNUM, sp); - /* And that should do it. Return the new stack pointer. */ + /* And that should do it. Return the new stack pointer. */ return sp; } @@ -842,30 +815,29 @@ iq2000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_double_format (gdbarch, floatformats_ieee_double); set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); set_gdbarch_return_value (gdbarch, iq2000_return_value); - set_gdbarch_breakpoint_from_pc (gdbarch, iq2000_breakpoint_from_pc); + set_gdbarch_breakpoint_kind_from_pc (gdbarch, + iq2000_breakpoint_kind_from_pc); + set_gdbarch_sw_breakpoint_from_kind (gdbarch, + iq2000_sw_breakpoint_from_kind); set_gdbarch_frame_args_skip (gdbarch, 0); set_gdbarch_skip_prologue (gdbarch, iq2000_skip_prologue); set_gdbarch_inner_than (gdbarch, core_addr_lessthan); - set_gdbarch_print_insn (gdbarch, print_insn_iq2000); set_gdbarch_register_type (gdbarch, iq2000_register_type); set_gdbarch_frame_align (gdbarch, iq2000_frame_align); - set_gdbarch_unwind_sp (gdbarch, iq2000_unwind_sp); - set_gdbarch_unwind_pc (gdbarch, iq2000_unwind_pc); - set_gdbarch_unwind_dummy_id (gdbarch, iq2000_unwind_dummy_id); frame_base_set_default (gdbarch, &iq2000_frame_base); set_gdbarch_push_dummy_call (gdbarch, iq2000_push_dummy_call); gdbarch_init_osabi (info, gdbarch); - frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer); - frame_unwind_append_sniffer (gdbarch, iq2000_frame_sniffer); + dwarf2_append_unwinders (gdbarch); + frame_unwind_append_unwinder (gdbarch, &iq2000_frame_unwind); return gdbarch; } /* Function: _initialize_iq2000_tdep Initializer function for the iq2000 module. - Called by gdb at start-up. */ + Called by gdb at start-up. */ void _initialize_iq2000_tdep (void)