/* Intel 386 target-dependent stuff.
- Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
- 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software
- Foundation, Inc.
+ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "arch-utils.h"
#include "dummy-frame.h"
#include "dwarf2-frame.h"
#include "doublest.h"
-#include "floatformat.h"
#include "frame.h"
#include "frame-base.h"
#include "frame-unwind.h"
#include "inferior.h"
#include "gdbcmd.h"
#include "gdbcore.h"
+#include "gdbtypes.h"
#include "objfiles.h"
#include "osabi.h"
#include "regcache.h"
/* Return the name of register REGNUM. */
const char *
-i386_register_name (int regnum)
+i386_register_name (struct gdbarch *gdbarch, int regnum)
{
- if (i386_mmx_regnum_p (current_gdbarch, regnum))
+ if (i386_mmx_regnum_p (gdbarch, regnum))
return i386_mmx_names[regnum - I387_MM0_REGNUM];
if (regnum >= 0 && regnum < i386_num_register_names)
number used by GDB. */
static int
-i386_dbx_reg_to_regnum (int reg)
+i386_dbx_reg_to_regnum (struct gdbarch *gdbarch, int reg)
{
/* This implements what GCC calls the "default" register map
(dbx_register_map[]). */
}
/* This will hopefully provoke a warning. */
- return NUM_REGS + NUM_PSEUDO_REGS;
+ return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
}
/* Convert SVR4 register number REG to the appropriate register number
used by GDB. */
static int
-i386_svr4_reg_to_regnum (int reg)
+i386_svr4_reg_to_regnum (struct gdbarch *gdbarch, int reg)
{
/* This implements the GCC register map that tries to be compatible
with the SVR4 C compiler for DWARF (svr4_dbx_register_map[]). */
/* Floating-point registers. */
return reg - 11 + I387_ST0_REGNUM;
}
- else if (reg >= 21)
+ else if (reg >= 21 && reg <= 36)
{
/* The SSE and MMX registers have the same numbers as with dbx. */
- return i386_dbx_reg_to_regnum (reg);
+ return i386_dbx_reg_to_regnum (gdbarch, reg);
+ }
+
+ switch (reg)
+ {
+ case 37: return I387_FCTRL_REGNUM;
+ case 38: return I387_FSTAT_REGNUM;
+ case 39: return I387_MXCSR_REGNUM;
+ case 40: return I386_ES_REGNUM;
+ case 41: return I386_CS_REGNUM;
+ case 42: return I386_SS_REGNUM;
+ case 43: return I386_DS_REGNUM;
+ case 44: return I386_FS_REGNUM;
+ case 45: return I386_GS_REGNUM;
}
/* This will hopefully provoke a warning. */
- return NUM_REGS + NUM_PSEUDO_REGS;
+ return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
}
#undef I387_ST0_REGNUM
This function is 64-bit safe. */
static const gdb_byte *
-i386_breakpoint_from_pc (CORE_ADDR *pc, int *len)
+i386_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc, int *len)
{
static gdb_byte break_insn[] = { 0xcc }; /* int 3 */
{
/* Base address. */
CORE_ADDR base;
- CORE_ADDR sp_offset;
+ LONGEST sp_offset;
CORE_ADDR pc;
/* Saved registers. */
CORE_ADDR saved_regs[I386_NUM_SAVED_REGS];
CORE_ADDR saved_sp;
+ int stack_align;
int pc_in_eax;
/* Stack space reserved for local variables. */
for (i = 0; i < I386_NUM_SAVED_REGS; i++)
cache->saved_regs[i] = -1;
cache->saved_sp = 0;
+ cache->stack_align = 0;
cache->pc_in_eax = 0;
/* Frameless until proven otherwise. */
long delta = 0;
int data16 = 0;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op == 0x66)
{
data16 = 1;
if (current_pc <= pc)
return pc;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op != 0x58) /* popl %eax */
return pc;
- read_memory (pc + 1, buf, 4);
+ read_memory_nobpt (pc + 1, buf, 4);
if (memcmp (buf, proto1, 3) != 0 && memcmp (buf, proto2, 4) != 0)
return pc;
gdb_byte buf[8];
gdb_byte op;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op == 0x68 || op == 0x6a)
{
return pc;
}
+/* GCC 4.1 and later, can put code in the prologue to realign the
+ stack pointer. Check whether PC points to such code, and update
+ CACHE accordingly. Return the first instruction after the code
+ sequence or CURRENT_PC, whichever is smaller. If we don't
+ recognize the code, return PC. */
+
+static CORE_ADDR
+i386_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
+ struct i386_frame_cache *cache)
+{
+ /* The register used by the compiler to perform the stack re-alignment
+ is, in order of preference, either %ecx, %edx, or %eax. GCC should
+ never use %ebx as it always treats it as callee-saved, whereas
+ the compiler can only use caller-saved registers. */
+ static const gdb_byte insns_ecx[10] = {
+ 0x8d, 0x4c, 0x24, 0x04, /* leal 4(%esp), %ecx */
+ 0x83, 0xe4, 0xf0, /* andl $-16, %esp */
+ 0xff, 0x71, 0xfc /* pushl -4(%ecx) */
+ };
+ static const gdb_byte insns_edx[10] = {
+ 0x8d, 0x54, 0x24, 0x04, /* leal 4(%esp), %edx */
+ 0x83, 0xe4, 0xf0, /* andl $-16, %esp */
+ 0xff, 0x72, 0xfc /* pushl -4(%edx) */
+ };
+ static const gdb_byte insns_eax[10] = {
+ 0x8d, 0x44, 0x24, 0x04, /* leal 4(%esp), %eax */
+ 0x83, 0xe4, 0xf0, /* andl $-16, %esp */
+ 0xff, 0x70, 0xfc /* pushl -4(%eax) */
+ };
+ gdb_byte buf[10];
+
+ if (target_read_memory (pc, buf, sizeof buf)
+ || (memcmp (buf, insns_ecx, sizeof buf) != 0
+ && memcmp (buf, insns_edx, sizeof buf) != 0
+ && memcmp (buf, insns_eax, sizeof buf) != 0))
+ return pc;
+
+ if (current_pc > pc + 4)
+ cache->stack_align = 1;
+
+ return min (pc + 10, current_pc);
+}
+
/* Maximum instruction length we need to handle. */
#define I386_MAX_INSN_LEN 6
struct i386_insn *insn;
gdb_byte op;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 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];
+ gdb_byte buf[I386_MAX_INSN_LEN - 1];
+ int insn_matched = 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);
+ read_memory_nobpt (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;
+ insn_matched = 0;
}
+
+ if (insn_matched)
+ return insn;
}
}
if (limit <= pc)
return limit;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op == 0x55) /* pushl %ebp */
{
if (limit <= pc + skip)
return limit;
- op = read_memory_unsigned_integer (pc + skip, 1);
+ read_memory_nobpt (pc + skip, &op, 1);
/* Check for `movl %esp, %ebp' -- can be written in two ways. */
switch (op)
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, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op == 0x83)
{
/* `subl' with 8-bit immediate. */
offset -= cache->locals;
for (i = 0; i < 8 && pc < current_pc; i++)
{
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op < 0x50 || op > 0x57)
break;
pc = i386_follow_jump (pc);
pc = i386_analyze_struct_return (pc, current_pc, cache);
pc = i386_skip_probe (pc);
+ pc = i386_analyze_stack_align (pc, current_pc, cache);
pc = i386_analyze_frame_setup (pc, current_pc, cache);
return i386_analyze_register_saves (pc, current_pc, cache);
}
/* Return PC of first real instruction. */
static CORE_ADDR
-i386_skip_prologue (CORE_ADDR start_pc)
+i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
{
static gdb_byte pic_pat[6] =
{
for (i = 0; i < 6; i++)
{
- op = read_memory_unsigned_integer (pc + i, 1);
+ read_memory_nobpt (pc + i, &op, 1);
if (pic_pat[i] != op)
break;
}
{
int delta = 6;
- op = read_memory_unsigned_integer (pc + delta, 1);
+ read_memory_nobpt (pc + delta, &op, 1);
if (op == 0x89) /* movl %ebx, x(%ebp) */
{
else /* Unexpected instruction. */
delta = 0;
- op = read_memory_unsigned_integer (pc + delta, 1);
+ read_memory_nobpt (pc + delta, &op, 1);
}
/* addl y,%ebx */
if (delta > 0 && op == 0x81
- && read_memory_unsigned_integer (pc + delta + 1, 1) == 0xc3);
+ && read_memory_unsigned_integer (pc + delta + 1, 1) == 0xc3)
{
pc += delta + 6;
}
{
gdb_byte buf[8];
- frame_unwind_register (next_frame, PC_REGNUM, buf);
+ frame_unwind_register (next_frame, gdbarch_pc_regnum (gdbarch), buf);
return extract_typed_address (buf, builtin_type_void_func_ptr);
}
\f
/* For normal frames, %eip is stored at 4(%ebp). */
cache->saved_regs[I386_EIP_REGNUM] = 4;
- cache->pc = frame_func_unwind (next_frame);
+ cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME);
if (cache->pc != 0)
i386_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache);
+ if (cache->stack_align)
+ {
+ /* Saved stack pointer has been saved in %ecx. */
+ frame_unwind_register (next_frame, I386_ECX_REGNUM, buf);
+ cache->saved_sp = extract_unsigned_integer(buf, 4);
+ }
+
if (cache->locals < 0)
{
/* We didn't find a valid frame, which means that CACHE->base
frame by looking at the stack pointer. For truly "frameless"
functions this might work too. */
- frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
- cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset;
+ if (cache->stack_align)
+ {
+ /* We're halfway aligning the stack. */
+ cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4;
+ cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4;
+
+ /* This will be added back below. */
+ cache->saved_regs[I386_EIP_REGNUM] -= cache->base;
+ }
+ else
+ {
+ frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset;
+ }
}
/* Now that we have the base address for the stack frame we can
calculate the value of %esp in the calling frame. */
- cache->saved_sp = cache->base + 8;
+ if (cache->saved_sp == 0)
+ cache->saved_sp = cache->base + 8;
/* Adjust all the saved registers such that they contain addresses
instead of offsets. */
i386_frame_prev_register (struct frame_info *next_frame, void **this_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *valuep)
+ int *realnump, gdb_byte *valuep)
{
struct i386_frame_cache *cache = i386_frame_cache (next_frame, this_cache);
{
/* Read the value in from memory. */
read_memory (*addrp, valuep,
- register_size (current_gdbarch, regnum));
+ register_size (get_frame_arch (next_frame), regnum));
}
return;
}
i386_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
{
struct i386_frame_cache *cache;
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame));
CORE_ADDR addr;
gdb_byte buf[4];
void **this_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *valuep)
+ int *realnump, gdb_byte *valuep)
{
/* Make sure we've initialized the cache. */
i386_sigtramp_frame_cache (next_frame, this_cache);
This function is 64-bit safe. */
static int
-i386_get_longjmp_target (CORE_ADDR *pc)
+i386_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
{
gdb_byte buf[8];
CORE_ADDR sp, jb_addr;
- int jb_pc_offset = gdbarch_tdep (current_gdbarch)->jb_pc_offset;
+ int jb_pc_offset = gdbarch_tdep (get_frame_arch (frame))->jb_pc_offset;
int len = TYPE_LENGTH (builtin_type_void_func_ptr);
/* If JB_PC_OFFSET is -1, we have no way to find out where the
/* Don't use I386_ESP_REGNUM here, since this function is also used
for AMD64. */
- regcache_cooked_read (current_regcache, SP_REGNUM, buf);
+ get_frame_register (frame, gdbarch_sp_regnum (get_frame_arch (frame)), buf);
sp = extract_typed_address (buf, builtin_type_void_data_ptr);
if (target_read_memory (sp + len, buf, len))
return 0;
multiple of [32-bit] words. This may require tail padding,
depending on the size of the argument."
- This makes sure the stack says word-aligned. */
+ This makes sure the stack stays word-aligned. */
sp -= (len + 3) & ~3;
write_memory (sp, value_contents_all (args[i]), len);
}
}
else
{
- int low_size = register_size (current_gdbarch, LOW_RETURN_REGNUM);
- int high_size = register_size (current_gdbarch, HIGH_RETURN_REGNUM);
+ int low_size = register_size (gdbarch, LOW_RETURN_REGNUM);
+ int high_size = register_size (gdbarch, HIGH_RETURN_REGNUM);
if (len <= low_size)
{
}
else
{
- int low_size = register_size (current_gdbarch, LOW_RETURN_REGNUM);
- int high_size = register_size (current_gdbarch, HIGH_RETURN_REGNUM);
+ int low_size = register_size (gdbarch, LOW_RETURN_REGNUM);
+ int high_size = register_size (gdbarch, HIGH_RETURN_REGNUM);
if (len <= low_size)
regcache_raw_write_part (regcache, LOW_RETURN_REGNUM, 0, len, valbuf);
};
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. */
+/* Return non-zero if TYPE, which is assumed to be a structure,
+ a union type, or an array type, should be returned in registers
+ for architecture GDBARCH. */
static int
i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
enum type_code code = TYPE_CODE (type);
int len = TYPE_LENGTH (type);
- gdb_assert (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION);
+ gdb_assert (code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION
+ || code == TYPE_CODE_ARRAY);
if (struct_convention == pcc_struct_convention
|| (struct_convention == default_struct_convention
&& tdep->struct_return == pcc_struct_return))
return 0;
+ /* Structures consisting of a single `float', `double' or 'long
+ double' member are returned in %st(0). */
+ if (code == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) == 1)
+ {
+ type = check_typedef (TYPE_FIELD_TYPE (type, 0));
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ return (len == 4 || len == 8 || len == 12);
+ }
+
return (len == 1 || len == 2 || len == 4 || len == 8);
}
{
enum type_code code = TYPE_CODE (type);
- if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
+ if ((code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION
+ || code == TYPE_CODE_ARRAY)
&& !i386_reg_struct_return_p (gdbarch, type))
{
/* The System V ABI says that:
So the ABI guarantees that we can always find the return
value just after the function has returned. */
+ /* Note that the ABI doesn't mention functions returning arrays,
+ which is something possible in certain languages such as Ada.
+ In this case, the value is returned as if it was wrapped in
+ a record, so the convention applied to records also applies
+ to arrays. */
+
if (readbuf)
{
ULONGEST addr;
}
/* 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. */
+ `float', `double' or 'long 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));
}
\f
-/* Types for the MMX and SSE registers. */
-static struct type *i386_mmx_type;
-static struct type *i386_sse_type;
+/* Type for %eflags. */
+struct type *i386_eflags_type;
-/* Construct the type for MMX registers. */
-static struct type *
-i386_build_mmx_type (void)
+/* Type for %mxcsr. */
+struct type *i386_mxcsr_type;
+
+/* Construct types for ISA-specific registers. */
+static void
+i386_init_types (void)
+{
+ struct type *type;
+
+ type = init_flags_type ("builtin_type_i386_eflags", 4);
+ append_flags_type_flag (type, 0, "CF");
+ append_flags_type_flag (type, 1, NULL);
+ append_flags_type_flag (type, 2, "PF");
+ append_flags_type_flag (type, 4, "AF");
+ append_flags_type_flag (type, 6, "ZF");
+ append_flags_type_flag (type, 7, "SF");
+ append_flags_type_flag (type, 8, "TF");
+ append_flags_type_flag (type, 9, "IF");
+ append_flags_type_flag (type, 10, "DF");
+ append_flags_type_flag (type, 11, "OF");
+ append_flags_type_flag (type, 14, "NT");
+ append_flags_type_flag (type, 16, "RF");
+ append_flags_type_flag (type, 17, "VM");
+ append_flags_type_flag (type, 18, "AC");
+ append_flags_type_flag (type, 19, "VIF");
+ append_flags_type_flag (type, 20, "VIP");
+ append_flags_type_flag (type, 21, "ID");
+ i386_eflags_type = type;
+
+ type = init_flags_type ("builtin_type_i386_mxcsr", 4);
+ append_flags_type_flag (type, 0, "IE");
+ append_flags_type_flag (type, 1, "DE");
+ append_flags_type_flag (type, 2, "ZE");
+ append_flags_type_flag (type, 3, "OE");
+ append_flags_type_flag (type, 4, "UE");
+ append_flags_type_flag (type, 5, "PE");
+ append_flags_type_flag (type, 6, "DAZ");
+ append_flags_type_flag (type, 7, "IM");
+ append_flags_type_flag (type, 8, "DM");
+ append_flags_type_flag (type, 9, "ZM");
+ append_flags_type_flag (type, 10, "OM");
+ append_flags_type_flag (type, 11, "UM");
+ append_flags_type_flag (type, 12, "PM");
+ append_flags_type_flag (type, 15, "FZ");
+ i386_mxcsr_type = type;
+}
+
+/* Construct vector type for MMX registers. */
+struct type *
+i386_mmx_type (struct gdbarch *gdbarch)
{
- /* The type we're building is this: */
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (!tdep->i386_mmx_type)
+ {
+ /* 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];
- };
+ 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);
+ append_composite_type_field (t, "v2_int32",
+ init_vector_type (builtin_type_int32, 2));
+ append_composite_type_field (t, "v4_int16",
+ init_vector_type (builtin_type_int16, 4));
+ append_composite_type_field (t, "v8_int8",
+ init_vector_type (builtin_type_int8, 8));
TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
TYPE_NAME (t) = "builtin_type_vec64i";
-
- i386_mmx_type = t;
+ tdep->i386_mmx_type = t;
}
- return i386_mmx_type;
+ return tdep->i386_mmx_type;
}
-/* Construct the type for SSE registers. */
-static struct type *
-i386_build_sse_type (void)
+struct type *
+i386_sse_type (struct gdbarch *gdbarch)
{
- if (! i386_sse_type)
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (!tdep->i386_sse_type)
{
+ /* The type we're building is this: */
+#if 0
+ union __gdb_builtin_type_vec128i
+ {
+ int128_t uint128;
+ int64_t v2_int64[2];
+ int32_t v4_int32[4];
+ int16_t v8_int16[8];
+ int8_t v16_int8[16];
+ double v2_double[2];
+ float v4_float[4];
+ };
+#endif
+
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, "v4_float",
+ init_vector_type (builtin_type_float, 4));
+ append_composite_type_field (t, "v2_double",
+ init_vector_type (builtin_type_double, 2));
+ append_composite_type_field (t, "v16_int8",
+ init_vector_type (builtin_type_int8, 16));
+ append_composite_type_field (t, "v8_int16",
+ init_vector_type (builtin_type_int16, 8));
+ append_composite_type_field (t, "v4_int32",
+ init_vector_type (builtin_type_int32, 4));
+ append_composite_type_field (t, "v2_int64",
+ init_vector_type (builtin_type_int64, 2));
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;
+ tdep->i386_sse_type = t;
}
- return i386_sse_type;
+ return tdep->i386_sse_type;
}
/* Return the GDB type object for the "standard" data type of data in
static struct type *
i386_register_type (struct gdbarch *gdbarch, int regnum)
{
- if (regnum == I386_EIP_REGNUM
- || regnum == I386_EBP_REGNUM || regnum == I386_ESP_REGNUM)
- return lookup_pointer_type (builtin_type_void);
+ if (regnum == I386_EIP_REGNUM)
+ return builtin_type_void_func_ptr;
+
+ if (regnum == I386_EFLAGS_REGNUM)
+ return i386_eflags_type;
+
+ if (regnum == I386_EBP_REGNUM || regnum == I386_ESP_REGNUM)
+ return builtin_type_void_data_ptr;
if (i386_fp_regnum_p (regnum))
return builtin_type_i387_ext;
+ if (i386_mmx_regnum_p (gdbarch, regnum))
+ return i386_mmx_type (gdbarch);
+
if (i386_sse_regnum_p (gdbarch, regnum))
- return i386_build_sse_type ();
+ return i386_sse_type (gdbarch);
- if (i386_mmx_regnum_p (gdbarch, regnum))
- return i386_build_mmx_type ();
+#define I387_ST0_REGNUM I386_ST0_REGNUM
+#define I387_NUM_XMM_REGS (gdbarch_tdep (gdbarch)->num_xmm_regs)
+
+ if (regnum == I387_MXCSR_REGNUM)
+ return i386_mxcsr_type;
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
return builtin_type_int;
}
needs any special handling. */
static int
-i386_convert_register_p (int regnum, struct type *type)
+i386_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
{
int len = TYPE_LENGTH (type);
return 1;
}
- return i386_fp_regnum_p (regnum);
+ return i387_convert_register_p (gdbarch, regnum, type);
}
/* Read a value of type TYPE from register REGNUM in frame FRAME, and
while (len > 0)
{
gdb_assert (regnum != -1);
- gdb_assert (register_size (current_gdbarch, regnum) == 4);
+ gdb_assert (register_size (get_frame_arch (frame), regnum) == 4);
get_frame_register (frame, regnum, to);
regnum = i386_next_regnum (regnum);
while (len > 0)
{
gdb_assert (regnum != -1);
- gdb_assert (register_size (current_gdbarch, regnum) == 4);
+ gdb_assert (register_size (get_frame_arch (frame), regnum) == 4);
put_frame_register (frame, regnum, from);
regnum = i386_next_regnum (regnum);
int regnum, const void *gregs, size_t len)
{
const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
- const bfd_byte *regs = gregs;
+ const gdb_byte *regs = gregs;
int i;
gdb_assert (len == tdep->sizeof_gregset);
int regnum, void *gregs, size_t len)
{
const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
- bfd_byte *regs = gregs;
+ gdb_byte *regs = gregs;
int i;
gdb_assert (len == tdep->sizeof_gregset);
}
\f
-#ifdef STATIC_TRANSFORM_NAME
-/* SunPRO encodes the static variables. This is not related to C++
- mangling, it is done for C too. */
-
-char *
-sunpro_static_transform_name (char *name)
-{
- char *p;
- if (IS_STATIC_TRANSFORM_NAME (name))
- {
- /* For file-local statics there will be a period, a bunch of
- junk (the contents of which match a string given in the
- N_OPT), a period and the name. For function-local statics
- there will be a bunch of junk (which seems to change the
- second character from 'A' to 'B'), a period, the name of the
- function, and the name. So just skip everything before the
- last period. */
- p = strrchr (name, '.');
- if (p != NULL)
- name = p + 1;
- }
- return name;
-}
-#endif /* STATIC_TRANSFORM_NAME */
-\f
-
/* Stuff for WIN32 PE style DLL's but is pretty generic really. */
CORE_ADDR
tdep->jb_pc_offset = 36;
}
-
-/* NetWare. */
-
-static void
-i386_nw_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
-{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
- tdep->jb_pc_offset = 24;
-}
\f
/* i386 register groups. In addition to the normal groups, add "mmx"
return arches->gdbarch;
/* Allocate space for the new architecture. */
- tdep = XMALLOC (struct gdbarch_tdep);
+ tdep = XCALLOC (1, struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
/* General-purpose registers. */
the i387 extended floating-point format. In fact, of all targets
in the GCC 2.95 tree, only OSF/1 does it different, and insists
on having a `long double' that's not `long' at all. */
- set_gdbarch_long_double_format (gdbarch, &floatformat_i387_ext);
+ set_gdbarch_long_double_format (gdbarch, floatformats_i387_ext);
/* Although the i387 extended floating-point has only 80 significant
bits, a `long double' actually takes up 96, probably to enforce
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
+ /* We don't set gdbarch_stab_reg_to_regnum, since ECOFF doesn't seem to
be in use on any of the supported i386 targets. */
set_gdbarch_print_float_info (gdbarch, i387_print_float_info);
return GDB_OSABI_UNKNOWN;
}
-
-static enum gdb_osabi
-i386_nlm_osabi_sniffer (bfd *abfd)
-{
- return GDB_OSABI_NETWARE;
-}
\f
/* Provide a prototype to silence -Wmissing-prototypes. */
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
i386_coff_osabi_sniffer);
- gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_nlm_flavour,
- i386_nlm_osabi_sniffer);
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_SVR4,
i386_svr4_init_abi);
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_GO32,
i386_go32_init_abi);
- gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETWARE,
- i386_nw_init_abi);
- /* Initialize the i386 specific register groups. */
+ /* Initialize the i386-specific register groups & types. */
i386_init_reggroups ();
+ i386_init_types();
}