X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fm32r-tdep.c;h=011a0d2a9c347b659850314c9b83180ac65806aa;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=12a91c223f92af2e3e8585391071c896856ad381;hpb=627b3ba2d386befaf2d1bd97bd780ac1218dd399;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c index 12a91c223f..011a0d2a9c 100644 --- a/gdb/m32r-tdep.c +++ b/gdb/m32r-tdep.c @@ -1,13 +1,12 @@ /* Target-dependent code for Renesas M32R, for GDB. - Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003 Free Software - Foundation, Inc. + Copyright (C) 1996-2020 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 +15,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" @@ -28,44 +25,24 @@ #include "gdbtypes.h" #include "gdbcmd.h" #include "gdbcore.h" -#include "gdb_string.h" #include "value.h" #include "inferior.h" #include "symfile.h" #include "objfiles.h" +#include "osabi.h" #include "language.h" #include "arch-utils.h" #include "regcache.h" #include "trad-frame.h" +#include "dis-asm.h" +#include "m32r-tdep.h" +#include -#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, -}; +/* The size of the argument registers (r0 - r3) in bytes. */ +#define M32R_ARG_REGISTER_SIZE 4 /* Local functions */ -extern void _initialize_m32r_tdep (void); - static CORE_ADDR m32r_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) { @@ -74,181 +51,170 @@ m32r_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) return sp & ~3; } -/* Should we use 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 = bp_tgt->reqstd_address; int val; - unsigned char *bp; - int bplen; - - bplen = (addr & 3) ? 2 : 4; + gdb_byte buf[4]; + gdb_byte contents_cache[4]; + 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 */ + memcpy (bp_tgt->shadow_contents, contents_cache, 4); + 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_raw_memory (addr & 0xfffffffc, buf, 4); return val; } -static const unsigned char * -m32r_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) +/* Implement the breakpoint_kind_from_pc gdbarch method. */ + +static int +m32r_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr) { - unsigned char *bp; + if ((*pcptr & 3) == 0) + return 4; + else + return 2; +} + +/* Implement the sw_breakpoint_from_kind gdbarch method. */ + +static const gdb_byte * +m32r_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size) +{ + static gdb_byte be_bp_entry[] = { + 0x10, 0xf1, 0x70, 0x00 + }; /* dpt -> nop */ + static gdb_byte le_bp_entry[] = { + 0x00, 0x70, 0xf1, 0x10 + }; /* dpt -> nop */ + + *size = kind; /* Determine appropriate breakpoint. */ - if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) - { - if ((*pcptr & 3) == 0) - { - static unsigned char insn[] = M32R_BE_BREAKPOINT32; - bp = insn; - *lenptr = sizeof (insn); - } - else - { - static unsigned char insn[] = M32R_BE_BREAKPOINT16; - bp = insn; - *lenptr = sizeof (insn); - } - } + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + return be_bp_entry; else { - if ((*pcptr & 3) == 0) - { - static unsigned char insn[] = M32R_LE_BREAKPOINT32; - bp = insn; - *lenptr = sizeof (insn); - } + if (kind == 4) + return le_bp_entry; else - { - static unsigned char insn[] = M32R_LE_BREAKPOINT16; - bp = insn; - *lenptr = sizeof (insn); - } + return le_bp_entry + 2; } - - return bp; } - -char *m32r_register_names[] = { +static const char *m32r_register_names[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "fp", "lr", "sp", "psw", "cbr", "spi", "spu", "bpc", "pc", "accl", "acch", "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) +m32r_register_name (struct gdbarch *gdbarch, 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]; } @@ -261,113 +227,112 @@ 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; } /* Write into appropriate registers a function return value - of type TYPE, given in virtual format. + of type TYPE, given in virtual format. - Things always get returned in RET1_REGNUM, RET2_REGNUM. */ + Things always get returned in RET1_REGNUM, RET2_REGNUM. */ static void m32r_store_return_value (struct type *type, struct regcache *regcache, - const void *valbuf) + const gdb_byte *valbuf) { + struct gdbarch *gdbarch = regcache->arch (); + 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 (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 +/* 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 */ + 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 */ + /* 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 */ + 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) - /* subtract 24 bit sign-extended negative-offset */ + 2, byte_order) + == 0x0f24) { - insn = read_memory_unsigned_integer (current_pc - 2, 4); + /* Subtract 24 bit sign-extended negative-offset. */ + insn = read_memory_unsigned_integer (current_pc - 2, + 4, byte_order); if (insn & 0x00800000) /* sign extend */ insn |= 0xff000000; /* negative */ else @@ -375,24 +340,22 @@ decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, framesize += insn; } } - after_prologue = current_pc; + after_push = current_pc + 2; continue; } } - op1 = insn & 0xf000; /* isolate just the first nibble */ + op1 = insn & 0xf000; /* Isolate just the first nibble. */ if ((insn & 0xf0ff) == 0x207f) { /* st reg, @-sp */ - int regno; framesize += 4; - regno = ((insn >> 8) & 0xf); after_prologue = 0; continue; } if ((insn >> 8) == 0x4f) /* addi sp, xx */ - /* add 8 bit sign-extended offset */ + /* 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 @@ -414,32 +377,40 @@ 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 */ + + /* Nop looks like a branch, continue explicitly. */ if (insn == 0x7000) { after_prologue = current_pc + 2; - continue; /* nop occurs between pushes */ + continue; /* nop occurs between pushes. */ } - /* End of prolog if any of these are branch instructions */ + /* 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 */ + /* Some of the branch instructions are mixed with other types. */ if (op1 == 0x1000) { int subop = insn & 0x0ff0; 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) @@ -447,38 +418,51 @@ decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, if (after_stack_adjust != 0) /* We did not find a "mv fp,sp", but we DID find a stack_adjust. Is it safe to use that as the - end of the prologue? I just don't know. */ + end of the prologue? I just don't know. */ { *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. - The way we do that is to return the original start_pc. - GDB will set a breakpoint at the start of the function (etc.) */ + of the prologue. No way to win -- we should report + failure. The way we do that is to return the original + start_pc. 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 */ + 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 */ + /* See what the symbol table says. */ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) { @@ -493,16 +477,23 @@ m32r_skip_prologue (CORE_ADDR pc) the end of the function. In this case, there probably isn't a prologue. */ { - func_end = min (func_end, func_addr + DEFAULT_SEARCH_LIMIT); + func_end = std::min (func_end, func_addr + DEFAULT_SEARCH_LIMIT); } } 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 @@ -525,36 +516,38 @@ struct m32r_unwind_cache the saved registers of frame described by FRAME_INFO. This includes special registers such as pc and fp saved in special ways in the stack frame. sp is even more special: the address we return - for it IS the sp for the next frame. */ + 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; int i; struct m32r_unwind_cache *info; + if ((*this_prologue_cache)) - return (*this_prologue_cache); + return (struct m32r_unwind_cache *) (*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 */ @@ -564,24 +557,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 */ @@ -592,7 +586,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) @@ -600,12 +594,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; @@ -617,7 +612,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; @@ -626,7 +621,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; } @@ -636,7 +631,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); @@ -654,54 +649,24 @@ m32r_frame_unwind_cache (struct frame_info *next_frame, } static CORE_ADDR -m32r_read_pc (ptid_t ptid) -{ - 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; - return pc; -} - -static void -m32r_write_pc (CORE_ADDR val, ptid_t ptid) -{ - ptid_t save_ptid; - - save_ptid = inferior_ptid; - inferior_ptid = ptid; - write_register (M32R_PC_REGNUM, val); - inferior_ptid = save_ptid; -} - -static CORE_ADDR -m32r_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) -{ - return frame_unwind_register_unsigned (next_frame, M32R_SP_REGNUM); -} - - -static CORE_ADDR -m32r_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr, +m32r_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct regcache *regcache, CORE_ADDR bp_addr, int nargs, - struct value **args, CORE_ADDR sp, int struct_return, + struct value **args, CORE_ADDR sp, + function_call_return_method return_method, CORE_ADDR struct_addr) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 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[M32R_ARG_REGISTER_SIZE]; int len; - int odd_sized_struct; - /* first force sp to a 4-byte alignment */ + /* First force sp to a 4-byte alignment. */ sp = sp & ~3; /* Set the return address. For the m32r, the return breakpoint is @@ -711,21 +676,21 @@ m32r_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr, /* If STRUCT_RETURN is true, then the struct return address (in STRUCT_ADDR) will consume the first argument-passing register. Both adjust the register count and store that value. */ - if (struct_return) + if (return_method == return_method_struct) { regcache_cooked_write_unsigned (regcache, argreg, struct_addr); argreg++; } - /* Now make sure there's space on the stack */ + /* 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); - sp -= stack_alloc; /* make room on stack for args */ + 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]); - typecode = TYPE_CODE (type); + type = value_type (args[argnum]); + typecode = type->code (); len = TYPE_LENGTH (type); memset (valbuf, 0, sizeof (valbuf)); @@ -734,35 +699,37 @@ m32r_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr, 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; } else if (len < 4) { - /* value gets right-justified in the register or stack word */ + /* 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) { if (argreg > ARGN_REGNUM) { - /* must go on the stack */ + /* Must go on the stack. */ write_memory (sp + stack_offset, val, 4); stack_offset += 4; } else if (argreg <= ARGN_REGNUM) { - /* there's room in a register */ + /* 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); } @@ -786,58 +753,64 @@ m32r_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr, static void m32r_extract_return_value (struct type *type, struct regcache *regcache, - void *dst) + gdb_byte *dst) { - bfd_byte *valbuf = dst; + struct gdbarch *gdbarch = regcache->arch (); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int len = TYPE_LENGTH (type); ULONGEST tmp; /* 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 (dst, (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. */ + 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 (dst + len - 4, 4, byte_order, tmp); } } - -static CORE_ADDR -m32r_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) +static enum return_value_convention +m32r_return_value (struct gdbarch *gdbarch, struct value *function, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { - return frame_unwind_register_unsigned (next_frame, M32R_PC_REGNUM); + 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; + } } /* Given a GDB frame, determine the address of the calling function's 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 bound_minimal_symbol msym_stack; struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); - - /* This is meant to halt the backtrace at "_start". Make sure we - don't halt it at a generic dummy frame. */ - if (deprecated_inside_entry_file (func)) - return; + func = get_frame_func (this_frame); /* Check if the stack is empty. */ msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL); - if (msym_stack && info->base == SYMBOL_VALUE_ADDRESS (msym_stack)) + if (msym_stack.minsym && info->base == BMSYMBOL_VALUE_ADDRESS (msym_stack)) return; /* Hopefully the prologue analysis either correctly determined the @@ -848,49 +821,32 @@ m32r_frame_this_id (struct frame_info *next_frame, return; id = frame_id_build (base, func); - - /* Check that we're not going round in circles with the same frame - ID (but avoid applying the test to sentinel frames which do go - round in circles). Can't use frame_id_eq() as that doesn't yet - compare the frame's PC value. */ - if (frame_relative_level (next_frame) >= 0 - && get_frame_type (next_frame) != DUMMY_FRAME - && frame_id_eq (get_frame_id (next_frame), id)) - return; - (*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_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, + default_frame_unwind_stop_reason, 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; } @@ -901,19 +857,6 @@ 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. */ - -static struct frame_id -m32r_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) -{ - return frame_id_build (m32r_unwind_sp (gdbarch, next_frame), - frame_pc_unwind (next_frame)); -} - - static gdbarch_init_ftype m32r_gdbarch_init; static struct gdbarch * @@ -928,59 +871,49 @@ m32r_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) return arches->gdbarch; /* Allocate space for the new architecture. */ - tdep = XMALLOC (struct gdbarch_tdep); + tdep = XCNEW (struct gdbarch_tdep); gdbarch = gdbarch_alloc (&info, tdep); - set_gdbarch_read_pc (gdbarch, m32r_read_pc); - set_gdbarch_write_pc (gdbarch, m32r_write_pc); - set_gdbarch_unwind_sp (gdbarch, m32r_unwind_sp); + set_gdbarch_wchar_bit (gdbarch, 16); + set_gdbarch_wchar_signed (gdbarch, 0); - set_gdbarch_num_regs (gdbarch, m32r_num_regs ()); + set_gdbarch_num_regs (gdbarch, M32R_NUM_REGS); + set_gdbarch_pc_regnum (gdbarch, M32R_PC_REGNUM); 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_extract_struct_value_address (gdbarch, - m32r_extract_struct_value_address); - set_gdbarch_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); - set_gdbarch_decr_pc_after_break (gdbarch, 0); - set_gdbarch_function_start_offset (gdbarch, 0); - set_gdbarch_breakpoint_from_pc (gdbarch, m32r_breakpoint_from_pc); + set_gdbarch_breakpoint_kind_from_pc (gdbarch, m32r_breakpoint_kind_from_pc); + set_gdbarch_sw_breakpoint_from_kind (gdbarch, m32r_sw_breakpoint_from_kind); set_gdbarch_memory_insert_breakpoint (gdbarch, m32r_memory_insert_breakpoint); set_gdbarch_memory_remove_breakpoint (gdbarch, m32r_memory_remove_breakpoint); - set_gdbarch_frame_args_skip (gdbarch, 0); - set_gdbarch_frameless_function_invocation (gdbarch, - 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 - 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); + /* Hook in ABI-specific overrides, if they have been registered. */ + gdbarch_init_osabi (info, gdbarch); - /* Return the unwound PC value. */ - set_gdbarch_unwind_pc (gdbarch, m32r_unwind_pc); + /* Hook in the default unwinders. */ + frame_unwind_append_unwinder (gdbarch, &m32r_frame_unwind); - set_gdbarch_print_insn (gdbarch, print_insn_m32r); + /* Support simple overlay manager. */ + set_gdbarch_overlay_update (gdbarch, simple_overlay_update); return gdbarch; } +void _initialize_m32r_tdep (); void -_initialize_m32r_tdep (void) +_initialize_m32r_tdep () { register_gdbarch_init (bfd_arch_m32r, m32r_gdbarch_init); }