Re: PATCH: Enable x86 XML target descriptions

Mark Kettenis
2010-03-01T14:49:31Z

> Date: Sun, 28 Feb 2010 13:15:34 -0800
> From: "H.J. Lu" <hongjiu.lu@intel.com>
>
> On Mon, Feb 22, 2010 at 01:03:56PM -0800, H.J. Lu wrote:
> > On Thu, Feb 18, 2010 at 03:01:35PM -0800, H.J. Lu wrote:
> > > On Thu, Feb 18, 2010 at 07:34:02AM -0800, H.J. Lu wrote:
> > > > On Wed, Feb 17, 2010 at 09:43:12PM -0800, H.J. Lu wrote:
> > > > > On Wed, Feb 10, 2010 at 12:03:03PM -0800, H.J. Lu wrote:
> > > > > > Hi,
> > > > > >
> > > > > > This patch enables x86 XML target descriptions. I used
> > > > > > i386_linux_init_orig_eax to support the old gdbserver which doesn't
> > > > > > have XML target descriptions.
> > > > > >
> > > > > > The register description processing is handled in i386_gdbarch_init
> > > > > > for 32bit/64bit as well as all ABIs to avoid code duplication and
> > > > > > unnecessary complexity.
> > > > > >
> > > > > > OK to install?
> > > > > >
> > > > >
> > > > > Here is the updated patch. I removed all BFD64 from i386 files. I
> > > > > renamed I386_NUM_FREGS to I387_NUM_REGS and put it in i387-tdep.h.
> > > > > I use it in amd64-tdep.c. I added a few fields to gdbarch_tdep so
> > > > > that I can pass values from xxx_abit_init to i386_gdbarch_init. OK
> > > > > to install?
> > > > >
> > > > > Thanks.
> > > > >
> > > > >
> > > >
> > > > A small update. I added I386_MXCSR_REGNUM so that "i387-tdep.h"
> > > > isn't added for amd64-linux-nat.c, amd64-linux-tdep.c and
> > > > i386-linux-tdep.c. OK to install?
> > > >
> > >
> > > A small bug fix. amd64_linux_read_description should return
> > > tdesc_i386_linux for 32bit.
> > >
> >
> > Here is the updated patch. I have addressed all issues raised so far
> > as mush as I can. Any comments/suggestions?
> >
>
> Here is the updated patch. Any comments/suggestions?

Given Daniel's explanation about num_regs and the feature names, this
is ok with me.

> gdb/
>
> 2010-02-28 H.J. Lu <hongjiu.lu@intel.com>
>
> * amd64-linux-nat.c (AMD64_LINUX_USER64_CS): New.
> (amd64_linux_read_description): Likewise.
> (_initialize_amd64_linux_nat): Set to_read_description to
> amd64_linux_read_description.
>
> * amd64-linux-tdep.c: Include "features/i386/amd64-linux.c".
> (amd64_linux_register_name): Removed.
> (amd64_linux_register_type): Likewise.
> (amd64_linux_core_read_description): New.
> (amd64_linux_init_abi): Set target description to
> tdesc_amd64_linux if needed. Support orig_rax in target
> description. Don't call set_gdbarch_register_name nor
> set_gdbarch_register_type. Call
> set_gdbarch_core_read_description.
> (_initialize_amd64_linux_tdep): Call
> initialize_tdesc_amd64_linux.
>
> * amd64-linux-tdep.h (tdesc_amd64_linux): New.
>
> * amd64-tdep.c: Include "features/i386/amd64.c".
> (amd64_register_names): Removed.
> (amd64_register_name): Likewise.
> (amd64_register_type): Likewise.
> (amd64_init_abi): Set num_core_regs and register_names. Set
> target description to tdesc_amd64 if needed. Don't call
> set_gdbarch_register_name nor set_gdbarch_register_type.
> (_initialize_amd64_tdep): New.
>
> * i386-linux-nat.c (i386_linux_read_description): New.
> (_initialize_i386_linux_nat): Set to_read_description to
> i386_linux_read_description.
>
> * i386-linux-tdep.c: Include "features/i386/i386-linux.c".
> (i386_linux_register_name): Removed.
> (i386_linux_core_read_description): New.
> (i386_linux_read_description): Likewise.
> (i386_linux_init_abi): Don't call set_gdbarch_register_name.
> Set target description to tdesc_i386_linux if needed. Support
> orig_eax. Set register_reggroup_p. Call
> set_gdbarch_core_read_description.
> (_initialize_i386_linux_tdep): Call initialize_tdesc_i386_linux.
>
> * i386-linux-tdep.h (tdesc_i386_linux): New.
>
> * i386-nto-tdep.c (i386nto_regset_id): Replace I386_NUM_FREGS
> with I387_NUM_REGS.
>
> * i386-tdep.c: Include "features/i386/i386.c".
> (i386_register_names): Make it const.
> (i386_mmx_names): Likewise.
> (i386_num_register_names): Removed.
> (i386_register_name): Likewise.
> (i386_eflags_type): Likewise.
> (i386_mxcsr_type): Likewise.
> (i386_sse_type): Likewise.
> (i386_register_type): Likewise.
> (i387_ext_type): Call tdesc_find_type instead of arch_float_type.
> (i386_pseudo_register_name): New.
> (i386_pseudo_register_type): Likewise.
> (i386_mmx_type): Make it static.
> (i386_gdbarch_init): Check arch. Replace I386_NUM_FREGS with
> I387_NUM_REGS. Set num_core_regs and register_names. Don't
> call set_gdbarch_register_name nor set_gdbarch_register_type.
> Set register_reggroup_p. Set target description to tdesc_i386
> if needed. Call set_tdesc_pseudo_register_type,
> set_tdesc_pseudo_register_name and tdesc_use_registers.
> (_initialize_i386_tdep): Call initialize_tdesc_i386.
> initialize_tdesc_x86_64.
>
> * i386-tdep.h (gdbarch_tdep): Remove i386_eflags_type,
> i386_mxcsr_type and i386_sse_type. Add num_core_regs,
> register_names, tdesc and register_reggroup_p.
> (I386_NUM_FREGS): Removed.
> (i386_eflags_type): Likewise.
> (i386_mxcsr_type): Likewise.
> (i386_mmx_type): Likewise.
> (i386_sse_type): Likewise.
> (i386_register_name): Likewise.
> (i386_regnum): Add I386_MXCSR_REGNUM.
> (I386_SSE_NUM_REGS): Defined with I386_MXCSR_REGNUM.
>
> * i387-tdep.h (I387_NUM_REGS): New.
>
> * regformats/i386/i386-linux.dat: Generated.
> * regformats/i386/i386.dat: Likewise.
> * regformats/i386/amd64-linux.dat: Likewise.
> * regformats/i386/amd64.dat: Likewise.
>
> * regformats/reg-i386-linux.dat: Removed.
> * regformats/reg-i386.dat: Likewise.
> * regformats/reg-x86-64-linux.dat: Likewise.
> * regformats/reg-x86-64.dat: Likewise.
>
> gdb/gdbserver/
>
> 2010-02-28 H.J. Lu <hongjiu.lu@intel.com>
>
> * Makefile.in (clean): Replace reg-i386.c, reg-x86-64.c,
> reg-i386-linux.c and reg-x86-64-linux.c with i386.c, amd64.c,
> i386-linux.c and amd64-linux.c.
> (reg-i386.o): Removed.
> (reg-i386.c): Likewise.
> (reg-i386-linux.o): Likewise.
> (reg-i386-linux.c): Likewise.
> (reg-x86-64.o): Likewise.
> (reg-x86-64.c): Likewise.
> (reg-x86-64-linux.o): Likewise.
> (reg-x86-64-linux.c): Likewise.
> (i386.o): New.
> (i386.c): Likewise.
> (i386-linux.o): Likewise.
> (i386-linux.c): Likewise.
> (amd64.o): Likewise.
> (amd64.c): Likewise.
> (amd64-linux.o): Likewise.
> (amd64-linux.c): Likewise.
>
> * configure.srv (srv_i386_regobj): New.
> (srv_i386_linux_regobj): Likewise.
> (srv_amd64_regobj): Likewise.
> (srv_amd64_linux_regobj): Likewise.
> (srv_i386_32bit_xmlfiles): Likewise.
> (srv_i386_64bit_xmlfiles): Likewise.
> (srv_i386_xmlfiles): Likewise.
> (srv_amd64_xmlfiles): Likewise.
> (srv_i386_linux_xmlfiles): Likewise.
> (srv_amd64_linux_xmlfiles): Likewise.
> (i[34567]86-*-cygwin*): Set srv_regobj to $srv_i386_regobj. Set
> srv_xmlfiles to $srv_i386_xmlfiles.
> (i[34567]86-*-mingw32ce*): Likewise.
> (i[34567]86-*-mingw*): Likewise.
> (i[34567]86-*-nto*): Likewise.
> (i[34567]86-*-linux*): Set srv_regobj to $srv_i386_linux_regobj
> and $srv_amd64_linux_regobj. Set srv_xmlfiles to
> $srv_i386_linux_xmlfiles and $srv_amd64_linux_xmlfiles.
> (x86_64-*-linux*): Likewise.
>
> * linux-x86-low.c (init_registers_x86_64_linux): Removed.
> (init_registers_amd64_linux): New.
> (x86_arch_setup): Replace init_registers_x86_64_linux with
> init_registers_amd64_linux.
>
> gdb/testsuite/
>
> 2010-02-28 H.J. Lu <hongjiu.lu@intel.com>
>
> * gdb.xml/tdesc-regs.exp (architecture): New. Set it for x86.
> (load_description): Set architecture if defined.
>
> diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
> index 5c9e558..b9d5833 100644
> --- a/gdb/amd64-linux-nat.c
> +++ b/gdb/amd64-linux-nat.c
> @@ -674,6 +674,39 @@ amd64_linux_siginfo_fixup (struct siginfo *native, gdb_byte *inf, int direction)
> return 0;
> }
>
> +/* Get Linux/x86 target description from running target.
> +
> + Value of CS segment register:
> + 1. 64bit process: 0x33.
> + 2. 32bit process: 0x23.
> + */
> +
> +#define AMD64_LINUX_USER64_CS 0x33
> +
> +static const struct target_desc *
> +amd64_linux_read_description (struct target_ops *ops)
> +{
> + unsigned long cs;
> + int tid;
> +
> + /* GNU/Linux LWP ID's are process ID's. */
> + tid = TIDGET (inferior_ptid);
> + if (tid == 0)
> + tid = PIDGET (inferior_ptid); /* Not a threaded program. */
> +
> + /* Get CS register. */
> + errno = 0;
> + cs = ptrace (PTRACE_PEEKUSER, tid,
> + offsetof (struct user_regs_struct, cs), 0);
> + if (errno != 0)
> + perror_with_name (_("Couldn't get CS register"));
> +
> + if (cs == AMD64_LINUX_USER64_CS)
> + return tdesc_amd64_linux;
> + else
> + return tdesc_i386_linux;
> +}
> +
> /* Provide a prototype to silence -Wmissing-prototypes. */
> void _initialize_amd64_linux_nat (void);
>
> @@ -712,6 +745,8 @@ _initialize_amd64_linux_nat (void)
> t->to_fetch_registers = amd64_linux_fetch_inferior_registers;
> t->to_store_registers = amd64_linux_store_inferior_registers;
>
> + t->to_read_description = amd64_linux_read_description;
> +
> /* Register the target. */
> linux_nat_add_target (t);
> linux_nat_set_new_thread (t, amd64_linux_new_thread);
> diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
> index c28eef7..4ad6dc9 100644
> --- a/gdb/amd64-linux-tdep.c
> +++ b/gdb/amd64-linux-tdep.c
> @@ -37,6 +37,8 @@
> #include "solib-svr4.h"
> #include "xml-syscall.h"
>
> +#include "features/i386/amd64-linux.c"
> +
> /* The syscall's XML filename for i386. */
> #define XML_SYSCALL_FILENAME_AMD64 "syscalls/amd64-linux.xml"
>
> @@ -234,26 +236,6 @@ static int amd64_linux_sc_reg_offset[] =
> -1 /* %gs */
> };
>
> -/* Replacement register functions which know about %orig_rax. */
> -
> -static const char *
> -amd64_linux_register_name (struct gdbarch *gdbarch, int reg)
> -{
> - if (reg == AMD64_LINUX_ORIG_RAX_REGNUM)
> - return "orig_rax";
> -
> - return amd64_register_name (gdbarch, reg);
> -}
> -
> -static struct type *
> -amd64_linux_register_type (struct gdbarch *gdbarch, int reg)
> -{
> - if (reg == AMD64_LINUX_ORIG_RAX_REGNUM)
> - return builtin_type (gdbarch)->builtin_int64;
> -
> - return amd64_register_type (gdbarch, reg);
> -}
> -
> static int
> amd64_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
> struct reggroup *group)
> @@ -1260,10 +1242,32 @@ amd64_linux_record_signal (struct gdbarch *gdbarch,
> return 0;
> }
>
> +/* Get Linux/x86 target description from core dump. */
> +
> +static const struct target_desc *
> +amd64_linux_core_read_description (struct gdbarch *gdbarch,
> + struct target_ops *target,
> + bfd *abfd)
> +{
> + asection *section = bfd_get_section_by_name (abfd, ".reg2");
> +
> + if (section == NULL)
> + return NULL;
> +
> + /* Linux/x86-64. */
> + return tdesc_amd64_linux;
> +}
> +
> static void
> amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> {
> struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> + const struct target_desc *tdesc = info.target_desc;
> + struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
> + const struct tdesc_feature *feature;
> + int valid_p;
> +
> + gdb_assert (tdesc_data);
>
> tdep->gregset_reg_offset = amd64_linux_gregset_reg_offset;
> tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset);
> @@ -1271,6 +1275,23 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> amd64_init_abi (info, gdbarch);
>
> + /* Reserve a number for orig_rax. */
> + set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS);
> +
> + if (! tdesc_has_registers (tdesc))
> + tdesc = tdesc_amd64_linux;
> + tdep->tdesc = tdesc;
> +
> + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux");
> + if (feature == NULL)
> + return;
> +
> + valid_p = tdesc_numbered_register (feature, tdesc_data,
> + AMD64_LINUX_ORIG_RAX_REGNUM,
> + "orig_rax");
> + if (!valid_p)
> + return;
> +
> tdep->sigtramp_p = amd64_linux_sigtramp_p;
> tdep->sigcontext_addr = amd64_linux_sigcontext_addr;
> tdep->sc_reg_offset = amd64_linux_sc_reg_offset;
> @@ -1282,10 +1303,8 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* Add the %orig_rax register used for syscall restarting. */
> set_gdbarch_write_pc (gdbarch, amd64_linux_write_pc);
> - set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS);
> - set_gdbarch_register_name (gdbarch, amd64_linux_register_name);
> - set_gdbarch_register_type (gdbarch, amd64_linux_register_type);
> - set_gdbarch_register_reggroup_p (gdbarch, amd64_linux_register_reggroup_p);
> +
> + tdep->register_reggroup_p = amd64_linux_register_reggroup_p;
>
> /* Functions for 'catch syscall'. */
> set_xml_syscall_file_name (XML_SYSCALL_FILENAME_AMD64);
> @@ -1299,6 +1318,9 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> /* GNU/Linux uses SVR4-style shared libraries. */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
>
> + set_gdbarch_core_read_description (gdbarch,
> + amd64_linux_core_read_description);
> +
> /* Displaced stepping. */
> set_gdbarch_displaced_step_copy_insn (gdbarch,
> amd64_displaced_step_copy_insn);
> @@ -1492,4 +1514,7 @@ _initialize_amd64_linux_tdep (void)
> {
> gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
> GDB_OSABI_LINUX, amd64_linux_init_abi);
> +
> + /* Initialize the Linux target description */
> + initialize_tdesc_amd64_linux ();
> }
> diff --git a/gdb/amd64-linux-tdep.h b/gdb/amd64-linux-tdep.h
> index 20a15ca..33316fb 100644
> --- a/gdb/amd64-linux-tdep.h
> +++ b/gdb/amd64-linux-tdep.h
> @@ -31,6 +31,9 @@
> /* Total number of registers for GNU/Linux. */
> #define AMD64_LINUX_NUM_REGS (AMD64_LINUX_ORIG_RAX_REGNUM + 1)
>
> +/* Linux target description. */
> +extern struct target_desc *tdesc_amd64_linux;
> +
> /* Enum that defines the syscall identifiers for amd64 linux.
> Used for process record/replay, these will be translated into
> a gdb-canonical set of syscall ids in linux-record.c. */
> diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
> index 2b15141..0ec60c1 100644
> --- a/gdb/amd64-tdep.c
> +++ b/gdb/amd64-tdep.c
> @@ -42,6 +42,8 @@
> #include "amd64-tdep.h"
> #include "i387-tdep.h"
>
> +#include "features/i386/amd64.c"
> +
> /* Note that the AMD64 architecture was previously known as x86-64.
> The latter is (forever) engraved into the canonical system name as
> returned by config.guess, and used as the name for the AMD64 port
> @@ -83,47 +85,6 @@ static int amd64_dummy_call_integer_regs[] =
> 9 /* %r9 */
> };
>
> -/* Return the name of register REGNUM. */
> -
> -const char *
> -amd64_register_name (struct gdbarch *gdbarch, int regnum)
> -{
> - if (regnum >= 0 && regnum < AMD64_NUM_REGS)
> - return amd64_register_names[regnum];
> -
> - return NULL;
> -}
> -
> -/* Return the GDB type object for the "standard" data type of data in
> - register REGNUM. */
> -
> -struct type *
> -amd64_register_type (struct gdbarch *gdbarch, int regnum)
> -{
> - if (regnum >= AMD64_RAX_REGNUM && regnum <= AMD64_RDI_REGNUM)
> - return builtin_type (gdbarch)->builtin_int64;
> - if (regnum == AMD64_RBP_REGNUM || regnum == AMD64_RSP_REGNUM)
> - return builtin_type (gdbarch)->builtin_data_ptr;
> - if (regnum >= AMD64_R8_REGNUM && regnum <= AMD64_R15_REGNUM)
> - return builtin_type (gdbarch)->builtin_int64;
> - if (regnum == AMD64_RIP_REGNUM)
> - return builtin_type (gdbarch)->builtin_func_ptr;
> - if (regnum == AMD64_EFLAGS_REGNUM)
> - return i386_eflags_type (gdbarch);
> - if (regnum >= AMD64_CS_REGNUM && regnum <= AMD64_GS_REGNUM)
> - return builtin_type (gdbarch)->builtin_int32;
> - if (regnum >= AMD64_ST0_REGNUM && regnum <= AMD64_ST0_REGNUM + 7)
> - return i387_ext_type (gdbarch);
> - if (regnum >= AMD64_FCTRL_REGNUM && regnum <= AMD64_FCTRL_REGNUM + 7)
> - return builtin_type (gdbarch)->builtin_int32;
> - if (regnum >= AMD64_XMM0_REGNUM && regnum <= AMD64_XMM0_REGNUM + 15)
> - return i386_sse_type (gdbarch);
> - if (regnum == AMD64_MXCSR_REGNUM)
> - return i386_mxcsr_type (gdbarch);
> -
> - internal_error (__FILE__, __LINE__, _("invalid regnum"));
> -}
> -
> /* DWARF Register Number Mapping as defined in the System V psABI,
> section 3.6. */
>
> @@ -2153,11 +2114,19 @@ void
> amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> {
> struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> + const struct target_desc *tdesc = info.target_desc;
>
> /* AMD64 generally uses `fxsave' instead of `fsave' for saving its
> floating-point registers. */
> tdep->sizeof_fpregset = I387_SIZEOF_FXSAVE;
>
> + if (! tdesc_has_registers (tdesc))
> + tdesc = tdesc_amd64;
> + tdep->tdesc = tdesc;
> +
> + tdep->num_core_regs = AMD64_NUM_GREGS + I387_NUM_REGS;
> + tdep->register_names = amd64_register_names;
> +
> /* AMD64 has an FPU and 16 SSE registers. */
> tdep->st0_regnum = AMD64_ST0_REGNUM;
> tdep->num_xmm_regs = 16;
> @@ -2173,8 +2142,6 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> set_gdbarch_long_double_bit (gdbarch, 128);
>
> set_gdbarch_num_regs (gdbarch, AMD64_NUM_REGS);
> - set_gdbarch_register_name (gdbarch, amd64_register_name);
> - set_gdbarch_register_type (gdbarch, amd64_register_type);
>
> /* Register numbers of various important registers. */
> set_gdbarch_sp_regnum (gdbarch, AMD64_RSP_REGNUM); /* %rsp */
> @@ -2236,6 +2203,15 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> set_gdbarch_get_longjmp_target (gdbarch, amd64_get_longjmp_target);
> }
> +
> +/* Provide a prototype to silence -Wmissing-prototypes. */
> +void _initialize_amd64_tdep (void);
> +
> +void
> +_initialize_amd64_tdep (void)
> +{
> + initialize_tdesc_amd64 ();
> +}
> \f
>
> /* The 64-bit FXSAVE format differs from the 32-bit format in the
> diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
> index 5bf82e2..7fecced 100644
> --- a/gdb/gdbserver/Makefile.in
> +++ b/gdb/gdbserver/Makefile.in
> @@ -203,9 +203,9 @@ clean:
> rm -f *.o ${ADD_FILES} *~
> rm -f version.c
> rm -f gdbserver$(EXEEXT) gdbreplay$(EXEEXT) core make.log
> - rm -f reg-arm.c reg-i386.c reg-ia64.c reg-m32r.c reg-m68k.c
> - rm -f reg-sh.c reg-sparc.c reg-spu.c reg-x86-64.c reg-i386-linux.c
> - rm -f reg-cris.c reg-crisv32.c reg-x86-64-linux.c reg-xtensa.c
> + rm -f reg-arm.c i386.c reg-ia64.c reg-m32r.c reg-m68k.c
> + rm -f reg-sh.c reg-sparc.c reg-spu.c amd64.c i386-linux.c
> + rm -f reg-cris.c reg-crisv32.c amd64-linux.c reg-xtensa.c
> rm -f arm-with-iwmmxt.c
> rm -f arm-with-vfpv2.c arm-with-vfpv3.c arm-with-neon.c
> rm -f mips-linux.c mips64-linux.c
> @@ -345,12 +345,12 @@ reg-cris.c : $(srcdir)/../regformats/reg-cris.dat $(regdat_sh)
> reg-crisv32.o : reg-crisv32.c $(regdef_h)
> reg-crisv32.c : $(srcdir)/../regformats/reg-crisv32.dat $(regdat_sh)
> $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-crisv32.dat reg-crisv32.c
> -reg-i386.o : reg-i386.c $(regdef_h)
> -reg-i386.c : $(srcdir)/../regformats/reg-i386.dat $(regdat_sh)
> - $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-i386.dat reg-i386.c
> -reg-i386-linux.o : reg-i386-linux.c $(regdef_h)
> -reg-i386-linux.c : $(srcdir)/../regformats/reg-i386-linux.dat $(regdat_sh)
> - $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-i386-linux.dat reg-i386-linux.c
> +i386.o : i386.c $(regdef_h)
> +i386.c : $(srcdir)/../regformats/i386/i386.dat $(regdat_sh)
> + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/i386.dat i386.c
> +i386-linux.o : i386-linux.c $(regdef_h)
> +i386-linux.c : $(srcdir)/../regformats/i386/i386-linux.dat $(regdat_sh)
> + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/i386-linux.dat i386-linux.c
> reg-ia64.o : reg-ia64.c $(regdef_h)
> reg-ia64.c : $(srcdir)/../regformats/reg-ia64.dat $(regdat_sh)
> $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-ia64.dat reg-ia64.c
> @@ -432,12 +432,12 @@ reg-sparc64.c : $(srcdir)/../regformats/reg-sparc64.dat $(regdat_sh)
> reg-spu.o : reg-spu.c $(regdef_h)
> reg-spu.c : $(srcdir)/../regformats/reg-spu.dat $(regdat_sh)
> $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-spu.dat reg-spu.c
> -reg-x86-64.o : reg-x86-64.c $(regdef_h)
> -reg-x86-64.c : $(srcdir)/../regformats/reg-x86-64.dat $(regdat_sh)
> - $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-x86-64.dat reg-x86-64.c
> -reg-x86-64-linux.o : reg-x86-64-linux.c $(regdef_h)
> -reg-x86-64-linux.c : $(srcdir)/../regformats/reg-x86-64-linux.dat $(regdat_sh)
> - $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-x86-64-linux.dat reg-x86-64-linux.c
> +amd64.o : amd64.c $(regdef_h)
> +amd64.c : $(srcdir)/../regformats/i386/amd64.dat $(regdat_sh)
> + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/amd64.dat amd64.c
> +amd64-linux.o : amd64-linux.c $(regdef_h)
> +amd64-linux.c : $(srcdir)/../regformats/i386/amd64-linux.dat $(regdat_sh)
> + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/amd64-linux.dat amd64-linux.c
> reg-xtensa.o : reg-xtensa.c $(regdef_h)
> reg-xtensa.c : $(srcdir)/../regformats/reg-xtensa.dat $(regdat_sh)
> $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-xtensa.dat reg-xtensa.c
> diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
> index f6d92b3..e5818cd 100644
> --- a/gdb/gdbserver/configure.srv
> +++ b/gdb/gdbserver/configure.srv
> @@ -22,6 +22,18 @@
> # Default hostio_last_error implementation
> srv_hostio_err_objs="hostio-errno.o"
>
> +srv_i386_regobj=i386.o
> +srv_i386_linux_regobj=i386-linux.o
> +srv_amd64_regobj=amd64.o
> +srv_amd64_linux_regobj=amd64-linux.o
> +
> +srv_i386_32bit_xmlfiles="i386/32bit-core.xml i386/32bit-sse.xml"
> +srv_i386_64bit_xmlfiles="i386/64bit-core.xml i386/64bit-sse.xml"
> +srv_i386_xmlfiles="i386/i386.xml $srv_i386_32bit_xmlfiles"
> +srv_amd64_xmlfiles="i386/amd64.xml $srv_i386_64bit_xmlfiles"
> +srv_i386_linux_xmlfiles="i386/i386-linux.xml i386/32bit-linux.xml $srv_i386_32bit_xmlfiles"
> +srv_amd64_linux_xmlfiles="i386/amd64-linux.xml i386/64bit-linux.xml $srv_i386_64bit_xmlfiles"
> +
> # Input is taken from the "${target}" variable.
>
> case "${target}" in
> @@ -60,12 +72,15 @@ case "${target}" in
> srv_linux_usrregs=yes
> srv_linux_thread_db=yes
> ;;
> - i[34567]86-*-cygwin*) srv_regobj=reg-i386.o
> + i[34567]86-*-cygwin*) srv_regobj="$srv_i386_regobj"
> srv_tgtobj="i386-low.o win32-low.o win32-i386-low.o"
> + srv_xmlfiles="$srv_i386_xmlfiles"
> ;;
> - i[34567]86-*-linux*) srv_regobj=reg-i386-linux.o
> + i[34567]86-*-linux*) srv_regobj="$srv_i386_linux_regobj"
> + srv_xmlfiles="$srv_i386_linux_xmlfiles"
> if test "$gdb_cv_i386_is_x86_64" = yes ; then
> - srv_regobj="reg-x86-64-linux.o $srv_regobj"
> + srv_regobj="$srv_regobj $srv_amd64_linux_regobj"
> + srv_xmlfiles="${srv_xmlfiles} $srv_amd64_linux_xmlfiles"
> fi
> srv_tgtobj="linux-low.o linux-x86-low.o i386-low.o i387-fp.o"
> srv_linux_usrregs=yes
> @@ -73,20 +88,23 @@ case "${target}" in
> srv_linux_thread_db=yes
> ;;
> i[34567]86-*-mingw32ce*)
> - srv_regobj=reg-i386.o
> + srv_regobj="$srv_i386_regobj"
> srv_tgtobj="i386-low.o win32-low.o win32-i386-low.o"
> srv_tgtobj="${srv_tgtobj} wincecompat.o"
> + srv_xmlfiles="$srv_i386_xmlfiles"
> # hostio_last_error implementation is in win32-low.c
> srv_hostio_err_objs=""
> srv_mingw=yes
> srv_mingwce=yes
> ;;
> - i[34567]86-*-mingw*) srv_regobj=reg-i386.o
> + i[34567]86-*-mingw*) srv_regobj="$srv_i386_regobj"
> srv_tgtobj="i386-low.o win32-low.o win32-i386-low.o"
> + srv_xmlfiles="$srv_i386_xmlfiles"
> srv_mingw=yes
> ;;
> - i[34567]86-*-nto*) srv_regobj=reg-i386.o
> + i[34567]86-*-nto*) srv_regobj="$srv_i386_regobj"
> srv_tgtobj="nto-low.o nto-x86-low.o"
> + srv_xmlfiles="$srv_i386_xmlfiles"
> srv_qnx="yes"
> ;;
> ia64-*-linux*) srv_regobj=reg-ia64.o
> @@ -206,8 +224,9 @@ case "${target}" in
> spu*-*-*) srv_regobj=reg-spu.o
> srv_tgtobj="spu-low.o"
> ;;
> - x86_64-*-linux*) srv_regobj="reg-x86-64-linux.o reg-i386-linux.o"
> + x86_64-*-linux*) srv_regobj="$srv_amd64_linux_regobj $srv_i386_linux_regobj"
> srv_tgtobj="linux-low.o linux-x86-low.o i386-low.o i387-fp.o"
> + srv_xmlfiles="$srv_i386_linux_xmlfiles $srv_amd64_linux_xmlfiles"
> srv_linux_usrregs=yes # This is for i386 progs.
> srv_linux_regsets=yes
> srv_linux_thread_db=yes
> diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
> index 0062432..496baa2 100644
> --- a/gdb/gdbserver/linux-x86-low.c
> +++ b/gdb/gdbserver/linux-x86-low.c
> @@ -27,10 +27,10 @@
>
> #include "gdb_proc_service.h"
>
> -/* Defined in auto-generated file reg-i386-linux.c. */
> +/* Defined in auto-generated file i386-linux.c. */
> void init_registers_i386_linux (void);
> -/* Defined in auto-generated file reg-x86-64-linux.c. */
> -void init_registers_x86_64_linux (void);
> +/* Defined in auto-generated file amd64-linux.c. */
> +void init_registers_amd64_linux (void);
>
> #include <sys/reg.h>
> #include <sys/procfs.h>
> @@ -792,7 +792,7 @@ x86_arch_setup (void)
> }
> else if (use_64bit)
> {
> - init_registers_x86_64_linux ();
> + init_registers_amd64_linux ();
>
> /* Amd64 doesn't have HAVE_LINUX_USRREGS. */
> the_low_target.num_regs = -1;
> diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
> index ff837f2..31b9086 100644
> --- a/gdb/i386-linux-nat.c
> +++ b/gdb/i386-linux-nat.c
> @@ -853,6 +853,14 @@ i386_linux_child_post_startup_inferior (ptid_t ptid)
> super_post_startup_inferior (ptid);
> }
>
> +/* Get Linux/x86 target description from running target. */
> +
> +static const struct target_desc *
> +i386_linux_read_description (struct target_ops *ops)
> +{
> + return tdesc_i386_linux;
> +}
> +
> void
> _initialize_i386_linux_nat (void)
> {
> @@ -881,6 +889,8 @@ _initialize_i386_linux_nat (void)
> t->to_fetch_registers = i386_linux_fetch_inferior_registers;
> t->to_store_registers = i386_linux_store_inferior_registers;
>
> + t->to_read_description = i386_linux_read_description;
> +
> /* Register the target. */
> linux_nat_add_target (t);
> linux_nat_set_new_thread (t, i386_linux_new_thread);
> diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
> index 5acd229..b23c109 100644
> --- a/gdb/i386-linux-tdep.c
> +++ b/gdb/i386-linux-tdep.c
> @@ -46,6 +46,8 @@
> #include "linux-record.h"
> #include <stdint.h>
>
> +#include "features/i386/i386-linux.c"
> +
> /* Supported register note sections. */
> static struct core_regset_section i386_linux_regset_sections[] =
> {
> @@ -55,18 +57,6 @@ static struct core_regset_section i386_linux_regset_sections[] =
> { NULL, 0 }
> };
>
> -/* Return the name of register REG. */
> -
> -static const char *
> -i386_linux_register_name (struct gdbarch *gdbarch, int reg)
> -{
> - /* Deal with the extra "orig_eax" pseudo register. */
> - if (reg == I386_LINUX_ORIG_EAX_REGNUM)
> - return "orig_eax";
> -
> - return i386_register_name (gdbarch, reg);
> -}
> -
> /* Return non-zero, when the register is in the corresponding register
> group. Put the LINUX_ORIG_EAX register in the system group. */
> static int
> @@ -570,21 +560,57 @@ static int i386_linux_sc_reg_offset[] =
> 0 * 4 /* %gs */
> };
>
> +/* Get Linux/x86 target description from core dump. */
> +
> +static const struct target_desc *
> +i386_linux_core_read_description (struct gdbarch *gdbarch,
> + struct target_ops *target,
> + bfd *abfd)
> +{
> + asection *section = bfd_get_section_by_name (abfd, ".reg2");
> +
> + if (section == NULL)
> + return NULL;
> +
> + /* Linux/i386. */
> + return tdesc_i386_linux;
> +}
> +
> static void
> i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> {
> struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> + const struct target_desc *tdesc = info.target_desc;
> + struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
> + const struct tdesc_feature *feature;
> + int valid_p;
> +
> + gdb_assert (tdesc_data);
>
> /* GNU/Linux uses ELF. */
> i386_elf_init_abi (info, gdbarch);
>
> - /* Since we have the extra "orig_eax" register on GNU/Linux, we have
> - to adjust a few things. */
> + /* Reserve a number for orig_eax. */
> + set_gdbarch_num_regs (gdbarch, I386_LINUX_NUM_REGS);
> +
> + if (! tdesc_has_registers (tdesc))
> + tdesc = tdesc_i386_linux;
> + tdep->tdesc = tdesc;
> +
> + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux");
> + if (feature == NULL)
> + return;
>
> + valid_p = tdesc_numbered_register (feature, tdesc_data,
> + I386_LINUX_ORIG_EAX_REGNUM,
> + "orig_eax");
> + if (!valid_p)
> + return;
> +
> + /* Add the %orig_eax register used for syscall restarting. */
> set_gdbarch_write_pc (gdbarch, i386_linux_write_pc);
> - set_gdbarch_num_regs (gdbarch, I386_LINUX_NUM_REGS);
> - set_gdbarch_register_name (gdbarch, i386_linux_register_name);
> - set_gdbarch_register_reggroup_p (gdbarch, i386_linux_register_reggroup_p);
> +
> + tdep->register_reggroup_p = i386_linux_register_reggroup_p;
>
> tdep->gregset_reg_offset = i386_linux_gregset_reg_offset;
> tdep->gregset_num_regs = ARRAY_SIZE (i386_linux_gregset_reg_offset);
> @@ -783,6 +809,9 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> /* Install supported register note sections. */
> set_gdbarch_core_regset_sections (gdbarch, i386_linux_regset_sections);
>
> + set_gdbarch_core_read_description (gdbarch,
> + i386_linux_core_read_description);
> +
> /* Displaced stepping. */
> set_gdbarch_displaced_step_copy_insn (gdbarch,
> simple_displaced_step_copy_insn);
> @@ -808,4 +837,7 @@ _initialize_i386_linux_tdep (void)
> {
> gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_LINUX,
> i386_linux_init_abi);
> +
> + /* Initialize the Linux target description */
> + initialize_tdesc_i386_linux ();
> }
> diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h
> index e66021d..11f7295 100644
> --- a/gdb/i386-linux-tdep.h
> +++ b/gdb/i386-linux-tdep.h
> @@ -35,4 +35,7 @@
> /* Total number of registers for GNU/Linux. */
> #define I386_LINUX_NUM_REGS (I386_LINUX_ORIG_EAX_REGNUM + 1)
>
> +/* Linux target description. */
> +extern struct target_desc *tdesc_i386_linux;
> +
> #endif /* i386-linux-tdep.h */
> diff --git a/gdb/i386-nto-tdep.c b/gdb/i386-nto-tdep.c
> index 06fc555..09c55e2 100644
> --- a/gdb/i386-nto-tdep.c
> +++ b/gdb/i386-nto-tdep.c
> @@ -122,7 +122,7 @@ i386nto_regset_id (int regno)
> return NTO_REG_END;
> else if (regno < I386_NUM_GREGS)
> return NTO_REG_GENERAL;
> - else if (regno < I386_NUM_GREGS + I386_NUM_FREGS)
> + else if (regno < I386_NUM_GREGS + I387_NUM_REGS)
> return NTO_REG_FLOAT;
> else if (regno < I386_SSE_NUM_REGS)
> return NTO_REG_FLOAT; /* We store xmm registers in fxsave_area. */
> diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
> index 83aa81f..1c188fd 100644
> --- a/gdb/i386-tdep.c
> +++ b/gdb/i386-tdep.c
> @@ -54,9 +54,11 @@
> #include "record.h"
> #include <stdint.h>
>
> +#include "features/i386/i386.c"
> +
> /* Register names. */
>
> -static char *i386_register_names[] =
> +static const char *i386_register_names[] =
> {
> "eax", "ecx", "edx", "ebx",
> "esp", "ebp", "esi", "edi",
> @@ -71,11 +73,9 @@ static char *i386_register_names[] =
> "mxcsr"
> };
>
> -static const int i386_num_register_names = ARRAY_SIZE (i386_register_names);
> -
> /* Register names for MMX pseudo-registers. */
>
> -static char *i386_mmx_names[] =
> +static const char *i386_mmx_names[] =
> {
> "mm0", "mm1", "mm2", "mm3",
> "mm4", "mm5", "mm6", "mm7"
> @@ -147,16 +147,11 @@ i386_fpc_regnum_p (struct gdbarch *gdbarch, int regnum)
>
> /* Return the name of register REGNUM. */
>
> -const char *
> -i386_register_name (struct gdbarch *gdbarch, int regnum)
> +static const char *
> +i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
> {
> - if (i386_mmx_regnum_p (gdbarch, regnum))
> - return i386_mmx_names[regnum - I387_MM0_REGNUM (gdbarch_tdep (gdbarch))];
> -
> - if (regnum >= 0 && regnum < i386_num_register_names)
> - return i386_register_names[regnum];
> -
> - return NULL;
> + gdb_assert (i386_mmx_regnum_p (gdbarch, regnum));
> + return i386_mmx_names[regnum - I387_MM0_REGNUM (gdbarch_tdep (gdbarch))];
> }
>
> /* Convert a dbx register number REG to the appropriate register
> @@ -2112,87 +2107,22 @@ i386_return_value (struct gdbarch *gdbarch, struct type *func_type,
> }
> \f
>
> -/* Construct types for ISA-specific registers. */
> -struct type *
> -i386_eflags_type (struct gdbarch *gdbarch)
> -{
> - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> -
> - if (!tdep->i386_eflags_type)
> - {
> - struct type *type;
> -
> - type = arch_flags_type (gdbarch, "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");
> -
> - tdep->i386_eflags_type = type;
> - }
> -
> - return tdep->i386_eflags_type;
> -}
> -
> -struct type *
> -i386_mxcsr_type (struct gdbarch *gdbarch)
> -{
> - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> -
> - if (!tdep->i386_mxcsr_type)
> - {
> - struct type *type;
> -
> - type = arch_flags_type (gdbarch, "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");
> -
> - tdep->i386_mxcsr_type = type;
> - }
> -
> - return tdep->i386_mxcsr_type;
> -}
> -
> struct type *
> i387_ext_type (struct gdbarch *gdbarch)
> {
> struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>
> if (!tdep->i387_ext_type)
> - tdep->i387_ext_type
> - = arch_float_type (gdbarch, -1, "builtin_type_i387_ext",
> - floatformats_i387_ext);
> + {
> + tdep->i387_ext_type = tdesc_find_type (gdbarch, "i387_ext");
> + gdb_assert (tdep->i387_ext_type != NULL);
> + }
>
> return tdep->i387_ext_type;
> }
>
> /* Construct vector type for MMX registers. */
> -struct type *
> +static struct type *
> i386_mmx_type (struct gdbarch *gdbarch)
> {
> struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> @@ -2233,84 +2163,14 @@ i386_mmx_type (struct gdbarch *gdbarch)
> return tdep->i386_mmx_type;
> }
>
> -struct type *
> -i386_sse_type (struct gdbarch *gdbarch)
> -{
> - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> -
> - if (!tdep->i386_sse_type)
> - {
> - const struct builtin_type *bt = builtin_type (gdbarch);
> -
> - /* 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 = arch_composite_type (gdbarch,
> - "__gdb_builtin_type_vec128i", TYPE_CODE_UNION);
> - append_composite_type_field (t, "v4_float",
> - init_vector_type (bt->builtin_float, 4));
> - append_composite_type_field (t, "v2_double",
> - init_vector_type (bt->builtin_double, 2));
> - append_composite_type_field (t, "v16_int8",
> - init_vector_type (bt->builtin_int8, 16));
> - append_composite_type_field (t, "v8_int16",
> - init_vector_type (bt->builtin_int16, 8));
> - append_composite_type_field (t, "v4_int32",
> - init_vector_type (bt->builtin_int32, 4));
> - append_composite_type_field (t, "v2_int64",
> - init_vector_type (bt->builtin_int64, 2));
> - append_composite_type_field (t, "uint128", bt->builtin_int128);
> -
> - TYPE_VECTOR (t) = 1;
> - TYPE_NAME (t) = "builtin_type_vec128i";
> - tdep->i386_sse_type = t;
> - }
> -
> - return tdep->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. */
> + register REGNUM. */
>
> static struct type *
> -i386_register_type (struct gdbarch *gdbarch, int regnum)
> +i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
> {
> - if (regnum == I386_EIP_REGNUM)
> - return builtin_type (gdbarch)->builtin_func_ptr;
> -
> - if (regnum == I386_EFLAGS_REGNUM)
> - return i386_eflags_type (gdbarch);
> -
> - if (regnum == I386_EBP_REGNUM || regnum == I386_ESP_REGNUM)
> - return builtin_type (gdbarch)->builtin_data_ptr;
> -
> - if (i386_fp_regnum_p (gdbarch, regnum))
> - return i387_ext_type (gdbarch);
> -
> - if (i386_mmx_regnum_p (gdbarch, regnum))
> - return i386_mmx_type (gdbarch);
> -
> - if (i386_sse_regnum_p (gdbarch, regnum))
> - return i386_sse_type (gdbarch);
> -
> - if (regnum == I387_MXCSR_REGNUM (gdbarch_tdep (gdbarch)))
> - return i386_mxcsr_type (gdbarch);
> -
> - return builtin_type (gdbarch)->builtin_int;
> + gdb_assert (i386_mmx_regnum_p (gdbarch, regnum));
> + return i386_mmx_type (gdbarch);
> }
>
> /* Map a cooked register onto a raw register or memory. For the i386,
> @@ -2761,7 +2621,7 @@ i386_go32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* DJGPP does not support the SSE registers. */
> tdep->num_xmm_regs = 0;
> - set_gdbarch_num_regs (gdbarch, I386_NUM_GREGS + I386_NUM_FREGS);
> + set_gdbarch_num_regs (gdbarch, I386_NUM_GREGS + I387_NUM_REGS);
>
> /* Native compiler is GCC, which uses the SVR4 register numbering
> even in COFF and STABS. See the comment in i386_gdbarch_init,
> @@ -5623,12 +5483,50 @@ i386_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
> return 1;
> }
>
> +static int
> +i386_validate_tdesc_p (struct gdbarch_tdep *tdep,
> + struct tdesc_arch_data *tdesc_data)
> +{
> + const struct target_desc *tdesc = tdep->tdesc;
> + const struct tdesc_feature *feature_core, *feature_vector;
> + int i, num_regs, valid_p;
> +
> + if (! tdesc_has_registers (tdesc))
> + return 0;
> +
> + /* Get core registers. */
> + feature_core = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.core");
> +
> + /* Get SSE registers. */
> + feature_vector = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.sse");
> +
> + if (feature_core == NULL || feature_vector == NULL)
> + return 0;
> +
> + valid_p = 1;
> +
> + num_regs = tdep->num_core_regs;
> + for (i = 0; i < num_regs; i++)
> + valid_p &= tdesc_numbered_register (feature_core, tdesc_data, i,
> + tdep->register_names[i]);
> +
> + /* Need to include %mxcsr, so add one. */
> + num_regs += tdep->num_xmm_regs + 1;
> + for (; i < num_regs; i++)
> + valid_p &= tdesc_numbered_register (feature_vector, tdesc_data, i,
> + tdep->register_names[i]);
> +
> + return valid_p;
> +}
> +
> \f
> static struct gdbarch *
> i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
> {
> struct gdbarch_tdep *tdep;
> struct gdbarch *gdbarch;
> + struct tdesc_arch_data *tdesc_data;
> + const struct target_desc *tdesc;
>
> /* If there is already a candidate, use it. */
> arches = gdbarch_list_lookup_by_info (arches, &info);
> @@ -5696,12 +5594,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
> alignment. */
> set_gdbarch_long_double_bit (gdbarch, 96);
>
> - /* 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);
> -
> /* Register numbers of various important registers. */
> set_gdbarch_sp_regnum (gdbarch, I386_ESP_REGNUM); /* %esp */
> set_gdbarch_pc_regnum (gdbarch, I386_EIP_REGNUM); /* %eip */
> @@ -5772,11 +5664,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>
> set_gdbarch_frame_args_skip (gdbarch, 8);
>
> - /* Wire in the MMX registers. */
> - set_gdbarch_num_pseudo_regs (gdbarch, i386_num_mmx_regs);
> - set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read);
> - set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
> -
> set_gdbarch_print_insn (gdbarch, i386_print_insn);
>
> set_gdbarch_dummy_id (gdbarch, i386_dummy_id);
> @@ -5785,7 +5672,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>
> /* Add the i386 register groups. */
> i386_add_reggroups (gdbarch);
> - set_gdbarch_register_reggroup_p (gdbarch, i386_register_reggroup_p);
> + tdep->register_reggroup_p = i386_register_reggroup_p;
>
> /* Helper for function argument information. */
> set_gdbarch_fetch_pointer_argument (gdbarch, i386_fetch_pointer_argument);
> @@ -5803,9 +5690,49 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>
> frame_base_set_default (gdbarch, &i386_frame_base);
>
> + /* Wire in the MMX registers. */
> + set_gdbarch_num_pseudo_regs (gdbarch, i386_num_mmx_regs);
> + set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read);
> + set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
> +
> + set_tdesc_pseudo_register_type (gdbarch, i386_pseudo_register_type);
> + set_tdesc_pseudo_register_name (gdbarch, i386_pseudo_register_name);
> +
> + /* The default ABI includes general-purpose registers,
> + floating-point registers, and the SSE registers. */
> + set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS);
> +
> + /* Get the x86 target description from INFO. */
> + tdesc = info.target_desc;
> + if (! tdesc_has_registers (tdesc))
> + tdesc = tdesc_i386;
> + tdep->tdesc = tdesc;
> +
> + tdep->num_core_regs = I386_NUM_GREGS + I387_NUM_REGS;
> + tdep->register_names = i386_register_names;
> +
> + tdesc_data = tdesc_data_alloc ();
> +
> /* Hook in ABI-specific overrides, if they have been registered. */
> + info.tdep_info = (void *) tdesc_data;
> gdbarch_init_osabi (info, gdbarch);
>
> + /* Target description may be changed. */
> + tdesc = tdep->tdesc;
> +
> + if (!i386_validate_tdesc_p (tdep, tdesc_data))
> + {
> + tdesc_data_cleanup (tdesc_data);
> + xfree (tdep);
> + gdbarch_free (gdbarch);
> + return NULL;
> + }
> +
> + tdesc_use_registers (gdbarch, tdesc, tdesc_data);
> +
> + /* Override gdbarch_register_reggroup_p set in tdesc_use_registers. */
> + set_gdbarch_register_reggroup_p (gdbarch, tdep->register_reggroup_p);
> +
> /* Hook in the legacy prologue-based unwinders last (fallback). */
> frame_unwind_append_unwinder (gdbarch, &i386_sigtramp_frame_unwind);
> frame_unwind_append_unwinder (gdbarch, &i386_frame_unwind);
> @@ -5882,4 +5809,7 @@ is \"default\"."),
>
> /* Initialize the i386-specific register groups. */
> i386_init_reggroups ();
> +
> + /* Initialize the standard target descriptions. */
> + initialize_tdesc_i386 ();
> }
> diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
> index 5915eb9..a64e5c3 100644
> --- a/gdb/i386-tdep.h
> +++ b/gdb/i386-tdep.h
> @@ -118,9 +118,21 @@ struct gdbarch_tdep
> of MMX support. */
> int mm0_regnum;
>
> + /* Number of core registers. */
> + int num_core_regs;
> +
> /* Number of SSE registers. */
> int num_xmm_regs;
>
> + /* Register names. */
> + const char **register_names;
> +
> + /* Target description. */
> + const struct target_desc *tdesc;
> +
> + /* Register group function. */
> + const void *register_reggroup_p;
> +
> /* Offset of saved PC in jmp_buf. */
> int jb_pc_offset;
>
> @@ -147,10 +159,7 @@ struct gdbarch_tdep
> int sc_sp_offset;
>
> /* ISA-specific data types. */
> - struct type *i386_eflags_type;
> - struct type *i386_mxcsr_type;
> struct type *i386_mmx_type;
> - struct type *i386_sse_type;
> struct type *i387_ext_type;
>
> /* Process record/replay target. */
> @@ -196,7 +205,8 @@ enum i386_regnum
> I386_ES_REGNUM, /* %es */
> I386_FS_REGNUM, /* %fs */
> I386_GS_REGNUM, /* %gs */
> - I386_ST0_REGNUM /* %st(0) */
> + I386_ST0_REGNUM, /* %st(0) */
> + I386_MXCSR_REGNUM = 40 /* %mxcsr */
> };
>
> /* Register numbers of RECORD_REGMAP. */
> @@ -230,20 +240,14 @@ enum record_i386_regnum
> };
>
> #define I386_NUM_GREGS 16
> -#define I386_NUM_FREGS 16
> #define I386_NUM_XREGS 9
>
> -#define I386_SSE_NUM_REGS (I386_NUM_GREGS + I386_NUM_FREGS \
> - + I386_NUM_XREGS)
> +#define I386_SSE_NUM_REGS (I386_MXCSR_REGNUM + 1)
>
> /* Size of the largest register. */
> #define I386_MAX_REGISTER_SIZE 16
>
> /* Types for i386-specific registers. */
> -extern struct type *i386_eflags_type (struct gdbarch *gdbarch);
> -extern struct type *i386_mxcsr_type (struct gdbarch *gdbarch);
> -extern struct type *i386_mmx_type (struct gdbarch *gdbarch);
> -extern struct type *i386_sse_type (struct gdbarch *gdbarch);
> extern struct type *i387_ext_type (struct gdbarch *gdbarch);
>
> /* Segment selectors. */
> @@ -263,9 +267,6 @@ extern CORE_ADDR i386_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
> /* Return whether the THIS_FRAME corresponds to a sigtramp routine. */
> extern int i386_sigtramp_p (struct frame_info *this_frame);
>
> -/* Return the name of register REGNUM. */
> -extern char const *i386_register_name (struct gdbarch * gdbarch, int regnum);
> -
> /* Return non-zero if REGNUM is a member of the specified group. */
> extern int i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
> struct reggroup *group);
> diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
> index 5a08ace..645eb91 100644
> --- a/gdb/i387-tdep.h
> +++ b/gdb/i387-tdep.h
> @@ -27,6 +27,9 @@ struct regcache;
> struct type;
> struct ui_file;
>
> +/* Number of i387 floating point registers. */
> +#define I387_NUM_REGS 16
> +
> #define I387_ST0_REGNUM(tdep) ((tdep)->st0_regnum)
> #define I387_NUM_XMM_REGS(tdep) ((tdep)->num_xmm_regs)
> #define I387_MM0_REGNUM(tdep) ((tdep)->mm0_regnum)
> diff --git a/gdb/regformats/i386/amd64-linux.dat b/gdb/regformats/i386/amd64-linux.dat
> new file mode 100644
> index 0000000..02a2c78
> --- /dev/null
> +++ b/gdb/regformats/i386/amd64-linux.dat
> @@ -0,0 +1,62 @@
> +# DO NOT EDIT: generated from i386/amd64-linux.xml
> +name:amd64_linux
> +xmltarget:amd64-linux.xml
> +expedite:rbp,rsp,rip
> +64:rax
> +64:rbx
> +64:rcx
> +64:rdx
> +64:rsi
> +64:rdi
> +64:rbp
> +64:rsp
> +64:r8
> +64:r9
> +64:r10
> +64:r11
> +64:r12
> +64:r13
> +64:r14
> +64:r15
> +64:rip
> +32:eflags
> +32:cs
> +32:ss
> +32:ds
> +32:es
> +32:fs
> +32:gs
> +80:st0
> +80:st1
> +80:st2
> +80:st3
> +80:st4
> +80:st5
> +80:st6
> +80:st7
> +32:fctrl
> +32:fstat
> +32:ftag
> +32:fiseg
> +32:fioff
> +32:foseg
> +32:fooff
> +32:fop
> +128:xmm0
> +128:xmm1
> +128:xmm2
> +128:xmm3
> +128:xmm4
> +128:xmm5
> +128:xmm6
> +128:xmm7
> +128:xmm8
> +128:xmm9
> +128:xmm10
> +128:xmm11
> +128:xmm12
> +128:xmm13
> +128:xmm14
> +128:xmm15
> +32:mxcsr
> +64:orig_rax
> diff --git a/gdb/regformats/i386/amd64.dat b/gdb/regformats/i386/amd64.dat
> new file mode 100644
> index 0000000..d589218
> --- /dev/null
> +++ b/gdb/regformats/i386/amd64.dat
> @@ -0,0 +1,61 @@
> +# DO NOT EDIT: generated from i386/amd64.xml
> +name:amd64
> +xmltarget:amd64.xml
> +expedite:rbp,rsp,rip
> +64:rax
> +64:rbx
> +64:rcx
> +64:rdx
> +64:rsi
> +64:rdi
> +64:rbp
> +64:rsp
> +64:r8
> +64:r9
> +64:r10
> +64:r11
> +64:r12
> +64:r13
> +64:r14
> +64:r15
> +64:rip
> +32:eflags
> +32:cs
> +32:ss
> +32:ds
> +32:es
> +32:fs
> +32:gs
> +80:st0
> +80:st1
> +80:st2
> +80:st3
> +80:st4
> +80:st5
> +80:st6
> +80:st7
> +32:fctrl
> +32:fstat
> +32:ftag
> +32:fiseg
> +32:fioff
> +32:foseg
> +32:fooff
> +32:fop
> +128:xmm0
> +128:xmm1
> +128:xmm2
> +128:xmm3
> +128:xmm4
> +128:xmm5
> +128:xmm6
> +128:xmm7
> +128:xmm8
> +128:xmm9
> +128:xmm10
> +128:xmm11
> +128:xmm12
> +128:xmm13
> +128:xmm14
> +128:xmm15
> +32:mxcsr
> diff --git a/gdb/regformats/i386/i386-linux.dat b/gdb/regformats/i386/i386-linux.dat
> new file mode 100644
> index 0000000..6fef8d9
> --- /dev/null
> +++ b/gdb/regformats/i386/i386-linux.dat
> @@ -0,0 +1,46 @@
> +# DO NOT EDIT: generated from i386/i386-linux.xml
> +name:i386_linux
> +xmltarget:i386-linux.xml
> +expedite:ebp,esp,eip
> +32:eax
> +32:ecx
> +32:edx
> +32:ebx
> +32:esp
> +32:ebp
> +32:esi
> +32:edi
> +32:eip
> +32:eflags
> +32:cs
> +32:ss
> +32:ds
> +32:es
> +32:fs
> +32:gs
> +80:st0
> +80:st1
> +80:st2
> +80:st3
> +80:st4
> +80:st5
> +80:st6
> +80:st7
> +32:fctrl
> +32:fstat
> +32:ftag
> +32:fiseg
> +32:fioff
> +32:foseg
> +32:fooff
> +32:fop
> +128:xmm0
> +128:xmm1
> +128:xmm2
> +128:xmm3
> +128:xmm4
> +128:xmm5
> +128:xmm6
> +128:xmm7
> +32:mxcsr
> +32:orig_eax
> diff --git a/gdb/regformats/i386/i386.dat b/gdb/regformats/i386/i386.dat
> new file mode 100644
> index 0000000..923d879
> --- /dev/null
> +++ b/gdb/regformats/i386/i386.dat
> @@ -0,0 +1,45 @@
> +# DO NOT EDIT: generated from i386/i386.xml
> +name:i386
> +xmltarget:i386.xml
> +expedite:ebp,esp,eip
> +32:eax
> +32:ecx
> +32:edx
> +32:ebx
> +32:esp
> +32:ebp
> +32:esi
> +32:edi
> +32:eip
> +32:eflags
> +32:cs
> +32:ss
> +32:ds
> +32:es
> +32:fs
> +32:gs
> +80:st0
> +80:st1
> +80:st2
> +80:st3
> +80:st4
> +80:st5
> +80:st6
> +80:st7
> +32:fctrl
> +32:fstat
> +32:ftag
> +32:fiseg
> +32:fioff
> +32:foseg
> +32:fooff
> +32:fop
> +128:xmm0
> +128:xmm1
> +128:xmm2
> +128:xmm3
> +128:xmm4
> +128:xmm5
> +128:xmm6
> +128:xmm7
> +32:mxcsr
> diff --git a/gdb/testsuite/gdb.xml/tdesc-regs.exp b/gdb/testsuite/gdb.xml/tdesc-regs.exp
> index 0922ca3..8eae0bd 100644
> --- a/gdb/testsuite/gdb.xml/tdesc-regs.exp
> +++ b/gdb/testsuite/gdb.xml/tdesc-regs.exp
> @@ -25,6 +25,7 @@ gdb_start
>
> set core-regs ""
> set regdir ""
> +set architecture ""
> switch -glob -- [istarget] {
> "*arm-*-*" {
> set core-regs {arm-core.xml}
> @@ -55,6 +56,16 @@ switch -glob -- [istarget] {
> unsupported "register tests"
> return 0
> }
> + "i?86-*-*" {
> + set architecture "i386"
> + set regdir "i386/"
> + set core-regs {32bit-core.xml 32bit-sse.xml}
> + }
> + "x86_64-*-*" {
> + set architecture "i386:x86-64"
> + set regdir "i386/"
> + set core-regs {64bit-core.xml 64bit-sse.xml}
> + }
> }
>
> # If no core registers were specified, assume this target does not
> @@ -89,12 +100,16 @@ proc load_description { file errmsg } {
> global subdir
> global gdb_prompt
> global core-regs
> + global architecture
>
> file delete "$subdir/regs.xml"
> set ifd [open "$srcdir/$subdir/$file" r]
> set ofd [open "$subdir/regs.xml" w]
> while {[gets $ifd line] >= 0} {
> if {[regexp {<xi:include href="core-regs.xml"/>} $line]} {
> + if {! [string equal ${architecture} ""]} {
> + puts $ofd " <architecture>${architecture}</architecture>"
> + }
> foreach src ${core-regs} {
> puts $ofd " <xi:include href=\"$src\"/>"
> }
>