aboutsummaryrefslogtreecommitdiff
path: root/gdb/arm-tdep.c
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>1998-11-23 12:35:23 +0000
committerAndrew Cagney <cagney@redhat.com>1998-11-23 12:35:23 +0000
commit98760eab33f4963e075077cb094f9f195ca33d01 (patch)
tree60590f385f7cdd40ccf6ce14fa0437140b19686a /gdb/arm-tdep.c
parent554eb429e4555ceaa7892a8ab93c7a41045a6824 (diff)
downloadfsf-binutils-gdb-98760eab33f4963e075077cb094f9f195ca33d01.zip
fsf-binutils-gdb-98760eab33f4963e075077cb094f9f195ca33d01.tar.gz
fsf-binutils-gdb-98760eab33f4963e075077cb094f9f195ca33d01.tar.bz2
CARP: Convert macro definitions of USE_STRUCT_CONVENTION into target
specific functions.
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r--gdb/arm-tdep.c98
1 files changed, 71 insertions, 27 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index ce55733..a190765 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -27,6 +27,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "gdb_string.h"
#include "coff/internal.h" /* Internal format of COFF symbols in BFD */
+/*
+ The following macros are actually wrong. Neither arm nor thumb can
+ or should set the lsb on addr.
+ The thumb addresses are mod 2, so (addr & 2) would be a good heuristic
+ to use when checking for thumb (see arm_pc_is_thumb() below).
+ Unfortunately, something else depends on these (incorrect) macros, so
+ fixing them actually breaks gdb. I didn't have time to investigate. Z.R.
+*/
/* Thumb function addresses are odd (bit 0 is set). Here are some
macros to test, set, or clear bit 0 of addresses. */
#define IS_THUMB_ADDR(addr) ((addr) & 1)
@@ -38,6 +46,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define ROUND_DOWN(n,a) ((n) & ~((a) - 1))
#define ROUND_UP(n,a) (((n) + (a) - 1) & ~((a) - 1))
+/* Should call_function allocate stack space for a struct return? */
+/* The system C compiler uses a similar structure return convention to gcc */
+int
+arm_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 4);
+}
+
/* Set to true if the 32-bit mode is in use. */
int arm_apcs_32 = 1;
@@ -838,6 +856,15 @@ arm_push_arguments(nargs, args, sp, struct_return, struct_addr)
int float_argreg;
int argnum;
int stack_offset;
+ struct stack_arg {
+ char *val;
+ int len;
+ int offset;
+ };
+ struct stack_arg *stack_args =
+ (struct stack_arg*)alloca (nargs * sizeof (struct stack_arg));
+ int nstack_args = 0;
+
/* Initialize the integer and float register pointers. */
argreg = A1_REGNUM;
@@ -852,10 +879,9 @@ arm_push_arguments(nargs, args, sp, struct_return, struct_addr)
This leaves room for the "home" area for register parameters. */
stack_offset = REGISTER_SIZE * 4;
- /* Now load as many as possible of the first arguments into
- registers, and push the rest onto the stack. Loop thru args
- from first to last. */
- for (argnum = 0; argnum < nargs; argnum++)
+ /* Process args from left to right. Store as many as allowed in
+ registers, save the rest to be pushed on the stack */
+ for(argnum = 0; argnum < nargs; argnum++)
{
char * val;
value_ptr arg = args[argnum];
@@ -864,6 +890,7 @@ arm_push_arguments(nargs, args, sp, struct_return, struct_addr)
int len = TYPE_LENGTH (arg_type);
enum type_code typecode = TYPE_CODE (arg_type);
CORE_ADDR regval;
+ int newarg;
val = (char *) VALUE_CONTENTS (arg);
@@ -899,30 +926,35 @@ arm_push_arguments(nargs, args, sp, struct_return, struct_addr)
registers and stack. */
while (len > 0)
{
- int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
-
if (argreg <= ARM_LAST_ARG_REGNUM)
{
+ int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
regval = extract_address (val, partial_len);
/* It's a simple argument being passed in a general
register. */
write_register (argreg, regval);
argreg++;
+ len -= partial_len;
+ val += partial_len;
}
else
{
- /* Write this portion of the argument to the stack. */
- partial_len = len;
- sp -= partial_len;
- write_memory (sp, val, partial_len);
+ /* keep for later pushing */
+ stack_args[nstack_args].val = val;
+ stack_args[nstack_args++].len = len;
+ break;
}
-
- len -= partial_len;
- val += partial_len;
}
}
}
+ /* now do the real stack pushing, process args right to left */
+ while(nstack_args--)
+ {
+ sp -= stack_args[nstack_args].len;
+ write_memory(sp, stack_args[nstack_args].val,
+ stack_args[nstack_args].len);
+ }
/* Return adjusted stack pointer. */
return sp;
@@ -1436,27 +1468,39 @@ arm_breakpoint_from_pc (pcptr, lenptr)
CORE_ADDR * pcptr;
int * lenptr;
{
- CORE_ADDR sp = read_sp();
-
if (arm_pc_is_thumb (*pcptr) || arm_pc_is_thumb_dummy (*pcptr))
{
- static char thumb_breakpoint[] = THUMB_BREAKPOINT;
-
- *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
- *lenptr = sizeof (thumb_breakpoint);
-
- return thumb_breakpoint;
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ static char thumb_breakpoint[] = THUMB_BE_BREAKPOINT;
+ *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
+ *lenptr = sizeof (thumb_breakpoint);
+ return thumb_breakpoint;
+ }
+ else
+ {
+ static char thumb_breakpoint[] = THUMB_LE_BREAKPOINT;
+ *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
+ *lenptr = sizeof (thumb_breakpoint);
+ return thumb_breakpoint;
+ }
}
else
{
- static char arm_breakpoint[] = ARM_BREAKPOINT;
-
- *lenptr = sizeof (arm_breakpoint);
-
- return arm_breakpoint;
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ static char arm_breakpoint[] = ARM_BE_BREAKPOINT;
+ *lenptr = sizeof (arm_breakpoint);
+ return arm_breakpoint;
+ }
+ else
+ {
+ static char arm_breakpoint[] = ARM_LE_BREAKPOINT;
+ *lenptr = sizeof (arm_breakpoint);
+ return arm_breakpoint;
+ }
}
}
-
/* Return non-zero if the PC is inside a call thunk (aka stub or trampoline).
This implements the IN_SOLIB_CALL_TRAMPOLINE macro. */