aboutsummaryrefslogtreecommitdiff
path: root/gdb/fr30-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/fr30-tdep.c')
-rw-r--r--gdb/fr30-tdep.c52
1 files changed, 48 insertions, 4 deletions
diff --git a/gdb/fr30-tdep.c b/gdb/fr30-tdep.c
index 0d442da..ae3b886 100644
--- a/gdb/fr30-tdep.c
+++ b/gdb/fr30-tdep.c
@@ -56,6 +56,48 @@ fr30_pop_frame ()
flush_cached_frames ();
}
+
+/* Function: fr30_store_return_value
+ Put a value where a caller expects to see it. Used by the 'return'
+ command. */
+void
+fr30_store_return_value (struct type *type,
+ char *valbuf)
+{
+ /* Here's how the FR30 returns values (gleaned from gcc/config/
+ fr30/fr30.h):
+
+ If the return value is 32 bits long or less, it goes in r4.
+
+ If the return value is 64 bits long or less, it goes in r4 (most
+ significant word) and r5 (least significant word.
+
+ If the function returns a structure, of any size, the caller
+ passes the function an invisible first argument where the callee
+ should store the value. But GDB doesn't let you do that anyway.
+
+ If you're returning a value smaller than a word, it's not really
+ necessary to zero the upper bytes of the register; the caller is
+ supposed to ignore them. However, the FR30 typically keeps its
+ values extended to the full register width, so we should emulate
+ that. */
+
+ /* The FR30 is big-endian, so if we return a small value (like a
+ short or a char), we need to position it correctly within the
+ register. We round the size up to a register boundary, and then
+ adjust the offset so as to place the value at the right end. */
+ int value_size = TYPE_LENGTH (type);
+ int returned_size = (value_size + FR30_REGSIZE - 1) & ~(FR30_REGSIZE - 1);
+ int offset = (REGISTER_BYTE (RETVAL_REG)
+ + (returned_size - value_size));
+ char *zeros = alloca (returned_size);
+ memset (zeros, 0, returned_size);
+
+ write_register_bytes (REGISTER_BYTE (RETVAL_REG), zeros, returned_size);
+ write_register_bytes (offset, valbuf, value_size);
+}
+
+
/* Function: skip_prologue
Return the address of the first code past the prologue of the function. */
@@ -180,11 +222,13 @@ fr30_push_arguments(nargs, args, sp, struct_return, struct_addr)
return sp;
}
-_initialize_fr30_tdep()
-{
- extern int print_insn_fr30(bfd_vma, disassemble_info *);
+void _initialize_fr30_tdep PARAMS ((void));
- tm_print_insn = print_insn_fr30;
+void
+_initialize_fr30_tdep ()
+{
+ extern int print_insn_fr30(bfd_vma, disassemble_info *);
+ tm_print_insn = print_insn_fr30;
}
/* Function: check_prologue_cache