Add explicit #include of "value.h".
[deliverable/binutils-gdb.git] / gdb / i386-tdep.c
index 446b268481fb467333309dcea1769fabfa601736..d1a730cdc821cf1862946477d89e085f91be566a 100644 (file)
 #include "command.h"
 #include "arch-utils.h"
 #include "regcache.h"
+#include "doublest.h"
+#include "value.h"
+
+#include "gdb_assert.h"
 
 /* i386_register_byte[i] is the offset into the register file of the
    start of register number i.  We initialize this from
@@ -57,6 +61,68 @@ int i386_register_raw_size[MAX_NUM_REGS] = {
 /* i386_register_virtual_size[i] is the size in bytes of the virtual
    type of register i.  */
 int i386_register_virtual_size[MAX_NUM_REGS];
+
+/* Convert stabs register number REG to the appropriate register
+   number used by GDB.  */
+
+int
+i386_stab_reg_to_regnum (int reg)
+{
+  /* This implements what GCC calls the "default" register map.  */
+  if (reg >= 0 && reg <= 7)
+    {
+      /* General registers.  */
+      return reg;
+    }
+  else if (reg >= 12 && reg <= 19)
+    {
+      /* Floating-point registers.  */
+      return reg - 12 + FP0_REGNUM;
+    }
+  else if (reg >= 21 && reg <= 28)
+    {
+      /* SSE registers.  */
+      return reg - 21 + XMM0_REGNUM;
+    }
+  else if (reg >= 29 && reg <= 36)
+    {
+      /* MMX registers.  */
+      /* FIXME: kettenis/2001-07-28: Should we have the MMX registers
+         as pseudo-registers?  */
+      return reg - 29 + FP0_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.  */
+
+int
+i386_dwarf_reg_to_regnum (int reg)
+{
+  /* The DWARF register numbering includes %eip and %eflags, and
+     numbers the floating point registers differently.  */
+  if (reg >= 0 && reg <= 9)
+    {
+      /* General registers.  */
+      return reg;
+    }
+  else if (reg >= 11 && reg <= 18)
+    {
+      /* Floating-point registers.  */
+      return reg - 11 + FP0_REGNUM;
+    }
+  else if (reg >= 21)
+    {
+      /* The SSE and MMX registers have identical numbers as in stabs.  */
+      return i386_stab_reg_to_regnum (reg);
+    }
+
+  /* This will hopefully provoke a warning.  */
+  return NUM_REGS + NUM_PSEUDO_REGS;
+}
 \f
 
 /* This is the variable that is set with "set disassembly-flavor", and
@@ -378,6 +444,23 @@ i386_frameless_function_invocation (struct frame_info *frame)
   return frameless_look_for_prologue (frame);
 }
 
+/* Return the saved program counter for FRAME.  */
+
+CORE_ADDR
+i386_frame_saved_pc (struct frame_info *frame)
+{
+  /* FIXME: kettenis/2001-05-09: Conditionalizing the next bit of code
+     on SIGCONTEXT_PC_OFFSET and I386V4_SIGTRAMP_SAVED_PC should be
+     considered a temporary hack.  I plan to come up with something
+     better when we go multi-arch.  */
+#if defined (SIGCONTEXT_PC_OFFSET) || defined (I386V4_SIGTRAMP_SAVED_PC)
+  if (frame->signal_handler_caller)
+    return sigtramp_saved_pc (frame);
+#endif
+
+  return read_memory_unsigned_integer (frame->frame + 4, 4);
+}
+
 /* Immediately after a function call, return the saved pc.  */
 
 CORE_ADDR
@@ -652,7 +735,7 @@ i386_push_dummy_frame (void)
 
 void
 i386_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
-                    value_ptr *args, struct type *type, int gcc_p)
+                    struct value **args, struct type *type, int gcc_p)
 {
   int from, to, delta, loc;
 
@@ -732,7 +815,7 @@ get_longjmp_target (CORE_ADDR *pc)
 \f
 
 CORE_ADDR
-i386_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp,
+i386_push_arguments (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);
@@ -844,13 +927,18 @@ i386_store_return_value (struct type *type, char *valbuf)
 
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
+      unsigned int fstat;
+
       if (NUM_FREGS == 0)
        {
          warning ("Cannot set floating-point return value.");
          return;
        }
 
-      /* Floating-point return values can be found in %st(0).  */
+      /* Returning floating-point values is a bit tricky.  Apart from
+         storing the return value in %st(0), we have to simulate the
+         state of the FPU at function return point.  */
+
       if (len == TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT
          && TARGET_LONG_DOUBLE_FORMAT == &floatformat_i387_ext)
        {
@@ -864,7 +952,7 @@ i386_store_return_value (struct type *type, char *valbuf)
          DOUBLEST val;
 
          /* Convert the value found in VALBUF to the extended
-             floating point format used by the FPU.  This is probably
+             floating-point format used by the FPU.  This is probably
              not exactly how it would happen on the target itself, but
              it is the best we can do.  */
          val = extract_floating (valbuf, TYPE_LENGTH (type));
@@ -872,6 +960,19 @@ i386_store_return_value (struct type *type, char *valbuf)
          write_register_bytes (REGISTER_BYTE (FP0_REGNUM), buf,
                                FPU_REG_RAW_SIZE);
        }
+
+      /* 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.  */
+      fstat = read_register (FSTAT_REGNUM);
+      fstat |= (7 << 11);
+      write_register (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.  */
+      write_register (FTAG_REGNUM, 0x3fff);
     }
   else
     {
@@ -937,27 +1038,45 @@ i386_register_convertible (int regnum)
 }
 
 /* Convert data from raw format for register REGNUM in buffer FROM to
-   virtual format with type TYPE in buffer TO.  In principle both
-   formats are identical except that the virtual format has two extra
-   bytes appended that aren't used.  We set these to zero.  */
+   virtual format with type TYPE in buffer TO.  */
 
 void
 i386_register_convert_to_virtual (int regnum, struct type *type,
                                  char *from, char *to)
 {
-  /* Copy straight over, but take care of the padding.  */
-  memcpy (to, from, FPU_REG_RAW_SIZE);
-  memset (to + FPU_REG_RAW_SIZE, 0, TYPE_LENGTH (type) - FPU_REG_RAW_SIZE);
+  char buf[12];
+  DOUBLEST d;
+
+  /* We only support floating-point values.  */
+  if (TYPE_CODE (type) != TYPE_CODE_FLT)
+    {
+      warning ("Cannot convert floating-point register value "
+              "to non-floating-point type.");
+      memset (to, 0, TYPE_LENGTH (type));
+      return;
+    }
+
+  /* First add the necessary padding.  */
+  memcpy (buf, from, FPU_REG_RAW_SIZE);
+  memset (buf + FPU_REG_RAW_SIZE, 0, sizeof buf - FPU_REG_RAW_SIZE);
+
+  /* Convert to TYPE.  This should be a no-op, if TYPE is equivalent
+     to the extended floating-point format used by the FPU.  */
+  d = extract_floating (buf, sizeof buf);
+  store_floating (to, TYPE_LENGTH (type), d);
 }
 
 /* Convert data from virtual format with type TYPE in buffer FROM to
-   raw format for register REGNUM in buffer TO.  Simply omit the two
-   unused bytes.  */
+   raw format for register REGNUM in buffer TO.  */
 
 void
 i386_register_convert_to_raw (struct type *type, int regnum,
                              char *from, char *to)
 {
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT
+             && TYPE_LENGTH (type) == 12);
+
+  /* Simply omit the two unused bytes.  */
   memcpy (to, from, FPU_REG_RAW_SIZE);
 }
 \f     
This page took 0.030884 seconds and 4 git commands to generate.