diff --git a/include/isa/riscv64.h b/include/isa/riscv64.h index adda68b207efe47fa2eeadda7d7c058ceadf1200..a784c47cef1bcb5ee16fd2f8e85d34e81bdf4732 100644 --- a/include/isa/riscv64.h +++ b/include/isa/riscv64.h @@ -11,10 +11,10 @@ typedef struct { union { - rtlreg_t _64; + uint64_t _64; } gpr[32]; - vaddr_t pc; + uint64_t pc; vaddr_t mstatus, mcause, mepc; vaddr_t sstatus, scause, sepc; diff --git a/src/engine/rv64/init.c b/src/engine/rv64/init.c new file mode 100644 index 0000000000000000000000000000000000000000..0359310291b4b6e3b037ecc25deaafd9b861e5d4 --- /dev/null +++ b/src/engine/rv64/init.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +void (*rv64_memcpy_from_frontend)(paddr_t dest, void *src, size_t n) = NULL; +void (*rv64_getregs)(void *c) = NULL; +void (*rv64_setregs)(const void *c) = NULL; +void (*rv64_exec)(uint64_t n) = NULL; + +static void init_rv64_interpreter() { + char so_file[256]; + sprintf(so_file, "%s/build/riscv64-nemu-interpreter-so", getenv("NEMU_HOME")); + + void *handle; + handle = dlopen(so_file, RTLD_LAZY | RTLD_DEEPBIND); + assert(handle); + + rv64_memcpy_from_frontend = dlsym(handle, "difftest_memcpy_from_dut"); + assert(rv64_memcpy_from_frontend); + + rv64_getregs = dlsym(handle, "difftest_getregs"); + assert(rv64_getregs); + + rv64_setregs = dlsym(handle, "difftest_setregs"); + assert(rv64_setregs); + + rv64_exec = dlsym(handle, "difftest_exec"); + assert(rv64_exec); + + void (*rv64_init)(int port) = dlsym(handle, "difftest_init"); + assert(rv64_init); + + void (*rv64_init_device)() = dlsym(handle, "init_device"); + assert(rv64_init_device); + + rv64_init(0); + rv64_init_device(); + rv64_memcpy_from_frontend(0, guest_to_host(0), PMEM_SIZE); +} + +void init_engine() { + init_rv64_interpreter(); +} diff --git a/src/engine/rv64/isa/x86.c b/src/engine/rv64/isa/x86.c new file mode 100644 index 0000000000000000000000000000000000000000..7815beb133af4f0f497808342211870087c0fa84 --- /dev/null +++ b/src/engine/rv64/isa/x86.c @@ -0,0 +1,29 @@ +#include +#include +#include + +uint8_t reg_ptr2idx(DecodeExecState *s, const rtlreg_t* dest) { + rtlreg_t* gpr_start = (rtlreg_t *)cpu.gpr; + rtlreg_t* gpr_end = (void *)gpr_start + sizeof(cpu.gpr); + + if (dest >= gpr_start && dest < gpr_end) + return (dest - gpr_start)|0x10;//from x16 to x23 + +#define CASE(ptr, idx) if (dest == ptr) return idx; + CASE(s0, 2) + CASE(s1, 3) + CASE(t0, 4) + CASE(t1, 5) + CASE(ir, 6) + CASE(dsrc1, 7) + CASE(dsrc2, 8) + CASE(ddest, 9) + CASE(&id_src1->addr, 10) + CASE(&id_src2->addr, 11) + CASE(&id_dest->addr, 12) + CASE(&cpu.CF, 13) + CASE(&cpu.OF, 14) + CASE(&cpu.ZF, 15) + CASE(&cpu.SF, 1) + panic("bad ptr = %p", dest); +} diff --git a/src/engine/rv64/paddr.h b/src/engine/rv64/paddr.h new file mode 100644 index 0000000000000000000000000000000000000000..af45dc7796d95d675907d93866faea7e837c1bcc --- /dev/null +++ b/src/engine/rv64/paddr.h @@ -0,0 +1,54 @@ +#ifndef __PADDR_H__ +#define __PADDR_H__ + +#include + +static inline uint64_t paddr_ifetch(paddr_t addr, int len) { + uint8_t paddr_ifetch8 (paddr_t addr); + uint16_t paddr_ifetch16(paddr_t addr); + uint32_t paddr_ifetch32(paddr_t addr); + uint64_t paddr_ifetch64(paddr_t addr); + switch (len) { + case 1: return paddr_ifetch8 (addr); + case 2: return paddr_ifetch16(addr); + case 4: return paddr_ifetch32(addr); +#ifdef ISA64 + case 8: return paddr_ifetch64(addr); +#endif + default: assert(0); + } +} + +static inline uint64_t paddr_read(paddr_t addr, int len) { + uint8_t paddr_read8 (paddr_t addr); + uint16_t paddr_read16(paddr_t addr); + uint32_t paddr_read32(paddr_t addr); + uint64_t paddr_read64(paddr_t addr); + switch (len) { + case 1: return paddr_read8 (addr); + case 2: return paddr_read16(addr); + case 4: return paddr_read32(addr); +#ifdef ISA64 + case 8: return paddr_read64(addr); +#endif + default: assert(0); + } +} + +static inline void paddr_write(paddr_t addr, uint64_t data, int len) { + void paddr_write8 (paddr_t addr, uint8_t data); + void paddr_write16(paddr_t addr, uint16_t data); + void paddr_write32(paddr_t addr, uint32_t data); + void paddr_write64(paddr_t addr, uint64_t data); + switch (len) { + case 1: paddr_write8 (addr, data); break; + case 2: paddr_write16(addr, data); break; + case 4: paddr_write32(addr, data); break; +#ifdef ISA64 + case 8: paddr_write64(addr, data); break; +#endif + default: assert(0); + } +} + +#endif diff --git a/src/engine/rv64/rtl-basic.h b/src/engine/rv64/rtl-basic.h new file mode 100644 index 0000000000000000000000000000000000000000..f91c875d43c145388990528d766bab1f0a12e3ad --- /dev/null +++ b/src/engine/rv64/rtl-basic.h @@ -0,0 +1,39 @@ +#ifndef __RTL_BASIC_H__ +#define __RTL_BASIC_H__ + +#include + +/* RTL basic instructions */ + +make_rtl(li, rtlreg_t* dest, rtlreg_t imm); +make_rtl(mv, rtlreg_t* dest, const rtlreg_t *src1); +make_rtl(add, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(sub, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(and, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(or, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(xor, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(shl, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(shr, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(sar, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(mul_lo, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(mul_hi, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(imul_lo, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(imul_hi, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(div_q, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(div_r, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(idiv_q, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(idiv_r, rtlreg_t* dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(div64_q, rtlreg_t* dest, const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2); +make_rtl(div64_r, rtlreg_t* dest, const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2); +make_rtl(idiv64_q, rtlreg_t* dest, const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2); +make_rtl(idiv64_r, rtlreg_t* dest, const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2); +make_rtl(lm, rtlreg_t *dest, const rtlreg_t* addr, int len); +make_rtl(sm, const rtlreg_t* addr, const rtlreg_t* src1, int len); +make_rtl(host_lm, rtlreg_t* dest, const void *addr, int len); +make_rtl(host_sm, void *addr, const rtlreg_t *src1, int len); +make_rtl(setrelop, uint32_t relop, rtlreg_t *dest, const rtlreg_t *src1, const rtlreg_t *src2); +make_rtl(j, vaddr_t target); +make_rtl(jr, rtlreg_t *target); +make_rtl(jrelop, uint32_t relop, const rtlreg_t *src1, const rtlreg_t *src2, vaddr_t target); + +#endif diff --git a/src/engine/rv64/rv64-backend/exec.c b/src/engine/rv64/rv64-backend/exec.c new file mode 100644 index 0000000000000000000000000000000000000000..48cbb2a2616fbd10fdafdd4f59934836cb353396 --- /dev/null +++ b/src/engine/rv64/rv64-backend/exec.c @@ -0,0 +1,23 @@ +#include + +extern void (*rv64_memcpy_from_frontend)(paddr_t dest, void *src, size_t n); +extern void (*rv64_getregs)(void *c); +extern void (*rv64_setregs)(const void *c); +extern void (*rv64_exec)(uint64_t n); + +vaddr_t rv64_exec_code(void *code, int nr_instr) { + const paddr_t rv64_start = 0; + // copy code to rv64 interpreter to execute it + rv64_memcpy_from_frontend(rv64_start, code, sizeof(uint32_t) * nr_instr); + + // set rv64.pc + CPU_state r; + rv64_getregs(&r); + r.pc = rv64_start; + rv64_setregs(&r); + + rv64_exec(nr_instr); + + rv64_getregs(&r); + return r.gpr[30]._64; +} diff --git a/src/engine/rv64/rv64-backend/relop.c b/src/engine/rv64/rv64-backend/relop.c new file mode 100644 index 0000000000000000000000000000000000000000..a159a87c0641438a5ad668b839c7ac445b1c6156 --- /dev/null +++ b/src/engine/rv64/rv64-backend/relop.c @@ -0,0 +1,95 @@ +#include +#include +#include "rv_ins_def.h" + +uint8_t reg_ptr2idx(DecodeExecState *s, const rtlreg_t* dest); + +void rv64_relop(DecodeExecState *s, uint32_t relop, + const rtlreg_t* dest, const rtlreg_t* src1, const rtlreg_t* src2) { + uint8_t idx_dest,idx_src1,idx_src2; + idx_dest=reg_ptr2idx(s, dest); + idx_src1=reg_ptr2idx(s, src1); + idx_src2=reg_ptr2idx(s, src2); + switch (relop) { + case RELOP_FALSE: //addi dest,x0,0 + //printf("addi x%d,x0,0\n",idx_dest); + gen_rv64_I_inst(ADDI_OP,idx_dest,ADDI_FUNCT3,0,0); + return; + case RELOP_TRUE: //addi dest,x0,1 + //printf("addi x%d,x0,1\n",idx_dest); + gen_rv64_I_inst(ADDI_OP,idx_dest,ADDI_FUNCT3,0,1); + return; + case RELOP_EQ: + //xor x31,src1,src2 + //sltu dest,x0,x31 + //xori dest,dest,1 + //printf("xor x31,x%d,x%d\n",idx_src1,idx_src2); + //printf("sltu x%d,x0,x31\n",idx_dest); + //printf("xori x%d,x%d,1\n",idx_dest,idx_dest); + gen_rv64_R_inst(XOR_OP,31,XOR_FUNCT3,idx_src1,idx_src2,XOR_FUNCT7); + gen_rv64_R_inst(SLTU_OP,idx_dest,SLTU_FUNCT3,0,31,SLTU_FUNCT7); + gen_rv64_I_inst(XORI_OP,idx_dest,XORI_FUNCT3,idx_dest,1); + return ; + case RELOP_NE: + //xor x31,src1,src2 + //sltu dest,x0,x31 + //printf("xor x31,x%d,x%d\n",idx_src1,idx_src2); + //printf("sltu x%d,x0,x31\n",idx_dest); + gen_rv64_R_inst(XOR_OP,31,XOR_FUNCT3,idx_src1,idx_src2,XOR_FUNCT7); + gen_rv64_R_inst(SLTU_OP,idx_dest,SLTU_FUNCT3,0,31,SLTU_FUNCT7); + return ; + case RELOP_LT: + //slt dest,src1,src2 + //printf("slt x%d,x%d,x%d\n",idx_dest,idx_src1,idx_src2); + gen_rv64_R_inst(SLT_OP,idx_dest,SLT_FUNCT3,idx_src1,idx_src2,SLT_FUNCT7); + return ; + case RELOP_LE: + //slt dest,src2,src1 + //xori dest,dest,1 + //printf("slt x%d,x%d,x%d\n",idx_dest,idx_src2,idx_src1); + //printf("xori x%d,x%d,1\n",idx_dest,idx_dest); + gen_rv64_R_inst(SLT_OP,idx_dest,SLT_FUNCT3,idx_src2,idx_src1,SLT_FUNCT7); + gen_rv64_I_inst(XORI_OP,idx_dest,XORI_FUNCT3,idx_dest,1); + return ; + case RELOP_GT: + //slt dest,src2,src1 + //printf("slt x%d,x%d,x%d\n",idx_dest,idx_src2,idx_src1); + gen_rv64_R_inst(SLT_OP,idx_dest,SLT_FUNCT3,idx_src2,idx_src1,SLT_FUNCT7); + return ; + case RELOP_GE: + //slt dest,src1,src2 + //xori dest,dest,1 + //printf("slt x%d,x%d,x%d\n",idx_dest,idx_src1,idx_src2); + //printf("xori x%d,x%d,1\n",idx_dest,idx_dest); + gen_rv64_R_inst(SLT_OP,idx_dest,SLT_FUNCT3,idx_src1,idx_src2,SLT_FUNCT7); + gen_rv64_I_inst(XORI_OP,idx_dest,XORI_FUNCT3,idx_dest,1); + return ; + case RELOP_LTU: + //sltu dest,src1,src2 + //printf("sltu x%d,x%d,x%d\n",idx_dest,idx_src1,idx_src2); + gen_rv64_R_inst(SLTU_OP,idx_dest,SLTU_FUNCT3,idx_src1,idx_src2,SLTU_FUNCT7); + return ; + case RELOP_LEU: + //sltu dest,src2,src1 + //xori dest,dest,1 + //printf("sltu x%d,x%d,x%d\n",idx_dest,idx_src2,idx_src1); + //printf("xori x%d,x%d,1\n",idx_dest,idx_dest); + gen_rv64_R_inst(SLTU_OP,idx_dest,SLTU_FUNCT3,idx_src2,idx_src1,SLTU_FUNCT7); + gen_rv64_I_inst(XORI_OP,idx_dest,XORI_FUNCT3,idx_dest,1); + return ; + case RELOP_GTU: + //sltu dest,src2,src1 + //printf("sltu x%d,x%d,x%d\n",idx_dest,idx_src2,idx_src1); + gen_rv64_R_inst(SLTU_OP,idx_dest,SLTU_FUNCT3,idx_src2,idx_src1,SLTU_FUNCT7); + return ; + case RELOP_GEU: + //sltu dest,src1,src2 + //xori dest,dest,1 + //printf("sltu x%d,x%d,x%d\n",idx_dest,idx_src1,idx_src2); + //printf("xori x%d,x%d,1\n",idx_dest,idx_dest); + gen_rv64_R_inst(SLTU_OP,idx_dest,SLTU_FUNCT3,idx_src1,idx_src2,SLTU_FUNCT7); + gen_rv64_I_inst(XORI_OP,idx_dest,XORI_FUNCT3,idx_dest,1); + return ; + default: panic("unsupport relop = %d", relop); + } +} diff --git a/src/engine/rv64/rv64-backend/rtl-basic.c b/src/engine/rv64/rv64-backend/rtl-basic.c new file mode 100644 index 0000000000000000000000000000000000000000..fc1f67f90c495d59a2a9429fc3f2f9a895a17a8d --- /dev/null +++ b/src/engine/rv64/rv64-backend/rtl-basic.c @@ -0,0 +1,312 @@ +#include +#include "rv64_op.h" +#include "rv_ins_def.h" + +void rv64_relop(DecodeExecState *s, uint32_t relop, + const rtlreg_t* dest, const rtlreg_t* src1, const rtlreg_t* src2); +uint8_t reg_ptr2idx(DecodeExecState *s, const rtlreg_t* dest); +extern int tran_is_jmp; + +/* RTL basic instructions */ + +make_rtl(li, rtlreg_t* dest, rtlreg_t imm) { + uint8_t idx=reg_ptr2idx(s, dest); + RV_IMM rv_imm; + rv_imm.val = imm; + //lui idx,rv_imm.imm_hi20 + //lui x31,rv_imm.imm_lo12 + //srliw x31,x31,12 + //or idx,idx,x31 + //printf("lui x%d,0x%x\n",idx,rv_imm.imm_31_12); + //printf("lui x31,0x%x\n",rv_imm.imm_11_0); + //printf ("srliw x31,x31,12\n"); + //printf("or x%d,x%d,x31\n",idx,idx); + gen_rv64_U_inst(LUI_OP,idx,rv_imm.imm_31_12); + gen_rv64_U_inst(LUI_OP,31,rv_imm.imm_11_0); + gen_rv64_R_inst(SRLIW_OP,31,SRLIW_FUNCT3,31,12,SRLIW_FUNCT7); + gen_rv64_R_inst(OR_OP,idx,OR_FUNCT3,idx,31,OR_FUNCT7); +} + + +make_rtl(mv, rtlreg_t* dest, const rtlreg_t *src1) { + uint8_t idx_dest,idx_src1; + idx_dest=reg_ptr2idx(s, dest); + idx_src1=reg_ptr2idx(s, src1); + //addiw idx_dest,idx_src1,0 + //printf("addiw x%d,x%d,0\n",idx_dest,idx_src1); + gen_rv64_I_inst(ADDIW_OP,idx_dest,ADDIW_FUNCT3,idx_src1,0); +} + +#define make_rtl_arith_logic(name) \ + make_rtl(name, rtlreg_t* dest, const rtlreg_t* src1, const rtlreg_t* src2) { \ + concat(rv64_, name) (dest, src1, src2); \ + } + +make_rtl_arith_logic(add) +make_rtl_arith_logic(sub) +make_rtl_arith_logic(and) +make_rtl_arith_logic(or) +make_rtl_arith_logic(xor) +make_rtl_arith_logic(shl) +make_rtl_arith_logic(shr) +make_rtl_arith_logic(sar) +make_rtl_arith_logic(mul_lo) +make_rtl_arith_logic(mul_hi) +make_rtl_arith_logic(imul_lo) +make_rtl_arith_logic(imul_hi) +make_rtl_arith_logic(div_q) +make_rtl_arith_logic(div_r) +make_rtl_arith_logic(idiv_q) +make_rtl_arith_logic(idiv_r) + +make_rtl(div64_q, rtlreg_t* dest, + const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2) { + uint8_t idx_dest,idx_src1_hi,idx_src1_lo,idx_src2; + idx_dest=reg_ptr2idx(s, dest); + idx_src1_hi=reg_ptr2idx(s, src1_hi); + idx_src1_lo=reg_ptr2idx(s, src1_lo); + idx_src2=reg_ptr2idx(s, src2); + gen_rv64_R64_inst(SLLI_OP,30,SLLI_FUNCT3,idx_src1_hi,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SLLI_OP,31,SLLI_FUNCT3,idx_src1_lo,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SRLI_OP,31,SRLI_FUNCT3,31,32,SRLI_FUNCT6); + gen_rv64_R_inst(OR_OP,30,OR_FUNCT3,30,31,OR_FUNCT7); + gen_rv64_R64_inst(SLLI_OP,31,SLLI_FUNCT3,idx_src2,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SRLI_OP,31,SRLI_FUNCT3,31,32,SRLI_FUNCT6); + gen_rv64_R_inst(DIVU_OP,idx_dest,DIVU_FUNCT3,30,31,DIVU_FUNCT7); +} + +make_rtl(div64_r, rtlreg_t* dest, + const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2) { + uint8_t idx_dest,idx_src1_hi,idx_src1_lo,idx_src2; + idx_dest=reg_ptr2idx(s, dest); + idx_src1_hi=reg_ptr2idx(s, src1_hi); + idx_src1_lo=reg_ptr2idx(s, src1_lo); + idx_src2=reg_ptr2idx(s, src2); + gen_rv64_R64_inst(SLLI_OP,30,SLLI_FUNCT3,idx_src1_hi,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SLLI_OP,31,SLLI_FUNCT3,idx_src1_lo,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SRLI_OP,31,SRLI_FUNCT3,31,32,SRLI_FUNCT6); + gen_rv64_R_inst(OR_OP,30,OR_FUNCT3,30,31,OR_FUNCT7); + gen_rv64_R64_inst(SLLI_OP,31,SLLI_FUNCT3,idx_src2,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SRLI_OP,31,SRLI_FUNCT3,31,32,SRLI_FUNCT6); + gen_rv64_R_inst(REMU_OP,idx_dest,REMU_FUNCT3,30,31,REMU_FUNCT7); +} + +make_rtl(idiv64_q, rtlreg_t* dest, + const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2) { + uint8_t idx_dest,idx_src1_hi,idx_src1_lo,idx_src2; + idx_dest=reg_ptr2idx(s, dest); + idx_src1_hi=reg_ptr2idx(s, src1_hi); + idx_src1_lo=reg_ptr2idx(s, src1_lo); + idx_src2=reg_ptr2idx(s, src2); + gen_rv64_R64_inst(SLLI_OP,30,SLLI_FUNCT3,idx_src1_hi,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SLLI_OP,31,SLLI_FUNCT3,idx_src1_lo,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SRLI_OP,31,SRLI_FUNCT3,31,32,SRLI_FUNCT6); + gen_rv64_R_inst(OR_OP,30,OR_FUNCT3,30,31,OR_FUNCT7); + gen_rv64_R_inst(DIV_OP,idx_dest,DIV_FUNCT3,30,idx_src2,DIV_FUNCT7); +} + +make_rtl(idiv64_r, rtlreg_t* dest, + const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2) { + uint8_t idx_dest,idx_src1_hi,idx_src1_lo,idx_src2; + idx_dest=reg_ptr2idx(s, dest); + idx_src1_hi=reg_ptr2idx(s, src1_hi); + idx_src1_lo=reg_ptr2idx(s, src1_lo); + idx_src2=reg_ptr2idx(s, src2); + gen_rv64_R64_inst(SLLI_OP,30,SLLI_FUNCT3,idx_src1_hi,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SLLI_OP,31,SLLI_FUNCT3,idx_src1_lo,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SRLI_OP,31,SRLI_FUNCT3,31,32,SRLI_FUNCT6); + gen_rv64_R_inst(OR_OP,30,OR_FUNCT3,30,31,OR_FUNCT7); + gen_rv64_R_inst(REM_OP,idx_dest,REM_FUNCT3,30,idx_src2,REM_FUNCT7); +} +//memory access +//lm sm need to suppose addr is unsigned +make_rtl(lm, rtlreg_t *dest, const rtlreg_t* addr, int len) { + uint8_t idx_dest,idx_addr; + idx_dest=reg_ptr2idx(s, dest); + idx_addr=reg_ptr2idx(s, addr); + //printf("slli x31,x%d,32\n",idx_addr); + //printf("srli x31,x31,32\n"); + gen_rv64_R64_inst(SLLI_OP,31,SLLI_FUNCT3,idx_addr,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SRLI_OP,31,SRLI_FUNCT3,31,32,SRLI_FUNCT6); + switch (len) + { + case 1: + //lb dest,addr + //printf("lb x%d,0(x31)\n",idx_dest); + gen_rv64_I_inst(LBU_OP,idx_dest,LBU_FUNCT3,31,0); + break; + case 2: + //lh dest,addr + //printf("lh x%d,0(x31)\n",idx_dest); + gen_rv64_I_inst(LHU_OP,idx_dest,LHU_FUNCT3,31,0); + break; + default://4 + //lw dest,addr + //printf("lw x%d,0(x31)\n",idx_dest); + gen_rv64_I_inst(LW_OP,idx_dest,LW_FUNCT3,31,0); + break; + } +} + +make_rtl(sm, const rtlreg_t* addr, const rtlreg_t* src1, int len) { + uint8_t idx_addr,idx_src1; + idx_addr=reg_ptr2idx(s, addr); + idx_src1=reg_ptr2idx(s, src1); + //printf("slli x31,x%d,32\n",idx_addr); + //printf("srli x31,x31,32\n"); + gen_rv64_R64_inst(SLLI_OP,31,SLLI_FUNCT3,idx_addr,32,SLLI_FUNCT6); + gen_rv64_R64_inst(SRLI_OP,31,SRLI_FUNCT3,31,32,SRLI_FUNCT6); + switch (len) + { + case 1: + //sb addr,src1 + //printf("sb x%d,0(x31)\n",idx_src1); + gen_rv64_S_inst(SB_OP,SB_FUNCT3,31,idx_src1,0); + break; + case 2: + //sh addr,src1 + //printf("sh x%d,0(x31)\n",idx_src1); + gen_rv64_S_inst(SH_OP,SH_FUNCT3,31,idx_src1,0); + break; + default://4 + //sw addr,src1 + //printf("sw x%d,0(x31)\n",idx_src1); + gen_rv64_S_inst(SW_OP,SW_FUNCT3,31,idx_src1,0); + break; + } +} + +//host memory access +//we can ignore this impl +make_rtl(host_lm, rtlreg_t* dest, const void *addr, int len) { + uint8_t idx_dest=reg_ptr2idx(s, dest); + + // we assume that `addr` is only from cpu.gpr in x86 + uintptr_t addr_align = (uintptr_t)addr & ~(sizeof(rtlreg_t) - 1); + uint8_t idx_r = reg_ptr2idx(s, (void *)addr_align); + switch (len) { + case 1: + if((uintptr_t)addr & 1){//high + //slli dest,r,48 + //srli dest,dest,56 + //printf("slli x%d,x%d,48\n",idx_dest,idx_r); + //printf("srli x%d,x%d,56\n",idx_dest,idx_dest); + gen_rv64_R64_inst(SLLI_OP,idx_dest,SLLI_FUNCT3,idx_r,48,SLLI_FUNCT6); + gen_rv64_R64_inst(SRLI_OP,idx_dest,SRLI_FUNCT3,idx_dest,56,SRLI_FUNCT6); + }else{//low + //slli dest,r,56 + //srli dest,dest,56 + //printf("slli x%d,x%d,56\n",idx_dest,idx_r); + //printf("srli x%d,x%d,56\n",idx_dest,idx_dest); + gen_rv64_R64_inst(SLLI_OP,idx_dest,SLLI_FUNCT3,idx_r,56,SLLI_FUNCT6); + gen_rv64_R64_inst(SRLI_OP,idx_dest,SRLI_FUNCT3,idx_dest,56,SRLI_FUNCT6); + } + return; + case 2: + //slli dest,r,48 + //srli dest,dest,48 + //printf("slli x%d,x%d,48\n",idx_dest,idx_r); + //printf("srli x%d,x%d,48\n",idx_dest,idx_dest); + gen_rv64_R64_inst(SLLI_OP,idx_dest,SLLI_FUNCT3,idx_r,48,SLLI_FUNCT6); + gen_rv64_R64_inst(SRLI_OP,idx_dest,SRLI_FUNCT3,idx_dest,48,SRLI_FUNCT6); + return; + default: assert(0); + } +} + +make_rtl(host_sm, void *addr, const rtlreg_t *src1, int len) { + uint8_t idx_src1=reg_ptr2idx(s, src1); + + // we assume that `addr` is only from cpu.gpr in x86 + uintptr_t addr_align = (uintptr_t)addr & ~(sizeof(rtlreg_t) - 1); + uint8_t idx_r = reg_ptr2idx(s, (void *)addr_align); + switch (len) { + case 1: + if((uintptr_t)addr & 1){//high + //addi x31,x0,0xff + //slliw x31,x31,8 + //slliw x30,src1,8 + //and x30,x30,x31 + //xori x31,x31,-1 + //and r,r,x31 + //or r,r,x30 + //printf("addi x31,x0,0xff\n"); + //printf("slliw x31,x31,8\n"); + //printf("slliw x30,x%d,8\n",idx_src1); + //printf("and x30,x30,x31\n"); + //printf("xori x31,x31,-1\n"); + //printf("and x%d,x%d,x31\n",idx_r,idx_r); + //printf("or x%d,x%d,x30\n",idx_r,idx_r); + gen_rv64_I_inst(ADDI_OP,31,ADDI_FUNCT3,0,0xff); + gen_rv64_R_inst(SLLIW_OP,31,SLLIW_FUNCT3,31,8,SLLIW_FUNCT7); + gen_rv64_R_inst(SLLIW_OP,30,SLLIW_FUNCT3,idx_src1,8,SLLIW_FUNCT7); + gen_rv64_R_inst(AND_OP,30,AND_FUNCT3,30,31,AND_FUNCT7); + gen_rv64_I_inst(XORI_OP,31,XOR_FUNCT3,31,-1); + gen_rv64_R_inst(AND_OP,idx_r,AND_FUNCT3,idx_r,31,AND_FUNCT7); + gen_rv64_R_inst(OR_OP,idx_r,OR_FUNCT3,idx_r,30,OR_FUNCT7); + }else{//low + //addi x31,x0,0xff + //xori x30,x0,-1 + //and x31,x31,src1 + //andi x30,x30,r + //or dest,x30,x31 + //printf("addi x31,x0,0xff\n"); + //printf("xori x30,x0,-1\n"); + //printf("and x31,x31,x%d\n",idx_src1); + //printf("and x30,x30,x%d\n",idx_r); + //printf("or x%d,x30,x31\n",idx_r); + gen_rv64_I_inst(ADDI_OP,31,ADDI_FUNCT3,0,0xff); + gen_rv64_I_inst(XORI_OP,30,XOR_FUNCT3,31,-1); + gen_rv64_R_inst(AND_OP,31,AND_FUNCT3,31,idx_src1,AND_FUNCT7); + gen_rv64_R_inst(AND_OP,30,AND_FUNCT3,30,idx_r,AND_FUNCT7); + gen_rv64_R_inst(OR_OP,idx_r,OR_FUNCT3,30,31,OR_FUNCT7); + } + return; + case 2: + //lui x31,0xffff0 + //xori x30,x31,-1 + //and x31,x31,r + //and x30,x30,src1 + //or r,x30,x31 + //printf("lui x31,0xffff0\n"); + //printf("xori x30,x0,-1\n"); + //printf("and x31,x31,x%d\n",idx_r); + //printf("and x30,x30,x%d\n",idx_src1); + //printf("or x%d,x30,x31\n",idx_r); + gen_rv64_U_inst(LUI_OP,31,0xffff0); + gen_rv64_I_inst(XORI_OP,30,XOR_FUNCT3,31,-1); + gen_rv64_R_inst(AND_OP,31,AND_FUNCT3,31,idx_r,AND_FUNCT7); + gen_rv64_R_inst(AND_OP,30,AND_FUNCT3,30,idx_src1,AND_FUNCT7); + gen_rv64_R_inst(OR_OP,idx_r,OR_FUNCT3,30,31,OR_FUNCT7); + return; + default: assert(0); + } +} + +//relop +make_rtl(setrelop, uint32_t relop, rtlreg_t *dest, const rtlreg_t *src1, const rtlreg_t *src2) { + rv64_relop(s, relop, dest, src1, src2); +} + +#define NEXT_BB_RV64_REG 30 + +//jump +make_rtl(j, vaddr_t target) { + rtl_li(s, ir, target); + gen_rv64_I_inst(ADDI_OP,NEXT_BB_RV64_REG,ADDI_FUNCT3,reg_ptr2idx(s, ir),0); + tran_is_jmp = true; +} + +make_rtl(jr, rtlreg_t *target) { + gen_rv64_I_inst(ADDI_OP,NEXT_BB_RV64_REG,ADDI_FUNCT3,reg_ptr2idx(s, target),0); + tran_is_jmp = true; +} + +make_rtl(jrelop, uint32_t relop, const rtlreg_t *src1, const rtlreg_t *src2, vaddr_t target) { + rtl_setrelop(s, relop, ddest, src1, src2); + rtl_li(s, dsrc1, target); + rtl_li(s, dsrc2, s->seq_pc); + rtl_mux(s, ddest, ddest, dsrc1, dsrc2); + gen_rv64_I_inst(ADDI_OP,NEXT_BB_RV64_REG,ADDI_FUNCT3,reg_ptr2idx(s, ddest),0); + tran_is_jmp = true; +} diff --git a/src/engine/rv64/rv64-backend/rv64_op.h b/src/engine/rv64/rv64-backend/rv64_op.h new file mode 100644 index 0000000000000000000000000000000000000000..0d3c659145782b73d1de22b747444d08d9588405 --- /dev/null +++ b/src/engine/rv64/rv64-backend/rv64_op.h @@ -0,0 +1,149 @@ +#ifndef __RV64_OP_H__ +#define __RV64_OP_H__ +#include "rv_ins_def.h" + +#define rv64_add(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*add c_idx,a_idx,b_idx*/ \ + /*printf("add x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(ADD_OP,c_idx,ADD_FUNCT3,a_idx,b_idx,ADD_FUNCT7); \ + }while(0) +#define rv64_sub(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*sub c_idx,a_idx,b_idx*/ \ + /*printf("sub x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(SUB_OP,c_idx,SUB_FUNCT3,a_idx,b_idx,SUB_FUNCT7); \ + }while(0) +#define rv64_and(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*and c_idx,a_idx,b_idx*/ \ + /*printf("and x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(AND_OP,c_idx,AND_FUNCT3,a_idx,b_idx,AND_FUNCT7); \ + }while(0) +#define rv64_or(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*or c_idx,a_idx,b_idx*/ \ + /*printf("or x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(OR_OP,c_idx,OR_FUNCT3,a_idx,b_idx,OR_FUNCT7); \ + }while(0) +#define rv64_xor(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*xor c_idx,a_idx,b_idx*/ \ + /*printf("xor x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(XOR_OP,c_idx,XOR_FUNCT3,a_idx,b_idx,XOR_FUNCT7); \ + }while(0) +#define rv64_shl(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*sllw c_idx,a_idx,b_idx*/ \ + /*printf("sllw x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(SLLW_OP,c_idx,SLLW_FUNCT3,a_idx,b_idx,SLLW_FUNCT7); \ + }while(0) +#define rv64_shr(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*srlw c_idx,a_idx,b_idx*/ \ + /*printf("srlw x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(SRLW_OP,c_idx,SRLW_FUNCT3,a_idx,b_idx,SRLW_FUNCT7); \ + }while(0) +#define rv64_sar(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*sraw c_idx,a_idx,b_idx*/ \ + /*printf("sraw x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(SRAW_OP,c_idx,SRAW_FUNCT3,a_idx,b_idx,SRAW_FUNCT7); \ + }while(0) + +#define rv64_mul_lo(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*mulw c_idx,a_idx,b_idx*/ \ + /*printf("mulw x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(MULW_OP,c_idx,MULW_FUNCT3,a_idx,b_idx,MULW_FUNCT7); \ + }while(0) +#define rv64_imul_lo(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*mulw c_idx,a_idx,b_idx*/ \ + /*printf("mulw x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(MULW_OP,c_idx,MULW_FUNCT3,a_idx,b_idx,MULW_FUNCT7); \ + }while(0) +#ifdef ISA64 +# define rv64_mul_hi(c, a, b) TODO() +# define rv64_imul_hi(c, a, b) TODO() +#else +# define rv64_mul_hi(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*mulw c_idx,a_idx,b_idx*/ \ + /*printf("mulw x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R64_inst(SLLI_OP,30,SLLI_FUNCT3,a_idx,32,SLLI_FUNCT6); \ + gen_rv64_R64_inst(SRLI_OP,30,SRLI_FUNCT3,30,32,SRLI_FUNCT6); \ + gen_rv64_R64_inst(SLLI_OP,31,SLLI_FUNCT3,b_idx,32,SLLI_FUNCT6); \ + gen_rv64_R64_inst(SRLI_OP,31,SRLI_FUNCT3,31,32,SRLI_FUNCT6); \ + gen_rv64_R_inst(MUL_OP,c_idx,MUL_FUNCT3,30,31,MUL_FUNCT7); \ + gen_rv64_R64_inst(SRAI_OP,c_idx,SRAI_FUNCT3,c_idx,32,SRAI_FUNCT6); \ + }while(0) +# define rv64_imul_hi(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*mul c_idx,a_idx,b_idx*/ \ + /*srai c_idx,c_idx,32*/ \ + /*printf("mul x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + /*printf("srai x%d,x%d,0x20\n",c_idx,c_idx);*/ \ + gen_rv64_R_inst(MUL_OP,c_idx,MUL_FUNCT3,a_idx,b_idx,MUL_FUNCT7); \ + gen_rv64_R64_inst(SRAI_OP,c_idx,SRAI_FUNCT3,c_idx,32,SRAI_FUNCT6); \ + }while(0) +#endif + +#define rv64_div_q(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*divuw c_idx,a_idx,b_idx*/ \ + /*printf("divuw x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(DIVUW_OP,c_idx,DIVUW_FUNCT3,a_idx,b_idx,DIVUW_FUNCT7); \ + }while(0) +#define rv64_div_r(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*remuw c_idx,a_idx,b_idx*/ \ + /*printf("remuw x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(REMUW_OP,c_idx,REMUW_FUNCT3,a_idx,b_idx,REMUW_FUNCT7); \ + }while(0) +#define rv64_idiv_q(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*divw c_idx,a_idx,b_idx*/ \ + /*printf("divw x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(DIVW_OP,c_idx,DIVW_FUNCT3,a_idx,b_idx,DIVW_FUNCT7); \ + }while(0) +#define rv64_idiv_r(c, a, b) do{ \ + uint8_t a_idx = reg_ptr2idx(s, a); \ + uint8_t b_idx = reg_ptr2idx(s, b); \ + uint8_t c_idx = reg_ptr2idx(s, c); \ + /*remw c_idx,a_idx,b_idx*/ \ + /*printf("remw x%d,x%d,x%d\n",c_idx,a_idx,b_idx);*/ \ + gen_rv64_R_inst(REMW_OP,c_idx,REMW_FUNCT3,a_idx,b_idx,REMW_FUNCT7); \ + }while(0) + +#endif diff --git a/src/engine/rv64/rv64-backend/rv_ins_def.h b/src/engine/rv64/rv64-backend/rv_ins_def.h new file mode 100644 index 0000000000000000000000000000000000000000..3a8be3abb6733e646a0d4ab80f679b352fba5b15 --- /dev/null +++ b/src/engine/rv64/rv64-backend/rv_ins_def.h @@ -0,0 +1,377 @@ +#ifndef _RV_INS_DEF_ +#define _RV_INS_DEF_ +#define BEQ_OP 0b1100011 +#define BEQ_FUNCT3 0b000 +#define BNE_OP 0b1100011 +#define BNE_FUNCT3 0b001 +#define BLT_OP 0b1100011 +#define BLT_FUNCT3 0b100 +#define BGE_OP 0b1100011 +#define BGE_FUNCT3 0b101 +#define BLTU_OP 0b1100011 +#define BLTU_FUNCT3 0b110 +#define BGEU_OP 0b1100011 +#define BGEU_FUNCT3 0b111 +#define JALR_OP 0b1100111 +#define JALR_FUNCT3 0b000 +#define JAL_OP 0b1101111 +#define LUI_OP 0b0110111 +#define AUIPC_OP 0b0010111 +#define ADDI_OP 0b0010011 +#define ADDI_FUNCT3 0b000 +#define SLLI_OP 0b0010011 +#define SLLI_FUNCT6 0b000000 +#define SLLI_FUNCT3 0b001 +#define SLTI_OP 0b0010011 +#define SLTI_FUNCT3 0b010 +#define SLTIU_OP 0b0010011 +#define SLTIU_FUNCT3 0b011 +#define XORI_OP 0b0010011 +#define XORI_FUNCT3 0b100 +#define SRLI_OP 0b0010011 +#define SRLI_FUNCT6 0b000000 +#define SRLI_FUNCT3 0b101 +#define SRAI_OP 0b0010011 +#define SRAI_FUNCT6 0b010000 +#define SRAI_FUNCT3 0b101 +#define ORI_OP 0b0010011 +#define ORI_FUNCT3 0b110 +#define ANDI_OP 0b0010011 +#define ANDI_FUNCT3 0b111 +#define ADD_OP 0b0110011 +#define ADD_FUNCT7 0b0000000 +#define ADD_FUNCT3 0b000 +#define SUB_OP 0b0110011 +#define SUB_FUNCT7 0b0100000 +#define SUB_FUNCT3 0b000 +#define SLL_OP 0b0110011 +#define SLL_FUNCT7 0b0000000 +#define SLL_FUNCT3 0b001 +#define SLT_OP 0b0110011 +#define SLT_FUNCT7 0b0000000 +#define SLT_FUNCT3 0b010 +#define SLTU_OP 0b0110011 +#define SLTU_FUNCT7 0b0000000 +#define SLTU_FUNCT3 0b011 +#define XOR_OP 0b0110011 +#define XOR_FUNCT7 0b0000000 +#define XOR_FUNCT3 0b100 +#define SRL_OP 0b0110011 +#define SRL_FUNCT7 0b0000000 +#define SRL_FUNCT3 0b101 +#define SRA_OP 0b0110011 +#define SRA_FUNCT7 0b0100000 +#define SRA_FUNCT3 0b101 +#define OR_OP 0b0110011 +#define OR_FUNCT7 0b0000000 +#define OR_FUNCT3 0b110 +#define AND_OP 0b0110011 +#define AND_FUNCT7 0b0000000 +#define AND_FUNCT3 0b111 +#define ADDIW_OP 0b0011011 +#define ADDIW_FUNCT3 0b000 +#define SLLIW_OP 0b0011011 +#define SLLIW_FUNCT7 0b0000000 +#define SLLIW_FUNCT3 0b001 +#define SRLIW_OP 0b0011011 +#define SRLIW_FUNCT7 0b0000000 +#define SRLIW_FUNCT3 0b101 +#define SRAIW_OP 0b0011011 +#define SRAIW_FUNCT7 0b0100000 +#define SRAIW_FUNCT3 0b101 +#define ADDW_OP 0b0111011 +#define ADDW_FUNCT7 0b0000000 +#define ADDW_FUNCT3 0b000 +#define SUBW_OP 0b0111011 +#define SUBW_FUNCT7 0b0100000 +#define SUBW_FUNCT3 0b000 +#define SLLW_OP 0b0111011 +#define SLLW_FUNCT7 0b0000000 +#define SLLW_FUNCT3 0b001 +#define SRLW_OP 0b0111011 +#define SRLW_FUNCT7 0b0000000 +#define SRLW_FUNCT3 0b101 +#define SRAW_OP 0b0111011 +#define SRAW_FUNCT7 0b0100000 +#define SRAW_FUNCT3 0b101 +#define LB_OP 0b0000011 +#define LB_FUNCT3 0b000 +#define LH_OP 0b0000011 +#define LH_FUNCT3 0b001 +#define LW_OP 0b0000011 +#define LW_FUNCT3 0b010 +#define LD_OP 0b0000011 +#define LD_FUNCT3 0b011 +#define LBU_OP 0b0000011 +#define LBU_FUNCT3 0b100 +#define LHU_OP 0b0000011 +#define LHU_FUNCT3 0b101 +#define LWU_OP 0b0000011 +#define LWU_FUNCT3 0b110 +#define SB_OP 0b0100011 +#define SB_FUNCT3 0b000 +#define SH_OP 0b0100011 +#define SH_FUNCT3 0b001 +#define SW_OP 0b0100011 +#define SW_FUNCT3 0b010 +#define SD_OP 0b0100011 +#define SD_FUNCT3 0b011 +#define FENCE_OP 0b0001111 +#define FENCE_FUNCT3 0b000 +#define FENCE_I_OP 0b0001111 +#define FENCE_I_FUNCT3 0b001 +#define MUL_OP 0b0110011 +#define MUL_FUNCT7 0b0000001 +#define MUL_FUNCT3 0b000 +#define MULH_OP 0b0110011 +#define MULH_FUNCT7 0b0000001 +#define MULH_FUNCT3 0b001 +#define MULHSU_OP 0b0110011 +#define MULHSU_FUNCT7 0b0000001 +#define MULHSU_FUNCT3 0b010 +#define MULHU_OP 0b0110011 +#define MULHU_FUNCT7 0b0000001 +#define MULHU_FUNCT3 0b011 +#define DIV_OP 0b0110011 +#define DIV_FUNCT7 0b0000001 +#define DIV_FUNCT3 0b100 +#define DIVU_OP 0b0110011 +#define DIVU_FUNCT7 0b0000001 +#define DIVU_FUNCT3 0b101 +#define REM_OP 0b0110011 +#define REM_FUNCT7 0b0000001 +#define REM_FUNCT3 0b110 +#define REMU_OP 0b0110011 +#define REMU_FUNCT7 0b0000001 +#define REMU_FUNCT3 0b111 +#define MULW_OP 0b0111011 +#define MULW_FUNCT7 0b0000001 +#define MULW_FUNCT3 0b000 +#define DIVW_OP 0b0111011 +#define DIVW_FUNCT7 0b0000001 +#define DIVW_FUNCT3 0b100 +#define DIVUW_OP 0b0111011 +#define DIVUW_FUNCT7 0b0000001 +#define DIVUW_FUNCT3 0b101 +#define REMW_OP 0b0111011 +#define REMW_FUNCT7 0b0000001 +#define REMW_FUNCT3 0b110 +#define REMUW_OP 0b0111011 +#define REMUW_FUNCT7 0b0000001 +#define REMUW_FUNCT3 0b111 +#define ECALL 0b00000000000000000000000001110011 +#define EBREAK 0b00000000000100000000000001110011 +#define CSRRW_OP 0b1110011 +#define CSRRW_FUNCT3 0b001 +#define CSRRS_OP 0b1110011 +#define CSRRS_FUNCT3 0b010 +#define CSRRC_OP 0b1110011 +#define CSRRC_FUNCT3 0b011 +#define CSRRWI_OP 0b1110011 +#define CSRRWI_FUNCT3 0b101 +#define CSRRSI_OP 0b1110011 +#define CSRRSI_FUNCT3 0b110 +#define CSRRCI_OP 0b1110011 +#define CSRRCI_FUNCT3 0b111 + +typedef union +{ + struct + { + uint32_t imm_11_0 :12; + uint32_t imm_31_12 :20; + }; + struct + { + uint32_t imm_4_0 :5; + uint32_t imm_11_5 :7; + uint32_t pad_1 :20; + }; + struct + { + uint32_t imm_0 :1; + uint32_t imm_4_1 :4; + uint32_t imm_10_5 :6; + uint32_t imm_11 :1; + uint32_t imm_12 :1; + uint32_t pad_2 :20; + }; + struct + { + uint32_t imm_20_l :20; + uint32_t pad_3 :12; + }; + struct + { + uint32_t imm_0_0 :1; + uint32_t imm_10_1 :10; + uint32_t imm_11_11 :1; + uint32_t imm_19_12 :8; + uint32_t imm_20 :1; + uint32_t pad_4 :11; + }; + struct + { + uint32_t imm_5_0 :6; + uint32_t pad_5 :26; + }; + uint32_t val; +}RV_IMM; + + +typedef union { + struct { + uint32_t R_opcode :7; + uint32_t R_rd :5; + uint32_t R_funct3 :3; + uint32_t R_rs1 :5; + uint32_t R_rs2 :5; + uint32_t R_funct7 :7; + }; + struct { + uint32_t I_opcode :7; + uint32_t I_rd :5; + uint32_t I_funct3 :3; + uint32_t I_rs1 :5; + uint32_t I_imm_11_0:12; + }; + struct { + uint32_t S_opcode :7; + uint32_t S_imm_4_0 :5; + uint32_t S_funct3 :3; + uint32_t S_rs1 :5; + uint32_t S_rs2 :5; + uint32_t S_imm_11_5 :7; + }; + struct { + uint32_t B_opcode :7; + uint32_t B_imm_11 :1; + uint32_t B_imm_4_1 :4; + uint32_t B_funct3 :3; + uint32_t B_rs1 :5; + uint32_t B_rs2 :5; + uint32_t B_imm_10_5 :6; + uint32_t B_imm_12 :1; + }; + struct { + uint32_t U_opcode :7; + uint32_t U_rd :5; + uint32_t U_imm_20_h :20; + }; + struct { + uint32_t J_opcode :7; + uint32_t J_rd :5; + uint32_t J_imm_19_12:8; + uint32_t J_imm_11 :1; + uint32_t J_imm_10_1 :10; + uint32_t J_imm_20 :1; + }; + struct { + uint32_t R64_opcode :7; + uint32_t R64_rd :5; + uint32_t R64_funct3 :3; + uint32_t R64_rs1 :5; + uint32_t R64_shamt :6; + uint32_t R64_funct6 :6; + }; + struct { + uint32_t CSR_opcode :7; + uint32_t CSR_rd :5; + uint32_t CSR_funct3 :3; + uint32_t CSR_rs1_imm :5; + uint32_t CSR_csr :11; + }; + uint32_t val; +} RV64_ins; + +void write_ins(uint32_t ins); + +static inline void gen_rv64_R_inst(uint8_t opcode,uint8_t rd,uint8_t funct3,uint8_t rs1,uint8_t rs2,uint8_t funct7){ + RV64_ins ins; + ins.R_opcode=opcode; + ins.R_rd=rd; + ins.R_funct3=funct3; + ins.R_rs1=rs1; + ins.R_rs2=rs2; + ins.R_funct7=funct7; + write_ins(ins.val); +} +static inline void gen_rv64_I_inst(uint8_t opcode,uint8_t rd,uint8_t funct3,uint8_t rs1,uint32_t imm){ + RV64_ins ins; + RV_IMM i; + i.val=imm; + ins.I_opcode=opcode; + ins.I_rd=rd; + ins.I_funct3=funct3; + ins.I_rs1=rs1; + ins.I_imm_11_0=i.imm_11_0; + write_ins(ins.val); +} +static inline void gen_rv64_S_inst(uint8_t opcode,uint8_t funct3,uint8_t rs1,uint8_t rs2,uint32_t imm){ + RV64_ins ins; + RV_IMM i; + i.val=imm; + ins.S_opcode=opcode; + ins.S_funct3=funct3; + ins.S_rs1=rs1; + ins.S_rs2=rs2; + ins.S_imm_4_0=i.imm_4_0; + ins.S_imm_11_5=i.imm_11_5; + write_ins(ins.val); +} +static inline void gen_rv64_B_inst(uint8_t opcode,uint8_t funct3,uint8_t rs1,uint8_t rs2,uint32_t imm){ + RV64_ins ins; + RV_IMM i; + i.val=imm; + ins.B_opcode=opcode; + ins.B_funct3=funct3; + ins.B_rs1=rs1; + ins.B_rs2=rs2; + ins.B_imm_11 = i.imm_11; + ins.B_imm_4_1 = i.imm_4_1; + ins.B_imm_10_5 = i.imm_10_5; + ins.B_imm_12=i.imm_12; + write_ins(ins.val); +} +//when using gen U, we assumed that the real imm is in the lower 20bit of imm(input) +static inline void gen_rv64_U_inst(uint8_t opcode,uint8_t rd,uint32_t imm){ + RV64_ins ins; + RV_IMM i; + i.val=imm; + ins.U_opcode=opcode; + ins.U_rd=rd; + ins.U_imm_20_h=i.imm_20_l; + write_ins(ins.val); +} +static inline void gen_rv64_J_inst(uint8_t opcode,uint8_t rd,uint32_t imm){ + RV64_ins ins; + RV_IMM i; + i.val=imm; + ins.J_opcode=opcode; + ins.J_rd=rd; + ins.J_imm_19_12=i.imm_19_12; + ins.J_imm_11=i.imm_11_11; + ins.J_imm_10_1=i.imm_10_1; + ins.J_imm_20=i.imm_20; + write_ins(ins.val); +} +static inline void gen_rv64_R64_inst(uint8_t opcode,uint8_t rd,uint8_t funct3,uint8_t rs1,uint8_t shamt,uint8_t funct6){ + RV64_ins ins; + ins.R64_opcode=opcode; + ins.R64_rd=rd; + ins.R64_funct3=funct3; + ins.R64_rs1=rs1; + ins.R64_shamt=shamt; + ins.R64_funct6=funct6; + write_ins(ins.val); +} +static inline void gen_rv64_CSR_inst(uint8_t opcode,uint8_t rd,uint8_t funct3,uint8_t rs1_imm,uint32_t csr){ + RV64_ins ins; + ins.CSR_opcode=opcode; + ins.CSR_rd=rd; + ins.CSR_funct3=funct3; + ins.CSR_rs1_imm=rs1_imm; + ins.CSR_csr=csr; + write_ins(ins.val); +} +#endif diff --git a/src/engine/rv64/tran.c b/src/engine/rv64/tran.c new file mode 100644 index 0000000000000000000000000000000000000000..d6b4143496633820094b3bd66ea872b2f8abd07b --- /dev/null +++ b/src/engine/rv64/tran.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +#define BUF_SIZE 13000 //8192 + +uint32_t trans_buffer[BUF_SIZE] = {}; +int trans_buffer_index = 0; +int tran_is_jmp = false; + +static void clear_trans_buffer() { trans_buffer_index = 0; } +void asm_print(vaddr_t ori_pc, int instr_len, bool print_flag); +vaddr_t rv64_exec_code(void *code, int nr_instr); + +void write_ins(uint32_t ins) { + assert(trans_buffer_index < BUF_SIZE); + trans_buffer[trans_buffer_index++]=ins; +} + +void mainloop() { + nemu_state.state = NEMU_RUNNING; + while (1) { + __attribute__((unused)) vaddr_t ori_pc = cpu.pc; + __attribute__((unused)) vaddr_t seq_pc = isa_exec_once(); + +#ifdef DEBUG + asm_print(ori_pc, seq_pc - ori_pc, true); +#endif + + if (nemu_state.state != NEMU_RUNNING) break; + if (tran_is_jmp) { + vaddr_t next_pc = rv64_exec_code(trans_buffer, trans_buffer_index); + cpu.pc = next_pc; + //Log("new basic block pc = %x", cpu.pc); + clear_trans_buffer(); + tran_is_jmp = false; + } + } + + switch (nemu_state.state) { + case NEMU_RUNNING: nemu_state.state = NEMU_STOP; break; + + case NEMU_END: case NEMU_ABORT: + Log("nemu: %s\33[0m at pc = " FMT_WORD "\n\n", + (nemu_state.state == NEMU_ABORT ? "\33[1;31mABORT" : + (nemu_state.halt_ret == 0 ? "\33[1;32mHIT GOOD TRAP" : "\33[1;31mHIT BAD TRAP")), + nemu_state.halt_pc); + if (nemu_state.state == NEMU_ABORT) abort(); + } +}