提交 2f434acc 编写于 作者: Z Zihao Yu

engine: add rv64 interpreter

* this engine will dynamically link with riscv64-nemu-interpreter-so,
  and control the rv64 interpreter by difftest API
上级 c30eb6fe
......@@ -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;
......
#include <dlfcn.h>
#include <isa.h>
#include <memory/paddr.h>
#include <stdlib.h>
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();
}
#include <cpu/decode.h>
#include <rtl/rtl.h>
#include <isa.h>
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);
}
#ifndef __PADDR_H__
#define __PADDR_H__
#include <common.h>
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
#ifndef __RTL_BASIC_H__
#define __RTL_BASIC_H__
#include <common.h>
/* 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
#include <isa/riscv64.h>
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;
}
#include <common.h>
#include <rtl/rtl.h>
#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);
}
}
#include <rtl/rtl.h>
#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;
}
#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
#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
#include <common.h>
#include <monitor/monitor.h>
#include <stdlib.h>
#include <isa.h>
#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();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册