X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fm32r-tdep.c;h=26deea0d5eed0314564b5116f49a127f82cb44de;hb=e122f1f5f1f443e5297d87eb971009456ac792cb;hp=8ea87ae7d160c464cb386dde7e16a04f10f7bc29;hpb=b5622e8d3cc3ba6ed60cbfee39a9c094074e27a1;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c index 8ea87ae7d1..26deea0d5e 100644 --- a/gdb/m32r-tdep.c +++ b/gdb/m32r-tdep.c @@ -1,7 +1,7 @@ /* Target-dependent code for Renesas M32R, for GDB. - Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003 Free Software - Foundation, Inc. + Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free + Software Foundation, Inc. This file is part of GDB. @@ -33,6 +33,7 @@ #include "inferior.h" #include "symfile.h" #include "objfiles.h" +#include "osabi.h" #include "language.h" #include "arch-utils.h" #include "regcache.h" @@ -41,27 +42,7 @@ #include "gdb_assert.h" -struct gdbarch_tdep -{ - /* gdbarch target dependent data here. Currently unused for M32R. */ -}; - -/* m32r register names. */ - -enum -{ - R0_REGNUM = 0, - R3_REGNUM = 3, - M32R_FP_REGNUM = 13, - LR_REGNUM = 14, - M32R_SP_REGNUM = 15, - PSW_REGNUM = 16, - M32R_PC_REGNUM = 21, - /* m32r calling convention. */ - ARG1_REGNUM = R0_REGNUM, - ARGN_REGNUM = R3_REGNUM, - RET1_REGNUM = R0_REGNUM, -}; +#include "m32r-tdep.h" /* Local functions */ @@ -75,124 +56,116 @@ m32r_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) return sp & ~3; } -/* Should we use DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS instead of - EXTRACT_RETURN_VALUE? GCC_P is true if compiled with gcc and TYPE - is the type (which is known to be struct, union or array). - - The m32r returns anything less than 8 bytes in size in - registers. */ - -static int -m32r_use_struct_convention (int gcc_p, struct type *type) -{ - return (TYPE_LENGTH (type) > 8); -} - -/* BREAKPOINT */ -#define M32R_BE_BREAKPOINT32 {0x10, 0xf1, 0x70, 0x00} -#define M32R_LE_BREAKPOINT32 {0xf1, 0x10, 0x00, 0x70} -#define M32R_BE_BREAKPOINT16 {0x10, 0xf1} -#define M32R_LE_BREAKPOINT16 {0xf1, 0x10} +/* Breakpoints + + The little endian mode of M32R is unique. In most of architectures, + two 16-bit instructions, A and B, are placed as the following: + + Big endian: + A0 A1 B0 B1 + + Little endian: + A1 A0 B1 B0 + + In M32R, they are placed like this: + + Big endian: + A0 A1 B0 B1 + + Little endian: + B1 B0 A1 A0 + + This is because M32R always fetches instructions in 32-bit. + + The following functions take care of this behavior. */ static int -m32r_memory_insert_breakpoint (CORE_ADDR addr, char *contents_cache) +m32r_memory_insert_breakpoint (CORE_ADDR addr, bfd_byte *contents_cache) { int val; - unsigned char *bp; - int bplen; - - bplen = (addr & 3) ? 2 : 4; + char buf[4]; + char bp_entry[] = { 0x10, 0xf1 }; /* dpt */ /* Save the memory contents. */ - val = target_read_memory (addr, contents_cache, bplen); + val = target_read_memory (addr & 0xfffffffc, contents_cache, 4); if (val != 0) return val; /* return error */ /* Determine appropriate breakpoint contents and size for this address. */ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) { - if (((addr & 3) == 0) - && ((contents_cache[0] & 0x80) || (contents_cache[2] & 0x80))) + if ((addr & 3) == 0) { - static unsigned char insn[] = M32R_BE_BREAKPOINT32; - bp = insn; - bplen = sizeof (insn); + buf[0] = bp_entry[0]; + buf[1] = bp_entry[1]; + buf[2] = contents_cache[2] & 0x7f; + buf[3] = contents_cache[3]; } else { - static unsigned char insn[] = M32R_BE_BREAKPOINT16; - bp = insn; - bplen = sizeof (insn); + buf[0] = contents_cache[0]; + buf[1] = contents_cache[1]; + buf[2] = bp_entry[0]; + buf[3] = bp_entry[1]; } } - else - { /* little-endian */ - if (((addr & 3) == 0) - && ((contents_cache[1] & 0x80) || (contents_cache[3] & 0x80))) + else /* little-endian */ + { + if ((addr & 3) == 0) { - static unsigned char insn[] = M32R_LE_BREAKPOINT32; - bp = insn; - bplen = sizeof (insn); + buf[0] = contents_cache[0]; + buf[1] = contents_cache[1] & 0x7f; + buf[2] = bp_entry[1]; + buf[3] = bp_entry[0]; } else { - static unsigned char insn[] = M32R_LE_BREAKPOINT16; - bp = insn; - bplen = sizeof (insn); + buf[0] = bp_entry[1]; + buf[1] = bp_entry[0]; + buf[2] = contents_cache[2]; + buf[3] = contents_cache[3]; } } /* Write the breakpoint. */ - val = target_write_memory (addr, (char *) bp, bplen); + val = target_write_memory (addr & 0xfffffffc, buf, 4); return val; } static int -m32r_memory_remove_breakpoint (CORE_ADDR addr, char *contents_cache) +m32r_memory_remove_breakpoint (CORE_ADDR addr, bfd_byte *contents_cache) { int val; - int bplen; + char buf[4]; - /* Determine appropriate breakpoint contents and size for this address. */ + buf[0] = contents_cache[0]; + buf[1] = contents_cache[1]; + buf[2] = contents_cache[2]; + buf[3] = contents_cache[3]; + + /* Remove parallel bit. */ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) { - if (((addr & 3) == 0) - && ((contents_cache[0] & 0x80) || (contents_cache[2] & 0x80))) - { - static unsigned char insn[] = M32R_BE_BREAKPOINT32; - bplen = sizeof (insn); - } - else - { - static unsigned char insn[] = M32R_BE_BREAKPOINT16; - bplen = sizeof (insn); - } + if ((buf[0] & 0x80) == 0 && (buf[2] & 0x80) != 0) + buf[2] &= 0x7f; } - else + else /* little-endian */ { - /* little-endian */ - if (((addr & 3) == 0) - && ((contents_cache[1] & 0x80) || (contents_cache[3] & 0x80))) - { - static unsigned char insn[] = M32R_BE_BREAKPOINT32; - bplen = sizeof (insn); - } - else - { - static unsigned char insn[] = M32R_BE_BREAKPOINT16; - bplen = sizeof (insn); - } + if ((buf[3] & 0x80) == 0 && (buf[1] & 0x80) != 0) + buf[1] &= 0x7f; } /* Write contents. */ - val = target_write_memory (addr, contents_cache, bplen); + val = target_write_memory (addr & 0xfffffffc, buf, 4); return val; } static const unsigned char * m32r_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) { + static char be_bp_entry[] = { 0x10, 0xf1, 0x70, 0x00 }; /* dpt -> nop */ + static char le_bp_entry[] = { 0x00, 0x70, 0xf1, 0x10 }; /* dpt -> nop */ unsigned char *bp; /* Determine appropriate breakpoint. */ @@ -200,30 +173,26 @@ m32r_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) { if ((*pcptr & 3) == 0) { - static unsigned char insn[] = M32R_BE_BREAKPOINT32; - bp = insn; - *lenptr = sizeof (insn); + bp = be_bp_entry; + *lenptr = 4; } else { - static unsigned char insn[] = M32R_BE_BREAKPOINT16; - bp = insn; - *lenptr = sizeof (insn); + bp = be_bp_entry; + *lenptr = 2; } } else { if ((*pcptr & 3) == 0) { - static unsigned char insn[] = M32R_LE_BREAKPOINT32; - bp = insn; - *lenptr = sizeof (insn); + bp = le_bp_entry; + *lenptr = 4; } else { - static unsigned char insn[] = M32R_LE_BREAKPOINT16; - bp = insn; - *lenptr = sizeof (insn); + bp = le_bp_entry + 2; + *lenptr = 2; } } @@ -238,18 +207,12 @@ char *m32r_register_names[] = { "evb" }; -static int -m32r_num_regs (void) -{ - return (sizeof (m32r_register_names) / sizeof (m32r_register_names[0])); -} - static const char * m32r_register_name (int reg_nr) { if (reg_nr < 0) return NULL; - if (reg_nr >= m32r_num_regs ()) + if (reg_nr >= M32R_NUM_REGS) return NULL; return m32r_register_names[reg_nr]; } @@ -292,69 +255,56 @@ m32r_store_return_value (struct type *type, struct regcache *regcache, } } -/* Extract from an array REGBUF containing the (raw) register state - the address in which a function should return its structure value, - as a CORE_ADDR (or an expression that can be used as one). */ - -static CORE_ADDR -m32r_extract_struct_value_address (struct regcache *regcache) -{ - ULONGEST addr; - regcache_cooked_read_unsigned (regcache, ARG1_REGNUM, &addr); - return addr; -} - - /* This is required by skip_prologue. The results of decoding a prologue should be cached because this thrashing is getting nuts. */ -static void +static int decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, - CORE_ADDR *pl_endptr) + CORE_ADDR *pl_endptr, unsigned long *framelength) { unsigned long framesize; int insn; int op1; - int maybe_one_more = 0; CORE_ADDR after_prologue = 0; + CORE_ADDR after_push = 0; CORE_ADDR after_stack_adjust = 0; CORE_ADDR current_pc; + LONGEST return_value; framesize = 0; after_prologue = 0; for (current_pc = start_pc; current_pc < scan_limit; current_pc += 2) { + /* Check if current pc's location is readable. */ + if (!safe_read_memory_integer (current_pc, 2, &return_value)) + return -1; + insn = read_memory_unsigned_integer (current_pc, 2); + if (insn == 0x0000) + break; + /* If this is a 32 bit instruction, we dont want to examine its immediate data as though it were an instruction */ if (current_pc & 0x02) { - /* Clear the parallel execution bit from 16 bit instruction */ - if (maybe_one_more) - { - /* The last instruction was a branch, usually terminates - the series, but if this is a parallel instruction, - it may be a stack framing instruction */ - if (!(insn & 0x8000)) - { - /* nope, we are really done */ - break; - } - } /* decode this instruction further */ insn &= 0x7fff; } else { - if (maybe_one_more) - break; /* This isnt the one more */ if (insn & 0x8000) { if (current_pc == scan_limit) scan_limit += 2; /* extend the search */ + current_pc += 2; /* skip the immediate data */ + + /* Check if current pc's location is readable. */ + if (!safe_read_memory_integer (current_pc, 2, &return_value)) + return -1; + if (insn == 0x8faf) /* add3 sp, sp, xxxx */ /* add 16 bit sign-extended offset */ { @@ -364,6 +314,8 @@ decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, else { if (((insn >> 8) == 0xe4) /* ld24 r4, xxxxxx; sub sp, r4 */ + && safe_read_memory_integer (current_pc + 2, 2, + &return_value) && read_memory_unsigned_integer (current_pc + 2, 2) == 0x0f24) /* subtract 24 bit sign-extended negative-offset */ @@ -376,7 +328,7 @@ decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, framesize += insn; } } - after_prologue = current_pc; + after_push = current_pc + 2; continue; } } @@ -415,17 +367,23 @@ decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, after_prologue = current_pc + 2; break; /* end of stack adjustments */ } + /* Nop looks like a branch, continue explicitly */ if (insn == 0x7000) { after_prologue = current_pc + 2; continue; /* nop occurs between pushes */ } + /* End of prolog if any of these are trap instructions */ + if ((insn & 0xfff0) == 0x10f0) + { + after_prologue = current_pc; + break; + } /* End of prolog if any of these are branch instructions */ if ((op1 == 0x7000) || (op1 == 0xb000) || (op1 == 0xf000)) { after_prologue = current_pc; - maybe_one_more = 1; continue; } /* Some of the branch instructions are mixed with other types */ @@ -435,12 +393,14 @@ decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, if ((subop == 0x0ec0) || (subop == 0x0fc0)) { after_prologue = current_pc; - maybe_one_more = 1; continue; /* jmp , jl */ } } } + if (framelength) + *framelength = framesize; + if (current_pc >= scan_limit) { if (pl_endptr) @@ -452,6 +412,13 @@ decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, { *pl_endptr = after_stack_adjust; } + else if (after_push != 0) + /* We did not find a "mv fp,sp", but we DID find + a push. Is it safe to use that as the + end of the prologue? I just don't know. */ + { + *pl_endptr = after_push; + } else /* We reached the end of the loop without finding the end of the prologue. No way to win -- we should report failure. @@ -459,25 +426,29 @@ decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, GDB will set a breakpoint at the start of the function (etc.) */ *pl_endptr = start_pc; } - return; + return 0; } + if (after_prologue == 0) after_prologue = current_pc; if (pl_endptr) *pl_endptr = after_prologue; + + return 0; } /* decode_prologue */ /* Function: skip_prologue Find end of function prologue */ -#define DEFAULT_SEARCH_LIMIT 44 +#define DEFAULT_SEARCH_LIMIT 128 CORE_ADDR m32r_skip_prologue (CORE_ADDR pc) { CORE_ADDR func_addr, func_end; struct symtab_and_line sal; + LONGEST return_value; /* See what the symbol table says */ @@ -499,11 +470,18 @@ m32r_skip_prologue (CORE_ADDR pc) } else func_end = pc + DEFAULT_SEARCH_LIMIT; - decode_prologue (pc, func_end, &sal.end); + + /* If pc's location is not readable, just quit. */ + if (!safe_read_memory_integer (pc, 4, &return_value)) + return pc; + + /* Find the end of prologue. */ + if (decode_prologue (pc, func_end, &sal.end, NULL) < 0) + return pc; + return sal.end; } - struct m32r_unwind_cache { /* The previous frame's inner most stack address. Used as this @@ -532,13 +510,14 @@ static struct m32r_unwind_cache * m32r_frame_unwind_cache (struct frame_info *next_frame, void **this_prologue_cache) { - CORE_ADDR pc; + CORE_ADDR pc, scan_limit; ULONGEST prev_sp; ULONGEST this_base; - unsigned long op; + unsigned long op, op2; int i; struct m32r_unwind_cache *info; + if ((*this_prologue_cache)) return (*this_prologue_cache); @@ -548,10 +527,11 @@ m32r_frame_unwind_cache (struct frame_info *next_frame, info->size = 0; info->sp_offset = 0; - info->uses_frame = 0; + + scan_limit = frame_pc_unwind (next_frame); for (pc = frame_func_unwind (next_frame); - pc > 0 && pc < frame_pc_unwind (next_frame); pc += 2) + pc > 0 && pc < scan_limit; pc += 2) { if ((pc & 2) == 0) { @@ -565,18 +545,19 @@ m32r_frame_unwind_cache (struct frame_info *next_frame, short n = op & 0xffff; info->sp_offset += n; } - else if (((op >> 8) == 0xe4) /* ld24 r4, xxxxxx; sub sp, r4 */ - && get_frame_memory_unsigned (next_frame, pc + 4, + else if (((op >> 8) == 0xe4) + && get_frame_memory_unsigned (next_frame, pc + 2, 2) == 0x0f24) { + /* ld24 r4, xxxxxx; sub sp, r4 */ unsigned long n = op & 0xffffff; info->sp_offset += n; - pc += 2; + pc += 2; /* skip sub instruction */ } - else - break; - pc += 2; + if (pc == scan_limit) + scan_limit += 2; /* extend the search */ + pc += 2; /* skip the immediate data */ continue; } } @@ -601,12 +582,13 @@ m32r_frame_unwind_cache (struct frame_info *next_frame, /* mv fp, sp */ info->uses_frame = 1; info->r13_offset = info->sp_offset; + break; /* end of stack adjustments */ + } + else if ((op & 0xfff0) == 0x10f0) + { + /* end of prologue if this is a trap instruction */ + break; /* end of stack adjustments */ } - else if (op == 0x7000) - /* nop */ - continue; - else - break; } info->size = -info->sp_offset; @@ -720,12 +702,12 @@ m32r_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Now make sure there's space on the stack */ for (argnum = 0, stack_alloc = 0; argnum < nargs; argnum++) - stack_alloc += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 3) & ~3); + stack_alloc += ((TYPE_LENGTH (value_type (args[argnum])) + 3) & ~3); sp -= stack_alloc; /* make room on stack for args */ for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++) { - type = VALUE_TYPE (args[argnum]); + type = value_type (args[argnum]); typecode = TYPE_CODE (type); len = TYPE_LENGTH (type); @@ -744,11 +726,11 @@ m32r_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { /* value gets right-justified in the register or stack word */ memcpy (valbuf + (register_size (gdbarch, argreg) - len), - (char *) VALUE_CONTENTS (args[argnum]), len); + (char *) value_contents (args[argnum]), len); val = valbuf; } else - val = (char *) VALUE_CONTENTS (args[argnum]); + val = (char *) value_contents (args[argnum]); while (len > 0) { @@ -807,6 +789,24 @@ m32r_extract_return_value (struct type *type, struct regcache *regcache, } } +enum return_value_convention +m32r_return_value (struct gdbarch *gdbarch, struct type *valtype, + struct regcache *regcache, void *readbuf, + const void *writebuf) +{ + if (TYPE_LENGTH (valtype) > 8) + return RETURN_VALUE_STRUCT_CONVENTION; + else + { + if (readbuf != NULL) + m32r_extract_return_value (valtype, regcache, readbuf); + if (writebuf != NULL) + m32r_store_return_value (valtype, regcache, writebuf); + return RETURN_VALUE_REGISTER_CONVENTION; + } +} + + static CORE_ADDR m32r_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) @@ -856,8 +856,8 @@ m32r_frame_prev_register (struct frame_info *next_frame, { struct m32r_unwind_cache *info = m32r_frame_unwind_cache (next_frame, this_prologue_cache); - trad_frame_prev_register (next_frame, info->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, bufferp); + trad_frame_get_prev_register (next_frame, info->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, bufferp); } static const struct frame_unwind m32r_frame_unwind = { @@ -921,16 +921,13 @@ m32r_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_write_pc (gdbarch, m32r_write_pc); set_gdbarch_unwind_sp (gdbarch, m32r_unwind_sp); - set_gdbarch_num_regs (gdbarch, m32r_num_regs ()); + set_gdbarch_num_regs (gdbarch, M32R_NUM_REGS); set_gdbarch_sp_regnum (gdbarch, M32R_SP_REGNUM); set_gdbarch_register_name (gdbarch, m32r_register_name); set_gdbarch_register_type (gdbarch, m32r_register_type); - set_gdbarch_extract_return_value (gdbarch, m32r_extract_return_value); set_gdbarch_push_dummy_call (gdbarch, m32r_push_dummy_call); - set_gdbarch_store_return_value (gdbarch, m32r_store_return_value); - set_gdbarch_deprecated_extract_struct_value_address (gdbarch, m32r_extract_struct_value_address); - set_gdbarch_deprecated_use_struct_convention (gdbarch, m32r_use_struct_convention); + set_gdbarch_return_value (gdbarch, m32r_return_value); set_gdbarch_skip_prologue (gdbarch, m32r_skip_prologue); set_gdbarch_inner_than (gdbarch, core_addr_lessthan); @@ -940,11 +937,8 @@ m32r_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_memory_remove_breakpoint (gdbarch, m32r_memory_remove_breakpoint); - set_gdbarch_deprecated_frameless_function_invocation (gdbarch, legacy_frameless_look_for_prologue); - set_gdbarch_frame_align (gdbarch, m32r_frame_align); - frame_unwind_append_sniffer (gdbarch, m32r_frame_sniffer); frame_base_set_default (gdbarch, &m32r_frame_base); /* Methods for saving / extracting a dummy frame's ID. The ID's @@ -957,6 +951,12 @@ m32r_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_print_insn (gdbarch, print_insn_m32r); + /* Hook in ABI-specific overrides, if they have been registered. */ + gdbarch_init_osabi (info, gdbarch); + + /* Hook in the default unwinders. */ + frame_unwind_append_sniffer (gdbarch, m32r_frame_sniffer); + return gdbarch; }