Regenerate autogenerated debug_defines.{c,h} files from current
riscv-debug-spec, sync remaining RISC-V target files with the
RISC-V fork.
This is based on the work of (in alphabetic order):
Aleksey Lotosh <lotosh@gmail.com>
Alexander Rumyantsev <cetygamer@gmail.com>
Anastasiya Chernikova <anastasiya.chernikova@syntacore.com>
Anatoly Parshintsev <114445139+aap-sc@users.noreply.github.com>
Bernhard Rosenkränzer <bero@baylibre.com>
bluew <bluewww@users.noreply.github.com>
Carsten Gosvig <40368726+cgsfv@users.noreply.github.com>
cgsfv <cgsfv@users.noreply.github.com>
Craig Blackmore <craig.blackmore@embecosm.com>
Dan Robertson <danlrobertson89@gmail.com>
Darius Rad <darius@bluespec.com>
dave-estes-syzexion <53795406+dave-estes-syzexion@users.noreply.github.com>
Dmitry Ryzhov <dmitry.ryzhov@cloudbear.ru>
Dolu1990 <charles.papon.90@gmail.com>
Emmanuel Blot <emmanuel.blot@free.fr>
Ernie Edgar <43148441+ernie-sifive@users.noreply.github.com>
Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
Farid Khaydari <f.khaydari@syntacore.com>
Gleb Gagarin <gleb@sifive.com>
Greg Savin <43152568+SiFiveGregS@users.noreply.github.com>
Hang Xu <xuhang@eswincomputing.com>
Hsiangkai <Hsiangkai@gmail.com>
Jan Matyas <jan.matyas@codasip.com>
jhjung81 <48940114+jhjung81@users.noreply.github.com>
Jiuyang Liu <liu@jiuyang.me>
Kaspar Schleiser <kaspar@schleiser.de>
Khem Raj <raj.khem@gmail.com>
Kirill Radkin <kirill.radkin@syntacore.com>
liangzhen <zhen.liang@spacemit.com>
Liviu Ionescu <ilg@livius.net>
Marc Schink <openocd-dev@marcschink.de>
Megan Wachs <megan@sifive.com>
Nils Wistoff <git@wistoff.net>
Palmer Dabbelt <palmer@dabbelt.com>
panciyan <panciyan@eswincomputing.com>
Parshintsev Anatoly <anatoly.parshintsev@syntacore.com>
Paul George <command.paul@gmail.com>
Pavel S. Smirnov <Paul.Smirnov.aka.sps@gmail.com>
Philipp Wagner <mail@philipp-wagner.com>
Ryan Macdonald <rmac@sifive.com>
Samuel Obuch <samuel.obuch17@gmail.com>
Tarek BOCHKATI <tarek.bouchkati@gmail.com>
Tim Newsome <tim@casualhacker.net>
Tobias Kaiser <mail@tb-kaiser.de>
Tom Hebb <tommyhebb@gmail.com>
Tommy Murphy <tommy_murphy@hotmail.com>
wxjstz <wxjstz@126.com>
wzgpeter <wzgpeter@outlook.com>
Xiang W <wxjstz@126.com>
zhusonghe <zhusonghe@eswincomputing.com>
Checkpatch-ignore MULTISTATEMENT_MACRO_USE_DO_WHILE is added to allow a
macro in riscv-013.c that can't use do/while because it expands to a
"case ...:" statement.
Checkpatch-ignore TRAILING_SEMICOLON is added to allow a construct in
riscv-013.c where a macro expands to either code (where it needs the
semicolon) or a member of an enum (where it needs a comma).
Checkpatch-ignore LONG_LINE_COMMENT and NEW_TYPEDEFS lines are added for
the sake of the autogenerated files from riscv-debug-spec.
All non-autogenerated files have been updated for checkpatch compliance.
Checkpatch-ignore: LONG_LINE_COMMENT
Checkpatch-ignore: NEW_TYPEDEFS
Checkpatch-ignore: MULTISTATEMENT_MACRO_USE_DO_WHILE
Checkpatch-ignore: TRAILING_SEMICOLON
Change-Id: Ie594915a4d6e6f9d9dad6016b176ab76409a099a
Signed-off-by: Bernhard Rosenkränzer <bero@baylibre.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8893
Tested-by: jenkins
Reviewed-by: Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
210 lines
5.9 KiB
C
210 lines
5.9 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "target/target.h"
|
|
#include "target/register.h"
|
|
#include "riscv.h"
|
|
#include "program.h"
|
|
#include "helper/log.h"
|
|
|
|
#include "debug_defines.h"
|
|
#include "encoding.h"
|
|
|
|
/* Program interface. */
|
|
int riscv_program_init(struct riscv_program *p, struct target *target)
|
|
{
|
|
memset(p, 0, sizeof(*p));
|
|
p->target = target;
|
|
p->instruction_count = 0;
|
|
|
|
for (unsigned int i = 0; i < RISCV013_MAX_PROGBUF_SIZE; ++i)
|
|
p->progbuf[i] = (uint32_t)(-1);
|
|
|
|
p->execution_result = RISCV_PROGBUF_EXEC_RESULT_NOT_EXECUTED;
|
|
return ERROR_OK;
|
|
}
|
|
|
|
int riscv_program_write(struct riscv_program *program)
|
|
{
|
|
for (unsigned int i = 0; i < program->instruction_count; ++i) {
|
|
LOG_TARGET_DEBUG(program->target, "progbuf[%02x] = DASM(0x%08x)",
|
|
i, program->progbuf[i]);
|
|
if (riscv_write_progbuf(program->target, i, program->progbuf[i]) != ERROR_OK)
|
|
return ERROR_FAIL;
|
|
}
|
|
return ERROR_OK;
|
|
}
|
|
|
|
/** Add ebreak and execute the program. */
|
|
int riscv_program_exec(struct riscv_program *p, struct target *t)
|
|
{
|
|
keep_alive();
|
|
|
|
p->execution_result = RISCV_PROGBUF_EXEC_RESULT_UNKNOWN;
|
|
|
|
if (riscv_program_ebreak(p) != ERROR_OK) {
|
|
LOG_TARGET_ERROR(t, "Unable to insert ebreak into program buffer");
|
|
for (unsigned int i = 0; i < riscv_progbuf_size(p->target); ++i)
|
|
LOG_TARGET_ERROR(t, "progbuf[%02x]: DASM(0x%08" PRIx32 ") [0x%08" PRIx32 "]",
|
|
i, p->progbuf[i], p->progbuf[i]);
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
if (riscv_program_write(p) != ERROR_OK)
|
|
return ERROR_FAIL;
|
|
|
|
uint32_t cmderr;
|
|
if (riscv_execute_progbuf(t, &cmderr) != ERROR_OK) {
|
|
p->execution_result = (cmderr == DM_ABSTRACTCS_CMDERR_EXCEPTION)
|
|
? RISCV_PROGBUF_EXEC_RESULT_EXCEPTION
|
|
: RISCV_PROGBUF_EXEC_RESULT_UNKNOWN_ERROR;
|
|
/* TODO: what happens if we fail here, but need to restore registers? */
|
|
LOG_TARGET_DEBUG(t, "Unable to execute program %p", p);
|
|
return ERROR_FAIL;
|
|
}
|
|
p->execution_result = RISCV_PROGBUF_EXEC_RESULT_SUCCESS;
|
|
|
|
return ERROR_OK;
|
|
}
|
|
|
|
int riscv_program_sdr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset)
|
|
{
|
|
return riscv_program_insert(p, sd(d, b, offset));
|
|
}
|
|
|
|
int riscv_program_swr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset)
|
|
{
|
|
return riscv_program_insert(p, sw(d, b, offset));
|
|
}
|
|
|
|
int riscv_program_shr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset)
|
|
{
|
|
return riscv_program_insert(p, sh(d, b, offset));
|
|
}
|
|
|
|
int riscv_program_sbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset)
|
|
{
|
|
return riscv_program_insert(p, sb(d, b, offset));
|
|
}
|
|
|
|
int riscv_program_store(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset,
|
|
unsigned int size)
|
|
{
|
|
switch (size) {
|
|
case 1:
|
|
return riscv_program_sbr(p, d, b, offset);
|
|
case 2:
|
|
return riscv_program_shr(p, d, b, offset);
|
|
case 4:
|
|
return riscv_program_swr(p, d, b, offset);
|
|
case 8:
|
|
return riscv_program_sdr(p, d, b, offset);
|
|
}
|
|
assert(false && "Unsupported size");
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
int riscv_program_ldr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset)
|
|
{
|
|
return riscv_program_insert(p, ld(d, b, offset));
|
|
}
|
|
|
|
int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset)
|
|
{
|
|
return riscv_program_insert(p, lw(d, b, offset));
|
|
}
|
|
|
|
int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset)
|
|
{
|
|
return riscv_program_insert(p, lh(d, b, offset));
|
|
}
|
|
|
|
int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset)
|
|
{
|
|
return riscv_program_insert(p, lb(d, b, offset));
|
|
}
|
|
|
|
int riscv_program_load(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset,
|
|
unsigned int size)
|
|
{
|
|
switch (size) {
|
|
case 1:
|
|
return riscv_program_lbr(p, d, b, offset);
|
|
case 2:
|
|
return riscv_program_lhr(p, d, b, offset);
|
|
case 4:
|
|
return riscv_program_lwr(p, d, b, offset);
|
|
case 8:
|
|
return riscv_program_ldr(p, d, b, offset);
|
|
}
|
|
assert(false && "Unsupported size");
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
int riscv_program_csrrsi(struct riscv_program *p, enum gdb_regno d, uint8_t z, enum gdb_regno csr)
|
|
{
|
|
assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095);
|
|
return riscv_program_insert(p, csrrsi(d, z, csr - GDB_REGNO_CSR0));
|
|
}
|
|
|
|
int riscv_program_csrrci(struct riscv_program *p, enum gdb_regno d, uint8_t z, enum gdb_regno csr)
|
|
{
|
|
assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095);
|
|
return riscv_program_insert(p, csrrci(d, z, csr - GDB_REGNO_CSR0));
|
|
}
|
|
|
|
int riscv_program_csrr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno csr)
|
|
{
|
|
assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095);
|
|
return riscv_program_insert(p, csrrs(d, GDB_REGNO_ZERO, csr - GDB_REGNO_CSR0));
|
|
}
|
|
|
|
int riscv_program_csrw(struct riscv_program *p, enum gdb_regno s, enum gdb_regno csr)
|
|
{
|
|
assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095);
|
|
return riscv_program_insert(p, csrrw(GDB_REGNO_ZERO, s, csr - GDB_REGNO_CSR0));
|
|
}
|
|
|
|
int riscv_program_fence_i(struct riscv_program *p)
|
|
{
|
|
return riscv_program_insert(p, fence_i());
|
|
}
|
|
|
|
int riscv_program_fence_rw_rw(struct riscv_program *p)
|
|
{
|
|
return riscv_program_insert(p, fence_rw_rw());
|
|
}
|
|
|
|
int riscv_program_ebreak(struct riscv_program *p)
|
|
{
|
|
struct target *target = p->target;
|
|
RISCV_INFO(r);
|
|
if (p->instruction_count == riscv_progbuf_size(target) &&
|
|
r->get_impebreak(target)) {
|
|
return ERROR_OK;
|
|
}
|
|
return riscv_program_insert(p, ebreak());
|
|
}
|
|
|
|
int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, int16_t u)
|
|
{
|
|
return riscv_program_insert(p, addi(d, s, u));
|
|
}
|
|
|
|
int riscv_program_insert(struct riscv_program *p, riscv_insn_t i)
|
|
{
|
|
if (p->instruction_count >= riscv_progbuf_size(p->target)) {
|
|
LOG_TARGET_ERROR(p->target, "Unable to insert program into progbuf, "
|
|
"capacity would be exceeded (progbufsize=%u).",
|
|
riscv_progbuf_size(p->target));
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
p->progbuf[p->instruction_count] = i;
|
|
p->instruction_count++;
|
|
return ERROR_OK;
|
|
}
|