/* 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.
#include "osabi.h"
#include "regcache.h"
#include "reggroups.h"
+#include "regset.h"
#include "symfile.h"
#include "symtab.h"
#include "target.h"
#include "value.h"
+#include "dis-asm.h"
#include "gdb_assert.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[] =
{
"mxcsr"
};
-static const int i386_num_register_names =
- (sizeof (i386_register_names) / sizeof (*i386_register_names));
+static const int i386_num_register_names = ARRAY_SIZE (i386_register_names);
-/* MMX registers. */
+/* Register names for MMX pseudo-registers. */
static char *i386_mmx_names[] =
{
"mm4", "mm5", "mm6", "mm7"
};
-static const int i386_num_mmx_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 regnum)
+i386_mmx_regnum_p (struct gdbarch *gdbarch, int regnum)
{
- return (regnum >= MM0_REGNUM
- && regnum < MM0_REGNUM + i386_num_mmx_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 (i386_mmx_regnum_p (reg))
- return i386_mmx_names[reg - MM0_REGNUM];
+ if (i386_mmx_regnum_p (current_gdbarch, regnum))
+ return i386_mmx_names[regnum - I387_MM0_REGNUM];
- if (reg >= 0 && reg < i386_num_register_names)
- return i386_register_names[reg];
+ if (regnum >= 0 && regnum < i386_num_register_names)
+ return i386_register_names[regnum];
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-purpose 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)
{
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
and can be inserted anywhere.
This function is 64-bit safe. */
-
-static const unsigned char *
+
+static const gdb_byte *
i386_breakpoint_from_pc (CORE_ADDR *pc, int *len)
{
- static unsigned char break_insn[] = { 0xcc }; /* int 3 */
-
+ static gdb_byte break_insn[] = { 0xcc }; /* int 3 */
+
*len = sizeof (break_insn);
return break_insn;
}
static CORE_ADDR
i386_follow_jump (CORE_ADDR pc)
{
- unsigned char op;
+ gdb_byte op;
long delta = 0;
int data16 = 0;
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;
+ static gdb_byte proto1[3] = { 0x87, 0x04, 0x24 };
+ static gdb_byte proto2[4] = { 0x87, 0x44, 0x24, 0x00 };
+ gdb_byte buf[4];
+ gdb_byte op;
if (current_pc <= pc)
return pc;
pushl %ebp
etc. */
- unsigned char buf[8];
- unsigned char op;
+ gdb_byte buf[8];
+ gdb_byte op;
op = read_memory_unsigned_integer (pc, 1);
return pc;
}
+/* Maximum instruction length we need to handle. */
+#define I386_MAX_INSN_LEN 6
+
+/* Instruction description. */
+struct i386_insn
+{
+ size_t len;
+ gdb_byte insn[I386_MAX_INSN_LEN];
+ gdb_byte 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;
+ gdb_byte 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 removes the "hidden"
- argument from the stack or CURRENT_PC, whichever is smaller.
- Otherwise, return PC. */
+ 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 current_pc,
+i386_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR limit,
struct i386_frame_cache *cache)
{
- unsigned char op;
+ struct i386_insn *insn;
+ gdb_byte op;
int skip = 0;
- if (current_pc <= pc)
- return current_pc;
+ if (limit <= pc)
+ return limit;
op = read_memory_unsigned_integer (pc, 1);
starts this instruction sequence. */
cache->saved_regs[I386_EBP_REGNUM] = 0;
cache->sp_offset += 4;
+ pc++;
/* If that's all, return now. */
- if (current_pc <= pc + 1)
- return current_pc;
-
- op = read_memory_unsigned_integer (pc + 1, 1);
-
- /* Check for some special instructions that might be migrated
- by GCC into the prologue. We check for
-
- xorl %ebx, %ebx
- xorl %ecx, %ecx
- xorl %edx, %edx
+ if (limit <= pc)
+ return limit;
- and the equivalent
-
- subl %ebx, %ebx
- subl %ecx, %ecx
- subl %edx, %edx
+ /* 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 (op == 0x29 || op == 0x31)
+ while (pc + skip < limit)
{
- op = read_memory_unsigned_integer (pc + skip + 2, 1);
- switch (op)
- {
- case 0xdb: /* %ebx */
- case 0xc9: /* %ecx */
- case 0xd2: /* %edx */
- skip += 2;
- break;
- default:
- return pc + 1;
- }
+ insn = i386_match_insn (pc + skip, i386_frame_setup_skip_insns);
+ if (insn == NULL)
+ break;
- op = read_memory_unsigned_integer (pc + skip + 1, 1);
+ 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 (read_memory_unsigned_integer (pc + skip + 2, 1) != 0xec)
- return pc + 1;
+ if (read_memory_unsigned_integer (pc + skip + 1, 1) != 0xec)
+ return pc;
break;
case 0x89:
- if (read_memory_unsigned_integer (pc + skip + 2, 1) != 0xe5)
- return pc + 1;
+ if (read_memory_unsigned_integer (pc + skip + 1, 1) != 0xe5)
+ return pc;
break;
default:
- return pc + 1;
+ return pc;
}
/* OK, we actually have a frame. We just don't know how large
necessary. We also now commit to skipping the special
instructions mentioned before. */
cache->locals = 0;
- pc += skip;
+ pc += (skip + 2);
/* If that's all, return now. */
- if (current_pc <= pc + 3)
- return current_pc;
+ if (limit <= pc)
+ return limit;
/* Check for stack adjustment
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);
+ op = read_memory_unsigned_integer (pc, 1);
if (op == 0x83)
{
- /* `subl' with 8 bit immediate. */
- if (read_memory_unsigned_integer (pc + 4, 1) != 0xec)
+ /* `subl' with 8-bit immediate. */
+ if (read_memory_unsigned_integer (pc + 1, 1) != 0xec)
/* Some instruction starting with 0x83 other than `subl'. */
- return pc + 3;
+ return pc;
- /* `subl' with signed byte immediate (though it wouldn't make
- sense to be negative). */
- cache->locals = read_memory_integer (pc + 5, 1);
- return pc + 6;
+ /* `subl' with signed 8-bit immediate (though it wouldn't
+ make sense to be negative). */
+ cache->locals = read_memory_integer (pc + 2, 1);
+ return pc + 3;
}
else if (op == 0x81)
{
- /* Maybe it is `subl' with a 32 bit immedediate. */
- if (read_memory_unsigned_integer (pc + 4, 1) != 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'. */
- return pc + 3;
+ return pc;
- /* It is `subl' with a 32 bit immediate. */
- cache->locals = read_memory_integer (pc + 5, 4);
- return pc + 9;
+ /* It is `subl' with a 32-bit immediate. */
+ cache->locals = read_memory_integer (pc + 2, 4);
+ return pc + 6;
}
else
{
/* Some instruction other than `subl'. */
- return pc + 3;
+ return pc;
}
}
- else if (op == 0xc8) /* enter $XXX */
+ else if (op == 0xc8) /* enter */
{
cache->locals = read_memory_unsigned_integer (pc + 1, 2);
return pc + 4;
i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
struct i386_frame_cache *cache)
{
- if (cache->locals >= 0)
- {
- CORE_ADDR offset;
- unsigned char op;
- int i;
+ CORE_ADDR offset = 0;
+ gdb_byte op;
+ int i;
- offset = - 4 - 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 (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;
- cache->saved_regs[op - 0x50] = offset;
- offset -= 4;
- pc++;
- }
+ offset -= 4;
+ cache->saved_regs[op - 0x50] = offset;
+ cache->sp_offset += 4;
+ pc++;
}
return 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,
static CORE_ADDR
i386_skip_prologue (CORE_ADDR start_pc)
{
- static unsigned char pic_pat[6] =
+ static gdb_byte pic_pat[6] =
{
0xe8, 0, 0, 0, 0, /* call 0x0 */
0x5b, /* popl %ebx */
};
struct i386_frame_cache cache;
CORE_ADDR pc;
- unsigned char op;
+ gdb_byte op;
int i;
cache.locals = -1;
}
}
- 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. */
static CORE_ADDR
i386_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
- char buf[8];
+ gdb_byte buf[8];
frame_unwind_register (next_frame, PC_REGNUM, buf);
return extract_typed_address (buf, builtin_type_void_func_ptr);
i386_frame_cache (struct frame_info *next_frame, void **this_cache)
{
struct i386_frame_cache *cache;
- char buf[4];
+ gdb_byte buf[4];
int i;
if (*this_cache)
if (regnum == I386_EIP_REGNUM && cache->pc_in_eax)
{
- frame_register_unwind (next_frame, I386_EAX_REGNUM,
- optimizedp, lvalp, addrp, realnump, valuep);
+ *optimizedp = 0;
+ *lvalp = lval_register;
+ *addrp = 0;
+ *realnump = I386_EAX_REGNUM;
+ if (valuep)
+ frame_unwind_register (next_frame, (*realnump), valuep);
return;
}
return;
}
- frame_register_unwind (next_frame, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
+ *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 =
struct i386_frame_cache *cache;
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
CORE_ADDR addr;
- char buf[4];
+ gdb_byte buf[4];
if (*this_cache)
return *this_cache;
static const struct frame_unwind *
i386_sigtramp_frame_sniffer (struct frame_info *next_frame)
{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
- char *name;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame));
- /* We shouldn't even bother to try if the OSABI didn't register
- a sigcontext_addr handler. */
- if (!gdbarch_tdep (current_gdbarch)->sigcontext_addr)
+ /* We shouldn't even bother if we don't have a sigcontext_addr
+ handler. */
+ if (tdep->sigcontext_addr == NULL)
return NULL;
- find_pc_partial_function (pc, &name, NULL, NULL);
- if (PC_IN_SIGTRAMP (pc, name))
- return &i386_sigtramp_frame_unwind;
+ if (tdep->sigtramp_p != NULL)
+ {
+ 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;
+ }
return NULL;
}
static struct frame_id
i386_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
- char buf[4];
+ gdb_byte buf[4];
CORE_ADDR fp;
frame_unwind_register (next_frame, I386_EBP_REGNUM, buf);
static int
i386_get_longjmp_target (CORE_ADDR *pc)
{
- char buf[8];
+ gdb_byte buf[8];
CORE_ADDR sp, jb_addr;
int jb_pc_offset = gdbarch_tdep (current_gdbarch)->jb_pc_offset;
int len = TYPE_LENGTH (builtin_type_void_func_ptr);
\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)
{
- char buf[4];
+ gdb_byte buf[4];
int i;
/* Push arguments in reverse order. */
for (i = nargs - 1; i >= 0; i--)
{
- int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
+ int len = TYPE_LENGTH (value_enclosing_type (args[i]));
/* The System V ABI says that:
This makes sure the stack says word-aligned. */
sp -= (len + 3) & ~3;
- write_memory (sp, VALUE_CONTENTS_ALL (args[i]), len);
+ write_memory (sp, value_contents_all (args[i]), len);
}
/* Push value address. */
(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
#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, gdb_byte *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;
- }
+ gdb_byte buf[I386_MAX_REGISTER_SIZE];
if (TYPE_CODE (type) == TYPE_CODE_FLT)
{
- if (FP0_REGNUM < 0)
+ if (tdep->st0_regnum < 0)
{
- warning ("Cannot find floating-point return value.");
+ warning (_("Cannot find floating-point return value."));
memset (valbuf, 0, len);
return;
}
}
else
internal_error (__FILE__, __LINE__,
- "Cannot extract return value of %d bytes long.", len);
+ _("Cannot extract return value of %d bytes long."), len);
}
}
-/* 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 gdb_byte *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];
+ gdb_byte buf[I386_MAX_REGISTER_SIZE];
- if (FP0_REGNUM < 0)
+ if (tdep->st0_regnum < 0)
{
- warning ("Cannot set floating-point return value.");
+ warning (_("Cannot set floating-point return value."));
return;
}
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
{
{
regcache_raw_write (regcache, LOW_RETURN_REGNUM, valbuf);
regcache_raw_write_part (regcache, HIGH_RETURN_REGNUM, 0,
- len - low_size, (char *) valbuf + low_size);
+ len - low_size, valbuf + low_size);
}
else
internal_error (__FILE__, __LINE__,
- "Cannot store return value of %d bytes long.", len);
+ _("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)
-{
- char buf[4];
- regcache_cooked_read (regcache, I386_EAX_REGNUM, buf);
- return extract_unsigned_integer (buf, 4);
+#undef I387_ST0_REGNUM
}
\f
};
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, gdb_byte *readbuf,
+ const gdb_byte *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
+/* Types for the MMX and SSE registers. */
+static struct type *i386_mmx_type;
+static struct type *i386_sse_type;
+
+/* Construct the type for MMX registers. */
+static struct type *
+i386_build_mmx_type (void)
+{
+ /* The type we're building is this: */
+#if 0
+ union __gdb_builtin_type_vec64i
+ {
+ int64_t uint64;
+ int32_t v2_int32[2];
+ int16_t v4_int16[4];
+ int8_t v8_int8[8];
+ };
+#endif
+
+ if (! i386_mmx_type)
+ {
+ struct type *t;
+
+ t = init_composite_type ("__gdb_builtin_type_vec64i", TYPE_CODE_UNION);
+ append_composite_type_field (t, "uint64", builtin_type_int64);
+ append_composite_type_field (t, "v2_int32", builtin_type_v2_int32);
+ append_composite_type_field (t, "v4_int16", builtin_type_v4_int16);
+ append_composite_type_field (t, "v8_int8", builtin_type_v8_int8);
+
+ TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+ TYPE_NAME (t) = "builtin_type_vec64i";
+
+ i386_mmx_type = t;
+ }
+
+ return i386_mmx_type;
+}
+
+/* Construct the type for SSE registers. */
+static struct type *
+i386_build_sse_type (void)
+{
+ if (! i386_sse_type)
+ {
+ struct type *t;
+
+ t = init_composite_type ("__gdb_builtin_type_vec128i", TYPE_CODE_UNION);
+ append_composite_type_field (t, "v4_float", builtin_type_v4_float);
+ append_composite_type_field (t, "v2_double", builtin_type_v2_double);
+ append_composite_type_field (t, "v16_int8", builtin_type_v16_int8);
+ append_composite_type_field (t, "v8_int16", builtin_type_v8_int16);
+ append_composite_type_field (t, "v4_int32", builtin_type_v4_int32);
+ append_composite_type_field (t, "v2_int64", builtin_type_v2_int64);
+ append_composite_type_field (t, "uint128", builtin_type_int128);
+
+ TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+ TYPE_NAME (t) = "builtin_type_vec128i";
+
+ i386_sse_type = t;
+ }
+
+ return i386_sse_type;
+}
+
/* Return the GDB type object for the "standard" data type of data in
register REGNUM. Perhaps %esi and %edi should go here, but
potentially they could be used for things other than address. */
if (i386_fp_regnum_p (regnum))
return builtin_type_i387_ext;
- if (i386_sse_regnum_p (regnum))
- return builtin_type_vec128i;
+ if (i386_sse_regnum_p (gdbarch, regnum))
+ return i386_build_sse_type ();
- if (i386_mmx_regnum_p (regnum))
- return builtin_type_vec64i;
+ if (i386_mmx_regnum_p (gdbarch, regnum))
+ return i386_build_mmx_type ();
return builtin_type_int;
}
static int
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;
+ fpreg = (mmxreg + tos) % 8;
- return (FP0_REGNUM + fpi);
+ 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)
+ int regnum, gdb_byte *buf)
{
- if (i386_mmx_regnum_p (regnum))
+ if (i386_mmx_regnum_p (gdbarch, regnum))
{
- char mmx_buf[MAX_REGISTER_SIZE];
+ gdb_byte mmx_buf[MAX_REGISTER_SIZE];
int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
/* Extract (always little endian). */
static void
i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
- int regnum, const void *buf)
+ int regnum, const gdb_byte *buf)
{
- if (i386_mmx_regnum_p (regnum))
+ if (i386_mmx_regnum_p (gdbarch, regnum))
{
- char mmx_buf[MAX_REGISTER_SIZE];
+ gdb_byte mmx_buf[MAX_REGISTER_SIZE];
int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
/* Read ... */
}
\f
-/* These registers don't have pervasive standard uses. Move them to
- i386-tdep.h if necessary. */
-
-#define I386_EBX_REGNUM 3 /* %ebx */
-#define I386_ECX_REGNUM 1 /* %ecx */
-#define I386_ESI_REGNUM 6 /* %esi */
-#define I386_EDI_REGNUM 7 /* %edi */
-
/* Return the register number of the register allocated by GCC after
REGNUM, or -1 if there is no such register. */
static void
i386_register_to_value (struct frame_info *frame, int regnum,
- struct type *type, void *to)
+ struct type *type, gdb_byte *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)? */
return;
}
- /* Read a value spread accross multiple registers. */
+ /* Read a value spread across multiple registers. */
gdb_assert (len > 4 && len % 4 == 0);
gdb_assert (regnum != -1);
gdb_assert (register_size (current_gdbarch, regnum) == 4);
- get_frame_register (frame, regnum, buf);
+ get_frame_register (frame, regnum, to);
regnum = i386_next_regnum (regnum);
len -= 4;
- buf += 4;
+ to += 4;
}
}
static void
i386_value_to_register (struct frame_info *frame, int regnum,
- struct type *type, const void *from)
+ struct type *type, const gdb_byte *from)
{
int len = TYPE_LENGTH (type);
- const char *buf = from;
if (i386_fp_regnum_p (regnum))
{
return;
}
- /* Write a value spread accross multiple registers. */
+ /* Write a value spread across multiple registers. */
gdb_assert (len > 4 && len % 4 == 0);
gdb_assert (regnum != -1);
gdb_assert (register_size (current_gdbarch, regnum) == 4);
- put_frame_register (frame, regnum, buf);
+ put_frame_register (frame, regnum, from);
regnum = i386_next_regnum (regnum);
len -= 4;
- buf += 4;
+ from += 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 gdb_byte *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);
+ gdb_byte *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 = gdbarch_tdep (regset->arch);
+
+ if (len == I387_SIZEOF_FXSAVE)
+ {
+ i387_supply_fxsave (regcache, regnum, fpregs);
+ return;
+ }
+
+ gdb_assert (len == tdep->sizeof_fpregset);
+ i387_supply_fsave (regcache, regnum, fpregs);
+}
+
+/* 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_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. */
+
+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
#ifdef STATIC_TRANSFORM_NAME
/* SunPRO encodes the static variables. This is not related to C++
}
\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
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);
/* 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));
static CORE_ADDR
i386_svr4_sigcontext_addr (struct frame_info *next_frame)
{
- char buf[4];
+ gdb_byte buf[4];
CORE_ADDR sp;
frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
}
\f
-/* DJGPP. */
-
-static int
-i386_go32_pc_in_sigtramp (CORE_ADDR pc, char *name)
-{
- /* DJGPP doesn't have any special frames for signal handlers. */
- return 0;
-}
-\f
-
/* Generic ELF. */
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). */
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 = 36 + 14 * 4;
tdep->sc_sp_offset = 36 + 17 * 4;
{
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;
}
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;
tdep = XMALLOC (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
- /* 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;
+ /* General-purpose registers. */
+ tdep->gregset = NULL;
+ tdep->gregset_reg_offset = NULL;
+ tdep->gregset_num_regs = I386_NUM_GREGS;
+ tdep->sizeof_gregset = 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;
alignment. */
set_gdbarch_long_double_bit (gdbarch, 96);
- /* The default ABI includes general-purpose registers and
- floating-point registers. */
- set_gdbarch_num_regs (gdbarch, I386_NUM_GREGS + I386_NUM_FREGS);
+ /* 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);
set_gdbarch_ps_regnum (gdbarch, I386_EFLAGS_REGNUM); /* %eflags */
set_gdbarch_fp0_regnum (gdbarch, I386_ST0_REGNUM); /* %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);
-
- /* 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);
+ /* 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_to_value (gdbarch, i386_register_to_value);
set_gdbarch_value_to_register (gdbarch, i386_value_to_register);
- set_gdbarch_extract_return_value (gdbarch, i386_extract_return_value);
- 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_return_value (gdbarch, i386_return_value);
set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
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);
set_gdbarch_frame_args_skip (gdbarch, 8);
- set_gdbarch_pc_in_sigtramp (gdbarch, i386_pc_in_sigtramp);
/* Wire in the MMX registers. */
set_gdbarch_num_pseudo_regs (gdbarch, i386_num_mmx_regs);
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;
}
register_gdbarch_init (bfd_arch_i386, i386_gdbarch_init);
/* Add the variable that controls the disassembly flavor. */
- {
- struct cmd_list_element *new_cmd;
-
- new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class,
- valid_flavors,
- &disassembly_flavor,
- "\
-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);
- }
+ add_setshow_enum_cmd ("disassembly-flavor", no_class, valid_flavors,
+ &disassembly_flavor, _("\
+Set the disassembly flavor."), _("\
+Show the disassembly flavor."), _("\
+The valid values are \"att\" and \"intel\", and the default value is \"att\"."),
+ NULL,
+ NULL, /* FIXME: i18n: */
+ &setlist, &showlist);
/* Add the variable that controls the convention for returning
structs. */
- {
- struct cmd_list_element *new_cmd;
-
- new_cmd = add_set_enum_cmd ("struct-convention", no_class,
- valid_conventions,
- &struct_convention, "\
-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);
- }
+ add_setshow_enum_cmd ("struct-convention", no_class, valid_conventions,
+ &struct_convention, _("\
+Set the convention for returning small structs."), _("\
+Show the convention for returning small structs."), _("\
+Valid values are \"default\", \"pcc\" and \"reg\", and the default value\n\
+is \"default\"."),
+ NULL,
+ NULL, /* FIXME: i18n: */
+ &setlist, &showlist);
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
i386_coff_osabi_sniffer);