+/* Helper function that returns valid pv_t for an instruction operand:
+ either a register or a constant. */
+
+static pv_t
+arc_pv_get_operand (pv_t *regs, const struct arc_instruction &insn, int operand)
+{
+ if (insn.operands[operand].kind == ARC_OPERAND_KIND_REG)
+ return regs[insn.operands[operand].value];
+ else
+ return pv_constant (arc_insn_get_operand_value (insn, operand));
+}
+
+/* Determine whether the given disassembled instruction may be part of a
+ function prologue. If it is, the information in the frame unwind cache will
+ be updated. */
+
+static bool
+arc_is_in_prologue (struct gdbarch *gdbarch, const struct arc_instruction &insn,
+ pv_t *regs, struct pv_area *stack)
+{
+ /* It might be that currently analyzed address doesn't contain an
+ instruction, hence INSN is not valid. It likely means that address points
+ to a data, non-initialized memory, or middle of a 32-bit instruction. In
+ practice this may happen if GDB connects to a remote target that has
+ non-zeroed memory. GDB would read PC value and would try to analyze
+ prologue, but there is no guarantee that memory contents at the address
+ specified in PC is address is a valid instruction. There is not much that
+ that can be done about that. */
+ if (!insn.valid)
+ return false;
+
+ /* Branch/jump or a predicated instruction. */
+ if (insn.is_control_flow || insn.condition_code != ARC_CC_AL)
+ return false;
+
+ /* Store of some register. May or may not update base address register. */
+ if (insn.insn_class == STORE || insn.insn_class == PUSH)
+ {
+ /* There is definitely at least one operand - register/value being
+ stored. */
+ gdb_assert (insn.operands_count > 0);
+
+ /* Store at some constant address. */
+ if (insn.operands_count > 1
+ && insn.operands[1].kind != ARC_OPERAND_KIND_REG)
+ return false;
+
+ /* Writeback modes:
+ Mode Address used Writeback value
+ --------------------------------------------------
+ No reg + offset no
+ A/AW reg + offset reg + offset
+ AB reg reg + offset
+ AS reg + (offset << scaling) no
+
+ "PUSH reg" is an alias to "ST.AW reg, [SP, -4]" encoding. However
+ 16-bit PUSH_S is a distinct instruction encoding, where offset and
+ base register are implied through opcode. */
+
+ /* Register with base memory address. */
+ int base_reg = arc_insn_get_memory_base_reg (insn);
+
+ /* Address where to write. arc_insn_get_memory_offset returns scaled
+ value for ARC_WRITEBACK_AS. */
+ pv_t addr;
+ if (insn.writeback_mode == ARC_WRITEBACK_AB)
+ addr = regs[base_reg];
+ else
+ addr = pv_add_constant (regs[base_reg],
+ arc_insn_get_memory_offset (insn));
+
+ if (stack->store_would_trash (addr))
+ return false;
+
+ if (insn.data_size_mode != ARC_SCALING_D)
+ {
+ /* Find the value being stored. */
+ pv_t store_value = arc_pv_get_operand (regs, insn, 0);
+
+ /* What is the size of a the stored value? */
+ CORE_ADDR size;
+ if (insn.data_size_mode == ARC_SCALING_B)
+ size = 1;
+ else if (insn.data_size_mode == ARC_SCALING_H)
+ size = 2;
+ else
+ size = ARC_REGISTER_SIZE;
+
+ stack->store (addr, size, store_value);
+ }
+ else
+ {
+ if (insn.operands[0].kind == ARC_OPERAND_KIND_REG)
+ {
+ /* If this is a double store, than write N+1 register as well. */
+ pv_t store_value1 = regs[insn.operands[0].value];
+ pv_t store_value2 = regs[insn.operands[0].value + 1];
+ stack->store (addr, ARC_REGISTER_SIZE, store_value1);
+ stack->store (pv_add_constant (addr, ARC_REGISTER_SIZE),
+ ARC_REGISTER_SIZE, store_value2);
+ }
+ else
+ {
+ pv_t store_value
+ = pv_constant (arc_insn_get_operand_value (insn, 0));
+ stack->store (addr, ARC_REGISTER_SIZE * 2, store_value);
+ }
+ }
+
+ /* Is base register updated? */
+ if (insn.writeback_mode == ARC_WRITEBACK_A
+ || insn.writeback_mode == ARC_WRITEBACK_AB)
+ regs[base_reg] = pv_add_constant (regs[base_reg],
+ arc_insn_get_memory_offset (insn));
+
+ return true;
+ }
+ else if (insn.insn_class == MOVE)
+ {
+ gdb_assert (insn.operands_count == 2);
+
+ /* Destination argument can be "0", so nothing will happen. */
+ if (insn.operands[0].kind == ARC_OPERAND_KIND_REG)
+ {
+ int dst_regnum = insn.operands[0].value;
+ regs[dst_regnum] = arc_pv_get_operand (regs, insn, 1);
+ }
+ return true;
+ }
+ else if (insn.insn_class == SUB)
+ {
+ gdb_assert (insn.operands_count == 3);
+
+ /* SUB 0,b,c. */
+ if (insn.operands[0].kind != ARC_OPERAND_KIND_REG)
+ return true;
+
+ int dst_regnum = insn.operands[0].value;
+ regs[dst_regnum] = pv_subtract (arc_pv_get_operand (regs, insn, 1),
+ arc_pv_get_operand (regs, insn, 2));
+ return true;
+ }
+ else if (insn.insn_class == ENTER)
+ {
+ /* ENTER_S is a prologue-in-instruction - it saves all callee-saved
+ registers according to given arguments thus greatly reducing code
+ size. Which registers will be actually saved depends on arguments.
+
+ ENTER_S {R13-...,FP,BLINK} stores registers in following order:
+
+ new SP ->
+ BLINK
+ R13
+ R14
+ R15
+ ...
+ FP
+ old SP ->
+
+ There are up to three arguments for this opcode, as presented by ARC
+ disassembler:
+ 1) amount of general-purpose registers to be saved - this argument is
+ always present even when it is 0;
+ 2) FP register number (27) if FP has to be stored, otherwise argument
+ is not present;
+ 3) BLINK register number (31) if BLINK has to be stored, otherwise
+ argument is not present. If both FP and BLINK are stored, then FP
+ is present before BLINK in argument list. */
+ gdb_assert (insn.operands_count > 0);
+
+ int regs_saved = arc_insn_get_operand_value (insn, 0);
+
+ bool is_fp_saved;
+ if (insn.operands_count > 1)
+ is_fp_saved = (insn.operands[1].value == ARC_FP_REGNUM);
+ else
+ is_fp_saved = false;
+
+ bool is_blink_saved;
+ if (insn.operands_count > 1)
+ is_blink_saved = (insn.operands[insn.operands_count - 1].value
+ == ARC_BLINK_REGNUM);
+ else
+ is_blink_saved = false;
+
+ /* Amount of bytes to be allocated to store specified registers. */
+ CORE_ADDR st_size = ((regs_saved + is_fp_saved + is_blink_saved)
+ * ARC_REGISTER_SIZE);
+ pv_t new_sp = pv_add_constant (regs[ARC_SP_REGNUM], -st_size);
+
+ /* Assume that if the last register (closest to new SP) can be written,
+ then it is possible to write all of them. */
+ if (stack->store_would_trash (new_sp))
+ return false;
+
+ /* Current store address. */
+ pv_t addr = regs[ARC_SP_REGNUM];
+
+ if (is_fp_saved)
+ {
+ addr = pv_add_constant (addr, -ARC_REGISTER_SIZE);
+ stack->store (addr, ARC_REGISTER_SIZE, regs[ARC_FP_REGNUM]);
+ }
+
+ /* Registers are stored in backward order: from GP (R26) to R13. */
+ for (int i = ARC_R13_REGNUM + regs_saved - 1; i >= ARC_R13_REGNUM; i--)
+ {
+ addr = pv_add_constant (addr, -ARC_REGISTER_SIZE);
+ stack->store (addr, ARC_REGISTER_SIZE, regs[i]);
+ }
+
+ if (is_blink_saved)
+ {
+ addr = pv_add_constant (addr, -ARC_REGISTER_SIZE);
+ stack->store (addr, ARC_REGISTER_SIZE,
+ regs[ARC_BLINK_REGNUM]);
+ }
+
+ gdb_assert (pv_is_identical (addr, new_sp));
+
+ regs[ARC_SP_REGNUM] = new_sp;
+
+ if (is_fp_saved)
+ regs[ARC_FP_REGNUM] = regs[ARC_SP_REGNUM];
+
+ return true;
+ }
+
+ /* Some other architectures, like nds32 or arm, try to continue as far as
+ possible when building a prologue cache (as opposed to when skipping
+ prologue), so that cache will be as full as possible. However current
+ code for ARC doesn't recognize some instructions that may modify SP, like
+ ADD, AND, OR, etc, hence there is no way to guarantee that SP wasn't
+ clobbered by the skipped instruction. Potential existence of extension
+ instruction, which may do anything they want makes this even more complex,
+ so it is just better to halt on a first unrecognized instruction. */
+
+ return false;
+}
+
+/* Copy of gdb_buffered_insn_length_fprintf from disasm.c. */
+
+static int ATTRIBUTE_PRINTF (2, 3)
+arc_fprintf_disasm (void *stream, const char *format, ...)
+{
+ return 0;
+}
+
+struct disassemble_info
+arc_disassemble_info (struct gdbarch *gdbarch)
+{
+ struct disassemble_info di;
+ init_disassemble_info (&di, &null_stream, arc_fprintf_disasm);
+ di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
+ di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+ di.endian = gdbarch_byte_order (gdbarch);
+ di.read_memory_func = [](bfd_vma memaddr, gdb_byte *myaddr,
+ unsigned int len, struct disassemble_info *info)
+ {
+ return target_read_code (memaddr, myaddr, len);
+ };
+ return di;
+}
+
+/* Analyze the prologue and update the corresponding frame cache for the frame
+ unwinder for unwinding frames that doesn't have debug info. In such
+ situation GDB attempts to parse instructions in the prologue to understand
+ where each register is saved.
+
+ If CACHE is not NULL, then it will be filled with information about saved
+ registers.
+
+ There are several variations of prologue which GDB may encounter. "Full"
+ prologue looks like this:
+
+ sub sp,sp,<imm> ; Space for variadic arguments.
+ push blink ; Store return address.
+ push r13 ; Store callee saved registers (up to R26/GP).
+ push r14
+ push fp ; Store frame pointer.
+ mov fp,sp ; Update frame pointer.
+ sub sp,sp,<imm> ; Create space for local vars on the stack.
+
+ Depending on compiler options lots of things may change:
+
+ 1) BLINK is not saved in leaf functions.
+ 2) Frame pointer is not saved and updated if -fomit-frame-pointer is used.
+ 3) 16-bit versions of those instructions may be used.
+ 4) Instead of a sequence of several push'es, compiler may instead prefer to
+ do one subtract on stack pointer and then store registers using normal
+ store, that doesn't update SP. Like this:
+
+
+ sub sp,sp,8 ; Create space for callee-saved registers.
+ st r13,[sp,4] ; Store callee saved registers (up to R26/GP).
+ st r14,[sp,0]
+
+ 5) ENTER_S instruction can encode most of prologue sequence in one
+ instruction (except for those subtracts for variadic arguments and local
+ variables).
+ 6) GCC may use "millicode" functions from libgcc to store callee-saved
+ registers with minimal code-size requirements. This function currently
+ doesn't support this.
+
+ ENTRYPOINT is a function entry point where prologue starts.
+
+ LIMIT_PC is a maximum possible end address of prologue (meaning address
+ of first instruction after the prologue). It might also point to the middle
+ of prologue if execution has been stopped by the breakpoint at this address
+ - in this case debugger should analyze prologue only up to this address,
+ because further instructions haven't been executed yet.
+
+ Returns address of the first instruction after the prologue. */
+
+static CORE_ADDR
+arc_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR entrypoint,
+ const CORE_ADDR limit_pc, struct arc_frame_cache *cache)
+{
+ if (arc_debug)
+ debug_printf ("arc: analyze_prologue (entrypoint=%s, limit_pc=%s)\n",
+ paddress (gdbarch, entrypoint),
+ paddress (gdbarch, limit_pc));
+
+ /* Prologue values. Only core registers can be stored. */
+ pv_t regs[ARC_LAST_CORE_REGNUM + 1];
+ for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
+ regs[i] = pv_register (i, 0);
+ pv_area stack (ARC_SP_REGNUM, gdbarch_addr_bit (gdbarch));
+
+ CORE_ADDR current_prologue_end = entrypoint;
+
+ /* Look at each instruction in the prologue. */
+ while (current_prologue_end < limit_pc)
+ {
+ struct arc_instruction insn;
+ struct disassemble_info di = arc_disassemble_info (gdbarch);
+ arc_insn_decode (current_prologue_end, &di, arc_delayed_print_insn,
+ &insn);
+
+ if (arc_debug >= 2)
+ arc_insn_dump (insn);
+
+ /* If this instruction is in the prologue, fields in the cache will be
+ updated, and the saved registers mask may be updated. */
+ if (!arc_is_in_prologue (gdbarch, insn, regs, &stack))
+ {
+ /* Found an instruction that is not in the prologue. */
+ if (arc_debug)
+ debug_printf ("arc: End of prologue reached at address %s\n",
+ paddress (gdbarch, insn.address));
+ break;
+ }
+
+ current_prologue_end = arc_insn_get_linear_next_pc (insn);
+ }
+
+ if (cache != NULL)
+ {
+ /* Figure out if it is a frame pointer or just a stack pointer. */
+ if (pv_is_register (regs[ARC_FP_REGNUM], ARC_SP_REGNUM))
+ {
+ cache->frame_base_reg = ARC_FP_REGNUM;
+ cache->frame_base_offset = -regs[ARC_FP_REGNUM].k;
+ }
+ else
+ {
+ cache->frame_base_reg = ARC_SP_REGNUM;
+ cache->frame_base_offset = -regs[ARC_SP_REGNUM].k;
+ }
+
+ /* Assign offset from old SP to all saved registers. */
+ for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
+ {
+ CORE_ADDR offset;
+ if (stack.find_reg (gdbarch, i, &offset))
+ cache->saved_regs[i].addr = offset;
+ }
+ }
+
+ return current_prologue_end;
+}
+
+/* Estimated maximum prologue length in bytes. This should include:
+ 1) Store instruction for each callee-saved register (R25 - R13 + 1)
+ 2) Two instructions for FP
+ 3) One for BLINK
+ 4) Three substract instructions for SP (for variadic args, for
+ callee saved regs and for local vars) and assuming that those SUB use
+ long-immediate (hence double length).
+ 5) Stores of arguments registers are considered part of prologue too
+ (R7 - R1 + 1).
+ This is quite an extreme case, because even with -O0 GCC will collapse first
+ two SUBs into one and long immediate values are quite unlikely to appear in
+ this case, but still better to overshoot a bit - prologue analysis will
+ anyway stop at the first instruction that doesn't fit prologue, so this
+ limit will be rarely reached. */
+
+const static int MAX_PROLOGUE_LENGTH
+ = 4 * (ARC_R25_REGNUM - ARC_R13_REGNUM + 1 + 2 + 1 + 6
+ + ARC_LAST_ARG_REGNUM - ARC_FIRST_ARG_REGNUM + 1);
+