+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ /* FIXME: kettenis/20020511: Why do we override this function here? */
+ set_gdbarch_frame_chain_valid (gdbarch, generic_func_frame_chain_valid);
+
+ tdep->jb_pc_offset = 24;
+}
+\f
+
+/* i386 register groups. In addition to the normal groups, add "mmx"
+ and "sse". */
+
+static struct reggroup *i386_sse_reggroup;
+static struct reggroup *i386_mmx_reggroup;
+
+static void
+i386_init_reggroups (void)
+{
+ i386_sse_reggroup = reggroup_new ("sse", USER_REGGROUP);
+ i386_mmx_reggroup = reggroup_new ("mmx", USER_REGGROUP);
+}
+
+static void
+i386_add_reggroups (struct gdbarch *gdbarch)
+{
+ reggroup_add (gdbarch, i386_sse_reggroup);
+ reggroup_add (gdbarch, i386_mmx_reggroup);
+ reggroup_add (gdbarch, general_reggroup);
+ reggroup_add (gdbarch, float_reggroup);
+ reggroup_add (gdbarch, all_reggroup);
+ reggroup_add (gdbarch, save_reggroup);
+ reggroup_add (gdbarch, restore_reggroup);
+ reggroup_add (gdbarch, vector_reggroup);
+ reggroup_add (gdbarch, system_reggroup);
+}
+
+int
+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 fp_regnum_p = (i386_fp_regnum_p (regnum)
+ || i386_fpc_regnum_p (regnum));
+ int mmx_regnum_p = (i386_mmx_regnum_p (regnum));
+ if (group == i386_mmx_reggroup)
+ return mmx_regnum_p;
+ if (group == i386_sse_reggroup)
+ return sse_regnum_p;
+ if (group == vector_reggroup)
+ return (mmx_regnum_p || sse_regnum_p);
+ if (group == float_reggroup)
+ return fp_regnum_p;
+ if (group == general_reggroup)
+ return (!fp_regnum_p && !mmx_regnum_p && !sse_regnum_p);
+ return default_register_reggroup_p (gdbarch, regnum, group);
+}
+
+\f
+static struct gdbarch *
+i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ struct gdbarch_tdep *tdep;
+ struct gdbarch *gdbarch;
+ enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
+
+ /* Try to determine the OS ABI of the object we're loading. */
+ if (info.abfd != NULL)
+ osabi = gdbarch_lookup_osabi (info.abfd);
+
+ /* Find a candidate among extant architectures. */
+ for (arches = gdbarch_list_lookup_by_info (arches, &info);
+ arches != NULL;
+ arches = gdbarch_list_lookup_by_info (arches->next, &info))
+ {
+ /* Make sure the OS ABI selection matches. */
+ tdep = gdbarch_tdep (arches->gdbarch);
+ if (tdep && tdep->osabi == osabi)
+ return arches->gdbarch;
+ }
+
+ /* Allocate space for the new architecture. */
+ tdep = XMALLOC (struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
+
+ tdep->osabi = osabi;
+
+ /* 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;
+
+ tdep->jb_pc_offset = -1;
+ tdep->struct_return = pcc_struct_return;
+ tdep->sigtramp_start = 0;
+ tdep->sigtramp_end = 0;
+ tdep->sigcontext_addr = NULL;
+ tdep->sc_pc_offset = -1;
+ tdep->sc_sp_offset = -1;
+
+ /* The format used for `long double' on almost all i386 targets is
+ 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);
+
+ /* Although the i387 extended floating-point has only 80 significant
+ bits, a `long double' actually takes up 96, probably to enforce
+ alignment. */
+ set_gdbarch_long_double_bit (gdbarch, 96);
+
+ /* NOTE: tm-i386aix.h, tm-i386bsd.h, tm-i386os9k.h, tm-ptx.h,
+ tm-symmetry.h currently override this. Sigh. */
+ set_gdbarch_num_regs (gdbarch, I386_NUM_GREGS + I386_NUM_FREGS);
+
+ set_gdbarch_sp_regnum (gdbarch, 4); /* %esp */
+ set_gdbarch_fp_regnum (gdbarch, 5); /* %ebp */
+ set_gdbarch_pc_regnum (gdbarch, 8); /* %eip */
+ set_gdbarch_ps_regnum (gdbarch, 9); /* %eflags */
+ set_gdbarch_fp0_regnum (gdbarch, 16); /* %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);
+
+ /* 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_name (gdbarch, i386_register_name);
+ set_gdbarch_register_size (gdbarch, 4);
+ set_gdbarch_register_bytes (gdbarch, I386_SIZEOF_GREGS + I386_SIZEOF_FREGS);
+ set_gdbarch_max_register_raw_size (gdbarch, I386_MAX_REGISTER_SIZE);
+ set_gdbarch_max_register_virtual_size (gdbarch, I386_MAX_REGISTER_SIZE);
+ set_gdbarch_register_virtual_type (gdbarch, i386_register_virtual_type);
+
+ set_gdbarch_print_float_info (gdbarch, i387_print_float_info);
+
+ set_gdbarch_get_longjmp_target (gdbarch, i386_get_longjmp_target);
+
+ set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
+
+ /* Call dummy code. */
+ set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
+ set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
+ set_gdbarch_call_dummy_start_offset (gdbarch, 0);
+ set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
+ set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
+ set_gdbarch_call_dummy_length (gdbarch, 0);
+ set_gdbarch_call_dummy_p (gdbarch, 1);
+ set_gdbarch_call_dummy_words (gdbarch, NULL);
+ set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
+ set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+ set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
+
+ set_gdbarch_register_convertible (gdbarch, i386_register_convertible);
+ set_gdbarch_register_convert_to_virtual (gdbarch,
+ i386_register_convert_to_virtual);
+ set_gdbarch_register_convert_to_raw (gdbarch, i386_register_convert_to_raw);
+
+ set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
+
+ /* "An argument's size is increased, if necessary, to make it a
+ multiple of [32-bit] words. This may require tail padding,
+ depending on the size of the argument" -- from the x86 ABI. */
+ set_gdbarch_parm_boundary (gdbarch, 32);
+
+ set_gdbarch_extract_return_value (gdbarch, i386_extract_return_value);
+ set_gdbarch_push_arguments (gdbarch, i386_push_arguments);
+ set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
+ set_gdbarch_push_return_address (gdbarch, i386_push_return_address);
+ set_gdbarch_pop_frame (gdbarch, i386_pop_frame);
+ set_gdbarch_store_struct_return (gdbarch, i386_store_struct_return);
+ 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_frame_init_saved_regs (gdbarch, i386_frame_init_saved_regs);
+ set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
+
+ /* Stack grows downward. */
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+
+ 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);
+
+ /* The following redefines make backtracing through sigtramp work.
+ They manufacture a fake sigtramp frame and obtain the saved pc in
+ sigtramp from the sigcontext structure which is pushed by the
+ kernel on the user stack, along with a pointer to it. */
+
+ set_gdbarch_frame_args_skip (gdbarch, 8);
+ set_gdbarch_frameless_function_invocation (gdbarch,
+ i386_frameless_function_invocation);
+ set_gdbarch_frame_chain (gdbarch, i386_frame_chain);
+ set_gdbarch_frame_chain_valid (gdbarch, generic_file_frame_chain_valid);
+ set_gdbarch_frame_saved_pc (gdbarch, i386_frame_saved_pc);
+ set_gdbarch_saved_pc_after_call (gdbarch, i386_saved_pc_after_call);
+ set_gdbarch_frame_num_args (gdbarch, i386_frame_num_args);
+ set_gdbarch_pc_in_sigtramp (gdbarch, i386_pc_in_sigtramp);
+
+ /* Wire in the MMX registers. */
+ set_gdbarch_num_pseudo_regs (gdbarch, mmx_num_regs);
+ set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
+
+ set_gdbarch_print_insn (gdbarch, i386_print_insn);
+
+ /* Add the i386 register groups. */
+ i386_add_reggroups (gdbarch);
+ set_gdbarch_register_reggroup_p (gdbarch, i386_register_reggroup_p);
+
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch, osabi);
+
+ return gdbarch;
+}
+
+static enum gdb_osabi
+i386_coff_osabi_sniffer (bfd *abfd)
+{
+ if (strcmp (bfd_get_target (abfd), "coff-go32-exe") == 0
+ || strcmp (bfd_get_target (abfd), "coff-go32") == 0)
+ return GDB_OSABI_GO32;
+
+ return GDB_OSABI_UNKNOWN;
+}
+
+static enum gdb_osabi
+i386_nlm_osabi_sniffer (bfd *abfd)
+{
+ return GDB_OSABI_NETWARE;