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

Merge branch 'refactor-rtl' into 'master'

Refactor rtl

See merge request projectn/nemu!43
......@@ -11,10 +11,10 @@ typedef struct {
int width;
union {
uint32_t reg;
rtlreg_t addr;
word_t imm;
sword_t simm;
};
rtlreg_t *preg;
rtlreg_t val;
char str[OP_STR_SIZE];
} Operand;
......@@ -26,7 +26,7 @@ typedef struct {
vaddr_t jmp_pc;
Operand src1, dest, src2;
int width;
rtlreg_t tmp_reg[5];
rtlreg_t tmp_reg[4];
struct ISADecodeInfo isa;
} DecodeExecState;
......
......@@ -82,6 +82,9 @@ typedef struct {
struct ISADecodeInfo {
bool is_operand_size_16;
uint8_t ext_opcode;
const rtlreg_t *mbase;
rtlreg_t mbr;
word_t moff;
};
#define suffix_char(width) ((width) == 4 ? 'l' : ((width) == 1 ? 'b' : ((width) == 2 ? 'w' : '?')))
......
......@@ -7,28 +7,13 @@
/* RTL pseudo instructions */
#define make_rtl_compute_imm(name) \
static inline make_rtl(name ## i, rtlreg_t* dest, const rtlreg_t* src1, sword_t imm) { \
rtl_li(s, ir, imm); \
rtl_ ## name (s, dest, src1, ir); \
}
static inline make_rtl(li, rtlreg_t* dest, const rtlreg_t imm) {
rtl_addi(s, dest, rz, imm);
}
make_rtl_compute_imm(add)
make_rtl_compute_imm(sub)
make_rtl_compute_imm(and)
make_rtl_compute_imm(or)
make_rtl_compute_imm(xor)
make_rtl_compute_imm(shl)
make_rtl_compute_imm(shr)
make_rtl_compute_imm(sar)
make_rtl_compute_imm(mul_lo)
make_rtl_compute_imm(mul_hi)
make_rtl_compute_imm(imul_lo)
make_rtl_compute_imm(imul_hi)
make_rtl_compute_imm(div_q)
make_rtl_compute_imm(div_r)
make_rtl_compute_imm(idiv_q)
make_rtl_compute_imm(idiv_r)
static inline make_rtl(mv, rtlreg_t* dest, const rtlreg_t *src1) {
if (dest != src1) rtl_add(s, dest, src1, rz);
}
static inline make_rtl(not, rtlreg_t *dest, const rtlreg_t* src1) {
// dest <- ~src1
......@@ -50,12 +35,6 @@ static inline make_rtl(sext, rtlreg_t* dest, const rtlreg_t* src1, int width) {
}
}
static inline make_rtl(setrelopi, uint32_t relop, rtlreg_t *dest,
const rtlreg_t *src1, int imm) {
rtl_li(s, ir, imm);
rtl_setrelop(s, relop, dest, src1, ir);
}
static inline make_rtl(msb, rtlreg_t* dest, const rtlreg_t* src1, int width) {
// dest <- src1[width * 8 - 1]
// TODO();
......
......@@ -7,14 +7,16 @@
#define id_src2 (&s->src2)
#define id_dest (&s->dest)
#define dsrc1 (&id_src1->val)
#define dsrc2 (&id_src2->val)
#define ddest (&id_dest->val)
#define ir (&s->tmp_reg[0])
#define s0 (&s->tmp_reg[1])
#define s1 (&s->tmp_reg[2])
#define t0 (&s->tmp_reg[3])
#define t1 (&s->tmp_reg[4])
#define dsrc1 (id_src1->preg)
#define dsrc2 (id_src2->preg)
#define ddest (id_dest->preg)
#define s0 (&s->tmp_reg[0])
#define s1 (&s->tmp_reg[1])
#define t0 (&s->tmp_reg[2])
#define t1 (&s->tmp_reg[3])
extern const rtlreg_t rzero;
#define rz (&rzero)
#define make_rtl(name, ...) void concat(rtl_, name)(DecodeExecState *s, __VA_ARGS__)
......
......@@ -6,27 +6,43 @@
/* RTL basic instructions */
static inline make_rtl(li, rtlreg_t* dest, rtlreg_t imm) {
*dest = imm;
}
static inline make_rtl(mv, rtlreg_t* dest, const rtlreg_t *src1) {
*dest = *src1;
}
#define make_rtl_compute_reg(name) \
static inline make_rtl(name, rtlreg_t* dest, const rtlreg_t* src1, const rtlreg_t* src2) { \
*dest = concat(c_, name) (*src1, *src2); \
}
make_rtl_compute_reg(add)
make_rtl_compute_reg(sub)
make_rtl_compute_reg(and)
make_rtl_compute_reg(or)
make_rtl_compute_reg(xor)
make_rtl_compute_reg(shl)
make_rtl_compute_reg(shr)
make_rtl_compute_reg(sar)
#define make_rtl_compute_imm(name) \
static inline make_rtl(name ## i, rtlreg_t* dest, const rtlreg_t* src1, const sword_t imm) { \
*dest = concat(c_, name) (*src1, imm); \
}
#define make_rtl_compute_reg_imm(name) \
make_rtl_compute_reg(name) \
make_rtl_compute_imm(name) \
// compute
make_rtl_compute_reg_imm(add)
make_rtl_compute_reg_imm(sub)
make_rtl_compute_reg_imm(and)
make_rtl_compute_reg_imm(or)
make_rtl_compute_reg_imm(xor)
make_rtl_compute_reg_imm(shl)
make_rtl_compute_reg_imm(shr)
make_rtl_compute_reg_imm(sar)
static inline make_rtl(setrelop, uint32_t relop, rtlreg_t *dest,
const rtlreg_t *src1, const rtlreg_t *src2) {
*dest = interpret_relop(relop, *src1, *src2);
}
static inline make_rtl(setrelopi, uint32_t relop, rtlreg_t *dest,
const rtlreg_t *src1, sword_t imm) {
*dest = interpret_relop(relop, *src1, imm);
}
// mul/div
make_rtl_compute_reg(mul_lo)
make_rtl_compute_reg(mul_hi)
make_rtl_compute_reg(imul_lo)
......@@ -64,12 +80,14 @@ static inline make_rtl(idiv64_r, rtlreg_t* dest,
*dest = dividend % divisor;
}
static inline make_rtl(lm, rtlreg_t *dest, const rtlreg_t* addr, int len) {
*dest = vaddr_read(*addr, len);
// memory
static inline make_rtl(lm, rtlreg_t *dest, const rtlreg_t* addr, word_t offset, int len) {
*dest = vaddr_read(*addr + offset, len);
}
static inline make_rtl(sm, const rtlreg_t* addr, const rtlreg_t* src1, int len) {
vaddr_write(*addr, *src1, len);
static inline make_rtl(sm, const rtlreg_t* addr, word_t offset, const rtlreg_t* src1, int len) {
vaddr_write(*addr + offset, *src1, len);
}
static inline make_rtl(host_lm, rtlreg_t* dest, const void *addr, int len) {
......@@ -90,10 +108,7 @@ static inline make_rtl(host_sm, void *addr, const rtlreg_t *src1, int len) {
}
}
static inline make_rtl(setrelop, uint32_t relop, rtlreg_t *dest,
const rtlreg_t *src1, const rtlreg_t *src2) {
*dest = interpret_relop(relop, *src1, *src2);
}
// control
static inline make_rtl(j, vaddr_t target) {
s->jmp_pc = target;
......
......@@ -10,17 +10,15 @@ uint8_t reg_ptr2idx(DecodeExecState *s, const rtlreg_t* dest) {
return (dest - gpr_start)|0x10;//from x16 to x23
#define CASE(ptr, idx) if (dest == ptr) return idx;
CASE(rz, 0)
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(&id_src1->val, 7)
CASE(&id_src2->val, 8)
CASE(&id_dest->val, 9)
CASE(&s->isa.mbr, 10)
CASE(&cpu.CF, 13)
CASE(&cpu.OF, 14)
CASE(&cpu.ZF, 15)
......
......@@ -5,8 +5,6 @@
/* 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);
......@@ -15,6 +13,17 @@ 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(addi, rtlreg_t* dest, const rtlreg_t *src1, const sword_t imm);
make_rtl(subi, rtlreg_t* dest, const rtlreg_t *src1, const sword_t imm);
make_rtl(andi, rtlreg_t* dest, const rtlreg_t *src1, const sword_t imm);
make_rtl(ori, rtlreg_t* dest, const rtlreg_t *src1, const sword_t imm);
make_rtl(xori, rtlreg_t* dest, const rtlreg_t *src1, const sword_t imm);
make_rtl(shli, rtlreg_t* dest, const rtlreg_t *src1, const sword_t imm);
make_rtl(shri, rtlreg_t* dest, const rtlreg_t *src1, const sword_t imm);
make_rtl(sari, rtlreg_t* dest, const rtlreg_t *src1, const sword_t imm);
make_rtl(setrelop, uint32_t relop, rtlreg_t *dest, const rtlreg_t *src1, const rtlreg_t *src2);
make_rtl(setrelopi, uint32_t relop, rtlreg_t *dest, const rtlreg_t *src1, const sword_t imm);
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);
......@@ -27,11 +36,12 @@ make_rtl(div64_q, rtlreg_t* dest, const rtlreg_t* src1_hi, const rtlreg_t* src1_
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(lm, rtlreg_t *dest, const rtlreg_t* addr, const sword_t offset, int len);
make_rtl(sm, const rtlreg_t* addr, const sword_t offset, 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);
......
#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 = reg_ptr2idx(s, dest);
uint8_t idx_src1 = reg_ptr2idx(s, src1);
uint8_t idx_src2 = reg_ptr2idx(s, src2);
void rv64_relop(uint32_t relop, uint32_t idx_dest, uint32_t idx_src1, uint32_t idx_src2) {
switch (relop) {
case RELOP_FALSE: rv64_addi(idx_dest, x0, 0); return;
case RELOP_TRUE: rv64_addi(idx_dest, x0, 1); return;
......
#include <rtl/rtl.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);
void rv64_relop(uint32_t relop, uint32_t idx_dest, uint32_t idx_src1, uint32_t idx_src2);
uint8_t reg_ptr2idx(DecodeExecState *s, const rtlreg_t* dest);
extern int tran_is_jmp;
......@@ -11,62 +10,107 @@ static inline void rv64_zextw(uint8_t rd, uint8_t rs) {
rv64_and(rd, rs, x24);
}
/* RTL basic instructions */
make_rtl(li, rtlreg_t* dest, rtlreg_t imm) {
uint8_t idx = reg_ptr2idx(s, dest);
// return true if `imm` can be represented within 12 bits
// else load it to x31, and reture false
static inline bool load_imm(const sword_t imm) {
RV_IMM rv_imm = { .val = imm };
uint32_t lui_imm = rv_imm.imm_31_12 + (rv_imm.imm_11_0 >> 11);
if (lui_imm == 0) {
rv64_addiw(idx, x0, rv_imm.imm_11_0);
} else {
rv64_lui(idx, lui_imm);
rv64_addiw(idx, idx, rv_imm.imm_11_0);
if (lui_imm == 0) return true;
else {
rv64_lui(x31, lui_imm);
if (rv_imm.imm_11_0 != 0) rv64_addiw(x31, x31, rv_imm.imm_11_0);
return false;
}
}
make_rtl(mv, rtlreg_t* dest, const rtlreg_t *src1) {
uint8_t idx_dest = reg_ptr2idx(s, dest);
uint8_t idx_src1 = reg_ptr2idx(s, src1);
if (dest != src1) rv64_addiw(idx_dest, idx_src1, 0);
}
#define rv64_shlw rv64_sllw
#define rv64_shrw rv64_srlw
#define rv64_sarw rv64_sraw
#define rv64_mul_lo rv64_mulw
#define rv64_imul_lo rv64_mulw
#define rv64_div_q rv64_divuw
#define rv64_div_r rv64_remuw
#define rv64_idiv_q rv64_divw
#define rv64_idiv_r rv64_remw
#define make_rtl_arith_logic_w(name) \
make_rtl(name, rtlreg_t* dest, const rtlreg_t* src1, const rtlreg_t* src2) { \
concat3(rv64_, name, w) (reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), reg_ptr2idx(s, src2)); \
/* RTL basic instructions */
#define make_rtl_compute_reg(rtl_name, rv64_name) \
make_rtl(rtl_name, rtlreg_t* dest, const rtlreg_t* src1, const rtlreg_t* src2) { \
concat(rv64_, rv64_name) (reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), reg_ptr2idx(s, src2)); \
}
#define make_rtl_compute_imm(rtl_name, rv64_name) \
make_rtl(rtl_name, rtlreg_t* dest, const rtlreg_t* src1, const sword_t imm) { \
concat(rv64_, rv64_name) (reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), imm); \
}
#define make_rtl_arith_logic(name) \
make_rtl(name, rtlreg_t* dest, const rtlreg_t* src1, const rtlreg_t* src2) { \
concat(rv64_, name) (reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), reg_ptr2idx(s, src2)); \
make_rtl_compute_reg(and, and)
make_rtl_compute_reg(or, or)
make_rtl_compute_reg(xor, xor)
make_rtl(addi, rtlreg_t* dest, const rtlreg_t* src1, const sword_t imm) {
if (load_imm(imm)) rv64_addiw(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), imm);
else rv64_addw(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), x31);
}
make_rtl(subi, rtlreg_t* dest, const rtlreg_t* src1, const sword_t imm) {
rtl_addi(s, dest, src1, -imm);
}
make_rtl(andi, rtlreg_t* dest, const rtlreg_t* src1, const sword_t imm) {
if (load_imm(imm)) rv64_andi(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), imm);
else rv64_and(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), x31);
}
make_rtl(xori, rtlreg_t* dest, const rtlreg_t* src1, const sword_t imm) {
if (load_imm(imm)) rv64_xori(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), imm);
else rv64_xor(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), x31);
}
make_rtl(ori, rtlreg_t* dest, const rtlreg_t* src1, const sword_t imm) {
if (load_imm(imm)) rv64_ori(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), imm);
else rv64_or(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), x31);
}
#ifdef ISA64
make_rtl_compute_reg(add, add)
make_rtl_compute_reg(sub, sub)
make_rtl_compute_reg(shl, sll)
make_rtl_compute_reg(shr, srl)
make_rtl_compute_reg(sar, sra)
make_rtl_compute_imm(shli, slli)
make_rtl_compute_imm(shri, srli)
make_rtl_compute_imm(sari, srai)
#else
make_rtl_compute_reg(add, addw)
make_rtl_compute_reg(sub, subw)
make_rtl_compute_reg(shl, sllw)
make_rtl_compute_reg(shr, srlw)
make_rtl_compute_reg(sar, sraw)
make_rtl_compute_imm(shli, slliw)
make_rtl_compute_imm(shri, srliw)
make_rtl_compute_imm(sari, sraiw)
#endif
make_rtl(setrelop, uint32_t relop, rtlreg_t *dest, const rtlreg_t *src1, const rtlreg_t *src2) {
rv64_relop(relop, reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), reg_ptr2idx(s, src2));
}
make_rtl(setrelopi, uint32_t relop, rtlreg_t *dest, const rtlreg_t *src1, const sword_t imm) {
int small_imm = load_imm(imm);
uint32_t idx_dest = reg_ptr2idx(s, dest);
uint32_t idx_src1 = reg_ptr2idx(s, src1);
if (small_imm && (relop == RELOP_LT || relop == RELOP_LTU)) {
switch (relop) {
case RELOP_LT: rv64_slt(idx_dest, idx_src1, imm); return;
case RELOP_LTU: rv64_sltu(idx_dest, idx_src1, imm); return;
// fall through for default cases
}
}
rv64_addiw(x31, x0, imm);
rv64_relop(relop, idx_dest, idx_src1, x31);
}
make_rtl_arith_logic_w(add)
make_rtl_arith_logic_w(sub)
make_rtl_arith_logic(and)
make_rtl_arith_logic(or)
make_rtl_arith_logic(xor)
make_rtl_arith_logic_w(shl)
make_rtl_arith_logic_w(shr)
make_rtl_arith_logic_w(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_compute_reg(mul_lo, mulw)
make_rtl_compute_reg(imul_lo, mulw)
make_rtl_compute_reg(div_q, divuw)
make_rtl_compute_reg(div_r, remuw)
make_rtl_compute_reg(idiv_q, divw)
make_rtl_compute_reg(idiv_r, remw)
#ifdef ISA64
# define rv64_mul_hi(c, a, b) TODO()
......@@ -145,28 +189,46 @@ make_rtl(idiv64_r, rtlreg_t* dest,
rv64_rem(idx_dest, x30, idx_src2);
}
make_rtl(lm, rtlreg_t *dest, const rtlreg_t* addr, int len) {
make_rtl(lm, rtlreg_t *dest, const rtlreg_t* addr, const sword_t imm, int len) {
uint8_t idx_dest = reg_ptr2idx(s, dest);
uint8_t idx_addr = reg_ptr2idx(s, addr);
rv64_zextw(x31, idx_addr);
RV_IMM rv_imm = { .val = imm };
uint32_t lui_imm = rv_imm.imm_31_12 + (rv_imm.imm_11_0 >> 11);
if (lui_imm != 0) {
rv64_lui(x31, lui_imm);
rv64_add(x31, x31, idx_addr);
rv64_zextw(x31, x31);
} else {
rv64_zextw(x31, idx_addr);
}
switch (len) {
case 1: rv64_lbu(idx_dest, x31, 0); break;
case 2: rv64_lhu(idx_dest, x31, 0); break;
case 4: rv64_lwu(idx_dest, x31, 0); break;
case 8: rv64_ld (idx_dest, x31, 0); break;
case 1: rv64_lbu(idx_dest, x31, imm & 0xfff); break;
case 2: rv64_lhu(idx_dest, x31, imm & 0xfff); break;
case 4: rv64_lwu(idx_dest, x31, imm & 0xfff); break;
case 8: rv64_ld (idx_dest, x31, imm & 0xfff); break;
default: assert(0);
}
}
make_rtl(sm, const rtlreg_t* addr, const rtlreg_t* src1, int len) {
make_rtl(sm, const rtlreg_t* addr, const sword_t imm, const rtlreg_t* src1, int len) {
uint8_t idx_addr = reg_ptr2idx(s, addr);
uint8_t idx_src1 = reg_ptr2idx(s, src1);
rv64_zextw(x31, idx_addr);
RV_IMM rv_imm = { .val = imm };
uint32_t lui_imm = rv_imm.imm_31_12 + (rv_imm.imm_11_0 >> 11);
if (lui_imm != 0) {
rv64_lui(x31, lui_imm);
rv64_add(x31, x31, idx_addr);
rv64_zextw(x31, x31);
} else {
rv64_zextw(x31, idx_addr);
}
switch (len) {
case 1: rv64_sb(x31, idx_src1, 0); break;
case 2: rv64_sh(x31, idx_src1, 0); break;
case 4: rv64_sw(x31, idx_src1, 0); break;
case 8: rv64_sd(x31, idx_src1, 0); break;
case 1: rv64_sb(x31, idx_src1, imm & 0xfff); break;
case 2: rv64_sh(x31, idx_src1, imm & 0xfff); break;
case 4: rv64_sw(x31, idx_src1, imm & 0xfff); break;
case 8: rv64_sd(x31, idx_src1, imm & 0xfff); break;
default: assert(0);
}
}
......@@ -229,14 +291,10 @@ 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) {
rv64_relop(s, relop, dest, src1, src2);
}
// we use x30 to store x86.pc of the next basic block
make_rtl(j, vaddr_t target) {
rtl_li(s, ir, target);
rv64_addi(x30, reg_ptr2idx(s, ir), 0);
if (load_imm(target)) rv64_addiw(x31, x31, target & 0xfff);
rv64_addi(x30, x31, 0);
tran_is_jmp = true;
}
......@@ -246,10 +304,10 @@ make_rtl(jr, rtlreg_t *target) {
}
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);
rv64_addi(x30, reg_ptr2idx(s, ddest), 0);
rtl_setrelop(s, relop, &id_dest->val, src1, src2);
rtl_li(s, &id_src1->val, target);
rtl_li(s, &id_src2->val, s->seq_pc);
rtl_mux(s, &id_dest->val, &id_dest->val, &id_src1->val, &id_src2->val);
rv64_addi(x30, reg_ptr2idx(s, &id_dest->val), 0);
tran_is_jmp = true;
}
......@@ -193,7 +193,7 @@ enum { x0 = 0, x24 = 24, x25, x26, x27, x28, x29, x30, x31 };
#define rv64_slti(rd, rs1, imm) gen_rv64_I_inst(0b0010011, rd, 0b010, rs1, imm)
#define rv64_sltiu(rd, rs1, imm) gen_rv64_I_inst(0b0010011, rd, 0b011, rs1, imm)
#define rv64_xori(rd, rs1, imm) gen_rv64_I_inst(0b0010011, rd, 0b100, rs1, imm)
#define rv64_xoi(rd, rs1, imm) gen_rv64_I_inst(0b0010011, rd, 0b110, rs1, imm)
#define rv64_ori(rd, rs1, imm) gen_rv64_I_inst(0b0010011, rd, 0b110, rs1, imm)
#define rv64_andi(rd, rs1, imm) gen_rv64_I_inst(0b0010011, rd, 0b111, rs1, imm)
#define rv64_slli(rd, rs1, shamt) gen_rv64_R64_inst(0b0010011, rd, 0b001, rs1, shamt, 0b000000)
#define rv64_srli(rd, rs1, shamt) gen_rv64_R64_inst(0b0010011, rd, 0b101, rs1, shamt, 0b000000)
......
......@@ -22,6 +22,7 @@ void write_ins(uint32_t ins) {
void mainloop() {
nemu_state.state = NEMU_RUNNING;
uint64_t total_instr = 0;
while (1) {
__attribute__((unused)) vaddr_t ori_pc = cpu.pc;
__attribute__((unused)) vaddr_t seq_pc = isa_exec_once();
......@@ -34,6 +35,7 @@ void mainloop() {
if (tran_is_jmp) {
#endif
vaddr_t next_pc = rv64_exec_trans_buffer(trans_buffer, trans_buffer_index);
total_instr += trans_buffer_index;
if (tran_is_jmp) cpu.pc = next_pc;
// Log("new basic block pc = %x", cpu.pc);
clear_trans_buffer();
......@@ -61,4 +63,6 @@ void mainloop() {
nemu_state.halt_pc);
if (nemu_state.state == NEMU_ABORT) abort();
}
Log("#(rv64 instr) = %ld\n", total_instr);
}
static inline make_EHelper(lui) {
rtl_shli(s, s0, dsrc2, 16);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_li(s, ddest, id_src2->imm << 16);
print_asm_template3(lui);
}
static inline make_EHelper(add) {
rtl_add(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_add(s, ddest, dsrc1, dsrc2);
print_asm_template3(add);
}
static inline make_EHelper(sub) {
rtl_sub(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sub(s, ddest, dsrc1, dsrc2);
print_asm_template3(sub);
}
static inline make_EHelper(slt) {
rtl_setrelop(s, RELOP_LT, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_setrelop(s, RELOP_LT, ddest, dsrc1, dsrc2);
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);
rtl_setrelop(s, RELOP_LTU, ddest, dsrc1, dsrc2);
print_asm_template3(sltu);
}
static inline make_EHelper(and) {
rtl_and(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_and(s, ddest, dsrc1, dsrc2);
print_asm_template3(and);
}
static inline make_EHelper(or) {
rtl_or(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_or(s, ddest, dsrc1, dsrc2);
print_asm_template3(or);
}
static inline make_EHelper(xor) {
rtl_xor(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_xor(s, ddest, dsrc1, dsrc2);
print_asm_template3(xor);
}
static inline make_EHelper(nor) {
rtl_or(s, s0, dsrc1, dsrc2);
rtl_not(s, s0, s0);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_not(s, ddest, s0);
print_asm_template3(nor);
}
static inline make_EHelper(sll) {
rtl_shl(s, s0, dsrc2, dsrc1);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_shl(s, ddest, dsrc2, dsrc1);
print_asm_template3(sll);
}
static inline make_EHelper(srl) {
rtl_shr(s, s0, dsrc2, dsrc1);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_shr(s, ddest, dsrc2, dsrc1);
print_asm_template3(srl);
}
static inline make_EHelper(sra) {
rtl_sar(s, s0, dsrc2, dsrc1);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sar(s, ddest, dsrc2, dsrc1);
print_asm_template3(sra);
}
static inline make_EHelper(movz) {
rtl_mux(s, s0, dsrc2, ddest, dsrc1);
rtl_sr(s, id_dest->reg, s0, 4);
static inline make_EHelper(addi) {
rtl_addi(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(addi);
}
static inline make_EHelper(slti) {
rtl_setrelopi(s, RELOP_LT, ddest, dsrc1, id_src2->imm);
print_asm_template3(slti);
}
static inline make_EHelper(sltui) {
rtl_setrelopi(s, RELOP_LTU, ddest, dsrc1, id_src2->imm);
print_asm_template3(sltui);
}
static inline make_EHelper(andi) {
rtl_andi(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(andi);
}
static inline make_EHelper(ori) {
rtl_ori(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(ori);
}
static inline make_EHelper(xori) {
rtl_xori(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(xori);
}
static inline make_EHelper(slli) {
rtl_shli(s, ddest, dsrc2, id_src1->imm);
print_asm_template3(slli);
}
static inline make_EHelper(srli) {
rtl_shri(s, ddest, dsrc2, id_src1->imm);
print_asm_template3(srli);
}
static inline make_EHelper(srai) {
rtl_sari(s, ddest, dsrc2, id_src1->imm);
print_asm_template3(srai);
}
static inline make_EHelper(movz) {
rtl_mux(s, ddest, dsrc2, ddest, dsrc1);
print_asm_template3(movz);
}
static inline make_EHelper(movn) {
rtl_mux(s, s0, dsrc2, dsrc1, ddest);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_mux(s, ddest, dsrc2, dsrc1, ddest);
print_asm_template3(movn);
}
......@@ -6,86 +6,64 @@ static inline void difftest_skip_delay_slot(void) {
static inline make_EHelper(j) {
difftest_skip_delay_slot();
rtl_j(s, s->jmp_pc);
print_asm_template1(j);
}
static inline make_EHelper(jal) {
difftest_skip_delay_slot();
rtl_addi(s, s0, &cpu.pc, 8);
rtl_sr(s, 31, s0, 4);
word_t ra = cpu.pc + 8;
rtl_j(s, s->jmp_pc);
rtl_li(s, &reg_l(31), ra);
print_asm_template1(jal);
}
static inline make_EHelper(jr) {
difftest_skip_delay_slot();
rtl_jr(s, dsrc1);
print_asm_template2(jr);
}
static inline make_EHelper(jalr) {
difftest_skip_delay_slot();
rtl_addi(s, s0, &cpu.pc, 8);
rtl_sr(s, id_dest->reg, s0, 4);
word_t ra = cpu.pc + 8;
rtl_jr(s, dsrc1);
rtl_li(s, ddest, ra);
print_asm_template2(jalr);
}
static inline make_EHelper(bne) {
difftest_skip_delay_slot();
rtl_jrelop(s, RELOP_NE, dsrc1, dsrc2, s->jmp_pc);
print_asm_template3(bne);
}
static inline make_EHelper(beq) {
difftest_skip_delay_slot();
rtl_jrelop(s, RELOP_EQ, dsrc1, dsrc2, s->jmp_pc);
print_asm_template3(beq);
}
static inline make_EHelper(blez) {
difftest_skip_delay_slot();
rtl_jrelop(s, RELOP_LE, dsrc1, dsrc2, s->jmp_pc);
print_asm_template3(blez);
}
static inline make_EHelper(bltz) {
difftest_skip_delay_slot();
rtl_li(s, s0, 0);
rtl_jrelop(s, RELOP_LT, dsrc1, s0, s->jmp_pc);
rtl_jrelop(s, RELOP_LT, dsrc1, rz, s->jmp_pc);
print_asm_template3(bltz);
}
static inline make_EHelper(bgtz) {
difftest_skip_delay_slot();
rtl_jrelop(s, RELOP_GT, dsrc1, dsrc2, s->jmp_pc);
print_asm_template3(blez);
}
static inline make_EHelper(bgez) {
difftest_skip_delay_slot();
rtl_li(s, s0, 0);
rtl_jrelop(s, RELOP_GE, dsrc1, s0, s->jmp_pc);
rtl_jrelop(s, RELOP_GE, dsrc1, rz, s->jmp_pc);
print_asm_template3(bltz);
}
......@@ -20,7 +20,7 @@ static inline void set_width(DecodeExecState *s, int width) {
static inline make_EHelper(special) {
switch (s->isa.instr.r.func) {
IDEX (000, shift, sll) IDEX (002, shift, srl) IDEX (003, shift, sra)
IDEX (000, shift, slli) IDEX (002, shift, srli)IDEX (003, shift, srai)
IDEX (004, R, sll) IDEX (006, R, srl) IDEX (007, R, sra)
IDEX (010, R, jr) IDEX (011, R, jalr) IDEX (012, cmov, movz) IDEX (013, cmov, movn)
EX (014, syscall)
......@@ -72,8 +72,8 @@ static inline void exec(DecodeExecState *s) {
switch (s->isa.instr.r.opcode) {
EX (000, special) EX (001, regimm) IDEX (002, J, j) IDEX (003, J, jal)
IDEX (004, B, beq) IDEX (005, B, bne) IDEX (006, B, blez) IDEX (007, B, bgtz)
IDEX (011, I, add) IDEX (012, I, slt) IDEX (013, I, sltu)
IDEX (014, IU, and) IDEX (015, IU, or) IDEX (016, IU, xor) IDEX (017, IU, lui)
IDEX (011, I, addi) IDEX (012, I, slti) IDEX (013, I, sltui)
IDEX (014, IU, andi) IDEX (015, IU, ori) IDEX (016, IU, xori) IDEX (017, IU, lui)
EX (020, cop0)
......
#include "../local-include/intr.h"
static inline make_EHelper(ld) {
rtl_lm(s, s0, &id_src1->addr, s->width);
rtl_lm(s, s0, dsrc1, id_src2->imm, s->width);
check_mem_ex();
rtl_sr(s, id_dest->reg, s0, 4);
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->imm, reg_name(id_src1->reg, 4));
switch (s->width) {
case 4: print_asm_template2(lw); break;
case 2: print_asm_template2(lhu); break;
......@@ -15,11 +16,11 @@ static inline make_EHelper(ld) {
// load sign value
static inline make_EHelper(lds) {
rtl_lm(s, s0, &id_src1->addr, s->width);
rtl_lm(s, s0, dsrc1, id_src2->imm, s->width);
check_mem_ex();
rtl_sext(s, s0, s0, s->width);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sext(s, ddest, s0, s->width);
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->imm, reg_name(id_src1->reg, 4));
switch (s->width) {
case 2: print_asm_template2(lh); break;
case 1: print_asm_template2(lb); break;
......@@ -28,9 +29,10 @@ static inline make_EHelper(lds) {
}
static inline make_EHelper(st) {
rtl_sm(s, &id_src1->addr, ddest, s->width);
rtl_sm(s, dsrc1, id_src2->imm, ddest, s->width);
check_mem_ex();
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->imm, reg_name(id_src1->reg, 4));
switch (s->width) {
case 4: print_asm_template2(sw); break;
case 2: print_asm_template2(sh); break;
......@@ -39,10 +41,12 @@ static inline make_EHelper(st) {
}
}
// we do not use pseudo-rtl here, so we can use t0/t1 safely
static inline make_EHelper(swl) {
// int reg_right_shift_amount [] = {24, 16, 8, 0};
// (3 - n) << 3
rtl_not(s, s0, &id_src1->addr);
rtl_addi(s, t0, dsrc1, id_src2->imm); // t0 = addr
rtl_not(s, s0, t0);
rtl_andi(s, s0, s0, 0x3);
rtl_shli(s, s0, s0, 3);
// prepare register data
......@@ -54,8 +58,8 @@ static inline make_EHelper(swl) {
rtl_sar(s, s1, s1, s0);
rtl_shli(s, s1, s1, 1);
// load the aligned memory word
rtl_andi(s, &id_src1->addr, &id_src1->addr, ~0x3u);
rtl_lm(s, s0, &id_src1->addr, 4);
rtl_andi(s, t0, t0, ~0x3u);
rtl_lm(s, s0, t0, 0, 4);
check_mem_ex();
// prepare memory data
rtl_and(s, s0, s0, s1);
......@@ -64,16 +68,18 @@ static inline make_EHelper(swl) {
rtl_or(s, s0, s0, ddest);
// write back
rtl_sm(s, &id_src1->addr, s0, 4);
rtl_sm(s, t0, 0, s0, 4);
check_mem_ex();
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->imm, reg_name(id_src1->reg, 4));
print_asm_template2(swl);
}
static inline make_EHelper(swr) {
// int reg_left_shift_amount [] = {0, 8, 16, 24};
// n << 3
rtl_andi(s, s0, &id_src1->addr, 0x3);
rtl_addi(s, t0, dsrc1, id_src2->imm); // t0 = addr
rtl_andi(s, s0, t0, 0x3);
rtl_shli(s, s0, s0, 3);
// prepare register data
rtl_shl(s, ddest, ddest, s0);
......@@ -84,8 +90,8 @@ static inline make_EHelper(swr) {
rtl_shl(s, s1, s1, s0);
rtl_not(s, s1, s1);
// load the aligned memory word
rtl_andi(s, &id_src1->addr, &id_src1->addr, ~0x3u);
rtl_lm(s, s0, &id_src1->addr, 4);
rtl_andi(s, t0, t0, ~0x3u);
rtl_lm(s, s0, t0, 0, 4);
check_mem_ex();
// prepare memory data
rtl_and(s, s0, s0, s1);
......@@ -94,16 +100,18 @@ static inline make_EHelper(swr) {
rtl_or(s, s0, s0, ddest);
// write back
rtl_sm(s, &id_src1->addr, s0, 4);
rtl_sm(s, t0, 0, s0, 4);
check_mem_ex();
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->imm, reg_name(id_src1->reg, 4));
print_asm_template2(swr);
}
static inline make_EHelper(lwl) {
// int mem_left_shift_amount [] = {24, 16, 8, 0};
// (3 - n) << 3
rtl_not(s, s0, &id_src1->addr);
rtl_addi(s, t0, dsrc1, id_src2->imm); // t0 = addr
rtl_not(s, s0, t0);
rtl_andi(s, s0, s0, 0x3);
rtl_shli(s, s0, s0, 3);
......@@ -116,8 +124,8 @@ static inline make_EHelper(lwl) {
rtl_and(s, ddest, ddest, s1);
// load the aligned memory word
rtl_andi(s, &id_src1->addr, &id_src1->addr, ~0x3u);
rtl_lm(s, s1, &id_src1->addr, 4);
rtl_andi(s, t0, t0, ~0x3u);
rtl_lm(s, s1, t0, 0, 4);
check_mem_ex();
// prepare memory data
rtl_shl(s, s1, s1, s0);
......@@ -128,13 +136,15 @@ static inline make_EHelper(lwl) {
// write back
rtl_sr(s, id_dest->reg, ddest, 4);
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->imm, reg_name(id_src1->reg, 4));
print_asm_template2(lwl);
}
static inline make_EHelper(lwr) {
// int mem_right_shift_amount [] = {0, 8, 16, 24};
// n << 3
rtl_andi(s, s0, &id_src1->addr, 0x3);
rtl_addi(s, t0, dsrc1, id_src2->imm); // t0 = addr
rtl_andi(s, s0, t0, 0x3);
rtl_shli(s, s0, s0, 3);
// int reg_mask [] = {0x0, 0xff000000, 0xffff0000, 0xffffff00};
......@@ -146,8 +156,8 @@ static inline make_EHelper(lwr) {
rtl_and(s, ddest, ddest, s1);
// load the aligned memory word
rtl_andi(s, &id_src1->addr, &id_src1->addr, ~0x3u);
rtl_lm(s, s1, &id_src1->addr, 4);
rtl_andi(s, t0, t0, ~0x3u);
rtl_lm(s, s1, t0, 0, 4);
check_mem_ex();
// prepare memory data
rtl_shr(s, s1, s1, s0);
......@@ -158,5 +168,6 @@ static inline make_EHelper(lwr) {
// write back
rtl_sr(s, id_dest->reg, ddest, 4);
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->imm, reg_name(id_src1->reg, 4));
print_asm_template2(lwr);
}
static inline make_EHelper(mfhi) {
rtl_sr(s, id_dest->reg, &cpu.hi, 4);
rtl_mv(s, ddest, &cpu.hi);
print_asm_template3(mfhi);
}
static inline make_EHelper(mflo) {
rtl_sr(s, id_dest->reg, &cpu.lo, 4);
rtl_mv(s, ddest, &cpu.lo);
print_asm_template3(mflo);
}
static inline make_EHelper(mthi) {
rtl_mv(s, &cpu.hi, dsrc1);
print_asm_template2(mthi);
}
static inline make_EHelper(mtlo) {
rtl_mv(s, &cpu.lo, dsrc1);
print_asm_template2(mtlo);
}
static inline make_EHelper(mul) {
rtl_imul_lo(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_imul_lo(s, ddest, dsrc1, dsrc2);
print_asm_template3(mul);
}
static inline make_EHelper(mult) {
rtl_imul_lo(s, &cpu.lo, dsrc1, dsrc2);
rtl_imul_hi(s, &cpu.hi, dsrc1, dsrc2);
print_asm_template3(mult);
}
static inline make_EHelper(multu) {
rtl_mul_lo(s, &cpu.lo, dsrc1, dsrc2);
rtl_mul_hi(s, &cpu.hi, dsrc1, dsrc2);
print_asm_template3(multu);
}
static inline make_EHelper(div) {
rtl_idiv_q(s, &cpu.lo, dsrc1, dsrc2);
rtl_idiv_r(s, &cpu.hi, dsrc1, dsrc2);
print_asm_template3(div);
}
static inline make_EHelper(divu) {
rtl_div_q(s, &cpu.lo, dsrc1, dsrc2);
rtl_div_r(s, &cpu.hi, dsrc1, dsrc2);
print_asm_template3(divu);
}
......@@ -2,15 +2,12 @@
static inline make_EHelper(syscall) {
raise_intr(s, EX_SYSCALL, cpu.pc);
print_asm("syscall");
}
static inline make_EHelper(eret) {
rtl_li(s, s0, cpu.epc);
rtl_jr(s, s0);
rtl_j(s, cpu.epc);
cpu.status.exl = 0;
print_asm("eret");
}
......@@ -30,19 +27,18 @@ static inline make_EHelper(mfc0) {
default: assert(0);
}
rtl_li(s, s0, val);
rtl_sr(s, id_src2->reg, s0, 4);
rtl_li(s, dsrc2, val);
}
static inline make_EHelper(mtc0) {
switch (id_dest->reg) {
case 0: cpu.index = id_src2->val; print_asm("mtc0 %s, index", id_src2->str); break;
case 2: cpu.entrylo0 = id_src2->val; print_asm("mtc0 %s, entrylo0", id_src2->str); break;
case 3: cpu.entrylo1 = id_src2->val; print_asm("mtc0 %s, entrylo1", id_src2->str); break;
case 10: cpu.entryhi.val = id_src2->val & ~0x1f00; print_asm("mtc0 %s, entryhi", id_src2->str); break;
case 12: cpu.status.val = id_src2->val; print_asm("mtc0 %s, status", id_src2->str); break;
case 13: cpu.cause = id_src2->val; print_asm("mtc0 %s, cause", id_src2->str); break;
case 14: cpu.epc = id_src2->val; print_asm("mtc0 %s, epc", id_src2->str); break;
case 0: cpu.index = *dsrc2; print_asm("mtc0 %s, index", id_src2->str); break;
case 2: cpu.entrylo0 = *dsrc2; print_asm("mtc0 %s, entrylo0", id_src2->str); break;
case 3: cpu.entrylo1 = *dsrc2; print_asm("mtc0 %s, entrylo1", id_src2->str); break;
case 10: cpu.entryhi.val = *dsrc2 & ~0x1f00; print_asm("mtc0 %s, entryhi", id_src2->str); break;
case 12: cpu.status.val = *dsrc2; print_asm("mtc0 %s, status", id_src2->str); break;
case 13: cpu.cause = *dsrc2; print_asm("mtc0 %s, cause", id_src2->str); break;
case 14: cpu.epc = *dsrc2; print_asm("mtc0 %s, epc", id_src2->str); break;
default: assert(0);
}
}
......
......@@ -8,7 +8,6 @@
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);
}
......@@ -16,9 +15,8 @@ static inline make_DopHelper(i) {
static inline make_DopHelper(r) {
op->type = OP_TYPE_REG;
op->reg = val;
if (load_val) {
rtl_lr(s, &op->val, op->reg, 4);
}
op->preg = &reg_l(val);
reg_l(0) = 0;
print_Dop(op->str, OP_STR_SIZE, "%s", reg_name(op->reg, 4));
}
......@@ -39,9 +37,7 @@ static inline make_DHelper(IU) {
static inline make_DHelper(J) {
vaddr_t target = (cpu.pc & 0xf0000000) | (s->isa.instr.j.target << 2);
decode_op_i(s, id_dest, target, true);
s->jmp_pc = target;
print_Dop(id_dest->str, OP_STR_SIZE, "0x%x", s->jmp_pc);
}
......@@ -51,22 +47,15 @@ static inline make_DHelper(R) {
decode_op_r(s, id_dest, s->isa.instr.r.rd, false);
}
static inline make_DHelper(addr) {
static inline make_DHelper(ld) {
decode_op_r(s, id_src1, s->isa.instr.i.rs, true);
decode_op_i(s, id_src2, s->isa.instr.i.simm, 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(ld) {
decode_addr(s);
decode_op_r(s, id_dest, s->isa.instr.i.rt, false);
}
static inline make_DHelper(st) {
decode_addr(s);
decode_op_r(s, id_src1, s->isa.instr.i.rs, true);
decode_op_i(s, id_src2, s->isa.instr.i.simm, true);
decode_op_r(s, id_dest, s->isa.instr.i.rt, true);
}
......@@ -77,7 +66,6 @@ static inline make_DHelper(B) {
decode_op_r(s, id_src1, s->isa.instr.i.rs, true);
decode_op_r(s, id_src2, s->isa.instr.i.rt, true);
decode_op_i(s, id_dest, s->jmp_pc, true);
print_Dop(id_dest->str, OP_STR_SIZE, "0x%x", s->jmp_pc);
}
......
......@@ -4,9 +4,10 @@
#include "difftest.h"
bool isa_difftest_checkregs(CPU_state *ref_r, vaddr_t pc) {
if (memcmp(&cpu, ref_r, DIFFTEST_REG_SIZE)) {
if (memcmp(&cpu.gpr[1], &ref_r->gpr[1], DIFFTEST_REG_SIZE - sizeof(cpu.gpr[0]))) {
int i;
for (i = 0; i < sizeof(cpu.gpr) / sizeof(cpu.gpr[0]); i ++) {
// do not check $0
for (i = 1; i < sizeof(cpu.gpr) / sizeof(cpu.gpr[0]); i ++) {
difftest_check_reg(reg_name(i, 4), pc, ref_r->gpr[i]._32, cpu.gpr[i]._32);
}
difftest_check_reg("pc", pc, ref_r->pc, cpu.pc);
......
static inline make_EHelper(add) {
rtl_add(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_add(s, ddest, dsrc1, dsrc2);
print_asm_template3(add);
}
static inline make_EHelper(sub) {
rtl_sub(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sub(s, ddest, dsrc1, dsrc2);
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);
rtl_shl(s, ddest, dsrc1, dsrc2);
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);
rtl_sar(s, ddest, dsrc1, dsrc2);
print_asm_template3(sra);
}
else {
rtl_shr(s, s0, dsrc1, dsrc2);
rtl_shr(s, ddest, dsrc1, dsrc2);
print_asm_template3(srl);
}
rtl_sr(s, id_dest->reg, s0, 4);
}
static inline make_EHelper(sra) {
......@@ -41,49 +30,87 @@ static inline make_EHelper(sra) {
}
static inline make_EHelper(slt) {
rtl_setrelop(s, RELOP_LT, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_setrelop(s, RELOP_LT, ddest, dsrc1, dsrc2);
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);
rtl_setrelop(s, RELOP_LTU, ddest, dsrc1, dsrc2);
print_asm_template3(sltu);
}
static inline make_EHelper(xor) {
rtl_xor(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_xor(s, ddest, dsrc1, dsrc2);
print_asm_template3(xor);
}
static inline make_EHelper(or) {
rtl_or(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_or(s, ddest, dsrc1, dsrc2);
print_asm_template3(or);
}
static inline make_EHelper(and) {
rtl_and(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_and(s, ddest, dsrc1, dsrc2);
print_asm_template3(and);
}
static inline make_EHelper(auipc) {
rtl_add(s, s0, dsrc1, &cpu.pc);
rtl_sr(s, id_dest->reg, s0, 4);
static inline make_EHelper(addi) {
rtl_addi(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(addi);
}
static inline make_EHelper(slli) {
rtl_shli(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(slli);
}
static inline make_EHelper(srli) {
if (s->isa.instr.r.funct7 == 32) {
// sra
rtl_sari(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(srai);
}
else {
rtl_shri(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(srli);
}
}
static inline make_EHelper(srai) {
exec_srli(s);
}
static inline make_EHelper(slti) {
rtl_setrelopi(s, RELOP_LT, ddest, dsrc1, id_src2->imm);
print_asm_template3(slti);
}
static inline make_EHelper(sltui) {
rtl_setrelopi(s, RELOP_LTU, ddest, dsrc1, id_src2->imm);
print_asm_template3(sltui);
}
static inline make_EHelper(xori) {
rtl_xori(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(xori);
}
static inline make_EHelper(ori) {
rtl_ori(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(ori);
}
static inline make_EHelper(andi) {
rtl_andi(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(andi);
}
static inline make_EHelper(auipc) {
rtl_li(s, ddest, id_src1->imm + cpu.pc);
print_asm_template2(auipc);
}
static inline make_EHelper(lui) {
rtl_sr(s, id_dest->reg, dsrc1, 4);
rtl_li(s, ddest, id_src1->imm);
print_asm_template2(lui);
}
#include <monitor/difftest.h>
static inline make_EHelper(jal) {
rtl_addi(s, s0, &cpu.pc, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_li(s, ddest, s->seq_pc);
rtl_j(s, s->jmp_pc);
print_asm_template2(jal);
}
static inline make_EHelper(jalr) {
rtl_addi(s, s0, &cpu.pc, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_add(s, s0, dsrc1, dsrc2);
rtl_addi(s, s0, dsrc1, id_src2->imm);
rtl_andi(s, s0, s0, ~0x1u);
rtl_jr(s, s0);
rtl_li(s, ddest, s->seq_pc);
difftest_skip_dut(1, 2);
print_asm_template3(jalr);
......@@ -38,5 +36,5 @@ static inline make_EHelper(branch) {
assert(type != 2 && type != 3);
rtl_jrelop(s, branch_map[type].relop, dsrc1, dsrc2, s->jmp_pc);
print_asm("b%s %s,%s,%s", branch_map[type].name, id_src1->str, id_src2->str, id_dest->str);
print_asm("b%s %s,%s,0x%x", branch_map[type].name, id_src1->str, id_src2->str, s->jmp_pc);
}
......@@ -32,8 +32,8 @@ static inline make_EHelper(store) {
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)
EX(0, addi) EX(1, slli) EX(2, slti) EX(3, sltui)
EX(4, xori) EX(5, srli) EX(6, ori) EX(7, andi)
default: exec_inv(s);
}
}
......@@ -68,10 +68,10 @@ 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 (0b00000, I, load)
IDEX (0b00100, I, op_imm)
IDEX (0b00101, U, auipc)
IDEX (0b01000, st, store) IDEX (0b01100, R, op)
IDEX (0b01000, S, 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 inline make_EHelper(ld) {
rtl_lm(s, s0, &id_src1->addr, s->width);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_lm(s, ddest, dsrc1, id_src2->imm, s->width);
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->val, reg_name(id_src1->reg, 4));
switch (s->width) {
case 4: print_asm_template2(lw); break;
case 2: print_asm_template2(lhu); break;
......@@ -12,10 +12,10 @@ static inline make_EHelper(ld) {
// load sign value
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);
rtl_lm(s, s0, dsrc1, id_src2->imm, s->width);
rtl_sext(s, ddest, s0, s->width);
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->val, reg_name(id_src1->reg, 4));
switch (s->width) {
case 2: print_asm_template2(lh); break;
case 1: print_asm_template2(lb); break;
......@@ -24,8 +24,9 @@ static inline make_EHelper(lds) {
}
static inline make_EHelper(st) {
rtl_sm(s, &id_src1->addr, ddest, s->width);
rtl_sm(s, dsrc1, id_src2->imm, ddest, s->width);
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->val, reg_name(id_src1->reg, 4));
switch (s->width) {
case 4: print_asm_template2(sw); break;
case 2: print_asm_template2(sh); break;
......
static inline make_EHelper(mul) {
rtl_imul_lo(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_imul_lo(s, ddest, dsrc1, dsrc2);
print_asm_template3(mul);
}
static inline make_EHelper(mulh) {
rtl_imul_hi(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_imul_hi(s, ddest, dsrc1, dsrc2);
print_asm_template3(mulh);
}
static inline make_EHelper(mulhu) {
rtl_mul_hi(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_mul_hi(s, ddest, dsrc1, dsrc2);
print_asm_template3(mulh);
}
static inline make_EHelper(div) {
rtl_idiv_q(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_idiv_q(s, ddest, dsrc1, dsrc2);
print_asm_template3(div);
}
static inline make_EHelper(divu) {
rtl_div_q(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_div_q(s, ddest, dsrc1, dsrc2);
print_asm_template3(divu);
}
static inline make_EHelper(rem) {
rtl_idiv_r(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_idiv_r(s, ddest, dsrc1, dsrc2);
print_asm_template3(rem);
}
static inline make_EHelper(remu) {
rtl_div_r(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_div_r(s, ddest, dsrc1, dsrc2);
print_asm_template3(remu);
}
......@@ -14,19 +14,31 @@ static inline rtlreg_t* csr_decode(uint32_t csr) {
}
static inline make_EHelper(csrrw) {
rtlreg_t *csr = csr_decode(id_src2->val);
rtlreg_t *csr = csr_decode(id_src2->imm);
rtl_sr(s, id_dest->reg, csr, 4);
rtl_mv(s, csr, dsrc1);
if (ddest == dsrc1) {
rtl_mv(s, s0, csr);
rtl_mv(s, csr, dsrc1);
rtl_mv(s, dsrc1, s0);
} else {
rtl_mv(s, ddest, csr);
rtl_mv(s, csr, dsrc1);
}
print_asm_template3("csrrw");
}
static inline make_EHelper(csrrs) {
rtlreg_t *csr = csr_decode(id_src2->val);
rtlreg_t *csr = csr_decode(id_src2->imm);
rtl_sr(s, id_dest->reg, csr, 4);
rtl_or(s, csr, csr, dsrc1);
if (ddest == dsrc1) {
rtl_mv(s, s0, csr);
rtl_or(s, csr, csr, dsrc1);
rtl_mv(s, dsrc1, s0);
} else {
rtl_mv(s, ddest, csr);
rtl_or(s, csr, csr, dsrc1);
}
print_asm_template3("csrrs");
}
......@@ -42,8 +54,7 @@ static inline make_EHelper(priv) {
case 0x102:
cpu.sstatus.sie = cpu.sstatus.spie;
cpu.sstatus.spie = 1;
rtl_li(s, s0, cpu.sepc);
rtl_jr(s, s0);
rtl_j(s, cpu.sepc);
print_asm("sret");
break;
default: panic("unimplemented priv instruction type = 0x%x", type);
......
......@@ -8,7 +8,6 @@
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);
}
......@@ -16,9 +15,8 @@ static inline make_DopHelper(i) {
static inline make_DopHelper(r) {
op->type = OP_TYPE_REG;
op->reg = val;
if (load_val) {
rtl_lr(s, &op->val, op->reg, 4);
}
op->preg = &reg_l(val);
reg_l(0) = 0;
print_Dop(op->str, OP_STR_SIZE, "%s", reg_name(op->reg, 4));
}
......@@ -46,7 +44,6 @@ 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);
......@@ -56,27 +53,16 @@ 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) {
static inline make_DHelper(S) {
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) {
......
......@@ -5,9 +5,10 @@
#include "difftest.h"
bool isa_difftest_checkregs(CPU_state *ref_r, vaddr_t pc) {
if (memcmp(&cpu, ref_r, DIFFTEST_REG_SIZE)) {
if (memcmp(&cpu.gpr[1], &ref_r->gpr[1], DIFFTEST_REG_SIZE - sizeof(cpu.gpr[0]))) {
int i;
for (i = 0; i < sizeof(cpu.gpr) / sizeof(cpu.gpr[0]); i ++) {
// do not check $0
for (i = 1; i < sizeof(cpu.gpr) / sizeof(cpu.gpr[0]); i ++) {
difftest_check_reg(reg_name(i, 4), pc, ref_r->gpr[i]._64, cpu.gpr[i]._64);
}
difftest_check_reg("pc", pc, ref_r->pc, cpu.pc);
......
#include "../local-include/intr.h"
static inline make_EHelper(lr) {
rtl_lm(s, s0, dsrc1, s->width);
rtl_lm(s, s0, dsrc1, 0, s->width);
check_mem_ex();
rtl_sext(s, s0, s0, s->width);
rtl_sr(s, id_dest->reg, s0, 0);
cpu.lr_addr = *dsrc1;
rtl_sext(s, ddest, s0, s->width);
print_asm_template3(lr);
}
......@@ -14,7 +12,7 @@ static inline make_EHelper(lr) {
static inline make_EHelper(sc) {
// should check overlapping instead of equality
if (cpu.lr_addr == *dsrc1) {
rtl_sm(s, dsrc1, dsrc2, s->width);
rtl_sm(s, dsrc1, 0, dsrc2, s->width);
check_mem_ex();
rtl_li(s, s0, 0);
} else {
......@@ -26,12 +24,12 @@ static inline make_EHelper(sc) {
}
static void inline amo_load(DecodeExecState *s) {
rtl_lm(s, s0, dsrc1, s->width);
rtl_lm(s, s0, dsrc1, 0, s->width);
rtl_sext(s, s0, s0, s->width);
}
static void inline amo_update(DecodeExecState *s) {
rtl_sm(s, dsrc1, s1, s->width);
rtl_sm(s, dsrc1, 0, s1, s->width);
check_mem_ex();
rtl_sr(s, id_dest->reg, s0, 0);
}
......
static inline make_EHelper(add) {
rtl_add(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_add(s, ddest, dsrc1, dsrc2);
print_asm_template3(add);
}
static inline make_EHelper(sub) {
rtl_sub(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sub(s, ddest, dsrc1, dsrc2);
print_asm_template3(sub);
}
static inline make_EHelper(sll) {
rtl_andi(s, dsrc2, dsrc2, 0x3f);
rtl_shl(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_shl(s, ddest, dsrc1, dsrc2);
print_asm_template3(sll);
}
static inline make_EHelper(sra) {
rtl_andi(s, dsrc2, dsrc2, 0x3f);
rtl_sar(s, s0, dsrc1, dsrc2);
rtl_sar(s, ddest, dsrc1, dsrc2);
print_asm_template3(sra);
rtl_sr(s, id_dest->reg, s0, 4);
}
static inline make_EHelper(srl) {
......@@ -34,108 +25,163 @@ static inline make_EHelper(srl) {
exec_sra(s);
return;
}
rtl_andi(s, dsrc2, dsrc2, 0x3f);
rtl_shr(s, s0, dsrc1, dsrc2);
rtl_shr(s, ddest, dsrc1, dsrc2);
print_asm_template3(srl);
rtl_sr(s, id_dest->reg, s0, 4);
}
static inline make_EHelper(slt) {
rtl_setrelop(s, RELOP_LT, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_setrelop(s, RELOP_LT, ddest, dsrc1, dsrc2);
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);
rtl_setrelop(s, RELOP_LTU, ddest, dsrc1, dsrc2);
print_asm_template3(sltu);
}
static inline make_EHelper(xor) {
rtl_xor(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_xor(s, ddest, dsrc1, dsrc2);
print_asm_template3(xor);
}
static inline make_EHelper(or) {
rtl_or(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_or(s, ddest, dsrc1, dsrc2);
print_asm_template3(or);
}
static inline make_EHelper(and) {
rtl_and(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_and(s, ddest, dsrc1, dsrc2);
print_asm_template3(and);
}
static inline make_EHelper(auipc) {
rtl_shli(s, s0, dsrc2, 12);
rtl_add(s, s0, s0, &cpu.pc);
rtl_sr(s, id_dest->reg, s0, 4);
static inline make_EHelper(addi) {
rtl_addi(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(addi);
}
static inline make_EHelper(slli) {
rtl_shli(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(slli);
}
static inline make_EHelper(srai) {
rtl_sari(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(srai);
}
static inline make_EHelper(srli) {
// the LSB of funct7 may be "1" due to the shift amount can be >= 32
// this rule is disabled when a compressed inst comes in
if ((s->isa.instr.r.funct7 & ~0x1) == 32 && s->isa.instr.r.opcode1_0 == 0x3) {
exec_srai(s);
} else {
rtl_shri(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(srli);
}
}
static inline make_EHelper(slti) {
rtl_setrelopi(s, RELOP_LT, ddest, dsrc1, id_src2->imm);
print_asm_template3(slti);
}
static inline make_EHelper(sltui) {
rtl_setrelopi(s, RELOP_LTU, ddest, dsrc1, id_src2->imm);
print_asm_template3(sltui);
}
static inline make_EHelper(xori) {
rtl_xori(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(xori);
}
static inline make_EHelper(ori) {
rtl_ori(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(ori);
}
static inline make_EHelper(andi) {
rtl_andi(s, ddest, dsrc1, id_src2->imm);
print_asm_template3(andi);
}
static inline make_EHelper(auipc) {
rtl_li(s, ddest, id_src2->imm + cpu.pc);
print_asm("auipc " FMT_WORD ",%s", *s0, id_dest->str);
}
static inline make_EHelper(lui) {
rtl_shli(s, s0, dsrc2, 12);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_li(s, ddest, id_src2->imm);
print_asm("lui " FMT_WORD ",%s", *s0, id_dest->str);
}
static inline make_EHelper(addw) {
rtl_add(s, s0, dsrc1, dsrc2);
rtl_sext(s, s0, s0, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sext(s, ddest, s0, 4);
print_asm_template3(addw);
}
static inline make_EHelper(subw) {
rtl_sub(s, s0, dsrc1, dsrc2);
rtl_sext(s, s0, s0, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sext(s, ddest, s0, 4);
print_asm_template3(subw);
}
static inline make_EHelper(sllw) {
rtl_andi(s, dsrc2, dsrc2, 0x1f);
rtl_shl(s, s0, dsrc1, dsrc2);
rtl_sext(s, s0, s0, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_andi(s, s0, dsrc2, 0x1f);
rtl_shl(s, s0, dsrc1, s0);
rtl_sext(s, ddest, s0, 4);
print_asm_template3(sllw);
}
static inline make_EHelper(srlw) {
rtl_andi(s, dsrc2, dsrc2, 0x1f);
rtl_andi(s, s0, dsrc2, 0x1f);
assert((s->isa.instr.r.funct7 & 0x1) == 0);
if (s->isa.instr.r.funct7 == 32) {
// sraw
rtl_sext(s, dsrc1, dsrc1, 4);
rtl_sar(s, s0, dsrc1, dsrc2);
rtl_sext(s, s0, s0, 4);
rtl_sext(s, s1, dsrc1, 4);
rtl_sar(s, s0, s1, s0);
print_asm_template3(sraw);
}
else {
// srlw
rtl_andi(s, dsrc1, dsrc1, 0xffffffffu);
rtl_shr(s, s0, dsrc1, dsrc2);
rtl_sext(s, s0, s0, 4);
rtl_andi(s, s1, dsrc1, 0xffffffffu);
rtl_shr(s, s0, s1, s0);
print_asm_template3(srlw);
}
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sext(s, ddest, s0, 4);
}
static inline make_EHelper(sraw) {
exec_srlw(s);
}
static inline make_EHelper(addiw) {
rtl_addi(s, s0, dsrc1, id_src2->imm);
rtl_sext(s, ddest, s0, 4);
print_asm_template3(addiw);
}
static inline make_EHelper(slliw) {
rtl_shli(s, s0, dsrc1, id_src2->imm & 0x1f);
rtl_sext(s, ddest, s0, 4);
print_asm_template3(slliw);
}
static inline make_EHelper(srliw) {
assert((s->isa.instr.r.funct7 & 0x1) == 0);
if (s->isa.instr.r.funct7 == 32) {
// sraw
rtl_sext(s, s0, dsrc1, 4);
rtl_sari(s, s0, s0, id_src2->imm & 0x1f);
print_asm_template3(sraiw);
}
else {
// srlw
rtl_andi(s, s0, dsrc1, 0xffffffffu);
rtl_shri(s, s0, s0, id_src2->imm & 0x1f);
print_asm_template3(srliw);
}
rtl_sext(s, ddest, s0, 4);
}
#include <monitor/difftest.h>
static inline make_EHelper(jal) {
rtl_li(s, s0, s->seq_pc);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_li(s, ddest, s->seq_pc);
rtl_j(s, s->jmp_pc);
print_asm_template2(jal);
}
static inline make_EHelper(jalr) {
rtl_li(s, s0, s->seq_pc);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_add(s, s0, dsrc1, dsrc2);
rtl_addi(s, s0, dsrc1, id_src2->imm);
rtl_andi(s, s0, s0, ~0x1lu);
rtl_jr(s, s0);
rtl_li(s, ddest, s->seq_pc);
difftest_skip_dut(1, 2);
print_asm_template3(jalr);
......
......@@ -33,14 +33,14 @@ static inline make_EHelper(store) {
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)
EX(0, addi) EX(1, slli) EX(2, slti) EX(3, sltui)
EX(4, xori) EX(5, srli) EX(6, ori) EX(7, andi)
}
}
static inline make_EHelper(op_imm32) {
switch (s->isa.instr.i.funct3) {
EX(0, addw) EX(1, sllw) EX(5, srlw)
EX(0, addiw) EX(1, slliw) EX(5, srliw)
default: exec_inv(s);
}
}
......@@ -88,7 +88,7 @@ static inline make_EHelper(branch) {
static inline make_EHelper(system) {
switch (s->isa.instr.i.funct3) {
EX(0, priv) IDEX(1, csr, csrrw) IDEX(2, csr, csrrs) IDEX(3, csr, csrrc)
EMPTY(4) IDEX(5, csri, csrrw) IDEX(6, csri, csrrs) IDEX(7, csri, csrrc)
EMPTY(4) IDEX(5, csri, csrrwi)IDEX(6, csri, csrrsi)IDEX(7, csri, csrrci)
}
}
......@@ -132,9 +132,9 @@ 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)
IDEX (2, C_ADDI16SP, addi)
default: // and other cases
IDEX (1, CI_simm, lui)
IDEX (1, CI_simm_lui, lui)
}
}
......@@ -149,9 +149,9 @@ static inline make_EHelper(misc_alu) {
}
} else {
switch (op) {
IDEX (0, CB_shift, srl)
IDEX (1, CB_shift, sra)
IDEX (2, CB_andi, and)
IDEX (0, CB_shift, srli)
IDEX (1, CB_shift, srai)
IDEX (2, CB_andi, andi)
}
}
}
......@@ -182,9 +182,9 @@ static inline void exec(DecodeExecState *s) {
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 (000, I, 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 (010, S, 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)
......@@ -199,11 +199,11 @@ 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)
IDEX (000, C_ADDI4SPN, addi)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)
IDEX (010, CI_simm, addi)IDEX (011, CI_simm, addiw)IDEX (012, C_LI, addi)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)
IDEX (020, CI_uimm, slli)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);
}
......
#include "../local-include/intr.h"
static inline make_EHelper(ld) {
rtl_lm(s, s0, &id_src1->addr, s->width);
rtl_lm(s, s0, dsrc1, id_src2->imm, s->width);
check_mem_ex();
rtl_sr(s, id_dest->reg, s0, 0);
rtl_mv(s, ddest, s0);
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->imm, reg_name(id_src1->reg, 4));
switch (s->width) {
case 8: print_asm_template2(ld); break;
case 4: print_asm_template2(lwu); break;
......@@ -16,11 +17,11 @@ static inline make_EHelper(ld) {
// load sign value
static inline make_EHelper(lds) {
rtl_lm(s, s0, &id_src1->addr, s->width);
rtl_lm(s, s0, dsrc1, id_src2->imm, s->width);
check_mem_ex();
rtl_sext(s, s0, s0, s->width);
rtl_sr(s, id_dest->reg, s0, 0);
rtl_sext(s, ddest, s0, s->width);
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->imm, reg_name(id_src1->reg, 4));
switch (s->width) {
case 4: print_asm_template2(lw); break;
case 2: print_asm_template2(lh); break;
......@@ -30,9 +31,10 @@ static inline make_EHelper(lds) {
}
static inline make_EHelper(st) {
rtl_sm(s, &id_src1->addr, ddest, s->width);
rtl_sm(s, dsrc1, id_src2->imm, ddest, s->width);
check_mem_ex();
print_Dop(id_src1->str, OP_STR_SIZE, "%d(%s)", id_src2->imm, reg_name(id_src1->reg, 4));
switch (s->width) {
case 8: print_asm_template2(sd); break;
case 4: print_asm_template2(sw); break;
......
static inline make_EHelper(mul) {
rtl_mul_lo(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_mul_lo(s, ddest, dsrc1, dsrc2);
print_asm_template3(mul);
}
static inline make_EHelper(mulh) {
rtl_imul_hi(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_imul_hi(s, ddest, dsrc1, dsrc2);
print_asm_template3(mulh);
}
static inline make_EHelper(mulhu) {
rtl_mul_hi(s, s0, dsrc1, dsrc2);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_mul_hi(s, ddest, dsrc1, dsrc2);
print_asm_template3(mulhu);
}
......@@ -37,66 +31,58 @@ static inline make_EHelper(mulhsu) {
rtl_sari(s, s0, dsrc1, 63);
rtl_and(s, s0, dsrc2, s0); // s0 = (id_src1->val < 0 ? id_src2->val : 0)
rtl_mul_hi(s, s1, dsrc1, dsrc2);
rtl_sub(s, s0, s1, s0);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sub(s, ddest, s1, s0);
print_asm_template3(mulhsu);
}
static inline make_EHelper(div) {
if (*dsrc2 == 0) {
rtl_li(s, s0, ~0lu);
rtl_li(s, ddest, ~0lu);
} else if (*dsrc1 == 0x8000000000000000LL && *dsrc2 == -1) {
rtl_mv(s, s0, dsrc1);
rtl_mv(s, ddest, dsrc1);
} else {
rtl_idiv_q(s, s0, dsrc1, dsrc2);
rtl_idiv_q(s, ddest, dsrc1, dsrc2);
}
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(div);
}
static inline make_EHelper(divu) {
if (*dsrc2 == 0) {
rtl_li(s, s0, ~0lu);
rtl_li(s, ddest, ~0lu);
} else {
rtl_div_q(s, s0, dsrc1, dsrc2);
rtl_div_q(s, ddest, dsrc1, dsrc2);
}
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(divu);
}
static inline make_EHelper(rem) {
if (*dsrc2 == 0) {
rtl_mv(s, s0, dsrc1);
rtl_mv(s, ddest, dsrc1);
} else if (*dsrc1 == 0x8000000000000000LL && *dsrc2 == -1) {
rtl_li(s, s0, 0);
rtl_li(s, ddest, 0);
} else {
rtl_idiv_r(s, s0, dsrc1, dsrc2);
rtl_idiv_r(s, ddest, dsrc1, dsrc2);
}
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(rem);
}
static inline make_EHelper(remu) {
if (*dsrc2 == 0) {
rtl_mv(s, s0, dsrc1);
rtl_mv(s, ddest, dsrc1);
} else {
rtl_div_r(s, s0, dsrc1, dsrc2);
rtl_div_r(s, ddest, dsrc1, dsrc2);
}
rtl_sr(s, id_dest->reg, s0, 4);
print_asm_template3(remu);
}
static inline make_EHelper(mulw) {
rtl_mul_lo(s, s0, dsrc1, dsrc2);
rtl_sext(s, s0, s0, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sext(s, ddest, s0, 4);
print_asm_template3(mulw);
}
......@@ -110,8 +96,7 @@ static inline make_EHelper(divw) {
} else {
rtl_idiv_q(s, s0, s0, s1);
}
rtl_sext(s, s0, s0, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sext(s, ddest, s0, 4);
print_asm_template3(divw);
}
......@@ -126,8 +111,7 @@ static inline make_EHelper(remw) {
} else {
rtl_idiv_r(s, s0, s0, s1);
}
rtl_sext(s, s0, s0, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sext(s, ddest, s0, 4);
print_asm_template3(remw);
}
......@@ -140,8 +124,7 @@ static inline make_EHelper(divuw) {
} else {
rtl_div_q(s, s0, s0, s1);
}
rtl_sext(s, s0, s0, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sext(s, ddest, s0, 4);
print_asm_template3(divuw);
}
......@@ -154,8 +137,7 @@ static inline make_EHelper(remuw) {
} else {
rtl_div_r(s, s0, s0, s1);
}
rtl_sext(s, s0, s0, 4);
rtl_sr(s, id_dest->reg, s0, 4);
rtl_sext(s, ddest, s0, 4);
print_asm_template3(remuw);
}
......@@ -14,42 +14,79 @@ static inline bool csr_check(DecodeExecState *s, uint32_t addr) {
}
static inline make_EHelper(csrrw) {
uint32_t addr = *dsrc2;
uint32_t addr = id_src2->imm;
if (!csr_check(s, addr)) return;
csr_read(s0, addr);
rtl_sr(s, id_dest->reg, s0, 8);
csr_write(addr, dsrc1);
rtl_mv(s, ddest, s0);
print_asm_template3("csrrw");
}
static inline make_EHelper(csrrs) {
uint32_t addr = *dsrc2;
uint32_t addr = id_src2->imm;
if (!csr_check(s, addr)) return;
csr_read(s0, addr);
rtl_sr(s, id_dest->reg, s0, 8);
if (id_src1->reg != 0) {
rtl_or(s, s0, s0, dsrc1);
csr_write(addr, s0);
rtl_or(s, s1, s0, dsrc1);
csr_write(addr, s1);
}
rtl_mv(s, ddest, s0);
print_asm_template3("csrrs");
}
static inline make_EHelper(csrrc) {
uint32_t addr = id_src2->val;
uint32_t addr = id_src2->imm;
if (!csr_check(s, addr)) return;
csr_read(s0, addr);
rtl_sr(s, id_dest->reg, s0, 8);
if (id_src1->reg != 0) {
rtl_not(s, s1, dsrc1);
rtl_and(s, s0, s0, s1);
csr_write(addr, s0);
rtl_and(s, s1, s0, s1);
csr_write(addr, s1);
}
rtl_mv(s, ddest, s0);
print_asm_template3("csrrc");
}
static inline make_EHelper(csrrwi) {
uint32_t addr = id_src2->imm;
if (!csr_check(s, addr)) return;
csr_read(s0, addr);
rtl_li(s, s1, id_src1->imm);
csr_write(addr, s1);
rtl_mv(s, ddest, s0);
print_asm_template3("csrrwi");
}
static inline make_EHelper(csrrsi) {
uint32_t addr = id_src2->imm;
if (!csr_check(s, addr)) return;
csr_read(s0, addr);
if (id_src1->reg != 0) {
rtl_ori(s, s1, s0, id_src1->imm);
csr_write(addr, s1);
}
rtl_mv(s, ddest, s0);
print_asm_template3("csrrsi");
}
static inline make_EHelper(csrrci) {
uint32_t addr = id_src2->imm;
if (!csr_check(s, addr)) return;
csr_read(s0, addr);
if (id_src1->reg != 0) {
rtl_andi(s, s1, s0, ~id_src1->imm);
csr_write(addr, s1);
}
rtl_mv(s, ddest, s0);
print_asm_template3("csrrci");
}
static inline make_EHelper(priv) {
uint32_t type = s->isa.instr.csr.csr;
switch (type) {
......
......@@ -8,7 +8,6 @@
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, "%ld", op->imm);
}
......@@ -16,9 +15,8 @@ static inline make_DopHelper(i) {
static inline make_DopHelper(r) {
op->type = OP_TYPE_REG;
op->reg = val;
if (load_val) {
rtl_lr(s, &op->val, op->reg, 4);
}
op->preg = &reg_l(val);
reg_l(0) = 0;
print_Dop(op->str, OP_STR_SIZE, "%s", reg_name(op->reg, 4));
}
......@@ -36,8 +34,7 @@ static inline make_DHelper(R) {
}
static inline make_DHelper(U) {
// shift at execute stage
decode_op_i(s, id_src2, (sword_t)s->isa.instr.u.simm31_12, true);
decode_op_i(s, id_src2, (sword_t)s->isa.instr.u.simm31_12 << 12, true);
decode_op_r(s, id_dest, s->isa.instr.u.rd, false);
print_Dop(id_src2->str, OP_STR_SIZE, "0x%x", s->isa.instr.u.simm31_12);
......@@ -47,7 +44,6 @@ 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%lx", s->jmp_pc);
decode_op_r(s, id_dest, s->isa.instr.j.rd, false);
......@@ -57,33 +53,16 @@ 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%lx", s->jmp_pc);
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_op_r(s, id_src1, s->isa.instr.i.rs1, true);
decode_op_i(s, id_src2, s->isa.instr.i.simm11_0, true);
print_Dop(id_src1->str, OP_STR_SIZE, "%ld(%s)", id_src2->val, reg_name(id_src1->reg, 4));
rtl_add(s, &id_src1->addr, dsrc1, dsrc2);
decode_op_r(s, id_dest, s->isa.instr.i.rd, false);
}
static inline make_DHelper(st) {
static inline make_DHelper(S) {
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);
print_Dop(id_src1->str, OP_STR_SIZE, "%ld(%s)", id_src2->val, reg_name(id_src1->reg, 4));
rtl_add(s, &id_src1->addr, dsrc1, dsrc2);
decode_op_r(s, id_dest, s->isa.instr.s.rs2, true);
}
......@@ -146,6 +125,11 @@ static inline make_DHelper(CI_simm) {
decode_op_rd_rs1_imm6(s, true, 0, 0, false);
}
static inline make_DHelper(CI_simm_lui) {
decode_CI_simm(s);
id_src2->imm <<= 12;
}
// for shift
static inline make_DHelper(CI_uimm) {
decode_op_rd_rs1_imm6(s, false, 0, 0, false);
......@@ -170,7 +154,6 @@ static inline make_DHelper(C_ADDI16SP) {
static inline void decode_C_xxSP(DecodeExecState *s, uint32_t imm6, int rotate) {
decode_op_r(s, id_src1, 2, true);
decode_op_C_imm6(s, imm6, false, 0, rotate);
rtl_add(s, &id_src1->addr, dsrc1, dsrc2);
}
static inline void decode_C_LxSP(DecodeExecState *s, int rotate) {
......@@ -226,7 +209,6 @@ static inline void decode_C_ldst_common(DecodeExecState *s, int rotate, bool is_
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);
decode_op_r(s, id_dest, creg2reg(BITS(instr, 4, 2)), is_store);
}
......@@ -311,7 +293,9 @@ static inline void decode_C_rs1_rs2_rd(DecodeExecState *s, bool is_rs1_zero, boo
}
static inline make_DHelper(C_JR) {
decode_C_rs1_rs2_rd(s, false, false, true);
decode_op_r(s, id_src1, BITS(s->isa.instr.val, 11, 7), true);
decode_op_i(s, id_src2, 0, true);
decode_op_r(s, id_dest, 0, false);
}
static inline make_DHelper(C_MOV) {
......@@ -324,6 +308,6 @@ static inline make_DHelper(C_ADD) {
static inline make_DHelper(C_JALR) {
decode_op_r(s, id_src1, BITS(s->isa.instr.val, 11, 7), true);
decode_op_r(s, id_src2, 0, true);
decode_op_i(s, id_src2, 0, true);
decode_op_r(s, id_dest, 1, false);
}
#include <cpu/exec.h>
#include "local-include/rtl.h"
#include "local-include/reg.h"
#include "local-include/decode.h"
typedef union {
struct {
......@@ -30,7 +31,6 @@ static inline void load_addr(DecodeExecState *s, ModR_M *m, Operand *rm) {
sword_t disp = 0;
int disp_size = 4;
int base_reg = -1, index_reg = -1, scale = 0;
rtl_li(s, s0, 0);
if (m->R_M == R_ESP) {
SIB sib;
......@@ -55,19 +55,15 @@ static inline void load_addr(DecodeExecState *s, ModR_M *m, Operand *rm) {
/* has disp */
disp = instr_fetch(&s->seq_pc, disp_size);
if (disp_size == 1) { disp = (int8_t)disp; }
rtl_addi(s, s0, s0, disp);
}
if (base_reg != -1) {
rtl_add(s, s0, s0, &reg_l(base_reg));
}
s->isa.mbase = (base_reg != -1 ? &reg_l(base_reg) : rz);
if (index_reg != -1) {
rtl_shli(s, s1, &reg_l(index_reg), scale);
rtl_add(s, s0, s0, s1);
rtl_add(s, &s->isa.mbr, s->isa.mbase, s1);
s->isa.mbase = &s->isa.mbr;
}
rtl_mv(s, &rm->addr, s0);
s->isa.moff = disp;
#ifdef DEBUG
char disp_buf[16];
......@@ -105,33 +101,13 @@ void read_ModR_M(DecodeExecState *s, Operand *rm, bool load_rm_val, Operand *reg
ModR_M m;
m.val = instr_fetch(&s->seq_pc, 1);
s->isa.ext_opcode = m.opcode;
if (reg != NULL) {
reg->type = OP_TYPE_REG;
reg->reg = m.reg;
if (load_reg_val) {
rtl_lr(s, &reg->val, reg->reg, reg->width);
}
#ifdef DEBUG
snprintf(reg->str, OP_STR_SIZE, "%%%s", reg_name(reg->reg, reg->width));
#endif
}
if (m.mod == 3) {
rm->type = OP_TYPE_REG;
rm->reg = m.R_M;
if (load_rm_val) {
rtl_lr(s, &rm->val, m.R_M, rm->width);
}
#ifdef DEBUG
sprintf(rm->str, "%%%s", reg_name(m.R_M, rm->width));
#endif
}
if (reg != NULL) operand_reg(s, reg, load_reg_val, m.reg, reg->width);
if (m.mod == 3) operand_reg(s, rm, load_rm_val, m.R_M, rm->width);
else {
load_addr(s, &m, rm);
if (load_rm_val) {
rtl_lm(s, &rm->val, &rm->addr, rm->width);
rtl_lm(s, &rm->val, s->isa.mbase, s->isa.moff, rm->width);
rm->preg = &rm->val;
}
}
}
......@@ -96,7 +96,8 @@ static inline make_EHelper(movzx) {
}
static inline make_EHelper(lea) {
operand_write(s, id_dest, &id_src1->addr);
rtl_addi(s, s0, s->isa.mbase, s->isa.moff);
operand_write(s, id_dest, s0);
print_asm_template2(lea);
}
......
static make_EHelper(movs) {
rtl_lm(s, s0, &cpu.esi, id_dest->width);
rtl_sm(s, &cpu.edi, s0, id_dest->width);
rtl_lm(s, s0, &cpu.esi, 0, id_dest->width);
rtl_sm(s, &cpu.edi, 0, s0, id_dest->width);
rtl_addi(s, &cpu.esi, &cpu.esi, id_dest->width);
rtl_addi(s, &cpu.edi, &cpu.edi, id_dest->width);
......
#include <monitor/difftest.h>
static make_EHelper(lidt) {
cpu.idtr.limit = vaddr_read(id_dest->addr, 2);
cpu.idtr.base = vaddr_read(id_dest->addr + 2, 4);
word_t addr = *s->isa.mbase + s->isa.moff;
cpu.idtr.limit = vaddr_read(addr, 2);
cpu.idtr.base = vaddr_read(addr + 2, 4);
print_asm_template1(lidt);
}
......
......@@ -8,11 +8,9 @@ void raise_intr(DecodeExecState *s, uint32_t NO, vaddr_t ret_addr) {
//TODO();
assert(NO < 256);
vaddr_t base = cpu.idtr.base + (NO << 3);
rtl_li(s, s0, base);
rtl_lm(s, s1, s0, 4);
rtl_addi(s, s0, s0, 4);
rtl_lm(s, s0, s0, 4);
rtl_li(s, s0, cpu.idtr.base);
rtl_lm(s, s1, s0, NO << 3, 4);
rtl_lm(s, s0, s0, (NO << 3) + 4, 4);
// check the present bit
assert((*s0 >> 15) & 0x1);
......
......@@ -3,6 +3,31 @@
void read_ModR_M(DecodeExecState *s, Operand *rm, bool load_rm_val, Operand *reg, bool load_reg_val);
static inline void operand_reg(DecodeExecState *s, Operand *op, bool load_val, int r, int width) {
op->type = OP_TYPE_REG;
op->reg = r;
if (width == 4) {
op->preg = &reg_l(r);
} else {
assert(width == 1 || width == 2);
op->preg = &op->val;
if (load_val) rtl_lr(s, &op->val, r, width);
}
print_Dop(op->str, OP_STR_SIZE, "%%%s", reg_name(r, width));
}
static inline void operand_imm(DecodeExecState *s, Operand *op, bool load_val, word_t imm, int width) {
op->type = OP_TYPE_IMM;
op->imm = imm;
if (load_val) {
rtl_li(s, &op->val, imm);
op->preg = &op->val;
}
print_Dop(op->str, OP_STR_SIZE, "$0x%x", imm);
}
// decode operand helper
#define make_DopHelper(name) void concat(decode_op_, name) (DecodeExecState *s, Operand *op, bool load_val)
......@@ -11,11 +36,8 @@ void read_ModR_M(DecodeExecState *s, Operand *rm, bool load_rm_val, Operand *reg
/* Ib, Iv */
static inline make_DopHelper(I) {
/* pc here is pointing to the immediate */
op->type = OP_TYPE_IMM;
op->imm = instr_fetch(&s->seq_pc, op->width);
rtl_li(s, &op->val, op->imm);
print_Dop(op->str, OP_STR_SIZE, "$0x%x", op->imm);
word_t imm = instr_fetch(&s->seq_pc, op->width);
operand_imm(s, op, load_val, imm, op->width);
}
/* I386 manual does not contain this abbreviation, but it is different from
......@@ -26,20 +48,15 @@ static inline make_DopHelper(I) {
static inline make_DopHelper(SI) {
assert(op->width == 1 || op->width == 4);
op->type = OP_TYPE_IMM;
/* TODO: Use instr_fetch() to read `op->width' bytes of memory
* pointed by 'pc'. Interpret the result as a signed immediate,
* and assign it to op->simm.
*
op->simm = ???
*/
op->simm = instr_fetch(&s->seq_pc, op->width);
if (op->width == 1) op->simm = (int8_t)op->simm;
rtl_li(s, &op->val, op->simm);
print_Dop(op->str, OP_STR_SIZE, "$0x%x", op->simm);
word_t imm = instr_fetch(&s->seq_pc, op->width);
if (op->width == 1) imm = (int8_t)imm;
operand_imm(s, op, load_val, imm, op->width);
}
/* I386 manual does not contain this abbreviation.
......@@ -47,13 +64,7 @@ static inline make_DopHelper(SI) {
*/
/* AL/eAX */
static inline make_DopHelper(a) {
op->type = OP_TYPE_REG;
op->reg = R_EAX;
if (load_val) {
rtl_lr(s, &op->val, R_EAX, op->width);
}
print_Dop(op->str, OP_STR_SIZE, "%%%s", reg_name(R_EAX, op->width));
operand_reg(s, op, load_val, R_EAX, op->width);
}
/* This helper function is use to decode register encoded in the opcode. */
......@@ -61,17 +72,11 @@ static inline make_DopHelper(a) {
* eXX: eAX, eCX, eDX, eBX, eSP, eBP, eSI, eDI
*/
static inline make_DopHelper(r) {
op->type = OP_TYPE_REG;
op->reg = s->opcode & 0x7;
if (load_val) {
rtl_lr(s, &op->val, op->reg, op->width);
}
print_Dop(op->str, OP_STR_SIZE, "%%%s", reg_name(op->reg, op->width));
operand_reg(s, op, load_val, s->opcode & 0x7, op->width);
}
/* I386 manual does not contain this abbreviation.
* We decode everything of modR/M byte by one time.
* We decode everything of modR/M byte in one time.
*/
/* Eb, Ew, Ev
* Gb, Gv
......@@ -80,45 +85,47 @@ static inline make_DopHelper(r) {
* Rd
* Sw
*/
static inline void decode_op_rm(DecodeExecState *s, Operand *rm, bool load_rm_val, Operand *reg, bool load_reg_val) {
static inline void operand_rm(DecodeExecState *s, Operand *rm, bool load_rm_val, Operand *reg, bool load_reg_val) {
read_ModR_M(s, rm, load_rm_val, reg, load_reg_val);
}
/* Ob, Ov */
static inline make_DopHelper(O) {
op->type = OP_TYPE_MEM;
rtl_li(s, &op->addr, instr_fetch(&s->seq_pc, 4));
s->isa.moff = instr_fetch(&s->seq_pc, 4);
s->isa.mbase = rz;
if (load_val) {
rtl_lm(s, &op->val, &op->addr, op->width);
rtl_lm(s, &op->val, s->isa.mbase, s->isa.moff, op->width);
op->preg = &op->val;
}
print_Dop(op->str, OP_STR_SIZE, "0x%x", op->addr);
print_Dop(op->str, OP_STR_SIZE, "0x%x", s->isa.moff);
}
/* Eb <- Gb
* Ev <- Gv
*/
static inline make_DHelper(G2E) {
decode_op_rm(s, id_dest, true, id_src1, true);
operand_rm(s, id_dest, true, id_src1, true);
}
static inline make_DHelper(mov_G2E) {
decode_op_rm(s, id_dest, false, id_src1, true);
operand_rm(s, id_dest, false, id_src1, true);
}
/* Gb <- Eb
* Gv <- Ev
*/
static inline make_DHelper(E2G) {
decode_op_rm(s, id_src1, true, id_dest, true);
operand_rm(s, id_src1, true, id_dest, true);
}
static inline make_DHelper(mov_E2G) {
decode_op_rm(s, id_src1, true, id_dest, false);
operand_rm(s, id_src1, true, id_dest, false);
}
static inline make_DHelper(lea_M2G) {
decode_op_rm(s, id_src1, false, id_dest, false);
operand_rm(s, id_src1, false, id_dest, false);
}
/* AL <- Ib
......@@ -133,7 +140,7 @@ static inline make_DHelper(I2a) {
* Gv <- EvIv
* use for imul */
static inline make_DHelper(I_E2G) {
decode_op_rm(s, id_src2, true, id_dest, false);
operand_rm(s, id_src2, true, id_dest, false);
decode_op_I(s, id_src1, true);
}
......@@ -141,12 +148,12 @@ static inline make_DHelper(I_E2G) {
* Ev <- Iv
*/
static inline make_DHelper(I2E) {
decode_op_rm(s, id_dest, true, NULL, false);
operand_rm(s, id_dest, true, NULL, false);
decode_op_I(s, id_src1, true);
}
static inline make_DHelper(mov_I2E) {
decode_op_rm(s, id_dest, false, NULL, false);
operand_rm(s, id_dest, false, NULL, false);
decode_op_I(s, id_src1, true);
}
......@@ -173,15 +180,15 @@ static inline make_DHelper(r) {
}
static inline make_DHelper(E) {
decode_op_rm(s, id_dest, true, NULL, false);
operand_rm(s, id_dest, true, NULL, false);
}
static inline make_DHelper(setcc_E) {
decode_op_rm(s, id_dest, false, NULL, false);
operand_rm(s, id_dest, false, NULL, false);
}
static inline make_DHelper(gp7_E) {
decode_op_rm(s, id_dest, false, NULL, false);
operand_rm(s, id_dest, false, NULL, false);
}
/* used by test in group3 */
......@@ -191,7 +198,7 @@ static inline make_DHelper(test_I) {
static inline make_DHelper(SI2E) {
assert(id_dest->width == 2 || id_dest->width == 4);
decode_op_rm(s, id_dest, true, NULL, false);
operand_rm(s, id_dest, true, NULL, false);
id_src1->width = 1;
decode_op_SI(s, id_src1, true);
if (id_dest->width == 2) {
......@@ -201,7 +208,7 @@ static inline make_DHelper(SI2E) {
static inline make_DHelper(SI_E2G) {
assert(id_dest->width == 2 || id_dest->width == 4);
decode_op_rm(s, id_src2, true, id_dest, false);
operand_rm(s, id_src2, true, id_dest, false);
id_src1->width = 1;
decode_op_SI(s, id_src1, true);
if (id_dest->width == 2) {
......@@ -210,25 +217,17 @@ static inline make_DHelper(SI_E2G) {
}
static inline make_DHelper(gp2_1_E) {
decode_op_rm(s, id_dest, true, NULL, false);
id_src1->type = OP_TYPE_IMM;
id_src1->imm = 1;
rtl_li(s, dsrc1, 1);
print_Dop(id_src1->str, OP_STR_SIZE, "$1");
operand_rm(s, id_dest, true, NULL, false);
operand_imm(s, id_src1, true, 1, 1);
}
static inline make_DHelper(gp2_cl2E) {
decode_op_rm(s, id_dest, true, NULL, false);
id_src1->type = OP_TYPE_REG;
id_src1->reg = R_CL;
rtl_lr(s, dsrc1, R_CL, 1);
print_Dop(id_src1->str, OP_STR_SIZE, "%%cl");
operand_rm(s, id_dest, true, NULL, false);
operand_reg(s, id_src1, true, R_CL, 1);
}
static inline make_DHelper(gp2_Ib2E) {
decode_op_rm(s, id_dest, true, NULL, false);
operand_rm(s, id_dest, true, NULL, false);
id_src1->width = 1;
decode_op_I(s, id_src1, true);
}
......@@ -236,7 +235,7 @@ static inline make_DHelper(gp2_Ib2E) {
/* Ev <- GvIb
* use for shld/shrd */
static inline make_DHelper(Ib_G2E) {
decode_op_rm(s, id_dest, true, id_src2, true);
operand_rm(s, id_dest, true, id_src2, true);
id_src1->width = 1;
decode_op_I(s, id_src1, true);
}
......@@ -244,12 +243,8 @@ static inline make_DHelper(Ib_G2E) {
/* Ev <- GvCL
* use for shld/shrd */
static inline make_DHelper(cl_G2E) {
decode_op_rm(s, id_dest, true, id_src2, true);
id_src1->type = OP_TYPE_REG;
id_src1->reg = R_CL;
rtl_lr(s, dsrc1, R_CL, 1);
print_Dop(id_src1->str, OP_STR_SIZE, "%%cl");
operand_rm(s, id_dest, true, id_src2, true);
operand_reg(s, id_src1, true, R_CL, 1);
}
static inline make_DHelper(O2a) {
......@@ -279,12 +274,7 @@ static inline make_DHelper(in_I2a) {
}
static inline make_DHelper(in_dx2a) {
id_src1->type = OP_TYPE_REG;
id_src1->reg = R_DX;
rtl_lr(s, dsrc1, R_DX, 2);
print_Dop(id_src1->str, OP_STR_SIZE, "(%%dx)");
operand_reg(s, id_src1, true, R_DX, 2);
decode_op_a(s, id_dest, false);
}
......@@ -296,16 +286,11 @@ static inline make_DHelper(out_a2I) {
static inline make_DHelper(out_a2dx) {
decode_op_a(s, id_src1, true);
id_dest->type = OP_TYPE_REG;
id_dest->reg = R_DX;
rtl_lr(s, ddest, R_DX, 2);
print_Dop(id_dest->str, OP_STR_SIZE, "(%%dx)");
operand_reg(s, id_dest, true, R_DX, 2);
}
static inline void operand_write(DecodeExecState *s, Operand *op, rtlreg_t* src) {
if (op->type == OP_TYPE_REG) { rtl_sr(s, op->reg, src, op->width); }
else if (op->type == OP_TYPE_MEM) { rtl_sm(s, &op->addr, src, op->width); }
else if (op->type == OP_TYPE_MEM) { rtl_sm(s, s->isa.mbase, s->isa.moff, src, op->width); }
else { assert(0); }
}
......@@ -29,14 +29,14 @@ static inline make_rtl(push, const rtlreg_t* src1) {
// M[esp] <- src1
// TODO();
rtl_subi(s, &cpu.esp, &cpu.esp, 4);
rtl_sm(s, &cpu.esp, src1, 4);
rtl_sm(s, &cpu.esp, 0, src1, 4);
}
static inline make_rtl(pop, rtlreg_t* dest) {
// dest <- M[esp]
// esp <- esp + 4
// TODO();
rtl_lm(s, dest, &cpu.esp, 4);
rtl_lm(s, dest, &cpu.esp, 0, 4);
rtl_addi(s, &cpu.esp, &cpu.esp, 4);
}
......
......@@ -19,6 +19,7 @@
CPU_state cpu;
NEMUState nemu_state = {.state = NEMU_STOP};
static uint64_t g_nr_guest_instr = 0;
const rtlreg_t rzero = 0;
void asm_print(vaddr_t ori_pc, int instr_len, bool print_flag);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册