error (_("arc_store_return_value: type length too large."));
}
+/* Implement the "get_longjmp_target" gdbarch method. */
+
+static int
+arc_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
+{
+ if (arc_debug)
+ debug_printf ("arc: get_longjmp_target\n");
+
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int pc_offset = tdep->jb_pc * ARC_REGISTER_SIZE;
+ gdb_byte buf[ARC_REGISTER_SIZE];
+ CORE_ADDR jb_addr = get_frame_register_unsigned (frame, ARC_FIRST_ARG_REGNUM);
+
+ if (target_read_memory (jb_addr + pc_offset, buf, ARC_REGISTER_SIZE))
+ return 0; /* Failed to read from memory. */
+
+ *pc = extract_unsigned_integer (buf, ARC_REGISTER_SIZE,
+ gdbarch_byte_order (gdbarch));
+ return 1;
+}
+
/* Implement the "return_value" gdbarch method. */
static enum return_value_convention
static const gdb_byte arc_brk_be[] = { 0x25, 0x6f, 0x00, 0x3f };
static const gdb_byte arc_brk_le[] = { 0x6f, 0x25, 0x3f, 0x00 };
-/* Implement the "breakpoint_from_pc" gdbarch method.
-
- For ARC ELF, breakpoint uses the 16-bit BRK_S instruction, which is 0x7fff
+/* For ARC ELF, breakpoint uses the 16-bit BRK_S instruction, which is 0x7fff
(little endian) or 0xff7f (big endian). We used to insert BRK_S even
instead of 32-bit instructions, which works mostly ok, unless breakpoint is
inserted into delay slot instruction. In this case if branch is taken
NB: Baremetal GDB uses BRK[_S], while user-space GDB uses TRAP_S. BRK[_S]
is much better because it doesn't commit unlike TRAP_S, so it can be set in
delay slots; however it cannot be used in user-mode, hence usage of TRAP_S
- in GDB for user-space.
+ in GDB for user-space. */
- PCPTR is a pointer to the PC where we want to place a breakpoint. LENPTR
- is a number of bytes used by the breakpoint. Returns the byte sequence of
- a breakpoint instruction. */
+/* Implement the "breakpoint_kind_from_pc" gdbarch method. */
-static const gdb_byte *
-arc_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
- int *lenptr)
+static int
+arc_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
{
size_t length_with_limm = gdb_insn_length (gdbarch, *pcptr);
bytes for 32-bit instructions. */
if ((length_with_limm == 4 || length_with_limm == 8)
&& !arc_mach_is_arc600 (gdbarch))
+ return sizeof (arc_brk_le);
+ else
+ return sizeof (arc_brk_s_le);
+}
+
+/* Implement the "sw_breakpoint_from_kind" gdbarch method. */
+
+static const gdb_byte *
+arc_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+ *size = kind;
+
+ if (kind == sizeof (arc_brk_le))
{
- *lenptr = sizeof (arc_brk_le);
return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
? arc_brk_be
: arc_brk_le);
}
else
{
- *lenptr = sizeof (arc_brk_s_le);
return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
? arc_brk_s_be
: arc_brk_s_le);
if (!arc_tdesc_init (info, &tdesc, &tdesc_data))
return NULL;
- struct gdbarch *gdbarch = gdbarch_alloc (&info, 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_skip_prologue (gdbarch, arc_skip_prologue);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- set_gdbarch_breakpoint_from_pc (gdbarch, arc_breakpoint_from_pc);
+ 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))
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);
+
tdesc_use_registers (gdbarch, tdesc, tdesc_data);
return gdbarch;
static void
arc_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
{
- /* Empty for now. */
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ fprintf_unfiltered (file, "arc_dump_tdep: jb_pc = %i\n", tdep->jb_pc);
}
/* Suppress warning from -Wmissing-prototypes. */