+ int len = TYPE_LENGTH (type);
+
+ switch (len)
+ {
+ case 1:
+ memcpy (valbuf, ®buf[HARD_D_REGNUM * 2 + 1], len);
+ break;
+
+ case 2:
+ memcpy (valbuf, ®buf[HARD_D_REGNUM * 2], len);
+ break;
+
+ case 3:
+ memcpy (&valbuf[0], ®buf[HARD_X_REGNUM * 2 + 1], 1);
+ memcpy (&valbuf[1], ®buf[HARD_D_REGNUM * 2], 2);
+ break;
+
+ case 4:
+ memcpy (&valbuf[0], ®buf[HARD_X_REGNUM * 2], 2);
+ memcpy (&valbuf[2], ®buf[HARD_D_REGNUM * 2], 2);
+ break;
+
+ default:
+ error ("bad size for return value");
+ }
+}
+
+/* Should call_function allocate stack space for a struct return? */
+static int
+m68hc11_use_struct_convention (int gcc_p, struct type *type)
+{
+ return (TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION
+ || TYPE_LENGTH (type) > 4);
+}
+
+static int
+m68hc11_return_value_on_stack (struct type *type)
+{
+ return TYPE_LENGTH (type) > 4;
+}
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+static CORE_ADDR
+m68hc11_extract_struct_value_address (char *regbuf)
+{
+ return extract_address (®buf[HARD_D_REGNUM * 2],
+ REGISTER_RAW_SIZE (HARD_D_REGNUM));
+}
+
+/* Function: push_return_address (pc)
+ Set up the return address for the inferior function call.
+ Needed for targets where we don't actually execute a JSR/BSR instruction */
+
+static CORE_ADDR
+m68hc11_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
+{
+ char valbuf[2];
+
+ pc = CALL_DUMMY_ADDRESS ();
+ sp -= 2;
+ store_unsigned_integer (valbuf, 2, pc);
+ write_memory (sp + STACK_CORRECTION, valbuf, 2);
+ return sp;
+}
+
+/* Test whether the ELF symbol corresponds to a function using rtc or
+ rti to return. */
+
+static void
+m68hc11_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym)
+{
+ unsigned char flags;
+
+ flags = ((elf_symbol_type *)sym)->internal_elf_sym.st_other;
+ if (flags & STO_M68HC12_FAR)
+ MSYMBOL_SET_RTC (msym);
+ if (flags & STO_M68HC12_INTERRUPT)
+ MSYMBOL_SET_RTI (msym);
+}
+
+static int
+gdb_print_insn_m68hc11 (bfd_vma memaddr, disassemble_info *info)
+{
+ if (TARGET_ARCHITECTURE->arch == bfd_arch_m68hc11)
+ return print_insn_m68hc11 (memaddr, info);
+ else
+ return print_insn_m68hc12 (memaddr, info);
+}
+
+static struct gdbarch *
+m68hc11_gdbarch_init (struct gdbarch_info info,
+ struct gdbarch_list *arches)
+{
+ static LONGEST m68hc11_call_dummy_words[] =
+ {0};
+ struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
+ int elf_flags;
+
+ soft_reg_initialized = 0;
+
+ /* Extract the elf_flags if available. */
+ if (info.abfd != NULL
+ && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
+ elf_flags = elf_elfheader (info.abfd)->e_flags;
+ else
+ elf_flags = 0;
+
+ /* try to find a pre-existing architecture */
+ for (arches = gdbarch_list_lookup_by_info (arches, &info);
+ arches != NULL;
+ arches = gdbarch_list_lookup_by_info (arches->next, &info))
+ {
+ if (gdbarch_tdep (arches->gdbarch)->elf_flags != elf_flags)
+ continue;
+
+ return arches->gdbarch;
+ }
+
+ /* Need a new architecture. Fill in a target specific vector. */
+ tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
+ gdbarch = gdbarch_alloc (&info, tdep);
+ tdep->elf_flags = elf_flags;
+
+ /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
+ ready to unwind the PC first (see frame.c:get_prev_frame()). */
+ set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
+
+ switch (info.bfd_arch_info->arch)
+ {
+ case bfd_arch_m68hc11:
+ tdep->stack_correction = 1;
+ tdep->use_page_register = 0;
+ tdep->prologue = m6811_prologue;
+ set_gdbarch_addr_bit (gdbarch, 16);
+ set_gdbarch_num_pseudo_regs (gdbarch, M68HC11_NUM_PSEUDO_REGS);
+ set_gdbarch_pc_regnum (gdbarch, HARD_PC_REGNUM);
+ set_gdbarch_num_regs (gdbarch, M68HC11_NUM_REGS);
+ break;
+
+ case bfd_arch_m68hc12:
+ tdep->stack_correction = 0;
+ tdep->use_page_register = elf_flags & E_M68HC12_BANKS;
+ tdep->prologue = m6812_prologue;
+ set_gdbarch_addr_bit (gdbarch, elf_flags & E_M68HC12_BANKS ? 32 : 16);
+ set_gdbarch_num_pseudo_regs (gdbarch,
+ elf_flags & E_M68HC12_BANKS
+ ? M68HC12_NUM_PSEUDO_REGS
+ : M68HC11_NUM_PSEUDO_REGS);
+ set_gdbarch_pc_regnum (gdbarch, elf_flags & E_M68HC12_BANKS
+ ? M68HC12_HARD_PC_REGNUM : HARD_PC_REGNUM);
+ set_gdbarch_num_regs (gdbarch, elf_flags & E_M68HC12_BANKS
+ ? M68HC12_NUM_REGS : M68HC11_NUM_REGS);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Initially set everything according to the ABI.
+ Use 16-bit integers since it will be the case for most
+ programs. The size of these types should normally be set
+ according to the dwarf2 debug information. */
+ set_gdbarch_short_bit (gdbarch, 16);
+ set_gdbarch_int_bit (gdbarch, elf_flags & E_M68HC11_I32 ? 32 : 16);
+ set_gdbarch_float_bit (gdbarch, 32);
+ set_gdbarch_double_bit (gdbarch, elf_flags & E_M68HC11_F64 ? 64 : 32);
+ set_gdbarch_long_double_bit (gdbarch, elf_flags & E_M68HC11_F64 ? 64 : 32);
+ set_gdbarch_long_bit (gdbarch, 32);
+ set_gdbarch_ptr_bit (gdbarch, 16);
+ set_gdbarch_long_long_bit (gdbarch, 64);
+
+ /* Set register info. */
+ set_gdbarch_fp0_regnum (gdbarch, -1);
+ set_gdbarch_max_register_raw_size (gdbarch, 2);
+ set_gdbarch_max_register_virtual_size (gdbarch, 2);
+ set_gdbarch_frame_init_saved_regs (gdbarch, m68hc11_frame_init_saved_regs);
+ set_gdbarch_frame_args_skip (gdbarch, 0);
+
+ set_gdbarch_read_pc (gdbarch, generic_target_read_pc);
+ set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
+ set_gdbarch_read_fp (gdbarch, generic_target_read_fp);
+ set_gdbarch_read_sp (gdbarch, generic_target_read_sp);
+ set_gdbarch_write_sp (gdbarch, generic_target_write_sp);
+
+ set_gdbarch_sp_regnum (gdbarch, HARD_SP_REGNUM);
+ set_gdbarch_fp_regnum (gdbarch, SOFT_FP_REGNUM);
+ set_gdbarch_register_name (gdbarch, m68hc11_register_name);
+ set_gdbarch_register_size (gdbarch, 2);
+ set_gdbarch_register_bytes (gdbarch, M68HC11_ALL_REGS * 2);
+ set_gdbarch_register_virtual_type (gdbarch, m68hc11_register_virtual_type);
+ set_gdbarch_pseudo_register_read (gdbarch, m68hc11_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, m68hc11_pseudo_register_write);
+
+ set_gdbarch_call_dummy_length (gdbarch, 0);
+ set_gdbarch_call_dummy_address (gdbarch, m68hc11_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_call_dummy_words (gdbarch, m68hc11_call_dummy_words);
+ set_gdbarch_sizeof_call_dummy_words (gdbarch,
+ sizeof (m68hc11_call_dummy_words));
+ set_gdbarch_call_dummy_p (gdbarch, 1);
+ set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+ set_gdbarch_get_saved_register (gdbarch, deprecated_generic_get_saved_register);
+ set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
+ set_gdbarch_deprecated_extract_return_value (gdbarch, m68hc11_extract_return_value);
+ set_gdbarch_push_arguments (gdbarch, m68hc11_push_arguments);
+ set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
+ set_gdbarch_push_return_address (gdbarch, m68hc11_push_return_address);
+ set_gdbarch_return_value_on_stack (gdbarch, m68hc11_return_value_on_stack);
+
+ set_gdbarch_store_struct_return (gdbarch, m68hc11_store_struct_return);
+ set_gdbarch_deprecated_store_return_value (gdbarch, m68hc11_store_return_value);
+ set_gdbarch_deprecated_extract_struct_value_address (gdbarch, m68hc11_extract_struct_value_address);
+ set_gdbarch_register_convertible (gdbarch, generic_register_convertible_not);
+
+
+ set_gdbarch_frame_chain (gdbarch, m68hc11_frame_chain);
+ set_gdbarch_frame_chain_valid (gdbarch, generic_file_frame_chain_valid);
+ set_gdbarch_frame_saved_pc (gdbarch, m68hc11_frame_saved_pc);
+ set_gdbarch_frame_args_address (gdbarch, m68hc11_frame_args_address);
+ set_gdbarch_frame_locals_address (gdbarch, m68hc11_frame_locals_address);
+ set_gdbarch_saved_pc_after_call (gdbarch, m68hc11_saved_pc_after_call);
+ set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
+
+ set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
+ set_gdbarch_get_saved_register (gdbarch, deprecated_generic_get_saved_register);
+
+ set_gdbarch_store_struct_return (gdbarch, m68hc11_store_struct_return);
+ set_gdbarch_deprecated_store_return_value (gdbarch, m68hc11_store_return_value);
+ set_gdbarch_deprecated_extract_struct_value_address
+ (gdbarch, m68hc11_extract_struct_value_address);
+ set_gdbarch_use_struct_convention (gdbarch, m68hc11_use_struct_convention);
+ set_gdbarch_init_extra_frame_info (gdbarch, m68hc11_init_extra_frame_info);
+ set_gdbarch_pop_frame (gdbarch, m68hc11_pop_frame);
+ set_gdbarch_skip_prologue (gdbarch, m68hc11_skip_prologue);
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ set_gdbarch_decr_pc_after_break (gdbarch, 0);
+ set_gdbarch_function_start_offset (gdbarch, 0);
+ set_gdbarch_breakpoint_from_pc (gdbarch, m68hc11_breakpoint_from_pc);
+ set_gdbarch_stack_align (gdbarch, m68hc11_stack_align);
+ set_gdbarch_print_insn (gdbarch, gdb_print_insn_m68hc11);
+
+ /* Minsymbol frobbing. */
+ set_gdbarch_elf_make_msymbol_special (gdbarch,
+ m68hc11_elf_make_msymbol_special);
+
+ set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+
+ return gdbarch;