+\f
+
+/* Initialize the current architecture based on INFO. If possible, re-use an
+ architecture from ARCHES, which is a list of architectures already created
+ during this debugging session.
+
+ Called e.g. at program startup, when reading a core file, and when reading
+ a binary file. */
+
+static struct gdbarch *
+alpha_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 ABI of the object we are loading. */
+
+ if (info.abfd != NULL)
+ {
+ osabi = gdbarch_lookup_osabi (info.abfd);
+ if (osabi == GDB_OSABI_UNKNOWN)
+ {
+ /* If it's an ECOFF file, assume it's OSF/1. */
+ if (bfd_get_flavour (info.abfd) == bfd_target_ecoff_flavour)
+ osabi = GDB_OSABI_OSF1;
+ }
+ }
+
+ /* 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 ABI selection matches. */
+ tdep = gdbarch_tdep (arches->gdbarch);
+ if (tdep && tdep->osabi == osabi)
+ return arches->gdbarch;
+ }
+
+ tdep = xmalloc (sizeof (struct gdbarch_tdep));
+ gdbarch = gdbarch_alloc (&info, tdep);
+
+ tdep->osabi = osabi;
+
+ /* Lowest text address. This is used by heuristic_proc_start() to
+ decide when to stop looking. */
+ tdep->vm_min_address = (CORE_ADDR) 0x120000000;
+
+ tdep->dynamic_sigtramp_offset = NULL;
+ tdep->skip_sigtramp_frame = NULL;
+ tdep->sigcontext_addr = NULL;
+
+ tdep->jb_pc = -1; /* longjmp support not enabled by default */
+
+ /* Type sizes */
+ set_gdbarch_short_bit (gdbarch, 16);
+ set_gdbarch_int_bit (gdbarch, 32);
+ set_gdbarch_long_bit (gdbarch, 64);
+ set_gdbarch_long_long_bit (gdbarch, 64);
+ set_gdbarch_float_bit (gdbarch, 32);
+ set_gdbarch_double_bit (gdbarch, 64);
+ set_gdbarch_long_double_bit (gdbarch, 64);
+ set_gdbarch_ptr_bit (gdbarch, 64);
+
+ /* Register info */
+ set_gdbarch_num_regs (gdbarch, ALPHA_NUM_REGS);
+ set_gdbarch_sp_regnum (gdbarch, ALPHA_SP_REGNUM);
+ set_gdbarch_fp_regnum (gdbarch, ALPHA_FP_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, ALPHA_PC_REGNUM);
+ set_gdbarch_fp0_regnum (gdbarch, ALPHA_FP0_REGNUM);
+
+ set_gdbarch_register_name (gdbarch, alpha_register_name);
+ set_gdbarch_register_size (gdbarch, ALPHA_REGISTER_SIZE);
+ set_gdbarch_register_bytes (gdbarch, ALPHA_REGISTER_BYTES);
+ set_gdbarch_register_byte (gdbarch, alpha_register_byte);
+ set_gdbarch_register_raw_size (gdbarch, alpha_register_raw_size);
+ set_gdbarch_max_register_raw_size (gdbarch, ALPHA_MAX_REGISTER_RAW_SIZE);
+ set_gdbarch_register_virtual_size (gdbarch, alpha_register_virtual_size);
+ set_gdbarch_max_register_virtual_size (gdbarch,
+ ALPHA_MAX_REGISTER_VIRTUAL_SIZE);
+ set_gdbarch_register_virtual_type (gdbarch, alpha_register_virtual_type);
+
+ set_gdbarch_cannot_fetch_register (gdbarch, alpha_cannot_fetch_register);
+ set_gdbarch_cannot_store_register (gdbarch, alpha_cannot_store_register);
+
+ set_gdbarch_register_convertible (gdbarch, alpha_register_convertible);
+ set_gdbarch_register_convert_to_virtual (gdbarch,
+ alpha_register_convert_to_virtual);
+ set_gdbarch_register_convert_to_raw (gdbarch, alpha_register_convert_to_raw);
+
+ set_gdbarch_skip_prologue (gdbarch, alpha_skip_prologue);
+
+ set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
+ set_gdbarch_frameless_function_invocation (gdbarch,
+ generic_frameless_function_invocation_not);
+
+ set_gdbarch_saved_pc_after_call (gdbarch, alpha_saved_pc_after_call);
+
+ set_gdbarch_frame_chain (gdbarch, alpha_frame_chain);
+ set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
+ set_gdbarch_frame_saved_pc (gdbarch, alpha_frame_saved_pc);
+
+ set_gdbarch_frame_init_saved_regs (gdbarch, alpha_frame_init_saved_regs);
+ set_gdbarch_get_saved_register (gdbarch, alpha_get_saved_register);
+
+ set_gdbarch_use_struct_convention (gdbarch, alpha_use_struct_convention);
+ set_gdbarch_extract_return_value (gdbarch, alpha_extract_return_value);
+
+ set_gdbarch_store_struct_return (gdbarch, alpha_store_struct_return);
+ set_gdbarch_store_return_value (gdbarch, alpha_store_return_value);
+ set_gdbarch_extract_struct_value_address (gdbarch,
+ alpha_extract_struct_value_address);
+
+ /* Settings for calling functions in the inferior. */
+ set_gdbarch_use_generic_dummy_frames (gdbarch, 0);
+ set_gdbarch_call_dummy_length (gdbarch, 0);
+ set_gdbarch_push_arguments (gdbarch, alpha_push_arguments);
+ set_gdbarch_pop_frame (gdbarch, alpha_pop_frame);
+
+ /* On the Alpha, the call dummy code is never copied to user space,
+ stopping the user call is achieved via a bp_call_dummy breakpoint.
+ But we need a fake CALL_DUMMY definition to enable the proper
+ call_function_by_hand and to avoid zero length array warnings. */
+ set_gdbarch_call_dummy_p (gdbarch, 1);
+ set_gdbarch_call_dummy_words (gdbarch, alpha_call_dummy_words);
+ set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
+ set_gdbarch_frame_args_address (gdbarch, alpha_frame_args_address);
+ set_gdbarch_frame_locals_address (gdbarch, alpha_frame_locals_address);
+ set_gdbarch_init_extra_frame_info (gdbarch, alpha_init_extra_frame_info);
+
+ /* Alpha OSF/1 inhibits execution of code on the stack. But there is
+ no need for a dummy on the Alpha. PUSH_ARGUMENTS takes care of all
+ argument handling and bp_call_dummy takes care of stopping the dummy. */
+ set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
+ set_gdbarch_call_dummy_address (gdbarch, alpha_call_dummy_address);
+ set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
+ set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
+ set_gdbarch_call_dummy_start_offset (gdbarch, 0);
+ set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
+ set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+ set_gdbarch_push_dummy_frame (gdbarch, alpha_push_dummy_frame);
+ set_gdbarch_fix_call_dummy (gdbarch, alpha_fix_call_dummy);
+ set_gdbarch_init_frame_pc (gdbarch, init_frame_pc_noop);
+ set_gdbarch_init_frame_pc_first (gdbarch, alpha_init_frame_pc_first);
+
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+
+ /* Floats are always passed as doubles. */
+ set_gdbarch_coerce_float_to_double (gdbarch,
+ standard_coerce_float_to_double);
+
+ set_gdbarch_breakpoint_from_pc (gdbarch, alpha_breakpoint_from_pc);
+ set_gdbarch_decr_pc_after_break (gdbarch, 4);
+
+ set_gdbarch_function_start_offset (gdbarch, 0);
+ set_gdbarch_frame_args_skip (gdbarch, 0);
+
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch, osabi);
+
+ /* Now that we have tuned the configuration, set a few final things
+ based on what the OS ABI has told us. */
+
+ if (tdep->jb_pc >= 0)
+ set_gdbarch_get_longjmp_target (gdbarch, alpha_get_longjmp_target);
+
+ return gdbarch;
+}
+
+static void
+alpha_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+ if (tdep == NULL)
+ return;
+
+ fprintf_unfiltered (file, "alpha_dump_tdep: OS ABI = %s\n",
+ gdbarch_osabi_name (tdep->osabi));
+
+ fprintf_unfiltered (file,
+ "alpha_dump_tdep: vm_min_address = 0x%lx\n",
+ (long) tdep->vm_min_address);
+
+ fprintf_unfiltered (file,
+ "alpha_dump_tdep: jb_pc = %d\n",
+ tdep->jb_pc);
+ fprintf_unfiltered (file,
+ "alpha_dump_tdep: jb_elt_size = %ld\n",
+ (long) tdep->jb_elt_size);
+}
+