aboutsummaryrefslogtreecommitdiff
path: root/gdb/mn10200-tdep.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>1997-03-05 20:01:04 +0000
committerJeff Law <law@redhat.com>1997-03-05 20:01:04 +0000
commitfc5c75955bde5eb212becddb87ba479305059ad8 (patch)
tree1c2d12b69e94799eca915d13990e81cc20dfaac1 /gdb/mn10200-tdep.c
parent1ea5264653b5c098d2d4bc2bd02c2e4b1d7c6c7a (diff)
downloadgdb-fc5c75955bde5eb212becddb87ba479305059ad8.zip
gdb-fc5c75955bde5eb212becddb87ba479305059ad8.tar.gz
gdb-fc5c75955bde5eb212becddb87ba479305059ad8.tar.bz2
* mn10200-tdep.c (mn10200_push_arguments): Handle new calling
conventions. (mn10200_store_struct_return): Likewise.
Diffstat (limited to 'gdb/mn10200-tdep.c')
-rw-r--r--gdb/mn10200-tdep.c77
1 files changed, 55 insertions, 22 deletions
diff --git a/gdb/mn10200-tdep.c b/gdb/mn10200-tdep.c
index 942e5b9..206e553 100644
--- a/gdb/mn10200-tdep.c
+++ b/gdb/mn10200-tdep.c
@@ -532,6 +532,7 @@ mn10200_push_arguments (nargs, args, sp, struct_return, struct_addr)
int argnum = 0;
int len = 0;
int stack_offset = 0;
+ int regsused = struct_return ? 1 : 0;
/* This should be a nop, but align the stack just in case something
went wrong. Stacks are two byte aligned on the mn10200. */
@@ -542,19 +543,45 @@ mn10200_push_arguments (nargs, args, sp, struct_return, struct_addr)
XXX This doesn't appear to handle pass-by-invisible reference
arguments. */
for (argnum = 0; argnum < nargs; argnum++)
- len += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 1) & ~1);
+ {
+ int arg_length = (TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 1) & ~1;
+
+ /* If we've used all argument registers, then this argument is
+ pushed. */
+ if (regsused >= 2 || arg_length > 4)
+ {
+ regsused = 2;
+ len += arg_length;
+ }
+ /* We know we've got some arg register space left. If this argument
+ will fit entirely in regs, then put it there. */
+ else if (arg_length <= 2
+ || TYPE_CODE (VALUE_TYPE (args[argnum])) == TYPE_CODE_PTR)
+ {
+ regsused++;
+ }
+ else if (regsused == 0)
+ {
+ regsused = 2;
+ }
+ else
+ {
+ regsused = 2;
+ len += arg_length;
+ }
+ }
/* Allocate stack space. */
sp -= len;
+ regsused = struct_return ? 1 : 0;
/* Push all arguments onto the stack. */
for (argnum = 0; argnum < nargs; argnum++)
{
int len;
char *val;
- /* XXX Check this. What about UNIONS? Size check looks
- wrong too. */
+ /* XXX Check this. What about UNIONS? */
if (TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_STRUCT
&& TYPE_LENGTH (VALUE_TYPE (*args)) > 8)
{
@@ -568,14 +595,30 @@ mn10200_push_arguments (nargs, args, sp, struct_return, struct_addr)
val = (char *)VALUE_CONTENTS (*args);
}
- while (len > 0)
+ if (regsused < 2
+ && (len <= 2
+ || TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_PTR))
{
- /* XXX This looks wrong; we can have one and two byte args. */
- write_memory (sp + stack_offset, val, 2);
+ write_register (regsused, extract_unsigned_integer (val, 4));
+ regsused++;
+ }
+ else if (regsused == 0 && len == 4)
+ {
+ write_register (regsused, extract_unsigned_integer (val, 2));
+ write_register (regsused + 1, extract_unsigned_integer (val + 2, 2));
+ regsused = 2;
+ }
+ else
+ {
+ regsused = 2;
+ while (len > 0)
+ {
+ write_memory (sp + stack_offset, val, 2);
- len -= 2;
- val += 2;
- stack_offset += 2;
+ len -= 2;
+ val += 2;
+ stack_offset += 2;
+ }
}
args++;
}
@@ -608,19 +651,9 @@ mn10200_store_struct_return (addr, sp)
CORE_ADDR addr;
CORE_ADDR sp;
{
- unsigned char buf1[4];
- unsigned char buf2[4];
-
- /* Get the saved PC and hold onto it. */
- target_read_memory (sp, buf1, 4);
-
- /* Now push the structure value address. */
- store_unsigned_integer (buf2, 4, addr);
- write_memory (sp, buf2, 4);
-
- /* Now push the saved PC back onto the stack. */
- target_write_memory (sp - 4, buf1, 4);
- return sp - 4;
+ /* The structure return address is passed as the first argument. */
+ write_register (0, addr);
+ return sp;
}
/* Function: frame_saved_pc