/* Target-dependent code for the RISC-V architecture, for GDB.
- Copyright (C) 2018-2021 Free Software Foundation, Inc.
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
This file is part of GDB.
static const char *riscv_feature_name_virtual = "org.gnu.gdb.riscv.virtual";
static const char *riscv_feature_name_vector = "org.gnu.gdb.riscv.vector";
+/* The current set of options to be passed to the disassembler. */
+static char *riscv_disassembler_options;
+
/* Cached information about a frame. */
struct riscv_unwind_cache
for (auto ® : m_registers)
{
int csr_num = reg.regnum - RISCV_FIRST_CSR_REGNUM;
- const char *alias = xstrprintf ("csr%d", csr_num);
- reg.names.push_back (alias);
+ gdb::unique_xmalloc_ptr<char> alias = xstrprintf ("csr%d", csr_num);
+ reg.names.push_back (alias.release ());
}
}
};
int
riscv_isa_xlen (struct gdbarch *gdbarch)
{
- return gdbarch_tdep (gdbarch)->isa_features.xlen;
+ riscv_gdbarch_tdep *tdep = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ return tdep->isa_features.xlen;
}
/* See riscv-tdep.h. */
int
riscv_abi_xlen (struct gdbarch *gdbarch)
{
- return gdbarch_tdep (gdbarch)->abi_features.xlen;
+ riscv_gdbarch_tdep *tdep = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ return tdep->abi_features.xlen;
}
/* See riscv-tdep.h. */
int
riscv_isa_flen (struct gdbarch *gdbarch)
{
- return gdbarch_tdep (gdbarch)->isa_features.flen;
+ riscv_gdbarch_tdep *tdep = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ return tdep->isa_features.flen;
}
/* See riscv-tdep.h. */
int
riscv_abi_flen (struct gdbarch *gdbarch)
{
- return gdbarch_tdep (gdbarch)->abi_features.flen;
+ riscv_gdbarch_tdep *tdep = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ return tdep->abi_features.flen;
}
/* See riscv-tdep.h. */
bool
riscv_abi_embedded (struct gdbarch *gdbarch)
{
- return gdbarch_tdep (gdbarch)->abi_features.embedded;
+ riscv_gdbarch_tdep *tdep = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ return tdep->abi_features.embedded;
}
/* Return true if the target for GDBARCH has floating point hardware. */
static bool
riscv_has_fp_abi (struct gdbarch *gdbarch)
{
- return gdbarch_tdep (gdbarch)->abi_features.flen > 0;
+ riscv_gdbarch_tdep *tdep = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ return tdep->abi_features.flen > 0;
}
/* Return true if REGNO is a floating pointer register. */
case 4:
return ebreak;
default:
- gdb_assert_not_reached (_("unhandled breakpoint kind"));
+ gdb_assert_not_reached ("unhandled breakpoint kind");
}
}
will show up in 'info register all'. Unless, we identify the
duplicate copies of these registers (in riscv_tdesc_unknown_reg) and
then hide the registers here by giving them no name. */
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ riscv_gdbarch_tdep *tdep = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (tdep->duplicate_fflags_regnum == regnum)
return NULL;
if (tdep->duplicate_frm_regnum == regnum)
static struct type *
riscv_fpreg_d_type (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ riscv_gdbarch_tdep *tdep = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (tdep->riscv_fpreg_d_type == nullptr)
{
&& regtype->field (2).type ()->code () == TYPE_CODE_FLT))
{
struct value_print_options opts;
- const gdb_byte *valaddr = value_contents_for_printing (val);
+ const gdb_byte *valaddr = value_contents_for_printing (val).data ();
enum bfd_endian byte_order = type_byte_order (regtype);
get_user_print_options (&opts);
static bool
riscv_is_unknown_csr (struct gdbarch *gdbarch, int regnum)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ riscv_gdbarch_tdep *tdep = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
return (regnum >= tdep->unknown_csrs_first_regnum
&& regnum < (tdep->unknown_csrs_first_regnum
+ tdep->unknown_csrs_count));
SW,
LD,
LW,
+ MV,
/* These are needed for software breakpoint support. */
JAL,
JALR,
else if (xlen != 4 && is_c_sdsp_insn (ival))
decode_css_type_insn (SD, ival, EXTRACT_CSSTYPE_SDSP_IMM (ival));
/* C_JR and C_MV have the same opcode. If RS2 is 0, then this is a C_JR.
- So must try to match C_JR first as it ahs more bits in mask. */
+ So must try to match C_JR first as it has more bits in mask. */
else if (is_c_jr_insn (ival))
decode_cr_type_insn (JALR, ival);
+ else if (is_c_mv_insn (ival))
+ decode_cr_type_insn (MV, ival);
else if (is_c_j_insn (ival))
decode_cj_type_insn (JAL, ival);
else if (is_c_beqz_insn (ival))
}
else if (insn.opcode () == riscv_insn::ADD)
{
- /* Handle: addi REG1, REG2, IMM */
+ /* Handle: add REG1, REG2, REG3 */
gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS);
gdb_assert (insn.rs1 () < RISCV_NUM_INTEGER_REGS);
gdb_assert (insn.rs2 () < RISCV_NUM_INTEGER_REGS);
insn.imm_signed ()),
(insn.opcode () == riscv_insn::LW ? 4 : 8));
}
+ else if (insn.opcode () == riscv_insn::MV)
+ {
+ /* Handle: c.mv RD, RS2 */
+ gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS);
+ gdb_assert (insn.rs2 () < RISCV_NUM_INTEGER_REGS);
+ gdb_assert (insn.rs2 () > 0);
+ regs[insn.rd ()] = regs[insn.rs2 ()];
+ }
else
{
end_prologue_addr = cur_pc;
for (i = 0; i < count; ++i)
{
- if (TYPE_FIELD_LOC_KIND (type, i) != FIELD_LOC_KIND_BITPOS)
+ if (type->field (i).loc_kind () != FIELD_LOC_KIND_BITPOS)
continue;
struct type *field_type = type->field (i).type ();
field_type = check_typedef (field_type);
int field_offset
- = offset + TYPE_FIELD_BITPOS (type, i) / TARGET_CHAR_BIT;
+ = offset + type->field (i).loc_bitpos () / TARGET_CHAR_BIT;
switch (field_type->code ())
{
case TYPE_CODE_RANGE:
case TYPE_CODE_ENUM:
case TYPE_CODE_PTR:
+ case TYPE_CODE_FIXED_POINT:
if (ainfo->length <= cinfo->xlen)
{
ainfo->type = builtin_type (gdbarch)->builtin_long;
break;
default:
- gdb_assert_not_reached (_("unknown argument location type"));
+ gdb_assert_not_reached ("unknown argument location type");
}
}
if (info->type != arg_type)
arg_value = value_cast (info->type, arg_value);
- info->contents = value_contents (arg_value);
+ info->contents = value_contents (arg_value).data ();
}
/* Adjust the stack pointer and align it. */
break;
default:
- gdb_assert_not_reached (_("unknown argument location type"));
+ gdb_assert_not_reached ("unknown argument location type");
}
if (second_arg_length > 0)
buffers of sufficient size. */
if (writebuf != nullptr)
{
- struct value *arg_val = value_from_contents (arg_type, writebuf);
- abi_val = value_cast (info.type, arg_val);
- writebuf = value_contents_raw (abi_val);
+ struct value *arg_val;
+
+ if (is_fixed_point_type (arg_type))
+ {
+ /* Convert the argument to the type used to pass
+ the return value, but being careful to preserve
+ the fact that the value needs to be returned
+ unscaled. */
+ gdb_mpz unscaled;
+
+ unscaled.read (gdb::make_array_view (writebuf,
+ TYPE_LENGTH (arg_type)),
+ type_byte_order (arg_type),
+ arg_type->is_unsigned ());
+ abi_val = allocate_value (info.type);
+ unscaled.write (value_contents_raw (abi_val),
+ type_byte_order (info.type),
+ info.type->is_unsigned ());
+ }
+ else
+ {
+ arg_val = value_from_contents (arg_type, writebuf);
+ abi_val = value_cast (info.type, arg_val);
+ }
+ writebuf = value_contents_raw (abi_val).data ();
}
else
{
abi_val = allocate_value (info.type);
old_readbuf = readbuf;
- readbuf = value_contents_raw (abi_val);
+ readbuf = value_contents_raw (abi_val).data ();
}
arg_len = TYPE_LENGTH (info.type);
comment at the head of this block for more details. */
if (readbuf != nullptr)
{
- struct value *arg_val = value_cast (arg_type, abi_val);
- memcpy (old_readbuf, value_contents_raw (arg_val),
+ struct value *arg_val;
+
+ if (is_fixed_point_type (arg_type))
+ {
+ /* Convert abi_val to the actual return type, but
+ being careful to preserve the fact that abi_val
+ is unscaled. */
+ gdb_mpz unscaled;
+
+ unscaled.read (value_contents (abi_val),
+ type_byte_order (info.type),
+ info.type->is_unsigned ());
+ arg_val = allocate_value (arg_type);
+ unscaled.write (value_contents_raw (arg_val),
+ type_byte_order (arg_type),
+ arg_type->is_unsigned ());
+ }
+ else
+ arg_val = value_cast (arg_type, abi_val);
+ memcpy (old_readbuf, value_contents_raw (arg_val).data (),
TYPE_LENGTH (arg_type));
}
}
record their register numbers here. */
if (strcmp (tdesc_feature_name (feature), riscv_freg_feature.name ()) == 0)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ riscv_gdbarch_tdep *tdep = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int *regnum_ptr = nullptr;
if (strcmp (reg_name, "fflags") == 0)
about register groups in riscv_register_reggroup_p. */
if (strcmp (tdesc_feature_name (feature), riscv_csr_feature.name ()) == 0)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ riscv_gdbarch_tdep *tdep = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (tdep->unknown_csrs_first_regnum == -1)
tdep->unknown_csrs_first_regnum = possible_regnum;
gdb_assert (tdep->unknown_csrs_first_regnum
struct gdbarch_list *arches)
{
struct gdbarch *gdbarch;
- struct gdbarch_tdep *tdep;
struct riscv_gdbarch_features features;
const struct target_desc *tdesc = info.target_desc;
/* Check that the feature set of the ARCHES matches the feature set
we are looking for. If it doesn't then we can't reuse this
gdbarch. */
- struct gdbarch_tdep *other_tdep = gdbarch_tdep (arches->gdbarch);
+ riscv_gdbarch_tdep *other_tdep
+ = (riscv_gdbarch_tdep *) gdbarch_tdep (arches->gdbarch);
if (other_tdep->isa_features != features
|| other_tdep->abi_features != abi_features)
return arches->gdbarch;
/* None found, so create a new architecture from the information provided. */
- tdep = new (struct gdbarch_tdep);
+ riscv_gdbarch_tdep *tdep = new riscv_gdbarch_tdep;
gdbarch = gdbarch_alloc (&info, tdep);
tdep->isa_features = features;
tdep->abi_features = abi_features;
set_gdbarch_gcc_target_options (gdbarch, riscv_gcc_target_options);
set_gdbarch_gnu_triplet_regexp (gdbarch, riscv_gnu_triplet_regexp);
+ /* Disassembler options support. */
+ set_gdbarch_valid_disassembler_options (gdbarch,
+ disassembler_options_riscv ());
+ set_gdbarch_disassembler_options (gdbarch, &riscv_disassembler_options);
+
/* Hook in OS ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
riscv_next_pc (struct regcache *regcache, CORE_ADDR pc)
{
struct gdbarch *gdbarch = regcache->arch ();
- const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ const riscv_gdbarch_tdep *tdep
+ = (riscv_gdbarch_tdep *) gdbarch_tdep (gdbarch);
struct riscv_insn insn;
CORE_ADDR next_pc;
/* Add root prefix command for all "set debug riscv" and "show debug
riscv" commands. */
- add_basic_prefix_cmd ("riscv", no_class,
- _("RISC-V specific debug commands."),
- &setdebugriscvcmdlist, 0,
- &setdebuglist);
-
- add_show_prefix_cmd ("riscv", no_class,
- _("RISC-V specific debug commands."),
- &showdebugriscvcmdlist, 0,
- &showdebuglist);
+ add_setshow_prefix_cmd ("riscv", no_class,
+ _("RISC-V specific debug commands."),
+ _("RISC-V specific debug commands."),
+ &setdebugriscvcmdlist, &showdebugriscvcmdlist,
+ &setdebuglist, &showdebuglist);
add_setshow_zuinteger_cmd ("breakpoints", class_maintenance,
&riscv_debug_breakpoints, _("\
&setdebugriscvcmdlist, &showdebugriscvcmdlist);
/* Add root prefix command for all "set riscv" and "show riscv" commands. */
- add_basic_prefix_cmd ("riscv", no_class,
- _("RISC-V specific commands."),
- &setriscvcmdlist, 0, &setlist);
-
- add_show_prefix_cmd ("riscv", no_class,
- _("RISC-V specific commands."),
- &showriscvcmdlist, 0, &showlist);
+ add_setshow_prefix_cmd ("riscv", no_class,
+ _("RISC-V specific commands."),
+ _("RISC-V specific commands."),
+ &setriscvcmdlist, &showriscvcmdlist,
+ &setlist, &showlist);
use_compressed_breakpoints = AUTO_BOOLEAN_AUTO;