#include "gdb_assert.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. */
"mxcsr"
};
-/* i386_register_offset[i] is the offset into the register file of the
- start of register number i. We initialize this from
- i386_register_size. */
-static int i386_register_offset[I386_SSE_NUM_REGS];
-
-/* i386_register_size[i] is the number of bytes of storage in GDB's
- register array occupied by register i. */
-static int i386_register_size[I386_SSE_NUM_REGS] = {
- 4, 4, 4, 4,
- 4, 4, 4, 4,
- 4, 4, 4, 4,
- 4, 4, 4, 4,
- 10, 10, 10, 10,
- 10, 10, 10, 10,
- 4, 4, 4, 4,
- 4, 4, 4, 4,
- 16, 16, 16, 16,
- 16, 16, 16, 16,
- 4
+/* MMX 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 int
+mmx_regnum_p (int reg)
+{
+ return (reg >= MM0_REGNUM && reg < MM0_REGNUM + mmx_num_regs);
+}
/* Return the name of register REG. */
{
if (reg < 0)
return NULL;
+ if (mmx_regnum_p (reg))
+ return i386_mmx_names[reg - MM0_REGNUM];
if (reg >= sizeof (i386_register_names) / sizeof (*i386_register_names))
return NULL;
return i386_register_names[reg];
}
-/* Return the offset into the register array of the start of register
- number REG. */
-int
-i386_register_byte (int reg)
-{
- return i386_register_offset[reg];
-}
-
-/* Return the number of bytes of storage in GDB's register array
- occupied by register REG. */
-
-int
-i386_register_raw_size (int reg)
-{
- return i386_register_size[reg];
-}
-
/* Convert stabs register number REG to the appropriate register
number used by GDB. */
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;
+ return reg - 29 + MM0_REGNUM;
}
/* This will hopefully provoke a warning. */
static CORE_ADDR
i386_extract_struct_value_address (struct regcache *regcache)
{
- return regcache_raw_read_as_address (regcache, LOW_RETURN_REGNUM);
+ /* NOTE: cagney/2002-08-12: Replaced a call to
+ regcache_raw_read_as_address() with a call to
+ regcache_cooked_read_unsigned(). The old, ...as_address function
+ was eventually calling extract_unsigned_integer (via
+ extract_address) to unpack the registers value. The below is
+ doing an unsigned extract so that it is functionally equivalent.
+ The read needs to be cooked as, otherwise, it will never
+ correctly return the value of a register in the [NUM_REGS
+ .. NUM_REGS+NUM_PSEUDO_REGS) range. */
+ ULONGEST val;
+ regcache_cooked_read_unsigned (regcache, LOW_RETURN_REGNUM, &val);
+ return val;
}
\f
if (IS_SSE_REGNUM (regnum))
return builtin_type_vec128i;
+ if (mmx_regnum_p (regnum))
+ return builtin_type_vec64i;
+
return builtin_type_int;
}
+/* Map a cooked register onto a raw register or memory. For the i386,
+ the MMX registers need to be mapped onto floating point registers. */
+
+static int
+mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
+{
+ int mmxi;
+ ULONGEST fstat;
+ int tos;
+ int fpi;
+ mmxi = regnum - MM0_REGNUM;
+ regcache_raw_read_unsigned (regcache, FSTAT_REGNUM, &fstat);
+ tos = (fstat >> 11) & 0x7;
+ fpi = (mmxi + tos) % 8;
+ return (FP0_REGNUM + fpi);
+}
+
+static void
+i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+ int regnum, void *buf)
+{
+ if (mmx_regnum_p (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);
+ /* Extract (always little endian). */
+ memcpy (buf, mmx_buf, REGISTER_RAW_SIZE (regnum));
+ }
+ else
+ regcache_raw_read (regcache, regnum, buf);
+}
+
+static void
+i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+ int regnum, const void *buf)
+{
+ if (mmx_regnum_p (regnum))
+ {
+ char *mmx_buf = alloca (MAX_REGISTER_RAW_SIZE);
+ int fpnum = 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));
+ /* ... Write. */
+ regcache_raw_write (regcache, fpnum, mmx_buf);
+ }
+ else
+ regcache_raw_write (regcache, regnum, buf);
+}
+
/* 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
/* Stuff for WIN32 PE style DLL's but is pretty generic really. */
CORE_ADDR
-skip_trampoline_code (CORE_ADDR pc, char *name)
+i386_pe_skip_trampoline_code (CORE_ADDR pc, char *name)
{
if (pc && read_memory_unsigned_integer (pc, 2) == 0x25ff) /* jmp *(dest) */
{
i386_elf_init_abi (info, gdbarch);
/* FIXME: kettenis/20020511: Why do we override this function here? */
- set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
+ set_gdbarch_frame_chain_valid (gdbarch, generic_func_frame_chain_valid);
set_gdbarch_pc_in_sigtramp (gdbarch, i386_svr4_pc_in_sigtramp);
tdep->sigcontext_addr = i386_svr4_sigcontext_addr;
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* FIXME: kettenis/20020511: Why do we override this function here? */
- set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
+ set_gdbarch_frame_chain_valid (gdbarch, generic_func_frame_chain_valid);
tdep->jb_pc_offset = 24;
}
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_byte (gdbarch, i386_register_byte);
- set_gdbarch_register_raw_size (gdbarch, i386_register_raw_size);
set_gdbarch_max_register_raw_size (gdbarch, I386_MAX_REGISTER_SIZE);
set_gdbarch_max_register_virtual_size (gdbarch, I386_MAX_REGISTER_SIZE);
set_gdbarch_register_virtual_type (gdbarch, i386_register_virtual_type);
+ set_gdbarch_print_float_info (gdbarch, i387_print_float_info);
+
set_gdbarch_get_longjmp_target (gdbarch, i386_get_longjmp_target);
set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
i386_register_convert_to_virtual);
set_gdbarch_register_convert_to_raw (gdbarch, i386_register_convert_to_raw);
- set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register);
+ set_gdbarch_get_saved_register (gdbarch, generic_unwind_get_saved_register);
set_gdbarch_push_arguments (gdbarch, i386_push_arguments);
set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
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_pseudo_register_read (gdbarch, i386_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
+
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch, osabi);
{
register_gdbarch_init (bfd_arch_i386, i386_gdbarch_init);
- /* Initialize the table saying where each register starts in the
- register file. */
- {
- int i, offset;
-
- offset = 0;
- for (i = 0; i < I386_SSE_NUM_REGS; i++)
- {
- i386_register_offset[i] = offset;
- offset += i386_register_size[i];
- }
- }
-
tm_print_insn = gdb_print_insn_i386;
tm_print_insn_info.mach = bfd_lookup_arch (bfd_arch_i386, 0)->mach;