#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
/* 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
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
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;
\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);
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)
{
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));
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
{
}
/* 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