X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fm32r-tdep.c;h=b9556fac9dd79bee99dc8f4d84782d8431c2b844;hb=066d7383accb1d6e19bcccd370d8c05b97483378;hp=73dce73b6c7dbc4e4dccb4567776bc8da55763b6;hpb=9b32d5267e5b0e0eb9100353a7b555c06a817466;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c index 73dce73b6c..b9556fac9d 100644 --- a/gdb/m32r-tdep.c +++ b/gdb/m32r-tdep.c @@ -1,13 +1,13 @@ /* Target-dependent code for Renesas M32R, for GDB. - Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003 Free Software - Foundation, Inc. + Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, + 2008, 2009 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -16,9 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "frame.h" @@ -33,6 +31,7 @@ #include "inferior.h" #include "symfile.h" #include "objfiles.h" +#include "osabi.h" #include "language.h" #include "arch-utils.h" #include "regcache.h" @@ -55,155 +54,151 @@ 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. */ +/* 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_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} - -static int -m32r_memory_insert_breakpoint (CORE_ADDR addr, char *contents_cache) +m32r_memory_insert_breakpoint (struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) { + CORE_ADDR addr = bp_tgt->placed_address; int val; - unsigned char *bp; - int bplen; - - bplen = (addr & 3) ? 2 : 4; + gdb_byte buf[4]; + gdb_byte *contents_cache = bp_tgt->shadow_contents; + gdb_byte 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 */ + bp_tgt->placed_size = bp_tgt->shadow_len = 4; + /* Determine appropriate breakpoint contents and size for this address. */ - if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + if (gdbarch_byte_order (gdbarch) == 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 (struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) { + CORE_ADDR addr = bp_tgt->placed_address; int val; - int bplen; + gdb_byte buf[4]; + gdb_byte *contents_cache = bp_tgt->shadow_contents; - /* Determine appropriate breakpoint contents and size for this address. */ - if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + buf[0] = contents_cache[0]; + buf[1] = contents_cache[1]; + buf[2] = contents_cache[2]; + buf[3] = contents_cache[3]; + + /* Remove parallel bit. */ + if (gdbarch_byte_order (gdbarch) == 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 const gdb_byte * +m32r_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr) { - unsigned char *bp; + static gdb_byte be_bp_entry[] = { 0x10, 0xf1, 0x70, 0x00 }; /* dpt -> nop */ + static gdb_byte le_bp_entry[] = { 0x00, 0x70, 0xf1, 0x10 }; /* dpt -> nop */ + gdb_byte *bp; /* Determine appropriate breakpoint. */ - if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) { 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; } } @@ -219,7 +214,7 @@ char *m32r_register_names[] = { }; static const char * -m32r_register_name (int reg_nr) +m32r_register_name (struct gdbarch *gdbarch, int reg_nr) { if (reg_nr < 0) return NULL; @@ -236,11 +231,11 @@ static struct type * m32r_register_type (struct gdbarch *gdbarch, int reg_nr) { if (reg_nr == M32R_PC_REGNUM) - return builtin_type_void_func_ptr; + return builtin_type (gdbarch)->builtin_func_ptr; else if (reg_nr == M32R_SP_REGNUM || reg_nr == M32R_FP_REGNUM) - return builtin_type_void_data_ptr; + return builtin_type (gdbarch)->builtin_data_ptr; else - return builtin_type_int32; + return builtin_type (gdbarch)->builtin_int32; } @@ -253,96 +248,95 @@ static void m32r_store_return_value (struct type *type, struct regcache *regcache, const void *valbuf) { + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); CORE_ADDR regval; int len = TYPE_LENGTH (type); - regval = extract_unsigned_integer (valbuf, len > 4 ? 4 : len); + regval = extract_unsigned_integer (valbuf, len > 4 ? 4 : len, byte_order); regcache_cooked_write_unsigned (regcache, RET1_REGNUM, regval); if (len > 4) { - regval = extract_unsigned_integer ((char *) valbuf + 4, len - 4); + regval = extract_unsigned_integer ((gdb_byte *) valbuf + 4, + len - 4, byte_order); regcache_cooked_write_unsigned (regcache, RET1_REGNUM + 1, regval); } } -/* 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 -decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, - CORE_ADDR *pl_endptr) +static int +decode_prologue (struct gdbarch *gdbarch, + CORE_ADDR start_pc, CORE_ADDR scan_limit, + CORE_ADDR *pl_endptr, unsigned long *framelength) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 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) { - insn = read_memory_unsigned_integer (current_pc, 2); + /* Check if current pc's location is readable. */ + if (!safe_read_memory_integer (current_pc, 2, byte_order, &return_value)) + return -1; + + insn = read_memory_unsigned_integer (current_pc, 2, byte_order); + + 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, byte_order, + &return_value)) + return -1; + if (insn == 0x8faf) /* add3 sp, sp, xxxx */ /* add 16 bit sign-extended offset */ { framesize += - -((short) read_memory_unsigned_integer (current_pc, 2)); + -((short) read_memory_unsigned_integer (current_pc, + 2, byte_order)); } else { if (((insn >> 8) == 0xe4) /* ld24 r4, xxxxxx; sub sp, r4 */ + && safe_read_memory_integer (current_pc + 2, + 2, byte_order, + &return_value) && read_memory_unsigned_integer (current_pc + 2, - 2) == 0x0f24) + 2, byte_order) + == 0x0f24) /* subtract 24 bit sign-extended negative-offset */ { - insn = read_memory_unsigned_integer (current_pc - 2, 4); + insn = read_memory_unsigned_integer (current_pc - 2, + 4, byte_order); if (insn & 0x00800000) /* sign extend */ insn |= 0xff000000; /* negative */ else @@ -350,7 +344,7 @@ decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, framesize += insn; } } - after_prologue = current_pc; + after_push = current_pc + 2; continue; } } @@ -367,7 +361,7 @@ decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, if ((insn >> 8) == 0x4f) /* addi sp, xx */ /* add 8 bit sign-extended offset */ { - int stack_adjust = (char) (insn & 0xff); + int stack_adjust = (signed char) (insn & 0xff); /* there are probably two of these stack adjustments: 1) A negative one in the prologue, and @@ -389,17 +383,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 */ @@ -409,12 +409,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) @@ -426,6 +428,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. @@ -433,25 +442,30 @@ 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) +static CORE_ADDR +m32r_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); CORE_ADDR func_addr, func_end; struct symtab_and_line sal; + LONGEST return_value; /* See what the symbol table says */ @@ -473,11 +487,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, byte_order, &return_value)) + return pc; + + /* Find the end of prologue. */ + if (decode_prologue (gdbarch, 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 @@ -503,33 +524,35 @@ struct m32r_unwind_cache for it IS the sp for the next frame. */ static struct m32r_unwind_cache * -m32r_frame_unwind_cache (struct frame_info *next_frame, +m32r_frame_unwind_cache (struct frame_info *this_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); info = FRAME_OBSTACK_ZALLOC (struct m32r_unwind_cache); (*this_prologue_cache) = info; - info->saved_regs = trad_frame_alloc_saved_regs (next_frame); + info->saved_regs = trad_frame_alloc_saved_regs (this_frame); info->size = 0; info->sp_offset = 0; - info->uses_frame = 0; - for (pc = frame_func_unwind (next_frame); - pc > 0 && pc < frame_pc_unwind (next_frame); pc += 2) + + scan_limit = get_frame_pc (this_frame); + for (pc = get_frame_func (this_frame); + pc > 0 && pc < scan_limit; pc += 2) { if ((pc & 2) == 0) { - op = get_frame_memory_unsigned (next_frame, pc, 4); + op = get_frame_memory_unsigned (this_frame, pc, 4); if ((op & 0x80000000) == 0x80000000) { /* 32-bit instruction */ @@ -539,24 +562,25 @@ 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 (this_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; } } /* 16-bit instructions */ - op = get_frame_memory_unsigned (next_frame, pc, 2) & 0x7fff; + op = get_frame_memory_unsigned (this_frame, pc, 2) & 0x7fff; if ((op & 0xf0ff) == 0x207f) { /* st rn, @-sp */ @@ -567,7 +591,7 @@ m32r_frame_unwind_cache (struct frame_info *next_frame, else if ((op & 0xff00) == 0x4f00) { /* addi sp, xx */ - int n = (char) (op & 0xff); + int n = (signed char) (op & 0xff); info->sp_offset += n; } else if (op == 0x1d8f) @@ -575,12 +599,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; @@ -592,7 +617,7 @@ m32r_frame_unwind_cache (struct frame_info *next_frame, /* The SP was moved to the FP. This indicates that a new frame was created. Get THIS frame's FP value by unwinding it from the next frame. */ - this_base = frame_unwind_register_unsigned (next_frame, M32R_FP_REGNUM); + this_base = get_frame_register_unsigned (this_frame, M32R_FP_REGNUM); /* The FP points at the last saved register. Adjust the FP back to before the first saved register giving the SP. */ prev_sp = this_base + info->size; @@ -601,7 +626,7 @@ m32r_frame_unwind_cache (struct frame_info *next_frame, { /* Assume that the FP is this frame's SP but with that pushed stack space added back. */ - this_base = frame_unwind_register_unsigned (next_frame, M32R_SP_REGNUM); + this_base = get_frame_register_unsigned (this_frame, M32R_SP_REGNUM); prev_sp = this_base + info->size; } @@ -611,7 +636,7 @@ m32r_frame_unwind_cache (struct frame_info *next_frame, /* Adjust all the saved registers so that they contain addresses and not offsets. */ - for (i = 0; i < NUM_REGS - 1; i++) + for (i = 0; i < gdbarch_num_regs (get_frame_arch (this_frame)) - 1; i++) if (trad_frame_addr_p (info->saved_regs, i)) info->saved_regs[i].addr = (info->prev_sp + info->saved_regs[i].addr); @@ -629,27 +654,17 @@ m32r_frame_unwind_cache (struct frame_info *next_frame, } static CORE_ADDR -m32r_read_pc (ptid_t ptid) +m32r_read_pc (struct regcache *regcache) { - ptid_t save_ptid; ULONGEST pc; - - save_ptid = inferior_ptid; - inferior_ptid = ptid; - regcache_cooked_read_unsigned (current_regcache, M32R_PC_REGNUM, &pc); - inferior_ptid = save_ptid; + regcache_cooked_read_unsigned (regcache, M32R_PC_REGNUM, &pc); return pc; } static void -m32r_write_pc (CORE_ADDR val, ptid_t ptid) +m32r_write_pc (struct regcache *regcache, CORE_ADDR val) { - ptid_t save_ptid; - - save_ptid = inferior_ptid; - inferior_ptid = ptid; - write_register (M32R_PC_REGNUM, val); - inferior_ptid = save_ptid; + regcache_cooked_write_unsigned (regcache, M32R_PC_REGNUM, val); } static CORE_ADDR @@ -665,14 +680,15 @@ m32r_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct value **args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int stack_offset, stack_alloc; int argreg = ARG1_REGNUM; int argnum; struct type *type; enum type_code typecode; CORE_ADDR regval; - char *val; - char valbuf[MAX_REGISTER_SIZE]; + gdb_byte *val; + gdb_byte valbuf[MAX_REGISTER_SIZE]; int len; int odd_sized_struct; @@ -694,12 +710,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); @@ -709,7 +725,8 @@ m32r_push_dummy_call (struct gdbarch *gdbarch, struct value *function, if (len > 8 && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)) { - store_unsigned_integer (valbuf, 4, VALUE_ADDRESS (args[argnum])); + store_unsigned_integer (valbuf, 4, byte_order, + value_address (args[argnum])); typecode = TYPE_CODE_PTR; len = 4; val = valbuf; @@ -718,11 +735,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); + (gdb_byte *) value_contents (args[argnum]), len); val = valbuf; } else - val = (char *) VALUE_CONTENTS (args[argnum]); + val = (gdb_byte *) value_contents (args[argnum]); while (len > 0) { @@ -737,7 +754,8 @@ m32r_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* there's room in a register */ regval = extract_unsigned_integer (val, - register_size (gdbarch, argreg)); + register_size (gdbarch, argreg), + byte_order); regcache_cooked_write_unsigned (regcache, argreg++, regval); } @@ -763,6 +781,8 @@ static void m32r_extract_return_value (struct type *type, struct regcache *regcache, void *dst) { + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); bfd_byte *valbuf = dst; int len = TYPE_LENGTH (type); ULONGEST tmp; @@ -770,17 +790,35 @@ m32r_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, RET1_REGNUM, &tmp); - store_unsigned_integer (valbuf, (len > 4 ? len - 4 : len), tmp); + store_unsigned_integer (valbuf, (len > 4 ? len - 4 : len), byte_order, tmp); /* Ignore return values more than 8 bytes in size because the m32r returns anything more than 8 bytes in the stack. */ if (len > 4) { regcache_cooked_read_unsigned (regcache, RET1_REGNUM + 1, &tmp); - store_unsigned_integer (valbuf + len - 4, 4, tmp); + store_unsigned_integer (valbuf + len - 4, 4, byte_order, tmp); } } +static enum return_value_convention +m32r_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *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) @@ -792,18 +830,18 @@ m32r_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) frame. This will be used to create a new GDB frame struct. */ static void -m32r_frame_this_id (struct frame_info *next_frame, +m32r_frame_this_id (struct frame_info *this_frame, void **this_prologue_cache, struct frame_id *this_id) { struct m32r_unwind_cache *info - = m32r_frame_unwind_cache (next_frame, this_prologue_cache); + = m32r_frame_unwind_cache (this_frame, this_prologue_cache); CORE_ADDR base; CORE_ADDR func; struct minimal_symbol *msym_stack; struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = get_frame_func (this_frame); /* Check if the stack is empty. */ msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL); @@ -821,36 +859,28 @@ m32r_frame_this_id (struct frame_info *next_frame, (*this_id) = id; } -static void -m32r_frame_prev_register (struct frame_info *next_frame, - void **this_prologue_cache, - int regnum, int *optimizedp, - enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, void *bufferp) +static struct value * +m32r_frame_prev_register (struct frame_info *this_frame, + void **this_prologue_cache, int regnum) { struct m32r_unwind_cache *info - = m32r_frame_unwind_cache (next_frame, this_prologue_cache); - trad_frame_get_prev_register (next_frame, info->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, bufferp); + = m32r_frame_unwind_cache (this_frame, this_prologue_cache); + return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); } static const struct frame_unwind m32r_frame_unwind = { NORMAL_FRAME, m32r_frame_this_id, - m32r_frame_prev_register + m32r_frame_prev_register, + NULL, + default_frame_sniffer }; -static const struct frame_unwind * -m32r_frame_sniffer (struct frame_info *next_frame) -{ - return &m32r_frame_unwind; -} - static CORE_ADDR -m32r_frame_base_address (struct frame_info *next_frame, void **this_cache) +m32r_frame_base_address (struct frame_info *this_frame, void **this_cache) { struct m32r_unwind_cache *info - = m32r_frame_unwind_cache (next_frame, this_cache); + = m32r_frame_unwind_cache (this_frame, this_cache); return info->base; } @@ -861,16 +891,15 @@ static const struct frame_base m32r_frame_base = { m32r_frame_base_address }; -/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that - dummy frame. The frame ID's base needs to match the TOS value - saved by save_dummy_frame_tos(), and the PC match the dummy frame's - breakpoint. */ +/* Assuming THIS_FRAME is a dummy, return the frame ID of that dummy + frame. The frame ID's base needs to match the TOS value saved by + save_dummy_frame_tos(), and the PC match the dummy frame's breakpoint. */ static struct frame_id -m32r_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) +m32r_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) { - return frame_id_build (m32r_unwind_sp (gdbarch, next_frame), - frame_pc_unwind (next_frame)); + CORE_ADDR sp = get_frame_register_unsigned (this_frame, M32R_SP_REGNUM); + return frame_id_build (sp, get_frame_pc (this_frame)); } @@ -900,13 +929,8 @@ m32r_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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); @@ -918,19 +942,27 @@ m32r_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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 stack address must match the SP value returned by PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos. */ - set_gdbarch_unwind_dummy_id (gdbarch, m32r_unwind_dummy_id); + set_gdbarch_dummy_id (gdbarch, m32r_dummy_id); /* Return the unwound PC value. */ set_gdbarch_unwind_pc (gdbarch, m32r_unwind_pc); 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_unwinder (gdbarch, &m32r_frame_unwind); + + /* Support simple overlay manager. */ + set_gdbarch_overlay_update (gdbarch, simple_overlay_update); + return gdbarch; }