2004-06-06 Randolph Chung <tausq@debian.org>
[deliverable/binutils-gdb.git] / gdb / i386-tdep.c
index dc8a0e77e32bfaf788b2b0c0f1f5c84a4a8c9dac..2008acb8b005ccf99496407bce4a28e9b8bec2c5 100644 (file)
@@ -572,12 +572,12 @@ i386_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR current_pc,
 
            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 = read_memory_unsigned_integer (pc + 3, 1);
       if (op == 0x83)
        {
-         /* `subl' with 8 bit immediate.  */
+         /* `subl' with 8-bit immediate.  */
          if (read_memory_unsigned_integer (pc + 4, 1) != 0xec)
            /* Some instruction starting with 0x83 other than `subl'.  */
            return pc + 3;
@@ -589,12 +589,12 @@ i386_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR current_pc,
        }
       else if (op == 0x81)
        {
-         /* Maybe it is `subl' with a 32 bit immedediate.  */
+         /* Maybe it is `subl' with a 32-bit immediate.  */
          if (read_memory_unsigned_integer (pc + 4, 1) != 0xec)
            /* Some instruction starting with 0x81 other than `subl'.  */
            return pc + 3;
 
-         /* It is `subl' with a 32 bit immediate.  */
+         /* It is `subl' with a 32-bit immediate.  */
          cache->locals = read_memory_integer (pc + 5, 4);
          return pc + 9;
        }
@@ -657,9 +657,9 @@ i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
    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.
+   '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.
 
    Next, the registers used by this function are pushed.  With the
    System V compiler they will always be in the order: %edi, %esi,
@@ -750,7 +750,13 @@ i386_skip_prologue (CORE_ADDR start_pc)
        }
     }
 
-  return i386_follow_jump (pc);
+  /* 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;
 }
 
 /* This function is 64-bit safe.  */
@@ -1113,7 +1119,7 @@ i386_get_longjmp_target (CORE_ADDR *pc)
 \f
 
 static CORE_ADDR
-i386_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_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)
@@ -1161,7 +1167,7 @@ i386_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
      (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
-     defenition of the stack address of a frame.  Otherwise
+     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
@@ -1346,7 +1352,28 @@ i386_return_value (struct gdbarch *gdbarch, struct type *type,
 
   if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
       && !i386_reg_struct_return_p (gdbarch, type))
-    return RETURN_VALUE_STRUCT_CONVENTION;
+    {
+      /* 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
@@ -1533,7 +1560,7 @@ i386_register_to_value (struct frame_info *frame, int regnum,
       return;
     }
 
-  /* Read a value spread accross multiple registers.  */
+  /* Read a value spread across multiple registers.  */
 
   gdb_assert (len > 4 && len % 4 == 0);
 
@@ -1565,7 +1592,7 @@ i386_value_to_register (struct frame_info *frame, int regnum,
       return;
     }
 
-  /* Write a value spread accross multiple registers.  */
+  /* Write a value spread across multiple registers.  */
 
   gdb_assert (len > 4 && len % 4 == 0);
 
@@ -1581,15 +1608,15 @@ i386_value_to_register (struct frame_info *frame, int regnum,
     }
 }
 \f
-/* Supply register REGNUM from the general-purpose register set REGSET
-   to register cache REGCACHE.  If REGNUM is -1, do this for all
-   registers in REGSET.  */
+/* 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 = regset->descr;
+  const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
   const char *regs = gregs;
   int i;
 
@@ -1603,15 +1630,39 @@ i386_supply_gregset (const struct regset *regset, struct regcache *regcache,
     }
 }
 
-/* Supply register REGNUM from the floating-point register set REGSET
-   to register cache REGCACHE.  If REGNUM is -1, do this for all
-   registers in REGSET.  */
+/* 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_supply_fpregset (const struct regset *regset, struct regcache *regcache,
                      int regnum, const void *fpregs, size_t len)
 {
-  const struct gdbarch_tdep *tdep = regset->descr;
+  const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
 
   if (len == I387_SIZEOF_FXSAVE)
     {
@@ -1623,6 +1674,27 @@ i386_supply_fpregset (const struct regset *regset, struct regcache *regcache,
   i387_supply_fsave (regcache, regnum, fpregs);
 }
 
+/* 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_collect_fpregset (const struct regset *regset,
+                      const struct regcache *regcache,
+                      int regnum, void *fpregs, size_t len)
+{
+  const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
+
+  if (len == I387_SIZEOF_FXSAVE)
+    {
+      i387_collect_fxsave (regcache, regnum, fpregs);
+      return;
+    }
+
+  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.  */
 
@@ -1635,11 +1707,8 @@ i386_regset_from_core_section (struct gdbarch *gdbarch,
   if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset)
     {
       if (tdep->gregset == NULL)
-       {
-         tdep->gregset = XMALLOC (struct regset);
-         tdep->gregset->descr = tdep;
-         tdep->gregset->supply_regset = i386_supply_gregset;
-       }
+       tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset,
+                                     i386_collect_gregset);
       return tdep->gregset;
     }
 
@@ -1648,11 +1717,8 @@ i386_regset_from_core_section (struct gdbarch *gdbarch,
          && sect_size == I387_SIZEOF_FXSAVE))
     {
       if (tdep->fpregset == NULL)
-       {
-         tdep->fpregset = XMALLOC (struct regset);
-         tdep->fpregset->descr = tdep;
-         tdep->fpregset->supply_regset = i386_supply_fpregset;
-       }
+       tdep->fpregset = regset_alloc (gdbarch, i386_supply_fpregset,
+                                      i386_collect_fpregset);
       return tdep->fpregset;
     }
 
@@ -1782,16 +1848,6 @@ i386_svr4_sigcontext_addr (struct frame_info *next_frame)
 }
 \f
 
-/* Generic COFF.  */
-
-void
-i386_coff_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
-{
-  /* We typically use DWARF-in-COFF with the dbx register numbering.  */
-  set_gdbarch_dwarf_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
-  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
-}
-
 /* Generic ELF.  */
 
 void
@@ -1936,7 +1992,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->sizeof_fpregset = I387_SIZEOF_FSAVE;
 
   /* The default settings include the FPU registers, the MMX registers
-     and the SSE registers.  This can be overidden for a specific ABI
+     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
@@ -1952,7 +2008,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->st0_regnum = I386_ST0_REGNUM;
 
   /* The MMX registers are implemented as pseudo-registers.  Put off
-     caclulating the register number for %mm0 until we know the number
+     calculating the register number for %mm0 until we know the number
      of raw registers.  */
   tdep->mm0_regnum = 0;
 
@@ -1995,12 +2051,12 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* 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 attays
+     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 us used for AMD64; see
+     implemented in dbx64_register_map, and is used for AMD64; see
      amd64-tdep.c.
 
      Currently, each GCC i386 target always uses the same register
@@ -2019,8 +2075,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      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 the functions
-     i386_coff_init_abi() and i386_elf_init_abi() do.  */
+     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);
This page took 0.028157 seconds and 4 git commands to generate.