summaryrefslogtreecommitdiff
path: root/gdb/ia64-tdep.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2007-10-13 00:05:07 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2007-10-13 00:05:07 +0000
commit21acbb9a4bbb9ef5a42d71f4e736b0589d1755f5 (patch)
tree240f5a6f8283ab342cf24c75c8347784efe8601b /gdb/ia64-tdep.c
parent152236d6364b64f7e6da56381f7c97e023b426f5 (diff)
downloadgdb-21acbb9a4bbb9ef5a42d71f4e736b0589d1755f5.tar.gz
* avr-tdep.c (avr_return_value): New function.
(avr_gdbarch_init): Call set_gdbarch_return_value instead of set_gdbarch_extract_return_value. * fvr-tdep.c (frv_return_value): New function. (frv_gdbarch_init): Call set_gdbarch_return_value instead of set_gdbarch_extract_return_value, set_gdbarch_store_return_value, and set_gdbarch_deprecated_use_struct_convention. * ia64-tdep.c (ia64_use_struct_convention): Make static. Add check for structure, union, or array types. (ia64_extract_return_value): Make static. (ia64_store_return_value): Make static. Support multi-word values. (ia64_return_value): New function. (ia64_gdbarch_init): Call set_gdbarch_return_value instead of set_gdbarch_extract_return_value, set_gdbarch_store_return_value, and set_gdbarch_deprecated_use_struct_convention.
Diffstat (limited to 'gdb/ia64-tdep.c')
-rw-r--r--gdb/ia64-tdep.c110
1 files changed, 85 insertions, 25 deletions
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index dd938c95e85..debee50851c 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -2929,14 +2929,18 @@ static struct libunwind_descr ia64_libunwind_descr =
#endif /* HAVE_LIBUNWIND_IA64_H */
-/* Should we use DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS instead of
- gdbarch_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). */
-int
-ia64_use_struct_convention (int gcc_p, struct type *type)
+static int
+ia64_use_struct_convention (struct type *type)
{
struct type *float_elt_type;
+ /* Don't use the struct convention for anything but structure,
+ union, or array types. */
+ if (!(TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION
+ || TYPE_CODE (type) == TYPE_CODE_ARRAY))
+ return 0;
+
/* HFAs are structures (or arrays) consisting entirely of floating
point values of the same length. Up to 8 of these are returned
in registers. Don't use the struct convention when this is the
@@ -2951,7 +2955,7 @@ ia64_use_struct_convention (int gcc_p, struct type *type)
return TYPE_LENGTH (type) > 32;
}
-void
+static void
ia64_extract_return_value (struct type *type, struct regcache *regcache,
gdb_byte *valbuf)
{
@@ -3001,6 +3005,80 @@ ia64_extract_return_value (struct type *type, struct regcache *regcache,
}
}
+static void
+ia64_store_return_value (struct type *type, struct regcache *regcache,
+ const gdb_byte *valbuf)
+{
+ struct type *float_elt_type;
+
+ float_elt_type = is_float_or_hfa_type (type);
+ if (float_elt_type != NULL)
+ {
+ char to[MAX_REGISTER_SIZE];
+ int offset = 0;
+ int regnum = IA64_FR8_REGNUM;
+ int n = TYPE_LENGTH (type) / TYPE_LENGTH (float_elt_type);
+
+ while (n-- > 0)
+ {
+ convert_typed_floating ((char *)valbuf + offset, float_elt_type,
+ to, builtin_type_ia64_ext);
+ regcache_cooked_write (regcache, regnum, to);
+ offset += TYPE_LENGTH (float_elt_type);
+ regnum++;
+ }
+ }
+ else
+ {
+ ULONGEST val;
+ int offset = 0;
+ int regnum = IA64_GR8_REGNUM;
+ int reglen = TYPE_LENGTH (register_type (get_regcache_arch (regcache),
+ IA64_GR8_REGNUM));
+ int n = TYPE_LENGTH (type) / reglen;
+ int m = TYPE_LENGTH (type) % reglen;
+
+ while (n-- > 0)
+ {
+ ULONGEST val;
+ memcpy (&val, (char *)valbuf + offset, reglen);
+ regcache_cooked_write_unsigned (regcache, regnum, val);
+ offset += reglen;
+ regnum++;
+ }
+
+ if (m)
+ {
+ memcpy (&val, (char *)valbuf + offset, m);
+ regcache_cooked_write_unsigned (regcache, regnum, val);
+ }
+ }
+}
+
+static enum return_value_convention
+ia64_return_value (struct gdbarch *gdbarch, struct type *valtype,
+ struct regcache *regcache, gdb_byte *readbuf,
+ const gdb_byte *writebuf)
+{
+ int struct_return = ia64_use_struct_convention (valtype);
+
+ if (writebuf != NULL)
+ {
+ gdb_assert (!struct_return);
+ ia64_store_return_value (valtype, regcache, writebuf);
+ }
+
+ if (readbuf != NULL)
+ {
+ gdb_assert (!struct_return);
+ ia64_extract_return_value (valtype, regcache, readbuf);
+ }
+
+ if (struct_return)
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ else
+ return RETURN_VALUE_REGISTER_CONVENTION;
+}
static int
is_float_or_hfa_type_recurse (struct type *t, struct type **etp)
@@ -3462,21 +3540,6 @@ ia64_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
return pc;
}
-static void
-ia64_store_return_value (struct type *type, struct regcache *regcache,
- const gdb_byte *valbuf)
-{
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
- {
- char to[MAX_REGISTER_SIZE];
- convert_typed_floating (valbuf, type, to, builtin_type_ia64_ext);
- regcache_cooked_write (regcache, IA64_FR8_REGNUM, (void *)to);
- target_store_registers (regcache, IA64_FR8_REGNUM);
- }
- else
- regcache_cooked_write (regcache, IA64_GR8_REGNUM, valbuf);
-}
-
static int
ia64_print_insn (bfd_vma memaddr, struct disassemble_info *info)
{
@@ -3544,10 +3607,7 @@ ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_skip_prologue (gdbarch, ia64_skip_prologue);
- set_gdbarch_deprecated_use_struct_convention (gdbarch, ia64_use_struct_convention);
- set_gdbarch_extract_return_value (gdbarch, ia64_extract_return_value);
-
- set_gdbarch_store_return_value (gdbarch, ia64_store_return_value);
+ set_gdbarch_return_value (gdbarch, ia64_return_value);
set_gdbarch_memory_insert_breakpoint (gdbarch, ia64_memory_insert_breakpoint);
set_gdbarch_memory_remove_breakpoint (gdbarch, ia64_memory_remove_breakpoint);