X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Favr-tdep.c;h=01d04e2962676488bf4451c567783e419aa2bfcf;hb=88c15c34004057ccff9993d517b4df5ba1a0e6f8;hp=563ecf204e8c7736c529a932024682aae62100a2;hpb=48c2c0a6f339c270820d46c8586f3779b1215fca;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c index 563ecf204e..01d04e2962 100644 --- a/gdb/avr-tdep.c +++ b/gdb/avr-tdep.c @@ -1,12 +1,13 @@ /* Target-dependent code for Atmel AVR, for GDB. - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. + + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2006, 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, @@ -15,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 . */ /* Contributed by Theodore A. Roth, troth@openavr.org */ @@ -31,6 +30,7 @@ #include "trad-frame.h" #include "gdbcmd.h" #include "gdbcore.h" +#include "gdbtypes.h" #include "inferior.h" #include "symfile.h" #include "arch-utils.h" @@ -188,7 +188,7 @@ struct gdbarch_tdep /* Lookup the name of a register given it's number. */ static const char * -avr_register_name (int regnum) +avr_register_name (struct gdbarch *gdbarch, int regnum) { static char *register_names[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", @@ -213,7 +213,7 @@ avr_register_type (struct gdbarch *gdbarch, int reg_nr) if (reg_nr == AVR_PC_REGNUM) return builtin_type_uint32; if (reg_nr == AVR_SP_REGNUM) - return builtin_type_void_data_ptr; + return builtin_type (gdbarch)->builtin_data_ptr; else return builtin_type_uint8; } @@ -278,7 +278,7 @@ avr_convert_saddr_to_raw (CORE_ADDR x) /* Convert from address to pointer and vice-versa. */ static void -avr_address_to_pointer (struct type *type, void *buf, CORE_ADDR addr) +avr_address_to_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr) { /* Is it a code address? */ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC @@ -296,7 +296,7 @@ avr_address_to_pointer (struct type *type, void *buf, CORE_ADDR addr) } static CORE_ADDR -avr_pointer_to_address (struct type *type, const void *buf) +avr_pointer_to_address (struct type *type, const gdb_byte *buf) { CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type)); @@ -310,38 +310,18 @@ avr_pointer_to_address (struct type *type, const void *buf) } static CORE_ADDR -avr_read_pc (ptid_t ptid) +avr_read_pc (struct regcache *regcache) { - ptid_t save_ptid; ULONGEST pc; - CORE_ADDR retval; - - save_ptid = inferior_ptid; - inferior_ptid = ptid; - regcache_cooked_read_unsigned (current_regcache, AVR_PC_REGNUM, &pc); - inferior_ptid = save_ptid; - retval = avr_make_iaddr (pc); - return retval; + regcache_cooked_read_unsigned (regcache, AVR_PC_REGNUM, &pc); + return avr_make_iaddr (pc); } static void -avr_write_pc (CORE_ADDR val, ptid_t ptid) -{ - ptid_t save_ptid; - - save_ptid = inferior_ptid; - inferior_ptid = ptid; - write_register (AVR_PC_REGNUM, avr_convert_iaddr_to_raw (val)); - inferior_ptid = save_ptid; -} - -static CORE_ADDR -avr_read_sp (void) +avr_write_pc (struct regcache *regcache, CORE_ADDR val) { - ULONGEST sp; - - regcache_cooked_read_unsigned (current_regcache, AVR_SP_REGNUM, &sp); - return (avr_make_saddr (sp)); + regcache_cooked_write_unsigned (regcache, AVR_PC_REGNUM, + avr_convert_iaddr_to_raw (val)); } static int @@ -588,7 +568,7 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info) if (num_pushes > AVR_MAX_PUSHES) { - fprintf_unfiltered (gdb_stderr, "Num pushes too large: %d\n", + fprintf_unfiltered (gdb_stderr, _("Num pushes too large: %d\n"), num_pushes); num_pushes = 0; } @@ -667,7 +647,7 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info) if (vpc >= AVR_MAX_PROLOGUE_SIZE) fprintf_unfiltered (gdb_stderr, - "Hit end of prologue while scanning pushes\n"); + _("Hit end of prologue while scanning pushes\n")); /* Second stage of the prologue scanning. Scan: @@ -764,7 +744,7 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info) } static CORE_ADDR -avr_skip_prologue (CORE_ADDR pc) +avr_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { CORE_ADDR func_addr, func_end; CORE_ADDR prologue_end = pc; @@ -808,7 +788,7 @@ avr_skip_prologue (CORE_ADDR pc) only target, this shouldn't be a problem (I hope). TRoth/2003-05-14 */ static const unsigned char * -avr_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr) +avr_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR * pcptr, int *lenptr) { static unsigned char avr_break_insn [] = { 0x98, 0x95 }; *lenptr = sizeof (avr_break_insn); @@ -822,7 +802,7 @@ avr_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr) static void avr_extract_return_value (struct type *type, struct regcache *regcache, - void *valbuf) + gdb_byte *valbuf) { ULONGEST r24, r25; ULONGEST c; @@ -847,14 +827,52 @@ avr_extract_return_value (struct type *type, struct regcache *regcache, } } +/* Determine, for architecture GDBARCH, how a return value of TYPE + should be returned. If it is supposed to be returned in registers, + and READBUF is non-zero, read the appropriate value from REGCACHE, + and copy it into READBUF. If WRITEBUF is non-zero, write the value + from WRITEBUF into REGCACHE. */ + +static enum return_value_convention +avr_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) +{ + int struct_return = ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT + || TYPE_CODE (valtype) == TYPE_CODE_UNION + || TYPE_CODE (valtype) == TYPE_CODE_ARRAY) + && !(TYPE_LENGTH (valtype) == 1 + || TYPE_LENGTH (valtype) == 2 + || TYPE_LENGTH (valtype) == 4 + || TYPE_LENGTH (valtype) == 8)); + + if (writebuf != NULL) + { + gdb_assert (!struct_return); + error (_("Cannot store return value.")); + } + + if (readbuf != NULL) + { + gdb_assert (!struct_return); + avr_extract_return_value (valtype, regcache, readbuf); + } + + if (struct_return) + return RETURN_VALUE_STRUCT_CONVENTION; + else + return RETURN_VALUE_REGISTER_CONVENTION; +} + + /* Put here the code to store, into fi->saved_regs, the addresses of 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. */ -struct avr_unwind_cache * -avr_frame_unwind_cache (struct frame_info *next_frame, +static struct avr_unwind_cache * +avr_frame_unwind_cache (struct frame_info *this_frame, void **this_prologue_cache) { CORE_ADDR pc; @@ -868,14 +886,14 @@ avr_frame_unwind_cache (struct frame_info *next_frame, info = FRAME_OBSTACK_ZALLOC (struct avr_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->prologue_type = AVR_PROLOGUE_NONE; - pc = frame_func_unwind (next_frame); + pc = get_frame_func (this_frame); - if ((pc > 0) && (pc < frame_pc_unwind (next_frame))) + if ((pc > 0) && (pc < get_frame_pc (this_frame))) avr_scan_prologue (pc, info); if ((info->prologue_type != AVR_PROLOGUE_NONE) @@ -886,8 +904,8 @@ avr_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. */ - frame_unwind_unsigned_register (next_frame, AVR_FP_REGNUM, &this_base); - frame_unwind_unsigned_register (next_frame, AVR_FP_REGNUM+1, &high_base); + this_base = get_frame_register_unsigned (this_frame, AVR_FP_REGNUM); + high_base = get_frame_register_unsigned (this_frame, AVR_FP_REGNUM+1); this_base += (high_base << 8); /* The FP points at the last saved register. Adjust the FP back @@ -898,7 +916,7 @@ avr_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. */ - frame_unwind_unsigned_register (next_frame, AVR_SP_REGNUM, &this_base); + this_base = get_frame_register_unsigned (this_frame, AVR_SP_REGNUM); prev_sp = this_base + info->size; } @@ -910,7 +928,7 @@ avr_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 (info->saved_regs[i].addr) { info->saved_regs[i].addr = (info->prev_sp - info->saved_regs[i].addr); @@ -936,27 +954,37 @@ avr_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) { ULONGEST pc; - frame_unwind_unsigned_register (next_frame, AVR_PC_REGNUM, &pc); + pc = frame_unwind_register_unsigned (next_frame, AVR_PC_REGNUM); return avr_make_iaddr (pc); } +static CORE_ADDR +avr_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + ULONGEST sp; + + sp = frame_unwind_register_unsigned (next_frame, AVR_SP_REGNUM); + + return avr_make_saddr (sp); +} + /* 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 -avr_frame_this_id (struct frame_info *next_frame, +avr_frame_this_id (struct frame_info *this_frame, void **this_prologue_cache, struct frame_id *this_id) { struct avr_unwind_cache *info - = avr_frame_unwind_cache (next_frame, this_prologue_cache); + = avr_frame_unwind_cache (this_frame, this_prologue_cache); CORE_ADDR base; CORE_ADDR func; struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = get_frame_func (this_frame); /* Hopefully the prologue analysis either correctly determined the frame's base (which is the SP from the previous frame), or set @@ -969,83 +997,69 @@ avr_frame_this_id (struct frame_info *next_frame, (*this_id) = id; } -static void -avr_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 * +avr_frame_prev_register (struct frame_info *this_frame, + void **this_prologue_cache, int regnum) { struct avr_unwind_cache *info - = avr_frame_unwind_cache (next_frame, this_prologue_cache); + = avr_frame_unwind_cache (this_frame, this_prologue_cache); if (regnum == AVR_PC_REGNUM) { if (trad_frame_addr_p (info->saved_regs, regnum)) { - *optimizedp = 0; - *lvalp = lval_memory; - *addrp = info->saved_regs[regnum].addr; - *realnump = -1; - if (bufferp != NULL) - { - /* Reading the return PC from the PC register is slightly - abnormal. register_size(AVR_PC_REGNUM) says it is 4 bytes, - but in reality, only two bytes (3 in upcoming mega256) are - stored on the stack. - - Also, note that the value on the stack is an addr to a word - not a byte, so we will need to multiply it by two at some - point. - - And to confuse matters even more, the return address stored - on the stack is in big endian byte order, even though most - everything else about the avr is little endian. Ick! */ - - /* FIXME: number of bytes read here will need updated for the - mega256 when it is available. */ - - ULONGEST pc; - unsigned char tmp; - unsigned char buf[2]; - - read_memory (info->saved_regs[regnum].addr, buf, 2); - - /* Convert the PC read from memory as a big-endian to - little-endian order. */ - tmp = buf[0]; - buf[0] = buf[1]; - buf[1] = tmp; - - pc = (extract_unsigned_integer (buf, 2) * 2); - store_unsigned_integer (bufferp, - register_size (current_gdbarch, regnum), - pc); - } + /* Reading the return PC from the PC register is slightly + abnormal. register_size(AVR_PC_REGNUM) says it is 4 bytes, + but in reality, only two bytes (3 in upcoming mega256) are + stored on the stack. + + Also, note that the value on the stack is an addr to a word + not a byte, so we will need to multiply it by two at some + point. + + And to confuse matters even more, the return address stored + on the stack is in big endian byte order, even though most + everything else about the avr is little endian. Ick! */ + + /* FIXME: number of bytes read here will need updated for the + mega256 when it is available. */ + + ULONGEST pc; + unsigned char tmp; + unsigned char buf[2]; + + read_memory (info->saved_regs[regnum].addr, buf, 2); + + /* Convert the PC read from memory as a big-endian to + little-endian order. */ + tmp = buf[0]; + buf[0] = buf[1]; + buf[1] = tmp; + + pc = (extract_unsigned_integer (buf, 2) * 2); + + return frame_unwind_got_constant (this_frame, regnum, pc); } + + return frame_unwind_got_optimized (this_frame, regnum); } - else - trad_frame_get_prev_register (next_frame, info->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, bufferp); + + return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); } static const struct frame_unwind avr_frame_unwind = { NORMAL_FRAME, avr_frame_this_id, - avr_frame_prev_register + avr_frame_prev_register, + NULL, + default_frame_sniffer }; -const struct frame_unwind * -avr_frame_sniffer (struct frame_info *next_frame) -{ - return &avr_frame_unwind; -} - static CORE_ADDR -avr_frame_base_address (struct frame_info *next_frame, void **this_cache) +avr_frame_base_address (struct frame_info *this_frame, void **this_cache) { struct avr_unwind_cache *info - = avr_frame_unwind_cache (next_frame, this_cache); + = avr_frame_unwind_cache (this_frame, this_cache); return info->base; } @@ -1057,18 +1071,17 @@ static const struct frame_base avr_frame_base = { avr_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 -avr_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) +avr_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) { ULONGEST base; - frame_unwind_unsigned_register (next_frame, AVR_SP_REGNUM, &base); - return frame_id_build (avr_make_saddr (base), frame_pc_unwind (next_frame)); + base = get_frame_register_unsigned (this_frame, AVR_SP_REGNUM); + return frame_id_build (avr_make_saddr (base), get_frame_pc (this_frame)); } /* When arguments must be pushed onto the stack, they go on in reverse @@ -1081,10 +1094,8 @@ struct stack_item void *data; }; -static struct stack_item *push_stack_item (struct stack_item *prev, - void *contents, int len); static struct stack_item * -push_stack_item (struct stack_item *prev, void *contents, int len) +push_stack_item (struct stack_item *prev, const bfd_byte *contents, int len) { struct stack_item *si; si = xmalloc (sizeof (struct stack_item)); @@ -1162,8 +1173,8 @@ avr_push_dummy_call (struct gdbarch *gdbarch, struct value *function, if (struct_return) { fprintf_unfiltered (gdb_stderr, "struct_return: 0x%lx\n", struct_addr); - write_register (argreg--, struct_addr & 0xff); - write_register (argreg--, (struct_addr >>8) & 0xff); + regcache_cooked_write_unsigned (regcache, argreg--, struct_addr & 0xff); + regcache_cooked_write_unsigned (regcache, argreg--, (struct_addr >>8) & 0xff); } #endif @@ -1172,8 +1183,8 @@ avr_push_dummy_call (struct gdbarch *gdbarch, struct value *function, int last_regnum; int j; struct value *arg = args[i]; - struct type *type = check_typedef (VALUE_TYPE (arg)); - char *contents = VALUE_CONTENTS (arg); + struct type *type = check_typedef (value_type (arg)); + const bfd_byte *contents = value_contents (arg); int len = TYPE_LENGTH (type); /* Calculate the potential last register needed. */ @@ -1268,13 +1279,12 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT); set_gdbarch_long_double_bit (gdbarch, 4 * TARGET_CHAR_BIT); - set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little); - set_gdbarch_double_format (gdbarch, &floatformat_ieee_single_little); - set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_single_little); + set_gdbarch_float_format (gdbarch, floatformats_ieee_single); + set_gdbarch_double_format (gdbarch, floatformats_ieee_single); + set_gdbarch_long_double_format (gdbarch, floatformats_ieee_single); set_gdbarch_read_pc (gdbarch, avr_read_pc); set_gdbarch_write_pc (gdbarch, avr_write_pc); - set_gdbarch_read_sp (gdbarch, avr_read_sp); set_gdbarch_num_regs (gdbarch, AVR_NUM_REGS); @@ -1284,7 +1294,7 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_register_name (gdbarch, avr_register_name); set_gdbarch_register_type (gdbarch, avr_register_type); - set_gdbarch_extract_return_value (gdbarch, avr_extract_return_value); + set_gdbarch_return_value (gdbarch, avr_return_value); set_gdbarch_print_insn (gdbarch, print_insn_avr); set_gdbarch_push_dummy_call (gdbarch, avr_push_dummy_call); @@ -1297,12 +1307,13 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_breakpoint_from_pc (gdbarch, avr_breakpoint_from_pc); - frame_unwind_append_sniffer (gdbarch, avr_frame_sniffer); + frame_unwind_append_unwinder (gdbarch, &avr_frame_unwind); frame_base_set_default (gdbarch, &avr_frame_base); - set_gdbarch_unwind_dummy_id (gdbarch, avr_unwind_dummy_id); + set_gdbarch_dummy_id (gdbarch, avr_dummy_id); set_gdbarch_unwind_pc (gdbarch, avr_unwind_pc); + set_gdbarch_unwind_sp (gdbarch, avr_unwind_sp); return gdbarch; } @@ -1324,48 +1335,38 @@ static void avr_io_reg_read_command (char *args, int from_tty) { LONGEST bufsiz = 0; - char buf[400]; + gdb_byte *buf; char query[400]; char *p; unsigned int nreg = 0; unsigned int val; int i, j, k, step; - /* Just get the maximum buffer size. */ - bufsiz = target_read_partial (¤t_target, TARGET_OBJECT_AVR, - NULL, NULL, 0, 0); - if (bufsiz < 0) - { - fprintf_unfiltered (gdb_stderr, - "ERR: info io_registers NOT supported by current " - "target\n"); - return; - } - if (bufsiz > sizeof (buf)) - bufsiz = sizeof (buf); - /* Find out how many io registers the target has. */ - strcpy (query, "avr.io_reg"); - target_read_partial (¤t_target, TARGET_OBJECT_AVR, query, buf, 0, - bufsiz); + bufsiz = target_read_alloc (¤t_target, TARGET_OBJECT_AVR, + "avr.io_reg", &buf); - if (strncmp (buf, "", bufsiz) == 0) + if (bufsiz <= 0) { fprintf_unfiltered (gdb_stderr, - "info io_registers NOT supported by target\n"); + _("ERR: info io_registers NOT supported " + "by current target\n")); return; } if (sscanf (buf, "%x", &nreg) != 1) { fprintf_unfiltered (gdb_stderr, - "Error fetching number of io registers\n"); + _("Error fetching number of io registers\n")); + xfree (buf); return; } + xfree (buf); + reinitialize_more_filter (); - printf_unfiltered ("Target has %u io registers:\n\n", nreg); + printf_unfiltered (_("Target has %u io registers:\n\n"), nreg); /* only fetch up to 8 registers at a time to keep the buffer small */ step = 8; @@ -1378,8 +1379,8 @@ avr_io_reg_read_command (char *args, int from_tty) j = nreg - i; /* last block is less than 8 registers */ snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j); - target_read_partial (¤t_target, TARGET_OBJECT_AVR, query, buf, - 0, bufsiz); + bufsiz = target_read_alloc (¤t_target, TARGET_OBJECT_AVR, + query, &buf); p = buf; for (k = i; k < (i + j); k++) @@ -1394,6 +1395,8 @@ avr_io_reg_read_command (char *args, int from_tty) break; } } + + xfree (buf); } } @@ -1412,5 +1415,6 @@ _initialize_avr_tdep (void) io_registers' to signify it is not available on other platforms. */ add_cmd ("io_registers", class_info, avr_io_reg_read_command, - "query remote avr target for io space register values", &infolist); + _("query remote avr target for io space register values"), + &infolist); }