aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog27
-rw-r--r--gdb/a29k-tdep.c12
-rw-r--r--gdb/arm-tdep.c98
-rw-r--r--gdb/config/a29k/tm-a29k.h3
-rw-r--r--gdb/config/arm/tm-arm.h389
-rw-r--r--gdb/config/d10v/tm-d10v.h4
-rw-r--r--gdb/config/i960/tm-i960.h3
-rw-r--r--gdb/config/m32r/tm-m32r.h4
-rw-r--r--gdb/config/mips/tm-mips.h10
-rw-r--r--gdb/config/mn10200/tm-mn10200.h4
-rw-r--r--gdb/config/mn10300/tm-mn10300.h4
-rw-r--r--gdb/config/sh/tm-sh.h3
-rw-r--r--gdb/config/v850/tm-v850.h4
-rw-r--r--gdb/d10v-tdep.c16
-rw-r--r--gdb/defs.h5
-rw-r--r--gdb/gould-tdep.c11
-rw-r--r--gdb/hppa-tdep.c10
-rw-r--r--gdb/i960-tdep.c22
-rw-r--r--gdb/mips-tdep.c65
-rw-r--r--gdb/mn10200-tdep.c12
-rw-r--r--gdb/mn10300-tdep.c13
-rw-r--r--gdb/sh-tdep.c11
-rw-r--r--gdb/v850-tdep.c11
-rw-r--r--gdb/values.c23
24 files changed, 548 insertions, 216 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1a8c0a0..03bab36 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,30 @@
+Mon Nov 23 10:47:54 1998 Andrew Cagney <cagney@chook.cygnus.com>
+
+ * config/sh/tm-sh.h, config/mn10200/tm-mn10200.h,
+ config/m32r/tm-m32r.h, config/arm/tm-arm.h, config/i960/tm-i960.h,
+ config/gould/tm-np1.h, config/d10v/tm-d10v.h,
+ config/v850/tm-v850.h, config/pa/tm-hppa.h, config/a29k/tm-a29k.h,
+ config/mn10300/tm-mn10300.h, config/mips/tm-mips.h
+ (USE_STRUCT_CONVENTION): Cleanup, define macro as function.
+
+ * sh-tdep.c (sh_use_struct_convention), mn10200-tdep.c
+ (mn10200_use_struct_convention), i960-tdep.c
+ (i960_use_struct_convention), gould-tdep.c
+ (gould_use_struct_convention), d10v-tdep.c
+ (d10v_use_struct_convention), v850-tdep.c
+ (v850_use_struct_convention), hppa-tdep.c
+ (hpha_use_struct_convention), m32r-tdep.c
+ (m32r_use_struct_convention), arm-tdep.c
+ (arm_use_struct_convention), mn10300-tdep.c
+ (mn10300_use_struct_convention), a29k-tdep.c
+ (a29k_use_struct_convention), mips-tdep.c
+ (mips_use_struct_convention): New functions
+
+ * value.h, values.c (generic_use_struct_convention): New function,
+ replace macro.
+ * values.c (USE_STRUCT_CONVENTION): Macro defaults to function
+ generic_use_struct_convention.
+
Sat Nov 21 17:15:40 1998 Philippe De Muyter <phdm@macqel.be>
* breakpoint.c (bpstat_stop_status): Do not increment hit_count
diff --git a/gdb/a29k-tdep.c b/gdb/a29k-tdep.c
index 696f284..d51d915 100644
--- a/gdb/a29k-tdep.c
+++ b/gdb/a29k-tdep.c
@@ -41,6 +41,18 @@ extern CORE_ADDR text_start; /* FIXME, kludge... */
static CORE_ADDR rstack_high_address = UINT_MAX;
+
+/* Should call_function allocate stack space for a struct return? */
+/* On the a29k objects over 16 words require the caller to allocate space. */
+int
+a29k_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 16 * 4);
+}
+
+
/* Structure to hold cached info about function prologues. */
struct prologue_info
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. */
diff --git a/gdb/config/a29k/tm-a29k.h b/gdb/config/a29k/tm-a29k.h
index 2be97ef..e71081f 100644
--- a/gdb/config/a29k/tm-a29k.h
+++ b/gdb/config/a29k/tm-a29k.h
@@ -281,7 +281,8 @@ CORE_ADDR skip_prologue ();
/* Should call_function allocate stack space for a struct return? */
/* On the a29k objects over 16 words require the caller to allocate space. */
-#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 16 * 4)
+extern use_struct_convention_fn a29k_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) a29k_use_struct_convention (gcc_p, type)
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
diff --git a/gdb/config/arm/tm-arm.h b/gdb/config/arm/tm-arm.h
index 7775ea2..202a815 100644
--- a/gdb/config/arm/tm-arm.h
+++ b/gdb/config/arm/tm-arm.h
@@ -1,5 +1,5 @@
-/* Definitions to make GDB target for an ARM under RISCiX (4.3bsd).
- Copyright 1986, 1987, 1989, 1991, 1993 Free Software Foundation, Inc.
+/* Definitions to make GDB target for an ARM
+ Copyright 1986, 1987, 1989, 1991, 1993, 1997, 1998 Free Software Foundation, Inc.
This file is part of GDB.
@@ -15,17 +15,36 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct type;
+struct value;
+#endif
+
+#define TARGET_BYTE_ORDER_SELECTABLE
/* IEEE format floating point */
#define IEEE_FLOAT
-/* I provide my own xfer_core_file to cope with shared libraries */
+/* FIXME: may need a floatformat_ieee_double_bigbyte_littleword format for
+ BIG_ENDIAN use. -fnf */
+
+#define TARGET_DOUBLE_FORMAT (target_byte_order == BIG_ENDIAN \
+ ? &floatformat_ieee_double_big \
+ : &floatformat_ieee_double_littlebyte_bigword)
+
+/* When reading symbols, we need to zap the low bit of the address, which
+ may be set to 1 for Thumb functions. */
+
+#define SMASH_TEXT_ADDRESS(addr) ((addr) &= ~0x1)
+
+/* Remove useless bits from addresses in a running program. */
-#define XFER_CORE_FILE
+CORE_ADDR arm_addr_bits_remove PARAMS ((CORE_ADDR));
+
+#define ADDR_BITS_REMOVE(val) (arm_addr_bits_remove (val))
/* Offset from address of function to start of its code.
Zero on most machines. */
@@ -35,14 +54,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
-#define SKIP_PROLOGUE(pc) pc = skip_prologue(pc)
+extern CORE_ADDR arm_skip_prologue PARAMS ((CORE_ADDR pc));
+
+#define SKIP_PROLOGUE(pc) { pc = arm_skip_prologue (pc); }
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
-#define SAVED_PC_AFTER_CALL(frame) (read_register (LR_REGNUM) & 0x03fffffc)
+#define SAVED_PC_AFTER_CALL(frame) arm_saved_pc_after_call (frame)
+struct frame_info;
+extern CORE_ADDR arm_saved_pc_after_call PARAMS ((struct frame_info *));
/* I don't know the real values for these. */
#define TARGET_UPAGES UPAGES
@@ -58,7 +81,30 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Sequence of bytes for breakpoint instruction. */
-#define BREAKPOINT {0x00,0x00,0x18,0xef} /* BKPT_SWI from <sys/ptrace.h> */
+/* !!!! if we're using RDP, then we're inserting breakpoints and storing
+ their handles instread of what was in memory. It is nice that
+ this is the same size as a handle - otherwise remote-rdp will
+ have to change. */
+
+#define ARM_LE_BREAKPOINT {0x00,0x00,0x18,0xef} /* BKPT_SWI from <sys/ptrace.h> */
+#define ARM_BE_BREAKPOINT {0xef,0x18,0x00,0x00} /* BKPT_SWI from <sys/ptrace.h> */
+#define THUMB_LE_BREAKPOINT {0x18,0xdf} /* swi 24 */
+#define THUMB_BE_BREAKPOINT {0xdf,0x18} /* swi 24 */
+
+/* The following has been superseded by BREAKPOINT_FOR_PC, but
+ is defined merely to keep mem-break.c happy. */
+#define LITTLE_BREAKPOINT ARM_LE_BREAKPOINT
+#define BIG_BREAKPOINT ARM_BE_BREAKPOINT
+
+/* BREAKPOINT_FROM_PC uses the program counter value to determine whether a
+ 16- or 32-bit breakpoint should be used. It returns a pointer
+ to a string of bytes that encode a breakpoint instruction, stores
+ the length of the string to *lenptr, and adjusts the pc (if necessary) to
+ point to the actual memory location where the breakpoint should be
+ inserted. */
+
+unsigned char * arm_breakpoint_from_pc PARAMS ((CORE_ADDR * pcptr, int * lenptr));
+#define BREAKPOINT_FROM_PC(pcptr, lenptr) arm_breakpoint_from_pc (pcptr, lenptr)
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
@@ -72,20 +118,17 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
((read_memory_integer(pc, 4) & 0x0fffffff == 0x01b0f00e) || \
(read_memory_integer(pc, 4) & 0x0ffff800 == 0x09eba800))
-/* Return 1 if P points to an invalid floating point value.
- LEN is the length in bytes. */
-
-#define INVALID_FLOAT(p, len) 0
-
/* code to execute to print interesting information about the
* floating point processor (if any)
* No need to define if there is nothing to do.
*/
#define FLOAT_INFO { arm_float_info (); }
-/* Say how long (ordinary) registers are. */
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
-#define REGISTER_TYPE long
+#define REGISTER_SIZE 4
/* Number of machine registers */
@@ -97,11 +140,32 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
-#define REGISTER_NAMES \
- { "a1", "a2", "a3", "a4", \
- "v1", "v2", "v3", "v4", "v5", "v6", \
- "sl", "fp", "ip", "sp", "lr", "pc", \
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "fps", "ps" }
+#define ORIGINAL_REGISTER_NAMES \
+{ "a1", "a2", "a3", "a4", /* 0 1 2 3 */ \
+ "v1", "v2", "v3", "v4", /* 4 5 6 7 */ \
+ "v5", "v6", "sl", "fp", /* 8 9 10 11 */ \
+ "ip", "sp", "lr", "pc", /* 12 13 14 15 */ \
+ "f0", "f1", "f2", "f3", /* 16 17 18 19 */ \
+ "f4", "f5", "f6", "f7", /* 20 21 22 23 */ \
+ "fps","ps" } /* 24 25 */
+
+/* These names are the ones which gcc emits, and
+ I find them less confusing. Toggle between them
+ using the `othernames' command. */
+
+#define ADDITIONAL_REGISTER_NAMES \
+{ "r0", "r1", "r2", "r3", /* 0 1 2 3 */ \
+ "r4", "r5", "r6", "r7", /* 4 5 6 7 */ \
+ "r8", "r9", "sl", "fp", /* 8 9 10 11 */ \
+ "ip", "sp", "lr", "pc", /* 12 13 14 15 */ \
+ "f0", "f1", "f2", "f3", /* 16 17 18 19 */ \
+ "f4", "f5", "f6", "f7", /* 20 21 22 23 */ \
+ "fps","ps" } /* 24 25 */
+
+#define REGISTER_NAMES ADDITIONAL_REGISTER_NAMES
+#ifndef REGISTER_NAMES
+#define REGISTER_NAMES ORIGINAL_REGISTER_NAMES
+#endif
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
@@ -110,15 +174,50 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
+#define A1_REGNUM 0 /* first integer-like argument */
+#define A4_REGNUM 3 /* last integer-like argument */
#define AP_REGNUM 11
#define FP_REGNUM 11 /* Contains address of executing stack frame */
#define SP_REGNUM 13 /* Contains address of top of stack */
#define LR_REGNUM 14 /* address to return to from a function call */
#define PC_REGNUM 15 /* Contains program counter */
#define F0_REGNUM 16 /* first floating point register */
+#define F3_REGNUM 19 /* last floating point argument register */
+#define F7_REGNUM 23 /* last floating point register */
#define FPS_REGNUM 24 /* floating point status register */
#define PS_REGNUM 25 /* Contains processor status */
+#define THUMB_FP_REGNUM 7 /* R7 is frame register on Thumb */
+
+#define ARM_NUM_ARG_REGS 4
+#define ARM_LAST_ARG_REGNUM A4_REGNUM
+#define ARM_NUM_FP_ARG_REGS 4
+#define ARM_LAST_FP_ARG_REGNUM F3_REGNUM
+
+/* Instruction condition field values. */
+#define INST_EQ 0x0
+#define INST_NE 0x1
+#define INST_CS 0x2
+#define INST_CC 0x3
+#define INST_MI 0x4
+#define INST_PL 0x5
+#define INST_VS 0x6
+#define INST_VC 0x7
+#define INST_HI 0x8
+#define INST_LS 0x9
+#define INST_GE 0xa
+#define INST_LT 0xb
+#define INST_GT 0xc
+#define INST_LE 0xd
+#define INST_AL 0xe
+#define INST_NV 0xf
+
+#define FLAG_N 0x80000000
+#define FLAG_Z 0x40000000
+#define FLAG_C 0x20000000
+#define FLAG_V 0x10000000
+
+
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
@@ -143,7 +242,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Largest value REGISTER_RAW_SIZE can have. */
-#define MAX_REGISTER_RAW_SIZE 12
+#define MAX_REGISTER_RAW_SIZE 12
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
@@ -151,27 +250,26 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Nonzero if register N requires conversion
from raw format to virtual format. */
-
#define REGISTER_CONVERTIBLE(N) ((unsigned)(N) - F0_REGNUM < 8)
-/* Convert data from raw format for register REGNUM
- to virtual format for register REGNUM. */
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
-#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
- if (REGISTER_CONVERTIBLE(REGNUM)) \
- convert_from_extended((FROM), (TO)); \
- else \
- memcpy ((TO), (FROM), 4);
-
-/* Convert data from virtual format for register REGNUM
- to raw format for register REGNUM. */
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ double val; \
+ convert_from_extended ((FROM), & val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
-#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
- if (REGISTER_CONVERTIBLE(REGNUM)) \
- convert_to_extended((FROM), (TO)); \
- else \
- memcpy ((TO), (FROM), 4);
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ convert_to_extended (&val, (TO)); \
+}
/* Return the GDB type object for the "standard" data type
of data in register N. */
@@ -179,8 +277,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
(((unsigned)(N) - F0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
/* The system C compiler uses a similar structure return convention to gcc */
-
-#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 4)
+extern use_struct_convention_fn arm_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) arm_use_struct_convention (gcc_p, type)
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function. */
@@ -194,7 +292,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
- convert_from_extended(REGBUF + REGISTER_BYTE (F0_REGNUM), VALBUF); \
+ convert_from_extended (REGBUF + REGISTER_BYTE (F0_REGNUM), VALBUF); \
else \
memcpy (VALBUF, REGBUF, TYPE_LENGTH (TYPE))
@@ -204,7 +302,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) { \
char _buf[MAX_REGISTER_RAW_SIZE]; \
- convert_to_extended(VALBUF, _buf); \
+ convert_to_extended (VALBUF, _buf); \
write_register_bytes (REGISTER_BYTE (F0_REGNUM), _buf, MAX_REGISTER_RAW_SIZE); \
} else \
write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
@@ -221,6 +319,25 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) (!(gcc_p))
+/* Define other aspects of the stack frame.
+ We keep the offsets of all saved registers, 'cause we need 'em a lot!
+ We also keep the current size of the stack frame, and the offset of
+ the frame pointer from the stack pointer (for frameless functions, and
+ when we're still in the prologue of a function with a frame) */
+
+#define EXTRA_FRAME_INFO \
+ struct frame_saved_regs fsr; \
+ int framesize; \
+ int frameoffset; \
+ int framereg;
+
+extern void arm_init_extra_frame_info PARAMS ((struct frame_info *fi));
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) arm_init_extra_frame_info (fi)
+
+/* Return the frame address. On ARM, it is R11; on Thumb it is R7. */
+CORE_ADDR arm_target_read_fp PARAMS ((void));
+#define TARGET_READ_FP() arm_target_read_fp ()
+
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
@@ -230,16 +347,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller. */
-/* In the case of the ARM, the frame's nominal address is the FP value,
- and 12 bytes before comes the saved previous FP value as a 4-byte word. */
+#define FRAME_CHAIN(thisframe) (CORE_ADDR) arm_frame_chain (thisframe)
+extern CORE_ADDR arm_frame_chain PARAMS ((struct frame_info *));
-#define FRAME_CHAIN(thisframe) \
- ((thisframe)->pc >= first_object_file_end ? \
- read_memory_integer ((thisframe)->frame - 12, 4) :\
- 0)
+#define LOWEST_PC 0x20 /* the first 0x20 bytes are the trap vectors. */
#define FRAME_CHAIN_VALID(chain, thisframe) \
- (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
+ (chain != 0 && (FRAME_SAVED_PC (thisframe) >= LOWEST_PC))
/* Define other aspects of the stack frame. */
@@ -258,8 +372,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Saved Pc. */
-#define FRAME_SAVED_PC(FRAME) \
- (read_memory_integer ((FRAME)->frame - 4, 4) & 0x03fffffc)
+#define FRAME_SAVED_PC(FRAME) arm_frame_saved_pc (FRAME)
+extern CORE_ADDR arm_frame_saved_pc PARAMS ((struct frame_info *));
#define FRAME_ARGS_ADDRESS(fi) (fi->frame)
@@ -280,121 +394,102 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
+struct frame_saved_regs;
+struct frame_info;
+void frame_find_saved_regs PARAMS((struct frame_info *fi,
+ struct frame_saved_regs *fsr));
+
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
-{ \
- register int regnum; \
- register int frame; \
- register int next_addr; \
- register int return_data_save; \
- register int saved_register_mask; \
- bzero (&frame_saved_regs, sizeof frame_saved_regs); \
- frame = (frame_info)->frame; \
- return_data_save = read_memory_integer(frame, 4) & 0x03fffffc - 12; \
- saved_register_mask = \
- read_memory_integer(return_data_save, 4); \
- next_addr = frame - 12; \
- for (regnum = 4; regnum < 10; regnum++) \
- if (saved_register_mask & (1<<regnum)) { \
- next_addr -= 4; \
- (frame_saved_regs).regs[regnum] = next_addr; \
- } \
- if (read_memory_integer(return_data_save + 4, 4) == 0xed6d7103) { \
- next_addr -= 12; \
- (frame_saved_regs).regs[F0_REGNUM + 7] = next_addr; \
- } \
- if (read_memory_integer(return_data_save + 8, 4) == 0xed6d6103) { \
- next_addr -= 12; \
- (frame_saved_regs).regs[F0_REGNUM + 6] = next_addr; \
- } \
- if (read_memory_integer(return_data_save + 12, 4) == 0xed6d5103) { \
- next_addr -= 12; \
- (frame_saved_regs).regs[F0_REGNUM + 5] = next_addr; \
- } \
- if (read_memory_integer(return_data_save + 16, 4) == 0xed6d4103) { \
- next_addr -= 12; \
- (frame_saved_regs).regs[F0_REGNUM + 4] = next_addr; \
- } \
- (frame_saved_regs).regs[SP_REGNUM] = next_addr; \
- (frame_saved_regs).regs[PC_REGNUM] = frame - 4; \
- (frame_saved_regs).regs[PS_REGNUM] = frame - 4; \
- (frame_saved_regs).regs[FP_REGNUM] = frame - 12; \
-}
+ arm_frame_find_saved_regs (frame_info, &(frame_saved_regs));
+
/* Things needed for making the inferior call functions. */
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = arm_push_arguments ((nargs), (args), (sp), (struct_return), (struct_addr))
+extern CORE_ADDR
+arm_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_ADDR));
+
/* Push an empty stack frame, to record the current PC, etc. */
-#define PUSH_DUMMY_FRAME \
-{ \
- register CORE_ADDR sp = read_register (SP_REGNUM); \
- register int regnum; \
- /* opcode for ldmdb fp,{v1-v6,fp,ip,lr,pc}^ */ \
- sp = push_word(sp, 0xe92dbf0); /* dummy return_data_save ins */ \
- /* push a pointer to the dummy instruction minus 12 */ \
- sp = push_word(sp, read_register (SP_REGNUM) - 16); \
- sp = push_word(sp, read_register (PS_REGNUM)); \
- sp = push_word(sp, read_register (SP_REGNUM)); \
- sp = push_word(sp, read_register (FP_REGNUM)); \
- for (regnum = 9; regnum >= 4; regnum --) \
- sp = push_word(sp, read_register (regnum)); \
- write_register (FP_REGNUM, read_register (SP_REGNUM) - 8); \
- write_register (SP_REGNUM, sp); }
+void arm_push_dummy_frame PARAMS ((void));
+
+#define PUSH_DUMMY_FRAME arm_push_dummy_frame ()
/* Discard from the stack the innermost frame, restoring all registers. */
-#define POP_FRAME \
-{ \
- register CORE_ADDR fp = read_register (FP_REGNUM); \
- register unsigned long return_data_save = \
- read_memory_integer ( (read_memory_integer (fp, 4) & \
- 0x03fffffc) - 12, 4); \
- register int regnum; \
- write_register (PS_REGNUM, read_memory_integer (fp - 4, 4)); \
- write_register (PC_REGNUM, read_register (PS_REGNUM) & 0x03fffffc); \
- write_register (SP_REGNUM, read_memory_integer (fp - 8, 4)); \
- write_register (FP_REGNUM, read_memory_integer (fp - 12, 4)); \
- fp -= 12; \
- for (regnum = 9; regnum >= 4; regnum--) \
- if (return_data_save & (1<<regnum)) { \
- fp -= 4; \
- write_register (regnum, read_memory_integer(fp, 4)); \
- } \
- flush_cached_frames (); \
- set_current_frame (create_new_frame (read_register (FP_REGNUM), \
- read_pc ())); \
-}
+void arm_pop_frame PARAMS ((void));
+
+#define POP_FRAME arm_pop_frame ()
/* This sequence of words is the instructions
- ldmia sp!,{a1-a4}
- mov lk,pc
- bl *+8
+ mov lr,pc
+ mov pc,r4
swi bkpt_swi
- Note this is 16 bytes. */
+ Note this is 12 bytes. */
-#define CALL_DUMMY {0xe8bd000f, 0xe1a0e00f, 0xeb000000, 0xef180000}
+#define CALL_DUMMY {0xe1a0e00f, 0xe1a0f004, 0xef180000}
#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+#define CALL_DUMMY_BREAKPOINT_OFFSET arm_call_dummy_breakpoint_offset()
+extern int arm_call_dummy_breakpoint_offset PARAMS ((void));
+
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
-{ \
- register enum type_code code = TYPE_CODE (type); \
- register nargs_in_registers, struct_return = 0; \
- /* fix the load-arguments mask to move the first 4 or less arguments \
- into a1-a4 but make sure the structure return address in a1 is \
- not disturbed if the function is returning a structure */ \
- if ((code == TYPE_CODE_STRUCT || \
- code == TYPE_CODE_UNION || \
- code == TYPE_CODE_ARRAY) && \
- TYPE_LENGTH (type) > 4) { \
- nargs_in_registers = min(nargs + 1, 4); \
- struct_return = 1; \
- } else \
- nargs_in_registers = min(nargs, 4); \
- *(char *) dummyname = (1 << nargs_in_registers) - 1 - struct_return; \
- *(int *)((char *) dummyname + 8) = \
- (((fun - (pc + 16)) / 4) & 0x00ffffff) | 0xeb000000; }
+ arm_fix_call_dummy (dummyname, pc, fun, nargs, args, type, gcc_p)
+
+void arm_fix_call_dummy PARAMS ((char *dummy, CORE_ADDR pc, CORE_ADDR fun,
+ int nargs, struct value **args,
+ struct type *type, int gcc_p));
+
+CORE_ADDR arm_get_next_pc PARAMS ((CORE_ADDR));
+
+/* Functions for dealing with Thumb call thunks. */
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) arm_in_call_stub (pc, name)
+#define SKIP_TRAMPOLINE_CODE(pc) arm_skip_stub (pc)
+extern int arm_in_call_stub PARAMS ((CORE_ADDR pc, char *name));
+extern CORE_ADDR arm_skip_stub PARAMS ((CORE_ADDR pc));
+
+/* Function to determine whether MEMADDR is in a Thumb function. */
+extern int arm_pc_is_thumb PARAMS ((bfd_vma memaddr));
+
+/* Function to determine whether MEMADDR is in a call dummy called from
+ a Thumb function. */
+extern int arm_pc_is_thumb_dummy PARAMS ((bfd_vma memaddr));
+
+/* Macros for setting and testing a bit in a minimal symbol that
+ marks it as Thumb function. The MSB of the minimal symbol's
+ "info" field is used for this purpose. This field is already
+ being used to store the symbol size, so the assumption is
+ that the symbol size cannot exceed 2^31.
+
+ COFF_MAKE_MSYMBOL_SPECIAL
+ ELF_MAKE_MSYMBOL_SPECIAL tests whether the COFF or ELF symbol corresponds
+ to a thumb function, and sets a "special" bit in a
+ minimal symbol to indicate that it does
+ MSYMBOL_SET_SPECIAL actually sets the "special" bit
+ MSYMBOL_IS_SPECIAL tests the "special" bit in a minimal symbol
+ MSYMBOL_SIZE returns the size of the minimal symbol, i.e.
+ the "info" field with the "special" bit masked out
+*/
+
+extern int coff_sym_is_thumb(int val);
+#define MSYMBOL_SET_SPECIAL(msym) \
+ MSYMBOL_INFO (msym) = (char *) (((long) MSYMBOL_INFO (msym)) | 0x80000000)
+#define MSYMBOL_IS_SPECIAL(msym) \
+ (((long) MSYMBOL_INFO (msym) & 0x80000000) != 0)
+#define MSYMBOL_SIZE(msym) \
+ ((long) MSYMBOL_INFO (msym) & 0x7fffffff)
+
+/* Thumb symbol are of type STT_LOPROC, (synonymous with STT_ARM_TFUNC) */
+#define ELF_MAKE_MSYMBOL_SPECIAL(sym,msym) \
+ { if(ELF_ST_TYPE(((elf_symbol_type *)(sym))->internal_elf_sym.st_info) == STT_LOPROC) \
+ MSYMBOL_SET_SPECIAL(msym); }
+
+#define COFF_MAKE_MSYMBOL_SPECIAL(val,msym) \
+ { if(coff_sym_is_thumb(val)) MSYMBOL_SET_SPECIAL(msym); }
diff --git a/gdb/config/d10v/tm-d10v.h b/gdb/config/d10v/tm-d10v.h
index 967ffcf..2062a68 100644
--- a/gdb/config/d10v/tm-d10v.h
+++ b/gdb/config/d10v/tm-d10v.h
@@ -186,8 +186,8 @@ extern CORE_ADDR d10v_skip_prologue ();
The d10v returns anything less than 8 bytes in size in
registers. */
-#define USE_STRUCT_CONVENTION(gcc_p, type) \
- (TYPE_LENGTH (type) > 8)
+extern use_struct_convention_fn d10v_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) d10v_use_struct_convention (gcc_p, type)
diff --git a/gdb/config/i960/tm-i960.h b/gdb/config/i960/tm-i960.h
index 57d7b98..39707b9 100644
--- a/gdb/config/i960/tm-i960.h
+++ b/gdb/config/i960/tm-i960.h
@@ -210,7 +210,8 @@ extern CORE_ADDR saved_pc_after_call ();
On i960, a structure is returned in registers g0-g3, if it will fit.
If it's more than 16 bytes long, g13 pointed to it on entry. */
-#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 16)
+extern use_struct_convention_fn i960_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) i960_use_struct_convention (gcc_p, type)
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
diff --git a/gdb/config/m32r/tm-m32r.h b/gdb/config/m32r/tm-m32r.h
index b6151e1..231a4ad 100644
--- a/gdb/config/m32r/tm-m32r.h
+++ b/gdb/config/m32r/tm-m32r.h
@@ -180,8 +180,8 @@ extern CORE_ADDR m32r_skip_prologue PARAMS ((CORE_ADDR pc));
#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP) \
write_register (0, STRUCT_ADDR)
-#define USE_STRUCT_CONVENTION(GCC_P, TYPE) \
- (TYPE_LENGTH (TYPE) > 8)
+extern use_struct_convention_fn m32r_use_struct_convention;
+#define USE_STRUCT_CONVENTION(GCC_P, TYPE) m32r_use_struct_convention (GCC_P, TYPE)
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
extract_address (REGBUF + REGISTER_BYTE (V0_REGNUM), \
diff --git a/gdb/config/mips/tm-mips.h b/gdb/config/mips/tm-mips.h
index cfd8fe3..960e315 100644
--- a/gdb/config/mips/tm-mips.h
+++ b/gdb/config/mips/tm-mips.h
@@ -350,14 +350,8 @@ extern void mips_store_return_value PARAMS ((struct type *, char *));
(extract_address (REGBUF + REGISTER_BYTE (V0_REGNUM), \
REGISTER_RAW_SIZE (V0_REGNUM)))
-#if MIPS_EABI
-#undef USE_STRUCT_CONVENTION
-#define USE_STRUCT_CONVENTION(gcc_p, type) \
- (TYPE_LENGTH (type) > 2 * MIPS_REGSIZE)
-#else
-/* Structures are returned by ref in extra arg0 */
-#define USE_STRUCT_CONVENTION(gcc_p, type) 1
-#endif
+extern use_struct_convention_fn mips_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) mips_use_struct_convention (gcc_p, type)
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
diff --git a/gdb/config/mn10200/tm-mn10200.h b/gdb/config/mn10200/tm-mn10200.h
index 94ab1c0..e4c71fd 100644
--- a/gdb/config/mn10200/tm-mn10200.h
+++ b/gdb/config/mn10200/tm-mn10200.h
@@ -201,8 +201,8 @@ mn10200_push_arguments PARAMS ((int, struct value **, CORE_ADDR,
#define REG_STRUCT_HAS_ADDR(gcc_p,TYPE) \
(TYPE_LENGTH (TYPE) > 8)
-#define USE_STRUCT_CONVENTION(GCC_P, TYPE) \
- (TYPE_NFIELDS (TYPE) > 1 || TYPE_LENGTH (TYPE) > 8)
+extern use_struct_convention_fn mn10200_use_struct_convention;
+#define USE_STRUCT_CONVENTION(GCC_P, TYPE) mn10200_use_struct_convention (GCC_P, TYPE)
/* Override the default get_saved_register function with
one that takes account of generic CALL_DUMMY frames. */
diff --git a/gdb/config/mn10300/tm-mn10300.h b/gdb/config/mn10300/tm-mn10300.h
index 242fdc1..cce0470 100644
--- a/gdb/config/mn10300/tm-mn10300.h
+++ b/gdb/config/mn10300/tm-mn10300.h
@@ -162,8 +162,8 @@ mn10300_push_arguments PARAMS ((int, struct value **, CORE_ADDR,
#define REG_STRUCT_HAS_ADDR(gcc_p,TYPE) \
(TYPE_LENGTH (TYPE) > 8)
-#define USE_STRUCT_CONVENTION(GCC_P, TYPE) \
- (TYPE_NFIELDS (TYPE) > 1 || TYPE_LENGTH (TYPE) > 8)
+extern use_struct_convention_fn mn10300_use_struct_convention;
+#define USE_STRUCT_CONVENTION(GCC_P, TYPE) mn10300_use_struct_convention (GCC_P, TYPE)
/* override the default get_saved_register function with
one that takes account of generic CALL_DUMMY frames */
diff --git a/gdb/config/sh/tm-sh.h b/gdb/config/sh/tm-sh.h
index 0ec375c..82108f3 100644
--- a/gdb/config/sh/tm-sh.h
+++ b/gdb/config/sh/tm-sh.h
@@ -167,7 +167,8 @@ extern CORE_ADDR sh_skip_prologue ();
#define STORE_STRUCT_RETURN(ADDR, SP) \
{ write_register (STRUCT_RETURN_REGNUM, (ADDR)); }
-#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH(type) > 1)
+extern use_struct_convention_fn sh_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) sh_use_struct_convention (gcc_p, type)
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
diff --git a/gdb/config/v850/tm-v850.h b/gdb/config/v850/tm-v850.h
index a53952e..e57b5fe 100644
--- a/gdb/config/v850/tm-v850.h
+++ b/gdb/config/v850/tm-v850.h
@@ -153,8 +153,8 @@ v850_push_arguments PARAMS ((int nargs, struct value **args, CORE_ADDR sp,
#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP)
-#define USE_STRUCT_CONVENTION(GCC_P, TYPE) \
- (TYPE_NFIELDS (TYPE) > 1 || TYPE_LENGTH (TYPE) > 4)
+extern use_struct_convention_fn v850_use_struct_convention;
+#define USE_STRUCT_CONVENTION(GCC_P, TYPE) v850_use_struct_convention (GCC_P, TYPE);
/* override the default get_saved_register function with
one that takes account of generic CALL_DUMMY frames */
diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c
index 10d249b..d0f2e80 100644
--- a/gdb/d10v-tdep.c
+++ b/gdb/d10v-tdep.c
@@ -36,6 +36,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
void d10v_frame_find_saved_regs PARAMS ((struct frame_info *fi,
struct frame_saved_regs *fsr));
+/* 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. */
+
+int
+d10v_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 8);
+}
+
+
/* Discard from the stack the innermost frame, restoring all saved
registers. */
diff --git a/gdb/defs.h b/gdb/defs.h
index c5acb2f..5f7c8c7 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -285,6 +285,11 @@ extern void mfree PARAMS ((PTR, PTR));
extern void set_demangling_style PARAMS ((char *));
+/* From tm.h */
+struct type;
+typedef int (use_struct_convention_fn) PARAMS ((int gcc_p, struct type *value_type));
+extern use_struct_convention_fn generic_use_struct_convention;
+
/* Annotation stuff. */
diff --git a/gdb/gould-tdep.c b/gdb/gould-tdep.c
index 79575e0..736ab47 100644
--- a/gdb/gould-tdep.c
+++ b/gdb/gould-tdep.c
@@ -33,6 +33,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Number of elements in the opcode table. */
#define NOPCODES (sizeof gld_opcodes / sizeof gld_opcodes[0])
+/* Both gcc and cc return small structs in registers (i.e. in GDB
+ terminology, small structs don't use the struct return convention). */
+int
+gould_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH(type) > 8);
+}
+
+
/* Print the GOULD instruction at address MEMADDR in debugged memory,
on STREAM. Returns length of the instruction, in bytes. */
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
index 0ecbc85..ff0318a 100644
--- a/gdb/hppa-tdep.c
+++ b/gdb/hppa-tdep.c
@@ -110,6 +110,16 @@ static void internalize_unwinds PARAMS ((struct objfile *,
static void pa_print_registers PARAMS ((char *, int, int));
static void pa_print_fp_reg PARAMS ((int));
+
+/* Should call_function allocate stack space for a struct return? */
+int
+hppa_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 8);
+}
+
/* Routines to extract various sized constants out of hppa
instructions. */
diff --git a/gdb/i960-tdep.c b/gdb/i960-tdep.c
index a125ec2..c2625c0 100644
--- a/gdb/i960-tdep.c
+++ b/gdb/i960-tdep.c
@@ -31,6 +31,28 @@ static CORE_ADDR next_insn PARAMS ((CORE_ADDR memaddr,
unsigned int *pword1,
unsigned int *pword2));
+/* Does the specified function use the "struct returning" convention
+ or the "value returning" convention? The "value returning" convention
+ almost invariably returns the entire value in registers. The
+ "struct returning" convention often returns the entire value in
+ memory, and passes a pointer (out of or into the function) saying
+ where the value (is or should go).
+
+ Since this sometimes depends on whether it was compiled with GCC,
+ this is also an argument. This is used in call_function to build a
+ stack, and in value_being_returned to print return values.
+
+ On i960, a structure is returned in registers g0-g3, if it will fit.
+ If it's more than 16 bytes long, g13 pointed to it on entry. */
+
+int
+i960_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 16);
+}
+
/* gdb960 is always running on a non-960 host. Check its characteristics.
This routine must be called as part of gdb initialization. */
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index ec0fa96..3a916ba 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -211,6 +211,21 @@ struct linked_proc_info
} *linked_proc_desc_table = NULL;
+/* Should the upper word of 64-bit addresses be zeroed? */
+static int mask_address_p = 1;
+
+/* Should call_function allocate stack space for a struct return? */
+int
+mips_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ if (MIPS_EABI)
+ return (TYPE_LENGTH (type) > 2 * MIPS_REGSIZE);
+ else
+ return 1; /* Structures are returned by ref in extra arg0 */
+}
+
/* Tell if the program counter value in MEMADDR is in a MIPS16 function. */
static int
@@ -1009,10 +1024,7 @@ mips_addr_bits_remove (addr)
CORE_ADDR addr;
{
#if GDB_TARGET_IS_MIPS64
- if ((addr >> 32 == (CORE_ADDR)0xffffffff)
- && (strcmp (target_shortname,"pmon")==0
- || strcmp (target_shortname,"ddb")==0
- || strcmp (target_shortname,"sim")==0))
+ if (mask_address_p && (addr >> 32 == (CORE_ADDR)0xffffffff))
{
/* This hack is a work-around for existing boards using PMON,
the simulator, and any other 64-bit targets that doesn't have
@@ -1766,9 +1778,11 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
#define ROUND_UP(n,a) (((n)+(a)-1) & ~((a)-1))
/* First ensure that the stack and structure return address (if any)
- are properly aligned. The stack has to be 64-bit aligned even
- on 32-bit machines, because doubles must be 64-bit aligned. */
- sp = ROUND_DOWN (sp, 8);
+ are properly aligned. The stack has to be at least 64-bit aligned
+ even on 32-bit machines, because doubles must be 64-bit aligned.
+ On at least one MIPS variant, stack frames need to be 128-bit
+ aligned, so we round to this widest known alignment. */
+ sp = ROUND_DOWN (sp, 16);
struct_addr = ROUND_DOWN (struct_addr, MIPS_REGSIZE);
/* Now make space on the stack for the args. We allocate more
@@ -1776,7 +1790,7 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
passed in registers, but that's OK. */
for (argnum = 0; argnum < nargs; argnum++)
len += ROUND_UP (TYPE_LENGTH(VALUE_TYPE(args[argnum])), MIPS_REGSIZE);
- sp -= ROUND_UP (len, 8);
+ sp -= ROUND_UP (len, 16);
/* Initialize the integer and float register pointers. */
argreg = A0_REGNUM;
@@ -2253,8 +2267,8 @@ do_gp_register_row (regnum)
int numregs = NUM_REGS;
/* start-sanitize-sky */
-#ifdef NUM_R5900_REGS
- numregs = NUM_R5900_REGS;
+#ifdef NUM_CORE_REGS
+ numregs = NUM_CORE_REGS;
#endif
/* end-sanitize-sky */
@@ -2331,10 +2345,10 @@ mips_do_registers_info (regnum, fpregs)
else
regnum = do_gp_register_row (regnum); /* GP (int) regs */
/* start-sanitize-sky */
-#ifdef NUM_R5900_REGS
+#ifdef NUM_CORE_REGS
/* For the sky project, NUM_REGS includes the vector slaves,
which are handled elsewhere */
- if (regnum >= NUM_R5900_REGS)
+ if (regnum >= NUM_CORE_REGS)
break;
#endif
/* end-sanitize-sky */
@@ -3151,6 +3165,24 @@ mips_ignore_helper (pc)
}
+/* Return a location where we can set a breakpoint that will be hit
+ when an inferior function call returns. This is normally the
+ program's entry point. Executables that don't have an entry
+ point (e.g. programs in ROM) should define a symbol __CALL_DUMMY_ADDRESS
+ whose address is the location where the breakpoint should be placed. */
+
+CORE_ADDR
+mips_call_dummy_address ()
+{
+ struct minimal_symbol *sym;
+
+ sym = lookup_minimal_symbol ("__CALL_DUMMY_ADDRESS", NULL, NULL);
+ if (sym)
+ return SYMBOL_VALUE_ADDRESS (sym);
+ else
+ return entry_point_address ();
+}
+
void
_initialize_mips_tdep ()
{
@@ -3215,4 +3247,13 @@ search. The only need to set it is when debugging a stripped executable.",
might change our ability to get backtraces. */
c->function.sfunc = reinit_frame_cache_sfunc;
add_show_from_set (c, &showlist);
+
+ /* Allow the user to control whether the upper bits of 64-bit
+ addresses should be zeroed. */
+ add_show_from_set
+ (add_set_cmd ("mask-address", no_class, var_boolean, (char *)&mask_address_p,
+ "Set zeroing of upper 32 bits of 64-bit addresses.\n\
+Use \"on\" to enable the masking, and \"off\" to disable it.\n\
+Without an argument, zeroing of upper address bits is enabled.", &setlist),
+ &showlist);
}
diff --git a/gdb/mn10200-tdep.c b/gdb/mn10200-tdep.c
index 757f2ba..cb7ead0 100644
--- a/gdb/mn10200-tdep.c
+++ b/gdb/mn10200-tdep.c
@@ -28,6 +28,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "gdbcore.h"
#include "symfile.h"
+
+/* Should call_function allocate stack space for a struct return? */
+int
+mn10200_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_NFIELDS (type) > 1 || TYPE_LENGTH (type) > 8);
+}
+
+
+
/* The main purpose of this file is dealing with prologues to extract
information about stack frames and saved registers.
diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c
index 770b0f0..1513319 100644
--- a/gdb/mn10300-tdep.c
+++ b/gdb/mn10300-tdep.c
@@ -49,6 +49,16 @@ static CORE_ADDR mn10300_analyze_prologue PARAMS ((struct frame_info *fi,
#define NO_MORE_FRAMES 0x4
+/* Should call_function allocate stack space for a struct return? */
+int
+mn10300_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_NFIELDS (type) > 1 || TYPE_LENGTH (type) > 8);
+}
+
+
/* Fix fi->frame if it's bogus at this point. This is a helper
function for mn10300_analyze_prologue. */
@@ -187,7 +197,8 @@ mn10300_analyze_prologue (fi, pc)
/* If we're in start, then give up. */
if (strcmp (name, "start") == 0)
{
- fi->status = NO_MORE_FRAMES;
+ if (fi != NULL)
+ fi->status = NO_MORE_FRAMES;
return pc;
}
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index 993f71e..e524509 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -105,6 +105,17 @@ struct {
#define IS_FMOV(x) (((x) & 0xf00f) == 0xf00b)
#define FPSCR_SZ (1 << 20)
+
+/* Should call_function allocate stack space for a struct return? */
+int
+sh_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 1);
+}
+
+
/* Skip any prologue before the guts of a function */
CORE_ADDR
diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c
index d6da5f3..0824724 100644
--- a/gdb/v850-tdep.c
+++ b/gdb/v850-tdep.c
@@ -48,6 +48,17 @@ struct prologue_info
static CORE_ADDR v850_scan_prologue PARAMS ((CORE_ADDR pc,
struct prologue_info *fs));
+
+
+/* Should call_function allocate stack space for a struct return? */
+int
+v850_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_NFIELDS (type) > 1 || TYPE_LENGTH (type) > 4);
+}
+
/* Function: scan_prologue
Scan the prologue of the function that contains PC, and record what
diff --git a/gdb/values.c b/gdb/values.c
index efa6f40..db6f204 100644
--- a/gdb/values.c
+++ b/gdb/values.c
@@ -1381,14 +1381,21 @@ value_being_returned (valtype, retbuf, struct_return)
2.0-2.3.3. This is somewhat unfortunate, but changing gcc2_compiled
would cause more chaos than dealing with some struct returns being
handled wrong. */
-#if !defined (USE_STRUCT_CONVENTION)
-#define USE_STRUCT_CONVENTION(gcc_p, type)\
- (!((gcc_p == 1) && (TYPE_LENGTH (value_type) == 1 \
- || TYPE_LENGTH (value_type) == 2 \
- || TYPE_LENGTH (value_type) == 4 \
- || TYPE_LENGTH (value_type) == 8 \
- ) \
- ))
+
+int
+generic_use_struct_convention (gcc_p, value_type)
+ int gcc_p;
+ struct type *value_type;
+{
+ return !((gcc_p == 1)
+ && (TYPE_LENGTH (value_type) == 1
+ || TYPE_LENGTH (value_type) == 2
+ || TYPE_LENGTH (value_type) == 4
+ || TYPE_LENGTH (value_type) == 8));
+}
+
+#ifndef USE_STRUCT_CONVENTION
+#define USE_STRUCT_CONVENTION(gcc_p,type) generic_use_struct_convention (gcc_p, type)
#endif
/* Some fundamental types (such as long double) are returned on the stack for