]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/config/sparc/tm-sparc.h
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / gdb / config / sparc / tm-sparc.h
index 70f1f20c4ab7fd7f801197dd6b2af81f24b7d43f..ecbe9e2285d97fc6d9590f1bc802227106aae7d1 100644 (file)
@@ -1,6 +1,7 @@
 /* Target machine sub-parameters for SPARC, for GDB, the GNU debugger.
    This is included by other tm-*.h files to define SPARC cpu-related info.
-   Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994
+   Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@mcc.com)
 
 This file is part of GDB.
@@ -17,35 +18,39 @@ 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.  */
+
+#ifdef __STDC__
+struct frame_info;
+struct type;
+struct value;
+#endif
 
 #define TARGET_BYTE_ORDER BIG_ENDIAN
 
 /* Floating point is IEEE compatible.  */
 #define IEEE_FLOAT
 
+/* If an argument is declared "register", Sun cc will keep it in a register,
+   never saving it onto the stack.  So we better not believe the "p" symbol
+   descriptor stab.  */
+
+#define USE_REGISTER_NOT_ARG
+
 /* When passing a structure to a function, Sun cc passes the address
    not the structure itself.  It (under SunOS4) creates two symbols,
    which we need to combine to a LOC_REGPARM.  Gcc version two (as of
    1.92) behaves like sun cc.  REG_STRUCT_HAS_ADDR is smart enough to
-   distinguish between Sun cc, gcc version 1 and gcc version 2.
+   distinguish between Sun cc, gcc version 1 and gcc version 2.  */
 
-   This still doesn't work if the argument is not one passed in a
-   register (i.e. it's the 7th or later argument).  */
-#define REG_STRUCT_HAS_ADDR(gcc_p) (gcc_p != 1)
+#define REG_STRUCT_HAS_ADDR(gcc_p,type) (gcc_p != 1)
 
-/* If Pcc says that a parameter is a short, it's a short.  This is
-   because the parameter does get passed in in a register as an int,
-   but pcc puts it onto the stack frame as a short (not nailing
-   whatever else might be there.  I'm not sure that I consider this
-   swift.  Sigh.)
+/* Sun /bin/cc gets this right as of SunOS 4.1.x.  We need to define
+   BELIEVE_PCC_PROMOTION to get this right now that the code which
+   detects gcc2_compiled. is broken.  This loses for SunOS 4.0.x and
+   earlier.  */
 
-   No, don't do this.  The problem here is that pcc says that the
-   argument is in the upper half of the word reserved on the stack,
-   but puts it in the lower half.  */
-/* #define BELIEVE_PCC_PROMOTION 1 */
-/* OK, I've added code to dbxread.c to deal with this case.  */
-#define BELIEVE_PCC_PROMOTION_TYPE
+#define BELIEVE_PCC_PROMOTION 1
 
 /* For acc, there's no need to correct LBRAC entries by guessing how
    they should work.  In fact, this is harmful because the LBRAC
@@ -87,7 +92,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
   { pc = skip_prologue (pc, 0); }
 #define SKIP_PROLOGUE_FRAMELESS_P(pc) \
   { pc = skip_prologue (pc, 1); }
-extern CORE_ADDR skip_prologue ();
+extern CORE_ADDR skip_prologue PARAMS ((CORE_ADDR, int));
 
 /* Immediately after a function call, return the saved pc.
    Can't go through the frames for this because on some machines
@@ -99,19 +104,20 @@ extern CORE_ADDR skip_prologue ();
    a fake insn, step past it.  */
 
 #define PC_ADJUST(pc) sparc_pc_adjust(pc)
-extern CORE_ADDR sparc_pc_adjust();
+extern CORE_ADDR sparc_pc_adjust PARAMS ((CORE_ADDR));
 
 #define SAVED_PC_AFTER_CALL(frame) PC_ADJUST (read_register (RP_REGNUM))
 
 /* Stack grows downward.  */
 
-#define INNER_THAN <
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
 
-/* Stack has strict alignment.  */
+/* Stack must be aligned on 64-bit boundaries when synthesizing
+   function calls. */
 
-#define STACK_ALIGN(ADDR) (((ADDR)+7)&-8)
+#define STACK_ALIGN(ADDR) (((ADDR) + 7) & -8)
 
-/* Sequence of bytes for breakpoint instruction */
+/* Sequence of bytes for breakpoint instruction (ta 1). */
 
 #define BREAKPOINT {0x91, 0xd0, 0x20, 0x01}
 
@@ -121,20 +127,11 @@ extern CORE_ADDR sparc_pc_adjust();
 
 #define DECR_PC_AFTER_BREAK 0
 
-/* Nonzero if instruction at PC is a return instruction.  */
-/* For SPARC, this is either a "jmpl %o7+8,%g0" or "jmpl %i7+8,%g0".
-
-   Note: this does not work for functions returning structures under SunOS.  */
-#define ABOUT_TO_RETURN(pc) \
-  ((read_memory_integer (pc, 4)|0x00040000) == 0x81c7e008)
-
-/* Return 1 if P points to an invalid floating point value.  */
-
-#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
-
-/* 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 */
 
@@ -179,6 +176,7 @@ extern CORE_ADDR sparc_pc_adjust();
 #define        FP0_REGNUM 32           /* Floating point register 0 */
 #define        Y_REGNUM 64             /* Temp register for multiplication, etc.  */
 #define        PS_REGNUM 65            /* Contains processor status */
+#define PS_FLAG_CARRY 0x100000 /* Carry bit in PS */
 #define        WIM_REGNUM 66           /* Window Invalid Mask (not really supported) */
 #define        TBR_REGNUM 67           /* Trap Base Register (not really supported) */
 #define        PC_REGNUM 68            /* Contains program counter */
@@ -190,11 +188,12 @@ extern CORE_ADDR sparc_pc_adjust();
    register state, the array `registers'.  On the sparc, `registers'
    contains the ins and locals, even though they are saved on the
    stack rather than with the other registers, and this causes hair
-   and confusion in places like pop_frame.  It probably would be
+   and confusion in places like pop_frame.  It might be
    better to remove the ins and locals from `registers', make sure
    that get_saved_register can get them from the stack (even in the
    innermost frame), and make this the way to access them.  For the
-   frame pointer we would do that via TARGET_READ_FP.  */
+   frame pointer we would do that via TARGET_READ_FP.  On the other hand,
+   that is likely to be confusing or worse for flat frames.  */
 
 #define REGISTER_BYTES (32*4+32*4+8*4)
 
@@ -203,18 +202,11 @@ extern CORE_ADDR sparc_pc_adjust();
 /* ?? */
 #define REGISTER_BYTE(N)  ((N)*4)
 
-/* The SPARC processor has register windows.  */
+/* We need to override GET_SAVED_REGISTER so that we can deal with the way
+   outs change into ins in different frames.  HAVE_REGISTER_WINDOWS can't
+   deal with this case and also handle flat frames at the same time.  */
 
-#define HAVE_REGISTER_WINDOWS
-
-/* Is this register part of the register window system?  A yes answer
-   implies that 1) The name of this register will not be the same in
-   other frames, and 2) This register is automatically "saved" (out
-   registers shifting into ins counts) upon subroutine calls and thus
-   there is no need to search more than one stack frame for it. */
-
-#define REGISTER_IN_WINDOW_P(regnum)   \
-  ((regnum) >= 8 && (regnum) < 32)
+#define GET_SAVED_REGISTER 1
 
 /* Number of bytes of storage in the actual machine representation
    for register N.  */
@@ -238,23 +230,6 @@ extern CORE_ADDR sparc_pc_adjust();
 
 #define MAX_REGISTER_VIRTUAL_SIZE 8
 
-/* Nonzero if register N requires conversion
-   from raw format to virtual format.  */
-
-#define REGISTER_CONVERTIBLE(N) (0)
-
-/* Convert data from raw format for register REGNUM
-   to virtual format for register REGNUM.  */
-
-#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
-{ memcpy ((TO), (FROM), REGISTER_RAW_SIZE (REGNUM)); }
-
-/* Convert data from virtual format for register REGNUM
-   to raw format for register REGNUM.  */
-
-#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
-{ memcpy ((TO), (FROM), REGISTER_RAW_SIZE (REGNUM)); }
-
 /* Return the GDB type object for the "standard" data type
    of data in register N.  */
 
@@ -268,43 +243,28 @@ extern CORE_ADDR sparc_pc_adjust();
 #define CANNOT_STORE_REGISTER(regno) ((regno) == G0_REGNUM)
 
 /* Store the address of the place in which to copy the structure the
-   subroutine will return.  This is called from call_function. */
+   subroutine will return.  This is called from call_function_by_hand. 
+   The ultimate mystery is, tho, what is the value "16"?  */
 
 #define STORE_STRUCT_RETURN(ADDR, SP) \
-  { target_write_memory ((SP)+(16*4), (char *)&(ADDR), 4); }
+  { char val[4]; \
+    store_unsigned_integer (val, 4, (ADDR)); \
+    write_memory ((SP)+(16*4), val, 4); }
 
 /* Extract from an array REGBUF containing the (raw) register state
    a function return value of type TYPE, and copy that, in virtual format,
    into VALBUF.  */
 
-#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF)             \
-  {                                                                       \
-    if (TYPE_CODE (TYPE) == TYPE_CODE_FLT)                                \
-      {                                                                           \
-       memcpy ((VALBUF), ((int *)(REGBUF))+FP0_REGNUM, TYPE_LENGTH(TYPE));\
-      }                                                                           \
-    else                                                                  \
-      memcpy ((VALBUF),                                                           \
-             (char *)(REGBUF) + 4 * 8 +                                   \
-             (TYPE_LENGTH(TYPE) >= 4 ? 0 : 4 - TYPE_LENGTH(TYPE)),        \
-             TYPE_LENGTH(TYPE));                                          \
-  }
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  sparc_extract_return_value(TYPE, REGBUF, VALBUF)
+extern void
+sparc_extract_return_value PARAMS ((struct type *, char [], char *));
 
 /* Write into appropriate registers a function return value
    of type TYPE, given in virtual format.  */
-/* On sparc, values are returned in register %o0.  */
 #define STORE_RETURN_VALUE(TYPE,VALBUF) \
-  {                                                                                 \
-    if (TYPE_CODE (TYPE) == TYPE_CODE_FLT)                                  \
-      /* Floating-point values are returned in the register pair */          \
-      /* formed by %f0 and %f1 (doubles are, anyway).  */                    \
-      write_register_bytes (REGISTER_BYTE (FP0_REGNUM), (VALBUF),           \
-                           TYPE_LENGTH (TYPE));                             \
-    else                                                                    \
-      /* Other values are returned in register %o0.  */                      \
-      write_register_bytes (REGISTER_BYTE (O0_REGNUM), (VALBUF),            \
-                           TYPE_LENGTH (TYPE));  \
-  }
+  sparc_store_return_value(TYPE, VALBUF)
+extern void sparc_store_return_value PARAMS ((struct type *, char *));
 
 /* Extract from an array REGBUF containing the (raw) register state
    the address in which a function should return its structure value,
@@ -346,18 +306,52 @@ sparc_extract_struct_value_address PARAMS ((char [REGISTER_BYTES]));
    The bottom field is misnamed, since it might imply that memory from
    bottom to frame contains this frame.  That need not be true if
    stack frames are allocated in different segments (e.g. some on a
-   stack, some on a heap in the data segment).  */
-
-#define EXTRA_FRAME_INFO       FRAME_ADDR bottom;
-#define INIT_EXTRA_FRAME_INFO(fromleaf, fci)  \
-  (fci)->bottom =                                      \
-   ((fci)->next ?                                      \
-    ((fci)->frame == (fci)->next->frame ?              \
-     (fci)->next->bottom : (fci)->next->frame) :       \
-    read_register (SP_REGNUM));
+   stack, some on a heap in the data segment).
+
+   GCC 2.6 and later can generate ``flat register window'' code that
+   makes frames by explicitly saving those registers that need to be
+   saved.  %i7 is used as the frame pointer, and the frame is laid out so
+   that flat and non-flat calls can be intermixed freely within a
+   program.  Unfortunately for GDB, this means it must detect and record
+   the flatness of frames.
+
+   Since the prologue in a flat frame also tells us where fp and pc
+   have been stashed (the frame is of variable size, so their location
+   is not fixed), it's convenient to record them in the frame info.  */
+
+#define EXTRA_FRAME_INFO  \
+  CORE_ADDR bottom;  \
+  int in_prologue; \
+  int flat;  \
+  /* Following fields only relevant for flat frames.  */ \
+  CORE_ADDR pc_addr;  \
+  CORE_ADDR fp_addr;  \
+  /* Add this to ->frame to get the value of the stack pointer at the */ \
+  /* time of the register saves.  */ \
+  int sp_offset;
+
+#define FRAME_INIT_SAVED_REGS(fp) /*no-op*/
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) \
+  sparc_init_extra_frame_info (fromleaf, fci)
+extern void sparc_init_extra_frame_info PARAMS((int, struct frame_info *));
+
+#define        PRINT_EXTRA_FRAME_INFO(fi) \
+  { \
+    if ((fi) && (fi)->flat) \
+      printf_filtered (" flat, pc saved at 0x%x, fp saved at 0x%x\n", \
+                       (fi)->pc_addr, (fi)->fp_addr); \
+  }
 
 #define FRAME_CHAIN(thisframe) (sparc_frame_chain (thisframe))
-CORE_ADDR sparc_frame_chain ();
+extern CORE_ADDR sparc_frame_chain PARAMS ((struct frame_info *));
+
+/* INIT_EXTRA_FRAME_INFO needs the PC to detect flat frames.  */
+
+#define        INIT_FRAME_PC(fromleaf, prev) /* nothing */
+#define INIT_FRAME_PC_FIRST(fromleaf, prev) \
+  (prev)->pc = ((fromleaf) ? SAVED_PC_AFTER_CALL ((prev)->next) : \
+             (prev)->next ? FRAME_SAVED_PC ((prev)->next) : read_pc ());
 
 /* Define other aspects of the stack frame.  */
 
@@ -367,10 +361,18 @@ CORE_ADDR sparc_frame_chain ();
 #define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
   (FRAMELESS) = frameless_look_for_prologue(FI)
 
+/* The location of I0 w.r.t SP.  This is actually dependent on how the system's
+   window overflow/underflow routines are written.  Most vendors save the L regs
+   followed by the I regs (at the higher address).  Some vendors get it wrong.
+ */
+
+#define        FRAME_SAVED_L0  0
+#define        FRAME_SAVED_I0  (8 * REGISTER_RAW_SIZE (L0_REGNUM))
+
 /* Where is the PC for a specific frame */
 
-#define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME)
-CORE_ADDR frame_saved_pc ();
+#define FRAME_SAVED_PC(FRAME) sparc_frame_saved_pc (FRAME)
+extern CORE_ADDR sparc_frame_saved_pc PARAMS ((struct frame_info *));
 
 /* If the argument is on the stack, it will be here.  */
 #define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
@@ -389,14 +391,6 @@ CORE_ADDR frame_saved_pc ();
 /* Return number of bytes at start of arglist that are not really args.  */
 
 #define FRAME_ARGS_SKIP 68
-
-/* Put here the code to store, into a struct frame_saved_regs,
-   the addresses of the saved registers of frame described by FRAME_INFO.
-   The actual code is in sparc-tdep.c so we can debug it sanely.  */
-
-#define FRAME_FIND_SAVED_REGS(fi, frame_saved_regs)                \
-       sparc_frame_find_saved_regs ((fi), &(frame_saved_regs))
-extern void sparc_frame_find_saved_regs ();
 \f
 /* Things needed for making the inferior call functions.  */
 /*
@@ -466,141 +460,94 @@ extern void sparc_frame_find_saved_regs ();
 #define PUSH_DUMMY_FRAME       sparc_push_dummy_frame ()
 #define POP_FRAME      sparc_pop_frame ()
 
-void sparc_push_dummy_frame (), sparc_pop_frame ();
+void sparc_push_dummy_frame PARAMS ((void)), sparc_pop_frame PARAMS ((void));
+
+#ifndef CALL_DUMMY
 /* This sequence of words is the instructions
 
-   save %sp,-0x140,%sp
-   std %f30,[%fp-0x08]
-   std %f28,[%fp-0x10]
-   std %f26,[%fp-0x18]
-   std %f24,[%fp-0x20]
-   std %f22,[%fp-0x28]
-   std %f20,[%fp-0x30]
-   std %f18,[%fp-0x38]
-   std %f16,[%fp-0x40]
-   std %f14,[%fp-0x48]
-   std %f12,[%fp-0x50]
-   std %f10,[%fp-0x58]
-   std %f8,[%fp-0x60]
-   std %f6,[%fp-0x68]
-   std %f4,[%fp-0x70]
-   std %f2,[%fp-0x78]
-   std %f0,[%fp-0x80]
-   std %g6,[%fp-0x88]
-   std %g4,[%fp-0x90]
-   std %g2,[%fp-0x98]
-   std %g0,[%fp-0xa0]
-   std %i6,[%fp-0xa8]
-   std %i4,[%fp-0xb0]
-   std %i2,[%fp-0xb8]
-   std %i0,[%fp-0xc0]
-   nop ! stcsr [%fp-0xc4]
-   nop ! stfsr [%fp-0xc8]
-   nop ! wr    %npc,[%fp-0xcc]
-   nop ! wr    %pc,[%fp-0xd0]
-   rd  %tbr,%o0
-   st  %o0,[%fp-0xd4]
-   rd  %wim,%o1
-   st  %o0,[%fp-0xd8]
-   rd  %psr,%o0
-   st  %o0,[%fp-0xdc]
-   rd  %y,%o0
-   st  %o0,[%fp-0xe0]
-
-     /..* The arguments are pushed at this point by GDB;
-       no code is needed in the dummy for this.
-       The CALL_DUMMY_START_OFFSET gives the position of
-       the following ld instruction.  *../
-
-   ld  [%sp+0x58],%o5
-   ld  [%sp+0x54],%o4
-   ld  [%sp+0x50],%o3
-   ld  [%sp+0x4c],%o2
-   ld  [%sp+0x48],%o1
-   call 0x00000000
-   ld  [%sp+0x44],%o0
-   nop
-   ta 1
-   nop
-
-   note that this is 192 bytes, which is a multiple of 8 (not only 4) bytes.
-   note that the `call' insn is a relative, not an absolute call.
-   note that the `nop' at the end is needed to keep the trap from
-        clobbering things (if NPC pointed to garbage instead).
-
-We actually start executing at the `sethi', since the pushing of the
-registers (as arguments) is done by PUSH_DUMMY_FRAME.  If this were
-real code, the arguments for the function called by the CALL would be
-pushed between the list of ST insns and the CALL, and we could allow
-it to execute through.  But the arguments have to be pushed by GDB
-after the PUSH_DUMMY_FRAME is done, and we cannot allow these ST
-insns to be performed again, lest the registers saved be taken for
-arguments.  */
-
-#define CALL_DUMMY { 0x9de3bee0, 0xfd3fbff8, 0xf93fbff0, 0xf53fbfe8,   \
-                    0xf13fbfe0, 0xed3fbfd8, 0xe93fbfd0, 0xe53fbfc8,    \
-                    0xe13fbfc0, 0xdd3fbfb8, 0xd93fbfb0, 0xd53fbfa8,    \
-                    0xd13fbfa0, 0xcd3fbf98, 0xc93fbf90, 0xc53fbf88,    \
-                    0xc13fbf80, 0xcc3fbf78, 0xc83fbf70, 0xc43fbf68,    \
-                    0xc03fbf60, 0xfc3fbf58, 0xf83fbf50, 0xf43fbf48,    \
-                    0xf03fbf40, 0x01000000, 0x01000000, 0x01000000,    \
-                    0x01000000, 0x91580000, 0xd027bf50, 0x93500000,    \
-                    0xd027bf4c, 0x91480000, 0xd027bf48, 0x91400000,    \
-                    0xd027bf44, 0xda03a058, 0xd803a054, 0xd603a050,    \
-                    0xd403a04c, 0xd203a048, 0x40000000, 0xd003a044,    \
-                    0x01000000, 0x91d02001, 0x01000000, 0x01000000}
-
-#define CALL_DUMMY_LENGTH 192
-
-#define CALL_DUMMY_START_OFFSET 148
+   0:   bc 10 00 01     mov  %g1, %fp
+   4:   9d e3 80 00     save  %sp, %g0, %sp
+   8:   bc 10 00 02     mov  %g2, %fp
+   c:   be 10 00 03     mov  %g3, %i7
+  10:   da 03 a0 58     ld  [ %sp + 0x58 ], %o5
+  14:   d8 03 a0 54     ld  [ %sp + 0x54 ], %o4
+  18:   d6 03 a0 50     ld  [ %sp + 0x50 ], %o3
+  1c:   d4 03 a0 4c     ld  [ %sp + 0x4c ], %o2
+  20:   d2 03 a0 48     ld  [ %sp + 0x48 ], %o1
+  24:   40 00 00 00     call  <fun>
+  28:   d0 03 a0 44     ld  [ %sp + 0x44 ], %o0
+  2c:   01 00 00 00     nop 
+  30:   91 d0 20 01     ta  1
+  34:   01 00 00 00     nop
+
+   NOTES:
+       * the first four instructions are necessary only on the simulator.
+       * this is a multiple of 8 (not only 4) bytes.
+       * the `call' insn is a relative, not an absolute call.
+       * the `nop' at the end is needed to keep the trap from
+         clobbering things (if NPC pointed to garbage instead).
+*/
+
+#define CALL_DUMMY { 0xbc100001, 0x9de38000, 0xbc100002, 0xbe100003,   \
+                    0xda03a058, 0xd803a054, 0xd603a050, 0xd403a04c,    \
+                    0xd203a048, 0x40000000, 0xd003a044, 0x01000000,    \
+                    0x91d02001, 0x01000000 }
+
+
+/* Size of the call dummy in bytes. */
+
+#define CALL_DUMMY_LENGTH 0x38
+
+/* Offset within call dummy of first instruction to execute. */
+
+#define CALL_DUMMY_START_OFFSET 0
+
+/* Offset within CALL_DUMMY of the 'call' instruction. */
+
+#define CALL_DUMMY_CALL_OFFSET (CALL_DUMMY_START_OFFSET + 0x24)
+
+/* Offset within CALL_DUMMY of the 'ta 1' instruction. */
+
+#define CALL_DUMMY_BREAKPOINT_OFFSET (CALL_DUMMY_START_OFFSET + 0x30)
 
 #define CALL_DUMMY_STACK_ADJUST 68
 
+#endif
 /* Insert the specified number of args and function address
-   into a call sequence of the above form stored at DUMMYNAME.
-
-   For structs and unions, if the function was compiled with Sun cc,
-   it expects 'unimp' after the call.  But gcc doesn't use that
-   (twisted) convention.  So leave a nop there for gcc (FIX_CALL_DUMMY
-   can assume it is operating on a pristine CALL_DUMMY, not one that
-   has already been customized for a different function).  */
-
-#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)     \
-{                                                                      \
-  *(int *)((char *) dummyname+168) = (0x40000000|((fun-(pc+168))>>2)); \
-  if (!gcc_p                                                            \
-      && (TYPE_CODE (type) == TYPE_CODE_STRUCT                         \
-         || TYPE_CODE (type) == TYPE_CODE_UNION))                      \
-    *(int *)((char *) dummyname+176) = (TYPE_LENGTH (type) & 0x1fff);  \
-}
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+ sparc_fix_call_dummy (dummyname, pc, fun, type, gcc_p)
+void sparc_fix_call_dummy PARAMS ((char *dummy, CORE_ADDR pc, CORE_ADDR fun,
+                                  struct type *value_type, int using_gcc));
+
+/* The Sparc returns long doubles on the stack.  */
 
+#define RETURN_VALUE_ON_STACK(TYPE) \
+  (TYPE_CODE(TYPE) == TYPE_CODE_FLT \
+   && TYPE_LENGTH(TYPE) > 8)
 \f
 /* Sparc has no reliable single step ptrace call */
 
-#define NO_SINGLE_STEP 1
-extern void single_step ();
+#define SOFTWARE_SINGLE_STEP_P 1
+extern void sparc_software_single_step PARAMS ((unsigned int, int));
+#define SOFTWARE_SINGLE_STEP(sig,bp_p) sparc_software_single_step (sig,bp_p)
 
 /* We need more arguments in a frame specification for the
    "frame" or "info frame" command.  */
 
 #define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv)
-/* FIXME:  Depends on equivalence between FRAME and "struct frame_info *",
-   and equivalence between CORE_ADDR and FRAME_ADDR. */
 extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));
 
-/* To print every pair of float registers as a double, we use this hook.  */
+/* To print every pair of float registers as a double, we use this hook.
+   We also print the condition code registers in a readable format
+   (FIXME: can expand this to all control regs).  */
 
+#undef         PRINT_REGISTER_HOOK
 #define        PRINT_REGISTER_HOOK(regno)      \
-  if (((regno) >= FP0_REGNUM)          \
-   && ((regno) <  FP0_REGNUM + 32)     \
-   && (0 == ((regno) & 1))) {          \
-    char doublereg[8];         /* two float regs */    \
-    if (!read_relative_register_raw_bytes ((regno)  , doublereg  )     \
-     && !read_relative_register_raw_bytes ((regno)+1, doublereg+4)) {  \
-      printf("\t");                    \
-      print_floating (doublereg, builtin_type_double, stdout); \
-    }                                  \
-  }
+  sparc_print_register_hook (regno)
+extern void sparc_print_register_hook PARAMS ((int regno));
+
 
 /* Optimization for storing registers to the inferior.  The hook
    DO_DEFERRED_STORES
@@ -616,3 +563,22 @@ extern int deferred_stores;
     target_store_registers (-2);
 #define        CLEAR_DEFERRED_STORES   \
   deferred_stores = 0;
+
+/* If the current gcc for for this target does not produce correct debugging
+   information for float parameters, both prototyped and unprototyped, then
+   define this macro.  This forces gdb to  always assume that floats are
+   passed as doubles and then converted in the callee. */
+
+#define COERCE_FLOAT_TO_DOUBLE 1
+
+/* Select the sparc disassembler */
+
+#define TM_PRINT_INSN_MACH bfd_mach_sparc
+
+/* Arguments smaller than an int must promoted to ints when synthesizing
+   function calls.  */
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+    sp = sparc_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))
+extern CORE_ADDR
+sparc_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_ADDR));