+static void
+h8300_store_return_value (struct type *type, char *valbuf)
+{
+ int regval;
+ int wordsize = BINWORD;
+ int len = TYPE_LENGTH (type);
+
+ switch (len)
+ {
+ case 1: /* char */
+ case 2: /* short, int */
+ regval = extract_address (valbuf, len);
+ write_register (0, regval);
+ break;
+ case 4: /* long, float */
+ regval = extract_address (valbuf, len);
+ if (wordsize == 4)
+ {
+ write_register (0, regval);
+ }
+ else
+ {
+ write_register (0, regval >> 16);
+ write_register (1, regval & 0xffff);
+ }
+ break;
+ case 8: /* presumeably double, but doesn't seem to happen */
+ error ("I don't know how to return a double.");
+ break;
+ }
+}
+
+static struct cmd_list_element *setmachinelist;
+
+static const char *
+h8300_register_name (int regno)
+{
+ /* The register names change depending on whether the h8300h processor
+ type is selected. */
+ static char *h8300_register_names[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6",
+ "sp", "ccr","pc","cycles", "tick", "inst", ""
+ };
+ static char *h8300s_register_names[] = {
+ "er0", "er1", "er2", "er3", "er4", "er5", "er6",
+ "sp", "ccr", "pc", "cycles", "exr", "tick", "inst"
+ };
+ char **register_names =
+ h8300smode ? h8300s_register_names : h8300_register_names;
+ if (regno < 0 || regno >= E_NUM_REGS)
+ internal_error (__FILE__, __LINE__,
+ "h8300_register_name: illegal register number %d", regno);
+ else
+ return register_names[regno];
+}
+
+static void
+h8300_print_register (struct gdbarch *gdbarch, struct ui_file *file,
+ struct frame_info *frame, int regno)
+{
+ ULONGEST rval;
+ long val;
+ const char *name = h8300_register_name (regno);
+
+ if (!name || !*name)
+ return;
+
+ /* FIXME: cagney/2002-10-22: The code below assumes that VAL is at
+ least 4 bytes (32 bits) in size and hence is large enough to hold
+ the largest h8300 register. Should instead be using ULONGEST and
+ the phex() functions. */
+ gdb_assert (sizeof (val) >= 4);
+ frame_read_unsigned_register (frame, regno, &rval);
+ val = rval;
+
+ fprintf_filtered (file, "%-14s ", name);
+ if (h8300hmode)
+ {
+ if (val)
+ fprintf_filtered (file, "0x%08lx %-8ld", val, val);
+ else
+ fprintf_filtered (file, "0x%-8lx %-8ld", val, val);
+ }
+ else
+ {
+ if (val)
+ fprintf_filtered (file, "0x%04lx %-4ld", val, val);
+ else
+ fprintf_filtered (file, "0x%-4lx %-4ld", val, val);
+ }
+ if (regno == E_CCR_REGNUM)
+ {
+ /* CCR register */
+ int C, Z, N, V;
+ unsigned char b[h8300h_reg_size];
+ unsigned char l;
+ frame_register_read (deprecated_selected_frame, regno, b);
+ l = b[REGISTER_VIRTUAL_SIZE (E_CCR_REGNUM) - 1];
+ fprintf_filtered (file, "\t");
+ fprintf_filtered (file, "I-%d ", (l & 0x80) != 0);
+ fprintf_filtered (file, "UI-%d ", (l & 0x40) != 0);
+ fprintf_filtered (file, "H-%d ", (l & 0x20) != 0);
+ fprintf_filtered (file, "U-%d ", (l & 0x10) != 0);
+ N = (l & 0x8) != 0;
+ Z = (l & 0x4) != 0;
+ V = (l & 0x2) != 0;
+ C = (l & 0x1) != 0;
+ fprintf_filtered (file, "N-%d ", N);
+ fprintf_filtered (file, "Z-%d ", Z);
+ fprintf_filtered (file, "V-%d ", V);
+ fprintf_filtered (file, "C-%d ", C);
+ if ((C | Z) == 0)
+ fprintf_filtered (file, "u> ");
+ if ((C | Z) == 1)
+ fprintf_filtered (file, "u<= ");
+ if ((C == 0))
+ fprintf_filtered (file, "u>= ");
+ if (C == 1)
+ fprintf_filtered (file, "u< ");
+ if (Z == 0)
+ fprintf_filtered (file, "!= ");
+ if (Z == 1)
+ fprintf_filtered (file, "== ");
+ if ((N ^ V) == 0)
+ fprintf_filtered (file, ">= ");
+ if ((N ^ V) == 1)
+ fprintf_filtered (file, "< ");
+ if ((Z | (N ^ V)) == 0)
+ fprintf_filtered (file, "> ");
+ if ((Z | (N ^ V)) == 1)
+ fprintf_filtered (file, "<= ");
+ }
+ else if (regno == E_EXR_REGNUM && h8300smode)
+ {
+ /* EXR register */
+ unsigned char b[h8300h_reg_size];
+ unsigned char l;
+ frame_register_read (deprecated_selected_frame, regno, b);
+ l = b[REGISTER_VIRTUAL_SIZE (E_EXR_REGNUM) - 1];
+ fprintf_filtered (file, "\t");
+ fprintf_filtered (file, "T-%d - - - ", (l & 0x80) != 0);
+ fprintf_filtered (file, "I2-%d ", (l & 4) != 0);
+ fprintf_filtered (file, "I1-%d ", (l & 2) != 0);
+ fprintf_filtered (file, "I0-%d", (l & 1) != 0);
+ }
+ fprintf_filtered (file, "\n");
+}
+
+static void
+h8300_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
+ struct frame_info *frame, int regno, int cpregs)
+{
+ if (regno < 0)
+ for (regno = 0; regno < E_NUM_REGS; ++regno)
+ h8300_print_register (gdbarch, file, frame, regno);
+ else
+ h8300_print_register (gdbarch, file, frame, regno);
+}
+
+static CORE_ADDR
+h8300_saved_pc_after_call (struct frame_info *ignore)
+{
+ return read_memory_unsigned_integer (read_register (E_SP_REGNUM), BINWORD);
+}
+
+static int
+h8300_register_byte (int regno)
+{
+ if (regno < 0 || regno >= E_NUM_REGS)
+ internal_error (__FILE__, __LINE__,
+ "h8300_register_byte: illegal register number %d", regno);
+ else
+ return regno * BINWORD;
+}
+
+static int
+h8300_register_raw_size (int regno)
+{
+ if (regno < 0 || regno >= E_NUM_REGS)
+ internal_error (__FILE__, __LINE__,
+ "h8300_register_raw_size: illegal register number %d",
+ regno);
+ else
+ return BINWORD;
+}
+
+static struct type *
+h8300_register_virtual_type (int regno)
+{
+ if (regno < 0 || regno >= E_NUM_REGS)
+ internal_error (__FILE__, __LINE__,
+ "h8300_register_virtual_type: illegal register number %d",
+ regno);
+ else
+ return h8300hmode ?
+ builtin_type_unsigned_long : builtin_type_unsigned_short;
+}
+
+static void
+h8300_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+{
+ write_register (0, addr);
+}
+
+static int
+h8300_use_struct_convention (int gcc_p, struct type *type)
+{
+ return 1;
+}
+
+static CORE_ADDR
+h8300_extract_struct_value_address (char *regbuf)
+{
+ return extract_address (regbuf + h8300_register_byte (E_ARG0_REGNUM),
+ h8300_register_raw_size (E_ARG0_REGNUM));
+}
+
+const static unsigned char *
+h8300_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+{
+ /*static unsigned char breakpoint[] = { 0x7A, 0xFF };*/ /* ??? */
+ static unsigned char breakpoint[] = { 0x01, 0x80 }; /* Sleep */
+
+ *lenptr = sizeof (breakpoint);
+ return breakpoint;
+}
+
+static void
+h8300_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
+ struct frame_info *frame, const char *args)
+{
+ fprintf_filtered (file, "\
+No floating-point info available for this processor.\n");
+}
+
+static struct gdbarch *
+h8300_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ static LONGEST call_dummy_words[1] = { 0 };
+ struct gdbarch_tdep *tdep = NULL;
+ struct gdbarch *gdbarch;
+
+ arches = gdbarch_list_lookup_by_info (arches, &info);
+ if (arches != NULL)
+ return arches->gdbarch;
+
+#if 0
+ tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
+#endif
+
+ if (info.bfd_arch_info->arch != bfd_arch_h8300)
+ return NULL;
+
+ switch (info.bfd_arch_info->mach)
+ {
+ case bfd_mach_h8300:
+ h8300smode = 0;
+ h8300hmode = 0;
+ break;
+ case bfd_mach_h8300h:
+ h8300smode = 0;
+ h8300hmode = 1;
+ break;
+ case bfd_mach_h8300s:
+ h8300smode = 1;
+ h8300hmode = 1;
+ break;
+ }
+
+ gdbarch = gdbarch_alloc (&info, 0);
+
+ /* 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);
+
+ /*
+ * Basic register fields and methods.
+ */
+
+ set_gdbarch_num_regs (gdbarch, E_NUM_REGS);
+ set_gdbarch_num_pseudo_regs (gdbarch, 0);
+ set_gdbarch_sp_regnum (gdbarch, E_SP_REGNUM);
+ set_gdbarch_fp_regnum (gdbarch, E_FP_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, E_PC_REGNUM);
+ set_gdbarch_register_name (gdbarch, h8300_register_name);
+ set_gdbarch_register_size (gdbarch, BINWORD);
+ set_gdbarch_register_bytes (gdbarch, E_NUM_REGS * BINWORD);
+ set_gdbarch_register_byte (gdbarch, h8300_register_byte);
+ set_gdbarch_register_raw_size (gdbarch, h8300_register_raw_size);
+ set_gdbarch_deprecated_max_register_raw_size (gdbarch, h8300h_reg_size);
+ set_gdbarch_register_virtual_size (gdbarch, h8300_register_raw_size);
+ set_gdbarch_deprecated_max_register_virtual_size (gdbarch, h8300h_reg_size);
+ set_gdbarch_register_virtual_type (gdbarch, h8300_register_virtual_type);
+ set_gdbarch_print_registers_info (gdbarch, h8300_print_registers_info);
+ set_gdbarch_print_float_info (gdbarch, h8300_print_float_info);
+
+ /*
+ * Frame Info
+ */
+ set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, h8300_frame_init_saved_regs);
+ set_gdbarch_deprecated_init_extra_frame_info (gdbarch, h8300_init_extra_frame_info);
+ set_gdbarch_frame_chain (gdbarch, h8300_frame_chain);
+ set_gdbarch_saved_pc_after_call (gdbarch, h8300_saved_pc_after_call);
+ set_gdbarch_deprecated_frame_saved_pc (gdbarch, h8300_frame_saved_pc);
+ set_gdbarch_skip_prologue (gdbarch, h8300_skip_prologue);
+ set_gdbarch_frame_args_address (gdbarch, h8300_frame_args_address);
+ set_gdbarch_frame_locals_address (gdbarch, h8300_frame_locals_address);
+
+ /*
+ * Miscelany
+ */
+ /* Stack grows up. */
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ /* PC stops zero byte after a trap instruction
+ (which means: exactly on trap instruction). */
+ set_gdbarch_decr_pc_after_break (gdbarch, 0);
+ /* This value is almost never non-zero... */
+ set_gdbarch_function_start_offset (gdbarch, 0);
+ /* This value is almost never non-zero... */
+ set_gdbarch_frame_args_skip (gdbarch, 0);
+ /* OK to default this value to 'unknown'. */
+ set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
+ set_gdbarch_frameless_function_invocation (gdbarch,
+ frameless_look_for_prologue);
+
+ /*
+ * Call Dummies
+ *
+ * These values and methods are used when gdb calls a target function. */
+ set_gdbarch_push_return_address (gdbarch, h8300_push_return_address);
+ set_gdbarch_deprecated_extract_return_value (gdbarch, h8300_extract_return_value);
+ set_gdbarch_push_arguments (gdbarch, h8300_push_arguments);
+ set_gdbarch_deprecated_pop_frame (gdbarch, h8300_pop_frame);
+ set_gdbarch_store_struct_return (gdbarch, h8300_store_struct_return);
+ set_gdbarch_deprecated_store_return_value (gdbarch, h8300_store_return_value);
+ set_gdbarch_deprecated_extract_struct_value_address (gdbarch, h8300_extract_struct_value_address);
+ set_gdbarch_use_struct_convention (gdbarch, h8300_use_struct_convention);
+ 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, call_dummy_words);
+ set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
+ set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+ /* set_gdbarch_call_dummy_stack_adjust */
+ set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
+ set_gdbarch_breakpoint_from_pc (gdbarch, h8300_breakpoint_from_pc);
+
+ set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT);
+ set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+ set_gdbarch_ptr_bit (gdbarch, BINWORD * TARGET_CHAR_BIT);
+ set_gdbarch_addr_bit (gdbarch, BINWORD * TARGET_CHAR_BIT);
+
+ /* set_gdbarch_stack_align (gdbarch, SOME_stack_align); */
+ set_gdbarch_extra_stack_alignment_needed (gdbarch, 0);
+ set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+
+ return gdbarch;
+}
+
+void
+_initialize_h8300_tdep (void)
+{
+ tm_print_insn = gdb_print_insn_h8300;
+ register_gdbarch_init (bfd_arch_h8300, h8300_gdbarch_init);