+
+ xfree (memory_image);
+ }
+
+ /* Finally, update the SP register. */
+ regcache_cooked_write_unsigned (regcache, gdbarch_sp_regnum (gdbarch), sp);
+
+ return sp;
+}
+
+/* Implement the "push_dummy_code" gdbarch method.
+
+ We don't actually push any code. We just identify where a breakpoint can
+ be inserted to which we are can return and the resume address where we
+ should be called.
+
+ ARC does not necessarily have an executable stack, so we can't put the
+ return breakpoint there. Instead we put it at the entry point of the
+ function. This means the SP is unchanged.
+
+ SP is a current stack pointer FUNADDR is an address of the function to be
+ called. ARGS is arguments to pass. NARGS is a number of args to pass.
+ VALUE_TYPE is a type of value returned. REAL_PC is a resume address when
+ the function is called. BP_ADDR is an address where breakpoint should be
+ set. Returns the updated stack pointer. */
+
+static CORE_ADDR
+arc_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, CORE_ADDR funaddr,
+ struct value **args, int nargs, struct type *value_type,
+ CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
+ struct regcache *regcache)
+{
+ *real_pc = funaddr;
+ *bp_addr = entry_point_address ();
+ return sp;
+}
+
+/* Implement the "cannot_fetch_register" gdbarch method. */
+
+static int
+arc_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
+{
+ /* Assume that register is readable if it is unknown. */
+ return FALSE;
+}
+
+/* Implement the "cannot_store_register" gdbarch method. */
+
+static int
+arc_cannot_store_register (struct gdbarch *gdbarch, int regnum)
+{
+ /* Assume that register is writable if it is unknown. */
+ switch (regnum)
+ {
+ case ARC_PCL_REGNUM:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/* Get the return value of a function from the registers/memory used to
+ return it, according to the convention used by the ABI - 4-bytes values are
+ in the R0, while 8-byte values are in the R0-R1.
+
+ TODO: This implementation ignores the case of "complex double", where
+ according to ABI, value is returned in the R0-R3 registers.
+
+ TYPE is a returned value's type. VALBUF is a buffer for the returned
+ value. */
+
+static void
+arc_extract_return_value (struct gdbarch *gdbarch, struct type *type,
+ struct regcache *regcache, gdb_byte *valbuf)
+{
+ unsigned int len = TYPE_LENGTH (type);
+
+ if (arc_debug)
+ debug_printf ("arc: extract_return_value\n");
+
+ if (len <= ARC_REGISTER_SIZE)
+ {
+ ULONGEST val;
+
+ /* Get the return value from one register. */
+ regcache_cooked_read_unsigned (regcache, ARC_R0_REGNUM, &val);
+ store_unsigned_integer (valbuf, (int) len,
+ gdbarch_byte_order (gdbarch), val);
+
+ if (arc_debug)
+ debug_printf ("arc: returning 0x%s\n", phex (val, ARC_REGISTER_SIZE));
+ }
+ else if (len <= ARC_REGISTER_SIZE * 2)
+ {
+ ULONGEST low, high;
+
+ /* Get the return value from two registers. */
+ regcache_cooked_read_unsigned (regcache, ARC_R0_REGNUM, &low);
+ regcache_cooked_read_unsigned (regcache, ARC_R1_REGNUM, &high);
+
+ store_unsigned_integer (valbuf, ARC_REGISTER_SIZE,
+ gdbarch_byte_order (gdbarch), low);
+ store_unsigned_integer (valbuf + ARC_REGISTER_SIZE,
+ (int) len - ARC_REGISTER_SIZE,
+ gdbarch_byte_order (gdbarch), high);
+
+ if (arc_debug)
+ debug_printf ("arc: returning 0x%s%s\n",
+ phex (high, ARC_REGISTER_SIZE),
+ phex (low, ARC_REGISTER_SIZE));
+ }
+ else
+ error (_("arc: extract_return_value: type length %u too large"), len);
+}
+
+
+/* Store the return value of a function into the registers/memory used to
+ return it, according to the convention used by the ABI.
+
+ TODO: This implementation ignores the case of "complex double", where
+ according to ABI, value is returned in the R0-R3 registers.
+
+ TYPE is a returned value's type. VALBUF is a buffer with the value to
+ return. */
+
+static void
+arc_store_return_value (struct gdbarch *gdbarch, struct type *type,
+ struct regcache *regcache, const gdb_byte *valbuf)
+{
+ unsigned int len = TYPE_LENGTH (type);
+
+ if (arc_debug)
+ debug_printf ("arc: store_return_value\n");
+
+ if (len <= ARC_REGISTER_SIZE)
+ {
+ ULONGEST val;
+
+ /* Put the return value into one register. */
+ val = extract_unsigned_integer (valbuf, (int) len,
+ gdbarch_byte_order (gdbarch));
+ regcache_cooked_write_unsigned (regcache, ARC_R0_REGNUM, val);
+
+ if (arc_debug)
+ debug_printf ("arc: storing 0x%s\n", phex (val, ARC_REGISTER_SIZE));
+ }
+ else if (len <= ARC_REGISTER_SIZE * 2)
+ {
+ ULONGEST low, high;
+
+ /* Put the return value into two registers. */
+ low = extract_unsigned_integer (valbuf, ARC_REGISTER_SIZE,
+ gdbarch_byte_order (gdbarch));
+ high = extract_unsigned_integer (valbuf + ARC_REGISTER_SIZE,
+ (int) len - ARC_REGISTER_SIZE,
+ gdbarch_byte_order (gdbarch));
+
+ regcache_cooked_write_unsigned (regcache, ARC_R0_REGNUM, low);
+ regcache_cooked_write_unsigned (regcache, ARC_R1_REGNUM, high);
+
+ if (arc_debug)
+ debug_printf ("arc: storing 0x%s%s\n",
+ phex (high, ARC_REGISTER_SIZE),
+ phex (low, ARC_REGISTER_SIZE));
+ }
+ else
+ 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
+arc_return_value (struct gdbarch *gdbarch, struct value *function,
+ struct type *valtype, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+ /* If the return type is a struct, or a union, or would occupy more than two
+ registers, the ABI uses the "struct return convention": the calling
+ function passes a hidden first parameter to the callee (in R0). That
+ parameter is the address at which the value being returned should be
+ stored. Otherwise, the result is returned in registers. */
+ int is_struct_return = (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
+ || TYPE_CODE (valtype) == TYPE_CODE_UNION
+ || TYPE_LENGTH (valtype) > 2 * ARC_REGISTER_SIZE);
+
+ if (arc_debug)
+ debug_printf ("arc: return_value (readbuf = %s, writebuf = %s)\n",
+ host_address_to_string (readbuf),
+ host_address_to_string (writebuf));
+
+ if (writebuf != NULL)
+ {
+ /* Case 1. GDB should not ask us to set a struct return value: it
+ should know the struct return location and write the value there
+ itself. */
+ gdb_assert (!is_struct_return);
+ arc_store_return_value (gdbarch, valtype, regcache, writebuf);
+ }
+ else if (readbuf != NULL)
+ {
+ /* Case 2. GDB should not ask us to get a struct return value: it
+ should know the struct return location and read the value from there
+ itself. */
+ gdb_assert (!is_struct_return);
+ arc_extract_return_value (gdbarch, valtype, regcache, readbuf);
+ }
+
+ return (is_struct_return
+ ? RETURN_VALUE_STRUCT_CONVENTION
+ : RETURN_VALUE_REGISTER_CONVENTION);
+}
+
+/* Return the base address of the frame. For ARC, the base address is the
+ frame pointer. */
+
+static CORE_ADDR
+arc_frame_base_address (struct frame_info *this_frame, void **prologue_cache)
+{
+ return (CORE_ADDR) get_frame_register_unsigned (this_frame, ARC_FP_REGNUM);
+}
+
+/* Implement the "skip_prologue" gdbarch method.
+
+ Skip the prologue for the function at PC. This is done by checking from
+ the line information read from the DWARF, if possible; otherwise, we scan
+ the function prologue to find its end. */
+
+static CORE_ADDR
+arc_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ if (arc_debug)
+ debug_printf ("arc: skip_prologue\n");
+
+ CORE_ADDR func_addr;
+ const char *func_name;
+
+ /* See what the symbol table says. */
+ if (find_pc_partial_function (pc, &func_name, &func_addr, NULL))
+ {
+ /* Found a function. */
+ CORE_ADDR postprologue_pc
+ = skip_prologue_using_sal (gdbarch, func_addr);
+
+ if (postprologue_pc != 0)
+ return std::max (pc, postprologue_pc);