diff options
Diffstat (limited to 'gdb/d10v-tdep.c')
-rw-r--r-- | gdb/d10v-tdep.c | 273 |
1 files changed, 113 insertions, 160 deletions
diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c index 129f563..6ad5ed5 100644 --- a/gdb/d10v-tdep.c +++ b/gdb/d10v-tdep.c @@ -1,4 +1,4 @@ -/* Target-dependent code for Mitsubishi D10V, for GDB. +/* Target-dependent code for Renesas D10V, for GDB. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. @@ -57,7 +57,7 @@ struct gdbarch_tdep }; /* These are the addresses the D10V-EVA board maps data and - instruction memory to. */ + instruction memory to. */ enum memspace { DMEM_START = 0x2000000, @@ -65,7 +65,7 @@ enum memspace { STACK_START = 0x200bffe }; -/* d10v register names. */ +/* d10v register names. */ enum { @@ -80,10 +80,9 @@ enum NR_A_REGS = 2, TS2_NUM_REGS = 37, TS3_NUM_REGS = 42, - /* d10v calling convention. */ + /* d10v calling convention. */ ARG1_REGNUM = R0_REGNUM, - ARGN_REGNUM = R3_REGNUM, - RET1_REGNUM = R0_REGNUM, + ARGN_REGNUM = R3_REGNUM }; static int @@ -114,44 +113,6 @@ d10v_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 d10v returns anything less than 8 bytes in size in - registers. */ - -static int -d10v_use_struct_convention (int gcc_p, struct type *type) -{ - long alignment; - int i; - /* The d10v only passes a struct in a register when that structure - has an alignment that matches the size of a register. */ - /* If the structure doesn't fit in 4 registers, put it on the - stack. */ - if (TYPE_LENGTH (type) > 8) - return 1; - /* If the struct contains only one field, don't put it on the stack - - gcc can fit it in one or more registers. */ - if (TYPE_NFIELDS (type) == 1) - return 0; - alignment = TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)); - for (i = 1; i < TYPE_NFIELDS (type); i++) - { - /* If the alignment changes, just assume it goes on the - stack. */ - if (TYPE_LENGTH (TYPE_FIELD_TYPE (type, i)) != alignment) - return 1; - } - /* If the alignment is suitable for the d10v's 16 bit registers, - don't put it on the stack. */ - if (alignment == 2 || alignment == 4) - return 0; - return 1; -} - - static const unsigned char * d10v_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) { @@ -162,7 +123,7 @@ d10v_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) } /* Map the REG_NR onto an ascii name. Return NULL or an empty string - when the reg_nr isn't valid. */ + when the reg_nr isn't valid. */ enum ts2_regnums { @@ -279,7 +240,7 @@ d10v_ts3_imap_register (void *regcache, int reg_nr) /* MAP GDB's internal register numbering (determined by the layout from the DEPRECATED_REGISTER_BYTE array) onto the simulator's - register numbering. */ + register numbering. */ static int d10v_ts2_register_sim_regno (int nr) @@ -353,7 +314,7 @@ static CORE_ADDR d10v_make_iaddr (CORE_ADDR x) { if (d10v_iaddr_p (x)) - return x; /* Idempotency -- x is already in the IMEM space. */ + return x; /* Idempotency -- x is already in the IMEM space. */ else return (((x) << 2) | IMEM_START); } @@ -413,54 +374,88 @@ d10v_integer_to_address (struct type *type, void *buf) return val; } -/* Write into appropriate registers a function return value - of type TYPE, given in virtual format. - - Things always get returned in RET1_REGNUM, RET2_REGNUM, ... */ +/* Handle the d10v's return_value convention. */ -static void -d10v_store_return_value (struct type *type, struct regcache *regcache, - const void *valbuf) +static enum return_value_convention +d10v_return_value (struct gdbarch *gdbarch, struct type *valtype, + struct regcache *regcache, void *readbuf, + const void *writebuf) { - /* Only char return values need to be shifted right within the first - regnum. */ - if (TYPE_LENGTH (type) == 1 - && TYPE_CODE (type) == TYPE_CODE_INT) + if (TYPE_LENGTH (valtype) > 8) + /* Anything larger than 8 bytes (4 registers) goes on the stack. */ + return RETURN_VALUE_STRUCT_CONVENTION; + if (TYPE_LENGTH (valtype) == 5 + || TYPE_LENGTH (valtype) == 6) + /* Anything 5 or 6 bytes in size goes in memory. Contents don't + appear to matter. Note that 7 and 8 byte objects do end up in + registers! */ + return RETURN_VALUE_STRUCT_CONVENTION; + if (TYPE_LENGTH (valtype) == 1) { - bfd_byte tmp[2]; - tmp[1] = *(bfd_byte *)valbuf; - regcache_cooked_write (regcache, RET1_REGNUM, tmp); + /* All single byte values go in a register stored right-aligned. + Note: 2 byte integer values are handled further down. */ + if (readbuf) + { + /* Since TYPE is smaller than the register, there isn't a + sign extension problem. Let the extraction truncate the + register value. */ + ULONGEST regval; + regcache_cooked_read_unsigned (regcache, R0_REGNUM, + ®val); + store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), regval); + + } + if (writebuf) + { + ULONGEST regval; + if (TYPE_CODE (valtype) == TYPE_CODE_INT) + /* Some sort of integer value stored in R0. Use + unpack_long since that should handle any required sign + extension. */ + regval = unpack_long (valtype, writebuf); + else + /* Some other type. Don't sign-extend the value when + storing it in the register. */ + regval = extract_unsigned_integer (writebuf, 1); + regcache_cooked_write_unsigned (regcache, R0_REGNUM, regval); + } + return RETURN_VALUE_REGISTER_CONVENTION; } - else + if ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT + || TYPE_CODE (valtype) == TYPE_CODE_UNION) + && TYPE_NFIELDS (valtype) > 1 + && TYPE_FIELD_BITPOS (valtype, 1) == 8) + /* If a composite is 8 bit aligned (determined by looking at the + start address of the second field), put it in memory. */ + return RETURN_VALUE_STRUCT_CONVENTION; + /* Assume it is in registers. */ + if (writebuf || readbuf) { int reg; - /* A structure is never more than 8 bytes long. See - use_struct_convention(). */ - gdb_assert (TYPE_LENGTH (type) <= 8); - /* Write out most registers, stop loop before trying to write - out any dangling byte at the end of the buffer. */ - for (reg = 0; (reg * 2) + 1 < TYPE_LENGTH (type); reg++) + /* Per above, the value is never more than 8 bytes long. */ + gdb_assert (TYPE_LENGTH (valtype) <= 8); + /* Xfer 2 bytes at a time. */ + for (reg = 0; (reg * 2) + 1 < TYPE_LENGTH (valtype); reg++) { - regcache_cooked_write (regcache, RET1_REGNUM + reg, - (bfd_byte *) valbuf + reg * 2); + if (readbuf) + regcache_cooked_read (regcache, R0_REGNUM + reg, + (bfd_byte *) readbuf + reg * 2); + if (writebuf) + regcache_cooked_write (regcache, R0_REGNUM + reg, + (bfd_byte *) writebuf + reg * 2); + } + /* Any trailing byte ends up _left_ aligned. */ + if ((reg * 2) < TYPE_LENGTH (valtype)) + { + if (readbuf) + regcache_cooked_read_part (regcache, R0_REGNUM + reg, + 0, 1, (bfd_byte *) readbuf + reg * 2); + if (writebuf) + regcache_cooked_write_part (regcache, R0_REGNUM + reg, + 0, 1, (bfd_byte *) writebuf + reg * 2); } - /* Write out any dangling byte at the end of the buffer. */ - if ((reg * 2) + 1 == TYPE_LENGTH (type)) - regcache_cooked_write_part (regcache, reg, 0, 1, - (bfd_byte *) valbuf + reg * 2); } -} - -/* 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 -d10v_extract_struct_value_address (struct regcache *regcache) -{ - ULONGEST addr; - regcache_cooked_read_unsigned (regcache, ARG1_REGNUM, &addr); - return (addr | DMEM_START); + return RETURN_VALUE_REGISTER_CONVENTION; } static int @@ -505,8 +500,8 @@ d10v_skip_prologue (CORE_ADDR pc) CORE_ADDR func_addr, func_end; struct symtab_and_line sal; - /* If we have line debugging information, then the end of the */ - /* prologue should the first assembly instruction of the first source line */ + /* If we have line debugging information, then the end of the prologue + should be the first assembly instruction of the first source line. */ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) { sal = find_pc_line (func_addr, 0); @@ -515,7 +510,7 @@ d10v_skip_prologue (CORE_ADDR pc) } if (target_read_memory (pc, (char *) &op, 4)) - return pc; /* Can't access it -- assume no prologue. */ + return pc; /* Can't access it -- assume no prologue. */ while (1) { @@ -545,8 +540,9 @@ d10v_skip_prologue (CORE_ADDR pc) { if (!check_prologue (op2)) { - /* if the previous opcode was really part of the prologue */ - /* and not just a NOP, then we want to break after both instructions */ + /* If the previous opcode was really part of the + prologue and not just a NOP, then we want to + break after both instructions. */ if (op1 != 0x5E00) pc += 4; break; @@ -657,7 +653,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op, 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 d10v_unwind_cache * d10v_frame_unwind_cache (struct frame_info *next_frame, @@ -795,11 +791,11 @@ d10v_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file, { ULONGEST pc, psw, rpt_s, rpt_e, rpt_c; - frame_read_unsigned_register (frame, D10V_PC_REGNUM, &pc); - frame_read_unsigned_register (frame, PSW_REGNUM, &psw); - frame_read_unsigned_register (frame, frame_map_name_to_regnum (frame, "rpt_s", -1), &rpt_s); - frame_read_unsigned_register (frame, frame_map_name_to_regnum (frame, "rpt_e", -1), &rpt_e); - frame_read_unsigned_register (frame, frame_map_name_to_regnum (frame, "rpt_c", -1), &rpt_c); + pc = get_frame_register_unsigned (frame, D10V_PC_REGNUM); + psw = get_frame_register_unsigned (frame, PSW_REGNUM); + rpt_s = get_frame_register_unsigned (frame, frame_map_name_to_regnum (frame, "rpt_s", -1)); + rpt_e = get_frame_register_unsigned (frame, frame_map_name_to_regnum (frame, "rpt_e", -1)); + rpt_c = get_frame_register_unsigned (frame, frame_map_name_to_regnum (frame, "rpt_c", -1)); fprintf_filtered (file, "PC=%04lx (0x%lx) PSW=%04lx RPT_S=%04lx RPT_E=%04lx RPT_C=%04lx\n", (long) pc, (long) d10v_make_iaddr (pc), (long) psw, (long) rpt_s, (long) rpt_e, (long) rpt_c); @@ -814,7 +810,7 @@ d10v_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file, for (r = group; r < group + 8; r++) { ULONGEST tmp; - frame_read_unsigned_register (frame, r, &tmp); + tmp = get_frame_register_unsigned (frame, r); fprintf_filtered (file, " %04lx", (long) tmp); } fprintf_filtered (file, "\n"); @@ -856,7 +852,7 @@ d10v_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file, { int i; fprintf_filtered (file, " "); - frame_read_register (frame, a, num); + get_frame_register (frame, a, num); for (i = 0; i < register_size (gdbarch, a); i++) { fprintf_filtered (file, "%02x", (num[i] & 0xff)); @@ -908,7 +904,7 @@ d10v_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) } /* When arguments must be pushed onto the stack, they go on in reverse - order. The below implements a FILO (stack) to do this. */ + order. The below implements a FILO (stack) to do this. */ struct stack_item { @@ -965,8 +961,8 @@ d10v_push_dummy_code (struct gdbarch *gdbarch, static CORE_ADDR d10v_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr, struct regcache *regcache, CORE_ADDR bp_addr, - int nargs, struct value **args, CORE_ADDR sp, int struct_return, - CORE_ADDR struct_addr) + int nargs, struct value **args, CORE_ADDR sp, + int struct_return, CORE_ADDR struct_addr) { int i; int regnum = ARG1_REGNUM; @@ -1042,51 +1038,11 @@ d10v_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr, return sp; } - -/* Given a return value in `regbuf' with a type `valtype', - extract and copy its value into `valbuf'. */ - -static void -d10v_extract_return_value (struct type *type, struct regcache *regcache, - void *valbuf) -{ - int len; - if (TYPE_LENGTH (type) == 1) - { - ULONGEST c; - regcache_cooked_read_unsigned (regcache, RET1_REGNUM, &c); - store_unsigned_integer (valbuf, 1, c); - } - else - { - /* For return values of odd size, the first byte is in the - least significant part of the first register. The - remaining bytes in remaining registers. Interestingly, when - such values are passed in, the last byte is in the most - significant byte of that same register - wierd. */ - int reg = RET1_REGNUM; - int off = 0; - if (TYPE_LENGTH (type) & 1) - { - regcache_cooked_read_part (regcache, RET1_REGNUM, 1, 1, - (bfd_byte *)valbuf + off); - off++; - reg++; - } - /* Transfer the remaining registers. */ - for (; off < TYPE_LENGTH (type); reg++, off += 2) - { - regcache_cooked_read (regcache, RET1_REGNUM + reg, - (bfd_byte *) valbuf + off); - } - } -} - /* Translate a GDB virtual ADDR/LEN into a format the remote target understands. Returns number of bytes that can be transfered starting at TARG_ADDR. Return ZERO if no bytes can be transfered (segmentation fault). Since the simulator knows all about how the - VM system works, we just call that to do the translation. */ + VM system works, we just call that to do the translation. */ static void remote_d10v_translate_xfer_address (struct gdbarch *gdbarch, @@ -1313,7 +1269,8 @@ tdisassemble_command (char *arg, int from_tty) } } - printf_filtered ("Dump of trace from %s to %s:\n", paddr_u (low), paddr_u (high)); + printf_filtered ("Dump of trace from %s to %s:\n", + paddr_u (low), paddr_u (high)); display_trace (low, high); @@ -1403,11 +1360,6 @@ d10v_frame_this_id (struct frame_info *next_frame, /* 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 (func <= IMEM_START || deprecated_inside_entry_file (func)) - return; - /* Hopefully the prologue analysis either correctly determined the frame's base (which is the SP from the previous frame), or set that base to "NULL". */ @@ -1483,13 +1435,13 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) gdbarch_register_name_ftype *d10v_register_name; gdbarch_register_sim_regno_ftype *d10v_register_sim_regno; - /* Find a candidate among the list of pre-declared architectures. */ + /* Find a candidate among the list of pre-declared architectures. */ arches = gdbarch_list_lookup_by_info (arches, &info); if (arches != NULL) return arches->gdbarch; /* None found, create a new architecture from the information - provided. */ + provided. */ tdep = XMALLOC (struct gdbarch_tdep); gdbarch = gdbarch_alloc (&info, tdep); @@ -1535,7 +1487,7 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT); set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT); /* NOTE: The d10v as a 32 bit ``float'' and ``double''. ``long - double'' is 64 bits. */ + double'' is 64 bits. */ set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT); set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT); set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT); @@ -1549,19 +1501,17 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) case BFD_ENDIAN_LITTLE: 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_double_little); + set_gdbarch_long_double_format (gdbarch, + &floatformat_ieee_double_little); break; default: internal_error (__FILE__, __LINE__, "d10v_gdbarch_init: bad byte order for float format"); } - set_gdbarch_extract_return_value (gdbarch, d10v_extract_return_value); + set_gdbarch_return_value (gdbarch, d10v_return_value); set_gdbarch_push_dummy_code (gdbarch, d10v_push_dummy_code); set_gdbarch_push_dummy_call (gdbarch, d10v_push_dummy_call); - set_gdbarch_store_return_value (gdbarch, d10v_store_return_value); - set_gdbarch_extract_struct_value_address (gdbarch, d10v_extract_struct_value_address); - set_gdbarch_use_struct_convention (gdbarch, d10v_use_struct_convention); set_gdbarch_skip_prologue (gdbarch, d10v_skip_prologue); set_gdbarch_inner_than (gdbarch, core_addr_lessthan); @@ -1569,10 +1519,12 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_function_start_offset (gdbarch, 0); set_gdbarch_breakpoint_from_pc (gdbarch, d10v_breakpoint_from_pc); - set_gdbarch_remote_translate_xfer_address (gdbarch, remote_d10v_translate_xfer_address); + set_gdbarch_remote_translate_xfer_address (gdbarch, + remote_d10v_translate_xfer_address); set_gdbarch_frame_args_skip (gdbarch, 0); - set_gdbarch_frameless_function_invocation (gdbarch, frameless_look_for_prologue); + set_gdbarch_frameless_function_invocation (gdbarch, + frameless_look_for_prologue); set_gdbarch_frame_align (gdbarch, d10v_frame_align); @@ -1604,7 +1556,8 @@ _initialize_d10v_tdep (void) target_resume_hook = d10v_eva_prepare_to_trace; target_wait_loop_hook = d10v_eva_get_trace_data; - deprecate_cmd (add_com ("regs", class_vars, show_regs, "Print all registers"), + deprecate_cmd (add_com ("regs", class_vars, show_regs, + "Print all registers"), "info registers"); add_com ("itrace", class_support, trace_command, |