X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fmn10300-tdep.c;h=b472c36ebf1bed280235a9c4d42cd56d58f7406b;hb=0c0adcc52478ebb707ed780173e18262df6eab7e;hp=9b59c50fe291e9399d0fdbfda5455a29530a37d8;hpb=bbc1a78472cfdce40f23258372411fd3b30bb114;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c index 9b59c50fe2..b472c36ebf 100644 --- a/gdb/mn10300-tdep.c +++ b/gdb/mn10300-tdep.c @@ -1,7 +1,6 @@ /* Target-dependent code for the Matsushita MN10300 for GDB, the GNU debugger. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2007 Free Software Foundation, Inc. + Copyright (C) 1996-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -23,24 +22,64 @@ #include "dis-asm.h" #include "gdbtypes.h" #include "regcache.h" -#include "gdb_string.h" -#include "gdb_assert.h" -#include "gdbcore.h" /* for write_memory_unsigned_integer */ +#include "gdbcore.h" /* For write_memory_unsigned_integer. */ #include "value.h" -#include "gdbtypes.h" #include "frame.h" #include "frame-unwind.h" #include "frame-base.h" -#include "trad-frame.h" #include "symtab.h" #include "dwarf2-frame.h" #include "osabi.h" +#include "infcall.h" +#include "prologue-value.h" +#include "target.h" #include "mn10300-tdep.h" -/* Forward decl. */ -extern struct trad_frame_cache *mn10300_frame_unwind_cache (struct frame_info*, - void **); + +/* The am33-2 has 64 registers. */ +#define MN10300_MAX_NUM_REGS 64 + +/* Big enough to hold the size of the largest register in bytes. */ +#define MN10300_MAX_REGISTER_SIZE 64 + +/* This structure holds the results of a prologue analysis. */ +struct mn10300_prologue +{ + /* The architecture for which we generated this prologue info. */ + struct gdbarch *gdbarch; + + /* The offset from the frame base to the stack pointer --- always + zero or negative. + + Calling this a "size" is a bit misleading, but given that the + stack grows downwards, using offsets for everything keeps one + from going completely sign-crazy: you never change anything's + sign for an ADD instruction; always change the second operand's + sign for a SUB instruction; and everything takes care of + itself. */ + int frame_size; + + /* Non-zero if this function has initialized the frame pointer from + the stack pointer, zero otherwise. */ + int has_frame_ptr; + + /* If has_frame_ptr is non-zero, this is the offset from the frame + base to where the frame pointer points. This is always zero or + negative. */ + int frame_ptr_offset; + + /* The address of the first instruction at which the frame has been + set up and the arguments are where the debug info says they are + --- as best as we can tell. */ + CORE_ADDR prologue_end; + + /* reg_offset[R] is the offset from the CFA at which register R is + saved, or 1 if register R has not been saved. (Real values are + always zero or negative.) */ + int reg_offset[MN10300_MAX_NUM_REGS]; +}; + /* Compute the alignment required by a type. */ @@ -60,6 +99,7 @@ mn10300_type_align (struct type *type) case TYPE_CODE_FLT: case TYPE_CODE_PTR: case TYPE_CODE_REF: + case TYPE_CODE_RVALUE_REF: return TYPE_LENGTH (type); case TYPE_CODE_COMPLEX: @@ -77,7 +117,7 @@ mn10300_type_align (struct type *type) case TYPE_CODE_ARRAY: /* HACK! Structures containing arrays, even small ones, are not - elligible for returning in registers. */ + eligible for returning in registers. */ return 256; case TYPE_CODE_TYPEDEF: @@ -129,7 +169,7 @@ mn10300_use_struct_convention (struct type *type) static void mn10300_store_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, const void *valbuf) + struct regcache *regcache, const gdb_byte *valbuf) { int len = TYPE_LENGTH (type); int reg, regsz; @@ -142,13 +182,12 @@ mn10300_store_return_value (struct gdbarch *gdbarch, struct type *type, regsz = register_size (gdbarch, reg); if (len <= regsz) - regcache_raw_write_part (regcache, reg, 0, len, valbuf); + regcache->raw_write_part (reg, 0, len, valbuf); else if (len <= 2 * regsz) { - regcache_raw_write (regcache, reg, valbuf); + regcache->raw_write (reg, valbuf); gdb_assert (regsz == register_size (gdbarch, reg + 1)); - regcache_raw_write_part (regcache, reg+1, 0, - len - regsz, (char *) valbuf + regsz); + regcache->raw_write_part (reg + 1, 0, len - regsz, valbuf + regsz); } else internal_error (__FILE__, __LINE__, @@ -159,7 +198,7 @@ static void mn10300_extract_return_value (struct gdbarch *gdbarch, struct type *type, struct regcache *regcache, void *valbuf) { - char buf[MAX_REGISTER_SIZE]; + gdb_byte buf[MN10300_MAX_REGISTER_SIZE]; int len = TYPE_LENGTH (type); int reg, regsz; @@ -169,17 +208,18 @@ mn10300_extract_return_value (struct gdbarch *gdbarch, struct type *type, reg = 0; regsz = register_size (gdbarch, reg); + gdb_assert (regsz <= MN10300_MAX_REGISTER_SIZE); if (len <= regsz) { - regcache_raw_read (regcache, reg, buf); + regcache->raw_read (reg, buf); memcpy (valbuf, buf, len); } else if (len <= 2 * regsz) { - regcache_raw_read (regcache, reg, buf); + regcache->raw_read (reg, buf); memcpy (valbuf, buf, regsz); gdb_assert (regsz == register_size (gdbarch, reg + 1)); - regcache_raw_read (regcache, reg + 1, buf); + regcache->raw_read (reg + 1, buf); memcpy ((char *) valbuf + regsz, buf, len - regsz); } else @@ -194,9 +234,9 @@ mn10300_extract_return_value (struct gdbarch *gdbarch, struct type *type, from WRITEBUF into REGCACHE. */ static enum return_value_convention -mn10300_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +mn10300_return_value (struct gdbarch *gdbarch, struct value *function, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { if (mn10300_use_struct_convention (type)) return RETURN_VALUE_STRUCT_CONVENTION; @@ -209,8 +249,8 @@ mn10300_return_value (struct gdbarch *gdbarch, struct type *type, return RETURN_VALUE_REGISTER_CONVENTION; } -static char * -register_name (int reg, char **regs, long sizeof_regs) +static const char * +register_name (int reg, const char **regs, long sizeof_regs) { if (reg < 0 || reg >= sizeof_regs / sizeof (regs[0])) return NULL; @@ -221,7 +261,7 @@ register_name (int reg, char **regs, long sizeof_regs) static const char * mn10300_generic_register_name (struct gdbarch *gdbarch, int reg) { - static char *regs[] = + static const char *regs[] = { "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", "sp", "pc", "mdr", "psw", "lir", "lar", "", "", "", "", "", "", "", "", "", "", @@ -234,7 +274,7 @@ mn10300_generic_register_name (struct gdbarch *gdbarch, int reg) static const char * am33_register_name (struct gdbarch *gdbarch, int reg) { - static char *regs[] = + static const char *regs[] = { "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", "sp", "pc", "mdr", "psw", "lir", "lar", "", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", @@ -246,7 +286,7 @@ am33_register_name (struct gdbarch *gdbarch, int reg) static const char * am33_2_register_name (struct gdbarch *gdbarch, int reg) { - static char *regs[] = + static const char *regs[] = { "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", "sp", "pc", "mdr", "psw", "lir", "lar", "mdrq", "r0", @@ -263,21 +303,7 @@ am33_2_register_name (struct gdbarch *gdbarch, int reg) static struct type * mn10300_register_type (struct gdbarch *gdbarch, int reg) { - return builtin_type_int; -} - -static CORE_ADDR -mn10300_read_pc (struct regcache *regcache) -{ - ULONGEST val; - regcache_cooked_read_unsigned (regcache, E_PC_REGNUM, &val); - return val; -} - -static void -mn10300_write_pc (struct regcache *regcache, CORE_ADDR val) -{ - regcache_cooked_write_unsigned (regcache, E_PC_REGNUM, val); + return builtin_type (gdbarch)->builtin_int; } /* The breakpoint instruction must be the same size as the smallest @@ -286,677 +312,839 @@ mn10300_write_pc (struct regcache *regcache, CORE_ADDR val) The Matsushita mn10x00 processors have single byte instructions so we need a single byte breakpoint. Matsushita hasn't defined one, so we defined it ourselves. */ +constexpr gdb_byte mn10300_break_insn[] = {0xff}; + +typedef BP_MANIPULATION (mn10300_break_insn) mn10300_breakpoint; + +/* Model the semantics of pushing a register onto the stack. This + is a helper function for mn10300_analyze_prologue, below. */ +static void +push_reg (pv_t *regs, struct pv_area *stack, int regnum) +{ + regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], -4); + stack->store (regs[E_SP_REGNUM], 4, regs[regnum]); +} -const static unsigned char * -mn10300_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr, - int *bp_size) +/* Translate an "r" register number extracted from an instruction encoding + into a GDB register number. Adapted from a simulator function + of the same name; see am33.igen. */ +static int +translate_rreg (int rreg) { - static char breakpoint[] = {0xff}; - *bp_size = 1; - return breakpoint; + /* The higher register numbers actually correspond to the + basic machine's address and data registers. */ + if (rreg > 7 && rreg < 12) + return E_A0_REGNUM + rreg - 8; + else if (rreg > 11 && rreg < 16) + return E_D0_REGNUM + rreg - 12; + else + return E_E0_REGNUM + rreg; } -/* Set offsets of saved registers. - This is a helper function for mn10300_analyze_prologue. */ +/* Find saved registers in a 'struct pv_area'; we pass this 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 + register was saved, record its offset in RESULT_UNTYPED. */ static void -set_reg_offsets (struct frame_info *fi, - void **this_cache, - int movm_args, - int fpregmask, - int stack_extra_size, - int frame_in_fp) +check_for_saved (void *result_untyped, pv_t addr, CORE_ADDR size, pv_t value) { - struct trad_frame_cache *cache; - int offset = 0; - CORE_ADDR base; + struct mn10300_prologue *result = (struct mn10300_prologue *) result_untyped; + + if (value.kind == pvk_register + && value.k == 0 + && pv_is_register (addr, E_SP_REGNUM) + && size == register_size (result->gdbarch, value.reg)) + result->reg_offset[value.reg] = addr.k; +} - if (fi == NULL || this_cache == NULL) - return; +/* Analyze the prologue to determine where registers are saved, + the end of the prologue, etc. The result of this analysis is + returned in RESULT. See struct mn10300_prologue above for more + information. */ +static void +mn10300_analyze_prologue (struct gdbarch *gdbarch, + CORE_ADDR start_pc, CORE_ADDR limit_pc, + struct mn10300_prologue *result) +{ + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR pc; + int rn; + pv_t regs[MN10300_MAX_NUM_REGS]; + CORE_ADDR after_last_frame_setup_insn = start_pc; + int am33_mode = AM33_MODE (gdbarch); - cache = mn10300_frame_unwind_cache (fi, this_cache); - if (cache == NULL) - return; + memset (result, 0, sizeof (*result)); + result->gdbarch = gdbarch; - if (frame_in_fp) + for (rn = 0; rn < MN10300_MAX_NUM_REGS; rn++) { - base = frame_unwind_register_unsigned (fi, E_A3_REGNUM); + regs[rn] = pv_register (rn, 0); + result->reg_offset[rn] = 1; } - else + pv_area stack (E_SP_REGNUM, gdbarch_addr_bit (gdbarch)); + + /* The typical call instruction will have saved the return address on the + stack. Space for the return address has already been preallocated in + the caller's frame. It's possible, such as when using -mrelax with gcc + that other registers were saved as well. If this happens, we really + have no chance of deciphering the frame. DWARF info can save the day + when this happens. */ + stack.store (regs[E_SP_REGNUM], 4, regs[E_PC_REGNUM]); + + pc = start_pc; + while (pc < limit_pc) { - base = frame_unwind_register_unsigned (fi, E_SP_REGNUM) + stack_extra_size; - } + int status; + gdb_byte instr[2]; + + /* Instructions can be as small as one byte; however, we usually + need at least two bytes to do the decoding, so fetch that many + to begin with. */ + status = target_read_memory (pc, instr, 2); + if (status != 0) + break; + + /* movm [regs], sp */ + if (instr[0] == 0xcf) + { + gdb_byte save_mask; - trad_frame_set_this_base (cache, base); + save_mask = instr[1]; - if (AM33_MODE == 2) - { - /* If bit N is set in fpregmask, fsN is saved on the stack. - The floating point registers are saved in ascending order. - For example: fs16 <- Frame Pointer - fs17 Frame Pointer + 4 */ - if (fpregmask != 0) - { - int i; - for (i = 0; i < 32; i++) + if ((save_mask & movm_exreg0_bit) && am33_mode) + { + push_reg (regs, &stack, E_E2_REGNUM); + push_reg (regs, &stack, E_E3_REGNUM); + } + if ((save_mask & movm_exreg1_bit) && am33_mode) + { + push_reg (regs, &stack, E_E4_REGNUM); + push_reg (regs, &stack, E_E5_REGNUM); + push_reg (regs, &stack, E_E6_REGNUM); + push_reg (regs, &stack, E_E7_REGNUM); + } + if ((save_mask & movm_exother_bit) && am33_mode) + { + push_reg (regs, &stack, E_E0_REGNUM); + push_reg (regs, &stack, E_E1_REGNUM); + push_reg (regs, &stack, E_MDRQ_REGNUM); + push_reg (regs, &stack, E_MCRH_REGNUM); + push_reg (regs, &stack, E_MCRL_REGNUM); + push_reg (regs, &stack, E_MCVF_REGNUM); + } + if (save_mask & movm_d2_bit) + push_reg (regs, &stack, E_D2_REGNUM); + if (save_mask & movm_d3_bit) + push_reg (regs, &stack, E_D3_REGNUM); + if (save_mask & movm_a2_bit) + push_reg (regs, &stack, E_A2_REGNUM); + if (save_mask & movm_a3_bit) + push_reg (regs, &stack, E_A3_REGNUM); + if (save_mask & movm_other_bit) { - if (fpregmask & (1 << i)) - { - trad_frame_set_reg_addr (cache, E_FS0_REGNUM + i, base + offset); - offset += 4; - } + push_reg (regs, &stack, E_D0_REGNUM); + push_reg (regs, &stack, E_D1_REGNUM); + push_reg (regs, &stack, E_A0_REGNUM); + push_reg (regs, &stack, E_A1_REGNUM); + push_reg (regs, &stack, E_MDR_REGNUM); + push_reg (regs, &stack, E_LIR_REGNUM); + push_reg (regs, &stack, E_LAR_REGNUM); + /* The `other' bit leaves a blank area of four bytes at + the beginning of its block of saved registers, making + it 32 bytes long in total. */ + regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], -4); } + + pc += 2; + after_last_frame_setup_insn = pc; } - } + /* mov sp, aN */ + else if ((instr[0] & 0xfc) == 0x3c) + { + int aN = instr[0] & 0x03; + regs[E_A0_REGNUM + aN] = regs[E_SP_REGNUM]; - if (movm_args & movm_other_bit) - { - /* The `other' bit leaves a blank area of four bytes at the - beginning of its block of saved registers, making it 32 bytes - long in total. */ - trad_frame_set_reg_addr (cache, E_LAR_REGNUM, base + offset + 4); - trad_frame_set_reg_addr (cache, E_LIR_REGNUM, base + offset + 8); - trad_frame_set_reg_addr (cache, E_MDR_REGNUM, base + offset + 12); - trad_frame_set_reg_addr (cache, E_A0_REGNUM + 1, base + offset + 16); - trad_frame_set_reg_addr (cache, E_A0_REGNUM, base + offset + 20); - trad_frame_set_reg_addr (cache, E_D0_REGNUM + 1, base + offset + 24); - trad_frame_set_reg_addr (cache, E_D0_REGNUM, base + offset + 28); - offset += 32; - } + pc += 1; + if (aN == 3) + after_last_frame_setup_insn = pc; + } + /* mov aM, aN */ + else if ((instr[0] & 0xf0) == 0x90 + && (instr[0] & 0x03) != ((instr[0] & 0x0c) >> 2)) + { + int aN = instr[0] & 0x03; + int aM = (instr[0] & 0x0c) >> 2; - if (movm_args & movm_a3_bit) - { - trad_frame_set_reg_addr (cache, E_A3_REGNUM, base + offset); - offset += 4; - } - if (movm_args & movm_a2_bit) - { - trad_frame_set_reg_addr (cache, E_A2_REGNUM, base + offset); - offset += 4; - } - if (movm_args & movm_d3_bit) - { - trad_frame_set_reg_addr (cache, E_D3_REGNUM, base + offset); - offset += 4; - } - if (movm_args & movm_d2_bit) - { - trad_frame_set_reg_addr (cache, E_D2_REGNUM, base + offset); - offset += 4; - } - if (AM33_MODE) - { - if (movm_args & movm_exother_bit) - { - trad_frame_set_reg_addr (cache, E_MCVF_REGNUM, base + offset); - trad_frame_set_reg_addr (cache, E_MCRL_REGNUM, base + offset + 4); - trad_frame_set_reg_addr (cache, E_MCRH_REGNUM, base + offset + 8); - trad_frame_set_reg_addr (cache, E_MDRQ_REGNUM, base + offset + 12); - trad_frame_set_reg_addr (cache, E_E1_REGNUM, base + offset + 16); - trad_frame_set_reg_addr (cache, E_E0_REGNUM, base + offset + 20); - offset += 24; - } - if (movm_args & movm_exreg1_bit) - { - trad_frame_set_reg_addr (cache, E_E7_REGNUM, base + offset); - trad_frame_set_reg_addr (cache, E_E6_REGNUM, base + offset + 4); - trad_frame_set_reg_addr (cache, E_E5_REGNUM, base + offset + 8); - trad_frame_set_reg_addr (cache, E_E4_REGNUM, base + offset + 12); - offset += 16; - } - if (movm_args & movm_exreg0_bit) - { - trad_frame_set_reg_addr (cache, E_E3_REGNUM, base + offset); - trad_frame_set_reg_addr (cache, E_E2_REGNUM, base + offset + 4); - offset += 8; - } - } - /* The last (or first) thing on the stack will be the PC. */ - trad_frame_set_reg_addr (cache, E_PC_REGNUM, base + offset); - /* Save the SP in the 'traditional' way. - This will be the same location where the PC is saved. */ - trad_frame_set_reg_value (cache, E_SP_REGNUM, base + offset); -} + regs[E_A0_REGNUM + aN] = regs[E_A0_REGNUM + aM]; -/* The main purpose of this file is dealing with prologues to extract - information about stack frames and saved registers. + pc += 1; + } + /* mov dM, dN */ + else if ((instr[0] & 0xf0) == 0x80 + && (instr[0] & 0x03) != ((instr[0] & 0x0c) >> 2)) + { + int dN = instr[0] & 0x03; + int dM = (instr[0] & 0x0c) >> 2; - In gcc/config/mn13000/mn10300.c, the expand_prologue prologue - function is pretty readable, and has a nice explanation of how the - prologue is generated. The prologues generated by that code will - have the following form (NOTE: the current code doesn't handle all - this!): + regs[E_D0_REGNUM + dN] = regs[E_D0_REGNUM + dM]; - + If this is an old-style varargs function, then its arguments - need to be flushed back to the stack: - - mov d0,(4,sp) - mov d1,(4,sp) + pc += 1; + } + /* mov aM, dN */ + else if (instr[0] == 0xf1 && (instr[1] & 0xf0) == 0xd0) + { + int dN = instr[1] & 0x03; + int aM = (instr[1] & 0x0c) >> 2; - + If we use any of the callee-saved registers, save them now. - - movm [some callee-saved registers],(sp) + regs[E_D0_REGNUM + dN] = regs[E_A0_REGNUM + aM]; - + If we have any floating-point registers to save: + pc += 2; + } + /* mov dM, aN */ + else if (instr[0] == 0xf1 && (instr[1] & 0xf0) == 0xe0) + { + int aN = instr[1] & 0x03; + int dM = (instr[1] & 0x0c) >> 2; - - Decrement the stack pointer to reserve space for the registers. - If the function doesn't need a frame pointer, we may combine - this with the adjustment that reserves space for the frame. + regs[E_A0_REGNUM + aN] = regs[E_D0_REGNUM + dM]; - add -SIZE, sp + pc += 2; + } + /* add imm8, SP */ + else if (instr[0] == 0xf8 && instr[1] == 0xfe) + { + gdb_byte buf[1]; + LONGEST imm8; - - Save the floating-point registers. We have two possible - strategies: - . Save them at fixed offset from the SP: + status = target_read_memory (pc + 2, buf, 1); + if (status != 0) + break; - fmov fsN,(OFFSETN,sp) - fmov fsM,(OFFSETM,sp) - ... + imm8 = extract_signed_integer (buf, 1, byte_order); + regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], imm8); - Note that, if OFFSETN happens to be zero, you'll get the - different opcode: fmov fsN,(sp) + pc += 3; + /* Stack pointer adjustments are frame related. */ + after_last_frame_setup_insn = pc; + } + /* add imm16, SP */ + else if (instr[0] == 0xfa && instr[1] == 0xfe) + { + gdb_byte buf[2]; + LONGEST imm16; - . Or, set a0 to the start of the save area, and then use - post-increment addressing to save the FP registers. + status = target_read_memory (pc + 2, buf, 2); + if (status != 0) + break; - mov sp, a0 - add SIZE, a0 - fmov fsN,(a0+) - fmov fsM,(a0+) - ... + imm16 = extract_signed_integer (buf, 2, byte_order); + regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], imm16); - + If the function needs a frame pointer, we set it here. + pc += 4; + /* Stack pointer adjustments are frame related. */ + after_last_frame_setup_insn = pc; + } + /* add imm32, SP */ + else if (instr[0] == 0xfc && instr[1] == 0xfe) + { + gdb_byte buf[4]; + LONGEST imm32; - mov sp, a3 + status = target_read_memory (pc + 2, buf, 4); + if (status != 0) + break; - + Now we reserve space for the stack frame proper. This could be - merged into the `add -SIZE, sp' instruction for FP saves up - above, unless we needed to set the frame pointer in the previous - step, or the frame is so large that allocating the whole thing at - once would put the FP register save slots out of reach of the - addressing mode (128 bytes). - - add -SIZE, sp - One day we might keep the stack pointer constant, that won't - change the code for prologues, but it will make the frame - pointerless case much more common. */ + imm32 = extract_signed_integer (buf, 4, byte_order); + regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], imm32); -/* Analyze the prologue to determine where registers are saved, - the end of the prologue, etc etc. Return the end of the prologue - scanned. + pc += 6; + /* Stack pointer adjustments are frame related. */ + after_last_frame_setup_insn = pc; + } + /* add imm8, aN */ + else if ((instr[0] & 0xfc) == 0x20) + { + int aN; + LONGEST imm8; - We store into FI (if non-null) several tidbits of information: + aN = instr[0] & 0x03; + imm8 = extract_signed_integer (&instr[1], 1, byte_order); - * stack_size -- size of this stack frame. Note that if we stop in - certain parts of the prologue/epilogue we may claim the size of the - current frame is zero. This happens when the current frame has - not been allocated yet or has already been deallocated. + regs[E_A0_REGNUM + aN] = pv_add_constant (regs[E_A0_REGNUM + aN], + imm8); - * fsr -- Addresses of registers saved in the stack by this frame. + pc += 2; + } + /* add imm16, aN */ + else if (instr[0] == 0xfa && (instr[1] & 0xfc) == 0xd0) + { + int aN; + LONGEST imm16; + gdb_byte buf[2]; - * status -- A (relatively) generic status indicator. It's a bitmask - with the following bits: + aN = instr[1] & 0x03; - MY_FRAME_IN_SP: The base of the current frame is actually in - the stack pointer. This can happen for frame pointerless - functions, or cases where we're stopped in the prologue/epilogue - itself. For these cases mn10300_analyze_prologue will need up - update fi->frame before returning or analyzing the register - save instructions. + status = target_read_memory (pc + 2, buf, 2); + if (status != 0) + break; - MY_FRAME_IN_FP: The base of the current frame is in the - frame pointer register ($a3). - NO_MORE_FRAMES: Set this if the current frame is "start" or - if the first instruction looks like mov ,sp. This tells - frame chain to not bother trying to unwind past this frame. */ + imm16 = extract_signed_integer (buf, 2, byte_order); -static CORE_ADDR -mn10300_analyze_prologue (struct frame_info *fi, - void **this_cache, - CORE_ADDR pc) -{ - CORE_ADDR func_addr, func_end, addr, stop; - long stack_extra_size = 0; - int imm_size; - unsigned char buf[4]; - int status; - int movm_args = 0; - int fpregmask = 0; - char *name; - int frame_in_fp = 0; - - /* Use the PC in the frame if it's provided to look up the - start of this function. - - Note: kevinb/2003-07-16: We used to do the following here: - pc = (fi ? get_frame_pc (fi) : pc); - But this is (now) badly broken when called from analyze_dummy_frame(). - */ - if (fi) - { - pc = (pc ? pc : get_frame_pc (fi)); - } + regs[E_A0_REGNUM + aN] = pv_add_constant (regs[E_A0_REGNUM + aN], + imm16); - /* Find the start of this function. */ - status = find_pc_partial_function (pc, &name, &func_addr, &func_end); + pc += 4; + } + /* add imm32, aN */ + else if (instr[0] == 0xfc && (instr[1] & 0xfc) == 0xd0) + { + int aN; + LONGEST imm32; + gdb_byte buf[4]; - /* Do nothing if we couldn't find the start of this function + aN = instr[1] & 0x03; - MVS: comment went on to say "or if we're stopped at the first - instruction in the prologue" -- but code doesn't reflect that, - and I don't want to do that anyway. */ - if (status == 0) - { - addr = pc; - goto finish_prologue; - } + status = target_read_memory (pc + 2, buf, 4); + if (status != 0) + break; - /* If we're in start, then give up. */ - if (strcmp (name, "start") == 0) - { - addr = pc; - goto finish_prologue; - } + imm32 = extract_signed_integer (buf, 2, byte_order); - /* Figure out where to stop scanning. */ - stop = fi ? pc : func_end; + regs[E_A0_REGNUM + aN] = pv_add_constant (regs[E_A0_REGNUM + aN], + imm32); + pc += 6; + } + /* fmov fsM, (rN) */ + else if (instr[0] == 0xf9 && (instr[1] & 0xfd) == 0x30) + { + int fsM, sM, Y, rN; + gdb_byte buf[1]; - /* Don't walk off the end of the function. */ - stop = stop > func_end ? func_end : stop; + Y = (instr[1] & 0x02) >> 1; - /* Start scanning on the first instruction of this function. */ - addr = func_addr; + status = target_read_memory (pc + 2, buf, 1); + if (status != 0) + break; - /* Suck in two bytes. */ - if (addr + 2 > stop || !safe_frame_unwind_memory (fi, addr, buf, 2)) - goto finish_prologue; + sM = (buf[0] & 0xf0) >> 4; + rN = buf[0] & 0x0f; + fsM = (Y << 4) | sM; - /* First see if this insn sets the stack pointer from a register; if - so, it's probably the initialization of the stack pointer in _start, - so mark this as the bottom-most frame. */ - if (buf[0] == 0xf2 && (buf[1] & 0xf3) == 0xf0) - { - goto finish_prologue; - } + stack.store (regs[translate_rreg (rN)], 4, + regs[E_FS0_REGNUM + fsM]); - /* Now look for movm [regs],sp, which saves the callee saved registers. + pc += 3; + } + /* fmov fsM, (sp) */ + else if (instr[0] == 0xf9 && (instr[1] & 0xfd) == 0x34) + { + int fsM, sM, Y; + gdb_byte buf[1]; - At this time we don't know if fi->frame is valid, so we only note - that we encountered a movm instruction. Later, we'll set the entries - in fsr.regs as needed. */ - if (buf[0] == 0xcf) - { - /* Extract the register list for the movm instruction. */ - movm_args = buf[1]; + Y = (instr[1] & 0x02) >> 1; - addr += 2; + status = target_read_memory (pc + 2, buf, 1); + if (status != 0) + break; - /* Quit now if we're beyond the stop point. */ - if (addr >= stop) - goto finish_prologue; + sM = (buf[0] & 0xf0) >> 4; + fsM = (Y << 4) | sM; - /* Get the next two bytes so the prologue scan can continue. */ - if (!safe_frame_unwind_memory (fi, addr, buf, 2)) - goto finish_prologue; - } + stack.store (regs[E_SP_REGNUM], 4, + regs[E_FS0_REGNUM + fsM]); - if (AM33_MODE == 2) - { - /* Determine if any floating point registers are to be saved. - Look for one of the following three prologue formats: - - [movm [regs],(sp)] [movm [regs],(sp)] [movm [regs],(sp)] - - add -SIZE,sp add -SIZE,sp add -SIZE,sp - fmov fs#,(sp) mov sp,a0/a1 mov sp,a0/a1 - fmov fs#,(#,sp) fmov fs#,(a0/a1+) add SIZE2,a0/a1 - ... ... fmov fs#,(a0/a1+) - ... ... ... - fmov fs#,(#,sp) fmov fs#,(a0/a1+) fmov fs#,(a0/a1+) - - [mov sp,a3] [mov sp,a3] - [add -SIZE2,sp] [add -SIZE2,sp] */ - - /* Remember the address at which we started in the event that we - don't ultimately find an fmov instruction. Once we're certain - that we matched one of the above patterns, we'll set - ``restore_addr'' to the appropriate value. Note: At one time - in the past, this code attempted to not adjust ``addr'' until - there was a fair degree of certainty that the pattern would be - matched. However, that code did not wait until an fmov instruction - was actually encountered. As a consequence, ``addr'' would - sometimes be advanced even when no fmov instructions were found. */ - CORE_ADDR restore_addr = addr; - - /* First, look for add -SIZE,sp (i.e. add imm8,sp (0xf8feXX) - or add imm16,sp (0xfafeXXXX) - or add imm32,sp (0xfcfeXXXXXXXX)) */ - imm_size = 0; - if (buf[0] == 0xf8 && buf[1] == 0xfe) - imm_size = 1; - else if (buf[0] == 0xfa && buf[1] == 0xfe) - imm_size = 2; - else if (buf[0] == 0xfc && buf[1] == 0xfe) - imm_size = 4; - if (imm_size != 0) + pc += 3; + } + /* fmov fsM, (rN, rI) */ + else if (instr[0] == 0xfb && instr[1] == 0x37) { - /* An "add -#,sp" instruction has been found. "addr + 2 + imm_size" - is the address of the next instruction. Don't modify "addr" until - the next "floating point prologue" instruction is found. If this - is not a prologue that saves floating point registers we need to - be able to back out of this bit of code and continue with the - prologue analysis. */ - if (addr + 2 + imm_size < stop) - { - if (!safe_frame_unwind_memory (fi, addr + 2 + imm_size, buf, 3)) - goto finish_prologue; - if ((buf[0] & 0xfc) == 0x3c) - { - /* Occasionally, especially with C++ code, the "fmov" - instructions will be preceded by "mov sp,aN" - (aN => a0, a1, a2, or a3). - - This is a one byte instruction: mov sp,aN = 0011 11XX - where XX is the register number. - - Skip this instruction by incrementing addr. The "fmov" - instructions will have the form "fmov fs#,(aN+)" in this - case, but that will not necessitate a change in the - "fmov" parsing logic below. */ - - addr++; - - if ((buf[1] & 0xfc) == 0x20) - { - /* Occasionally, especially with C++ code compiled with - the -fomit-frame-pointer or -O3 options, the - "mov sp,aN" instruction will be followed by an - "add #,aN" instruction. This indicates the - "stack_size", the size of the portion of the stack - containing the arguments. This instruction format is: - add #,aN = 0010 00XX YYYY YYYY - where XX is the register number - YYYY YYYY is the constant. - Note the size of the stack (as a negative number) in - the frame info structure. */ - if (fi) - stack_extra_size += -buf[2]; - - addr += 2; - } - } - - if ((buf[0] & 0xfc) == 0x3c || - buf[0] == 0xf9 || buf[0] == 0xfb) - { - /* An "fmov" instruction has been found indicating that this - prologue saves floating point registers (or, as described - above, a "mov sp,aN" and possible "add #,aN" have been - found and we will assume an "fmov" follows). Process the - consecutive "fmov" instructions. */ - for (addr += 2 + imm_size;;addr += imm_size) - { - int regnum; - - /* Read the "fmov" instruction. */ - if (addr >= stop || - !safe_frame_unwind_memory (fi, addr, buf, 4)) - goto finish_prologue; - - if (buf[0] != 0xf9 && buf[0] != 0xfb) - break; - - /* An fmov instruction has just been seen. We can - now really commit to the pattern match. Set the - address to restore at the end of this speculative - bit of code to the actually address that we've - been incrementing (or not) throughout the - speculation. */ - restore_addr = addr; - - /* Get the floating point register number from the - 2nd and 3rd bytes of the "fmov" instruction: - Machine Code: 0000 00X0 YYYY 0000 => - Regnum: 000X YYYY */ - regnum = (buf[1] & 0x02) << 3; - regnum |= ((buf[2] & 0xf0) >> 4) & 0x0f; - - /* Add this register number to the bit mask of floating - point registers that have been saved. */ - fpregmask |= 1 << regnum; - - /* Determine the length of this "fmov" instruction. - fmov fs#,(sp) => 3 byte instruction - fmov fs#,(#,sp) => 4 byte instruction */ - imm_size = (buf[0] == 0xf9) ? 3 : 4; - } - } - else - { - /* No "fmov" was found. Reread the two bytes at the original - "addr" to reset the state. */ - addr = restore_addr; - if (!safe_frame_unwind_memory (fi, addr, buf, 2)) - goto finish_prologue; - } - } - /* else the prologue consists entirely of an "add -SIZE,sp" - instruction. Handle this below. */ + int fsM, sM, Z, rN, rI; + gdb_byte buf[2]; + + + status = target_read_memory (pc + 2, buf, 2); + if (status != 0) + break; + + rI = (buf[0] & 0xf0) >> 4; + rN = buf[0] & 0x0f; + sM = (buf[1] & 0xf0) >> 4; + Z = (buf[1] & 0x02) >> 1; + fsM = (Z << 4) | sM; + + stack.store (pv_add (regs[translate_rreg (rN)], + regs[translate_rreg (rI)]), + 4, regs[E_FS0_REGNUM + fsM]); + + pc += 4; } - /* else no "add -SIZE,sp" was found indicating no floating point - registers are saved in this prologue. */ - - /* In the pattern match code contained within this block, `restore_addr' - is set to the starting address at the very beginning and then - iteratively to the next address to start scanning at once the - pattern match has succeeded. Thus `restore_addr' will contain - the address to rewind to if the pattern match failed. If the - match succeeded, `restore_addr' and `addr' will already have the - same value. */ - addr = restore_addr; - } + /* fmov fsM, (d8, rN) */ + else if (instr[0] == 0xfb && (instr[1] & 0xfd) == 0x30) + { + int fsM, sM, Y, rN; + LONGEST d8; + gdb_byte buf[2]; - /* Now see if we set up a frame pointer via "mov sp,a3" */ - if (buf[0] == 0x3f) - { - addr += 1; + Y = (instr[1] & 0x02) >> 1; + + status = target_read_memory (pc + 2, buf, 2); + if (status != 0) + break; - /* The frame pointer is now valid. */ - if (fi) + sM = (buf[0] & 0xf0) >> 4; + rN = buf[0] & 0x0f; + fsM = (Y << 4) | sM; + d8 = extract_signed_integer (&buf[1], 1, byte_order); + + stack.store (pv_add_constant (regs[translate_rreg (rN)], d8), + 4, regs[E_FS0_REGNUM + fsM]); + + pc += 4; + } + /* fmov fsM, (d24, rN) */ + else if (instr[0] == 0xfd && (instr[1] & 0xfd) == 0x30) { - frame_in_fp = 1; + int fsM, sM, Y, rN; + LONGEST d24; + gdb_byte buf[4]; + + Y = (instr[1] & 0x02) >> 1; + + status = target_read_memory (pc + 2, buf, 4); + if (status != 0) + break; + + sM = (buf[0] & 0xf0) >> 4; + rN = buf[0] & 0x0f; + fsM = (Y << 4) | sM; + d24 = extract_signed_integer (&buf[1], 3, byte_order); + + stack.store (pv_add_constant (regs[translate_rreg (rN)], d24), + 4, regs[E_FS0_REGNUM + fsM]); + + pc += 6; } + /* fmov fsM, (d32, rN) */ + else if (instr[0] == 0xfe && (instr[1] & 0xfd) == 0x30) + { + int fsM, sM, Y, rN; + LONGEST d32; + gdb_byte buf[5]; - /* Quit now if we're beyond the stop point. */ - if (addr >= stop) - goto finish_prologue; + Y = (instr[1] & 0x02) >> 1; - /* Get two more bytes so scanning can continue. */ - if (!safe_frame_unwind_memory (fi, addr, buf, 2)) - goto finish_prologue; - } + status = target_read_memory (pc + 2, buf, 5); + if (status != 0) + break; - /* Next we should allocate the local frame. No more prologue insns - are found after allocating the local frame. + sM = (buf[0] & 0xf0) >> 4; + rN = buf[0] & 0x0f; + fsM = (Y << 4) | sM; + d32 = extract_signed_integer (&buf[1], 4, byte_order); - Search for add imm8,sp (0xf8feXX) - or add imm16,sp (0xfafeXXXX) - or add imm32,sp (0xfcfeXXXXXXXX). + stack.store (pv_add_constant (regs[translate_rreg (rN)], d32), + 4, regs[E_FS0_REGNUM + fsM]); - If none of the above was found, then this prologue has no - additional stack. */ + pc += 7; + } + /* fmov fsM, (d8, SP) */ + else if (instr[0] == 0xfb && (instr[1] & 0xfd) == 0x34) + { + int fsM, sM, Y; + LONGEST d8; + gdb_byte buf[2]; - imm_size = 0; - if (buf[0] == 0xf8 && buf[1] == 0xfe) - imm_size = 1; - else if (buf[0] == 0xfa && buf[1] == 0xfe) - imm_size = 2; - else if (buf[0] == 0xfc && buf[1] == 0xfe) - imm_size = 4; + Y = (instr[1] & 0x02) >> 1; - if (imm_size != 0) - { - /* Suck in imm_size more bytes, they'll hold the size of the - current frame. */ - if (!safe_frame_unwind_memory (fi, addr + 2, buf, imm_size)) - goto finish_prologue; + status = target_read_memory (pc + 2, buf, 2); + if (status != 0) + break; - /* Note the size of the stack. */ - stack_extra_size -= extract_signed_integer (buf, imm_size); + sM = (buf[0] & 0xf0) >> 4; + fsM = (Y << 4) | sM; + d8 = extract_signed_integer (&buf[1], 1, byte_order); - /* We just consumed 2 + imm_size bytes. */ - addr += 2 + imm_size; + stack.store (pv_add_constant (regs[E_SP_REGNUM], d8), + 4, regs[E_FS0_REGNUM + fsM]); - /* No more prologue insns follow, so begin preparation to return. */ - goto finish_prologue; + pc += 4; + } + /* fmov fsM, (d24, SP) */ + else if (instr[0] == 0xfd && (instr[1] & 0xfd) == 0x34) + { + int fsM, sM, Y; + LONGEST d24; + gdb_byte buf[4]; + + Y = (instr[1] & 0x02) >> 1; + + status = target_read_memory (pc + 2, buf, 4); + if (status != 0) + break; + + sM = (buf[0] & 0xf0) >> 4; + fsM = (Y << 4) | sM; + d24 = extract_signed_integer (&buf[1], 3, byte_order); + + stack.store (pv_add_constant (regs[E_SP_REGNUM], d24), + 4, regs[E_FS0_REGNUM + fsM]); + + pc += 6; + } + /* fmov fsM, (d32, SP) */ + else if (instr[0] == 0xfe && (instr[1] & 0xfd) == 0x34) + { + int fsM, sM, Y; + LONGEST d32; + gdb_byte buf[5]; + + Y = (instr[1] & 0x02) >> 1; + + status = target_read_memory (pc + 2, buf, 5); + if (status != 0) + break; + + sM = (buf[0] & 0xf0) >> 4; + fsM = (Y << 4) | sM; + d32 = extract_signed_integer (&buf[1], 4, byte_order); + + stack.store (pv_add_constant (regs[E_SP_REGNUM], d32), + 4, regs[E_FS0_REGNUM + fsM]); + + pc += 7; + } + /* fmov fsM, (rN+) */ + else if (instr[0] == 0xf9 && (instr[1] & 0xfd) == 0x31) + { + int fsM, sM, Y, rN, rN_regnum; + gdb_byte buf[1]; + + Y = (instr[1] & 0x02) >> 1; + + status = target_read_memory (pc + 2, buf, 1); + if (status != 0) + break; + + sM = (buf[0] & 0xf0) >> 4; + rN = buf[0] & 0x0f; + fsM = (Y << 4) | sM; + + rN_regnum = translate_rreg (rN); + + stack.store (regs[rN_regnum], 4, + regs[E_FS0_REGNUM + fsM]); + regs[rN_regnum] = pv_add_constant (regs[rN_regnum], 4); + + pc += 3; + } + /* fmov fsM, (rN+, imm8) */ + else if (instr[0] == 0xfb && (instr[1] & 0xfd) == 0x31) + { + int fsM, sM, Y, rN, rN_regnum; + LONGEST imm8; + gdb_byte buf[2]; + + Y = (instr[1] & 0x02) >> 1; + + status = target_read_memory (pc + 2, buf, 2); + if (status != 0) + break; + + sM = (buf[0] & 0xf0) >> 4; + rN = buf[0] & 0x0f; + fsM = (Y << 4) | sM; + imm8 = extract_signed_integer (&buf[1], 1, byte_order); + + rN_regnum = translate_rreg (rN); + + stack.store (regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]); + regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm8); + + pc += 4; + } + /* fmov fsM, (rN+, imm24) */ + else if (instr[0] == 0xfd && (instr[1] & 0xfd) == 0x31) + { + int fsM, sM, Y, rN, rN_regnum; + LONGEST imm24; + gdb_byte buf[4]; + + Y = (instr[1] & 0x02) >> 1; + + status = target_read_memory (pc + 2, buf, 4); + if (status != 0) + break; + + sM = (buf[0] & 0xf0) >> 4; + rN = buf[0] & 0x0f; + fsM = (Y << 4) | sM; + imm24 = extract_signed_integer (&buf[1], 3, byte_order); + + rN_regnum = translate_rreg (rN); + + stack.store (regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]); + regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm24); + + pc += 6; + } + /* fmov fsM, (rN+, imm32) */ + else if (instr[0] == 0xfe && (instr[1] & 0xfd) == 0x31) + { + int fsM, sM, Y, rN, rN_regnum; + LONGEST imm32; + gdb_byte buf[5]; + + Y = (instr[1] & 0x02) >> 1; + + status = target_read_memory (pc + 2, buf, 5); + if (status != 0) + break; + + sM = (buf[0] & 0xf0) >> 4; + rN = buf[0] & 0x0f; + fsM = (Y << 4) | sM; + imm32 = extract_signed_integer (&buf[1], 4, byte_order); + + rN_regnum = translate_rreg (rN); + + stack.store (regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]); + regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm32); + + pc += 7; + } + /* mov imm8, aN */ + else if ((instr[0] & 0xf0) == 0x90) + { + int aN = instr[0] & 0x03; + LONGEST imm8; + + imm8 = extract_signed_integer (&instr[1], 1, byte_order); + + regs[E_A0_REGNUM + aN] = pv_constant (imm8); + pc += 2; + } + /* mov imm16, aN */ + else if ((instr[0] & 0xfc) == 0x24) + { + int aN = instr[0] & 0x03; + gdb_byte buf[2]; + LONGEST imm16; + + status = target_read_memory (pc + 1, buf, 2); + if (status != 0) + break; + + imm16 = extract_signed_integer (buf, 2, byte_order); + regs[E_A0_REGNUM + aN] = pv_constant (imm16); + pc += 3; + } + /* mov imm32, aN */ + else if (instr[0] == 0xfc && ((instr[1] & 0xfc) == 0xdc)) + { + int aN = instr[1] & 0x03; + gdb_byte buf[4]; + LONGEST imm32; + + status = target_read_memory (pc + 2, buf, 4); + if (status != 0) + break; + + imm32 = extract_signed_integer (buf, 4, byte_order); + regs[E_A0_REGNUM + aN] = pv_constant (imm32); + pc += 6; + } + /* mov imm8, dN */ + else if ((instr[0] & 0xf0) == 0x80) + { + int dN = instr[0] & 0x03; + LONGEST imm8; + + imm8 = extract_signed_integer (&instr[1], 1, byte_order); + + regs[E_D0_REGNUM + dN] = pv_constant (imm8); + pc += 2; + } + /* mov imm16, dN */ + else if ((instr[0] & 0xfc) == 0x2c) + { + int dN = instr[0] & 0x03; + gdb_byte buf[2]; + LONGEST imm16; + + status = target_read_memory (pc + 1, buf, 2); + if (status != 0) + break; + + imm16 = extract_signed_integer (buf, 2, byte_order); + regs[E_D0_REGNUM + dN] = pv_constant (imm16); + pc += 3; + } + /* mov imm32, dN */ + else if (instr[0] == 0xfc && ((instr[1] & 0xfc) == 0xcc)) + { + int dN = instr[1] & 0x03; + gdb_byte buf[4]; + LONGEST imm32; + + status = target_read_memory (pc + 2, buf, 4); + if (status != 0) + break; + + imm32 = extract_signed_integer (buf, 4, byte_order); + regs[E_D0_REGNUM + dN] = pv_constant (imm32); + pc += 6; + } + else + { + /* We've hit some instruction that we don't recognize. Hopefully, + we have enough to do prologue analysis. */ + break; + } + } + + /* Is the frame size (offset, really) a known constant? */ + if (pv_is_register (regs[E_SP_REGNUM], E_SP_REGNUM)) + result->frame_size = regs[E_SP_REGNUM].k; + + /* Was the frame pointer initialized? */ + if (pv_is_register (regs[E_A3_REGNUM], E_SP_REGNUM)) + { + result->has_frame_ptr = 1; + result->frame_ptr_offset = regs[E_A3_REGNUM].k; } - /* Do the essentials and get out of here. */ - finish_prologue: - /* Note if/where callee saved registers were saved. */ - if (fi) - set_reg_offsets (fi, this_cache, movm_args, fpregmask, stack_extra_size, frame_in_fp); - return addr; + + /* Record where all the registers were saved. */ + stack.scan (check_for_saved, (void *) result); + + result->prologue_end = after_last_frame_setup_insn; } /* Function: skip_prologue Return the address of the first inst past the prologue of the function. */ static CORE_ADDR -mn10300_skip_prologue (CORE_ADDR pc) +mn10300_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { - return mn10300_analyze_prologue (NULL, NULL, pc); + const char *name; + CORE_ADDR func_addr, func_end; + struct mn10300_prologue p; + + /* Try to find the extent of the function that contains PC. */ + if (!find_pc_partial_function (pc, &name, &func_addr, &func_end)) + return pc; + + mn10300_analyze_prologue (gdbarch, pc, func_end, &p); + return p.prologue_end; } -/* Simple frame_unwind_cache. - This finds the "extra info" for the frame. */ -struct trad_frame_cache * -mn10300_frame_unwind_cache (struct frame_info *next_frame, - void **this_prologue_cache) +/* Wrapper for mn10300_analyze_prologue: find the function start; + use the current frame PC as the limit, then + invoke mn10300_analyze_prologue and return its result. */ +static struct mn10300_prologue * +mn10300_analyze_frame_prologue (struct frame_info *this_frame, + void **this_prologue_cache) { - struct trad_frame_cache *cache; - CORE_ADDR pc, start, end; - - if (*this_prologue_cache) - return (*this_prologue_cache); - - cache = trad_frame_cache_zalloc (next_frame); - pc = gdbarch_unwind_pc (get_frame_arch (next_frame), next_frame); - mn10300_analyze_prologue (next_frame, (void **) &cache, pc); - if (find_pc_partial_function (pc, NULL, &start, &end)) - trad_frame_set_id (cache, - frame_id_build (trad_frame_get_this_base (cache), - start)); - else + if (!*this_prologue_cache) { - start = frame_func_unwind (next_frame, NORMAL_FRAME); - trad_frame_set_id (cache, - frame_id_build (trad_frame_get_this_base (cache), - start)); + CORE_ADDR func_start, stop_addr; + + *this_prologue_cache = FRAME_OBSTACK_ZALLOC (struct mn10300_prologue); + + func_start = get_frame_func (this_frame); + stop_addr = get_frame_pc (this_frame); + + /* If we couldn't find any function containing the PC, then + just initialize the prologue cache, but don't do anything. */ + if (!func_start) + stop_addr = func_start; + + mn10300_analyze_prologue (get_frame_arch (this_frame), + func_start, stop_addr, + ((struct mn10300_prologue *) + *this_prologue_cache)); } - (*this_prologue_cache) = cache; - return cache; + return (struct mn10300_prologue *) *this_prologue_cache; } -/* Here is a dummy implementation. */ -static struct frame_id -mn10300_unwind_dummy_id (struct gdbarch *gdbarch, - struct frame_info *next_frame) +/* Given the next frame and a prologue cache, return this frame's + base. */ +static CORE_ADDR +mn10300_frame_base (struct frame_info *this_frame, void **this_prologue_cache) { - return frame_id_build (frame_sp_unwind (next_frame), - frame_pc_unwind (next_frame)); + struct mn10300_prologue *p + = mn10300_analyze_frame_prologue (this_frame, this_prologue_cache); + + /* In functions that use alloca, the distance between the stack + pointer and the frame base varies dynamically, so we can't use + the SP plus static information like prologue analysis to find the + frame base. However, such functions must have a frame pointer, + to be able to restore the SP on exit. So whenever we do have a + frame pointer, use that to find the base. */ + if (p->has_frame_ptr) + { + CORE_ADDR fp = get_frame_register_unsigned (this_frame, E_A3_REGNUM); + return fp - p->frame_ptr_offset; + } + else + { + CORE_ADDR sp = get_frame_register_unsigned (this_frame, E_SP_REGNUM); + return sp - p->frame_size; + } } -/* Trad frame implementation. */ static void -mn10300_frame_this_id (struct frame_info *next_frame, +mn10300_frame_this_id (struct frame_info *this_frame, void **this_prologue_cache, struct frame_id *this_id) { - struct trad_frame_cache *cache = - mn10300_frame_unwind_cache (next_frame, this_prologue_cache); + *this_id = frame_id_build (mn10300_frame_base (this_frame, + this_prologue_cache), + get_frame_func (this_frame)); - trad_frame_get_id (cache, this_id); } -static void -mn10300_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, gdb_byte *bufferp) +static struct value * +mn10300_frame_prev_register (struct frame_info *this_frame, + void **this_prologue_cache, int regnum) { - struct trad_frame_cache *cache = - mn10300_frame_unwind_cache (next_frame, this_prologue_cache); - - trad_frame_get_register (cache, next_frame, regnum, optimizedp, - lvalp, addrp, realnump, bufferp); - /* Or... - trad_frame_get_prev_register (next_frame, cache->prev_regs, regnum, - optimizedp, lvalp, addrp, realnump, bufferp); - */ + struct mn10300_prologue *p + = mn10300_analyze_frame_prologue (this_frame, this_prologue_cache); + CORE_ADDR frame_base = mn10300_frame_base (this_frame, this_prologue_cache); + + if (regnum == E_SP_REGNUM) + return frame_unwind_got_constant (this_frame, regnum, frame_base); + + /* If prologue analysis says we saved this register somewhere, + return a description of the stack slot holding it. */ + 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. */ + return frame_unwind_got_register (this_frame, regnum, regnum); } static const struct frame_unwind mn10300_frame_unwind = { NORMAL_FRAME, + default_frame_unwind_stop_reason, mn10300_frame_this_id, - mn10300_frame_prev_register + mn10300_frame_prev_register, + NULL, + default_frame_sniffer }; -static CORE_ADDR -mn10300_frame_base_address (struct frame_info *next_frame, - void **this_prologue_cache) -{ - struct trad_frame_cache *cache = - mn10300_frame_unwind_cache (next_frame, this_prologue_cache); - - return trad_frame_get_this_base (cache); -} - -static const struct frame_unwind * -mn10300_frame_sniffer (struct frame_info *next_frame) -{ - return &mn10300_frame_unwind; -} - -static const struct frame_base mn10300_frame_base = { - &mn10300_frame_unwind, - mn10300_frame_base_address, - mn10300_frame_base_address, - mn10300_frame_base_address -}; - -static CORE_ADDR -mn10300_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) -{ - ULONGEST pc; - - pc = frame_unwind_register_unsigned (next_frame, E_PC_REGNUM); - return pc; -} - -static CORE_ADDR -mn10300_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) -{ - ULONGEST sp; - - sp = frame_unwind_register_unsigned (next_frame, E_SP_REGNUM); - return sp; -} - static void mn10300_frame_unwind_init (struct gdbarch *gdbarch) { - frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer); - frame_unwind_append_sniffer (gdbarch, mn10300_frame_sniffer); - frame_base_set_default (gdbarch, &mn10300_frame_base); - set_gdbarch_unwind_dummy_id (gdbarch, mn10300_unwind_dummy_id); - set_gdbarch_unwind_pc (gdbarch, mn10300_unwind_pc); - set_gdbarch_unwind_sp (gdbarch, mn10300_unwind_sp); + dwarf2_append_unwinders (gdbarch); + frame_unwind_append_unwinder (gdbarch, &mn10300_frame_unwind); } /* Function: push_dummy_call @@ -973,15 +1161,17 @@ mn10300_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp, - int struct_return, + function_call_return_method return_method, CORE_ADDR struct_addr) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); const int push_size = register_size (gdbarch, E_PC_REGNUM); int regs_used; int len, arg_len; int stack_offset = 0; int argnum; - char *val, valbuf[MAX_REGISTER_SIZE]; + const gdb_byte *val; + gdb_byte valbuf[MN10300_MAX_REGISTER_SIZE]; /* This should be a nop, but align the stack just in case something went wrong. Stacks are four byte aligned on the mn10300. */ @@ -991,7 +1181,7 @@ mn10300_push_dummy_call (struct gdbarch *gdbarch, XXX This doesn't appear to handle pass-by-invisible reference arguments. */ - regs_used = struct_return ? 1 : 0; + regs_used = (return_method == return_method_struct) ? 1 : 0; for (len = 0, argnum = 0; argnum < nargs; argnum++) { arg_len = (TYPE_LENGTH (value_type (args[argnum])) + 3) & ~3; @@ -1006,7 +1196,7 @@ mn10300_push_dummy_call (struct gdbarch *gdbarch, /* Allocate stack space. */ sp -= len; - if (struct_return) + if (return_method == return_method_struct) { regs_used = 1; regcache_cooked_write_unsigned (regcache, E_D0_REGNUM, struct_addr); @@ -1014,7 +1204,7 @@ mn10300_push_dummy_call (struct gdbarch *gdbarch, else regs_used = 0; - /* Push all arguments onto the stack. */ + /* Push all arguments onto the stack. */ for (argnum = 0; argnum < nargs; argnum++) { /* FIXME what about structs? Unions? */ @@ -1023,20 +1213,21 @@ mn10300_push_dummy_call (struct gdbarch *gdbarch, { /* Change to pointer-to-type. */ arg_len = push_size; - store_unsigned_integer (valbuf, push_size, - VALUE_ADDRESS (*args)); + gdb_assert (push_size <= MN10300_MAX_REGISTER_SIZE); + store_unsigned_integer (valbuf, push_size, byte_order, + value_address (*args)); val = &valbuf[0]; } else { arg_len = TYPE_LENGTH (value_type (*args)); - val = (char *) value_contents (*args); + val = value_contents (*args); } while (regs_used < 2 && arg_len > 0) { regcache_cooked_write_unsigned (regcache, regs_used, - extract_unsigned_integer (val, push_size)); + extract_unsigned_integer (val, push_size, byte_order)); val += push_size; arg_len -= push_size; regs_used++; @@ -1058,7 +1249,7 @@ mn10300_push_dummy_call (struct gdbarch *gdbarch, /* Push the return address that contains the magic breakpoint. */ sp -= 4; - write_memory_unsigned_integer (sp, push_size, bp_addr); + write_memory_unsigned_integer (sp, push_size, byte_order, bp_addr); /* The CPU also writes the return address always into the MDR register on "call". */ @@ -1066,6 +1257,33 @@ mn10300_push_dummy_call (struct gdbarch *gdbarch, /* Update $sp. */ regcache_cooked_write_unsigned (regcache, E_SP_REGNUM, sp); + + /* On the mn10300, it's possible to move some of the stack adjustment + and saving of the caller-save registers out of the prologue and + into the call sites. (When using gcc, this optimization can + occur when using the -mrelax switch.) If this occurs, the dwarf2 + info will reflect this fact. We can test to see if this is the + case by creating a new frame using the current stack pointer and + the address of the function that we're about to call. We then + unwind SP and see if it's different than the SP of our newly + created frame. If the SP values are the same, the caller is not + expected to allocate any additional stack. On the other hand, if + the SP values are different, the difference determines the + additional stack that must be allocated. + + Note that we don't update the return value though because that's + the value of the stack just after pushing the arguments, but prior + to performing the call. This value is needed in order to + construct the frame ID of the dummy call. */ + { + CORE_ADDR func_addr = find_function_addr (target_func, NULL); + CORE_ADDR unwound_sp + = gdbarch_unwind_sp (gdbarch, create_new_frame (sp, func_addr)); + if (sp != unwound_sp) + regcache_cooked_write_unsigned (regcache, E_SP_REGNUM, + sp - (unwound_sp - sp)); + } + return sp; } @@ -1077,28 +1295,38 @@ mn10300_push_dummy_call (struct gdbarch *gdbarch, to work with the existing GDB, neither of them can change. So we just have to cope. */ static int -mn10300_dwarf2_reg_to_regnum (int dwarf2) +mn10300_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int dwarf2) { /* This table is supposed to be shaped like the gdbarch_register_name initializer in gcc/config/mn10300/mn10300.h. Registers which appear in GCC's numbering, but have no counterpart in GDB's world, are marked with a -1. */ static int dwarf2_to_gdb[] = { - 0, 1, 2, 3, 4, 5, 6, 7, -1, 8, - 15, 16, 17, 18, 19, 20, 21, 22, - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, - 9 + E_D0_REGNUM, E_D1_REGNUM, E_D2_REGNUM, E_D3_REGNUM, + E_A0_REGNUM, E_A1_REGNUM, E_A2_REGNUM, E_A3_REGNUM, + -1, E_SP_REGNUM, + + E_E0_REGNUM, E_E1_REGNUM, E_E2_REGNUM, E_E3_REGNUM, + E_E4_REGNUM, E_E5_REGNUM, E_E6_REGNUM, E_E7_REGNUM, + + E_FS0_REGNUM + 0, E_FS0_REGNUM + 1, E_FS0_REGNUM + 2, E_FS0_REGNUM + 3, + E_FS0_REGNUM + 4, E_FS0_REGNUM + 5, E_FS0_REGNUM + 6, E_FS0_REGNUM + 7, + + E_FS0_REGNUM + 8, E_FS0_REGNUM + 9, E_FS0_REGNUM + 10, E_FS0_REGNUM + 11, + E_FS0_REGNUM + 12, E_FS0_REGNUM + 13, E_FS0_REGNUM + 14, E_FS0_REGNUM + 15, + + E_FS0_REGNUM + 16, E_FS0_REGNUM + 17, E_FS0_REGNUM + 18, E_FS0_REGNUM + 19, + E_FS0_REGNUM + 20, E_FS0_REGNUM + 21, E_FS0_REGNUM + 22, E_FS0_REGNUM + 23, + + E_FS0_REGNUM + 24, E_FS0_REGNUM + 25, E_FS0_REGNUM + 26, E_FS0_REGNUM + 27, + E_FS0_REGNUM + 28, E_FS0_REGNUM + 29, E_FS0_REGNUM + 30, E_FS0_REGNUM + 31, + + E_MDR_REGNUM, E_PSW_REGNUM, E_PC_REGNUM }; if (dwarf2 < 0 || dwarf2 >= ARRAY_SIZE (dwarf2_to_gdb)) - { - warning (_("Bogus register number in debug info: %d"), dwarf2); - return -1; - } + return -1; return dwarf2_to_gdb[dwarf2]; } @@ -1115,7 +1343,7 @@ mn10300_gdbarch_init (struct gdbarch_info info, if (arches != NULL) return arches->gdbarch; - tdep = xmalloc (sizeof (struct gdbarch_tdep)); + tdep = XCNEW (struct gdbarch_tdep); gdbarch = gdbarch_alloc (&info, tdep); switch (info.bfd_arch_info->mach) @@ -1143,12 +1371,13 @@ mn10300_gdbarch_init (struct gdbarch_info info, break; } + /* By default, chars are unsigned. */ + set_gdbarch_char_signed (gdbarch, 0); + /* Registers. */ set_gdbarch_num_regs (gdbarch, num_regs); set_gdbarch_register_type (gdbarch, mn10300_register_type); set_gdbarch_skip_prologue (gdbarch, mn10300_skip_prologue); - set_gdbarch_read_pc (gdbarch, mn10300_read_pc); - set_gdbarch_write_pc (gdbarch, mn10300_write_pc); set_gdbarch_pc_regnum (gdbarch, E_PC_REGNUM); set_gdbarch_sp_regnum (gdbarch, E_SP_REGNUM); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, mn10300_dwarf2_reg_to_regnum); @@ -1156,10 +1385,11 @@ mn10300_gdbarch_init (struct gdbarch_info info, /* Stack unwinding. */ set_gdbarch_inner_than (gdbarch, core_addr_lessthan); /* Breakpoints. */ - set_gdbarch_breakpoint_from_pc (gdbarch, mn10300_breakpoint_from_pc); - /* decr_pc_after_break? */ - /* Disassembly. */ - set_gdbarch_print_insn (gdbarch, print_insn_mn10300); + set_gdbarch_breakpoint_kind_from_pc (gdbarch, + mn10300_breakpoint::kind_from_pc); + set_gdbarch_sw_breakpoint_from_kind (gdbarch, + mn10300_breakpoint::bp_from_kind); + /* decr_pc_after_break? */ /* Stage 2 */ set_gdbarch_return_value (gdbarch, mn10300_return_value); @@ -1177,7 +1407,7 @@ mn10300_gdbarch_init (struct gdbarch_info info, return gdbarch; } -/* Dump out the mn10300 specific architecture information. */ +/* Dump out the mn10300 specific architecture information. */ static void mn10300_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)