提交 d9b19c39 编写于 作者: Z Zihao Yu

riscv64: fix RVC and pass linux

上级 165050f3
......@@ -43,9 +43,9 @@ static inline void update_pc(DecodeExecState *s) {
print_asm(str(instr) "%c %s", suffix_char(id_dest->width), id_dest->str)
#define print_asm_template2(instr) \
print_asm(str(instr) "%c %s,%s", suffix_char(id_dest->width), id_src->str, id_dest->str)
print_asm(str(instr) "%c %s,%s", suffix_char(id_dest->width), id_src1->str, id_dest->str)
#define print_asm_template3(instr) \
print_asm(str(instr) "%c %s,%s,%s", suffix_char(id_dest->width), id_src->str, id_src2->str, id_dest->str)
print_asm(str(instr) "%c %s,%s,%s", suffix_char(id_dest->width), id_src1->str, id_src2->str, id_dest->str)
#endif
......@@ -15,6 +15,6 @@
#define uint_type(bits) concat3(uint, bits, _t)
#define BITMASK(bits) ((1 << (bits)) - 1)
#define BITS(x, hi, lo) (((x) >> (lo)) & BITMASK((hi) - (lo) + 1)) // similar to x[hi:lo] in verilog
#define SEXT(x, len) ({ struct { int64_t n : len; } __x = { .n = x }; __x.n; })
#define SEXT(x, len) ({ struct { int64_t n : len; } __x = { .n = x }; (int64_t)__x.n; })
#endif
#include <monitor/difftest.h>
static inline make_EHelper(jal) {
rtl_addi(s, s0, &cpu.pc, 4);
rtl_li(s, s0, s->seq_pc);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_j(s, s->jmp_pc);
......@@ -13,7 +13,7 @@ static inline make_EHelper(jalr) {
rtl_sr(s, id_dest->reg, s0, 4);
rtl_add(s, s0, dsrc1, dsrc2);
rtl_andi(s, s0, s0, ~0x1u);
rtl_andi(s, s0, s0, ~0x1lu);
rtl_jr(s, s0);
difftest_skip_dut(1, 2);
......
......@@ -39,7 +39,7 @@ static inline make_EHelper(op_imm) {
}
}
static make_EHelper(op_imm32) {
static inline make_EHelper(op_imm32) {
switch (s->isa.instr.i.funct3) {
EX(0, addw) EX(1, sllw) EX(5, srlw)
default: exec_inv(s);
......@@ -63,7 +63,7 @@ static inline make_EHelper(op) {
}
static make_EHelper(op32) {
static inline make_EHelper(op32) {
uint32_t idx = s->isa.instr.r.funct7;
if (idx == 32) idx = 2;
assert(idx <= 2);
......@@ -108,105 +108,70 @@ static inline make_EHelper(atomic) {
cpu.amo = false;
}
static make_EHelper(fp) {
static inline make_EHelper(fp) {
longjmp_raise_intr(EX_II);
}
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) EX (0b00001, fp) EX (0b00011, fence)
IDEX (0b00100, I, op_imm) IDEX (0b00101, U, auipc) IDEX (0b00110, I, op_imm32)
IDEX (0b01000, st, store) EX (0b01001, fp) IDEX (0b01011, R, atomic)
IDEX (0b01100, R, op) IDEX (0b01101, U, lui) IDEX (0b01110, R, op32)
EX (0b10000, fp)
EX (0b10100, fp)
IDEX (0b11000, B, branch) IDEX (0b11001, I, jalr) EX (0b11010, nemu_trap) IDEX (0b11011, J, jal)
EX (0b11100, system)
// RVC
static inline make_EHelper(misc) {
uint32_t instr = s->isa.instr.val;
uint32_t bits12not0 = (BITS(instr, 12, 12) != 0);
uint32_t bits11_7not0 = (BITS(instr, 11, 7) != 0);
uint32_t bits6_2not0 = (BITS(instr, 6, 2) != 0);
uint32_t op = (bits12not0 << 2) | (bits11_7not0 << 1) | bits6_2not0;
switch (op) {
IDEX (0b010, C_JR, jalr)
IDEX (0b011, C_MOV, add)
IDEX (0b110, C_JALR, jalr)
IDEX (0b111, C_ADD, add)
default: exec_inv(s);
}
}
vaddr_t isa_exec_once() {
DecodeExecState s;
s.is_jmp = 0;
s.seq_pc = cpu.pc;
exec(&s);
update_pc(&s);
#if !defined(DIFF_TEST) && !_SHARE
void query_intr(DecodeExecState *s);
query_intr(&s);
#endif
return s.seq_pc;
static inline make_EHelper(lui_addi16sp) {
uint32_t rd = BITS(s->isa.instr.val, 11, 7);
assert(rd != 0);
switch (rd) {
IDEX (2, C_ADDI16SP, add)
default: // and other cases
IDEX (1, CI_simm, lui)
}
}
// RVC
#if 0
static make_EHelper(C_10_100) {
static OpcodeEntry table [8] = {
EMPTY, EMPTY, IDEX(C_rs1_rs2_0, jalr), IDEX(C_0_rs2_rd, add), EMPTY, EMPTY, IDEX(C_JALR, jalr), IDEX(C_rs1_rs2_rd, add),
};
uint32_t cond_c_simm12_not0 = (decinfo.isa.instr.c_simm12 != 0);
uint32_t cond_c_rd_rs1_not0 = (decinfo.isa.instr.c_rd_rs1 != 0);
uint32_t cond_c_rs2_not0 = (decinfo.isa.instr.c_rs2 != 0);
uint32_t idx = (cond_c_simm12_not0 << 2) | (cond_c_rd_rs1_not0 << 1) | cond_c_rs2_not0;
assert(idx < 8);
idex(pc, &table[idx]);
}
static make_EHelper(C_01_011) {
static OpcodeEntry table [2] = { IDEX(C_0_imm_rd, lui), IDEX(C_ADDI16SP, add)};
assert(decinfo.isa.instr.c_rd_rs1 != 0);
int idx = (decinfo.isa.instr.c_rd_rs1 == 2);
idex(pc, &table[idx]);
}
static make_EHelper(C_01_100) {
uint32_t func = decinfo.isa.instr.c_func6 & 0x3;
if (func == 3) {
decode_CR(pc);
static OpcodeEntry table [8] = {
EX(sub), EX(xor), EX(or), EX(and), EX(subw), EX(addw), EMPTY, EMPTY,
};
uint32_t idx2 = (decinfo.isa.instr.c_func6 >> 2) & 0x1;
uint32_t idx1_0 = decinfo.isa.instr.c_func2;
uint32_t idx = (idx2 << 2) | idx1_0;
assert(idx < 8);
idex(pc, &table[idx]);
static inline make_EHelper(misc_alu) {
uint32_t instr = s->isa.instr.val;
uint32_t op = BITS(instr, 11, 10);
if (op == 3) {
uint32_t op2 = (BITS(instr, 12, 12) << 2) | BITS(instr, 6, 5);
switch (op2) {
IDEX (0, CS, sub) IDEX (1, CS, xor) IDEX (2, CS, or) IDEX (3, CS, and)
IDEX (4, CS, subw)IDEX (5, CS, addw)EMPTY(6) EMPTY(7)
}
} else {
decode_C_rs1__imm_rd_(pc);
static OpcodeEntry table [3] = { EX(srl), EX(sra), EX(and) };
idex(pc, &table[func]);
switch (op) {
IDEX (0, CB_shift, srl)
IDEX (1, CB_shift, sra)
IDEX (2, CB_andi, and)
}
}
}
static OpcodeEntry rvc_table [3][8] = {
{IDEX(C_ADDI4SPN, add), EX(fp), IDEXW(C_LW, lds, 4), IDEXW(C_LD, ld, 8), EMPTY, EX(fp), IDEXW(C_SW, st, 4), IDEXW(C_SD, st, 8)},
{IDEX(C_rs1_imm_rd, add), IDEX(C_rs1_imm_rd, addw), IDEX(C_0_imm_rd, add), EX(C_01_011), EX(C_01_100), IDEX(C_J, jal), IDEX(CB, beq), IDEX(CB, bne)},
{IDEX(C_rs1_imm_rd, sll), EX(fp), IDEXW(C_LWSP, lds, 4), IDEXW(C_LDSP, ld, 8), EX(C_10_100), EX(fp), IDEXW(C_SWSP, st, 4), IDEXW(C_SDSP, st, 8)}
};
void isa_exec(vaddr_t *pc) {
static inline void exec(DecodeExecState *s) {
extern jmp_buf intr_buf;
int setjmp_ret;
if ((setjmp_ret = setjmp(intr_buf)) != 0) {
int exception = setjmp_ret - 1;
void raise_intr(word_t, vaddr_t);
raise_intr(exception, cpu.pc);
raise_intr(s, exception, cpu.pc);
return;
}
cpu.fetching = true;
if ((*pc & 0xfff) == 0xffe) {
if ((s->seq_pc & 0xfff) == 0xffe) {
// instruction may accross page boundary
uint32_t lo = instr_fetch(pc, 2);
decinfo.isa.instr.val = lo & 0xffff;
if (decinfo.isa.instr.opcode1_0 != 0x3) {
uint32_t lo = instr_fetch(&s->seq_pc, 2);
s->isa.instr.val = lo & 0xffff;
if (s->isa.instr.r.opcode1_0 != 0x3) {
// this is an RVC instruction
cpu.fetching = false;
goto rvc;
......@@ -215,21 +180,56 @@ void isa_exec(vaddr_t *pc) {
// NOTE: The fetch here may cause IPF.
// If it is the case, we should have mepc = xxxffe and mtval = yyy000.
// Refer to `mtval` in the privileged manual for more details.
uint32_t hi = instr_fetch(pc, 2);
decinfo.isa.instr.val |= ((hi & 0xffff) << 16);
uint32_t hi = instr_fetch(&s->seq_pc, 2);
s->isa.instr.val |= ((hi & 0xffff) << 16);
} else {
// in-page instructions, fetch 4 byte and
// see whether it is an RVC instruction later
decinfo.isa.instr.val = instr_fetch(pc, 4);
s->isa.instr.val = instr_fetch(&s->seq_pc, 4);
}
cpu.fetching = false;
if (decinfo.isa.instr.opcode1_0 == 0x3) {
idex(pc, &opcode_table[decinfo.isa.instr.opcode6_2]);
if (s->isa.instr.r.opcode1_0 == 0x3) {
switch (s->isa.instr.r.opcode6_2) {
IDEX (000, ld, load) EX (001, fp) EX (003, fence)
IDEX (004, I, op_imm) IDEX (005, U, auipc) IDEX (006, I, op_imm32)
IDEX (010, st, store) EX (011, fp) IDEX (013, R, atomic)
IDEX (014, R, op) IDEX (015, U, lui) IDEX (016, R, op32)
EX (020, fp)
EX (024, fp)
IDEX (030, B, branch) IDEX (031, I, jalr) EX (032, nemu_trap) IDEX (033, J, jal)
EX (034, system)
default: exec_inv(s);
}
} else {
// RVC instructions are only 2-byte
*pc -= 2;
rvc:
idex(pc, &rvc_table[decinfo.isa.instr.opcode1_0][decinfo.isa.instr.c_funct3]);
s->seq_pc -= 2;
rvc: ;
//idex(pc, &rvc_table[decinfo.isa.instr.opcode1_0][decinfo.isa.instr.c_funct3]);
uint32_t rvc_opcode = (s->isa.instr.r.opcode1_0 << 3) | BITS(s->isa.instr.val, 15, 13);
switch (rvc_opcode) {
IDEX (000, C_ADDI4SPN, add) EX (001, fp) IDEXW(002, C_LW, lds, 4) IDEXW(003, C_LD, ld, 8)
EX (005, fp) IDEXW(006, C_SW, st, 4) IDEXW(007, C_SD, st, 8)
IDEX (010, CI_simm, add) IDEX (011, CI_simm, addw) IDEX (012, C_LI, add) EX (013, lui_addi16sp)
EX (014, misc_alu) IDEX (015, C_J, jal) IDEX (016, CB, beq) IDEX (017, CB, bne)
IDEX (020, CI_uimm, sll) EX (021, fp) IDEXW(022, C_LWSP, lds, 4)IDEXW(023, C_LDSP, ld, 8)
EX (024, misc) EX (025, fp) IDEXW(026, C_SWSP, st, 4) IDEXW(027, C_SDSP, st, 8)
default: exec_inv(s);
}
}
}
vaddr_t isa_exec_once() {
DecodeExecState s;
s.is_jmp = 0;
s.seq_pc = cpu.pc;
exec(&s);
update_pc(&s);
#if !defined(DIFF_TEST) && !_SHARE
void query_intr(DecodeExecState *s);
query_intr(&s);
#endif
return s.seq_pc;
}
......@@ -35,13 +35,11 @@ static inline make_EHelper(csrrc) {
print_asm_template3("csrrc");
}
extern void raise_intr(word_t NO, vaddr_t epc);
static inline make_EHelper(priv) {
uint32_t type = s->isa.instr.csr.csr;
switch (type) {
case 0:
raise_intr(8 + cpu.mode, cpu.pc);
raise_intr(s, 8 + cpu.mode, cpu.pc);
print_asm("ecall");
break;
case 0x102:
......
......@@ -106,10 +106,10 @@ static inline make_DHelper(csri) {
// rotate without shift, e.g. ror(0bxxxxyy, 6, 2) = 0byyxxxx00
static inline uint32_t ror_imm(uint32_t imm, int len, int r) {
if (r == 0) return imm;
const uint32_t mask = BITMASK(len);
uint32_t lo = imm & (mask << r); // now it is at the right place
uint32_t hi = (imm << (len - r)) & mask;
return (hi | lo);
uint32_t copy = imm | (imm << len);
uint32_t mask = BITMASK(len) << r;
uint32_t res = copy & mask;
return res;
}
static inline void decode_op_C_imm6(DecodeExecState *s, uint32_t imm6, bool sign, int shift, int rotate) {
......@@ -142,23 +142,19 @@ static inline make_DHelper(CR) {
// ---------- CI ----------
static inline make_DHelper(C_CI_simm) {
static inline make_DHelper(CI_simm) {
decode_op_rd_rs1_imm6(s, true, 0, 0, false);
}
// for shift
static inline make_DHelper(C_CI_uimm) {
static inline make_DHelper(CI_uimm) {
decode_op_rd_rs1_imm6(s, false, 0, 0, false);
}
#if 0
static inline make_DHelper(C_LUI) {
decode_op_rd_rs1_imm6(s, true, 0, 0, false);
assert(id_src2->imm != 0);
assert(id_dest->reg != 2);
static inline make_DHelper(C_LI) {
decode_CI_simm(s);
decode_op_r(s, id_src1, 0, true);
}
#endif
static inline make_DHelper(C_ADDI16SP) {
decode_op_r(s, id_src1, 2, true);
......@@ -227,7 +223,7 @@ static inline make_DHelper(C_ADDI4SPN) {
static inline void decode_C_ldst_common(DecodeExecState *s, int rotate, bool is_store) {
uint32_t instr = s->isa.instr.val;
decode_op_r(s, id_src1, creg2reg(BITS(instr, 9, 7)), true);
uint32_t imm5 = (BITS(instr, 12, 10) << 3) | BITS(instr, 6, 5);
uint32_t imm5 = (BITS(instr, 12, 10) << 2) | BITS(instr, 6, 5);
uint32_t imm = ror_imm(imm5, 5, rotate) << 1;
decode_op_i(s, id_src2, imm, true);
rtl_add(s, &id_src1->addr, dsrc1, dsrc2);
......@@ -253,9 +249,7 @@ static inline make_DHelper(C_SD) {
}
static inline make_DHelper(CS) {
uint32_t rd_rs1 = creg2reg(BITS(s->isa.instr.val, 9, 7));
decode_op_r(s, id_src1, rd_rs1, true);
decode_op_r(s, id_dest, rd_rs1, false);
decode_op_C_rd_rs1(s, true);
uint32_t rs2 = creg2reg(BITS(s->isa.instr.val, 4, 2));
decode_op_r(s, id_src2, rs2, true);
}
......@@ -310,45 +304,23 @@ static inline make_DHelper(C_J) {
decode_op_r(s, id_dest, 0, false);
}
#if 0
static void decode_C_xxx_imm_rd(bool is_rs1_zero, bool is_reg_compress) {
int reg = (is_reg_compress ? creg2reg(s->isa.instr.c_rd_rs1_) : s->isa.instr.c_rd_rs1);
decode_op_r(id_src1, (is_rs1_zero ? 0 : reg), true);
sword_t simm = (s->isa.instr.c_simm12 << 5) | s->isa.instr.c_imm6_2;
decode_op_i(id_src2, simm, true);
decode_op_r(id_dest, reg, false);
}
make_DHelper(C_0_imm_rd) {
decode_C_xxx_imm_rd(true, false);
}
make_DHelper(C_rs1_imm_rd) {
decode_C_xxx_imm_rd(false, false);
}
make_DHelper(C_rs1__imm_rd_) {
decode_C_xxx_imm_rd(false, true);
}
static void decode_C_xxx_xxx_xxx(bool is_rs1_zero, bool is_rs2_zero, bool is_rd_zero) {
decode_op_r(id_src1, (is_rs1_zero ? 0 : s->isa.instr.c_rd_rs1), true);
decode_op_r(id_src2, (is_rs2_zero ? 0 : s->isa.instr.c_rs2), true);
decode_op_r(id_dest, (is_rd_zero ? 0 : s->isa.instr.c_rd_rs1), false);
static inline void decode_C_rs1_rs2_rd(DecodeExecState *s, bool is_rs1_zero, bool is_rs2_zero, bool is_rd_zero) {
decode_op_r(s, id_src1, (is_rs1_zero ? 0 : BITS(s->isa.instr.val, 11, 7)), true);
decode_op_r(s, id_src2, (is_rs2_zero ? 0 : BITS(s->isa.instr.val, 6, 2)), true);
decode_op_r(s, id_dest, (is_rd_zero ? 0 : BITS(s->isa.instr.val, 11, 7)), false);
}
make_DHelper(C_0_rs2_rd) {
decode_C_xxx_xxx_xxx(true, false, false);
static inline make_DHelper(C_JR) {
decode_C_rs1_rs2_rd(s, false, false, true);
}
make_DHelper(C_rs1_rs2_0) {
decode_C_xxx_xxx_xxx(false, false, true);
static inline make_DHelper(C_MOV) {
decode_C_rs1_rs2_rd(s, true, false, false);
}
make_DHelper(C_rs1_rs2_rd) {
decode_C_xxx_xxx_xxx(false, false, false);
static inline make_DHelper(C_ADD) {
decode_C_rs1_rs2_rd(s, false, false, false);
}
#endif
static inline make_DHelper(C_JALR) {
decode_op_r(s, id_src1, BITS(s->isa.instr.val, 11, 7), true);
......
#ifndef __INTR_H__
#define __INTR_H__
#include <cpu/decode.h>
enum {
EX_IAM, // instruction address misaligned
EX_IAF, // instruction address fault
......@@ -20,6 +22,7 @@ enum {
EX_SPF, // store/amo page fault
};
void raise_intr(DecodeExecState *s, word_t NO, vaddr_t epc);
void longjmp_raise_intr(uint32_t);
#endif
......@@ -75,7 +75,7 @@ void init_difftest(char *ref_so_file, long img_size, int port) {
"If it is not necessary, you can turn it off in include/common.h.", ref_so_file);
ref_difftest_init(port);
ref_difftest_memcpy_from_dut(IMAGE_START, guest_to_host(IMAGE_START), img_size);
ref_difftest_memcpy_from_dut(IMAGE_START + PMEM_BASE, guest_to_host(IMAGE_START), img_size);
ref_difftest_setregs(&cpu);
}
......
......@@ -36,8 +36,6 @@ static uint32_t initcode[] = {
void init_isa(void) {
return;
// put initcode to QEMU to setup a PMP to permit access to all of memory in S mode
bool ok = gdb_memcpy_to_qemu(0x80000000, initcode, sizeof(initcode));
assert(ok == 1);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册