+/* Implement the "init" gdbarch method. */
+
+static struct gdbarch *
+arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ const struct target_desc *tdesc;
+ struct tdesc_arch_data *tdesc_data;
+
+ if (arc_debug)
+ debug_printf ("arc: Architecture initialization.\n");
+
+ if (!arc_tdesc_init (info, &tdesc, &tdesc_data))
+ return NULL;
+
+ /* Allocate the ARC-private target-dependent information structure, and the
+ GDB target-independent information structure. */
+ struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
+ tdep->jb_pc = -1; /* No longjmp support by default. */
+ struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
+
+ /* Data types. */
+ set_gdbarch_short_bit (gdbarch, 16);
+ set_gdbarch_int_bit (gdbarch, 32);
+ set_gdbarch_long_bit (gdbarch, 32);
+ set_gdbarch_long_long_bit (gdbarch, 64);
+ set_gdbarch_type_align (gdbarch, arc_type_align);
+ set_gdbarch_float_bit (gdbarch, 32);
+ set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
+ set_gdbarch_double_bit (gdbarch, 64);
+ set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
+ set_gdbarch_ptr_bit (gdbarch, 32);
+ set_gdbarch_addr_bit (gdbarch, 32);
+ set_gdbarch_char_signed (gdbarch, 0);
+
+ set_gdbarch_write_pc (gdbarch, arc_write_pc);
+
+ set_gdbarch_virtual_frame_pointer (gdbarch, arc_virtual_frame_pointer);
+
+ /* tdesc_use_registers expects gdbarch_num_regs to return number of registers
+ parsed by gdbarch_init, and then it will add all of the remaining
+ registers and will increase number of registers. */
+ set_gdbarch_num_regs (gdbarch, ARC_LAST_REGNUM + 1);
+ set_gdbarch_num_pseudo_regs (gdbarch, 0);
+ set_gdbarch_sp_regnum (gdbarch, ARC_SP_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, ARC_PC_REGNUM);
+ set_gdbarch_ps_regnum (gdbarch, ARC_STATUS32_REGNUM);
+ set_gdbarch_fp0_regnum (gdbarch, -1); /* No FPU registers. */
+
+ set_gdbarch_push_dummy_call (gdbarch, arc_push_dummy_call);
+ set_gdbarch_push_dummy_code (gdbarch, arc_push_dummy_code);
+
+ set_gdbarch_cannot_fetch_register (gdbarch, arc_cannot_fetch_register);
+ set_gdbarch_cannot_store_register (gdbarch, arc_cannot_store_register);
+
+ set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+
+ set_gdbarch_return_value (gdbarch, arc_return_value);
+
+ set_gdbarch_skip_prologue (gdbarch, arc_skip_prologue);
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+
+ set_gdbarch_breakpoint_kind_from_pc (gdbarch, arc_breakpoint_kind_from_pc);
+ set_gdbarch_sw_breakpoint_from_kind (gdbarch, arc_sw_breakpoint_from_kind);
+
+ /* On ARC 600 BRK_S instruction advances PC, unlike other ARC cores. */
+ if (!arc_mach_is_arc600 (gdbarch))
+ set_gdbarch_decr_pc_after_break (gdbarch, 0);
+ else
+ set_gdbarch_decr_pc_after_break (gdbarch, 2);
+
+ set_gdbarch_frame_align (gdbarch, arc_frame_align);
+
+ set_gdbarch_print_insn (gdbarch, arc_delayed_print_insn);
+
+ set_gdbarch_cannot_step_breakpoint (gdbarch, 1);
+
+ /* "nonsteppable" watchpoint means that watchpoint triggers before
+ instruction is committed, therefore it is required to remove watchpoint
+ to step though instruction that triggers it. ARC watchpoints trigger
+ only after instruction is committed, thus there is no need to remove
+ them. In fact on ARC watchpoint for memory writes may trigger with more
+ significant delay, like one or two instructions, depending on type of
+ memory where write is performed (CCM or external) and next instruction
+ after the memory write. */
+ set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 0);
+
+ /* This doesn't include possible long-immediate value. */
+ set_gdbarch_max_insn_length (gdbarch, 4);
+
+ /* Frame unwinders and sniffers. */
+ dwarf2_frame_set_init_reg (gdbarch, arc_dwarf2_frame_init_reg);
+ dwarf2_append_unwinders (gdbarch);
+ frame_unwind_append_unwinder (gdbarch, &arc_frame_unwind);
+ frame_base_set_default (gdbarch, &arc_normal_base);
+
+ /* Setup stuff specific to a particular environment (baremetal or Linux).
+ It can override functions set earlier. */
+ gdbarch_init_osabi (info, gdbarch);
+
+ if (tdep->jb_pc >= 0)
+ set_gdbarch_get_longjmp_target (gdbarch, arc_get_longjmp_target);
+
+ /* Disassembler options. Enforce CPU if it was specified in XML target
+ description, otherwise use default method of determining CPU (ELF private
+ header). */
+ if (info.target_desc != NULL)
+ {
+ const struct bfd_arch_info *tdesc_arch
+ = tdesc_architecture (info.target_desc);
+ if (tdesc_arch != NULL)
+ {
+ xfree (arc_disassembler_options);
+ /* FIXME: It is not really good to change disassembler options
+ behind the scene, because that might override options
+ specified by the user. However as of now ARC doesn't support
+ `set disassembler-options' hence this code is the only place
+ where options are changed. It also changes options for all
+ existing gdbarches, which also can be problematic, if
+ arc_gdbarch_init will start reusing existing gdbarch
+ instances. */
+ /* Target description specifies a BFD architecture, which is
+ different from ARC cpu, as accepted by disassembler (and most
+ other ARC tools), because cpu values are much more fine grained -
+ there can be multiple cpu values per single BFD architecture. As
+ a result this code should translate architecture to some cpu
+ value. Since there is no info on exact cpu configuration, it is
+ best to use the most feature-rich CPU, so that disassembler will
+ recognize all instructions available to the specified
+ architecture. */
+ switch (tdesc_arch->mach)
+ {
+ case bfd_mach_arc_arc601:
+ arc_disassembler_options = xstrdup ("cpu=arc601");
+ break;
+ case bfd_mach_arc_arc600:
+ arc_disassembler_options = xstrdup ("cpu=arc600");
+ break;
+ case bfd_mach_arc_arc700:
+ arc_disassembler_options = xstrdup ("cpu=arc700");
+ break;
+ case bfd_mach_arc_arcv2:
+ /* Machine arcv2 has three arches: ARCv2, EM and HS; where ARCv2
+ is treated as EM. */
+ if (arc_arch_is_hs (tdesc_arch))
+ arc_disassembler_options = xstrdup ("cpu=hs38_linux");
+ else
+ arc_disassembler_options = xstrdup ("cpu=em4_fpuda");
+ break;
+ default:
+ arc_disassembler_options = NULL;
+ break;
+ }
+ set_gdbarch_disassembler_options (gdbarch,
+ &arc_disassembler_options);
+ }
+ }
+
+ tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+
+ return gdbarch;
+}
+
+/* Implement the "dump_tdep" gdbarch method. */
+