Skip to content

Commit

Permalink
Manipulate csr_cycle and PC by register
Browse files Browse the repository at this point in the history
  • Loading branch information
qwe661234 committed Oct 11, 2023
1 parent 20b3a44 commit dca17cc
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 104 deletions.
2 changes: 1 addition & 1 deletion src/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ typedef struct rv_insn {
* self-recursive version, enabling the compiler to leverage TCO.
*/
bool tailcall;
bool (*impl)(riscv_t *, const struct rv_insn *);
bool (*impl)(riscv_t *, const struct rv_insn *, uint64_t, uint32_t);

/* Two pointers, 'branch_taken' and 'branch_untaken', are employed to
* avoid the overhead associated with aggressive memory copying. Instead
Expand Down
133 changes: 84 additions & 49 deletions src/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,11 @@ RV_EXCEPTION_LIST
#define RV_EXC_MISALIGN_HANDLER(mask_or_pc, type, compress, IO) \
IIF(IO) \
(if (!rv->io.allow_misalign && unlikely(addr & (mask_or_pc))), \
if (unlikely(insn_is_misaligned(rv->PC)))) \
if (unlikely(insn_is_misaligned(PC)))) \
{ \
rv->compressed = compress; \
rv->csr_cycle = cycle; \
rv->PC = PC; \
rv_except_##type##_misaligned(rv, IIF(IO)(addr, mask_or_pc)); \
return false; \
}
Expand Down Expand Up @@ -368,17 +370,21 @@ static bool branch_taken = false;
static uint32_t last_pc = 0;

/* Interpreter-based execution path */
#define RVOP(inst, code) \
static bool do_##inst(riscv_t *rv, const rv_insn_t *ir) \
{ \
rv->csr_cycle++; \
code; \
nextop: \
rv->PC += ir->insn_len; \
if (unlikely(RVOP_NO_NEXT(ir))) \
return true; \
const rv_insn_t *next = ir->next; \
MUST_TAIL return next->impl(rv, next); \
#define RVOP(inst, code) \
static bool do_##inst(riscv_t *rv, const rv_insn_t *ir, uint64_t cycle, \
uint32_t PC) \
{ \
cycle++; \
code; \
nextop: \
PC += ir->insn_len; \
if (unlikely(RVOP_NO_NEXT(ir))) { \
rv->csr_cycle = cycle; \
rv->PC = PC; \
return true; \
} \
const rv_insn_t *next = ir->next; \
MUST_TAIL return next->impl(rv, next, cycle, PC); \
}

#include "rv32_template.c"
Expand Down Expand Up @@ -408,36 +414,42 @@ enum {
};

/* multiple lui */
static bool do_fuse1(riscv_t *rv, rv_insn_t *ir)
static bool do_fuse1(riscv_t *rv, rv_insn_t *ir, uint64_t cycle, uint32_t PC)
{
rv->csr_cycle += ir->imm2;
cycle += ir->imm2;
opcode_fuse_t *fuse = ir->fuse;
for (int i = 0; i < ir->imm2; i++)
rv->X[fuse[i].rd] = fuse[i].imm;
rv->PC += ir->imm2 * ir->insn_len;
if (unlikely(RVOP_NO_NEXT(ir)))
PC += ir->imm2 * ir->insn_len;
if (unlikely(RVOP_NO_NEXT(ir))) {
rv->csr_cycle = cycle;
rv->PC = PC;
return true;
}
const rv_insn_t *next = ir->next;
MUST_TAIL return next->impl(rv, next);
MUST_TAIL return next->impl(rv, next, cycle, PC);
}

/* LUI + ADD */
static bool do_fuse2(riscv_t *rv, rv_insn_t *ir)
static bool do_fuse2(riscv_t *rv, rv_insn_t *ir, uint64_t cycle, uint32_t PC)
{
rv->csr_cycle += 2;
cycle += 2;
rv->X[ir->rd] = ir->imm;
rv->X[ir->rs2] = rv->X[ir->rd] + rv->X[ir->rs1];
rv->PC += 2 * ir->insn_len;
if (unlikely(RVOP_NO_NEXT(ir)))
PC += 2 * ir->insn_len;
if (unlikely(RVOP_NO_NEXT(ir))) {
rv->csr_cycle = cycle;
rv->PC = PC;
return true;
}
const rv_insn_t *next = ir->next;
MUST_TAIL return next->impl(rv, next);
MUST_TAIL return next->impl(rv, next, cycle, PC);
}

/* multiple SW */
static bool do_fuse3(riscv_t *rv, rv_insn_t *ir)
static bool do_fuse3(riscv_t *rv, rv_insn_t *ir, uint64_t cycle, uint32_t PC)
{
rv->csr_cycle += ir->imm2;
cycle += ir->imm2;
opcode_fuse_t *fuse = ir->fuse;
/* The memory addresses of the sw instructions are contiguous, thus only
* the first SW instruction needs to be checked to determine if its memory
Expand All @@ -448,17 +460,20 @@ static bool do_fuse3(riscv_t *rv, rv_insn_t *ir)
RV_EXC_MISALIGN_HANDLER(3, store, false, 1);
rv->io.mem_write_w(addr, rv->X[fuse[i].rs2]);
}
rv->PC += ir->imm2 * ir->insn_len;
if (unlikely(RVOP_NO_NEXT(ir)))
PC += ir->imm2 * ir->insn_len;
if (unlikely(RVOP_NO_NEXT(ir))) {
rv->csr_cycle = cycle;
rv->PC = PC;
return true;
}
const rv_insn_t *next = ir->next;
MUST_TAIL return next->impl(rv, next);
MUST_TAIL return next->impl(rv, next, cycle, PC);
}

/* multiple LW */
static bool do_fuse4(riscv_t *rv, rv_insn_t *ir)
static bool do_fuse4(riscv_t *rv, rv_insn_t *ir, uint64_t cycle, uint32_t PC)
{
rv->csr_cycle += ir->imm2;
cycle += ir->imm2;
opcode_fuse_t *fuse = ir->fuse;
/* The memory addresses of the lw instructions are contiguous, therefore
* only the first LW instruction needs to be checked to determine if its
Expand All @@ -469,53 +484,74 @@ static bool do_fuse4(riscv_t *rv, rv_insn_t *ir)
RV_EXC_MISALIGN_HANDLER(3, load, false, 1);
rv->X[fuse[i].rd] = rv->io.mem_read_w(addr);
}
rv->PC += ir->imm2 * ir->insn_len;
if (unlikely(RVOP_NO_NEXT(ir)))
PC += ir->imm2 * ir->insn_len;
if (unlikely(RVOP_NO_NEXT(ir))) {
rv->csr_cycle = cycle;
rv->PC = PC;
return true;
}
const rv_insn_t *next = ir->next;
MUST_TAIL return next->impl(rv, next);
MUST_TAIL return next->impl(rv, next, cycle, PC);
}

/* memset */
static bool do_fuse5(riscv_t *rv, const rv_insn_t *ir)
static bool do_fuse5(riscv_t *rv,
const rv_insn_t *ir,
uint64_t cycle,
uint32_t PC)
{
rv->csr_cycle += 2;
cycle += 2;
memory_t *m = ((state_t *) rv->userdata)->mem;
memset((char *) m->mem_base + rv->X[rv_reg_a0], rv->X[rv_reg_a1],
rv->X[rv_reg_a2]);
rv->PC = rv->X[rv_reg_ra] & ~1U;
if (unlikely(RVOP_NO_NEXT(ir)))
PC = rv->X[rv_reg_ra] & ~1U;
if (unlikely(RVOP_NO_NEXT(ir))) {
rv->csr_cycle = cycle;
rv->PC = PC;
return true;
}
const rv_insn_t *next = ir->next;
MUST_TAIL return next->impl(rv, next);
MUST_TAIL return next->impl(rv, next, cycle, PC);
}

/* memcpy */
static bool do_fuse6(riscv_t *rv, const rv_insn_t *ir)
static bool do_fuse6(riscv_t *rv,
const rv_insn_t *ir,
uint64_t cycle,
uint32_t PC)
{
rv->csr_cycle += 2;
cycle += 2;
memory_t *m = ((state_t *) rv->userdata)->mem;
memcpy((char *) m->mem_base + rv->X[rv_reg_a0],
(char *) m->mem_base + rv->X[rv_reg_a1], rv->X[rv_reg_a2]);
rv->PC = rv->X[rv_reg_ra] & ~1U;
if (unlikely(RVOP_NO_NEXT(ir)))
PC = rv->X[rv_reg_ra] & ~1U;
if (unlikely(RVOP_NO_NEXT(ir))) {
rv->csr_cycle = cycle;
rv->PC = PC;
return true;
}
const rv_insn_t *next = ir->next;
MUST_TAIL return next->impl(rv, next);
MUST_TAIL return next->impl(rv, next, cycle, PC);
}

/* multiple shift immediate */
static bool do_fuse7(riscv_t *rv, const rv_insn_t *ir)
static bool do_fuse7(riscv_t *rv,
const rv_insn_t *ir,
uint64_t cycle,
uint32_t PC)
{
rv->csr_cycle += ir->imm2;
cycle += ir->imm2;
opcode_fuse_t *fuse = ir->fuse;
for (int i = 0; i < ir->imm2; i++)
shift_func(rv, (const rv_insn_t *) (&fuse[i]));
rv->PC += ir->imm2 * ir->insn_len;
if (unlikely(RVOP_NO_NEXT(ir)))
PC += ir->imm2 * ir->insn_len;
if (unlikely(RVOP_NO_NEXT(ir))) {
rv->csr_cycle = cycle;
rv->PC = PC;
return true;
}
const rv_insn_t *next = ir->next;
MUST_TAIL return next->impl(rv, next);
MUST_TAIL return next->impl(rv, next, cycle, PC);
}

/* clang-format off */
Expand Down Expand Up @@ -988,9 +1024,8 @@ void rv_step(riscv_t *rv, int32_t cycles)

/* execute the block */
const rv_insn_t *ir = block->ir_head;
if (unlikely(!ir->impl(rv, ir)))
if (unlikely(!ir->impl(rv, ir, rv->csr_cycle, rv->PC)))
break;

prev = block;
}
}
Expand Down
Loading

0 comments on commit dca17cc

Please sign in to comment.