aboutsummaryrefslogtreecommitdiff
path: root/gdb/riscv-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/riscv-tdep.c')
-rw-r--r--gdb/riscv-tdep.c92
1 files changed, 71 insertions, 21 deletions
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index a735c09..680176b 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -4163,6 +4163,20 @@ riscv_gnu_triplet_regexp (struct gdbarch *gdbarch)
return "riscv(32|64)?";
}
+/* Implement the "print_insn" gdbarch method. */
+
+static int
+riscv_print_insn (bfd_vma addr, struct disassemble_info *info)
+{
+ /* Initialize the BFD section to enable ISA string detection depending on the
+ object in scope. */
+ struct obj_section *s = find_pc_section (addr);
+ if (s != nullptr)
+ info->section = s->the_bfd_section;
+
+ return default_print_insn (addr, info);
+}
+
/* Implementation of `gdbarch_stap_is_single_operand', as defined in
gdbarch.h. */
@@ -4429,6 +4443,9 @@ riscv_gdbarch_init (struct gdbarch_info info,
disassembler_options_riscv ());
set_gdbarch_disassembler_options (gdbarch, &riscv_disassembler_options);
+ /* Disassembler print_insn. */
+ set_gdbarch_print_insn (gdbarch, riscv_print_insn);
+
/* SystemTap Support. */
set_gdbarch_stap_is_single_operand (gdbarch, riscv_stap_is_single_operand);
set_gdbarch_stap_register_indirection_prefixes
@@ -4778,9 +4795,7 @@ riscv_supply_regset (const struct regset *regset,
}
}
-void _initialize_riscv_tdep ();
-void
-_initialize_riscv_tdep ()
+INIT_GDB_FILE (riscv_tdep)
{
riscv_init_reggroups ();
@@ -4884,7 +4899,7 @@ try_read (struct regcache *regcache, int regnum, ULONGEST &addr)
if (regcache->raw_read (regnum, &addr)
!= register_status::REG_VALID)
{
- warning (_("Can not read at address %lx"), addr);
+ warning (_("Can not read at address %s"), hex_string (addr));
return false;
}
return true;
@@ -4909,6 +4924,8 @@ public:
/* Corner cases. */
ECALL,
EBREAK,
+ SRET,
+ MRET,
};
private:
@@ -4993,6 +5010,14 @@ private:
return (ival >> OP_SH_CSR) & OP_MASK_CSR;
}
+ /* Set any record type. Always returns true. */
+ bool
+ set_record_type (record_type type) noexcept
+ {
+ m_record_type = type;
+ return true;
+ }
+
/* Set ordinary record type. Always returns true. */
bool
set_ordinary_record_type () noexcept
@@ -5051,7 +5076,8 @@ private:
return (is_beq_insn (ival) || is_bne_insn (ival) || is_blt_insn (ival)
|| is_bge_insn (ival) || is_bltu_insn (ival) || is_bgeu_insn (ival)
|| is_fence_insn (ival) || is_pause_insn (ival)
- || is_fence_i_insn (ival));
+ || is_fence_i_insn (ival) || is_wfi_insn (ival)
+ || is_sfence_vma_insn (ival));
}
/* Returns true if instruction is classified. */
@@ -5158,7 +5184,7 @@ private:
{
return (is_csrrw_insn (ival) || is_csrrs_insn (ival) || is_csrrc_insn (ival)
|| is_csrrwi_insn (ival) || is_csrrsi_insn (ival)
- || is_csrrc_insn (ival));
+ || is_csrrci_insn (ival));
}
/* Returns true if instruction is classified. This function can set
@@ -5255,14 +5281,26 @@ private:
if (is_ecall_insn (ival))
{
- m_record_type = record_type::ECALL;
- return true;
+ return set_record_type (record_type::ECALL);
}
if (is_ebreak_insn (ival))
{
- m_record_type = record_type::EBREAK;
- return true;
+ return set_record_type (record_type::EBREAK);
+ }
+
+ if (is_sret_insn (ival))
+ {
+ return (!save_reg (RISCV_CSR_SSTATUS_REGNUM)
+ || !save_reg (RISCV_CSR_MEPC_REGNUM)
+ || set_record_type (record_type::SRET));
+ }
+
+ if (is_mret_insn (ival))
+ {
+ return (!save_reg (RISCV_CSR_MSTATUS_REGNUM)
+ || !save_reg (RISCV_CSR_MEPC_REGNUM)
+ || set_record_type (record_type::MRET));
}
if (try_save_pc (ival) || try_save_pc_rd (ival) || try_save_pc_fprd (ival)
@@ -5270,8 +5308,8 @@ private:
|| try_save_pc_rd_mem (ival, regcache))
return !has_error ();
- warning (_("Currently this instruction with len 4(%lx) is unsupported"),
- ival);
+ warning (_("Currently this instruction with len 4(%s) is unsupported"),
+ hex_string (ival));
return false;
}
@@ -5356,8 +5394,7 @@ private:
if (is_c_ebreak_insn (ival))
{
- m_record_type = record_type::EBREAK;
- return true;
+ return set_record_type (record_type::EBREAK);
}
if (is_c_jalr_insn (ival))
@@ -5380,8 +5417,8 @@ private:
|| !save_mem (addr + offset, 4) || set_ordinary_record_type ());
}
- warning (_("Currently this instruction with len 2(%lx) is unsupported"),
- ival);
+ warning (_("Currently this instruction with len 2(%s) is unsupported"),
+ hex_string (ival));
return false;
}
@@ -5399,8 +5436,20 @@ public:
gdb_assert (regcache != nullptr);
int m_length = 0;
+ ULONGEST ival = 0;
m_xlen = riscv_isa_xlen (gdbarch);
- ULONGEST ival = riscv_insn::fetch_instruction (gdbarch, addr, &m_length);
+
+ /* Since fetch_instruction can throw an exception,
+ it must be wrapped in a try-catch block. */
+ try
+ {
+ ival = riscv_insn::fetch_instruction (gdbarch, addr, &m_length);
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ warning ("%s", ex.what ());
+ return false;
+ }
if (!save_reg (RISCV_PC_REGNUM))
return false;
@@ -5415,7 +5464,8 @@ public:
are not defined yet, so just ignore it. */
gdb_assert (m_length > 0 && m_length % 2 == 0);
- warning (_("Can not record unknown instruction (opcode = %lx)"), ival);
+ warning (_("Can not record unknown instruction (opcode = %s)"),
+ hex_string (ival));
return false;
}
@@ -5493,6 +5543,9 @@ riscv_record_insn_details (struct gdbarch *gdbarch, struct regcache *regcache,
switch (insn.get_record_type ())
{
case riscv_recorded_insn::record_type::ORDINARY:
+ case riscv_recorded_insn::record_type::EBREAK:
+ case riscv_recorded_insn::record_type::SRET:
+ case riscv_recorded_insn::record_type::MRET:
break;
case riscv_recorded_insn::record_type::ECALL:
@@ -5508,9 +5561,6 @@ riscv_record_insn_details (struct gdbarch *gdbarch, struct regcache *regcache,
return tdep->riscv_syscall_record (regcache, reg_val);
}
- case riscv_recorded_insn::record_type::EBREAK:
- break;
-
default:
return -1;
}