2005-02-02 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / i386-tdep.c
index ffdad06f4d035f2a06cf04db6ccbd31c4abfa400..671ad506b3e3cea99b4ca467a0d42bde8c134cfc 100644 (file)
@@ -1,7 +1,8 @@
 /* Intel 386 target-dependent stuff.
 
    Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
-   1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software
+   Foundation, Inc.
 
    This file is part of GDB.
 
    Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
-#include "gdb_string.h"
+#include "arch-utils.h"
+#include "command.h"
+#include "dummy-frame.h"
+#include "dwarf2-frame.h"
+#include "doublest.h"
+#include "floatformat.h"
 #include "frame.h"
+#include "frame-base.h"
+#include "frame-unwind.h"
 #include "inferior.h"
+#include "gdbcmd.h"
 #include "gdbcore.h"
 #include "objfiles.h"
-#include "target.h"
-#include "floatformat.h"
+#include "osabi.h"
+#include "regcache.h"
+#include "reggroups.h"
+#include "regset.h"
 #include "symfile.h"
 #include "symtab.h"
-#include "gdbcmd.h"
-#include "command.h"
-#include "arch-utils.h"
-#include "regcache.h"
-#include "doublest.h"
+#include "target.h"
 #include "value.h"
+#include "dis-asm.h"
+
 #include "gdb_assert.h"
-#include "reggroups.h"
-#include "dummy-frame.h"
-#include "osabi.h"
+#include "gdb_string.h"
 
 #include "i386-tdep.h"
 #include "i387-tdep.h"
 
-/* Names of the registers.  The first 10 registers match the register
-   numbering scheme used by GCC for stabs and DWARF.  */
+/* Register names.  */
+
 static char *i386_register_names[] =
 {
   "eax",   "ecx",    "edx",   "ebx",
@@ -61,129 +68,176 @@ static char *i386_register_names[] =
   "mxcsr"
 };
 
-/* MMX registers.  */
+static const int i386_num_register_names = ARRAY_SIZE (i386_register_names);
+
+/* Register names for MMX pseudo-registers.  */
 
 static char *i386_mmx_names[] =
 {
   "mm0", "mm1", "mm2", "mm3",
   "mm4", "mm5", "mm6", "mm7"
 };
-static const int mmx_num_regs = (sizeof (i386_mmx_names)
-                                / sizeof (i386_mmx_names[0]));
-#define MM0_REGNUM (NUM_REGS)
+
+static const int i386_num_mmx_regs = ARRAY_SIZE (i386_mmx_names);
 
 static int
-i386_mmx_regnum_p (int reg)
+i386_mmx_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  return (reg >= MM0_REGNUM && reg < MM0_REGNUM + mmx_num_regs);
+  int mm0_regnum = gdbarch_tdep (gdbarch)->mm0_regnum;
+
+  if (mm0_regnum < 0)
+    return 0;
+
+  return (regnum >= mm0_regnum && regnum < mm0_regnum + i386_num_mmx_regs);
 }
 
-/* FP register?  */
+/* SSE register?  */
 
-int
-i386_fp_regnum_p (int regnum)
+static int
+i386_sse_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  return (regnum < NUM_REGS
-         && (FP0_REGNUM && FP0_REGNUM <= (regnum) && (regnum) < FPC_REGNUM));
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+#define I387_ST0_REGNUM tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
+
+  if (I387_NUM_XMM_REGS == 0)
+    return 0;
+
+  return (I387_XMM0_REGNUM <= regnum && regnum < I387_MXCSR_REGNUM);
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
 }
 
-int
-i386_fpc_regnum_p (int regnum)
+static int
+i386_mxcsr_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  return (regnum < NUM_REGS
-         && (FPC_REGNUM <= (regnum) && (regnum) < XMM0_REGNUM));
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+#define I387_ST0_REGNUM tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
+
+  if (I387_NUM_XMM_REGS == 0)
+    return 0;
+
+  return (regnum == I387_MXCSR_REGNUM);
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
 }
 
-/* SSE register?  */
+#define I387_ST0_REGNUM (gdbarch_tdep (current_gdbarch)->st0_regnum)
+#define I387_MM0_REGNUM (gdbarch_tdep (current_gdbarch)->mm0_regnum)
+#define I387_NUM_XMM_REGS (gdbarch_tdep (current_gdbarch)->num_xmm_regs)
+
+/* FP register?  */
 
 int
-i386_sse_regnum_p (int regnum)
+i386_fp_regnum_p (int regnum)
 {
-  return (regnum < NUM_REGS
-         && (XMM0_REGNUM <= (regnum) && (regnum) < MXCSR_REGNUM));
+  if (I387_ST0_REGNUM < 0)
+    return 0;
+
+  return (I387_ST0_REGNUM <= regnum && regnum < I387_FCTRL_REGNUM);
 }
 
 int
-i386_mxcsr_regnum_p (int regnum)
+i386_fpc_regnum_p (int regnum)
 {
-  return (regnum < NUM_REGS
-         && (regnum == MXCSR_REGNUM));
+  if (I387_ST0_REGNUM < 0)
+    return 0;
+
+  return (I387_FCTRL_REGNUM <= regnum && regnum < I387_XMM0_REGNUM);
 }
 
-/* Return the name of register REG.  */
+/* Return the name of register REGNUM.  */
 
 const char *
-i386_register_name (int reg)
+i386_register_name (int regnum)
 {
-  if (reg < 0)
-    return NULL;
-  if (i386_mmx_regnum_p (reg))
-    return i386_mmx_names[reg - MM0_REGNUM];
-  if (reg >= sizeof (i386_register_names) / sizeof (*i386_register_names))
-    return NULL;
+  if (i386_mmx_regnum_p (current_gdbarch, regnum))
+    return i386_mmx_names[regnum - I387_MM0_REGNUM];
+
+  if (regnum >= 0 && regnum < i386_num_register_names)
+    return i386_register_names[regnum];
 
-  return i386_register_names[reg];
+  return NULL;
 }
 
-/* Convert stabs register number REG to the appropriate register
+/* Convert a dbx register number REG to the appropriate register
    number used by GDB.  */
 
 static int
-i386_stab_reg_to_regnum (int reg)
+i386_dbx_reg_to_regnum (int reg)
 {
-  /* This implements what GCC calls the "default" register map.  */
+  /* This implements what GCC calls the "default" register map
+     (dbx_register_map[]).  */
+
   if (reg >= 0 && reg <= 7)
     {
-      /* General registers.  */
-      return reg;
+      /* General-purpose registers.  The debug info calls %ebp
+         register 4, and %esp register 5.  */
+      if (reg == 4)
+        return 5;
+      else if (reg == 5)
+        return 4;
+      else return reg;
     }
   else if (reg >= 12 && reg <= 19)
     {
       /* Floating-point registers.  */
-      return reg - 12 + FP0_REGNUM;
+      return reg - 12 + I387_ST0_REGNUM;
     }
   else if (reg >= 21 && reg <= 28)
     {
       /* SSE registers.  */
-      return reg - 21 + XMM0_REGNUM;
+      return reg - 21 + I387_XMM0_REGNUM;
     }
   else if (reg >= 29 && reg <= 36)
     {
       /* MMX registers.  */
-      return reg - 29 + MM0_REGNUM;
+      return reg - 29 + I387_MM0_REGNUM;
     }
 
   /* This will hopefully provoke a warning.  */
   return NUM_REGS + NUM_PSEUDO_REGS;
 }
 
-/* Convert DWARF register number REG to the appropriate register
-   number used by GDB.  */
+/* Convert SVR4 register number REG to the appropriate register number
+   used by GDB.  */
 
 static int
-i386_dwarf_reg_to_regnum (int reg)
+i386_svr4_reg_to_regnum (int reg)
 {
-  /* The DWARF register numbering includes %eip and %eflags, and
+  /* This implements the GCC register map that tries to be compatible
+     with the SVR4 C compiler for DWARF (svr4_dbx_register_map[]).  */
+
+  /* The SVR4 register numbering includes %eip and %eflags, and
      numbers the floating point registers differently.  */
   if (reg >= 0 && reg <= 9)
     {
-      /* General registers.  */
+      /* General-purpose registers.  */
       return reg;
     }
   else if (reg >= 11 && reg <= 18)
     {
       /* Floating-point registers.  */
-      return reg - 11 + FP0_REGNUM;
+      return reg - 11 + I387_ST0_REGNUM;
     }
   else if (reg >= 21)
     {
-      /* The SSE and MMX registers have identical numbers as in stabs.  */
-      return i386_stab_reg_to_regnum (reg);
+      /* The SSE and MMX registers have the same numbers as with dbx.  */
+      return i386_dbx_reg_to_regnum (reg);
     }
 
   /* This will hopefully provoke a warning.  */
   return NUM_REGS + NUM_PSEUDO_REGS;
 }
+
+#undef I387_ST0_REGNUM
+#undef I387_MM0_REGNUM
+#undef I387_NUM_XMM_REGS
 \f
 
 /* This is the variable that is set with "set disassembly-flavor", and
@@ -197,695 +251,926 @@ static const char *valid_flavors[] =
   NULL
 };
 static const char *disassembly_flavor = att_flavor;
+\f
 
-/* Stdio style buffering was used to minimize calls to ptrace, but
-   this buffering did not take into account that the code section
-   being accessed may not be an even number of buffers long (even if
-   the buffer is only sizeof(int) long).  In cases where the code
-   section size happened to be a non-integral number of buffers long,
-   attempting to read the last buffer would fail.  Simply using
-   target_read_memory and ignoring errors, rather than read_memory, is
-   not the correct solution, since legitimate access errors would then
-   be totally ignored.  To properly handle this situation and continue
-   to use buffering would require that this code be able to determine
-   the minimum code section size granularity (not the alignment of the
-   section itself, since the actual failing case that pointed out this
-   problem had a section alignment of 4 but was not a multiple of 4
-   bytes long), on a target by target basis, and then adjust it's
-   buffer size accordingly.  This is messy, but potentially feasible.
-   It probably needs the bfd library's help and support.  For now, the
-   buffer size is set to 1.  (FIXME -fnf) */
-
-#define CODESTREAM_BUFSIZ 1    /* Was sizeof(int), see note above.  */
-static CORE_ADDR codestream_next_addr;
-static CORE_ADDR codestream_addr;
-static unsigned char codestream_buf[CODESTREAM_BUFSIZ];
-static int codestream_off;
-static int codestream_cnt;
-
-#define codestream_tell() (codestream_addr + codestream_off)
-#define codestream_peek() \
-  (codestream_cnt == 0 ? \
-   codestream_fill(1) : codestream_buf[codestream_off])
-#define codestream_get() \
-  (codestream_cnt-- == 0 ? \
-   codestream_fill(0) : codestream_buf[codestream_off++])
-
-static unsigned char
-codestream_fill (int peek_flag)
-{
-  codestream_addr = codestream_next_addr;
-  codestream_next_addr += CODESTREAM_BUFSIZ;
-  codestream_off = 0;
-  codestream_cnt = CODESTREAM_BUFSIZ;
-  read_memory (codestream_addr, (char *) codestream_buf, CODESTREAM_BUFSIZ);
-
-  if (peek_flag)
-    return (codestream_peek ());
-  else
-    return (codestream_get ());
-}
+/* Use the program counter to determine the contents and size of a
+   breakpoint instruction.  Return a pointer to a string of bytes that
+   encode a breakpoint instruction, store the length of the string in
+   *LEN and optionally adjust *PC to point to the correct memory
+   location for inserting the breakpoint.
 
-static void
-codestream_seek (CORE_ADDR place)
-{
-  codestream_next_addr = place / CODESTREAM_BUFSIZ;
-  codestream_next_addr *= CODESTREAM_BUFSIZ;
-  codestream_cnt = 0;
-  codestream_fill (1);
-  while (codestream_tell () != place)
-    codestream_get ();
-}
+   On the i386 we have a single breakpoint that fits in a single byte
+   and can be inserted anywhere.
 
-static void
-codestream_read (unsigned char *buf, int count)
+   This function is 64-bit safe.  */
+   
+static const unsigned char *
+i386_breakpoint_from_pc (CORE_ADDR *pc, int *len)
 {
-  unsigned char *p;
-  int i;
-  p = buf;
-  for (i = 0; i < count; i++)
-    *p++ = codestream_get ();
+  static unsigned char break_insn[] = { 0xcc };        /* int 3 */
+  
+  *len = sizeof (break_insn);
+  return break_insn;
 }
 \f
+#ifdef I386_REGNO_TO_SYMMETRY
+#error "The Sequent Symmetry is no longer supported."
+#endif
 
-/* If the next instruction is a jump, move to its target.  */
+/* According to the System V ABI, the registers %ebp, %ebx, %edi, %esi
+   and %esp "belong" to the calling function.  Therefore these
+   registers should be saved if they're going to be modified.  */
 
-static void
-i386_follow_jump (void)
+/* The maximum number of saved registers.  This should include all
+   registers mentioned above, and %eip.  */
+#define I386_NUM_SAVED_REGS    I386_NUM_GREGS
+
+struct i386_frame_cache
 {
-  unsigned char buf[4];
-  long delta;
+  /* Base address.  */
+  CORE_ADDR base;
+  CORE_ADDR sp_offset;
+  CORE_ADDR pc;
 
-  int data16;
-  CORE_ADDR pos;
+  /* Saved registers.  */
+  CORE_ADDR saved_regs[I386_NUM_SAVED_REGS];
+  CORE_ADDR saved_sp;
+  int pc_in_eax;
 
-  pos = codestream_tell ();
+  /* Stack space reserved for local variables.  */
+  long locals;
+};
+
+/* Allocate and initialize a frame cache.  */
+
+static struct i386_frame_cache *
+i386_alloc_frame_cache (void)
+{
+  struct i386_frame_cache *cache;
+  int i;
+
+  cache = FRAME_OBSTACK_ZALLOC (struct i386_frame_cache);
+
+  /* Base address.  */
+  cache->base = 0;
+  cache->sp_offset = -4;
+  cache->pc = 0;
+
+  /* Saved registers.  We initialize these to -1 since zero is a valid
+     offset (that's where %ebp is supposed to be stored).  */
+  for (i = 0; i < I386_NUM_SAVED_REGS; i++)
+    cache->saved_regs[i] = -1;
+  cache->saved_sp = 0;
+  cache->pc_in_eax = 0;
+
+  /* Frameless until proven otherwise.  */
+  cache->locals = -1;
+
+  return cache;
+}
+
+/* If the instruction at PC is a jump, return the address of its
+   target.  Otherwise, return PC.  */
 
-  data16 = 0;
-  if (codestream_peek () == 0x66)
+static CORE_ADDR
+i386_follow_jump (CORE_ADDR pc)
+{
+  unsigned char op;
+  long delta = 0;
+  int data16 = 0;
+
+  op = read_memory_unsigned_integer (pc, 1);
+  if (op == 0x66)
     {
-      codestream_get ();
       data16 = 1;
+      op = read_memory_unsigned_integer (pc + 1, 1);
     }
 
-  switch (codestream_get ())
+  switch (op)
     {
     case 0xe9:
       /* Relative jump: if data16 == 0, disp32, else disp16.  */
       if (data16)
        {
-         codestream_read (buf, 2);
-         delta = extract_signed_integer (buf, 2);
+         delta = read_memory_integer (pc + 2, 2);
 
          /* Include the size of the jmp instruction (including the
              0x66 prefix).  */
-         pos += delta + 4;
+         delta += 4;
        }
       else
        {
-         codestream_read (buf, 4);
-         delta = extract_signed_integer (buf, 4);
+         delta = read_memory_integer (pc + 1, 4);
 
-         pos += delta + 5;
+         /* Include the size of the jmp instruction.  */
+         delta += 5;
        }
       break;
     case 0xeb:
       /* Relative jump, disp8 (ignore data16).  */
-      codestream_read (buf, 1);
-      /* Sign-extend it.  */
-      delta = extract_signed_integer (buf, 1);
+      delta = read_memory_integer (pc + data16 + 1, 1);
 
-      pos += delta + 2;
+      delta += data16 + 2;
       break;
     }
-  codestream_seek (pos);
-}
 
-/* Find & return the amount a local space allocated, and advance the
-   codestream to the first register push (if any).
+  return pc + delta;
+}
 
-   If the entry sequence doesn't make sense, return -1, and leave
-   codestream pointer at a random spot.  */
+/* Check whether PC points at a prologue for a function returning a
+   structure or union.  If so, it updates CACHE and returns the
+   address of the first instruction after the code sequence that
+   removes the "hidden" argument from the stack or CURRENT_PC,
+   whichever is smaller.  Otherwise, return PC.  */
 
-static long
-i386_get_frame_setup (CORE_ADDR pc)
+static CORE_ADDR
+i386_analyze_struct_return (CORE_ADDR pc, CORE_ADDR current_pc,
+                           struct i386_frame_cache *cache)
 {
+  /* Functions that return a structure or union start with:
+
+        popl %eax             0x58
+        xchgl %eax, (%esp)    0x87 0x04 0x24
+     or xchgl %eax, 0(%esp)   0x87 0x44 0x24 0x00
+
+     (the System V compiler puts out the second `xchg' instruction,
+     and the assembler doesn't try to optimize it, so the 'sib' form
+     gets generated).  This sequence is used to get the address of the
+     return buffer for a function that returns a structure.  */
+  static unsigned char proto1[3] = { 0x87, 0x04, 0x24 };
+  static unsigned char proto2[4] = { 0x87, 0x44, 0x24, 0x00 };
+  unsigned char buf[4];
   unsigned char op;
 
-  codestream_seek (pc);
+  if (current_pc <= pc)
+    return pc;
+
+  op = read_memory_unsigned_integer (pc, 1);
 
-  i386_follow_jump ();
+  if (op != 0x58)              /* popl %eax */
+    return pc;
 
-  op = codestream_get ();
+  read_memory (pc + 1, buf, 4);
+  if (memcmp (buf, proto1, 3) != 0 && memcmp (buf, proto2, 4) != 0)
+    return pc;
 
-  if (op == 0x58)              /* popl %eax */
+  if (current_pc == pc)
     {
-      /* This function must start with
-
-           popl %eax             0x58
-            xchgl %eax, (%esp)    0x87 0x04 0x24
-         or xchgl %eax, 0(%esp)   0x87 0x44 0x24 0x00
-
-        (the System V compiler puts out the second `xchg'
-        instruction, and the assembler doesn't try to optimize it, so
-        the 'sib' form gets generated).  This sequence is used to get
-        the address of the return buffer for a function that returns
-        a structure.  */
-      int pos;
-      unsigned char buf[4];
-      static unsigned char proto1[3] = { 0x87, 0x04, 0x24 };
-      static unsigned char proto2[4] = { 0x87, 0x44, 0x24, 0x00 };
-
-      pos = codestream_tell ();
-      codestream_read (buf, 4);
-      if (memcmp (buf, proto1, 3) == 0)
-       pos += 3;
-      else if (memcmp (buf, proto2, 4) == 0)
-       pos += 4;
-
-      codestream_seek (pos);
-      op = codestream_get ();  /* Update next opcode.  */
+      cache->sp_offset += 4;
+      return current_pc;
     }
 
-  if (op == 0x68 || op == 0x6a)
+  if (current_pc == pc + 1)
     {
-      /* This function may start with
+      cache->pc_in_eax = 1;
+      return current_pc;
+    }
+  
+  if (buf[1] == proto1[1])
+    return pc + 4;
+  else
+    return pc + 5;
+}
+
+static CORE_ADDR
+i386_skip_probe (CORE_ADDR pc)
+{
+  /* A function may start with
 
-            pushl constant
-            call _probe
-           addl $4, %esp
+        pushl constant
+        call _probe
+       addl $4, %esp
           
-        followed by
+     followed by
+
+        pushl %ebp
 
-            pushl %ebp
+     etc.  */
+  unsigned char buf[8];
+  unsigned char op;
+
+  op = read_memory_unsigned_integer (pc, 1);
 
-        etc.  */
-      int pos;
-      unsigned char buf[8];
+  if (op == 0x68 || op == 0x6a)
+    {
+      int delta;
 
-      /* Skip past the `pushl' instruction; it has either a one-byte 
-         or a four-byte operand, depending on the opcode.  */
-      pos = codestream_tell ();
+      /* Skip past the `pushl' instruction; it has either a one-byte or a
+        four-byte operand, depending on the opcode.  */
       if (op == 0x68)
-       pos += 4;
+       delta = 5;
       else
-       pos += 1;
-      codestream_seek (pos);
+       delta = 2;
 
-      /* Read the following 8 bytes, which should be "call _probe" (6
-         bytes) followed by "addl $4,%esp" (2 bytes).  */
-      codestream_read (buf, sizeof (buf));
+      /* Read the following 8 bytes, which should be `call _probe' (6
+        bytes) followed by `addl $4,%esp' (2 bytes).  */
+      read_memory (pc + delta, buf, sizeof (buf));
       if (buf[0] == 0xe8 && buf[6] == 0xc4 && buf[7] == 0x4)
-       pos += sizeof (buf);
-      codestream_seek (pos);
-      op = codestream_get ();  /* Update next opcode.  */
+       pc += delta + sizeof (buf);
     }
 
+  return pc;
+}
+
+/* Maximum instruction length we need to handle.  */
+#define I386_MAX_INSN_LEN      6
+
+/* Instruction description.  */
+struct i386_insn
+{
+  size_t len;
+  unsigned char insn[I386_MAX_INSN_LEN];
+  unsigned char mask[I386_MAX_INSN_LEN];
+};
+
+/* Search for the instruction at PC in the list SKIP_INSNS.  Return
+   the first instruction description that matches.  Otherwise, return
+   NULL.  */
+
+static struct i386_insn *
+i386_match_insn (CORE_ADDR pc, struct i386_insn *skip_insns)
+{
+  struct i386_insn *insn;
+  unsigned char op;
+
+  op = read_memory_unsigned_integer (pc, 1);
+
+  for (insn = skip_insns; insn->len > 0; insn++)
+    {
+      if ((op & insn->mask[0]) == insn->insn[0])
+       {
+         unsigned char buf[I386_MAX_INSN_LEN - 1];
+         size_t i;
+
+         gdb_assert (insn->len > 1);
+         gdb_assert (insn->len <= I386_MAX_INSN_LEN);
+
+         read_memory (pc + 1, buf, insn->len - 1);
+         for (i = 1; i < insn->len; i++)
+           {
+             if ((buf[i - 1] & insn->mask[i]) != insn->insn[i])
+               break;
+
+             return insn;
+           }
+       }
+    }
+
+  return NULL;
+}
+
+/* Some special instructions that might be migrated by GCC into the
+   part of the prologue that sets up the new stack frame.  Because the
+   stack frame hasn't been setup yet, no registers have been saved
+   yet, and only the scratch registers %eax, %ecx and %edx can be
+   touched.  */
+
+struct i386_insn i386_frame_setup_skip_insns[] =
+{
+  /* Check for `movb imm8, r' and `movl imm32, r'. 
+    
+     ??? Should we handle 16-bit operand-sizes here?  */
+
+  /* `movb imm8, %al' and `movb imm8, %ah' */
+  /* `movb imm8, %cl' and `movb imm8, %ch' */
+  { 2, { 0xb0, 0x00 }, { 0xfa, 0x00 } },
+  /* `movb imm8, %dl' and `movb imm8, %dh' */
+  { 2, { 0xb2, 0x00 }, { 0xfb, 0x00 } },
+  /* `movl imm32, %eax' and `movl imm32, %ecx' */
+  { 5, { 0xb8 }, { 0xfe } },
+  /* `movl imm32, %edx' */
+  { 5, { 0xba }, { 0xff } },
+
+  /* Check for `mov imm32, r32'.  Note that there is an alternative
+     encoding for `mov m32, %eax'.
+
+     ??? Should we handle SIB adressing here?
+     ??? Should we handle 16-bit operand-sizes here?  */
+
+  /* `movl m32, %eax' */
+  { 5, { 0xa1 }, { 0xff } },
+  /* `movl m32, %eax' and `mov; m32, %ecx' */
+  { 6, { 0x89, 0x05 }, {0xff, 0xf7 } },
+  /* `movl m32, %edx' */
+  { 6, { 0x89, 0x15 }, {0xff, 0xff } },
+
+  /* Check for `xorl r32, r32' and the equivalent `subl r32, r32'.
+     Because of the symmetry, there are actually two ways to encode
+     these instructions; opcode bytes 0x29 and 0x2b for `subl' and
+     opcode bytes 0x31 and 0x33 for `xorl'.  */
+
+  /* `subl %eax, %eax' */
+  { 2, { 0x29, 0xc0 }, { 0xfd, 0xff } },
+  /* `subl %ecx, %ecx' */
+  { 2, { 0x29, 0xc9 }, { 0xfd, 0xff } },
+  /* `subl %edx, %edx' */
+  { 2, { 0x29, 0xd2 }, { 0xfd, 0xff } },
+  /* `xorl %eax, %eax' */
+  { 2, { 0x31, 0xc0 }, { 0xfd, 0xff } },
+  /* `xorl %ecx, %ecx' */
+  { 2, { 0x31, 0xc9 }, { 0xfd, 0xff } },
+  /* `xorl %edx, %edx' */
+  { 2, { 0x31, 0xd2 }, { 0xfd, 0xff } },
+  { 0 }
+};
+
+/* Check whether PC points at a code that sets up a new stack frame.
+   If so, it updates CACHE and returns the address of the first
+   instruction after the sequence that sets up the frame or LIMIT,
+   whichever is smaller.  If we don't recognize the code, return PC.  */
+
+static CORE_ADDR
+i386_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR limit,
+                         struct i386_frame_cache *cache)
+{
+  struct i386_insn *insn;
+  unsigned char op;
+  int skip = 0;
+
+  if (limit <= pc)
+    return limit;
+
+  op = read_memory_unsigned_integer (pc, 1);
+
   if (op == 0x55)              /* pushl %ebp */
     {
-      /* Check for "movl %esp, %ebp" -- can be written in two ways.  */
-      switch (codestream_get ())
+      /* Take into account that we've executed the `pushl %ebp' that
+        starts this instruction sequence.  */
+      cache->saved_regs[I386_EBP_REGNUM] = 0;
+      cache->sp_offset += 4;
+      pc++;
+
+      /* If that's all, return now.  */
+      if (limit <= pc)
+       return limit;
+
+      /* Check for some special instructions that might be migrated by
+        GCC into the prologue and skip them.  At this point in the
+        prologue, code should only touch the scratch registers %eax,
+        %ecx and %edx, so while the number of posibilities is sheer,
+        it is limited.
+
+        Make sure we only skip these instructions if we later see the
+        `movl %esp, %ebp' that actually sets up the frame.  */
+      while (pc + skip < limit)
+       {
+         insn = i386_match_insn (pc + skip, i386_frame_setup_skip_insns);
+         if (insn == NULL)
+           break;
+
+         skip += insn->len;
+       }
+
+      /* If that's all, return now.  */
+      if (limit <= pc + skip)
+       return limit;
+
+      op = read_memory_unsigned_integer (pc + skip, 1);
+
+      /* Check for `movl %esp, %ebp' -- can be written in two ways.  */
+      switch (op)
        {
        case 0x8b:
-         if (codestream_get () != 0xec)
-           return -1;
+         if (read_memory_unsigned_integer (pc + skip + 1, 1) != 0xec)
+           return pc;
          break;
        case 0x89:
-         if (codestream_get () != 0xe5)
-           return -1;
+         if (read_memory_unsigned_integer (pc + skip + 1, 1) != 0xe5)
+           return pc;
          break;
        default:
-         return -1;
+         return pc;
        }
+
+      /* OK, we actually have a frame.  We just don't know how large
+        it is yet.  Set its size to zero.  We'll adjust it if
+        necessary.  We also now commit to skipping the special
+        instructions mentioned before.  */
+      cache->locals = 0;
+      pc += (skip + 2);
+
+      /* If that's all, return now.  */
+      if (limit <= pc)
+       return limit;
+
       /* Check for stack adjustment 
 
-           subl $XXX, %esp
+           subl $XXX, %esp
 
-        NOTE: You can't subtract a 16 bit immediate from a 32 bit
+        NOTE: You can't subtract a 16-bit immediate from a 32-bit
         reg, so we don't have to worry about a data16 prefix.  */
-      op = codestream_peek ();
+      op = read_memory_unsigned_integer (pc, 1);
       if (op == 0x83)
        {
-         /* `subl' with 8 bit immediate.  */
-         codestream_get ();
-         if (codestream_get () != 0xec)
+         /* `subl' with 8-bit immediate.  */
+         if (read_memory_unsigned_integer (pc + 1, 1) != 0xec)
            /* Some instruction starting with 0x83 other than `subl'.  */
-           {
-             codestream_seek (codestream_tell () - 2);
-             return 0;
-           }
-         /* `subl' with signed byte immediate (though it wouldn't
+           return pc;
+
+         /* `subl' with signed 8-bit immediate (though it wouldn't
             make sense to be negative).  */
-         return (codestream_get ());
+         cache->locals = read_memory_integer (pc + 2, 1);
+         return pc + 3;
        }
       else if (op == 0x81)
        {
-         char buf[4];
-         /* Maybe it is `subl' with a 32 bit immedediate.  */
-         codestream_get ();
-         if (codestream_get () != 0xec)
+         /* Maybe it is `subl' with a 32-bit immediate.  */
+         if (read_memory_unsigned_integer (pc + 1, 1) != 0xec)
            /* Some instruction starting with 0x81 other than `subl'.  */
-           {
-             codestream_seek (codestream_tell () - 2);
-             return 0;
-           }
-         /* It is `subl' with a 32 bit immediate.  */
-         codestream_read ((unsigned char *) buf, 4);
-         return extract_signed_integer (buf, 4);
+           return pc;
+
+         /* It is `subl' with a 32-bit immediate.  */
+         cache->locals = read_memory_integer (pc + 2, 4);
+         return pc + 6;
        }
       else
        {
-         return 0;
+         /* Some instruction other than `subl'.  */
+         return pc;
        }
     }
-  else if (op == 0xc8)
+  else if (op == 0xc8)         /* enter */
     {
-      char buf[2];
-      /* `enter' with 16 bit unsigned immediate.  */
-      codestream_read ((unsigned char *) buf, 2);
-      codestream_get ();       /* Flush final byte of enter instruction.  */
-      return extract_unsigned_integer (buf, 2);
+      cache->locals = read_memory_unsigned_integer (pc + 1, 2);
+      return pc + 4;
     }
-  return (-1);
-}
-
-/* Signal trampolines don't have a meaningful frame.  The frame
-   pointer value we use is actually the frame pointer of the calling
-   frame -- that is, the frame which was in progress when the signal
-   trampoline was entered.  GDB mostly treats this frame pointer value
-   as a magic cookie.  We detect the case of a signal trampoline by
-   testing for get_frame_type() == SIGTRAMP_FRAME, which is set based
-   on PC_IN_SIGTRAMP.
-
-   When a signal trampoline is invoked from a frameless function, we
-   essentially have two frameless functions in a row.  In this case,
-   we use the same magic cookie for three frames in a row.  We detect
-   this case by seeing whether the next frame is a SIGTRAMP_FRAME,
-   and, if it does, checking whether the current frame is actually
-   frameless.  In this case, we need to get the PC by looking at the
-   SP register value stored in the signal context.
-
-   This should work in most cases except in horrible situations where
-   a signal occurs just as we enter a function but before the frame
-   has been set up.  Incidentally, that's just what happens when we
-   call a function from GDB with a signal pending (there's a test in
-   the testsuite that makes this happen).  Therefore we pretend that
-   we have a frameless function if we're stopped at the start of a
-   function.  */
-
-/* Return non-zero if we're dealing with a frameless signal, that is,
-   a signal trampoline invoked from a frameless function.  */
 
-int
-i386_frameless_signal_p (struct frame_info *frame)
-{
-  return (get_next_frame (frame)
-         && get_frame_type (get_next_frame (frame)) == SIGTRAMP_FRAME
-         && (frameless_look_for_prologue (frame)
-             || get_frame_pc (frame) == get_pc_function_start (get_frame_pc (frame))));
+  return pc;
 }
 
-/* Return the chain-pointer for FRAME.  In the case of the i386, the
-   frame's nominal address is the address of a 4-byte word containing
-   the calling frame's address.  */
+/* Check whether PC points at code that saves registers on the stack.
+   If so, it updates CACHE and returns the address of the first
+   instruction after the register saves or CURRENT_PC, whichever is
+   smaller.  Otherwise, return PC.  */
 
 static CORE_ADDR
-i386_frame_chain (struct frame_info *frame)
+i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
+                            struct i386_frame_cache *cache)
 {
-  if (pc_in_dummy_frame (get_frame_pc (frame)))
-    return get_frame_base (frame);
+  CORE_ADDR offset = 0;
+  unsigned char op;
+  int i;
 
-  if (get_frame_type (frame) == SIGTRAMP_FRAME
-      || i386_frameless_signal_p (frame))
-    return get_frame_base (frame);
+  if (cache->locals > 0)
+    offset -= cache->locals;
+  for (i = 0; i < 8 && pc < current_pc; i++)
+    {
+      op = read_memory_unsigned_integer (pc, 1);
+      if (op < 0x50 || op > 0x57)
+       break;
 
-  if (! inside_entry_file (get_frame_pc (frame)))
-    return read_memory_unsigned_integer (get_frame_base (frame), 4);
+      offset -= 4;
+      cache->saved_regs[op - 0x50] = offset;
+      cache->sp_offset += 4;
+      pc++;
+    }
 
-  return 0;
+  return pc;
 }
 
-/* Determine whether the function invocation represented by FRAME does
-   not have a from on the stack associated with it.  If it does not,
-   return non-zero, otherwise return zero.  */
+/* Do a full analysis of the prologue at PC and update CACHE
+   accordingly.  Bail out early if CURRENT_PC is reached.  Return the
+   address where the analysis stopped.
 
-static int
-i386_frameless_function_invocation (struct frame_info *frame)
-{
-  if (get_frame_type (frame) == SIGTRAMP_FRAME)
-    return 0;
+   We handle these cases:
 
-  return frameless_look_for_prologue (frame);
-}
+   The startup sequence can be at the start of the function, or the
+   function can start with a branch to startup code at the end.
+
+   %ebp can be set up with either the 'enter' instruction, or "pushl
+   %ebp, movl %esp, %ebp" (`enter' is too slow to be useful, but was
+   once used in the System V compiler).
+
+   Local space is allocated just below the saved %ebp by either the
+   'enter' instruction, or by "subl $<size>, %esp".  'enter' has a
+   16-bit unsigned argument for space to allocate, and the 'addl'
+   instruction could have either a signed byte, or 32-bit immediate.
 
-/* Assuming FRAME is for a sigtramp routine, return the saved program
-   counter.  */
+   Next, the registers used by this function are pushed.  With the
+   System V compiler they will always be in the order: %edi, %esi,
+   %ebx (and sometimes a harmless bug causes it to also save but not
+   restore %eax); however, the code below is willing to see the pushes
+   in any order, and will handle up to 8 of them.
+   If the setup sequence is at the end of the function, then the next
+   instruction will be a branch back to the start.  */
 
 static CORE_ADDR
-i386_sigtramp_saved_pc (struct frame_info *frame)
+i386_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
+                      struct i386_frame_cache *cache)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  CORE_ADDR addr;
-
-  addr = tdep->sigcontext_addr (frame);
-  return read_memory_unsigned_integer (addr + tdep->sc_pc_offset, 4);
+  pc = i386_follow_jump (pc);
+  pc = i386_analyze_struct_return (pc, current_pc, cache);
+  pc = i386_skip_probe (pc);
+  pc = i386_analyze_frame_setup (pc, current_pc, cache);
+  return i386_analyze_register_saves (pc, current_pc, cache);
 }
 
-/* Assuming FRAME is for a sigtramp routine, return the saved stack
-   pointer.  */
+/* Return PC of first real instruction.  */
 
 static CORE_ADDR
-i386_sigtramp_saved_sp (struct frame_info *frame)
+i386_skip_prologue (CORE_ADDR start_pc)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  CORE_ADDR addr;
+  static unsigned char pic_pat[6] =
+  {
+    0xe8, 0, 0, 0, 0,          /* call 0x0 */
+    0x5b,                      /* popl %ebx */
+  };
+  struct i386_frame_cache cache;
+  CORE_ADDR pc;
+  unsigned char op;
+  int i;
 
-  addr = tdep->sigcontext_addr (frame);
-  return read_memory_unsigned_integer (addr + tdep->sc_sp_offset, 4);
-}
+  cache.locals = -1;
+  pc = i386_analyze_prologue (start_pc, 0xffffffff, &cache);
+  if (cache.locals < 0)
+    return start_pc;
 
-/* Return the saved program counter for FRAME.  */
+  /* Found valid frame setup.  */
 
-static CORE_ADDR
-i386_frame_saved_pc (struct frame_info *frame)
-{
-  if (pc_in_dummy_frame (get_frame_pc (frame)))
-    {
-      ULONGEST pc;
+  /* The native cc on SVR4 in -K PIC mode inserts the following code
+     to get the address of the global offset table (GOT) into register
+     %ebx:
 
-      frame_unwind_unsigned_register (frame, PC_REGNUM, &pc);
-      return pc;
-    }
+        call   0x0
+       popl    %ebx
+        movl    %ebx,x(%ebp)    (optional)
+        addl    y,%ebx
 
-  if (get_frame_type (frame) == SIGTRAMP_FRAME)
-    return i386_sigtramp_saved_pc (frame);
+     This code is with the rest of the prologue (at the end of the
+     function), so we have to skip it to get to the first real
+     instruction at the start of the function.  */
 
-  if (i386_frameless_signal_p (frame))
+  for (i = 0; i < 6; i++)
     {
-      CORE_ADDR sp = i386_sigtramp_saved_sp (get_next_frame (frame));
-      return read_memory_unsigned_integer (sp, 4);
+      op = read_memory_unsigned_integer (pc + i, 1);
+      if (pic_pat[i] != op)
+       break;
     }
+  if (i == 6)
+    {
+      int delta = 6;
+
+      op = read_memory_unsigned_integer (pc + delta, 1);
+
+      if (op == 0x89)          /* movl %ebx, x(%ebp) */
+       {
+         op = read_memory_unsigned_integer (pc + delta + 1, 1);
+
+         if (op == 0x5d)       /* One byte offset from %ebp.  */
+           delta += 3;
+         else if (op == 0x9d)  /* Four byte offset from %ebp.  */
+           delta += 6;
+         else                  /* Unexpected instruction.  */
+           delta = 0;
 
-  return read_memory_unsigned_integer (get_frame_base (frame) + 4, 4);
+         op = read_memory_unsigned_integer (pc + delta, 1);
+       }
+
+      /* addl y,%ebx */
+      if (delta > 0 && op == 0x81
+         && read_memory_unsigned_integer (pc + delta + 1, 1) == 0xc3);
+       {
+         pc += delta + 6;
+       }
+    }
+
+  /* If the function starts with a branch (to startup code at the end)
+     the last instruction should bring us back to the first
+     instruction of the real code.  */
+  if (i386_follow_jump (start_pc) != start_pc)
+    pc = i386_follow_jump (pc);
+
+  return pc;
 }
 
-/* Immediately after a function call, return the saved pc.  */
+/* This function is 64-bit safe.  */
 
 static CORE_ADDR
-i386_saved_pc_after_call (struct frame_info *frame)
+i386_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  if (get_frame_type (frame) == SIGTRAMP_FRAME)
-    return i386_sigtramp_saved_pc (frame);
+  char buf[8];
 
-  return read_memory_unsigned_integer (read_register (SP_REGNUM), 4);
+  frame_unwind_register (next_frame, PC_REGNUM, buf);
+  return extract_typed_address (buf, builtin_type_void_func_ptr);
 }
+\f
 
-/* Return number of args passed to a frame.
-   Can return -1, meaning no way to tell.  */
+/* Normal frames.  */
 
-static int
-i386_frame_num_args (struct frame_info *fi)
+static struct i386_frame_cache *
+i386_frame_cache (struct frame_info *next_frame, void **this_cache)
 {
-#if 1
-  return -1;
-#else
-  /* This loses because not only might the compiler not be popping the
-     args right after the function call, it might be popping args from
-     both this call and a previous one, and we would say there are
-     more args than there really are.  */
+  struct i386_frame_cache *cache;
+  char buf[4];
+  int i;
 
-  int retpc;
-  unsigned char op;
-  struct frame_info *pfi;
+  if (*this_cache)
+    return *this_cache;
 
-  /* On the i386, the instruction following the call could be:
-     popl %ecx        -  one arg
-     addl $imm, %esp  -  imm/4 args; imm may be 8 or 32 bits
-     anything else    -  zero args.  */
+  cache = i386_alloc_frame_cache ();
+  *this_cache = cache;
 
-  int frameless;
+  /* In principle, for normal frames, %ebp holds the frame pointer,
+     which holds the base address for the current stack frame.
+     However, for functions that don't need it, the frame pointer is
+     optional.  For these "frameless" functions the frame pointer is
+     actually the frame pointer of the calling frame.  Signal
+     trampolines are just a special case of a "frameless" function.
+     They (usually) share their frame pointer with the frame that was
+     in progress when the signal occurred.  */
 
-  frameless = FRAMELESS_FUNCTION_INVOCATION (fi);
-  if (frameless)
-    /* In the absence of a frame pointer, GDB doesn't get correct
-       values for nameless arguments.  Return -1, so it doesn't print
-       any nameless arguments.  */
-    return -1;
+  frame_unwind_register (next_frame, I386_EBP_REGNUM, buf);
+  cache->base = extract_unsigned_integer (buf, 4);
+  if (cache->base == 0)
+    return cache;
 
-  pfi = get_prev_frame (fi);
-  if (pfi == 0)
-    {
-      /* NOTE: This can happen if we are looking at the frame for
-         main, because DEPRECATED_FRAME_CHAIN_VALID won't let us go
-         into start.  If we have debugging symbols, that's not really
-         a big deal; it just means it will only show as many arguments
-         to main as are declared.  */
-      return -1;
-    }
-  else
-    {
-      retpc = pfi->pc;
-      op = read_memory_integer (retpc, 1);
-      if (op == 0x59)          /* pop %ecx */
-       return 1;
-      else if (op == 0x83)
-       {
-         op = read_memory_integer (retpc + 1, 1);
-         if (op == 0xc4)
-           /* addl $<signed imm 8 bits>, %esp */
-           return (read_memory_integer (retpc + 2, 1) & 0xff) / 4;
-         else
-           return 0;
-       }
-      else if (op == 0x81)     /* `add' with 32 bit immediate.  */
-       {
-         op = read_memory_integer (retpc + 1, 1);
-         if (op == 0xc4)
-           /* addl $<imm 32>, %esp */
-           return read_memory_integer (retpc + 2, 4) / 4;
-         else
-           return 0;
-       }
-      else
-       {
-         return 0;
-       }
-    }
-#endif
-}
+  /* For normal frames, %eip is stored at 4(%ebp).  */
+  cache->saved_regs[I386_EIP_REGNUM] = 4;
 
-/* Parse the first few instructions the function to see what registers
-   were stored.
-   
-   We handle these cases:
+  cache->pc = frame_func_unwind (next_frame);
+  if (cache->pc != 0)
+    i386_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache);
 
-   The startup sequence can be at the start of the function, or the
-   function can start with a branch to startup code at the end.
+  if (cache->locals < 0)
+    {
+      /* We didn't find a valid frame, which means that CACHE->base
+        currently holds the frame pointer for our calling frame.  If
+        we're at the start of a function, or somewhere half-way its
+        prologue, the function's frame probably hasn't been fully
+        setup yet.  Try to reconstruct the base address for the stack
+        frame by looking at the stack pointer.  For truly "frameless"
+        functions this might work too.  */
+
+      frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
+      cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset;
+    }
 
-   %ebp can be set up with either the 'enter' instruction, or "pushl
-   %ebp, movl %esp, %ebp" (`enter' is too slow to be useful, but was
-   once used in the System V compiler).
+  /* Now that we have the base address for the stack frame we can
+     calculate the value of %esp in the calling frame.  */
+  cache->saved_sp = cache->base + 8;
 
-   Local space is allocated just below the saved %ebp by either the
-   'enter' instruction, or by "subl $<size>, %esp".  'enter' has a 16
-   bit unsigned argument for space to allocate, and the 'addl'
-   instruction could have either a signed byte, or 32 bit immediate.
+  /* Adjust all the saved registers such that they contain addresses
+     instead of offsets.  */
+  for (i = 0; i < I386_NUM_SAVED_REGS; i++)
+    if (cache->saved_regs[i] != -1)
+      cache->saved_regs[i] += cache->base;
 
-   Next, the registers used by this function are pushed.  With the
-   System V compiler they will always be in the order: %edi, %esi,
-   %ebx (and sometimes a harmless bug causes it to also save but not
-   restore %eax); however, the code below is willing to see the pushes
-   in any order, and will handle up to 8 of them.
-   If the setup sequence is at the end of the function, then the next
-   instruction will be a branch back to the start.  */
+  return cache;
+}
 
 static void
-i386_frame_init_saved_regs (struct frame_info *fip)
+i386_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                   struct frame_id *this_id)
 {
-  long locals = -1;
-  unsigned char op;
-  CORE_ADDR addr;
-  CORE_ADDR pc;
-  int i;
+  struct i386_frame_cache *cache = i386_frame_cache (next_frame, this_cache);
 
-  if (get_frame_saved_regs (fip))
+  /* This marks the outermost frame.  */
+  if (cache->base == 0)
     return;
 
-  frame_saved_regs_zalloc (fip);
+  /* See the end of i386_push_dummy_call.  */
+  (*this_id) = frame_id_build (cache->base + 8, cache->pc);
+}
 
-  pc = get_pc_function_start (get_frame_pc (fip));
-  if (pc != 0)
-    locals = i386_get_frame_setup (pc);
+static void
+i386_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+                         int regnum, int *optimizedp,
+                         enum lval_type *lvalp, CORE_ADDR *addrp,
+                         int *realnump, void *valuep)
+{
+  struct i386_frame_cache *cache = i386_frame_cache (next_frame, this_cache);
 
-  if (locals >= 0)
-    {
-      addr = get_frame_base (fip) - 4 - locals;
-      for (i = 0; i < 8; i++)
-       {
-         op = codestream_get ();
-         if (op < 0x50 || op > 0x57)
-           break;
-#ifdef I386_REGNO_TO_SYMMETRY
-         /* Dynix uses different internal numbering.  Ick.  */
-         get_frame_saved_regs (fip)[I386_REGNO_TO_SYMMETRY (op - 0x50)] = addr;
-#else
-         get_frame_saved_regs (fip)[op - 0x50] = addr;
-#endif
-         addr -= 4;
-       }
-    }
+  gdb_assert (regnum >= 0);
 
-  get_frame_saved_regs (fip)[PC_REGNUM] = get_frame_base (fip) + 4;
-  get_frame_saved_regs (fip)[FP_REGNUM] = get_frame_base (fip);
-}
+  /* The System V ABI says that:
 
-/* Return PC of first real instruction.  */
+     "The flags register contains the system flags, such as the
+     direction flag and the carry flag.  The direction flag must be
+     set to the forward (that is, zero) direction before entry and
+     upon exit from a function.  Other user flags have no specified
+     role in the standard calling sequence and are not preserved."
 
-static CORE_ADDR
-i386_skip_prologue (CORE_ADDR pc)
-{
-  unsigned char op;
-  int i;
-  static unsigned char pic_pat[6] =
-  { 0xe8, 0, 0, 0, 0,          /* call   0x0 */
-    0x5b,                      /* popl   %ebx */
-  };
-  CORE_ADDR pos;
+     To guarantee the "upon exit" part of that statement we fake a
+     saved flags register that has its direction flag cleared.
 
-  if (i386_get_frame_setup (pc) < 0)
-    return (pc);
+     Note that GCC doesn't seem to rely on the fact that the direction
+     flag is cleared after a function return; it always explicitly
+     clears the flag before operations where it matters.
 
-  /* Found valid frame setup -- codestream now points to start of push
-     instructions for saving registers.  */
+     FIXME: kettenis/20030316: I'm not quite sure whether this is the
+     right thing to do.  The way we fake the flags register here makes
+     it impossible to change it.  */
 
-  /* Skip over register saves.  */
-  for (i = 0; i < 8; i++)
+  if (regnum == I386_EFLAGS_REGNUM)
     {
-      op = codestream_peek ();
-      /* Break if not `pushl' instrunction.  */
-      if (op < 0x50 || op > 0x57)
-       break;
-      codestream_get ();
-    }
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (valuep)
+       {
+         ULONGEST val;
 
-  /* The native cc on SVR4 in -K PIC mode inserts the following code
-     to get the address of the global offset table (GOT) into register
-     %ebx
-     
-        call   0x0
-       popl    %ebx
-        movl    %ebx,x(%ebp)    (optional)
-        addl    y,%ebx
+         /* Clear the direction flag.  */
+         val = frame_unwind_register_unsigned (next_frame,
+                                               I386_EFLAGS_REGNUM);
+         val &= ~(1 << 10);
+         store_unsigned_integer (valuep, 4, val);
+       }
 
-     This code is with the rest of the prologue (at the end of the
-     function), so we have to skip it to get to the first real
-     instruction at the start of the function.  */
+      return;
+    }
 
-  pos = codestream_tell ();
-  for (i = 0; i < 6; i++)
+  if (regnum == I386_EIP_REGNUM && cache->pc_in_eax)
     {
-      op = codestream_get ();
-      if (pic_pat[i] != op)
-       break;
+      *optimizedp = 0;
+      *lvalp = lval_register;
+      *addrp = 0;
+      *realnump = I386_EAX_REGNUM;
+      if (valuep)
+       frame_unwind_register (next_frame, (*realnump), valuep);
+      return;
     }
-  if (i == 6)
-    {
-      unsigned char buf[4];
-      long delta = 6;
 
-      op = codestream_get ();
-      if (op == 0x89)          /* movl %ebx, x(%ebp) */
+  if (regnum == I386_ESP_REGNUM && cache->saved_sp)
+    {
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (valuep)
        {
-         op = codestream_get ();
-         if (op == 0x5d)       /* One byte offset from %ebp.  */
-           {
-             delta += 3;
-             codestream_read (buf, 1);
-           }
-         else if (op == 0x9d)  /* Four byte offset from %ebp.  */
-           {
-             delta += 6;
-             codestream_read (buf, 4);
-           }
-         else                  /* Unexpected instruction.  */
-           delta = -1;
-         op = codestream_get ();
+         /* Store the value.  */
+         store_unsigned_integer (valuep, 4, cache->saved_sp);
        }
-      /* addl y,%ebx */
-      if (delta > 0 && op == 0x81 && codestream_get () == 0xc3)
+      return;
+    }
+
+  if (regnum < I386_NUM_SAVED_REGS && cache->saved_regs[regnum] != -1)
+    {
+      *optimizedp = 0;
+      *lvalp = lval_memory;
+      *addrp = cache->saved_regs[regnum];
+      *realnump = -1;
+      if (valuep)
        {
-         pos += delta + 6;
+         /* Read the value in from memory.  */
+         read_memory (*addrp, valuep,
+                      register_size (current_gdbarch, regnum));
        }
+      return;
     }
-  codestream_seek (pos);
 
-  i386_follow_jump ();
+  *optimizedp = 0;
+  *lvalp = lval_register;
+  *addrp = 0;
+  *realnump = regnum;
+  if (valuep)
+    frame_unwind_register (next_frame, (*realnump), valuep);
+}
+
+static const struct frame_unwind i386_frame_unwind =
+{
+  NORMAL_FRAME,
+  i386_frame_this_id,
+  i386_frame_prev_register
+};
+
+static const struct frame_unwind *
+i386_frame_sniffer (struct frame_info *next_frame)
+{
+  return &i386_frame_unwind;
+}
+\f
+
+/* Signal trampolines.  */
+
+static struct i386_frame_cache *
+i386_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  struct i386_frame_cache *cache;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  CORE_ADDR addr;
+  char buf[4];
+
+  if (*this_cache)
+    return *this_cache;
+
+  cache = i386_alloc_frame_cache ();
+
+  frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
+  cache->base = extract_unsigned_integer (buf, 4) - 4;
+
+  addr = tdep->sigcontext_addr (next_frame);
+  if (tdep->sc_reg_offset)
+    {
+      int i;
 
-  return (codestream_tell ());
-}
+      gdb_assert (tdep->sc_num_regs <= I386_NUM_SAVED_REGS);
 
-/* Use the program counter to determine the contents and size of a
-   breakpoint instruction.  Return a pointer to a string of bytes that
-   encode a breakpoint instruction, store the length of the string in
-   *LEN and optionally adjust *PC to point to the correct memory
-   location for inserting the breakpoint.
+      for (i = 0; i < tdep->sc_num_regs; i++)
+       if (tdep->sc_reg_offset[i] != -1)
+         cache->saved_regs[i] = addr + tdep->sc_reg_offset[i];
+    }
+  else
+    {
+      cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset;
+      cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset;
+    }
 
-   On the i386 we have a single breakpoint that fits in a single byte
-   and can be inserted anywhere.  */
-   
-static const unsigned char *
-i386_breakpoint_from_pc (CORE_ADDR *pc, int *len)
-{
-  static unsigned char break_insn[] = { 0xcc };        /* int 3 */
-  
-  *len = sizeof (break_insn);
-  return break_insn;
+  *this_cache = cache;
+  return cache;
 }
 
-/* Push the return address (pointing to the call dummy) onto the stack
-   and return the new value for the stack pointer.  */
-
-static CORE_ADDR
-i386_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
+static void
+i386_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                            struct frame_id *this_id)
 {
-  char buf[4];
+  struct i386_frame_cache *cache =
+    i386_sigtramp_frame_cache (next_frame, this_cache);
 
-  store_unsigned_integer (buf, 4, CALL_DUMMY_ADDRESS ());
-  write_memory (sp - 4, buf, 4);
-  return sp - 4;
+  /* See the end of i386_push_dummy_call.  */
+  (*this_id) = frame_id_build (cache->base + 8, frame_pc_unwind (next_frame));
 }
 
 static void
-i386_do_pop_frame (struct frame_info *frame)
+i386_sigtramp_frame_prev_register (struct frame_info *next_frame,
+                                  void **this_cache,
+                                  int regnum, int *optimizedp,
+                                  enum lval_type *lvalp, CORE_ADDR *addrp,
+                                  int *realnump, void *valuep)
 {
-  CORE_ADDR fp;
-  int regnum;
-  char regbuf[I386_MAX_REGISTER_SIZE];
+  /* Make sure we've initialized the cache.  */
+  i386_sigtramp_frame_cache (next_frame, this_cache);
+
+  i386_frame_prev_register (next_frame, this_cache, regnum,
+                           optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind i386_sigtramp_frame_unwind =
+{
+  SIGTRAMP_FRAME,
+  i386_sigtramp_frame_this_id,
+  i386_sigtramp_frame_prev_register
+};
+
+static const struct frame_unwind *
+i386_sigtramp_frame_sniffer (struct frame_info *next_frame)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame));
 
-  fp = get_frame_base (frame);
-  i386_frame_init_saved_regs (frame);
+  /* We shouldn't even bother if we don't have a sigcontext_addr
+     handler.  */
+  if (tdep->sigcontext_addr == NULL)
+    return NULL;
 
-  for (regnum = 0; regnum < NUM_REGS; regnum++)
+  if (tdep->sigtramp_p != NULL)
     {
-      CORE_ADDR addr;
-      addr = get_frame_saved_regs (frame)[regnum];
-      if (addr)
-       {
-         read_memory (addr, regbuf, REGISTER_RAW_SIZE (regnum));
-         deprecated_write_register_gen (regnum, regbuf);
-       }
+      if (tdep->sigtramp_p (next_frame))
+       return &i386_sigtramp_frame_unwind;
+    }
+
+  if (tdep->sigtramp_start != 0)
+    {
+      CORE_ADDR pc = frame_pc_unwind (next_frame);
+
+      gdb_assert (tdep->sigtramp_end != 0);
+      if (pc >= tdep->sigtramp_start && pc < tdep->sigtramp_end)
+       return &i386_sigtramp_frame_unwind;
     }
-  write_register (FP_REGNUM, read_memory_integer (fp, 4));
-  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
-  write_register (SP_REGNUM, fp + 8);
-  flush_cached_frames ();
+
+  return NULL;
 }
+\f
 
-static void
-i386_pop_frame (void)
+static CORE_ADDR
+i386_frame_base_address (struct frame_info *next_frame, void **this_cache)
+{
+  struct i386_frame_cache *cache = i386_frame_cache (next_frame, this_cache);
+
+  return cache->base;
+}
+
+static const struct frame_base i386_frame_base =
+{
+  &i386_frame_unwind,
+  i386_frame_base_address,
+  i386_frame_base_address,
+  i386_frame_base_address
+};
+
+static struct frame_id
+i386_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  generic_pop_current_frame (i386_do_pop_frame);
+  char buf[4];
+  CORE_ADDR fp;
+
+  frame_unwind_register (next_frame, I386_EBP_REGNUM, buf);
+  fp = extract_unsigned_integer (buf, 4);
+
+  /* See the end of i386_push_dummy_call.  */
+  return frame_id_build (fp + 8, frame_pc_unwind (next_frame));
 }
 \f
 
@@ -893,7 +1178,9 @@ i386_pop_frame (void)
    stack.  We expect the first arg to be a pointer to the jmp_buf
    structure from which we extract the address that we will land at.
    This address is copied into PC.  This routine returns non-zero on
-   success.  */
+   success.
+
+   This function is 64-bit safe.  */
 
 static int
 i386_get_longjmp_target (CORE_ADDR *pc)
@@ -901,78 +1188,106 @@ i386_get_longjmp_target (CORE_ADDR *pc)
   char buf[8];
   CORE_ADDR sp, jb_addr;
   int jb_pc_offset = gdbarch_tdep (current_gdbarch)->jb_pc_offset;
-  int len = TARGET_PTR_BIT / TARGET_CHAR_BIT;
+  int len = TYPE_LENGTH (builtin_type_void_func_ptr);
 
   /* If JB_PC_OFFSET is -1, we have no way to find out where the
      longjmp will land.  */
   if (jb_pc_offset == -1)
     return 0;
 
-  sp = read_register (SP_REGNUM);
+  /* Don't use I386_ESP_REGNUM here, since this function is also used
+     for AMD64.  */
+  regcache_cooked_read (current_regcache, SP_REGNUM, buf);
+  sp = extract_typed_address (buf, builtin_type_void_data_ptr);
   if (target_read_memory (sp + len, buf, len))
     return 0;
 
-  jb_addr = extract_address (buf, len);
+  jb_addr = extract_typed_address (buf, builtin_type_void_data_ptr);
   if (target_read_memory (jb_addr + jb_pc_offset, buf, len))
     return 0;
 
-  *pc = extract_address (buf, len);
+  *pc = extract_typed_address (buf, builtin_type_void_func_ptr);
   return 1;
 }
 \f
 
 static CORE_ADDR
-i386_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
-                    int struct_return, CORE_ADDR struct_addr)
+i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+                     struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
+                     struct value **args, CORE_ADDR sp, int struct_return,
+                     CORE_ADDR struct_addr)
 {
-  sp = default_push_arguments (nargs, args, sp, struct_return, struct_addr);
-  
-  if (struct_return)
+  char buf[4];
+  int i;
+
+  /* Push arguments in reverse order.  */
+  for (i = nargs - 1; i >= 0; i--)
     {
-      char buf[4];
+      int len = TYPE_LENGTH (value_enclosing_type (args[i]));
+
+      /* The System V ABI says that:
+
+        "An argument's size is increased, if necessary, to make it a
+        multiple of [32-bit] words.  This may require tail padding,
+        depending on the size of the argument."
+
+        This makes sure the stack says word-aligned.  */
+      sp -= (len + 3) & ~3;
+      write_memory (sp, VALUE_CONTENTS_ALL (args[i]), len);
+    }
 
+  /* Push value address.  */
+  if (struct_return)
+    {
       sp -= 4;
-      store_address (buf, 4, struct_addr);
+      store_unsigned_integer (buf, 4, struct_addr);
       write_memory (sp, buf, 4);
     }
 
-  return sp;
-}
-
-static void
-i386_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
-{
-  /* Do nothing.  Everything was already done by i386_push_arguments.  */
+  /* Store return address.  */
+  sp -= 4;
+  store_unsigned_integer (buf, 4, bp_addr);
+  write_memory (sp, buf, 4);
+
+  /* Finally, update the stack pointer...  */
+  store_unsigned_integer (buf, 4, sp);
+  regcache_cooked_write (regcache, I386_ESP_REGNUM, buf);
+
+  /* ...and fake a frame pointer.  */
+  regcache_cooked_write (regcache, I386_EBP_REGNUM, buf);
+
+  /* MarkK wrote: This "+ 8" is all over the place:
+     (i386_frame_this_id, i386_sigtramp_frame_this_id,
+     i386_unwind_dummy_id).  It's there, since all frame unwinders for
+     a given target have to agree (within a certain margin) on the
+     definition of the stack address of a frame.  Otherwise
+     frame_id_inner() won't work correctly.  Since DWARF2/GCC uses the
+     stack address *before* the function call as a frame's CFA.  On
+     the i386, when %ebp is used as a frame pointer, the offset
+     between the contents %ebp and the CFA as defined by GCC.  */
+  return sp + 8;
 }
 
 /* These registers are used for returning integers (and on some
    targets also for returning `struct' and `union' values when their
    size and alignment match an integer type).  */
-#define LOW_RETURN_REGNUM 0    /* %eax */
-#define HIGH_RETURN_REGNUM 2   /* %edx */
+#define LOW_RETURN_REGNUM      I386_EAX_REGNUM /* %eax */
+#define HIGH_RETURN_REGNUM     I386_EDX_REGNUM /* %edx */
 
-/* Extract from an array REGBUF containing the (raw) register state, a
-   function return value of TYPE, and copy that, in virtual format,
-   into VALBUF.  */
+/* Read, for architecture GDBARCH, a function return value of TYPE
+   from REGCACHE, and copy that into VALBUF.  */
 
 static void
-i386_extract_return_value (struct type *type, struct regcache *regcache,
-                          void *dst)
+i386_extract_return_value (struct gdbarch *gdbarch, struct type *type,
+                          struct regcache *regcache, void *valbuf)
 {
-  bfd_byte *valbuf = dst;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int len = TYPE_LENGTH (type);
   char buf[I386_MAX_REGISTER_SIZE];
 
-  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
-      && TYPE_NFIELDS (type) == 1)
-    {
-      i386_extract_return_value (TYPE_FIELD_TYPE (type, 0), regcache, valbuf);
-      return;
-    }
-
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
-      if (FP0_REGNUM == 0)
+      if (tdep->st0_regnum < 0)
        {
          warning ("Cannot find floating-point return value.");
          memset (valbuf, 0, len);
@@ -983,13 +1298,13 @@ i386_extract_return_value (struct type *type, struct regcache *regcache,
         its contents to the desired type.  This is probably not
         exactly how it would happen on the target itself, but it is
         the best we can do.  */
-      regcache_raw_read (regcache, FP0_REGNUM, buf);
+      regcache_raw_read (regcache, I386_ST0_REGNUM, buf);
       convert_typed_floating (buf, builtin_type_i387_ext, valbuf, type);
     }
   else
     {
-      int low_size = REGISTER_RAW_SIZE (LOW_RETURN_REGNUM);
-      int high_size = REGISTER_RAW_SIZE (HIGH_RETURN_REGNUM);
+      int low_size = register_size (current_gdbarch, LOW_RETURN_REGNUM);
+      int high_size = register_size (current_gdbarch, HIGH_RETURN_REGNUM);
 
       if (len <= low_size)
        {
@@ -1001,7 +1316,7 @@ i386_extract_return_value (struct type *type, struct regcache *regcache,
          regcache_raw_read (regcache, LOW_RETURN_REGNUM, buf);
          memcpy (valbuf, buf, low_size);
          regcache_raw_read (regcache, HIGH_RETURN_REGNUM, buf);
-         memcpy (valbuf + low_size, buf, len - low_size);
+         memcpy ((char *) valbuf + low_size, buf, len - low_size);
        }
       else
        internal_error (__FILE__, __LINE__,
@@ -1009,28 +1324,26 @@ i386_extract_return_value (struct type *type, struct regcache *regcache,
     }
 }
 
-/* Write into the appropriate registers a function return value stored
-   in VALBUF of type TYPE, given in virtual format.  */
+/* Write, for architecture GDBARCH, a function return value of TYPE
+   from VALBUF into REGCACHE.  */
 
 static void
-i386_store_return_value (struct type *type, struct regcache *regcache,
-                        const void *valbuf)
+i386_store_return_value (struct gdbarch *gdbarch, struct type *type,
+                        struct regcache *regcache, const void *valbuf)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int len = TYPE_LENGTH (type);
 
-  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
-      && TYPE_NFIELDS (type) == 1)
-    {
-      i386_store_return_value (TYPE_FIELD_TYPE (type, 0), regcache, valbuf);
-      return;
-    }
+  /* Define I387_ST0_REGNUM such that we use the proper definitions
+     for the architecture.  */
+#define I387_ST0_REGNUM I386_ST0_REGNUM
 
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
       ULONGEST fstat;
-      char buf[FPU_REG_RAW_SIZE];
+      char buf[I386_MAX_REGISTER_SIZE];
 
-      if (FP0_REGNUM == 0)
+      if (tdep->st0_regnum < 0)
        {
          warning ("Cannot set floating-point return value.");
          return;
@@ -1045,25 +1358,25 @@ i386_store_return_value (struct type *type, struct regcache *regcache,
         not exactly how it would happen on the target itself, but
         it is the best we can do.  */
       convert_typed_floating (valbuf, type, buf, builtin_type_i387_ext);
-      regcache_raw_write (regcache, FP0_REGNUM, buf);
+      regcache_raw_write (regcache, I386_ST0_REGNUM, buf);
 
       /* Set the top of the floating-point register stack to 7.  The
          actual value doesn't really matter, but 7 is what a normal
          function return would end up with if the program started out
          with a freshly initialized FPU.  */
-      regcache_raw_read_unsigned (regcache, FSTAT_REGNUM, &fstat);
+      regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM, &fstat);
       fstat |= (7 << 11);
-      regcache_raw_write_unsigned (regcache, FSTAT_REGNUM, fstat);
+      regcache_raw_write_unsigned (regcache, I387_FSTAT_REGNUM, fstat);
 
       /* Mark %st(1) through %st(7) as empty.  Since we set the top of
          the floating-point register stack to 7, the appropriate value
          for the tag word is 0x3fff.  */
-      regcache_raw_write_unsigned (regcache, FTAG_REGNUM, 0x3fff);
+      regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM, 0x3fff);
     }
   else
     {
-      int low_size = REGISTER_RAW_SIZE (LOW_RETURN_REGNUM);
-      int high_size = REGISTER_RAW_SIZE (HIGH_RETURN_REGNUM);
+      int low_size = register_size (current_gdbarch, LOW_RETURN_REGNUM);
+      int high_size = register_size (current_gdbarch, HIGH_RETURN_REGNUM);
 
       if (len <= low_size)
        regcache_raw_write_part (regcache, LOW_RETURN_REGNUM, 0, len, valbuf);
@@ -1077,19 +1390,8 @@ i386_store_return_value (struct type *type, struct regcache *regcache,
        internal_error (__FILE__, __LINE__,
                        "Cannot store return value of %d bytes long.", len);
     }
-}
 
-/* Extract from REGCACHE, which contains the (raw) register state, the
-   address in which a function should return its structure value, as a
-   CORE_ADDR.  */
-
-static CORE_ADDR
-i386_extract_struct_value_address (struct regcache *regcache)
-{
-  ULONGEST addr;
-
-  regcache_raw_read_unsigned (regcache, LOW_RETURN_REGNUM, &addr);
-  return addr;
+#undef I387_ST0_REGNUM
 }
 \f
 
@@ -1107,20 +1409,83 @@ static const char *valid_conventions[] =
 };
 static const char *struct_convention = default_struct_convention;
 
+/* Return non-zero if TYPE, which is assumed to be a structure or
+   union type, should be returned in registers for architecture
+   GDBARCH.  */
+
 static int
-i386_use_struct_convention (int gcc_p, struct type *type)
+i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
 {
-  enum struct_return struct_return;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum type_code code = TYPE_CODE (type);
+  int len = TYPE_LENGTH (type);
 
-  if (struct_convention == default_struct_convention)
-    struct_return = gdbarch_tdep (current_gdbarch)->struct_return;
-  else if (struct_convention == pcc_struct_convention)
-    struct_return = pcc_struct_return;
-  else
-    struct_return = reg_struct_return;
+  gdb_assert (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION);
+
+  if (struct_convention == pcc_struct_convention
+      || (struct_convention == default_struct_convention
+         && tdep->struct_return == pcc_struct_return))
+    return 0;
+
+  return (len == 1 || len == 2 || len == 4 || len == 8);
+}
+
+/* Determine, for architecture GDBARCH, how a return value of TYPE
+   should be returned.  If it is supposed to be returned in registers,
+   and READBUF is non-zero, read the appropriate value from REGCACHE,
+   and copy it into READBUF.  If WRITEBUF is non-zero, write the value
+   from WRITEBUF into REGCACHE.  */
+
+static enum return_value_convention
+i386_return_value (struct gdbarch *gdbarch, struct type *type,
+                  struct regcache *regcache, void *readbuf,
+                  const void *writebuf)
+{
+  enum type_code code = TYPE_CODE (type);
+
+  if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
+      && !i386_reg_struct_return_p (gdbarch, type))
+    {
+      /* The System V ABI says that:
+
+        "A function that returns a structure or union also sets %eax
+        to the value of the original address of the caller's area
+        before it returns.  Thus when the caller receives control
+        again, the address of the returned object resides in register
+        %eax and can be used to access the object."
+
+        So the ABI guarantees that we can always find the return
+        value just after the function has returned.  */
+
+      if (readbuf)
+       {
+         ULONGEST addr;
+
+         regcache_raw_read_unsigned (regcache, I386_EAX_REGNUM, &addr);
+         read_memory (addr, readbuf, TYPE_LENGTH (type));
+       }
+
+      return RETURN_VALUE_ABI_RETURNS_ADDRESS;
+    }
+
+  /* This special case is for structures consisting of a single
+     `float' or `double' member.  These structures are returned in
+     %st(0).  For these structures, we call ourselves recursively,
+     changing TYPE into the type of the first member of the structure.
+     Since that should work for all structures that have only one
+     member, we don't bother to check the member's type here.  */
+  if (code == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) == 1)
+    {
+      type = check_typedef (TYPE_FIELD_TYPE (type, 0));
+      return i386_return_value (gdbarch, type, regcache, readbuf, writebuf);
+    }
 
-  return generic_use_struct_convention (struct_return == reg_struct_return,
-                                       type);
+  if (readbuf)
+    i386_extract_return_value (gdbarch, type, regcache, readbuf);
+  if (writebuf)
+    i386_store_return_value (gdbarch, type, regcache, writebuf);
+
+  return RETURN_VALUE_REGISTER_CONVENTION;
 }
 \f
 
@@ -1131,16 +1496,17 @@ i386_use_struct_convention (int gcc_p, struct type *type)
 static struct type *
 i386_register_type (struct gdbarch *gdbarch, int regnum)
 {
-  if (regnum == PC_REGNUM || regnum == FP_REGNUM || regnum == SP_REGNUM)
+  if (regnum == I386_EIP_REGNUM
+      || regnum == I386_EBP_REGNUM || regnum == I386_ESP_REGNUM)
     return lookup_pointer_type (builtin_type_void);
 
   if (i386_fp_regnum_p (regnum))
     return builtin_type_i387_ext;
 
-  if (i386_sse_regnum_p (regnum))
+  if (i386_sse_regnum_p (gdbarch, regnum))
     return builtin_type_vec128i;
 
-  if (i386_mmx_regnum_p (regnum))
+  if (i386_mmx_regnum_p (gdbarch, regnum))
     return builtin_type_vec64i;
 
   return builtin_type_int;
@@ -1150,30 +1516,39 @@ i386_register_type (struct gdbarch *gdbarch, int regnum)
    the MMX registers need to be mapped onto floating point registers.  */
 
 static int
-mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
+i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
 {
-  int mmxi;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+  int mmxreg, fpreg;
   ULONGEST fstat;
   int tos;
-  int fpi;
-  mmxi = regnum - MM0_REGNUM;
-  regcache_raw_read_unsigned (regcache, FSTAT_REGNUM, &fstat);
+
+  /* Define I387_ST0_REGNUM such that we use the proper definitions
+     for REGCACHE's architecture.  */
+#define I387_ST0_REGNUM tdep->st0_regnum
+
+  mmxreg = regnum - tdep->mm0_regnum;
+  regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM, &fstat);
   tos = (fstat >> 11) & 0x7;
-  fpi = (mmxi + tos) % 8;
-  return (FP0_REGNUM + fpi);
+  fpreg = (mmxreg + tos) % 8;
+
+  return (I387_ST0_REGNUM + fpreg);
+
+#undef I387_ST0_REGNUM
 }
 
 static void
 i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int regnum, void *buf)
 {
-  if (i386_mmx_regnum_p (regnum))
+  if (i386_mmx_regnum_p (gdbarch, regnum))
     {
-      char *mmx_buf = alloca (MAX_REGISTER_RAW_SIZE);
-      int fpnum = mmx_regnum_to_fp_regnum (regcache, regnum);
-      regcache_raw_read (regcache, fpnum, mmx_buf);
+      char mmx_buf[MAX_REGISTER_SIZE];
+      int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
+
       /* Extract (always little endian).  */
-      memcpy (buf, mmx_buf, REGISTER_RAW_SIZE (regnum));
+      regcache_raw_read (regcache, fpnum, mmx_buf);
+      memcpy (buf, mmx_buf, register_size (gdbarch, regnum));
     }
   else
     regcache_raw_read (regcache, regnum, buf);
@@ -1183,79 +1558,267 @@ static void
 i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
                            int regnum, const void *buf)
 {
-  if (i386_mmx_regnum_p (regnum))
+  if (i386_mmx_regnum_p (gdbarch, regnum))
     {
-      char *mmx_buf = alloca (MAX_REGISTER_RAW_SIZE);
-      int fpnum = mmx_regnum_to_fp_regnum (regcache, regnum);
+      char mmx_buf[MAX_REGISTER_SIZE];
+      int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
+
       /* Read ...  */
       regcache_raw_read (regcache, fpnum, mmx_buf);
       /* ... Modify ... (always little endian).  */
-      memcpy (mmx_buf, buf, REGISTER_RAW_SIZE (regnum));
+      memcpy (mmx_buf, buf, register_size (gdbarch, regnum));
       /* ... Write.  */
       regcache_raw_write (regcache, fpnum, mmx_buf);
     }
   else
     regcache_raw_write (regcache, regnum, buf);
 }
+\f
+
+/* Return the register number of the register allocated by GCC after
+   REGNUM, or -1 if there is no such register.  */
+
+static int
+i386_next_regnum (int regnum)
+{
+  /* GCC allocates the registers in the order:
+
+     %eax, %edx, %ecx, %ebx, %esi, %edi, %ebp, %esp, ...
+
+     Since storing a variable in %esp doesn't make any sense we return
+     -1 for %ebp and for %esp itself.  */
+  static int next_regnum[] =
+  {
+    I386_EDX_REGNUM,           /* Slot for %eax.  */
+    I386_EBX_REGNUM,           /* Slot for %ecx.  */
+    I386_ECX_REGNUM,           /* Slot for %edx.  */
+    I386_ESI_REGNUM,           /* Slot for %ebx.  */
+    -1, -1,                    /* Slots for %esp and %ebp.  */
+    I386_EDI_REGNUM,           /* Slot for %esi.  */
+    I386_EBP_REGNUM            /* Slot for %edi.  */
+  };
+
+  if (regnum >= 0 && regnum < sizeof (next_regnum) / sizeof (next_regnum[0]))
+    return next_regnum[regnum];
+
+  return -1;
+}
 
-/* Return true iff register REGNUM's virtual format is different from
-   its raw format.  Note that this definition assumes that the host
-   supports IEEE 32-bit floats, since it doesn't say that SSE
-   registers need conversion.  Even if we can't find a counterexample,
-   this is still sloppy.  */
+/* Return nonzero if a value of type TYPE stored in register REGNUM
+   needs any special handling.  */
 
 static int
-i386_register_convertible (int regnum)
+i386_convert_register_p (int regnum, struct type *type)
 {
+  int len = TYPE_LENGTH (type);
+
+  /* Values may be spread across multiple registers.  Most debugging
+     formats aren't expressive enough to specify the locations, so
+     some heuristics is involved.  Right now we only handle types that
+     have a length that is a multiple of the word size, since GCC
+     doesn't seem to put any other types into registers.  */
+  if (len > 4 && len % 4 == 0)
+    {
+      int last_regnum = regnum;
+
+      while (len > 4)
+       {
+         last_regnum = i386_next_regnum (last_regnum);
+         len -= 4;
+       }
+
+      if (last_regnum != -1)
+       return 1;
+    }
+
   return i386_fp_regnum_p (regnum);
 }
 
-/* Convert data from raw format for register REGNUM in buffer FROM to
-   virtual format with type TYPE in buffer TO.  */
+/* Read a value of type TYPE from register REGNUM in frame FRAME, and
+   return its contents in TO.  */
+
+static void
+i386_register_to_value (struct frame_info *frame, int regnum,
+                       struct type *type, void *to)
+{
+  int len = TYPE_LENGTH (type);
+  char *buf = to;
+
+  /* FIXME: kettenis/20030609: What should we do if REGNUM isn't
+     available in FRAME (i.e. if it wasn't saved)?  */
+
+  if (i386_fp_regnum_p (regnum))
+    {
+      i387_register_to_value (frame, regnum, type, to);
+      return;
+    }
+
+  /* Read a value spread across multiple registers.  */
+
+  gdb_assert (len > 4 && len % 4 == 0);
+
+  while (len > 0)
+    {
+      gdb_assert (regnum != -1);
+      gdb_assert (register_size (current_gdbarch, regnum) == 4);
+
+      get_frame_register (frame, regnum, buf);
+      regnum = i386_next_regnum (regnum);
+      len -= 4;
+      buf += 4;
+    }
+}
+
+/* Write the contents FROM of a value of type TYPE into register
+   REGNUM in frame FRAME.  */
+
+static void
+i386_value_to_register (struct frame_info *frame, int regnum,
+                       struct type *type, const void *from)
+{
+  int len = TYPE_LENGTH (type);
+  const char *buf = from;
+
+  if (i386_fp_regnum_p (regnum))
+    {
+      i387_value_to_register (frame, regnum, type, from);
+      return;
+    }
+
+  /* Write a value spread across multiple registers.  */
+
+  gdb_assert (len > 4 && len % 4 == 0);
+
+  while (len > 0)
+    {
+      gdb_assert (regnum != -1);
+      gdb_assert (register_size (current_gdbarch, regnum) == 4);
+
+      put_frame_register (frame, regnum, buf);
+      regnum = i386_next_regnum (regnum);
+      len -= 4;
+      buf += 4;
+    }
+}
+\f
+/* Supply register REGNUM from the buffer specified by GREGS and LEN
+   in the general-purpose register set REGSET to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+void
+i386_supply_gregset (const struct regset *regset, struct regcache *regcache,
+                    int regnum, const void *gregs, size_t len)
+{
+  const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
+  const char *regs = gregs;
+  int i;
+
+  gdb_assert (len == tdep->sizeof_gregset);
+
+  for (i = 0; i < tdep->gregset_num_regs; i++)
+    {
+      if ((regnum == i || regnum == -1)
+         && tdep->gregset_reg_offset[i] != -1)
+       regcache_raw_supply (regcache, i, regs + tdep->gregset_reg_offset[i]);
+    }
+}
+
+/* Collect register REGNUM from the register cache REGCACHE and store
+   it in the buffer specified by GREGS and LEN as described by the
+   general-purpose register set REGSET.  If REGNUM is -1, do this for
+   all registers in REGSET.  */
+
+void
+i386_collect_gregset (const struct regset *regset,
+                     const struct regcache *regcache,
+                     int regnum, void *gregs, size_t len)
+{
+  const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
+  char *regs = gregs;
+  int i;
+
+  gdb_assert (len == tdep->sizeof_gregset);
+
+  for (i = 0; i < tdep->gregset_num_regs; i++)
+    {
+      if ((regnum == i || regnum == -1)
+         && tdep->gregset_reg_offset[i] != -1)
+       regcache_raw_collect (regcache, i, regs + tdep->gregset_reg_offset[i]);
+    }
+}
+
+/* Supply register REGNUM from the buffer specified by FPREGS and LEN
+   in the floating-point register set REGSET to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
 
 static void
-i386_register_convert_to_virtual (int regnum, struct type *type,
-                                 char *from, char *to)
+i386_supply_fpregset (const struct regset *regset, struct regcache *regcache,
+                     int regnum, const void *fpregs, size_t len)
 {
-  gdb_assert (i386_fp_regnum_p (regnum));
+  const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
 
-  /* We only support floating-point values.  */
-  if (TYPE_CODE (type) != TYPE_CODE_FLT)
+  if (len == I387_SIZEOF_FXSAVE)
     {
-      warning ("Cannot convert floating-point register value "
-              "to non-floating-point type.");
-      memset (to, 0, TYPE_LENGTH (type));
+      i387_supply_fxsave (regcache, regnum, fpregs);
       return;
     }
 
-  /* Convert to TYPE.  This should be a no-op if TYPE is equivalent to
-     the extended floating-point format used by the FPU.  */
-  convert_typed_floating (from, builtin_type_i387_ext, to, type);
+  gdb_assert (len == tdep->sizeof_fpregset);
+  i387_supply_fsave (regcache, regnum, fpregs);
 }
 
-/* Convert data from virtual format with type TYPE in buffer FROM to
-   raw format for register REGNUM in buffer TO.  */
+/* Collect register REGNUM from the register cache REGCACHE and store
+   it in the buffer specified by FPREGS and LEN as described by the
+   floating-point register set REGSET.  If REGNUM is -1, do this for
+   all registers in REGSET.  */
 
 static void
-i386_register_convert_to_raw (struct type *type, int regnum,
-                             char *from, char *to)
+i386_collect_fpregset (const struct regset *regset,
+                      const struct regcache *regcache,
+                      int regnum, void *fpregs, size_t len)
 {
-  gdb_assert (i386_fp_regnum_p (regnum));
+  const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
 
-  /* We only support floating-point values.  */
-  if (TYPE_CODE (type) != TYPE_CODE_FLT)
+  if (len == I387_SIZEOF_FXSAVE)
     {
-      warning ("Cannot convert non-floating-point type "
-              "to floating-point register value.");
-      memset (to, 0, TYPE_LENGTH (type));
+      i387_collect_fxsave (regcache, regnum, fpregs);
       return;
     }
 
-  /* Convert from TYPE.  This should be a no-op if TYPE is equivalent
-     to the extended floating-point format used by the FPU.  */
-  convert_typed_floating (from, type, to, builtin_type_i387_ext);
+  gdb_assert (len == tdep->sizeof_fpregset);
+  i387_collect_fsave (regcache, regnum, fpregs);
+}
+
+/* Return the appropriate register set for the core section identified
+   by SECT_NAME and SECT_SIZE.  */
+
+const struct regset *
+i386_regset_from_core_section (struct gdbarch *gdbarch,
+                              const char *sect_name, size_t sect_size)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset)
+    {
+      if (tdep->gregset == NULL)
+       tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset,
+                                     i386_collect_gregset);
+      return tdep->gregset;
+    }
+
+  if ((strcmp (sect_name, ".reg2") == 0 && sect_size == tdep->sizeof_fpregset)
+      || (strcmp (sect_name, ".reg-xfp") == 0
+         && sect_size == I387_SIZEOF_FXSAVE))
+    {
+      if (tdep->fpregset == NULL)
+       tdep->fpregset = regset_alloc (gdbarch, i386_supply_fpregset,
+                                      i386_collect_fpregset);
+      return tdep->fpregset;
+    }
+
+  return NULL;
 }
-\f     
+\f
 
 #ifdef STATIC_TRANSFORM_NAME
 /* SunPRO encodes the static variables.  This is not related to C++
@@ -1306,12 +1869,16 @@ i386_pe_skip_trampoline_code (CORE_ADDR pc, char *name)
 }
 \f
 
-/* Return non-zero if PC and NAME show that we are in a signal
-   trampoline.  */
+/* Return whether the frame preceding NEXT_FRAME corresponds to a
+   sigtramp routine.  */
 
 static int
-i386_pc_in_sigtramp (CORE_ADDR pc, char *name)
+i386_sigtramp_p (struct frame_info *next_frame)
 {
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  char *name;
+
+  find_pc_partial_function (pc, &name, NULL, NULL);
   return (name && strcmp ("_sigtramp", name) == 0);
 }
 \f
@@ -1320,7 +1887,7 @@ i386_pc_in_sigtramp (CORE_ADDR pc, char *name)
    deals with switching between those.  */
 
 static int
-i386_print_insn (bfd_vma pc, disassemble_info *info)
+i386_print_insn (bfd_vma pc, struct disassemble_info *info)
 {
   gdb_assert (disassembly_flavor == att_flavor
              || disassembly_flavor == intel_flavor);
@@ -1341,49 +1908,37 @@ i386_print_insn (bfd_vma pc, disassemble_info *info)
 
 /* System V Release 4 (SVR4).  */
 
+/* Return whether the frame preceding NEXT_FRAME corresponds to a SVR4
+   sigtramp routine.  */
+
 static int
-i386_svr4_pc_in_sigtramp (CORE_ADDR pc, char *name)
+i386_svr4_sigtramp_p (struct frame_info *next_frame)
 {
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  char *name;
+
+  /* UnixWare uses _sigacthandler.  The origin of the other symbols is
+     currently unknown.  */
+  find_pc_partial_function (pc, &name, NULL, NULL);
   return (name && (strcmp ("_sigreturn", name) == 0
                   || strcmp ("_sigacthandler", name) == 0
                   || strcmp ("sigvechandler", name) == 0));
 }
 
-/* Get address of the pushed ucontext (sigcontext) on the stack for
-   all three variants of SVR4 sigtramps.  */
+/* Assuming NEXT_FRAME is for a frame following a SVR4 sigtramp
+   routine, return the address of the associated sigcontext (ucontext)
+   structure.  */
 
 static CORE_ADDR
-i386_svr4_sigcontext_addr (struct frame_info *frame)
+i386_svr4_sigcontext_addr (struct frame_info *next_frame)
 {
-  int sigcontext_offset = -1;
-  char *name = NULL;
-
-  find_pc_partial_function (get_frame_pc (frame), &name, NULL, NULL);
-  if (name)
-    {
-      if (strcmp (name, "_sigreturn") == 0)
-       sigcontext_offset = 132;
-      else if (strcmp (name, "_sigacthandler") == 0)
-       sigcontext_offset = 80;
-      else if (strcmp (name, "sigvechandler") == 0)
-       sigcontext_offset = 120;
-    }
-
-  gdb_assert (sigcontext_offset != -1);
-
-  if (get_next_frame (frame))
-    return get_frame_base (get_next_frame (frame)) + sigcontext_offset;
-  return read_register (SP_REGNUM) + sigcontext_offset;
-}
-\f
+  char buf[4];
+  CORE_ADDR sp;
 
-/* DJGPP.  */
+  frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
+  sp = extract_unsigned_integer (buf, 4);
 
-static int
-i386_go32_pc_in_sigtramp (CORE_ADDR pc, char *name)
-{
-  /* DJGPP doesn't have any special frames for signal handlers.  */
-  return 0;
+  return read_memory_unsigned_integer (sp + 8, 4);
 }
 \f
 
@@ -1392,8 +1947,8 @@ i386_go32_pc_in_sigtramp (CORE_ADDR pc, char *name)
 void
 i386_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
-  /* We typically use stabs-in-ELF with the DWARF register numbering.  */
-  set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
+  /* We typically use stabs-in-ELF with the SVR4 register numbering.  */
+  set_gdbarch_stab_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
 }
 
 /* System V Release 4 (SVR4).  */
@@ -1407,13 +1962,12 @@ i386_svr4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   i386_elf_init_abi (info, gdbarch);
 
   /* System V Release 4 has shared libraries.  */
-  set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
 
-  set_gdbarch_pc_in_sigtramp (gdbarch, i386_svr4_pc_in_sigtramp);
+  tdep->sigtramp_p = i386_svr4_sigtramp_p;
   tdep->sigcontext_addr = i386_svr4_sigcontext_addr;
-  tdep->sc_pc_offset = 14 * 4;
-  tdep->sc_sp_offset = 7 * 4;
+  tdep->sc_pc_offset = 36 + 14 * 4;
+  tdep->sc_sp_offset = 36 + 17 * 4;
 
   tdep->jb_pc_offset = 20;
 }
@@ -1425,7 +1979,8 @@ i386_go32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  set_gdbarch_pc_in_sigtramp (gdbarch, i386_go32_pc_in_sigtramp);
+  /* DJGPP doesn't have any special frames for signal handlers.  */
+  tdep->sigtramp_p = NULL;
 
   tdep->jb_pc_offset = 36;
 }
@@ -1472,11 +2027,12 @@ int
 i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
                          struct reggroup *group)
 {
-  int sse_regnum_p = (i386_sse_regnum_p (regnum)
-                     || i386_mxcsr_regnum_p (regnum));
+  int sse_regnum_p = (i386_sse_regnum_p (gdbarch, regnum)
+                     || i386_mxcsr_regnum_p (gdbarch, regnum));
   int fp_regnum_p = (i386_fp_regnum_p (regnum)
                     || i386_fpc_regnum_p (regnum));
-  int mmx_regnum_p = (i386_mmx_regnum_p (regnum));
+  int mmx_regnum_p = (i386_mmx_regnum_p (gdbarch, regnum));
+
   if (group == i386_mmx_reggroup)
     return mmx_regnum_p;
   if (group == i386_sse_reggroup)
@@ -1487,8 +2043,20 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
     return fp_regnum_p;
   if (group == general_reggroup)
     return (!fp_regnum_p && !mmx_regnum_p && !sse_regnum_p);
+
   return default_register_reggroup_p (gdbarch, regnum, group);
 }
+\f
+
+/* Get the ARGIth function argument for the current function.  */
+
+static CORE_ADDR
+i386_fetch_pointer_argument (struct frame_info *frame, int argi, 
+                            struct type *type)
+{
+  CORE_ADDR sp = get_frame_register_unsigned  (frame, I386_ESP_REGNUM);
+  return read_memory_unsigned_integer (sp + (4 * (argi + 1)), 4);
+}
 
 \f
 static struct gdbarch *
@@ -1506,20 +2074,47 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep = XMALLOC (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
 
-  /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
-     ready to unwind the PC first (see frame.c:get_prev_frame()).  */
-  set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
+  /* General-purpose registers.  */
+  tdep->gregset = NULL;
+  tdep->gregset_reg_offset = NULL;
+  tdep->gregset_num_regs = I386_NUM_GREGS;
+  tdep->sizeof_gregset = 0;
 
-  /* The i386 default settings don't include the SSE registers.
-     FIXME: kettenis/20020614: They do include the FPU registers for
-     now, which probably is not quite right.  */
-  tdep->num_xmm_regs = 0;
+  /* Floating-point registers.  */
+  tdep->fpregset = NULL;
+  tdep->sizeof_fpregset = I387_SIZEOF_FSAVE;
+
+  /* The default settings include the FPU registers, the MMX registers
+     and the SSE registers.  This can be overridden for a specific ABI
+     by adjusting the members `st0_regnum', `mm0_regnum' and
+     `num_xmm_regs' of `struct gdbarch_tdep', otherwise the registers
+     will show up in the output of "info all-registers".  Ideally we
+     should try to autodetect whether they are available, such that we
+     can prevent "info all-registers" from displaying registers that
+     aren't available.
+
+     NOTE: kevinb/2003-07-13: ... if it's a choice between printing
+     [the SSE registers] always (even when they don't exist) or never
+     showing them to the user (even when they do exist), I prefer the
+     former over the latter.  */
+
+  tdep->st0_regnum = I386_ST0_REGNUM;
+
+  /* The MMX registers are implemented as pseudo-registers.  Put off
+     calculating the register number for %mm0 until we know the number
+     of raw registers.  */
+  tdep->mm0_regnum = 0;
+
+  /* I386_NUM_XREGS includes %mxcsr, so substract one.  */
+  tdep->num_xmm_regs = I386_NUM_XREGS - 1;
 
   tdep->jb_pc_offset = -1;
   tdep->struct_return = pcc_struct_return;
   tdep->sigtramp_start = 0;
   tdep->sigtramp_end = 0;
+  tdep->sigtramp_p = i386_sigtramp_p;
   tdep->sigcontext_addr = NULL;
+  tdep->sc_reg_offset = NULL;
   tdep->sc_pc_offset = -1;
   tdep->sc_sp_offset = -1;
 
@@ -1534,68 +2129,72 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      alignment.  */
   set_gdbarch_long_double_bit (gdbarch, 96);
 
-  /* NOTE: tm-i386aix.h, tm-i386bsd.h, tm-i386os9k.h, tm-ptx.h,
-     tm-symmetry.h currently override this.  Sigh.  */
-  set_gdbarch_num_regs (gdbarch, I386_NUM_GREGS + I386_NUM_FREGS);
-
-  set_gdbarch_sp_regnum (gdbarch, 4); /* %esp */
-  set_gdbarch_fp_regnum (gdbarch, 5); /* %ebp */
-  set_gdbarch_pc_regnum (gdbarch, 8); /* %eip */
-  set_gdbarch_ps_regnum (gdbarch, 9); /* %eflags */
-  set_gdbarch_fp0_regnum (gdbarch, 16);        /* %st(0) */
-
-  /* Use the "default" register numbering scheme for stabs and COFF.  */
-  set_gdbarch_stab_reg_to_regnum (gdbarch, i386_stab_reg_to_regnum);
-  set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_stab_reg_to_regnum);
+  /* The default ABI includes general-purpose registers, 
+     floating-point registers, and the SSE registers.  */
+  set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS);
+  set_gdbarch_register_name (gdbarch, i386_register_name);
+  set_gdbarch_register_type (gdbarch, i386_register_type);
 
-  /* Use the DWARF register numbering scheme for DWARF and DWARF 2.  */
-  set_gdbarch_dwarf_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
-  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
+  /* Register numbers of various important registers.  */
+  set_gdbarch_sp_regnum (gdbarch, I386_ESP_REGNUM); /* %esp */
+  set_gdbarch_pc_regnum (gdbarch, I386_EIP_REGNUM); /* %eip */
+  set_gdbarch_ps_regnum (gdbarch, I386_EFLAGS_REGNUM); /* %eflags */
+  set_gdbarch_fp0_regnum (gdbarch, I386_ST0_REGNUM); /* %st(0) */
+
+  /* NOTE: kettenis/20040418: GCC does have two possible register
+     numbering schemes on the i386: dbx and SVR4.  These schemes
+     differ in how they number %ebp, %esp, %eflags, and the
+     floating-point registers, and are implemented by the arrays
+     dbx_register_map[] and svr4_dbx_register_map in
+     gcc/config/i386.c.  GCC also defines a third numbering scheme in
+     gcc/config/i386.c, which it designates as the "default" register
+     map used in 64bit mode.  This last register numbering scheme is
+     implemented in dbx64_register_map, and is used for AMD64; see
+     amd64-tdep.c.
+
+     Currently, each GCC i386 target always uses the same register
+     numbering scheme across all its supported debugging formats
+     i.e. SDB (COFF), stabs and DWARF 2.  This is because
+     gcc/sdbout.c, gcc/dbxout.c and gcc/dwarf2out.c all use the
+     DBX_REGISTER_NUMBER macro which is defined by each target's
+     respective config header in a manner independent of the requested
+     output debugging format.
+
+     This does not match the arrangement below, which presumes that
+     the SDB and stabs numbering schemes differ from the DWARF and
+     DWARF 2 ones.  The reason for this arrangement is that it is
+     likely to get the numbering scheme for the target's
+     default/native debug format right.  For targets where GCC is the
+     native compiler (FreeBSD, NetBSD, OpenBSD, GNU/Linux) or for
+     targets where the native toolchain uses a different numbering
+     scheme for a particular debug format (stabs-in-ELF on Solaris)
+     the defaults below will have to be overridden, like
+     i386_elf_init_abi() does.  */
+
+  /* Use the dbx register numbering scheme for stabs and COFF.  */
+  set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
+  set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
+
+  /* Use the SVR4 register numbering scheme for DWARF and DWARF 2.  */
+  set_gdbarch_dwarf_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
+  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
 
   /* We don't define ECOFF_REG_TO_REGNUM, since ECOFF doesn't seem to
      be in use on any of the supported i386 targets.  */
 
-  set_gdbarch_register_name (gdbarch, i386_register_name);
-  set_gdbarch_register_size (gdbarch, 4);
-  set_gdbarch_register_bytes (gdbarch, I386_SIZEOF_GREGS + I386_SIZEOF_FREGS);
-  set_gdbarch_register_type (gdbarch, i386_register_type);
-
   set_gdbarch_print_float_info (gdbarch, i387_print_float_info);
 
   set_gdbarch_get_longjmp_target (gdbarch, i386_get_longjmp_target);
 
   /* Call dummy code.  */
-  set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
-  set_gdbarch_call_dummy_start_offset (gdbarch, 0);
-  set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
-  set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
-  set_gdbarch_call_dummy_length (gdbarch, 0);
-  set_gdbarch_call_dummy_p (gdbarch, 1);
-  set_gdbarch_call_dummy_words (gdbarch, NULL);
-  set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
-  set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
-
-  set_gdbarch_register_convertible (gdbarch, i386_register_convertible);
-  set_gdbarch_register_convert_to_virtual (gdbarch,
-                                          i386_register_convert_to_virtual);
-  set_gdbarch_register_convert_to_raw (gdbarch, i386_register_convert_to_raw);
-
-  /* "An argument's size is increased, if necessary, to make it a
-     multiple of [32-bit] words.  This may require tail padding,
-     depending on the size of the argument" -- from the x86 ABI.  */
-  set_gdbarch_parm_boundary (gdbarch, 32);
-
-  set_gdbarch_extract_return_value (gdbarch, i386_extract_return_value);
-  set_gdbarch_push_arguments (gdbarch, i386_push_arguments);
-  set_gdbarch_push_return_address (gdbarch, i386_push_return_address);
-  set_gdbarch_deprecated_pop_frame (gdbarch, i386_pop_frame);
-  set_gdbarch_store_struct_return (gdbarch, i386_store_struct_return);
-  set_gdbarch_store_return_value (gdbarch, i386_store_return_value);
-  set_gdbarch_extract_struct_value_address (gdbarch,
-                                           i386_extract_struct_value_address);
-  set_gdbarch_use_struct_convention (gdbarch, i386_use_struct_convention);
-
-  set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, i386_frame_init_saved_regs);
+  set_gdbarch_push_dummy_call (gdbarch, i386_push_dummy_call);
+
+  set_gdbarch_convert_register_p (gdbarch, i386_convert_register_p);
+  set_gdbarch_register_to_value (gdbarch,  i386_register_to_value);
+  set_gdbarch_value_to_register (gdbarch, i386_value_to_register);
+
+  set_gdbarch_return_value (gdbarch, i386_return_value);
+
   set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
 
   /* Stack grows downward.  */
@@ -1603,36 +2202,50 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_breakpoint_from_pc (gdbarch, i386_breakpoint_from_pc);
   set_gdbarch_decr_pc_after_break (gdbarch, 1);
-  set_gdbarch_function_start_offset (gdbarch, 0);
-
-  /* The following redefines make backtracing through sigtramp work.
-     They manufacture a fake sigtramp frame and obtain the saved pc in
-     sigtramp from the sigcontext structure which is pushed by the
-     kernel on the user stack, along with a pointer to it.  */
 
   set_gdbarch_frame_args_skip (gdbarch, 8);
-  set_gdbarch_frameless_function_invocation (gdbarch,
-                                           i386_frameless_function_invocation);
-  set_gdbarch_deprecated_frame_chain (gdbarch, i386_frame_chain);
-  set_gdbarch_deprecated_frame_saved_pc (gdbarch, i386_frame_saved_pc);
-  set_gdbarch_saved_pc_after_call (gdbarch, i386_saved_pc_after_call);
-  set_gdbarch_frame_num_args (gdbarch, i386_frame_num_args);
-  set_gdbarch_pc_in_sigtramp (gdbarch, i386_pc_in_sigtramp);
 
   /* Wire in the MMX registers.  */
-  set_gdbarch_num_pseudo_regs (gdbarch, mmx_num_regs);
+  set_gdbarch_num_pseudo_regs (gdbarch, i386_num_mmx_regs);
   set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
 
   set_gdbarch_print_insn (gdbarch, i386_print_insn);
 
+  set_gdbarch_unwind_dummy_id (gdbarch, i386_unwind_dummy_id);
+
+  set_gdbarch_unwind_pc (gdbarch, i386_unwind_pc);
+
   /* Add the i386 register groups.  */
   i386_add_reggroups (gdbarch);
   set_gdbarch_register_reggroup_p (gdbarch, i386_register_reggroup_p);
 
+  /* Helper for function argument information.  */
+  set_gdbarch_fetch_pointer_argument (gdbarch, i386_fetch_pointer_argument);
+
+  /* Hook in the DWARF CFI frame unwinder.  */
+  frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
+
+  frame_base_set_default (gdbarch, &i386_frame_base);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
+  frame_unwind_append_sniffer (gdbarch, i386_sigtramp_frame_sniffer);
+  frame_unwind_append_sniffer (gdbarch, i386_frame_sniffer);
+
+  /* If we have a register mapping, enable the generic core file
+     support, unless it has already been enabled.  */
+  if (tdep->gregset_reg_offset
+      && !gdbarch_regset_from_core_section_p (gdbarch))
+    set_gdbarch_regset_from_core_section (gdbarch,
+                                         i386_regset_from_core_section);
+
+  /* Unless support for MMX has been disabled, make %mm0 the first
+     pseudo-register.  */
+  if (tdep->mm0_regnum == 0)
+    tdep->mm0_regnum = gdbarch_num_regs (gdbarch);
+
   return gdbarch;
 }
 
@@ -1672,7 +2285,7 @@ _initialize_i386_tdep (void)
 Set the disassembly flavor, the valid values are \"att\" and \"intel\", \
 and the default value is \"att\".",
                                &setlist);
-    add_show_from_set (new_cmd, &showlist);
+    deprecated_add_show_from_set (new_cmd, &showlist);
   }
 
   /* Add the variable that controls the convention for returning
@@ -1686,7 +2299,7 @@ and the default value is \"att\".",
 Set the convention for returning small structs, valid values \
 are \"default\", \"pcc\" and \"reg\", and the default value is \"default\".",
                                 &setlist);
-    add_show_from_set (new_cmd, &showlist);
+    deprecated_add_show_from_set (new_cmd, &showlist);
   }
 
   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
This page took 0.056894 seconds and 4 git commands to generate.