Upstream a whole host of RISC-V changes.

Made no attempt to separate this out into reviewable chunks, since this
is all RISC-V-specific code developed at
https://github.com/riscv/riscv-openocd

Memory sample and repeat read functionality was left out of this change
since it requires some target-independent changes that I'll upstream
some other time.

Change-Id: I92917c86d549c232cbf36ffbfefc93331c05accd
Signed-off-by: Tim Newsome <tim@sifive.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6529
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Tim Newsome 2021-09-01 15:00:46 -07:00 committed by Antonio Borneo
parent f4612e06c6
commit 615709d140
9 changed files with 2617 additions and 1655 deletions

View File

@ -27,23 +27,33 @@ struct riscv_batch *riscv_batch_alloc(struct target *target, size_t scans, size_
out->allocated_scans = scans; out->allocated_scans = scans;
out->idle_count = idle; out->idle_count = idle;
out->data_out = malloc(sizeof(*out->data_out) * (scans) * DMI_SCAN_BUF_SIZE); out->data_out = malloc(sizeof(*out->data_out) * (scans) * DMI_SCAN_BUF_SIZE);
if (!out->data_out) if (!out->data_out) {
LOG_ERROR("Failed to allocate data_out in RISC-V batch.");
goto error1; goto error1;
};
out->data_in = malloc(sizeof(*out->data_in) * (scans) * DMI_SCAN_BUF_SIZE); out->data_in = malloc(sizeof(*out->data_in) * (scans) * DMI_SCAN_BUF_SIZE);
if (!out->data_in) if (!out->data_in) {
LOG_ERROR("Failed to allocate data_in in RISC-V batch.");
goto error2; goto error2;
}
out->fields = malloc(sizeof(*out->fields) * (scans)); out->fields = malloc(sizeof(*out->fields) * (scans));
if (!out->fields) if (!out->fields) {
LOG_ERROR("Failed to allocate fields in RISC-V batch.");
goto error3; goto error3;
}
if (bscan_tunnel_ir_width != 0) { if (bscan_tunnel_ir_width != 0) {
out->bscan_ctxt = malloc(sizeof(*out->bscan_ctxt) * (scans)); out->bscan_ctxt = malloc(sizeof(*out->bscan_ctxt) * (scans));
if (!out->bscan_ctxt) if (!out->bscan_ctxt) {
LOG_ERROR("Failed to allocate bscan_ctxt in RISC-V batch.");
goto error4; goto error4;
}
} }
out->last_scan = RISCV_SCAN_TYPE_INVALID; out->last_scan = RISCV_SCAN_TYPE_INVALID;
out->read_keys = malloc(sizeof(*out->read_keys) * (scans)); out->read_keys = malloc(sizeof(*out->read_keys) * (scans));
if (!out->read_keys) if (!out->read_keys) {
LOG_ERROR("Failed to allocate read_keys in RISC-V batch.");
goto error5; goto error5;
}
return out; return out;
error5: error5:
@ -82,8 +92,6 @@ int riscv_batch_run(struct riscv_batch *batch)
return ERROR_OK; return ERROR_OK;
} }
keep_alive();
riscv_batch_add_nop(batch); riscv_batch_add_nop(batch);
for (size_t i = 0; i < batch->used_scans; ++i) { for (size_t i = 0; i < batch->used_scans; ++i) {
@ -96,11 +104,15 @@ int riscv_batch_run(struct riscv_batch *batch)
jtag_add_runtest(batch->idle_count, TAP_IDLE); jtag_add_runtest(batch->idle_count, TAP_IDLE);
} }
keep_alive();
if (jtag_execute_queue() != ERROR_OK) { if (jtag_execute_queue() != ERROR_OK) {
LOG_ERROR("Unable to execute JTAG queue"); LOG_ERROR("Unable to execute JTAG queue");
return ERROR_FAIL; return ERROR_FAIL;
} }
keep_alive();
if (bscan_tunnel_ir_width != 0) { if (bscan_tunnel_ir_width != 0) {
/* need to right-shift "in" by one bit, because of clock skew between BSCAN TAP and DM TAP */ /* need to right-shift "in" by one bit, because of clock skew between BSCAN TAP and DM TAP */
for (size_t i = 0; i < batch->used_scans; ++i) for (size_t i = 0; i < batch->used_scans; ++i)

File diff suppressed because it is too large Load Diff

View File

@ -17,214 +17,202 @@ static uint32_t bit(uint32_t value, unsigned int b)
return (value >> b) & 1; return (value >> b) & 1;
} }
static uint32_t inst_rd(uint32_t r) __attribute__ ((unused));
static uint32_t inst_rd(uint32_t r)
{
return bits(r, 4, 0) << 7;
}
static uint32_t inst_rs1(uint32_t r) __attribute__ ((unused));
static uint32_t inst_rs1(uint32_t r)
{
return bits(r, 4, 0) << 15;
}
static uint32_t inst_rs2(uint32_t r) __attribute__ ((unused));
static uint32_t inst_rs2(uint32_t r)
{
return bits(r, 4, 0) << 20;
}
static uint32_t imm_i(uint32_t imm) __attribute__ ((unused));
static uint32_t imm_i(uint32_t imm)
{
return bits(imm, 11, 0) << 20;
}
static uint32_t imm_s(uint32_t imm) __attribute__ ((unused));
static uint32_t imm_s(uint32_t imm)
{
return (bits(imm, 4, 0) << 7) | (bits(imm, 11, 5) << 25);
}
static uint32_t imm_b(uint32_t imm) __attribute__ ((unused));
static uint32_t imm_b(uint32_t imm)
{
return (bit(imm, 11) << 7) | (bits(imm, 4, 1) << 8) | (bits(imm, 10, 5) << 25) | (bit(imm, 12) << 31);
}
static uint32_t imm_u(uint32_t imm) __attribute__ ((unused));
static uint32_t imm_u(uint32_t imm)
{
return bits(imm, 31, 12) << 12;
}
static uint32_t imm_j(uint32_t imm) __attribute__ ((unused));
static uint32_t imm_j(uint32_t imm)
{
return (bits(imm, 19, 12) << 12) | (bit(imm, 11) << 20) | (bits(imm, 10, 1) << 21) | (bit(imm, 20) << 31);
}
static uint32_t jal(unsigned int rd, uint32_t imm) __attribute__ ((unused)); static uint32_t jal(unsigned int rd, uint32_t imm) __attribute__ ((unused));
static uint32_t jal(unsigned int rd, uint32_t imm) static uint32_t jal(unsigned int rd, uint32_t imm)
{ {
return (bit(imm, 20) << 31) | return imm_j(imm) | inst_rd(rd) | MATCH_JAL;
(bits(imm, 10, 1) << 21) |
(bit(imm, 11) << 20) |
(bits(imm, 19, 12) << 12) |
(rd << 7) |
MATCH_JAL;
} }
static uint32_t csrsi(unsigned int csr, uint16_t imm) __attribute__ ((unused)); static uint32_t csrsi(unsigned int csr, uint16_t imm) __attribute__ ((unused));
static uint32_t csrsi(unsigned int csr, uint16_t imm) static uint32_t csrsi(unsigned int csr, uint16_t imm)
{ {
return (csr << 20) | return imm_i(csr) | inst_rs1(imm) | MATCH_CSRRSI;
(bits(imm, 4, 0) << 15) |
MATCH_CSRRSI;
} }
static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset) static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 5) << 25) | return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SW;
(src << 20) |
(base << 15) |
(bits(offset, 4, 0) << 7) |
MATCH_SW;
} }
static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset) static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 5) << 25) | return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SD;
(src << 20) |
(base << 15) |
(bits(offset, 4, 0) << 7) |
MATCH_SD;
} }
static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset) static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 5) << 25) | return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SH;
(src << 20) |
(base << 15) |
(bits(offset, 4, 0) << 7) |
MATCH_SH;
} }
static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset) static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 5) << 25) | return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SB;
(src << 20) |
(base << 15) |
(bits(offset, 4, 0) << 7) |
MATCH_SB;
} }
static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset) static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 0) << 20) | return imm_i(offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LD;
(base << 15) |
(bits(rd, 4, 0) << 7) |
MATCH_LD;
} }
static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset) static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 0) << 20) | return imm_i(offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LW;
(base << 15) |
(bits(rd, 4, 0) << 7) |
MATCH_LW;
} }
static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset) static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 0) << 20) | return imm_i(offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LH;
(base << 15) |
(bits(rd, 4, 0) << 7) |
MATCH_LH;
} }
static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset) static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 0) << 20) | return imm_i(offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LB;
(base << 15) |
(bits(rd, 4, 0) << 7) |
MATCH_LB;
} }
static uint32_t csrw(unsigned int source, unsigned int csr) __attribute__ ((unused)); static uint32_t csrw(unsigned int source, unsigned int csr) __attribute__ ((unused));
static uint32_t csrw(unsigned int source, unsigned int csr) static uint32_t csrw(unsigned int source, unsigned int csr)
{ {
return (csr << 20) | (source << 15) | MATCH_CSRRW; return imm_i(csr) | inst_rs1(source) | MATCH_CSRRW;
} }
static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused)); static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused));
static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm) static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm)
{ {
return (bits(imm, 11, 0) << 20) | return imm_i(imm) | inst_rs1(src) | inst_rd(dest) | MATCH_ADDI;
(src << 15) |
(dest << 7) |
MATCH_ADDI;
} }
static uint32_t csrr(unsigned int rd, unsigned int csr) __attribute__ ((unused)); static uint32_t csrr(unsigned int rd, unsigned int csr) __attribute__ ((unused));
static uint32_t csrr(unsigned int rd, unsigned int csr) static uint32_t csrr(unsigned int rd, unsigned int csr)
{ {
return (csr << 20) | (rd << 7) | MATCH_CSRRS; return imm_i(csr) | inst_rd(rd) | MATCH_CSRRS;
} }
static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused)); static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused));
static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr) static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr)
{ {
return (csr << 20) | (rs << 15) | (rd << 7) | MATCH_CSRRS; return imm_i(csr) | inst_rs1(rs) | inst_rd(rd) | MATCH_CSRRS;
} }
static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused)); static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused));
static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr) static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr)
{ {
return (csr << 20) | (rs << 15) | (rd << 7) | MATCH_CSRRW; return imm_i(csr) | inst_rs1(rs) | inst_rd(rd) | MATCH_CSRRW;
} }
static uint32_t csrrci(unsigned int rd, unsigned int zimm, unsigned int csr) __attribute__ ((unused)); static uint32_t csrrci(unsigned int rd, unsigned int zimm, unsigned int csr) __attribute__ ((unused));
static uint32_t csrrci(unsigned int rd, unsigned int zimm, unsigned int csr) static uint32_t csrrci(unsigned int rd, unsigned int zimm, unsigned int csr)
{ {
return (csr << 20) | (zimm << 15) | (rd << 7) | MATCH_CSRRCI; return imm_i(csr) | inst_rs1(zimm) | inst_rd(rd) | MATCH_CSRRCI;
} }
static uint32_t csrrsi(unsigned int rd, unsigned int zimm, unsigned int csr) __attribute__ ((unused)); static uint32_t csrrsi(unsigned int rd, unsigned int zimm, unsigned int csr) __attribute__ ((unused));
static uint32_t csrrsi(unsigned int rd, unsigned int zimm, unsigned int csr) static uint32_t csrrsi(unsigned int rd, unsigned int zimm, unsigned int csr)
{ {
return (csr << 20) | (zimm << 15) | (rd << 7) | MATCH_CSRRSI; return imm_i(csr) | inst_rs1(zimm) | inst_rd(rd) | MATCH_CSRRSI;
} }
static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset) static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 5) << 25) | return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_FSW;
(bits(src, 4, 0) << 20) |
(base << 15) |
(bits(offset, 4, 0) << 7) |
MATCH_FSW;
} }
static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 5) << 25) | return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_FSD;
(bits(src, 4, 0) << 20) |
(base << 15) |
(bits(offset, 4, 0) << 7) |
MATCH_FSD;
} }
static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset) static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 0) << 20) | return imm_i(offset) | inst_rs1(base) | inst_rd(dest) | MATCH_FLW;
(base << 15) |
(bits(dest, 4, 0) << 7) |
MATCH_FLW;
} }
static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused)); static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused));
static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset) static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset)
{ {
return (bits(offset, 11, 0) << 20) | return imm_i(offset) | inst_rs1(base) | inst_rd(dest) | MATCH_FLD;
(base << 15) |
(bits(dest, 4, 0) << 7) |
MATCH_FLD;
} }
static uint32_t fmv_x_w(unsigned dest, unsigned src) __attribute__ ((unused)); static uint32_t fmv_x_w(unsigned dest, unsigned src) __attribute__ ((unused));
static uint32_t fmv_x_w(unsigned dest, unsigned src) static uint32_t fmv_x_w(unsigned dest, unsigned src)
{ {
return src << 15 | return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_X_W;
dest << 7 |
MATCH_FMV_X_W;
} }
static uint32_t fmv_x_d(unsigned dest, unsigned src) __attribute__ ((unused)); static uint32_t fmv_x_d(unsigned dest, unsigned src) __attribute__ ((unused));
static uint32_t fmv_x_d(unsigned dest, unsigned src) static uint32_t fmv_x_d(unsigned dest, unsigned src)
{ {
return src << 15 | return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_X_D;
dest << 7 |
MATCH_FMV_X_D;
} }
static uint32_t fmv_w_x(unsigned dest, unsigned src) __attribute__ ((unused)); static uint32_t fmv_w_x(unsigned dest, unsigned src) __attribute__ ((unused));
static uint32_t fmv_w_x(unsigned dest, unsigned src) static uint32_t fmv_w_x(unsigned dest, unsigned src)
{ {
return src << 15 | return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_W_X;
dest << 7 |
MATCH_FMV_W_X;
} }
static uint32_t fmv_d_x(unsigned dest, unsigned src) __attribute__ ((unused)); static uint32_t fmv_d_x(unsigned dest, unsigned src) __attribute__ ((unused));
static uint32_t fmv_d_x(unsigned dest, unsigned src) static uint32_t fmv_d_x(unsigned dest, unsigned src)
{ {
return src << 15 | return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_D_X;
dest << 7 |
MATCH_FMV_D_X;
} }
static uint32_t ebreak(void) __attribute__ ((unused)); static uint32_t ebreak(void) __attribute__ ((unused));
@ -250,9 +238,7 @@ static uint32_t fence_i(void)
static uint32_t lui(unsigned int dest, uint32_t imm) __attribute__ ((unused)); static uint32_t lui(unsigned int dest, uint32_t imm) __attribute__ ((unused));
static uint32_t lui(unsigned int dest, uint32_t imm) static uint32_t lui(unsigned int dest, uint32_t imm)
{ {
return (bits(imm, 19, 0) << 12) | return imm_u(imm) | inst_rd(dest) | MATCH_LUI;
(dest << 7) |
MATCH_LUI;
} }
/* /*
@ -299,19 +285,13 @@ static uint32_t nop(void)
static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused)); static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused));
static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm) static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm)
{ {
return (bits(imm, 11, 0) << 20) | return imm_i(imm) | inst_rs1(src) | inst_rd(dest) | MATCH_XORI;
(src << 15) |
(dest << 7) |
MATCH_XORI;
} }
static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt) __attribute__ ((unused)); static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt) __attribute__ ((unused));
static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt) static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt)
{ {
return (bits(shamt, 4, 0) << 20) | return inst_rs2(shamt) | inst_rs1(src) | inst_rd(dest) | MATCH_SRLI;
(src << 15) |
(dest << 7) |
MATCH_SRLI;
} }
static uint32_t fence(void) __attribute__((unused)); static uint32_t fence(void) __attribute__((unused));
@ -323,28 +303,25 @@ static uint32_t fence(void)
static uint32_t auipc(unsigned int dest) __attribute__((unused)); static uint32_t auipc(unsigned int dest) __attribute__((unused));
static uint32_t auipc(unsigned int dest) static uint32_t auipc(unsigned int dest)
{ {
return MATCH_AUIPC | (dest << 7); return MATCH_AUIPC | inst_rd(dest);
} }
static uint32_t vsetvli(unsigned int dest, unsigned int src, uint16_t imm) __attribute__((unused)); static uint32_t vsetvli(unsigned int dest, unsigned int src, uint16_t imm) __attribute__((unused));
static uint32_t vsetvli(unsigned int dest, unsigned int src, uint16_t imm) static uint32_t vsetvli(unsigned int dest, unsigned int src, uint16_t imm)
{ {
return (bits(imm, 10, 0) << 20) | return (bits(imm, 10, 0) << 20) | inst_rs1(src) | inst_rd(dest) | MATCH_VSETVLI;
(src << 15) |
(dest << 7) |
MATCH_VSETVLI;
} }
static uint32_t vmv_x_s(unsigned int rd, unsigned int vs2) __attribute__((unused)); static uint32_t vmv_x_s(unsigned int rd, unsigned int vs2) __attribute__((unused));
static uint32_t vmv_x_s(unsigned int rd, unsigned int vs2) static uint32_t vmv_x_s(unsigned int rd, unsigned int vs2)
{ {
return (vs2 << 20) | (rd << 7) | MATCH_VMV_X_S; return inst_rs2(vs2) | inst_rd(rd) | MATCH_VMV_X_S;
} }
static uint32_t vmv_s_x(unsigned int vd, unsigned int vs2) __attribute__((unused)); static uint32_t vmv_s_x(unsigned int vd, unsigned int vs2) __attribute__((unused));
static uint32_t vmv_s_x(unsigned int vd, unsigned int rs1) static uint32_t vmv_s_x(unsigned int vd, unsigned int rs1)
{ {
return (rs1 << 15) | (vd << 7) | MATCH_VMV_S_X; return inst_rs1(rs1) | inst_rd(vd) | MATCH_VMV_S_X;
} }
static uint32_t vslide1down_vx(unsigned int vd, unsigned int vs2, static uint32_t vslide1down_vx(unsigned int vd, unsigned int vs2,
@ -352,6 +329,6 @@ static uint32_t vslide1down_vx(unsigned int vd, unsigned int vs2,
static uint32_t vslide1down_vx(unsigned int vd, unsigned int vs2, static uint32_t vslide1down_vx(unsigned int vd, unsigned int vs2,
unsigned int rs1, unsigned int vm) unsigned int rs1, unsigned int vm)
{ {
return (vm << 25) | (vs2 << 20) | (rs1 << 15) | (vd << 7) | return ((vm & 1) << 25) | inst_rs2(vs2) | inst_rs1(rs1) | inst_rd(vd) | MATCH_VSLIDE1DOWN_VX;
MATCH_VSLIDE1DOWN_VX;
} }

View File

@ -40,20 +40,10 @@ int riscv_program_write(struct riscv_program *program);
* program to execute. That's OK, just make sure this eventually terminates. * program to execute. That's OK, just make sure this eventually terminates.
* */ * */
int riscv_program_exec(struct riscv_program *p, struct target *t); int riscv_program_exec(struct riscv_program *p, struct target *t);
int riscv_program_load(struct riscv_program *p, struct target *t);
/* Clears a program, removing all the state associated with it. */
int riscv_program_clear(struct riscv_program *p, struct target *t);
/* A lower level interface, you shouldn't use this unless you have a reason. */ /* A lower level interface, you shouldn't use this unless you have a reason. */
int riscv_program_insert(struct riscv_program *p, riscv_insn_t i); int riscv_program_insert(struct riscv_program *p, riscv_insn_t i);
/* There is hardware support for saving at least one register. This register
* doesn't need to be saved/restored the usual way, which is useful during
* early initialization when we can't save/restore arbitrary registerrs to host
* memory. */
int riscv_program_save_to_dscratch(struct riscv_program *p, enum gdb_regno to_save);
/* Helpers to assemble various instructions. Return 0 on success. These might /* Helpers to assemble various instructions. Return 0 on success. These might
* assemble into a multi-instruction sequence that overwrites some other * assemble into a multi-instruction sequence that overwrites some other
* register, but those will be properly saved and restored. */ * register, but those will be properly saved and restored. */

View File

@ -152,6 +152,9 @@ typedef enum slot {
#define DMINFO_AUTHTYPE (3<<2) #define DMINFO_AUTHTYPE (3<<2)
#define DMINFO_VERSION 3 #define DMINFO_VERSION 3
#define DMAUTHDATA0 0x12
#define DMAUTHDATA1 0x13
/*** Info about the core being debugged. ***/ /*** Info about the core being debugged. ***/
#define DBUS_ADDRESS_UNKNOWN 0xffff #define DBUS_ADDRESS_UNKNOWN 0xffff
@ -216,8 +219,7 @@ typedef struct {
static int poll_target(struct target *target, bool announce); static int poll_target(struct target *target, bool announce);
static int riscv011_poll(struct target *target); static int riscv011_poll(struct target *target);
static int get_register(struct target *target, riscv_reg_t *value, int hartid, static int get_register(struct target *target, riscv_reg_t *value, int regid);
int regid);
/*** Utility functions. ***/ /*** Utility functions. ***/
@ -226,6 +228,8 @@ static int get_register(struct target *target, riscv_reg_t *value, int hartid,
static riscv011_info_t *get_info(const struct target *target) static riscv011_info_t *get_info(const struct target *target)
{ {
riscv_info_t *info = (riscv_info_t *) target->arch_info; riscv_info_t *info = (riscv_info_t *) target->arch_info;
assert(info);
assert(info->version_specific);
return (riscv011_info_t *) info->version_specific; return (riscv011_info_t *) info->version_specific;
} }
@ -1230,7 +1234,7 @@ static int update_mstatus_actual(struct target *target)
/* Force reading the register. In that process mstatus_actual will be /* Force reading the register. In that process mstatus_actual will be
* updated. */ * updated. */
riscv_reg_t mstatus; riscv_reg_t mstatus;
return get_register(target, &mstatus, 0, GDB_REGNO_MSTATUS); return get_register(target, &mstatus, GDB_REGNO_MSTATUS);
} }
/*** OpenOCD target functions. ***/ /*** OpenOCD target functions. ***/
@ -1334,10 +1338,8 @@ static int register_write(struct target *target, unsigned int number,
return ERROR_OK; return ERROR_OK;
} }
static int get_register(struct target *target, riscv_reg_t *value, int hartid, static int get_register(struct target *target, riscv_reg_t *value, int regid)
int regid)
{ {
assert(hartid == 0);
riscv011_info_t *info = get_info(target); riscv011_info_t *info = get_info(target);
maybe_write_tselect(target); maybe_write_tselect(target);
@ -1380,10 +1382,8 @@ static int get_register(struct target *target, riscv_reg_t *value, int hartid,
return ERROR_OK; return ERROR_OK;
} }
static int set_register(struct target *target, int hartid, int regid, static int set_register(struct target *target, int regid, uint64_t value)
uint64_t value)
{ {
assert(hartid == 0);
return register_write(target, regid, value); return register_write(target, regid, value);
} }
@ -1523,7 +1523,7 @@ static int examine(struct target *target)
} }
/* Pretend this is a 32-bit system until we have found out the true value. */ /* Pretend this is a 32-bit system until we have found out the true value. */
r->xlen[0] = 32; r->xlen = 32;
/* Figure out XLEN, and test writing all of Debug RAM while we're at it. */ /* Figure out XLEN, and test writing all of Debug RAM while we're at it. */
cache_set32(target, 0, xori(S1, ZERO, -1)); cache_set32(target, 0, xori(S1, ZERO, -1));
@ -1551,11 +1551,11 @@ static int examine(struct target *target)
uint32_t word1 = cache_get32(target, 1); uint32_t word1 = cache_get32(target, 1);
riscv_info_t *generic_info = (riscv_info_t *) target->arch_info; riscv_info_t *generic_info = (riscv_info_t *) target->arch_info;
if (word0 == 1 && word1 == 0) { if (word0 == 1 && word1 == 0) {
generic_info->xlen[0] = 32; generic_info->xlen = 32;
} else if (word0 == 0xffffffff && word1 == 3) { } else if (word0 == 0xffffffff && word1 == 3) {
generic_info->xlen[0] = 64; generic_info->xlen = 64;
} else if (word0 == 0xffffffff && word1 == 0xffffffff) { } else if (word0 == 0xffffffff && word1 == 0xffffffff) {
generic_info->xlen[0] = 128; generic_info->xlen = 128;
} else { } else {
uint32_t exception = cache_get32(target, info->dramsize-1); uint32_t exception = cache_get32(target, info->dramsize-1);
LOG_ERROR("Failed to discover xlen; word0=0x%x, word1=0x%x, exception=0x%x", LOG_ERROR("Failed to discover xlen; word0=0x%x, word1=0x%x, exception=0x%x",
@ -1565,11 +1565,11 @@ static int examine(struct target *target)
} }
LOG_DEBUG("Discovered XLEN is %d", riscv_xlen(target)); LOG_DEBUG("Discovered XLEN is %d", riscv_xlen(target));
if (read_remote_csr(target, &r->misa[0], CSR_MISA) != ERROR_OK) { if (read_remote_csr(target, &r->misa, CSR_MISA) != ERROR_OK) {
const unsigned old_csr_misa = 0xf10; const unsigned old_csr_misa = 0xf10;
LOG_WARNING("Failed to read misa at 0x%x; trying 0x%x.", CSR_MISA, LOG_WARNING("Failed to read misa at 0x%x; trying 0x%x.", CSR_MISA,
old_csr_misa); old_csr_misa);
if (read_remote_csr(target, &r->misa[0], old_csr_misa) != ERROR_OK) { if (read_remote_csr(target, &r->misa, old_csr_misa) != ERROR_OK) {
/* Maybe this is an old core that still has $misa at the old /* Maybe this is an old core that still has $misa at the old
* address. */ * address. */
LOG_ERROR("Failed to read misa at 0x%x.", old_csr_misa); LOG_ERROR("Failed to read misa at 0x%x.", old_csr_misa);
@ -1591,7 +1591,7 @@ static int examine(struct target *target)
for (size_t i = 0; i < 32; ++i) for (size_t i = 0; i < 32; ++i)
reg_cache_set(target, i, -1); reg_cache_set(target, i, -1);
LOG_INFO("Examined RISCV core; XLEN=%d, misa=0x%" PRIx64, LOG_INFO("Examined RISCV core; XLEN=%d, misa=0x%" PRIx64,
riscv_xlen(target), r->misa[0]); riscv_xlen(target), r->misa);
return ERROR_OK; return ERROR_OK;
} }
@ -2294,21 +2294,95 @@ static int arch_state(struct target *target)
return ERROR_OK; return ERROR_OK;
} }
COMMAND_HELPER(riscv011_print_info, struct target *target)
{
/* Abstract description. */
riscv_print_info_line(CMD, "target", "memory.read_while_running8", 0);
riscv_print_info_line(CMD, "target", "memory.write_while_running8", 0);
riscv_print_info_line(CMD, "target", "memory.read_while_running16", 0);
riscv_print_info_line(CMD, "target", "memory.write_while_running16", 0);
riscv_print_info_line(CMD, "target", "memory.read_while_running32", 0);
riscv_print_info_line(CMD, "target", "memory.write_while_running32", 0);
riscv_print_info_line(CMD, "target", "memory.read_while_running64", 0);
riscv_print_info_line(CMD, "target", "memory.write_while_running64", 0);
riscv_print_info_line(CMD, "target", "memory.read_while_running128", 0);
riscv_print_info_line(CMD, "target", "memory.write_while_running128", 0);
uint32_t dminfo = dbus_read(target, DMINFO);
riscv_print_info_line(CMD, "dm", "authenticated", get_field(dminfo, DMINFO_AUTHENTICATED));
return 0;
}
static int wait_for_authbusy(struct target *target)
{
time_t start = time(NULL);
while (1) {
uint32_t dminfo = dbus_read(target, DMINFO);
if (!get_field(dminfo, DMINFO_AUTHBUSY))
break;
if (time(NULL) - start > riscv_command_timeout_sec) {
LOG_ERROR("Timed out after %ds waiting for authbusy to go low (dminfo=0x%x). "
"Increase the timeout with riscv set_command_timeout_sec.",
riscv_command_timeout_sec,
dminfo);
return ERROR_FAIL;
}
}
return ERROR_OK;
}
static int riscv011_authdata_read(struct target *target, uint32_t *value, unsigned int index)
{
if (index > 1) {
LOG_ERROR("Spec 0.11 only has a two authdata registers.");
return ERROR_FAIL;
}
if (wait_for_authbusy(target) != ERROR_OK)
return ERROR_FAIL;
uint16_t authdata_address = index ? DMAUTHDATA1 : DMAUTHDATA0;
*value = dbus_read(target, authdata_address);
return ERROR_OK;
}
static int riscv011_authdata_write(struct target *target, uint32_t value, unsigned int index)
{
if (index > 1) {
LOG_ERROR("Spec 0.11 only has a two authdata registers.");
return ERROR_FAIL;
}
if (wait_for_authbusy(target) != ERROR_OK)
return ERROR_FAIL;
uint16_t authdata_address = index ? DMAUTHDATA1 : DMAUTHDATA0;
dbus_write(target, authdata_address, value);
return ERROR_OK;
}
static int init_target(struct command_context *cmd_ctx, static int init_target(struct command_context *cmd_ctx,
struct target *target) struct target *target)
{ {
LOG_DEBUG("init"); LOG_DEBUG("init");
riscv_info_t *generic_info = (riscv_info_t *)target->arch_info; RISCV_INFO(generic_info);
generic_info->get_register = get_register; generic_info->get_register = get_register;
generic_info->set_register = set_register; generic_info->set_register = set_register;
generic_info->read_memory = read_memory; generic_info->read_memory = read_memory;
generic_info->authdata_read = &riscv011_authdata_read;
generic_info->authdata_write = &riscv011_authdata_write;
generic_info->print_info = &riscv011_print_info;
generic_info->version_specific = calloc(1, sizeof(riscv011_info_t)); generic_info->version_specific = calloc(1, sizeof(riscv011_info_t));
if (!generic_info->version_specific) if (!generic_info->version_specific)
return ERROR_FAIL; return ERROR_FAIL;
/* Assume 32-bit until we discover the real value in examine(). */ /* Assume 32-bit until we discover the real value in examine(). */
generic_info->xlen[0] = 32; generic_info->xlen = 32;
riscv_init_registers(target); riscv_init_registers(target);
return ERROR_OK; return ERROR_OK;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,7 @@ struct riscv_program;
#include "gdb_regs.h" #include "gdb_regs.h"
#include "jtag/jtag.h" #include "jtag/jtag.h"
#include "target/register.h" #include "target/register.h"
#include <helper/command.h>
/* The register cache is statically allocated. */ /* The register cache is statically allocated. */
#define RISCV_MAX_HARTS 1024 #define RISCV_MAX_HARTS 1024
@ -26,6 +27,8 @@ struct riscv_program;
# define PG_MAX_LEVEL 4 # define PG_MAX_LEVEL 4
#define RISCV_NUM_MEM_ACCESS_METHODS 3
extern struct target_type riscv011_target; extern struct target_type riscv011_target;
extern struct target_type riscv013_target; extern struct target_type riscv013_target;
@ -36,6 +39,13 @@ typedef uint64_t riscv_reg_t;
typedef uint32_t riscv_insn_t; typedef uint32_t riscv_insn_t;
typedef uint64_t riscv_addr_t; typedef uint64_t riscv_addr_t;
enum riscv_mem_access_method {
RISCV_MEM_ACCESS_UNSPECIFIED,
RISCV_MEM_ACCESS_PROGBUF,
RISCV_MEM_ACCESS_SYSBUS,
RISCV_MEM_ACCESS_ABSTRACT
};
enum riscv_halt_reason { enum riscv_halt_reason {
RISCV_HALT_INTERRUPT, RISCV_HALT_INTERRUPT,
RISCV_HALT_BREAKPOINT, RISCV_HALT_BREAKPOINT,
@ -51,15 +61,35 @@ typedef struct {
unsigned custom_number; unsigned custom_number;
} riscv_reg_info_t; } riscv_reg_info_t;
#define RISCV_SAMPLE_BUF_TIMESTAMP_BEFORE 0x80
#define RISCV_SAMPLE_BUF_TIMESTAMP_AFTER 0x81
struct riscv_sample_buf {
uint8_t *buf;
unsigned int used;
unsigned int size;
};
typedef struct {
bool enabled;
struct {
bool enabled;
target_addr_t address;
uint32_t size_bytes;
} bucket[16];
} riscv_sample_config_t;
typedef struct {
struct list_head list;
uint16_t low, high;
char *name;
} range_list_t;
typedef struct { typedef struct {
unsigned dtm_version; unsigned dtm_version;
struct command_context *cmd_ctx; struct command_context *cmd_ctx;
void *version_specific; void *version_specific;
/* The hart that the RTOS thinks is currently being debugged. */
int rtos_hartid;
/* The hart that is currently being debugged. Note that this is /* The hart that is currently being debugged. Note that this is
* different than the hartid that the RTOS is expected to use. This * different than the hartid that the RTOS is expected to use. This
* one will change all the time, it's more of a global argument to * one will change all the time, it's more of a global argument to
@ -76,13 +106,13 @@ typedef struct {
char *reg_names; char *reg_names;
/* It's possible that each core has a different supported ISA set. */ /* It's possible that each core has a different supported ISA set. */
int xlen[RISCV_MAX_HARTS]; int xlen;
riscv_reg_t misa[RISCV_MAX_HARTS]; riscv_reg_t misa;
/* Cached value of vlenb. 0 if vlenb is not readable for some reason. */ /* Cached value of vlenb. 0 if vlenb is not readable for some reason. */
unsigned vlenb[RISCV_MAX_HARTS]; unsigned int vlenb;
/* The number of triggers per hart. */ /* The number of triggers per hart. */
unsigned trigger_count[RISCV_MAX_HARTS]; unsigned int trigger_count;
/* For each physical trigger, contains -1 if the hwbp is available, or the /* For each physical trigger, contains -1 if the hwbp is available, or the
* unique_id of the breakpoint/watchpoint that is using it. * unique_id of the breakpoint/watchpoint that is using it.
@ -91,7 +121,7 @@ typedef struct {
int trigger_unique_id[RISCV_MAX_HWBPS]; int trigger_unique_id[RISCV_MAX_HWBPS];
/* The number of entries in the debug buffer. */ /* The number of entries in the debug buffer. */
int debug_buffer_size[RISCV_MAX_HARTS]; int debug_buffer_size;
/* This avoids invalidating the register cache too often. */ /* This avoids invalidating the register cache too often. */
bool registers_initialized; bool registers_initialized;
@ -112,10 +142,8 @@ typedef struct {
/* Helper functions that target the various RISC-V debug spec /* Helper functions that target the various RISC-V debug spec
* implementations. */ * implementations. */
int (*get_register)(struct target *target, int (*get_register)(struct target *target, riscv_reg_t *value, int regid);
riscv_reg_t *value, int hid, int rid); int (*set_register)(struct target *target, int regid, uint64_t value);
int (*set_register)(struct target *target, int hartid, int regid,
uint64_t value);
int (*get_register_buf)(struct target *target, uint8_t *buf, int regno); int (*get_register_buf)(struct target *target, uint8_t *buf, int regno);
int (*set_register_buf)(struct target *target, int regno, int (*set_register_buf)(struct target *target, int regno,
const uint8_t *buf); const uint8_t *buf);
@ -143,8 +171,8 @@ typedef struct {
void (*fill_dmi_read_u64)(struct target *target, char *buf, int a); void (*fill_dmi_read_u64)(struct target *target, char *buf, int a);
void (*fill_dmi_nop_u64)(struct target *target, char *buf); void (*fill_dmi_nop_u64)(struct target *target, char *buf);
int (*authdata_read)(struct target *target, uint32_t *value); int (*authdata_read)(struct target *target, uint32_t *value, unsigned int index);
int (*authdata_write)(struct target *target, uint32_t value); int (*authdata_write)(struct target *target, uint32_t value, unsigned int index);
int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address); int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address);
int (*dmi_write)(struct target *target, uint32_t address, uint32_t value); int (*dmi_write)(struct target *target, uint32_t address, uint32_t value);
@ -152,7 +180,10 @@ typedef struct {
int (*test_sba_config_reg)(struct target *target, target_addr_t legal_address, int (*test_sba_config_reg)(struct target *target, target_addr_t legal_address,
uint32_t num_words, target_addr_t illegal_address, bool run_sbbusyerror_test); uint32_t num_words, target_addr_t illegal_address, bool run_sbbusyerror_test);
int (*test_compliance)(struct target *target); int (*sample_memory)(struct target *target,
struct riscv_sample_buf *buf,
riscv_sample_config_t *config,
int64_t until_ms);
int (*read_memory)(struct target *target, target_addr_t address, int (*read_memory)(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment); uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment);
@ -161,6 +192,8 @@ typedef struct {
int (*hart_count)(struct target *target); int (*hart_count)(struct target *target);
unsigned (*data_bits)(struct target *target); unsigned (*data_bits)(struct target *target);
COMMAND_HELPER((*print_info), struct target *target);
/* Storage for vector register types. */ /* Storage for vector register types. */
struct reg_data_type_vector vector_uint8; struct reg_data_type_vector vector_uint8;
struct reg_data_type_vector vector_uint16; struct reg_data_type_vector vector_uint16;
@ -179,8 +212,31 @@ typedef struct {
/* Set when trigger registers are changed by the user. This indicates we eed /* Set when trigger registers are changed by the user. This indicates we eed
* to beware that we may hit a trigger that we didn't realize had been set. */ * to beware that we may hit a trigger that we didn't realize had been set. */
bool manual_hwbp_set; bool manual_hwbp_set;
/* Memory access methods to use, ordered by priority, highest to lowest. */
int mem_access_methods[RISCV_NUM_MEM_ACCESS_METHODS];
/* Different memory regions may need different methods but single configuration is applied
* for all. Following flags are used to warn only once about failing memory access method. */
bool mem_access_progbuf_warn;
bool mem_access_sysbus_warn;
bool mem_access_abstract_warn;
/* In addition to the ones in the standard spec, we'll also expose additional
* CSRs in this list. */
struct list_head expose_csr;
/* Same, but for custom registers.
* Custom registers are for non-standard extensions and use abstract register numbers
* from range 0xc000 ... 0xffff. */
struct list_head expose_custom;
riscv_sample_config_t sample_config;
struct riscv_sample_buf sample_buf;
} riscv_info_t; } riscv_info_t;
COMMAND_HELPER(riscv_print_info_line, const char *section, const char *key,
unsigned int value);
typedef struct { typedef struct {
uint8_t tunneled_dr_width; uint8_t tunneled_dr_width;
struct scan_field tunneled_dr[4]; struct scan_field tunneled_dr[4];
@ -205,8 +261,6 @@ extern int riscv_command_timeout_sec;
/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/ /* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
extern int riscv_reset_timeout_sec; extern int riscv_reset_timeout_sec;
extern bool riscv_prefer_sba;
extern bool riscv_enable_virtual; extern bool riscv_enable_virtual;
extern bool riscv_ebreakm; extern bool riscv_ebreakm;
extern bool riscv_ebreaks; extern bool riscv_ebreaks;
@ -216,7 +270,10 @@ extern bool riscv_ebreaku;
* that provides that. */ * that provides that. */
static inline riscv_info_t *riscv_info(const struct target *target) __attribute__((unused)); static inline riscv_info_t *riscv_info(const struct target *target) __attribute__((unused));
static inline riscv_info_t *riscv_info(const struct target *target) static inline riscv_info_t *riscv_info(const struct target *target)
{ return target->arch_info; } {
assert(target->arch_info);
return target->arch_info;
}
#define RISCV_INFO(R) riscv_info_t *R = riscv_info(target); #define RISCV_INFO(R) riscv_info_t *R = riscv_info(target);
extern uint8_t ir_dtmcontrol[4]; extern uint8_t ir_dtmcontrol[4];
@ -269,44 +326,30 @@ void riscv_info_init(struct target *target, riscv_info_t *r);
* then the only hart. */ * then the only hart. */
int riscv_step_rtos_hart(struct target *target); int riscv_step_rtos_hart(struct target *target);
bool riscv_supports_extension(struct target *target, int hartid, char letter); bool riscv_supports_extension(struct target *target, char letter);
/* Returns XLEN for the given (or current) hart. */ /* Returns XLEN for the given (or current) hart. */
unsigned riscv_xlen(const struct target *target); unsigned riscv_xlen(const struct target *target);
int riscv_xlen_of_hart(const struct target *target, int hartid); int riscv_xlen_of_hart(const struct target *target);
bool riscv_rtos_enabled(const struct target *target);
/* Sets the current hart, which is the hart that will actually be used when /* Sets the current hart, which is the hart that will actually be used when
* issuing debug commands. */ * issuing debug commands. */
int riscv_set_current_hartid(struct target *target, int hartid); int riscv_set_current_hartid(struct target *target, int hartid);
int riscv_select_current_hart(struct target *target);
int riscv_current_hartid(const struct target *target); int riscv_current_hartid(const struct target *target);
/*** Support functions for the RISC-V 'RTOS', which provides multihart support /*** Support functions for the RISC-V 'RTOS', which provides multihart support
* without requiring multiple targets. */ * without requiring multiple targets. */
/* When using the RTOS to debug, this selects the hart that is currently being
* debugged. This doesn't propagate to the hardware. */
void riscv_set_all_rtos_harts(struct target *target);
void riscv_set_rtos_hartid(struct target *target, int hartid);
/* Lists the number of harts in the system, which are assumed to be /* Lists the number of harts in the system, which are assumed to be
* consecutive and start with mhartid=0. */ * consecutive and start with mhartid=0. */
int riscv_count_harts(struct target *target); int riscv_count_harts(struct target *target);
/* Returns TRUE if the target has the given register on the given hart. */
bool riscv_has_register(struct target *target, int hartid, int regid);
/** Set register, updating the cache. */ /** Set register, updating the cache. */
int riscv_set_register(struct target *target, enum gdb_regno i, riscv_reg_t v); int riscv_set_register(struct target *target, enum gdb_regno i, riscv_reg_t v);
/** Set register, updating the cache. */
int riscv_set_register_on_hart(struct target *target, int hid, enum gdb_regno rid, uint64_t v);
/** Get register, from the cache if it's in there. */ /** Get register, from the cache if it's in there. */
int riscv_get_register(struct target *target, riscv_reg_t *value, int riscv_get_register(struct target *target, riscv_reg_t *value,
enum gdb_regno r); enum gdb_regno r);
/** Get register, from the cache if it's in there. */
int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value,
int hartid, enum gdb_regno regid);
/* Checks the state of the current hart -- "is_halted" checks the actual /* Checks the state of the current hart -- "is_halted" checks the actual
* on-device register. */ * on-device register. */
@ -329,9 +372,6 @@ int riscv_dmi_write_u64_bits(struct target *target);
/* Invalidates the register cache. */ /* Invalidates the register cache. */
void riscv_invalidate_register_cache(struct target *target); void riscv_invalidate_register_cache(struct target *target);
/* Returns TRUE when a hart is enabled in this target. */
bool riscv_hart_enabled(struct target *target, int hartid);
int riscv_enumerate_triggers(struct target *target); int riscv_enumerate_triggers(struct target *target);
int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint); int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint);
@ -356,4 +396,7 @@ semihosting_result_t riscv_semihosting(struct target *target, int *retval);
void riscv_add_bscan_tunneled_scan(struct target *target, struct scan_field *field, void riscv_add_bscan_tunneled_scan(struct target *target, struct scan_field *field,
riscv_bscan_tunneled_scan_context_t *ctxt); riscv_bscan_tunneled_scan_context_t *ctxt);
int riscv_read_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer);
int riscv_write_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer);
#endif #endif

View File

@ -85,12 +85,15 @@ semihosting_result_t riscv_semihosting(struct target *target, int *retval)
if (result != ERROR_OK) if (result != ERROR_OK)
return SEMI_ERROR; return SEMI_ERROR;
uint8_t tmp[12]; uint8_t tmp_buf[12];
/* Read the current instruction, including the bracketing */ /* Read three uncompressed instructions: The previous, the current one (pointed to by PC) and the next one */
*retval = target_read_memory(target, pc - 4, 2, 6, tmp); for (int i = 0; i < 3; i++) {
if (*retval != ERROR_OK) /* Instruction memories may not support arbitrary read size. Use any size that will work. */
return SEMI_ERROR; *retval = riscv_read_by_any_size(target, (pc - 4) + 4 * i, 4, tmp_buf + 4 * i);
if (*retval != ERROR_OK)
return SEMI_ERROR;
}
/* /*
* The instructions that trigger a semihosting call, * The instructions that trigger a semihosting call,
@ -100,9 +103,9 @@ semihosting_result_t riscv_semihosting(struct target *target, int *retval)
* 00100073 ebreak * 00100073 ebreak
* 40705013 srai zero,zero,0x7 * 40705013 srai zero,zero,0x7
*/ */
uint32_t pre = target_buffer_get_u32(target, tmp); uint32_t pre = target_buffer_get_u32(target, tmp_buf);
uint32_t ebreak = target_buffer_get_u32(target, tmp + 4); uint32_t ebreak = target_buffer_get_u32(target, tmp_buf + 4);
uint32_t post = target_buffer_get_u32(target, tmp + 8); uint32_t post = target_buffer_get_u32(target, tmp_buf + 8);
LOG_DEBUG("check %08x %08x %08x from 0x%" PRIx64 "-4", pre, ebreak, post, pc); LOG_DEBUG("check %08x %08x %08x from 0x%" PRIx64 "-4", pre, ebreak, post, pc);
if (pre != 0x01f01013 || ebreak != 0x00100073 || post != 0x40705013) { if (pre != 0x01f01013 || ebreak != 0x00100073 || post != 0x40705013) {