提交 3a13f57b 编写于 作者: Z Zihao Yu

riscv32: adapt to latest API

上级 b735fce5
......@@ -25,6 +25,7 @@ typedef struct {
bool is_jmp;
vaddr_t jmp_pc;
Operand src1, dest, src2;
int width;
rtlreg_t tmp_reg[5];
struct ISADecodeInfo isa;
} DecodeExecState;
......
#ifndef __ISA_RISCV32_H__
#define __ISA_RISCV32_H__
#include <common.h>
// memory
#define IMAGE_START 0x100000
#define PMEM_BASE 0x80000000
// reg
typedef struct {
union {
rtlreg_t _32;
} gpr[32];
vaddr_t pc;
vaddr_t stvec;
vaddr_t scause;
vaddr_t sepc;
union {
struct {
uint32_t uie : 1;
uint32_t sie : 1;
uint32_t pad0: 2;
uint32_t upie: 1;
uint32_t spie: 1;
uint32_t pad1: 2;
uint32_t spp : 1;
uint32_t dontcare :21;
};
uint32_t val;
} sstatus;
union {
struct {
uint32_t ppn :22;
uint32_t asid: 9;
uint32_t mode: 1;
};
uint32_t val;
} satp;
bool INTR;
} CPU_state;
// decode
struct ISADecodeInfo {
union {
struct {
uint32_t opcode1_0 : 2;
uint32_t opcode6_2 : 5;
uint32_t rd : 5;
uint32_t funct3 : 3;
uint32_t rs1 : 5;
uint32_t rs2 : 5;
uint32_t funct7 : 7;
} r;
struct {
uint32_t opcode1_0 : 2;
uint32_t opcode6_2 : 5;
uint32_t rd : 5;
uint32_t funct3 : 3;
uint32_t rs1 : 5;
int32_t simm11_0 :12;
} i;
struct {
uint32_t opcode1_0 : 2;
uint32_t opcode6_2 : 5;
uint32_t imm4_0 : 5;
uint32_t funct3 : 3;
uint32_t rs1 : 5;
uint32_t rs2 : 5;
int32_t simm11_5 : 7;
} s;
struct {
uint32_t opcode1_0 : 2;
uint32_t opcode6_2 : 5;
uint32_t imm11 : 1;
uint32_t imm4_1 : 4;
uint32_t funct3 : 3;
uint32_t rs1 : 5;
uint32_t rs2 : 5;
uint32_t imm10_5 : 6;
int32_t simm12 : 1;
} b;
struct {
uint32_t opcode1_0 : 2;
uint32_t opcode6_2 : 5;
uint32_t rd : 5;
uint32_t imm31_12 :20;
} u;
struct {
uint32_t opcode1_0 : 2;
uint32_t opcode6_2 : 5;
uint32_t rd : 5;
uint32_t imm19_12 : 8;
uint32_t imm11 : 1;
uint32_t imm10_1 :10;
int32_t simm20 : 1;
} j;
struct {
uint32_t pad7 :20;
uint32_t csr :12;
} csr;
uint32_t val;
} instr;
};
#endif
#include "cpu/decode.h"
#include "rtl/rtl.h"
// decode operand helper
#define make_DopHelper(name) void concat(decode_op_, name) (Operand *op, uint32_t val, bool load_val)
static inline make_DopHelper(i) {
op->type = OP_TYPE_IMM;
op->imm = val;
rtl_li(&op->val, op->imm);
print_Dop(op->str, OP_STR_SIZE, "%d", op->imm);
}
static inline make_DopHelper(r) {
op->type = OP_TYPE_REG;
op->reg = val;
if (load_val) {
rtl_lr(&op->val, op->reg, 4);
}
print_Dop(op->str, OP_STR_SIZE, "%s", reg_name(op->reg, 4));
}
make_DHelper(I) {
decode_op_r(id_src, decinfo.isa.instr.rs1, true);
decode_op_i(id_src2, decinfo.isa.instr.simm11_0, true);
decode_op_r(id_dest, decinfo.isa.instr.rd, false);
}
make_DHelper(R) {
decode_op_r(id_src, decinfo.isa.instr.rs1, true);
decode_op_r(id_src2, decinfo.isa.instr.rs2, true);
decode_op_r(id_dest, decinfo.isa.instr.rd, false);
}
make_DHelper(U) {
decode_op_i(id_src, decinfo.isa.instr.imm31_12 << 12, true);
decode_op_r(id_dest, decinfo.isa.instr.rd, false);
print_Dop(id_src->str, OP_STR_SIZE, "0x%x", decinfo.isa.instr.imm31_12);
}
make_DHelper(J) {
sword_t offset = (decinfo.isa.instr.simm20 << 20) | (decinfo.isa.instr.imm19_12 << 12) |
(decinfo.isa.instr.imm11_ << 11) | (decinfo.isa.instr.imm10_1 << 1);
decinfo.jmp_pc = cpu.pc + offset;
decode_op_i(id_src, decinfo.jmp_pc, true);
print_Dop(id_src->str, OP_STR_SIZE, "0x%x", decinfo.jmp_pc);
decode_op_r(id_dest, decinfo.isa.instr.rd, false);
}
make_DHelper(B) {
sword_t offset = (decinfo.isa.instr.simm12 << 12) | (decinfo.isa.instr.imm11 << 11) |
(decinfo.isa.instr.imm10_5 << 5) | (decinfo.isa.instr.imm4_1 << 1);
decinfo.jmp_pc = cpu.pc + offset;
decode_op_i(id_dest, decinfo.jmp_pc, true);
print_Dop(id_dest->str, OP_STR_SIZE, "0x%x", decinfo.jmp_pc);
decode_op_r(id_src, decinfo.isa.instr.rs1, true);
decode_op_r(id_src2, decinfo.isa.instr.rs2, true);
}
make_DHelper(ld) {
decode_op_r(id_src, decinfo.isa.instr.rs1, true);
decode_op_i(id_src2, decinfo.isa.instr.simm11_0, true);
print_Dop(id_src->str, OP_STR_SIZE, "%d(%s)", id_src2->val, reg_name(id_src->reg, 4));
rtl_add(&id_src->addr, &id_src->val, &id_src2->val);
decode_op_r(id_dest, decinfo.isa.instr.rd, false);
}
make_DHelper(st) {
decode_op_r(id_src, decinfo.isa.instr.rs1, true);
sword_t simm = (decinfo.isa.instr.simm11_5 << 5) | decinfo.isa.instr.imm4_0;
decode_op_i(id_src2, simm, true);
print_Dop(id_src->str, OP_STR_SIZE, "%d(%s)", id_src2->val, reg_name(id_src->reg, 4));
rtl_add(&id_src->addr, &id_src->val, &id_src2->val);
decode_op_r(id_dest, decinfo.isa.instr.rs2, true);
}
make_DHelper(csr) {
decode_op_r(id_src, decinfo.isa.instr.rs1, true);
decode_op_i(id_src2, decinfo.isa.instr.csr, true);
decode_op_r(id_dest, decinfo.isa.instr.rd, false);
}
#ifndef __RISCV32_DIFF_TEST_H__
#define __RISCV32_DIFF_TEST_H__
#ifndef __DIFFTEST_H__
#define __DIFFTEST_H__
#define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 33) // GRPs + pc
#define isa_difftest_getregs_hook()
#define isa_difftest_setregs_hook()
#endif
#include "nemu.h"
#include "monitor/diff-test.h"
#include <isa.h>
#include <monitor/difftest.h>
#include "../local-include/reg.h"
#include "difftest.h"
bool isa_difftest_checkregs(CPU_state *ref_r, vaddr_t pc) {
if (memcmp(&cpu, ref_r, DIFFTEST_REG_SIZE)) {
......
#include <isa.h>
#include <cpu/exec.h>
#include "difftest.h"
void isa_difftest_getregs(void *r) {
memcpy(r, &cpu, DIFFTEST_REG_SIZE);
}
void isa_difftest_setregs(const void *r) {
memcpy(&cpu, r, DIFFTEST_REG_SIZE);
}
void isa_difftest_raise_intr(word_t NO) {
DecodeExecState s;
s.is_jmp = 0;
s.isa = (struct ISADecodeInfo) { 0 };
void raise_intr(DecodeExecState *s, word_t NO, vaddr_t epc);
raise_intr(&s, NO, cpu.pc);
update_pc(&s);
}
#include "cpu/exec.h"
#include "../local-include/rtl.h"
make_EHelper(add);
make_EHelper(sub);
make_EHelper(sll);
make_EHelper(srl);
make_EHelper(sra);
make_EHelper(slt);
make_EHelper(sltu);
make_EHelper(xor);
make_EHelper(or);
make_EHelper(and);
make_EHelper(auipc);
make_EHelper(lui);
make_EHelper(ld);
make_EHelper(lds);
make_EHelper(st);
make_EHelper(jal);
make_EHelper(jalr);
make_EHelper(branch);
#include "compute.h"
#include "control.h"
#include "ldst.h"
#include "muldiv.h"
#include "system.h"
make_EHelper(inv);
make_EHelper(nemu_trap);
make_EHelper(csrrw);
make_EHelper(csrrs);
make_EHelper(priv);
make_EHelper(mul);
make_EHelper(mulh);
make_EHelper(mulhu);
make_EHelper(div);
make_EHelper(divu);
make_EHelper(rem);
make_EHelper(remu);
#include "cpu/exec.h"
make_EHelper(add) {
rtl_add(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(add);
}
make_EHelper(sub) {
rtl_sub(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(sub);
}
make_EHelper(sll) {
rtl_andi(&id_src2->val, &id_src2->val, 0x1f);
rtl_shl(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(sll);
}
make_EHelper(srl) {
rtl_andi(&id_src2->val, &id_src2->val, 0x1f);
if (decinfo.isa.instr.funct7 == 32) {
// sra
rtl_sar(&s0, &id_src->val, &id_src2->val);
print_asm_template3(sra);
}
else {
rtl_shr(&s0, &id_src->val, &id_src2->val);
print_asm_template3(srl);
}
rtl_sr(id_dest->reg, &s0, 4);
}
make_EHelper(sra) {
exec_srl(NULL);
}
make_EHelper(slt) {
rtl_setrelop(RELOP_LT, &s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(slt);
}
make_EHelper(sltu) {
rtl_setrelop(RELOP_LTU, &s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(sltu);
}
make_EHelper(xor) {
rtl_xor(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(xor);
}
make_EHelper(or) {
rtl_or(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(or);
}
make_EHelper(and) {
rtl_and(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(and);
}
make_EHelper(auipc) {
rtl_add(&s0, &id_src->val, &cpu.pc);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template2(auipc);
}
make_EHelper(lui) {
rtl_sr(id_dest->reg, &id_src->val, 4);
print_asm_template2(lui);
}
static inline make_EHelper(add) {
rtl_add(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(add);
}
static inline make_EHelper(sub) {
rtl_sub(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(sub);
}
static inline make_EHelper(sll) {
rtl_andi(s, dsrc2, dsrc2, 0x1f);
rtl_shl(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(sll);
}
static inline make_EHelper(srl) {
rtl_andi(s, dsrc2, dsrc2, 0x1f);
if (s->isa.instr.r.funct7 == 32) {
// sra
rtl_sar(s, s0, dsrc1, dsrc2);
print_asm_template3(sra);
}
else {
rtl_shr(s, s0, dsrc1, dsrc2);
print_asm_template3(srl);
}
rtl_sr(s, id_dest->reg, s0, 4);
}
static inline make_EHelper(sra) {
exec_srl(s);
}
static inline make_EHelper(slt) {
rtl_setrelop(s, RELOP_LT, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(slt);
}
static inline make_EHelper(sltu) {
rtl_setrelop(s, RELOP_LTU, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(sltu);
}
static inline make_EHelper(xor) {
rtl_xor(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(xor);
}
static inline make_EHelper(or) {
rtl_or(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(or);
}
static inline make_EHelper(and) {
rtl_and(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(and);
}
static inline make_EHelper(auipc) {
rtl_add(s, s0, dsrc1, &cpu.pc);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template2(auipc);
}
static inline make_EHelper(lui) {
rtl_sr(s, id_dest->reg, dsrc1, 4);
print_asm_template2(lui);
}
#include "cpu/exec.h"
#include <monitor/difftest.h>
make_EHelper(jal) {
rtl_addi(&s0, &cpu.pc, 4);
rtl_sr(id_dest->reg, &s0, 4);
rtl_j(decinfo.jmp_pc);
static inline make_EHelper(jal) {
rtl_addi(s, s0, &cpu.pc, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_j(s, s->jmp_pc);
print_asm_template2(jal);
}
make_EHelper(jalr) {
rtl_addi(&s0, &cpu.pc, 4);
rtl_sr(id_dest->reg, &s0, 4);
static inline make_EHelper(jalr) {
rtl_addi(s, s0, &cpu.pc, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_add(&s0, &id_src->val, &id_src2->val);
rtl_andi(&s0, &s0, ~0x1u);
rtl_jr(&s0);
rtl_add(s, s0, dsrc1, dsrc2);
rtl_andi(s, s0, s0, ~0x1u);
rtl_jr(s, s0);
difftest_skip_dut(1, 2);
......@@ -33,10 +33,10 @@ static const struct {
[7] = { RELOP_GEU, "geu"},
};
make_EHelper(branch) {
int type = decinfo.isa.instr.funct3;
static inline make_EHelper(branch) {
int type = s->isa.instr.b.funct3;
assert(type != 2 && type != 3);
rtl_jrelop(branch_map[type].relop, &id_src->val, &id_src2->val, decinfo.jmp_pc);
rtl_jrelop(s, branch_map[type].relop, dsrc1, dsrc2, s->jmp_pc);
print_asm("b%s %s,%s,%s", branch_map[type].name, id_src->str, id_src2->str, id_dest->str);
}
#include "cpu/exec.h"
#include <cpu/exec.h>
#include "../local-include/decode.h"
#include "all-instr.h"
static OpcodeEntry load_table [8] = {
EXW(lds, 1), EXW(lds, 2), EXW(ld, 4), EMPTY, EXW(ld, 1), EXW(ld, 2), EMPTY, EMPTY
};
#define decode_empty(s)
static make_EHelper(load) {
decinfo.width = load_table[decinfo.isa.instr.funct3].width;
idex(pc, &load_table[decinfo.isa.instr.funct3]);
static inline void set_width(DecodeExecState *s, int width) {
if (width != 0) s->width = width;
}
static OpcodeEntry store_table [8] = {
EXW(st, 1), EXW(st, 2), EXW(st, 4), EMPTY, EMPTY, EMPTY, EMPTY, EMPTY
};
#define IDEXW(idx, id, ex, w) CASE_ENTRY(idx, concat(decode_, id), concat(exec_, ex), w)
#define IDEX(idx, id, ex) IDEXW(idx, id, ex, 0)
#define EXW(idx, ex, w) IDEXW(idx, empty, ex, w)
#define EX(idx, ex) EXW(idx, ex, 0)
#define EMPTY(idx) //EX(idx, inv)
static make_EHelper(store) {
decinfo.width = store_table[decinfo.isa.instr.funct3].width;
idex(pc, &store_table[decinfo.isa.instr.funct3]);
}
static OpcodeEntry op_imm_table [8] = {
EX(add), EX(sll), EX(slt), EX(sltu), EX(xor), EX(srl), EX(or), EX(and)
};
#define CASE_ENTRY(idx, id, ex, w) case idx: set_width(s, w); id(s); ex(s); break;
static make_EHelper(op_imm) {
idex(pc, &op_imm_table[decinfo.isa.instr.funct3]);
static inline make_EHelper(load) {
switch (s->isa.instr.i.funct3) {
EXW (0, lds, 1) EXW (1, lds, 2) EXW (2, ld, 4)
EXW (4, ld, 1) EXW (5, ld, 2)
default: exec_inv(s);
}
}
static OpcodeEntry op_table [8] = {
EX(add), EX(sll), EX(slt), EX(sltu), EX(xor), EX(srl), EX(or), EX(and)
};
static OpcodeEntry op2_table [8] = {
EX(sub), EMPTY, EMPTY, EMPTY, EMPTY, EX(sra), EMPTY, EMPTY
};
static inline make_EHelper(store) {
switch (s->isa.instr.s.funct3) {
EXW(0, st, 1) EXW(1, st, 2) EXW(2, st, 4)
}
}
static OpcodeEntry muldiv_table [8] = {
EX(mul), EX(mulh), EMPTY, EX(mulhu), EX(div), EX(divu), EX(rem), EX(remu)
};
static inline make_EHelper(op_imm) {
switch (s->isa.instr.i.funct3) {
EX(0, add) EX(1, sll) EX(2, slt) EX(3, sltu)
EX(4, xor) EX(5, srl) EX(6, or) EX(7, and)
default: exec_inv(s);
}
}
static make_EHelper(op) {
switch (decinfo.isa.instr.funct7) {
case 0: idex(pc, &op_table[decinfo.isa.instr.funct3]); break;
case 1: idex(pc, &muldiv_table[decinfo.isa.instr.funct3]); break;
case 32: idex(pc, &op2_table[decinfo.isa.instr.funct3]); break;
default: assert(0);
static inline make_EHelper(op) {
if (s->isa.instr.r.funct7 == 32) {
switch (s->isa.instr.r.funct3) {
EX(0, sub) EX(5, sra)
default: exec_inv(s);
}
} else {
#define pair(x, y) (((x) << 3) | (y))
switch (pair(s->isa.instr.r.funct7, s->isa.instr.r.funct3)) {
EX(pair(0, 0), add) EX(pair(0, 1), sll) EX(pair(0, 2), slt) EX(pair(0, 3), sltu)
EX(pair(0, 4), xor) EX(pair(0, 5), srl) EX(pair(0, 6), or) EX(pair(0, 7), and)
EX(pair(1, 0), mul) EX(pair(1, 1), mulh) EX(pair(1, 3), mulhu)
EX(pair(1, 4), div) EX(pair(1, 5), divu) EX(pair(1, 6), rem) EX(pair(1, 7), remu)
default: exec_inv(s);
}
#undef pair
}
}
static OpcodeEntry system_table [8] = {
EX(priv), IDEX(csr, csrrw), IDEX(csr, csrrs), EMPTY, EMPTY, EMPTY, EMPTY, EMPTY
};
static inline make_EHelper(system) {
switch (s->isa.instr.i.funct3) {
EX(0, priv) IDEX (1, csr, csrrw) IDEX (2, csr, csrrs)
default: exec_inv(s);
}
}
static make_EHelper(system) {
idex(pc, &system_table[decinfo.isa.instr.funct3]);
static inline void exec(DecodeExecState *s) {
s->isa.instr.val = instr_fetch(&s->seq_pc, 4);
assert(s->isa.instr.r.opcode1_0 == 0x3);
switch (s->isa.instr.r.opcode6_2) {
IDEX (0b00000, ld, load)
IDEX (0b00100, I, op_imm)
IDEX (0b00101, U, auipc)
IDEX (0b01000, st, store) IDEX (0b01100, R, op)
IDEX (0b01101, U, lui) IDEX (0b11000, B, branch) IDEX (0b11001, I, jalr) EX (0b11010, nemu_trap)
IDEX (0b11011, J, jal) EX (0b11100, system)
default: exec_inv(s);
}
}
static OpcodeEntry opcode_table [32] = {
/* b00 */ IDEX(ld, load), EMPTY, EMPTY, EMPTY, IDEX(I, op_imm), IDEX(U, auipc), EMPTY, EMPTY,
/* b01 */ IDEX(st, store), EMPTY, EMPTY, EMPTY, IDEX(R, op), IDEX(U, lui), EMPTY, EMPTY,
/* b10 */ EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
/* b11 */ IDEX(B, branch), IDEX(I, jalr), EX(nemu_trap), IDEX(J, jal), EX(system), EMPTY, EMPTY, EMPTY,
};
vaddr_t isa_exec_once() {
DecodeExecState s;
s.is_jmp = 0;
s.seq_pc = cpu.pc;
exec(&s);
update_pc(&s);
void isa_exec(vaddr_t *pc) {
decinfo.isa.instr.val = instr_fetch(pc, 4);
assert(decinfo.isa.instr.opcode1_0 == 0x3);
idex(pc, &opcode_table[decinfo.isa.instr.opcode6_2]);
#if !defined(DIFF_TEST) && !_SHARE
void query_intr(DecodeExecState *s);
query_intr(&s);
#endif
return s.seq_pc;
}
#include "cpu/exec.h"
static inline make_EHelper(ld) {
rtl_lm(s, s0, &id_src1->addr, s->width);
rtl_sr(s, id_dest->reg, s0, 4);
make_EHelper(ld) {
rtl_lm(&s0, &id_src->addr, decinfo.width);
rtl_sr(id_dest->reg, &s0, 4);
switch (decinfo.width) {
switch (s->width) {
case 4: print_asm_template2(lw); break;
case 2: print_asm_template2(lhu); break;
case 1: print_asm_template2(lbu); break;
......@@ -13,22 +11,22 @@ make_EHelper(ld) {
}
// load sign value
make_EHelper(lds) {
rtl_lm(&s0, &id_src->addr, decinfo.width);
rtl_sext(&s0, &s0, decinfo.width);
rtl_sr(id_dest->reg, &s0, 4);
static inline make_EHelper(lds) {
rtl_lm(s, s0, &id_src1->addr, s->width);
rtl_sext(s, s0, s0, s->width);
rtl_sr(s, id_dest->reg, s0, 4);
switch (decinfo.width) {
switch (s->width) {
case 2: print_asm_template2(lh); break;
case 1: print_asm_template2(lb); break;
default: assert(0);
}
}
make_EHelper(st) {
rtl_sm(&id_src->addr, &id_dest->val, decinfo.width);
static inline make_EHelper(st) {
rtl_sm(s, &id_src1->addr, ddest, s->width);
switch (decinfo.width) {
switch (s->width) {
case 4: print_asm_template2(sw); break;
case 2: print_asm_template2(sh); break;
case 1: print_asm_template2(sb); break;
......
#include "cpu/exec.h"
make_EHelper(mul) {
rtl_imul_lo(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(mul);
}
make_EHelper(mulh) {
rtl_imul_hi(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(mulh);
}
make_EHelper(mulhu) {
rtl_mul_hi(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(mulh);
}
make_EHelper(div) {
rtl_idiv_q(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(div);
}
make_EHelper(divu) {
rtl_div_q(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(divu);
}
make_EHelper(rem) {
rtl_idiv_r(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(rem);
}
make_EHelper(remu) {
rtl_div_r(&s0, &id_src->val, &id_src2->val);
rtl_sr(id_dest->reg, &s0, 4);
print_asm_template3(remu);
}
static inline make_EHelper(mul) {
rtl_imul_lo(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(mul);
}
static inline make_EHelper(mulh) {
rtl_imul_hi(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(mulh);
}
static inline make_EHelper(mulhu) {
rtl_mul_hi(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(mulh);
}
static inline make_EHelper(div) {
rtl_idiv_q(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(div);
}
static inline make_EHelper(divu) {
rtl_div_q(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(divu);
}
static inline make_EHelper(rem) {
rtl_idiv_r(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(rem);
}
static inline make_EHelper(remu) {
rtl_div_r(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(remu);
}
#include "cpu/exec.h"
#include "monitor/monitor.h"
#include <cpu/exec.h>
#include <monitor/monitor.h>
#include <monitor/difftest.h>
make_EHelper(inv) {
/* invalid opcode */
uint32_t instr[2];
*pc = cpu.pc;
instr[0] = instr_fetch(pc, 4);
instr[1] = instr_fetch(pc, 4);
s->seq_pc = cpu.pc;
instr[0] = instr_fetch(&s->seq_pc, 4);
instr[1] = instr_fetch(&s->seq_pc, 4);
printf("invalid opcode(PC = 0x%08x): %08x %08x ...\n\n",
cpu.pc, instr[0], instr[1]);
......@@ -22,7 +23,7 @@ make_EHelper(inv) {
make_EHelper(nemu_trap) {
difftest_skip_ref();
rtl_exit(NEMU_END, cpu.pc, cpu.gpr[10]._32); // grp[10] is $a0
rtl_exit(NEMU_END, cpu.pc, cpu.gpr[10]._32); // gpr[10] is $a0
print_asm("nemu trap");
return;
......
#include "cpu/exec.h"
static inline rtlreg_t* csr_decode(uint32_t csr) {
difftest_skip_dut(1, 3);
......@@ -14,38 +12,37 @@ static inline rtlreg_t* csr_decode(uint32_t csr) {
return NULL;
}
make_EHelper(csrrw) {
static inline make_EHelper(csrrw) {
rtlreg_t *csr = csr_decode(id_src2->val);
rtl_sr(id_dest->reg, csr, 4);
rtl_mv(csr, &id_src->val);
rtl_sr(s, id_dest->reg, csr, 4);
rtl_mv(s, csr, dsrc1);
print_asm_template3("csrrw");
}
make_EHelper(csrrs) {
static inline make_EHelper(csrrs) {
rtlreg_t *csr = csr_decode(id_src2->val);
rtl_sr(id_dest->reg, csr, 4);
rtl_or(csr, csr, &id_src->val);
rtl_sr(s, id_dest->reg, csr, 4);
rtl_or(s, csr, csr, dsrc1);
print_asm_template3("csrrs");
}
extern void raise_intr(uint32_t NO, vaddr_t epc);
make_EHelper(priv) {
uint32_t type = decinfo.isa.instr.csr;
void raise_intr(DecodeExecState *s, uint32_t NO, vaddr_t epc);
static inline make_EHelper(priv) {
uint32_t type = s->isa.instr.csr.csr;
switch (type) {
case 0:
raise_intr(9, cpu.pc);
raise_intr(s, 9, cpu.pc);
print_asm("ecall");
break;
case 0x102:
cpu.sstatus.sie = cpu.sstatus.spie;
cpu.sstatus.spie = 1;
rtl_li(&s0, cpu.sepc);
rtl_jr(&s0);
rtl_li(s, s0, cpu.sepc);
rtl_jr(s, s0);
print_asm("sret");
break;
default: panic("unimplemented priv instruction type = 0x%x", type);
......
#ifndef __RISCV32_DECODE_H__
#define __RISCV32_DECODE_H__
typedef union {
struct {
uint32_t opcode1_0 : 2;
uint32_t opcode6_2 : 5;
uint32_t rd : 5;
uint32_t funct3 : 3;
uint32_t rs1 : 5;
uint32_t rs2 : 5;
uint32_t funct7 : 7;
};
struct {
uint32_t pad0 :20;
int32_t simm11_0 :12;
};
struct {
uint32_t pad1 : 7;
uint32_t imm4_0 : 5;
uint32_t pad2 :13;
int32_t simm11_5 : 7;
};
struct {
uint32_t pad3 : 7;
uint32_t imm11 : 1;
uint32_t imm4_1 : 4;
uint32_t pad4 :13;
uint32_t imm10_5 : 6;
int32_t simm12 : 1;
};
struct {
uint32_t pad5 :12;
uint32_t imm31_12 :20;
};
struct {
uint32_t pad6 :12;
uint32_t imm19_12 : 8;
uint32_t imm11_ : 1;
uint32_t imm10_1 :10;
int32_t simm20 : 1;
};
struct {
uint32_t pad7 :20;
uint32_t csr :12;
};
uint32_t val;
} Instr;
struct ISADecodeInfo {
Instr instr;
};
make_DHelper(I);
make_DHelper(R);
make_DHelper(U);
make_DHelper(J);
make_DHelper(B);
make_DHelper(ld);
make_DHelper(st);
make_DHelper(csr);
#endif
#ifndef __RISCV32_RTL_H__
#define __RISCV32_RTL_H__
#include "rtl/rtl.h"
static inline void rtl_lr(rtlreg_t* dest, int r, int width) {
if (r != 0) { rtl_mv(dest, &reg_l(r)); }
else { rtl_li(dest, 0); }
}
static inline void rtl_sr(int r, const rtlreg_t *src1, int width) {
if (r != 0) { rtl_mv(&reg_l(r), src1); }
}
#endif
#include "nemu.h"
#include <isa.h>
#include <memory/memory.h>
// this is not consistent with uint8_t
// but it is ok since we do not access the array directly
const uint32_t isa_default_img [] = {
static const uint32_t img [] = {
0x800002b7, // lui t0,0x80000
0x0002a023, // sw zero,0(t0)
0x0002a503, // lw a0,0(t0)
0x0000006b, // nemu_trap
};
const long isa_default_img_size = sizeof(isa_default_img);
void init_isa(void) {
static void restart() {
cpu.gpr[0]._32 = 0;
cpu.pc = PC_START;
cpu.pc = PMEM_BASE + IMAGE_START;
cpu.sstatus.val = 0x000c0100;
}
void init_isa() {
/* Load built-in image. */
memcpy(guest_to_host(IMAGE_START), img, sizeof(img));
register_pmem(0x80000000u);
/* Initialize this virtual computer system. */
restart();
}
#include "rtl/rtl.h"
#include <cpu/exec.h>
#include "local-include/rtl.h"
void raise_intr(uint32_t NO, vaddr_t epc) {
void raise_intr(DecodeExecState *s, uint32_t NO, vaddr_t epc) {
/* TODO: Trigger an interrupt/exception with ``NO''.
* That is, use ``NO'' to index the IDT.
*/
......@@ -9,15 +10,14 @@ void raise_intr(uint32_t NO, vaddr_t epc) {
cpu.sepc = epc;
cpu.sstatus.spie = cpu.sstatus.sie;
cpu.sstatus.sie = 0;
rtl_li(&s0, cpu.stvec);
rtl_jr(&s0);
rtl_li(s, s0, cpu.stvec);
rtl_jr(s, s0);
}
bool isa_query_intr(void) {
void query_intr(DecodeExecState *s) {
if (cpu.INTR && cpu.sstatus.sie) {
cpu.INTR = false;
raise_intr(0x80000005, cpu.pc);
return true;
raise_intr(s, 0x80000005, cpu.pc);
update_pc(s);
}
return false;
}
#include <cpu/exec.h>
#include "rtl.h"
// decode operand helper
#define make_DopHelper(name) \
void concat(decode_op_, name) (DecodeExecState *s, Operand *op, uint32_t val, bool load_val)
static inline make_DopHelper(i) {
op->type = OP_TYPE_IMM;
op->imm = val;
rtl_li(s, &op->val, op->imm);
print_Dop(op->str, OP_STR_SIZE, "%d", op->imm);
}
static inline make_DopHelper(r) {
op->type = OP_TYPE_REG;
op->reg = val;
if (load_val) {
rtl_lr(s, &op->val, op->reg, 4);
}
print_Dop(op->str, OP_STR_SIZE, "%s", reg_name(op->reg, 4));
}
static inline make_DHelper(I) {
decode_op_r(s, id_src1, s->isa.instr.i.rs1, true);
decode_op_i(s, id_src2, s->isa.instr.i.simm11_0, true);
decode_op_r(s, id_dest, s->isa.instr.i.rd, false);
}
static inline make_DHelper(R) {
decode_op_r(s, id_src1, s->isa.instr.r.rs1, true);
decode_op_r(s, id_src2, s->isa.instr.r.rs2, true);
decode_op_r(s, id_dest, s->isa.instr.r.rd, false);
}
static inline make_DHelper(U) {
decode_op_i(s, id_src1, s->isa.instr.u.imm31_12 << 12, true);
decode_op_r(s, id_dest, s->isa.instr.u.rd, false);
print_Dop(id_src1->str, OP_STR_SIZE, "0x%x", s->isa.instr.u.imm31_12);
}
static inline make_DHelper(J) {
sword_t offset = (s->isa.instr.j.simm20 << 20) | (s->isa.instr.j.imm19_12 << 12) |
(s->isa.instr.j.imm11 << 11) | (s->isa.instr.j.imm10_1 << 1);
s->jmp_pc = cpu.pc + offset;
decode_op_i(s, id_src1, s->jmp_pc, true);
print_Dop(id_src1->str, OP_STR_SIZE, "0x%x", s->jmp_pc);
decode_op_r(s, id_dest, s->isa.instr.j.rd, false);
}
static inline make_DHelper(B) {
sword_t offset = (s->isa.instr.b.simm12 << 12) | (s->isa.instr.b.imm11 << 11) |
(s->isa.instr.b.imm10_5 << 5) | (s->isa.instr.b.imm4_1 << 1);
s->jmp_pc = cpu.pc + offset;
decode_op_i(s, id_dest, s->jmp_pc, true);
print_Dop(id_dest->str, OP_STR_SIZE, "0x%x", s->jmp_pc);
decode_op_r(s, id_src1, s->isa.instr.b.rs1, true);
decode_op_r(s, id_src2, s->isa.instr.b.rs2, true);
}
static inline make_DHelper(ld) {
decode_I(s);
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->val, reg_name(id_src1->reg, 4));
rtl_add(s, &id_src1->addr, dsrc1, dsrc2);
}
static inline make_DHelper(st) {
decode_op_r(s, id_src1, s->isa.instr.s.rs1, true);
sword_t simm = (s->isa.instr.s.simm11_5 << 5) | s->isa.instr.s.imm4_0;
decode_op_i(s, id_src2, simm, true);
decode_op_r(s, id_dest, s->isa.instr.s.rs2, true);
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->val, reg_name(id_src1->reg, 4));
rtl_add(s, &id_src1->addr, dsrc1, dsrc2);
}
static inline make_DHelper(csr) {
decode_op_r(s, id_src1, s->isa.instr.i.rs1, true);
decode_op_i(s, id_src2, s->isa.instr.csr.csr, true);
decode_op_r(s, id_dest, s->isa.instr.i.rd, false);
}
#ifndef __RISCV32_REG_H__
#define __RISCV32_REG_H__
#include "common.h"
#include "memory.h"
#define PC_START (0x80000000u + IMAGE_START)
typedef struct {
union {
rtlreg_t _32;
uint16_t _16[2];
uint8_t _8[4];
} gpr[32];
vaddr_t pc;
vaddr_t stvec;
vaddr_t scause;
vaddr_t sepc;
union {
struct {
uint32_t uie : 1;
uint32_t sie : 1;
uint32_t pad0: 2;
uint32_t upie: 1;
uint32_t spie: 1;
uint32_t pad1: 2;
uint32_t spp : 1;
uint32_t dontcare :21;
};
uint32_t val;
} sstatus;
union {
struct {
uint32_t ppn :22;
uint32_t asid: 9;
uint32_t mode: 1;
};
uint32_t val;
} satp;
bool INTR;
} CPU_state;
#include <common.h>
static inline int check_reg_index(int index) {
assert(index >= 0 && index < 32);
......
#ifndef __RISCV32_RTL_H__
#define __RISCV32_RTL_H__
#include <rtl/rtl.h>
#include "reg.h"
static inline make_rtl(lr, rtlreg_t* dest, int r, int width) {
rtl_mv(s, dest, &reg_l(r));
}
static inline make_rtl(sr, int r, const rtlreg_t *src1, int width) {
if (r != 0) { rtl_mv(s, &reg_l(r), src1); }
}
#endif
#include "nemu.h"
#include "memory/memory.h"
#include <isa.h>
#include <memory/memory.h>
/* the 32bit Page Table Entry(second level page table) data structure */
typedef union PageTableEntry {
......@@ -57,12 +57,17 @@ static inline paddr_t page_translate(vaddr_t addr, bool is_write) {
return page_walk(addr, is_write) | (addr & PAGE_MASK);
}
word_t isa_vaddr_read(vaddr_t addr, int len) {
paddr_t paddr = (cpu.satp.mode ? page_translate(addr, false) : addr);
return paddr_read(paddr, len);
#define make_isa_vaddr_template(bits) \
uint_type(bits) concat(isa_vaddr_read, bits) (vaddr_t addr) { \
paddr_t paddr = (cpu.satp.mode ? page_translate(addr, false) : addr); \
return concat(paddr_read, bits)(paddr); \
} \
void concat(isa_vaddr_write, bits) (vaddr_t addr, uint_type(bits) data) { \
paddr_t paddr = (cpu.satp.mode ? page_translate(addr, true) : addr); \
concat(paddr_write, bits)(paddr, data); \
}
void isa_vaddr_write(vaddr_t addr, word_t data, int len) {
paddr_t paddr = (cpu.satp.mode ? page_translate(addr, true) : addr);
paddr_write(paddr, data, len);
}
make_isa_vaddr_template(8)
make_isa_vaddr_template(16)
make_isa_vaddr_template(32)
make_isa_vaddr_template(64)
#include "nemu.h"
#include <isa.h>
#include "local-include/reg.h"
const char *regsl[] = {
"$0", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
......@@ -11,9 +12,7 @@ void isa_reg_display() {
int i;
for (i = 0; i < 32; i ++) {
printf("%s: 0x%08x ", regsl[i], cpu.gpr[i]._32);
if (i % 4 == 3) {
printf("\n");
}
if (i % 4 == 3) printf("\n");
}
printf("pc: 0x%08x\n", cpu.pc);
}
......@@ -22,14 +21,10 @@ word_t isa_reg_str2val(const char *s, bool *success) {
int i;
*success = true;
for (i = 0; i < 32; i ++) {
if (strcmp(regsl[i], s) == 0) {
return reg_l(i);
}
if (strcmp(regsl[i], s) == 0) return reg_l(i);
}
if (strcmp("pc", s) == 0) {
return cpu.pc;
}
if (strcmp("pc", s) == 0) return cpu.pc;
*success = false;
return 0;
......
......@@ -4,7 +4,7 @@
#define ISA_QEMU_BIN "qemu-system-riscv32"
#define ISA_QEMU_ARGS
#include "../../../../../../src/isa/riscv32/include/isa/diff-test.h"
#include "../../../../src/isa/riscv32/difftest/difftest.h"
union isa_gdb_regs {
struct {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册