aboutsummaryrefslogtreecommitdiff
path: root/gdb/d10v-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/d10v-tdep.c')
-rw-r--r--gdb/d10v-tdep.c273
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,
+ &regval);
+ 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,