]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/config/mips/tm-mips.h
import gdb-1999-09-08 snapshot
[thirdparty/binutils-gdb.git] / gdb / config / mips / tm-mips.h
index 916dba33994598a5e97200c137df548a5cd2a72e..6e7e72c5762cc080d9b432bda3c00b08a98a594e 100644 (file)
@@ -1,39 +1,78 @@
 /* Definitions to make GDB run on a mips box under 4.3bsd.
-   Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995
+   Free Software Foundation, Inc.
    Contributed by Per Bothner (bothner@cs.wisc.edu) at U.Wisconsin
    and by Alessandro Forin (af@cs.cmu.edu) at CMU..
 
-This file is part of GDB.
+   This file is part of GDB.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.  */
+   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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TM_MIPS_H
+#define TM_MIPS_H 1
+
+struct frame_info;
+struct symbol;
+struct type;
+struct value;
 
 #include <bfd.h>
 #include "coff/sym.h"          /* Needed for PDR below.  */
 #include "coff/symconst.h"
 
-#if !defined (TARGET_BYTE_ORDER)
-#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+#if !defined (TARGET_BYTE_ORDER_DEFAULT)
+#define TARGET_BYTE_ORDER_DEFAULT LITTLE_ENDIAN
+#endif
+
+#if !defined (GDB_TARGET_IS_MIPS64)
+#define GDB_TARGET_IS_MIPS64 0
+#endif
+
+#if !defined (MIPS_EABI)
+#define MIPS_EABI 0
+#endif
+
+#if !defined (TARGET_MONITOR_PROMPT)
+#define TARGET_MONITOR_PROMPT "<IDT>"
+#endif
+
+/* PC should be masked to remove possible MIPS16 flag */
+#if !defined (GDB_TARGET_MASK_DISAS_PC)
+#define GDB_TARGET_MASK_DISAS_PC(addr) UNMAKE_MIPS16_ADDR(addr)
+#endif
+#if !defined (GDB_TARGET_UNMASK_DISAS_PC)
+#define GDB_TARGET_UNMASK_DISAS_PC(addr) MAKE_MIPS16_ADDR(addr)
 #endif
 
 /* Floating point is IEEE compliant */
 #define IEEE_FLOAT
 
-/* Some MIPS boards are provided both with and without a floating
-   point coprocessor; we provide a user settable variable to tell gdb
-   whether there is one or not.  */
-extern int mips_fpu;
+/* The name of the usual type of MIPS processor that is in the target
+   system.  */
+
+#define DEFAULT_MIPS_TYPE "generic"
+
+/* Remove useless bits from an instruction address.  */
+
+#define ADDR_BITS_REMOVE(addr) mips_addr_bits_remove(addr)
+CORE_ADDR mips_addr_bits_remove PARAMS ((CORE_ADDR addr));
+
+/* Remove useless bits from the stack pointer.  */
+
+#define TARGET_READ_SP() ADDR_BITS_REMOVE (read_register (SP_REGNUM))
 
 /* Offset from address of function to start of its code.
    Zero on most machines.  */
@@ -43,9 +82,15 @@ extern int mips_fpu;
 /* Advance PC across any function entry prologue instructions
    to reach some "real" code.  */
 
-#define SKIP_PROLOGUE(pc)      pc = mips_skip_prologue (pc, 0)
+#define SKIP_PROLOGUE(pc) (mips_skip_prologue (pc, 0))
 extern CORE_ADDR mips_skip_prologue PARAMS ((CORE_ADDR addr, int lenient));
 
+/* Return non-zero if PC points to an instruction which will cause a step
+   to execute both the instruction at PC and an instruction at PC+4.  */
+extern int mips_step_skips_delay PARAMS ((CORE_ADDR));
+#define STEP_SKIPS_DELAY_P (1)
+#define STEP_SKIPS_DELAY(pc) (mips_step_skips_delay (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
@@ -60,14 +105,17 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
 
 /* Stack grows downward.  */
 
-#define INNER_THAN <
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
 
-#define BIG_ENDIAN 4321
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
-#define BREAKPOINT {0, 0x5, 0, 0xd}
-#else
-#define BREAKPOINT {0xd, 0, 0x5, 0}
-#endif
+/* 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.  */
+
+extern breakpoint_from_pc_fn mips_breakpoint_from_pc;
+#define BREAKPOINT_FROM_PC(pcptr, lenptr) mips_breakpoint_from_pc(pcptr, lenptr)
 
 /* Amount PC must be decremented by after a breakpoint.
    This is often the number of bytes in BREAKPOINT
@@ -75,26 +123,41 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
 
 #define DECR_PC_AFTER_BREAK 0
 
-/* Nonzero if instruction at PC is a return instruction. "j ra" on mips. */
+/* 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 ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 4) == 0x3e00008)
+#define REGISTER_SIZE 4
 
-/* This is taken care of in print_floating [IEEE_FLOAT].  */
+/* The size of a register.  This is predefined in tm-mips64.h.  We
+   can't use REGISTER_SIZE because that is used for various other
+   things.  */
 
-#define INVALID_FLOAT(p,l) 0
+#ifndef MIPS_REGSIZE
+#define MIPS_REGSIZE 4
+#endif
 
-/* Say how long (all) registers are.  */
+/* The sizes of floating point registers.  */
 
-#define REGISTER_TYPE long
+#define MIPS_FPU_SINGLE_REGSIZE 4
+#define MIPS_FPU_DOUBLE_REGSIZE 8
 
 /* Number of machine registers */
 
-#define NUM_REGS 80
+#ifndef NUM_REGS
+#define NUM_REGS 90
+#endif
+
+/* Given the register index, return the name of the corresponding
+   register. */
+extern char *mips_register_name PARAMS ((int regnr));
+#define REGISTER_NAME(i) mips_register_name (i)
 
 /* Initializer for an array of names of registers.
    There should be NUM_REGS strings in this initializer.  */
 
-#define REGISTER_NAMES         \
+#ifndef MIPS_REGISTER_NAMES
+#define MIPS_REGISTER_NAMES    \
     {  "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3", \
        "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7", \
        "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7", \
@@ -104,9 +167,11 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
        "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15", \
        "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",\
        "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",\
-       "fsr",  "fir",  "fp",   "inx",  "rand", "tlblo","ctxt", "tlbhi",\
-       "epc",  "prid"\
+       "fsr",  "fir",  "fp",   "", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
     }
+#endif
 
 /* Register numbers of various important registers.
    Note that some of these values are "real" register numbers,
@@ -118,44 +183,85 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
 #define ZERO_REGNUM 0          /* read-only register, always 0 */
 #define V0_REGNUM 2            /* Function integer return value */
 #define A0_REGNUM 4            /* Loc of first arg during a subr call */
+#if MIPS_EABI
+#define MIPS_LAST_ARG_REGNUM 11        /* EABI uses R4 through R11 for args */
+#define MIPS_NUM_ARG_REGS 8
+#else
+#define MIPS_LAST_ARG_REGNUM 7 /* old ABI uses R4 through R7 for args */
+#define MIPS_NUM_ARG_REGS 4
+#endif
+#define T9_REGNUM 25           /* Contains address of callee in PIC */
 #define SP_REGNUM 29           /* Contains address of top of stack */
 #define RA_REGNUM 31           /* Contains return address value */
 #define PS_REGNUM 32           /* Contains processor status */
-#define HI_REGNUM 34            /* Multiple/divide temp */
-#define LO_REGNUM 33            /* ... */
+#define HI_REGNUM 34           /* Multiple/divide temp */
+#define LO_REGNUM 33           /* ... */
 #define BADVADDR_REGNUM 35     /* bad vaddr for addressing exception */
 #define CAUSE_REGNUM 36                /* describes last exception */
 #define PC_REGNUM 37           /* Contains program counter */
-#define FP0_REGNUM 38           /* Floating point register 0 (single float) */
-#define FCRCS_REGNUM 70         /* FP control/status */
-#define FCRIR_REGNUM 71         /* FP implementation/revision */
+#define FP0_REGNUM 38          /* Floating point register 0 (single float) */
+#define FPA0_REGNUM (FP0_REGNUM+12)    /* First float argument register */
+#if MIPS_EABI                  /* EABI uses F12 through F19 for args */
+#define MIPS_LAST_FP_ARG_REGNUM (FP0_REGNUM+19)
+#define MIPS_NUM_FP_ARG_REGS 8
+#else /* old ABI uses F12 through F15 for args */
+#define MIPS_LAST_FP_ARG_REGNUM (FP0_REGNUM+15)
+#define MIPS_NUM_FP_ARG_REGS 4
+#endif
+#define FCRCS_REGNUM 70                /* FP control/status */
+#define FCRIR_REGNUM 71                /* FP implementation/revision */
 #define FP_REGNUM 72           /* Pseudo register that contains true address of executing stack frame */
-#define        FIRST_EMBED_REGNUM 73   /* First supervisor register for embedded use */
-#define        LAST_EMBED_REGNUM 79    /* Last one */
+#define        UNUSED_REGNUM 73        /* Never used, FIXME */
+#define        FIRST_EMBED_REGNUM 74   /* First CP0 register for embedded use */
+#define        PRID_REGNUM 89          /* Processor ID */
+#define        LAST_EMBED_REGNUM 89    /* Last one */
 
 /* Define DO_REGISTERS_INFO() to do machine-specific formatting
    of register dumps. */
 
 #define DO_REGISTERS_INFO(_regnum, fp) mips_do_registers_info(_regnum, fp)
+extern void mips_do_registers_info PARAMS ((int, int));
 
 /* Total amount of space needed to store our copies of the machine's
    register state, the array `registers'.  */
-#define REGISTER_BYTES (NUM_REGS*4)
+
+#define REGISTER_BYTES (NUM_REGS*MIPS_REGSIZE)
 
 /* Index within `registers' of the first byte of the space for
    register N.  */
 
-#define REGISTER_BYTE(N) ((N) * 4)
+#define REGISTER_BYTE(N) ((N) * MIPS_REGSIZE)
+
+/* Number of bytes of storage in the actual machine representation for
+   register N.  NOTE: This indirectly defines the register size
+   transfered by the GDB protocol. */
+
+extern int mips_register_raw_size PARAMS ((int reg_nr));
+#define REGISTER_RAW_SIZE(N) (mips_register_raw_size ((N)))
+
+
+/* Covert between the RAW and VIRTUAL registers.
+
+   Some MIPS (SR, FSR, FIR) have a `raw' size of MIPS_REGSIZE but are
+   really 32 bit registers.  This is a legacy of the 64 bit MIPS GDB
+   protocol which transfers 64 bits for 32 bit registers. */
 
-/* Number of bytes of storage in the actual machine representation
-   for register N.  On mips, all regs are 4 bytes.  */
+extern int mips_register_convertible PARAMS ((int reg_nr));
+#define REGISTER_CONVERTIBLE(N) (mips_register_convertible ((N)))
+     
 
-#define REGISTER_RAW_SIZE(N) 4
+void mips_register_convert_to_virtual PARAMS ((int reg_nr, struct type *virtual_type, char *raw_buf, char *virt_buf));
+#define REGISTER_CONVERT_TO_VIRTUAL(N,VIRTUAL_TYPE,RAW_BUF,VIRT_BUF) \
+  mips_register_convert_to_virtual (N,VIRTUAL_TYPE,RAW_BUF,VIRT_BUF)
+
+void mips_register_convert_to_raw PARAMS ((struct type *virtual_type, int reg_nr, char *virt_buf, char *raw_buf));
+#define REGISTER_CONVERT_TO_RAW(VIRTUAL_TYPE,N,VIRT_BUF,RAW_BUF) \
+  mips_register_convert_to_raw (VIRTUAL_TYPE,N,VIRT_BUF,RAW_BUF)
 
 /* Number of bytes of storage in the program's representation
-   for register N.  On mips, all regs are 4 bytes.  */
+   for register N. */
 
-#define REGISTER_VIRTUAL_SIZE(N) 4
+#define REGISTER_VIRTUAL_SIZE(N) TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (N))
 
 /* Largest value REGISTER_RAW_SIZE can have.  */
 
@@ -165,40 +271,49 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
 
 #define MAX_REGISTER_VIRTUAL_SIZE 8
 
-/* Return the GDB type object for the "standard" data type
-   of data in register N.  */
+/* Return the GDB type object for the "standard" data type of data in
+   register N.  */
 
+#ifndef REGISTER_VIRTUAL_TYPE
 #define REGISTER_VIRTUAL_TYPE(N) \
-       (((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32)  \
-        ? builtin_type_float : builtin_type_int) \
+       (((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) ? builtin_type_float \
+        : ((N) == 32 /*SR*/) ? builtin_type_uint32 \
+        : ((N) >= 70 && (N) <= 89) ? builtin_type_uint32 \
+        : builtin_type_int)
+#endif
 
-#if HOST_BYTE_ORDER == BIG_ENDIAN
 /* All mips targets store doubles in a register pair with the least
    significant register in the lower numbered register.
-   If the host is big endian, double register values need conversion between
-   memory and register formats.  */
+   If the target is big endian, double register values need conversion
+   between memory and register formats.  */
 
 #define REGISTER_CONVERT_TO_TYPE(n, type, buffer)                      \
-  do {if ((n) >= FP0_REGNUM && (n) < FP0_REGNUM + 32 &&                \
-         TYPE_CODE(type) == TYPE_CODE_FLT && TYPE_LENGTH(type) == 8) { \
+  do {if (TARGET_BYTE_ORDER == BIG_ENDIAN                              \
+         && REGISTER_RAW_SIZE (n) == 4                                 \
+         && (n) >= FP0_REGNUM && (n) < FP0_REGNUM + 32                 \
+         && TYPE_CODE(type) == TYPE_CODE_FLT                           \
+         && TYPE_LENGTH(type) == 8) {                                  \
         char __temp[4];                                                        \
        memcpy (__temp, ((char *)(buffer))+4, 4);                       \
        memcpy (((char *)(buffer))+4, (buffer), 4);                     \
        memcpy (((char *)(buffer)), __temp, 4); }} while (0)
 
 #define REGISTER_CONVERT_FROM_TYPE(n, type, buffer)                    \
-  do {if ((n) >= FP0_REGNUM && (n) < FP0_REGNUM + 32 &&                        \
-         TYPE_CODE(type) == TYPE_CODE_FLT && TYPE_LENGTH(type) == 8) { \
+  do {if (TARGET_BYTE_ORDER == BIG_ENDIAN                              \
+         && REGISTER_RAW_SIZE (n) == 4                                 \
+         && (n) >= FP0_REGNUM && (n) < FP0_REGNUM + 32                 \
+         && TYPE_CODE(type) == TYPE_CODE_FLT                           \
+         && TYPE_LENGTH(type) == 8) {                                  \
         char __temp[4];                                                        \
        memcpy (__temp, ((char *)(buffer))+4, 4);                       \
        memcpy (((char *)(buffer))+4, (buffer), 4);                     \
        memcpy (((char *)(buffer)), __temp, 4); }} while (0)
-#endif
 
 /* Store the address of the place in which to copy the structure the
    subroutine will return.  Handled by mips_push_arguments.  */
 
-#define STORE_STRUCT_RETURN(addr, sp)  /**/
+#define STORE_STRUCT_RETURN(addr, sp)
+/**/
 
 /* Extract from an array REGBUF containing the (raw) register state
    a function return value of type TYPE, and copy that, in virtual format,
@@ -206,12 +321,15 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
 
 #define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
   mips_extract_return_value(TYPE, REGBUF, VALBUF)
+extern void
+mips_extract_return_value PARAMS ((struct type *, char[], char *));
 
 /* Write into appropriate registers a function return value
    of type TYPE, given in virtual format.  */
 
 #define STORE_RETURN_VALUE(TYPE,VALBUF) \
   mips_store_return_value(TYPE, VALBUF)
+extern void mips_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,
@@ -225,9 +343,8 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
   (extract_address (REGBUF + REGISTER_BYTE (V0_REGNUM), \
                    REGISTER_RAW_SIZE (V0_REGNUM)))
 
-/* Structures are returned by ref in extra arg0 */
-#define USE_STRUCT_CONVENTION(gcc_p, type)     1
-
+extern use_struct_convention_fn mips_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) mips_use_struct_convention (gcc_p, type)
 \f
 /* Describe the pointer in each stack frame to the previous stack frame
    (its caller).  */
@@ -235,7 +352,8 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
 /* FRAME_CHAIN takes a frame's nominal address
    and produces the frame's chain-pointer. */
 
-#define FRAME_CHAIN(thisframe) (FRAME_ADDR)mips_frame_chain(thisframe)
+#define FRAME_CHAIN(thisframe) (CORE_ADDR) mips_frame_chain (thisframe)
+extern CORE_ADDR mips_frame_chain PARAMS ((struct frame_info *));
 
 /* Define other aspects of the stack frame.  */
 
@@ -245,11 +363,12 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
    does not, FRAMELESS is set to 1, else 0.  */
 /* We handle this differently for mips, and maybe we should not */
 
-#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS)  {(FRAMELESS) = 0;}
+#define FRAMELESS_FUNCTION_INVOCATION(FI)  (0)
 
 /* Saved Pc.  */
 
 #define FRAME_SAVED_PC(FRAME)  (mips_frame_saved_pc(FRAME))
+extern CORE_ADDR mips_frame_saved_pc PARAMS ((struct frame_info *));
 
 #define FRAME_ARGS_ADDRESS(fi) (fi)->frame
 
@@ -258,7 +377,8 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
 /* Return number of args passed to a frame.
    Can return -1, meaning no way to tell.  */
 
-#define FRAME_NUM_ARGS(num, fi)        (num = mips_frame_num_args(fi))
+#define FRAME_NUM_ARGS(fi)     (mips_frame_num_args(fi))
+extern int mips_frame_num_args PARAMS ((struct frame_info *));
 
 /* Return number of bytes at start of arglist that are not really args.  */
 
@@ -270,149 +390,104 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
    ways in the stack frame.  sp is even more special:
    the address we return for it IS the sp for the next frame.  */
 
-#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) ( \
-  (frame_saved_regs) = *(frame_info)->saved_regs, \
-  (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame)
-
+#define FRAME_INIT_SAVED_REGS(frame_info) \
+  do { \
+    if ((frame_info)->saved_regs == NULL) \
+      mips_find_saved_regs (frame_info); \
+    (frame_info)->saved_regs[SP_REGNUM] = (frame_info)->frame; \
+  } while (0)
+extern void mips_find_saved_regs PARAMS ((struct frame_info *));
 \f
+
 /* Things needed for making the inferior call functions.  */
 
-/* Stack has strict alignment. However, use PUSH_ARGUMENTS
-   to take care of it. */
-/*#define STACK_ALIGN(addr)    (((addr)+3)&~3)*/
+/* Stack must be aligned on 32-bit boundaries when synthesizing
+   function calls.  We don't need STACK_ALIGN, PUSH_ARGUMENTS will
+   handle it. */
 
+extern CORE_ADDR mips_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_ADDR));
 #define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
-    sp = mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
+  (mips_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr)))
+
+extern CORE_ADDR mips_push_return_address PARAMS ((CORE_ADDR pc, CORE_ADDR sp));
+#define PUSH_RETURN_ADDRESS(PC, SP) (mips_push_return_address ((PC), (SP)))
 
 /* Push an empty stack frame, to record the current PC, etc.  */
 
 #define PUSH_DUMMY_FRAME       mips_push_dummy_frame()
+extern void mips_push_dummy_frame PARAMS ((void));
 
 /* Discard from the stack the innermost frame, restoring all registers.  */
 
 #define POP_FRAME              mips_pop_frame()
+extern void mips_pop_frame PARAMS ((void));
+
+#define CALL_DUMMY { 0 }
+
+#define CALL_DUMMY_START_OFFSET (0)
+
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
 
-#define MK_OP(op,rs,rt,offset) (((op)<<26)|((rs)<<21)|((rt)<<16)|(offset))
-#define CALL_DUMMY_SIZE (16*4)
-#define Dest_Reg 2
-#define CALL_DUMMY {\
- MK_OP(0,RA_REGNUM,0,8),       /* jr $ra # Fake ABOUT_TO_RETURN ...*/\
- 0,                            /* nop    #  ... to stop raw backtrace*/\
- 0x27bd0000,                   /* addu sp,?0 # Pseudo prologue */\
-/* Start here: */\
- MK_OP(061,SP_REGNUM,12,0),    /* lwc1 $f12,0(sp) # Reload FP regs*/\
- MK_OP(061,SP_REGNUM,13,4),    /* lwc1 $f13,4(sp) */\
- MK_OP(061,SP_REGNUM,14,8),    /* lwc1 $f14,8(sp) */\
- MK_OP(061,SP_REGNUM,15,12),   /* lwc1 $f15,12(sp) */\
- MK_OP(043,SP_REGNUM,4,0),     /* lw $r4,0(sp) # Reload first 4 args*/\
- MK_OP(043,SP_REGNUM,5,4),     /* lw $r5,4(sp) */\
- MK_OP(043,SP_REGNUM,6,8),     /* lw $r6,8(sp) */\
- MK_OP(043,SP_REGNUM,7,12),    /* lw $r7,12(sp) */\
- (017<<26)| (Dest_Reg << 16),  /* lui $r31,<target upper 16 bits>*/\
- MK_OP(13,Dest_Reg,Dest_Reg,0),        /* ori $r31,$r31,<lower 16 bits>*/ \
- (Dest_Reg<<21) | (31<<11) | 9,        /* jalr $r31 */\
- MK_OP(043,SP_REGNUM,7,12),    /* lw $r7,12(sp) */\
- 0x5000d,                      /* bpt */\
-}
-
-#define CALL_DUMMY_START_OFFSET 12
-
-/* Insert the specified number of args and function address
-   into a call sequence of the above form stored at DUMMYNAME.  */
-
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
-/* For big endian mips machines the loading of FP values depends on whether
-   they are single or double precision. */
+/* On Irix, $t9 ($25) contains the address of the callee (used for PIC).
+   It doesn't hurt to do this on other systems; $t9 will be ignored.  */
 #define FIX_CALL_DUMMY(dummyname, start_sp, fun, nargs, args, rettype, gcc_p) \
-  do {                                                                 \
-    ((int*)(dummyname))[11] |= ((unsigned long)(fun)) >> 16;           \
-    ((int*)(dummyname))[12] |= (unsigned short)(fun);                  \
-    if (! mips_fpu) {                                                  \
-      ((int *) (dummyname))[3] = 0; ((int *) (dummyname))[4] = 0;      \
-      ((int *) (dummyname))[5] = 0; ((int *) (dummyname))[6] = 0;      \
-    } else {                                                           \
-      if (nargs > 0 &&                                                 \
-         TYPE_CODE(VALUE_TYPE(args[0])) == TYPE_CODE_FLT &&            \
-         TYPE_LENGTH(VALUE_TYPE(args[0])) == 8) {                      \
-       ((int *) (dummyname))[3] = MK_OP(061,SP_REGNUM,12,4);           \
-       ((int *) (dummyname))[4] = MK_OP(061,SP_REGNUM,13,0);           \
-      }                                                                        \
-      if (nargs > 1 &&                                                 \
-         TYPE_CODE(VALUE_TYPE(args[1])) == TYPE_CODE_FLT &&            \
-         TYPE_LENGTH(VALUE_TYPE(args[1])) == 8) {                      \
-       ((int *) (dummyname))[5] = MK_OP(061,SP_REGNUM,14,12);          \
-       ((int *) (dummyname))[6] = MK_OP(061,SP_REGNUM,15,8);           \
-      }                                                                        \
-    }                                                                  \
-  } while (0)
-#else
-#define FIX_CALL_DUMMY(dummyname, start_sp, fun, nargs,        args, rettype, gcc_p)\
-  do \
-    { \
-      ((int*)(dummyname))[11] |= ((unsigned long)(fun)) >> 16; \
-      ((int*)(dummyname))[12] |= (unsigned short)(fun); \
-      if (! mips_fpu) \
-       { \
-         ((int *) (dummyname))[3] = 0; \
-         ((int *) (dummyname))[4] = 0; \
-         ((int *) (dummyname))[5] = 0; \
-         ((int *) (dummyname))[6] = 0; \
-       } \
-    } \
-  while (0)
-#endif
+    write_register(T9_REGNUM, fun)
+
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+
+#define CALL_DUMMY_ADDRESS() (mips_call_dummy_address ())
+extern CORE_ADDR mips_call_dummy_address PARAMS ((void));
 
 /* There's a mess in stack frame creation.  See comments in blockframe.c
    near reference to INIT_FRAME_PC_FIRST.  */
 
-#define        INIT_FRAME_PC(fromleaf, prev) /* nada */
+#define        INIT_FRAME_PC(fromleaf, prev)   /* nada */
 
 #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 ());
+   mips_init_frame_pc_first(fromleaf, prev)
+extern void mips_init_frame_pc_first PARAMS ((int, struct frame_info *));
 
 /* Special symbol found in blocks associated with routines.  We can hang
    mips_extra_func_info_t's off of this.  */
 
 #define MIPS_EFI_SYMBOL_NAME "__GDB_EFI_INFO__"
+extern void ecoff_relocate_efi PARAMS ((struct symbol *, CORE_ADDR));
 
 /* Specific information about a procedure.
    This overlays the MIPS's PDR records, 
    mipsread.c (ab)uses this to save memory */
 
-typedef struct mips_extra_func_info {
-       long    numargs;        /* number of args to procedure (was iopt) */
-       PDR     pdr;            /* Procedure descriptor record */
-} *mips_extra_func_info_t;
-
-#define EXTRA_FRAME_INFO \
-  mips_extra_func_info_t proc_desc; \
-  int num_args;\
-  struct frame_saved_regs *saved_regs;
+typedef struct mips_extra_func_info
+  {
+    long numargs;              /* number of args to procedure (was iopt) */
+    bfd_vma high_addr;         /* upper address bound */
+    long frame_adjust;         /* offset of FP from SP (used on MIPS16) */
+    PDR pdr;                   /* Procedure descriptor record */
+  }
+ *mips_extra_func_info_t;
 
-#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) init_extra_frame_info(fci)
+extern void mips_init_extra_frame_info PARAMS ((int fromleaf, struct frame_info *));
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) \
+  mips_init_extra_frame_info(fromleaf, fci)
 
+extern void mips_print_extra_frame_info PARAMS ((struct frame_info * frame));
 #define        PRINT_EXTRA_FRAME_INFO(fi) \
-  { \
-    if (fi && fi->proc_desc && fi->proc_desc->pdr.framereg < NUM_REGS) \
-      printf_filtered (" frame pointer is at %s+%d\n", \
-                       reg_names[fi->proc_desc->pdr.framereg], \
-                                 fi->proc_desc->pdr.frameoffset); \
-  }
+  mips_print_extra_frame_info (fi)
 
-/* It takes two values to specify a frame on the MIPS.  Sigh.
+/* It takes two values to specify a frame on the MIPS.
 
-   In fact, at the moment, the *PC* is the primary value that sets up
-   a frame.  The PC is looked up to see what function it's in; symbol
-   information from that function tells us which register is the frame
-   pointer base, and what offset from there is the "virtual frame pointer".
-   (This is usually an offset from SP.)  FIXME -- this should be cleaned
-   up so that the primary value is the SP, and the PC is used to disambiguate
-   multiple functions with the same SP that are at different stack levels. */
+   In fact, the *PC* is the primary value that sets up a frame.  The
+   PC is looked up to see what function it's in; symbol information
+   from that function tells us which register is the frame pointer
+   base, and what offset from there is the "virtual frame pointer".
+   (This is usually an offset from SP.)  On most non-MIPS machines,
+   the primary value is the SP, and the PC, if needed, disambiguates
+   multiple functions with the same SP.  But on the MIPS we can't do
+   that since the PC is not stored in the same part of the frame every
+   time.  This does not seem to be a very clever way to set up frames,
+   but there is nothing we can do about that).  */
 
 #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 *));
 
 /* Convert a dbx stab register number (from `r' declaration) to a gdb REGNUM */
@@ -422,3 +497,89 @@ extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));
 /* Convert a ecoff register number to a gdb REGNUM */
 
 #define ECOFF_REG_TO_REGNUM(num) ((num) < 32 ? (num) : (num)+FP0_REGNUM-32)
+
+/* 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.
+
+   For the mips chip, it appears that the debug info marks the parameters as
+   floats regardless of whether the function is prototyped, but the actual
+   values are passed as doubles for the non-prototyped case and floats for
+   the prototyped case.  Thus we choose to make the non-prototyped case work
+   for C and break the prototyped case, since the non-prototyped case is
+   probably much more common.  (FIXME). */
+
+#define COERCE_FLOAT_TO_DOUBLE (current_language -> la_language == language_c)
+
+/* Select the default mips disassembler */
+
+#define TM_PRINT_INSN_MACH 0
+
+
+/* These are defined in mdebugread.c and are used in mips-tdep.c  */
+extern CORE_ADDR sigtramp_address, sigtramp_end;
+extern void fixup_sigtramp PARAMS ((void));
+
+/* Defined in mips-tdep.c and used in remote-mips.c */
+extern char *mips_read_processor_type PARAMS ((void));
+
+/* Functions for dealing with MIPS16 call and return stubs.  */
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name)     mips_in_call_stub (pc, name)
+#define IN_SOLIB_RETURN_TRAMPOLINE(pc, name)   mips_in_return_stub (pc, name)
+#define SKIP_TRAMPOLINE_CODE(pc)               mips_skip_stub (pc)
+#define IGNORE_HELPER_CALL(pc)                 mips_ignore_helper (pc)
+extern int mips_in_call_stub PARAMS ((CORE_ADDR pc, char *name));
+extern int mips_in_return_stub PARAMS ((CORE_ADDR pc, char *name));
+extern CORE_ADDR mips_skip_stub PARAMS ((CORE_ADDR pc));
+extern int mips_ignore_helper PARAMS ((CORE_ADDR pc));
+
+#ifndef TARGET_MIPS
+#define TARGET_MIPS
+#endif
+
+/* Definitions and declarations used by mips-tdep.c and remote-mips.c  */
+#define MIPS_INSTLEN 4         /* Length of an instruction */
+#define MIPS16_INSTLEN 2       /* Length of an instruction on MIPS16 */
+#define MIPS_NUMREGS 32                /* Number of integer or float registers */
+typedef unsigned long t_inst;  /* Integer big enough to hold an instruction */
+
+/* MIPS16 function addresses are odd (bit 0 is set).  Here are some
+   macros to test, set, or clear bit 0 of addresses.  */
+#define IS_MIPS16_ADDR(addr)    ((addr) & 1)
+#define MAKE_MIPS16_ADDR(addr)  ((addr) | 1)
+#define UNMAKE_MIPS16_ADDR(addr) ((addr) & ~1)
+
+#endif /* TM_MIPS_H */
+
+/* Macros for setting and testing a bit in a minimal symbol that
+   marks it as 16-bit 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.
+
+   ELF_MAKE_MSYMBOL_SPECIAL
+   tests whether an ELF symbol is "special", i.e. refers
+   to a 16-bit function, and sets a "special" bit in a 
+   minimal symbol to mark it as a 16-bit function
+   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
+ */
+
+#define ELF_MAKE_MSYMBOL_SPECIAL(sym,msym) \
+ { \
+  if (((elf_symbol_type *)(sym))->internal_elf_sym.st_other == STO_MIPS16) { \
+    MSYMBOL_INFO (msym) = (char *) (((long) MSYMBOL_INFO (msym)) | 0x80000000); \
+    SYMBOL_VALUE_ADDRESS (msym) |= 1; \
+  } \
+ }
+
+#define MSYMBOL_IS_SPECIAL(msym) \
+  (((long) MSYMBOL_INFO (msym) & 0x80000000) != 0)
+#define MSYMBOL_SIZE(msym) \
+  ((long) MSYMBOL_INFO (msym) & 0x7fffffff)
+
+
+/* Command to set the processor type. */
+extern void mips_set_processor_type_command (char *, int);