Merge remote-tracking branch 'origin/riscv' into riscv-compliance

riscv-compliance-dev
Megan Wachs 2018-05-14 07:31:25 -07:00
commit efd7260972
6 changed files with 238 additions and 105 deletions

View File

@ -55,6 +55,6 @@ script:
# 50 changes any case. Most merges won't consist of more than 40 changes,
# so this should work fine most of the time, and be a lot better than not
# checking at all.
- git diff origin/riscv | ./tools/scripts/checkpatch.pl --no-signoff -
- git diff -U20 HEAD~40 | ./tools/scripts/checkpatch.pl --no-signoff -
- ./bootstrap && ./configure --enable-remote-bitbang --enable-jtag_vpi $CONFIGURE_ARGS && make
- file src/$EXECUTABLE

View File

@ -436,6 +436,12 @@ static int slow_fespi_write_buffer(struct flash_bank *bank,
uint32_t ctrl_base = fespi_info->ctrl_base;
uint32_t ii;
if (offset & 0xFF000000) {
LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%x",
offset);
return ERROR_FAIL;
}
/* TODO!!! assert that len < page size */
fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
@ -769,6 +775,12 @@ static void as_add_set_dir(struct algorithm_steps *as, bool dir)
static int steps_add_buffer_write(struct algorithm_steps *as,
const uint8_t *buffer, uint32_t chip_offset, uint32_t len)
{
if (chip_offset & 0xFF000000) {
LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%x",
chip_offset);
return ERROR_FAIL;
}
as_add_tx1(as, SPIFLASH_WRITE_ENABLE);
as_add_txwm_wait(as);
as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);

View File

@ -149,6 +149,8 @@ extern int debug_level;
*/
#define ERROR_FAIL (-4)
#define ERROR_WAIT (-5)
/* ERROR_TIMEOUT is already taken by winerror.h. */
#define ERROR_TIMEOUT_REACHED (-6)
#endif /* OPENOCD_HELPER_LOG_H */

View File

@ -1,4 +1,4 @@
// See LICENSE for license details.
/* See LICENSE for license details. */
#ifndef RISCV_CSR_ENCODING_H
#define RISCV_CSR_ENCODING_H
@ -156,16 +156,16 @@
#define EXT_IO_BASE 0x40000000
#define DRAM_BASE 0x80000000
// page table entry (PTE) fields
#define PTE_V 0x001 // Valid
#define PTE_R 0x002 // Read
#define PTE_W 0x004 // Write
#define PTE_X 0x008 // Execute
#define PTE_U 0x010 // User
#define PTE_G 0x020 // Global
#define PTE_A 0x040 // Accessed
#define PTE_D 0x080 // Dirty
#define PTE_SOFT 0x300 // Reserved for Software
/* page table entry (PTE) fields */
#define PTE_V 0x001 /* Valid */
#define PTE_R 0x002 /* Read */
#define PTE_W 0x004 /* Write */
#define PTE_X 0x008 /* Execute */
#define PTE_U 0x010 /* User */
#define PTE_G 0x020 /* Global */
#define PTE_A 0x040 /* Accessed */
#define PTE_D 0x080 /* Dirty */
#define PTE_SOFT 0x300 /* Reserved for Software */
#define PTE_PPN_SHIFT 10
@ -191,6 +191,7 @@
#ifdef __GNUC__
/*
#define read_csr(reg) ({ unsigned long __tmp; \
asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
__tmp; })
@ -209,6 +210,7 @@
#define clear_csr(reg, bit) ({ unsigned long __tmp; \
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
__tmp; })
*/
#define rdtime() read_csr(time)
#define rdcycle() read_csr(cycle)

View File

@ -57,7 +57,7 @@ static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int a,
static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a);
static int riscv013_dmi_write_u64_bits(struct target *target);
static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf);
static int riscv013_test_compliance(struct target *target);
static int register_read(struct target *target, uint64_t *value, uint32_t number);
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number);
static int register_write_direct(struct target *target, unsigned number,
uint64_t value);
@ -65,6 +65,7 @@ static int read_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer);
static int write_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, const uint8_t *buffer);
static int riscv013_test_compliance(struct target *target);
/**
* Since almost everything can be accomplish by scanning the dbus register, all
@ -144,6 +145,8 @@ typedef struct {
bool was_reset;
/* Targets that are connected to this DM. */
struct list_head target_list;
/* The currently selected hartid on this DM. */
int current_hartid;
} dm013_info_t;
typedef struct {
@ -243,6 +246,7 @@ static dm013_info_t *get_dm(struct target *target)
if (!dm) {
dm = calloc(1, sizeof(dm013_info_t));
dm->abs_chain_position = abs_chain_position;
dm->current_hartid = -1;
INIT_LIST_HEAD(&dm->target_list);
list_add(&dm->list, &dm_list);
}
@ -484,8 +488,8 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
}
static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op,
uint32_t address, uint32_t data_out)
static int dmi_op_timeout(struct target *target, uint32_t *data_in, int dmi_op,
uint32_t address, uint32_t data_out, int timeout_sec)
{
select_dmi(target);
@ -522,14 +526,8 @@ static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op,
LOG_ERROR("failed %s at 0x%x, status=%d", op_name, address, status);
return ERROR_FAIL;
}
if (time(NULL) - start > riscv_command_timeout_sec) {
LOG_ERROR("dmi.op is still busy after %d seconds. The target is "
"either really slow or broken. You could increase the "
"timeout with riscv set_command_timeout_sec.",
riscv_command_timeout_sec);
return ERROR_FAIL;
}
usleep(100000);
if (time(NULL) - start > timeout_sec)
return ERROR_TIMEOUT_REACHED;
}
if (status != DMI_STATUS_SUCCESS) {
@ -552,13 +550,8 @@ static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op,
status);
return ERROR_FAIL;
}
if (time(NULL) - start > riscv_command_timeout_sec) {
LOG_ERROR("dmi.op is still busy after %d seconds. The target is "
"either really slow or broken. You could increase the "
"timeout with riscv set_command_timeout_sec.",
riscv_command_timeout_sec);
return ERROR_FAIL;
}
if (time(NULL) - start > timeout_sec)
return ERROR_TIMEOUT_REACHED;
}
if (status != DMI_STATUS_SUCCESS) {
@ -575,6 +568,21 @@ static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op,
return ERROR_OK;
}
static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op,
uint32_t address, uint32_t data_out)
{
int result = dmi_op_timeout(target, data_in, dmi_op, address, data_out,
riscv_command_timeout_sec);
if (result == ERROR_TIMEOUT_REACHED) {
LOG_ERROR("DMI operation didn't complete in %d seconds. The target is "
"either really slow or broken. You could increase the "
"timeout with riscv set_command_timeout_sec.",
riscv_command_timeout_sec);
return ERROR_FAIL;
}
return result;
}
static int dmi_read(struct target *target, uint32_t *value, uint32_t address)
{
return dmi_op(target, value, DMI_OP_READ, address, 0);
@ -585,11 +593,13 @@ static int dmi_write(struct target *target, uint32_t address, uint32_t value)
return dmi_op(target, NULL, DMI_OP_WRITE, address, value);
}
int dmstatus_read(struct target *target, uint32_t *dmstatus,
bool authenticated)
int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus,
bool authenticated, unsigned timeout_sec)
{
if (dmi_read(target, dmstatus, DMI_DMSTATUS) != ERROR_OK)
return ERROR_FAIL;
int result = dmi_op_timeout(target, dmstatus, DMI_OP_READ, DMI_DMSTATUS, 0,
timeout_sec);
if (result != ERROR_OK)
return result;
if (authenticated && !get_field(*dmstatus, DMI_DMSTATUS_AUTHENTICATED)) {
LOG_ERROR("Debugger is not authenticated to target Debug Module. "
"(dmstatus=0x%x). Use `riscv authdata_read` and "
@ -599,6 +609,13 @@ int dmstatus_read(struct target *target, uint32_t *dmstatus,
return ERROR_OK;
}
int dmstatus_read(struct target *target, uint32_t *dmstatus,
bool authenticated)
{
return dmstatus_read_timeout(target, dmstatus, authenticated,
riscv_command_timeout_sec);
}
static void increase_ac_busy_delay(struct target *target)
{
riscv013_info_t *info = get_info(target);
@ -668,17 +685,12 @@ static int execute_abstract_command(struct target *target, uint32_t command)
LOG_DEBUG("command=0x%x", command);
dmi_write(target, DMI_COMMAND, command);
{
uint32_t abstractcs = 0;
wait_for_idle(target, &abstractcs);
}
uint32_t abstractcs = 0;
wait_for_idle(target, &abstractcs);
uint32_t cs;
if (dmi_read(target, &cs, DMI_ABSTRACTCS) != ERROR_OK)
return ERROR_FAIL;
info->cmderr = get_field(cs, DMI_ABSTRACTCS_CMDERR);
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
if (info->cmderr != 0) {
LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, cs);
LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, abstractcs);
/* Clear the error. */
dmi_write(target, DMI_ABSTRACTCS, set_field(0, DMI_ABSTRACTCS_CMDERR,
info->cmderr));
@ -849,7 +861,7 @@ static int examine_progbuf(struct target *target)
}
uint64_t s0;
if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
struct riscv_program program;
@ -1058,6 +1070,11 @@ static int register_write_direct(struct target *target, unsigned number,
int result = register_write_abstract(target, number, value,
register_size(target, number));
if (result == ERROR_OK && target->reg_cache) {
struct reg *reg = &target->reg_cache->reg_list[number];
buf_set_u64(reg->value, 0, reg->size, value);
reg->valid = true;
}
if (result == ERROR_OK || info->progbufsize + r->impebreak < 2 ||
!riscv_is_halted(target))
return result;
@ -1066,7 +1083,7 @@ static int register_write_direct(struct target *target, unsigned number,
riscv_program_init(&program, target);
uint64_t s0;
if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
@ -1106,6 +1123,11 @@ static int register_write_direct(struct target *target, unsigned number,
int exec_out = riscv_program_exec(&program, target);
/* Don't message on error. Probably the register doesn't exist. */
if (exec_out == ERROR_OK && target->reg_cache) {
struct reg *reg = &target->reg_cache->reg_list[number];
buf_set_u64(reg->value, 0, reg->size, value);
reg->valid = true;
}
/* Restore S0. */
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK)
@ -1114,6 +1136,35 @@ static int register_write_direct(struct target *target, unsigned number,
return exec_out;
}
/** Return the cached value, or read from the target if necessary. */
static int register_read(struct target *target, uint64_t *value, uint32_t number)
{
if (number == GDB_REGNO_ZERO) {
*value = 0;
return ERROR_OK;
}
if (target->reg_cache &&
(number <= GDB_REGNO_XPR31 ||
(number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31))) {
/* Only check the cache for registers that we know won't spontaneously
* change. */
struct reg *reg = &target->reg_cache->reg_list[number];
if (reg && reg->valid) {
*value = buf_get_u64(reg->value, 0, reg->size);
return ERROR_OK;
}
}
int result = register_read_direct(target, value, number);
if (result != ERROR_OK)
return ERROR_FAIL;
if (target->reg_cache) {
struct reg *reg = &target->reg_cache->reg_list[number];
buf_set_u64(reg->value, 0, reg->size, *value);
reg->valid = true;
}
return ERROR_OK;
}
/** Actually read registers from the target right now. */
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number)
{
@ -1133,14 +1184,14 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
bool use_scratch = false;
uint64_t s0;
if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
/* Write program to move data into s0. */
uint64_t mstatus;
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
if (register_read_direct(target, &mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
if (register_read(target, &mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
return ERROR_FAIL;
if ((mstatus & MSTATUS_FS) == 0)
if (register_write_direct(target, GDB_REGNO_MSTATUS,
@ -1383,7 +1434,7 @@ static int examine(struct target *target)
else
r->xlen[i] = 32;
if (register_read_direct(target, &r->misa[i], GDB_REGNO_MISA)) {
if (register_read(target, &r->misa[i], GDB_REGNO_MISA)) {
LOG_ERROR("Fatal: Failed to read MISA from hart %d.", i);
return ERROR_FAIL;
}
@ -1595,53 +1646,45 @@ static int deassert_reset(struct target *target)
index = r->current_hartid;
}
char *operation;
uint32_t expected_field;
uint32_t unexpected_field;
if (target->reset_halt) {
LOG_DEBUG("Waiting for hart %d to halt out of reset.", index);
/* set this temporarily because this read could take the entire
* time the hart takes to come out of reset. */
int saved_riscv_command_timeout_sec = riscv_command_timeout_sec;
riscv_command_timeout_sec = MAX(riscv_reset_timeout_sec, riscv_command_timeout_sec);
do {
if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
return ERROR_FAIL;
if (get_field(dmstatus, DMI_DMSTATUS_ALLHALTED) == 1)
break;
if (time(NULL) - start > riscv_reset_timeout_sec) {
LOG_ERROR("Hart %d didn't halt coming out of reset in %ds; "
"dmstatus=0x%x; "
"Increase the timeout with riscv set_reset_timeout_sec.",
index, riscv_reset_timeout_sec, dmstatus);
return ERROR_FAIL;
}
} while (get_field(dmstatus, DMI_DMSTATUS_ALLHALTED) == 0);
target->state = TARGET_HALTED;
riscv_command_timeout_sec = saved_riscv_command_timeout_sec;
operation = "halt";
expected_field = DMI_DMSTATUS_ALLHALTED;
unexpected_field = DMI_DMSTATUS_ANYRUNNING;
} else {
LOG_DEBUG("Waiting for hart %d to run out of reset.", index);
int saved_riscv_command_timeout_sec = riscv_command_timeout_sec;
riscv_command_timeout_sec = MAX(riscv_reset_timeout_sec, riscv_command_timeout_sec);
while (get_field(dmstatus, DMI_DMSTATUS_ALLRUNNING) == 0) {
if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
return ERROR_FAIL;
if (get_field(dmstatus, DMI_DMSTATUS_ANYHALTED) ||
get_field(dmstatus, DMI_DMSTATUS_ANYUNAVAIL)) {
LOG_ERROR("Unexpected hart %d status during reset. dmstatus=0x%x",
index, dmstatus);
return ERROR_FAIL;
}
if (get_field(dmstatus, DMI_DMSTATUS_ALLRUNNING) == 1)
break;
if (time(NULL) - start > riscv_reset_timeout_sec) {
LOG_ERROR("Hart %d didn't run coming out of reset in %ds; "
"dmstatus=0x%x; "
"Increase the timeout with riscv set_reset_timeout_sec.",
index, riscv_reset_timeout_sec, dmstatus);
return ERROR_FAIL;
}
}
target->state = TARGET_RUNNING;
riscv_command_timeout_sec = saved_riscv_command_timeout_sec;
operation = "run";
expected_field = DMI_DMSTATUS_ALLRUNNING;
unexpected_field = DMI_DMSTATUS_ANYHALTED;
}
LOG_DEBUG("Waiting for hart %d to %s out of reset.", index, operation);
while (1) {
int result = dmstatus_read_timeout(target, &dmstatus, true,
riscv_reset_timeout_sec);
if (result == ERROR_TIMEOUT_REACHED)
LOG_ERROR("Hart %d didn't complete a DMI read coming out of "
"reset in %ds; Increase the timeout with riscv "
"set_reset_timeout_sec.",
index, riscv_reset_timeout_sec);
if (result != ERROR_OK)
return result;
if (get_field(dmstatus, unexpected_field)) {
LOG_ERROR("Unexpected hart %d status during reset. dmstatus=0x%x",
index, dmstatus);
return ERROR_FAIL;
}
if (get_field(dmstatus, expected_field))
break;
if (time(NULL) - start > riscv_reset_timeout_sec) {
LOG_ERROR("Hart %d didn't %s coming out of reset in %ds; "
"dmstatus=0x%x; "
"Increase the timeout with riscv set_reset_timeout_sec.",
index, operation, riscv_reset_timeout_sec, dmstatus);
return ERROR_FAIL;
}
}
target->state = TARGET_HALTED;
if (get_field(dmstatus, DMI_DMSTATUS_ALLHAVERESET)) {
/* Ack reset. */
@ -1805,8 +1848,8 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
LOG_ERROR("Timed out after %ds waiting for sbbusy to go low (sbcs=0x%x). "
"Increase the timeout with riscv set_command_timeout_sec.",
riscv_command_timeout_sec, *sbcs);
return ERROR_FAIL;
}
return ERROR_FAIL;
}
}
@ -1934,6 +1977,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
dmi_write(target, DMI_SBCS, DMI_SBCS_SBBUSYERROR);
next_address = sb_read_address(target);
info->bus_master_read_delay += info->bus_master_read_delay / 10 + 1;
continue;
}
unsigned error = get_field(sbcs, DMI_SBCS_SBERROR);
@ -1970,9 +2014,9 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
* s1 holds the next data value to write
*/
uint64_t s0, s1;
if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
if (register_read_direct(target, &s1, GDB_REGNO_S1) != ERROR_OK)
if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL;
if (execute_fence(target) != ERROR_OK)
@ -2372,6 +2416,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address,
dmi_write(target, DMI_SBCS, DMI_SBCS_SBBUSYERROR);
next_address = sb_read_address(target);
info->bus_master_write_delay += info->bus_master_write_delay / 10 + 1;
continue;
}
unsigned error = get_field(sbcs, DMI_SBCS_SBERROR);
@ -2403,9 +2448,9 @@ static int write_memory_progbuf(struct target *target, target_addr_t address,
int result = ERROR_OK;
uint64_t s0, s1;
if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
if (register_read_direct(target, &s1, GDB_REGNO_S1) != ERROR_OK)
if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL;
/* Write the program (store, increment) */
@ -2629,14 +2674,14 @@ static int riscv013_get_register(struct target *target,
int result = ERROR_OK;
if (rid == GDB_REGNO_PC) {
result = register_read_direct(target, value, GDB_REGNO_DPC);
result = register_read(target, value, GDB_REGNO_DPC);
LOG_DEBUG("read PC from DPC: 0x%016" PRIx64, *value);
} else if (rid == GDB_REGNO_PRIV) {
uint64_t dcsr;
result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
result = register_read(target, &dcsr, GDB_REGNO_DCSR);
*value = get_field(dcsr, CSR_DCSR_PRV);
} else {
result = register_read_direct(target, value, rid);
result = register_read(target, value, rid);
if (result != ERROR_OK)
*value = -1;
}
@ -2666,7 +2711,7 @@ static int riscv013_set_register(struct target *target, int hid, int rid, uint64
}
} else if (rid == GDB_REGNO_PRIV) {
uint64_t dcsr;
register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
register_read(target, &dcsr, GDB_REGNO_DCSR);
dcsr = set_field(dcsr, CSR_DCSR_PRV, value);
return register_write_direct(target, GDB_REGNO_DCSR, dcsr);
} else {
@ -2680,11 +2725,17 @@ static int riscv013_select_current_hart(struct target *target)
{
RISCV_INFO(r);
dm013_info_t *dm = get_dm(target);
if (r->current_hartid == dm->current_hartid)
return ERROR_OK;
uint32_t dmcontrol;
if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
return ERROR_FAIL;
dmcontrol = set_field(dmcontrol, hartsel_mask(target), r->current_hartid);
return dmi_write(target, DMI_DMCONTROL, dmcontrol);
int result = dmi_write(target, DMI_DMCONTROL, dmcontrol);
dm->current_hartid = r->current_hartid;
return result;
}
static int riscv013_halt_current_hart(struct target *target)
@ -2779,7 +2830,7 @@ static bool riscv013_is_halted(struct target *target)
static enum riscv_halt_reason riscv013_halt_reason(struct target *target)
{
riscv_reg_t dcsr;
int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
int result = register_read(target, &dcsr, GDB_REGNO_DCSR);
if (result != ERROR_OK)
return RISCV_HALT_UNKNOWN;
@ -2878,7 +2929,7 @@ static int riscv013_on_step_or_resume(struct target *target, bool step)
/* We want to twiddle some bits in the debug CSR so debugging works. */
riscv_reg_t dcsr;
int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
int result = register_read(target, &dcsr, GDB_REGNO_DCSR);
if (result != ERROR_OK)
return result;
dcsr = set_field(dcsr, CSR_DCSR_STEP, step);

View File

@ -1732,7 +1732,7 @@ int riscv_set_current_hartid(struct target *target, int hartid)
{
RISCV_INFO(r);
if (!r->select_current_hart)
return ERROR_FAIL;
return ERROR_OK;
int previous_hartid = riscv_current_hartid(target);
r->current_hartid = hartid;
@ -2407,6 +2407,72 @@ int riscv_init_registers(struct target *target)
r->exist = riscv_supports_extension(target, riscv_current_hartid(target), 'S') ||
riscv_supports_extension(target, riscv_current_hartid(target), 'N');
break;
case CSR_CYCLEH:
case CSR_TIMEH:
case CSR_INSTRETH:
case CSR_HPMCOUNTER3H:
case CSR_HPMCOUNTER4H:
case CSR_HPMCOUNTER5H:
case CSR_HPMCOUNTER6H:
case CSR_HPMCOUNTER7H:
case CSR_HPMCOUNTER8H:
case CSR_HPMCOUNTER9H:
case CSR_HPMCOUNTER10H:
case CSR_HPMCOUNTER11H:
case CSR_HPMCOUNTER12H:
case CSR_HPMCOUNTER13H:
case CSR_HPMCOUNTER14H:
case CSR_HPMCOUNTER15H:
case CSR_HPMCOUNTER16H:
case CSR_HPMCOUNTER17H:
case CSR_HPMCOUNTER18H:
case CSR_HPMCOUNTER19H:
case CSR_HPMCOUNTER20H:
case CSR_HPMCOUNTER21H:
case CSR_HPMCOUNTER22H:
case CSR_HPMCOUNTER23H:
case CSR_HPMCOUNTER24H:
case CSR_HPMCOUNTER25H:
case CSR_HPMCOUNTER26H:
case CSR_HPMCOUNTER27H:
case CSR_HPMCOUNTER28H:
case CSR_HPMCOUNTER29H:
case CSR_HPMCOUNTER30H:
case CSR_HPMCOUNTER31H:
case CSR_MCYCLEH:
case CSR_MINSTRETH:
case CSR_MHPMCOUNTER3H:
case CSR_MHPMCOUNTER4H:
case CSR_MHPMCOUNTER5H:
case CSR_MHPMCOUNTER6H:
case CSR_MHPMCOUNTER7H:
case CSR_MHPMCOUNTER8H:
case CSR_MHPMCOUNTER9H:
case CSR_MHPMCOUNTER10H:
case CSR_MHPMCOUNTER11H:
case CSR_MHPMCOUNTER12H:
case CSR_MHPMCOUNTER13H:
case CSR_MHPMCOUNTER14H:
case CSR_MHPMCOUNTER15H:
case CSR_MHPMCOUNTER16H:
case CSR_MHPMCOUNTER17H:
case CSR_MHPMCOUNTER18H:
case CSR_MHPMCOUNTER19H:
case CSR_MHPMCOUNTER20H:
case CSR_MHPMCOUNTER21H:
case CSR_MHPMCOUNTER22H:
case CSR_MHPMCOUNTER23H:
case CSR_MHPMCOUNTER24H:
case CSR_MHPMCOUNTER25H:
case CSR_MHPMCOUNTER26H:
case CSR_MHPMCOUNTER27H:
case CSR_MHPMCOUNTER28H:
case CSR_MHPMCOUNTER29H:
case CSR_MHPMCOUNTER30H:
case CSR_MHPMCOUNTER31H:
r->exist = riscv_xlen(target) == 32;
break;
}
if (!r->exist && expose_csr) {