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

Merge branch 'reg_spilling' into 'master'

Reg spilling

See merge request projectn/nemu!54
......@@ -58,6 +58,7 @@ CC = gcc
LD = gcc
INCLUDES = $(addprefix -I, $(INC_DIR))
CFLAGS += -O2 -MMD -Wall -Werror -ggdb3 $(INCLUDES) \
-D__ENGINE_$(ENGINE)__ \
-D__ISA__=$(ISA) -D__ISA_$(ISA)__ -D_ISA_H_=\"isa/$(ISA).h\"
# Files to be compiled
......
......@@ -4,7 +4,11 @@
#include <common.h>
// memory
#ifdef __ENGINE_rv64__
#define riscv64_IMAGE_START 0x100000
#else
#define riscv64_IMAGE_START 0x0
#endif
#define riscv64_PMEM_BASE 0x80000000
// reg
......
......@@ -41,6 +41,20 @@ static inline make_rtl(sext, rtlreg_t* dest, const rtlreg_t* src1, int width) {
}
}
static inline make_rtl(zext, rtlreg_t* dest, const rtlreg_t* src1, int width) {
// dest <- zeroext(src1[(width * 8 - 1) .. 0])
// TODO();
const int word_size = sizeof(word_t);
if (width == word_size) {
rtl_mv(s, dest, src1);
} else {
assert(width == 1 || width == 2 || width == 4);
rtl_shli(s, dest, src1, (word_size - width) * 8);
rtl_shri(s, dest, dest, (word_size - width) * 8);
}
}
static inline make_rtl(msb, rtlreg_t* dest, const rtlreg_t* src1, int width) {
// dest <- src1[width * 8 - 1]
// TODO();
......
......@@ -95,7 +95,8 @@ static void sdcard_io_handler(uint32_t offset, int len, bool is_write) {
case SDDATA:
// TODO
if (!write_cmd && fp) {
fread(&base[SDDATA], 4, 1, fp);
__attribute__((unused)) int ret;
ret = fread(&base[SDDATA], 4, 1, fp);
}
addr += 4;
break;
......
......@@ -12,6 +12,7 @@ void (*backend_exec)(uint64_t n) = NULL;
void backend_exec_code(uint64_t pc, int nr_instr);
void guest_setregs(const CPU_state *cpu);
void spill_init();
static void init_rv64_interpreter() {
char so_file[256];
......@@ -75,6 +76,7 @@ static void init_rv64_reg() {
backend_getregs(&r);
r.gpr[mask32]._64 = 0x00000000fffffffful;
r.gpr[mask16]._64 = 0x000000000000fffful;
if (spm_base != 0) r.gpr[spm_base]._64 = riscv64_PMEM_BASE;
backend_setregs(&r);
}
......@@ -85,4 +87,5 @@ void init_engine() {
backend_exec_code(riscv64_PMEM_BASE, 100);
guest_setregs(&cpu);
init_rv64_reg();
spill_init();
}
......@@ -6,27 +6,31 @@
#include <isa/riscv64.h>
#include "../tran.h"
uint32_t reg_ptr2idx(DecodeExecState *s, const rtlreg_t* dest) {
uint32_t rtlreg2varidx(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) {
int idx = dest - gpr_start;
switch (idx) { // idx
case 28: assert(0); break; // gp
case 1: case 26: case 27: break; // at, k0, k1
case 25: assert(0); break; // t9
default: return idx;
int rvidx = dest - gpr_start;
switch (rvidx) {
case tmp0: return 1 | SPMIDX_MASK; // fixed to tmp0
case spm_base: return 2 | SPMIDX_MASK; // used to store sratchpad addr
case tmp_reg1: return 3 | SPMIDX_MASK; // tmp_reg 1
case tmp_reg2: return 4 | SPMIDX_MASK; // tmp_reg 2
case mask32: return 5 | SPMIDX_MASK; // fixed to mask32
default: return rvidx;
}
}
if (dest == rz) return 0;
// other temps
if (dest == &cpu.lo) return 6 | SPMIDX_MASK;
if (dest == &cpu.hi) return 7 | SPMIDX_MASK;
if (dest == s0) return 8 | SPMIDX_MASK;
if (dest == s1) return 9 | SPMIDX_MASK;
#define CASE(ptr, idx) if (dest == ptr) return idx;
CASE(rz, 0)
CASE(&cpu.lo, 25)
CASE(&cpu.hi, 27)
CASE(s0, 26)
//CASE(s1, 27)
panic("bad ptr = %p", dest);
return 0;
}
void guest_getregs(CPU_state *mips32) {
......@@ -35,10 +39,11 @@ void guest_getregs(CPU_state *mips32) {
int i;
for (i = 0; i < 32; i ++) {
switch (i) {
case 28: case 1: case 26: case 27: case 25: continue;
case tmp0: case mask32: case spm_base: case tmp_reg1: case tmp_reg2: continue;
}
mips32->gpr[i]._32 = r.gpr[i]._64;
}
// FIXME: these are wrong
mips32->lo = r.gpr[25]._64;
mips32->hi = r.gpr[27]._64;
}
......@@ -49,10 +54,11 @@ void guest_setregs(const CPU_state *mips32) {
int i;
for (i = 0; i < 32; i ++) {
switch (i) {
case 28: case 1: case 26: case 27: case 25: continue;
case tmp0: case mask32: case spm_base: case tmp_reg1: case tmp_reg2: continue;
}
r.gpr[i]._64 = mips32->gpr[i]._32;
}
// FIXME: these are wrong
r.gpr[25]._64 = mips32->lo;
r.gpr[27]._64 = mips32->hi;
backend_setregs(&r);
......
......@@ -6,22 +6,29 @@
#include <isa/riscv64.h>
#include "../tran.h"
uint32_t reg_ptr2idx(DecodeExecState *s, const rtlreg_t* dest) {
uint32_t rtlreg2varidx(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) {
int idx = dest - gpr_start;
switch (idx) { // idx
case 3: case 4: case 31: assert(0); break; // gp, tp, t6
default: return idx;
int rvidx = dest - gpr_start;
switch (rvidx) {
case tmp0: return 1 | SPMIDX_MASK; // fixed to tmp0
case spm_base: return 2 | SPMIDX_MASK; // used to store sratchpad addr
case tmp_reg1: return 3 | SPMIDX_MASK; // tmp_reg 1
case tmp_reg2: return 4 | SPMIDX_MASK; // tmp_reg 2
case mask32: return 5 | SPMIDX_MASK; // fixed to mask32
default: return rvidx;
}
}
if (dest == rz) return 0;
// other temps
if (dest == s0) return 6 | SPMIDX_MASK;
if (dest == s1) return 7 | SPMIDX_MASK;
#define CASE(ptr, idx) if (dest == ptr) return idx;
CASE(rz, 0)
CASE(s0, 31)
panic("bad ptr = %p", dest);
return 0;
}
void guest_getregs(CPU_state *riscv32) {
......@@ -30,7 +37,7 @@ void guest_getregs(CPU_state *riscv32) {
int i;
for (i = 0; i < 32; i ++) {
switch (i) {
case 3: case 4: case 31: continue;
case tmp0: case mask32: case spm_base: case tmp_reg1: case tmp_reg2: continue;
}
riscv32->gpr[i]._32 = r.gpr[i]._64;
}
......@@ -42,7 +49,7 @@ void guest_setregs(const CPU_state *riscv32) {
int i;
for (i = 0; i < 32; i ++) {
switch (i) {
case 3: case 4: case 31: continue;
case tmp0: case mask32: case spm_base: case tmp_reg1: case tmp_reg2: continue;
}
r.gpr[i]._64 = riscv32->gpr[i]._32;
}
......
#ifdef __ISA_riscv64__
#include <cpu/decode.h>
#include <rtl/rtl.h>
#include <isa.h>
#include <isa/riscv64.h>
#include "../tran.h"
uint32_t rtlreg2varidx(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) {
int rvidx = dest - gpr_start;
switch (rvidx) {
case tmp0: return 1 | SPMIDX_MASK; // fixed to tmp0
case spm_base: return 2 | SPMIDX_MASK; // used to store sratchpad addr
case tmp_reg1: return 3 | SPMIDX_MASK; // tmp_reg 1
case tmp_reg2: return 4 | SPMIDX_MASK; // tmp_reg 2
default: return rvidx;
}
}
if (dest == rz) return 0;
// other temps
if (dest == s0) return 6 | SPMIDX_MASK;
if (dest == s1) return 7 | SPMIDX_MASK;
panic("bad ptr = %p", dest);
return 0;
}
void guest_getregs(CPU_state *riscv64) {
riscv64_CPU_state r;
backend_getregs(&r);
int i;
for (i = 0; i < 32; i ++) {
switch (i) {
case tmp0: case spm_base: case tmp_reg1: case tmp_reg2: continue;
}
riscv64->gpr[i]._64 = r.gpr[i]._64;
}
}
void guest_setregs(const CPU_state *riscv64) {
riscv64_CPU_state r;
backend_getregs(&r);
int i;
for (i = 0; i < 32; i ++) {
switch (i) {
case tmp0: case spm_base: case tmp_reg1: case tmp_reg2: continue;
}
r.gpr[i]._64 = riscv64->gpr[i]._64;
}
backend_setregs(&r);
}
#endif
......@@ -6,7 +6,7 @@
#include <isa/riscv64.h>
#include "../tran.h"
uint32_t reg_ptr2idx(DecodeExecState *s, const rtlreg_t* dest) {
uint32_t rtlreg2varidx(DecodeExecState *s, const rtlreg_t* dest) {
rtlreg_t* gpr_start = (rtlreg_t *)cpu.gpr;
rtlreg_t* gpr_end = (void *)gpr_start + sizeof(cpu.gpr);
......
#include <rtl/rtl.h>
#include "rv_ins_def.h"
#include "../tran.h"
#include "../spill.h"
void rv64_relop(uint32_t relop, uint32_t idx_dest, uint32_t idx_src1, uint32_t idx_src2);
uint32_t reg_ptr2idx(DecodeExecState *s, const rtlreg_t* dest);
uint32_t dest2rvidx(DecodeExecState *s, const rtlreg_t* dest);
uint32_t src2rvidx(DecodeExecState *s, const rtlreg_t* src);
static inline void rv64_zextw(uint32_t rd, uint32_t rs) {
#ifndef ISA64
// mask32 is set during initialization
rv64_and(rd, rs, mask32);
#endif
}
static inline void rv64_sextw(uint32_t rd, uint32_t rs) {
#ifndef ISA64
rv64_addw(rd, rs, x0);
#endif
}
// return false if `imm` can be represented within 12 bits
......@@ -22,79 +28,66 @@ static inline bool load_imm_big(uint32_t r, const sword_t imm) {
if (lui_imm == 0) return false;
else {
rv64_lui(r, lui_imm);
if (rv_imm.imm_11_0 != 0) rv64_addiw(r, r, rv_imm.imm_11_0);
if (rv_imm.imm_11_0 != 0) rv64_addi(r, r, rv_imm.imm_11_0);
return true;
}
}
static inline void load_imm(uint32_t r, const sword_t imm) {
if (imm == 0) {
rv64_addi(r, x0, 0);
return;
}
RV_IMM rv_imm = { .val = imm };
uint32_t lui_imm = (rv_imm.imm_31_12 + (rv_imm.imm_11_0 >> 11)) & 0xfffffu;
uint32_t hi = x0;
if (lui_imm != 0) {
rv64_lui(r, lui_imm);
hi = r;
}
if (rv_imm.imm_11_0 != 0) rv64_addiw(r, hi, rv_imm.imm_11_0);
if (!load_imm_big(r, imm)) rv64_addi(r, x0, imm & 0xfff);
}
static inline void load_imm_no_opt(uint32_t r, 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)) & 0xfffffu;
rv64_lui(r, lui_imm);
rv64_addiw(r, r, rv_imm.imm_11_0);
rv64_addi(r, r, rv_imm.imm_11_0);
}
/* 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)); \
uint32_t ret = rtlreg2rvidx_pair(s, src1, true, src2, true); \
uint32_t src1_rvidx = ret >> 16; \
uint32_t src2_rvidx = ret & 0xffff; \
uint32_t dest_rvidx = dest2rvidx(s, dest); \
concat(rv64_, rv64_name) (dest_rvidx, src1_rvidx, src2_rvidx); \
}
#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); \
uint32_t ret = rtlreg2rvidx_pair(s, dest, false, src1, true); \
uint32_t dest_rvidx = ret >> 16; \
uint32_t src1_rvidx = ret & 0xffff; \
concat(rv64_, rv64_name) (dest_rvidx, src1_rvidx, imm); \
spill_set_dirty_rvidx(dest_rvidx); \
}
#define make_rtl_compute_imm_opt(rtl_name, rv64_name, rv64_imm_name) \
make_rtl(rtl_name, rtlreg_t* dest, const rtlreg_t* src1, const sword_t imm) { \
uint32_t ret = rtlreg2rvidx_pair(s, dest, false, src1, true); \
uint32_t dest_rvidx = ret >> 16; \
uint32_t src1_rvidx = ret & 0xffff; \
if (src1 == rz) load_imm(dest_rvidx, imm); \
else if (load_imm_big(tmp0, imm)) concat(rv64_, rv64_name) (dest_rvidx, src1_rvidx, tmp0); \
else concat(rv64_, rv64_imm_name) (dest_rvidx, src1_rvidx, imm); \
spill_set_dirty_rvidx(dest_rvidx); \
}
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 (src1 == rz) load_imm(reg_ptr2idx(s, dest), imm);
else if (load_imm_big(tmp0, imm)) rv64_addw(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), tmp0);
else rv64_addiw(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), imm);
}
make_rtl_compute_imm_opt(addi, add, addi)
make_rtl_compute_imm_opt(andi, and, andi)
make_rtl_compute_imm_opt(xori, xor, xori)
make_rtl_compute_imm_opt(ori, or, ori)
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 (src1 == rz) load_imm(reg_ptr2idx(s, dest), 0);
else if (load_imm_big(tmp0, imm)) rv64_and(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), tmp0);
else rv64_andi(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), imm);
}
make_rtl(xori, rtlreg_t* dest, const rtlreg_t* src1, const sword_t imm) {
if (src1 == rz) load_imm(reg_ptr2idx(s, dest), imm);
else if (load_imm_big(tmp0, imm)) rv64_xor(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), tmp0);
else rv64_xori(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), imm);
}
make_rtl(ori, rtlreg_t* dest, const rtlreg_t* src1, const sword_t imm) {
if (src1 == rz) load_imm(reg_ptr2idx(s, dest), imm);
else if (load_imm_big(tmp0, imm)) rv64_or(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), tmp0);
else rv64_ori(reg_ptr2idx(s, dest), reg_ptr2idx(s, src1), imm);
}
#ifdef ISA64
make_rtl_compute_reg(add, add)
make_rtl_compute_reg(sub, sub)
......@@ -116,27 +109,42 @@ 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));
uint32_t ret = rtlreg2rvidx_pair(s, src1, true, src2, true);
uint32_t src1_rvidx = ret >> 16;
uint32_t src2_rvidx = ret & 0xffff;
uint32_t dest_rvidx = dest2rvidx(s, dest);
rv64_relop(relop, dest_rvidx, src1_rvidx, src2_rvidx);
}
make_rtl(setrelopi, uint32_t relop, rtlreg_t *dest, const rtlreg_t *src1, const sword_t imm) {
int big_imm = load_imm_big(tmp0, imm);
uint32_t idx_dest = reg_ptr2idx(s, dest);
uint32_t idx_src1 = reg_ptr2idx(s, src1);
uint32_t ret = rtlreg2rvidx_pair(s, dest, false, src1, true);
uint32_t dest_rvidx = ret >> 16;
uint32_t src1_rvidx = ret & 0xffff;
if (!big_imm && (relop == RELOP_LT || relop == RELOP_LTU)) {
switch (relop) {
case RELOP_LT: rv64_slti(idx_dest, idx_src1, imm); return;
case RELOP_LTU: rv64_sltiu(idx_dest, idx_src1, imm); return;
case RELOP_LT: rv64_slti(dest_rvidx, src1_rvidx, imm); goto finish;
case RELOP_LTU: rv64_sltiu(dest_rvidx, src1_rvidx, imm); goto finish;
// fall through for default cases
}
}
if (!big_imm) rv64_addiw(tmp0, x0, imm);
rv64_relop(relop, idx_dest, idx_src1, tmp0);
if (!big_imm) rv64_addi(tmp0, x0, imm);
rv64_relop(relop, dest_rvidx, src1_rvidx, tmp0);
finish:
spill_set_dirty_rvidx(dest_rvidx);
}
//make_rtl_arith_logic(mul_hi)
//make_rtl_arith_logic(imul_hi)
#ifdef ISA64
make_rtl_compute_reg(mul_lo, mul)
make_rtl_compute_reg(mul_hi, mulhu)
make_rtl_compute_reg(imul_lo, mul)
make_rtl_compute_reg(imul_hi, mulh)
make_rtl_compute_reg(div_q, divu)
make_rtl_compute_reg(div_r, remu)
make_rtl_compute_reg(idiv_q, div)
make_rtl_compute_reg(idiv_r, rem)
#else
make_rtl_compute_reg(mul_lo, mulw)
make_rtl_compute_reg(imul_lo, mulw)
make_rtl_compute_reg(div_q, divuw)
......@@ -144,146 +152,129 @@ 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()
# define rv64_imul_hi(c, a, b) TODO()
#else
make_rtl(mul_hi, rtlreg_t* dest, const rtlreg_t* src1, const rtlreg_t* src2) {
uint32_t idx_dest = reg_ptr2idx(s, dest);
uint32_t idx_src1 = reg_ptr2idx(s, src1);
uint32_t idx_src2 = reg_ptr2idx(s, src2);
rv64_zextw(idx_src1, idx_src1);
rv64_zextw(idx_src2, idx_src2);
rv64_mul(idx_dest, idx_src1, idx_src2);
rv64_srai(idx_dest, idx_dest, 32);
uint32_t ret = rtlreg2rvidx_pair(s, src1, true, src2, true);
uint32_t src1_rvidx = ret >> 16;
uint32_t src2_rvidx = ret & 0xffff;
rv64_zextw(src1_rvidx, src1_rvidx);
rv64_zextw(src2_rvidx, src2_rvidx);
uint32_t dest_rvidx = dest2rvidx(s, dest);
rv64_mul(dest_rvidx, src1_rvidx, src2_rvidx);
rv64_srai(dest_rvidx, dest_rvidx, 32);
}
make_rtl(imul_hi, rtlreg_t* dest, const rtlreg_t* src1, const rtlreg_t* src2) {
uint32_t idx_dest = reg_ptr2idx(s, dest);
uint32_t idx_src1 = reg_ptr2idx(s, src1);
uint32_t idx_src2 = reg_ptr2idx(s, src2);
rv64_sextw(idx_src1, idx_src1);
rv64_sextw(idx_src2, idx_src2);
rv64_mul(idx_dest, idx_src1, idx_src2);
rv64_srai(idx_dest, idx_dest, 32);
uint32_t ret = rtlreg2rvidx_pair(s, src1, true, src2, true);
uint32_t src1_rvidx = ret >> 16;
uint32_t src2_rvidx = ret & 0xffff;
rv64_sextw(src1_rvidx, src1_rvidx);
rv64_sextw(src2_rvidx, src2_rvidx);
uint32_t dest_rvidx = dest2rvidx(s, dest);
rv64_mul(dest_rvidx, src1_rvidx, src2_rvidx);
rv64_srai(dest_rvidx, dest_rvidx, 32);
}
#endif
make_rtl(div64_q, rtlreg_t* dest,
const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2) {
uint32_t idx_dest = reg_ptr2idx(s, dest);
uint32_t idx_src1_hi = reg_ptr2idx(s, src1_hi);
uint32_t idx_src1_lo = reg_ptr2idx(s, src1_lo);
uint32_t idx_src2 = reg_ptr2idx(s, src2);
rv64_slli(tmp0, idx_src1_hi, 32);
rv64_zextw(idx_src1_lo, idx_src1_lo);
rv64_or(tmp0, tmp0, idx_src1_lo);
rv64_zextw(idx_src2, idx_src2);
rv64_divu(idx_dest, tmp0, idx_src2);
}
make_rtl(div64_r, rtlreg_t* dest,
const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2) {
uint32_t idx_dest = reg_ptr2idx(s, dest);
uint32_t idx_src1_hi = reg_ptr2idx(s, src1_hi);
uint32_t idx_src1_lo = reg_ptr2idx(s, src1_lo);
uint32_t idx_src2 = reg_ptr2idx(s, src2);
rv64_slli(tmp0, idx_src1_hi, 32);
rv64_zextw(idx_src1_lo, idx_src1_lo);
rv64_or(tmp0, tmp0, idx_src1_lo);
rv64_zextw(idx_src2, idx_src2);
rv64_remu(idx_dest, tmp0, idx_src2);
#ifdef __ISA_x86__
#define make_x86_div64(rtl_name, ext_type, rv64_name) \
make_rtl(rtl_name, rtlreg_t* dest, \
const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2) { \
uint32_t idx_dest = dest2rvidx(s, dest); \
uint32_t idx_src1_hi = src2rvidx(s, src1_hi); \
uint32_t idx_src1_lo = src2rvidx(s, src1_lo); \
uint32_t idx_src2 = src2rvidx(s, src2); \
rv64_slli(tmp0, idx_src1_hi, 32); \
rv64_zextw(idx_src1_lo, idx_src1_lo); \
rv64_or(tmp0, tmp0, idx_src1_lo); \
ext_type(idx_src2, idx_src2); \
concat(rv64_, rv64_name) (idx_dest, tmp0, idx_src2); \
}
make_rtl(idiv64_q, rtlreg_t* dest,
const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2) {
uint32_t idx_dest = reg_ptr2idx(s, dest);
uint32_t idx_src1_hi = reg_ptr2idx(s, src1_hi);
uint32_t idx_src1_lo = reg_ptr2idx(s, src1_lo);
uint32_t idx_src2 = reg_ptr2idx(s, src2);
rv64_slli(tmp0, idx_src1_hi, 32);
rv64_zextw(idx_src1_lo, idx_src1_lo);
rv64_or(tmp0, tmp0, idx_src1_lo);
rv64_sextw(idx_src2, idx_src2);
rv64_div(idx_dest, tmp0, idx_src2);
#else
#define make_x86_div64(rtl_name, ext_type, rv64_name) \
make_rtl(rtl_name, rtlreg_t* dest, \
const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2) { \
panic("only support in x86"); \
}
#endif
make_rtl(idiv64_r, rtlreg_t* dest,
const rtlreg_t* src1_hi, const rtlreg_t* src1_lo, const rtlreg_t* src2) {
uint32_t idx_dest = reg_ptr2idx(s, dest);
uint32_t idx_src1_hi = reg_ptr2idx(s, src1_hi);
uint32_t idx_src1_lo = reg_ptr2idx(s, src1_lo);
uint32_t idx_src2 = reg_ptr2idx(s, src2);
rv64_slli(tmp0, idx_src1_hi, 32);
rv64_zextw(idx_src1_lo, idx_src1_lo);
rv64_or(tmp0, tmp0, idx_src1_lo);
rv64_sextw(idx_src2, idx_src2);
rv64_rem(idx_dest, tmp0, idx_src2);
}
make_x86_div64(div64_q, rv64_zextw, divu)
make_x86_div64(div64_r, rv64_zextw, remu)
make_x86_div64(idiv64_q, rv64_sextw, div)
make_x86_div64(idiv64_r, rv64_sextw, rem)
make_rtl(lm, rtlreg_t *dest, const rtlreg_t* addr, const sword_t imm, int len) {
uint32_t idx_dest = reg_ptr2idx(s, dest);
uint32_t idx_addr = reg_ptr2idx(s, addr);
uint32_t ret = rtlreg2rvidx_pair(s, dest, false, addr, true);
uint32_t dest_rvidx = ret >> 16;
uint32_t addr_rvidx = ret & 0xffff;
uint32_t addr_rvidx_final = dest_rvidx;
RV_IMM rv_imm = { .val = imm };
uint32_t lui_imm = (rv_imm.imm_31_12 + (rv_imm.imm_11_0 >> 11)) & 0xfffffu;
if (addr == rz) rv64_lui(tmp0, lui_imm);
else if (lui_imm == 0) rv64_zextw(tmp0, idx_addr);
if (addr == rz) rv64_lui(dest_rvidx, lui_imm);
else if (lui_imm == 0) {
#ifdef ISA64
addr_rvidx_final = addr_rvidx;
#else
rv64_zextw(dest_rvidx, addr_rvidx);
#endif
}
else {
rv64_lui(tmp0, lui_imm);
rv64_add(tmp0, tmp0, idx_addr);
rv64_zextw(tmp0, tmp0);
rv64_add(dest_rvidx, tmp0, addr_rvidx);
rv64_zextw(dest_rvidx, dest_rvidx);
}
switch (len) {
case 1: rv64_lbu(idx_dest, tmp0, imm & 0xfff); break;
case 2: rv64_lhu(idx_dest, tmp0, imm & 0xfff); break;
case 1: rv64_lbu(dest_rvidx, addr_rvidx_final, imm & 0xfff); break;
case 2: rv64_lhu(dest_rvidx, addr_rvidx_final, imm & 0xfff); break;
#ifdef ISA64
case 4: rv64_lwu(idx_dest, tmp0, imm & 0xfff); break;
case 4: rv64_lwu(dest_rvidx, addr_rvidx_final, imm & 0xfff); break;
#else
case 4: rv64_lw (idx_dest, tmp0, imm & 0xfff); break;
case 4: rv64_lw (dest_rvidx, addr_rvidx_final, imm & 0xfff); break;
#endif
case 8: rv64_ld (idx_dest, tmp0, imm & 0xfff); break;
case 8: rv64_ld (dest_rvidx, addr_rvidx_final, imm & 0xfff); break;
default: assert(0);
}
spill_set_dirty_rvidx(dest_rvidx);
}
make_rtl(sm, const rtlreg_t* addr, const sword_t imm, const rtlreg_t* src1, int len) {
uint32_t idx_addr = reg_ptr2idx(s, addr);
uint32_t idx_src1 = reg_ptr2idx(s, src1);
uint32_t ret = rtlreg2rvidx_pair(s, addr, true, src1, true);
uint32_t addr_rvidx = ret >> 16;
uint32_t src1_rvidx = ret & 0xffff;
uint32_t addr_rvidx_final = tmp0;
RV_IMM rv_imm = { .val = imm };
uint32_t lui_imm = (rv_imm.imm_31_12 + (rv_imm.imm_11_0 >> 11)) & 0xfffffu;
if (addr == rz) rv64_lui(tmp0, lui_imm);
else if (lui_imm == 0) rv64_zextw(tmp0, idx_addr);
else if (lui_imm == 0) {
#ifdef ISA64
addr_rvidx_final = addr_rvidx;
#else
rv64_zextw(tmp0, addr_rvidx);
#endif
}
else {
rv64_lui(tmp0, lui_imm);
rv64_add(tmp0, tmp0, idx_addr);
rv64_add(tmp0, tmp0, addr_rvidx);
rv64_zextw(tmp0, tmp0);
}
switch (len) {
case 1: rv64_sb(idx_src1, tmp0, imm & 0xfff); break;
case 2: rv64_sh(idx_src1, tmp0, imm & 0xfff); break;
case 4: rv64_sw(idx_src1, tmp0, imm & 0xfff); break;
case 8: rv64_sd(idx_src1, tmp0, imm & 0xfff); break;
case 1: rv64_sb(src1_rvidx, addr_rvidx_final, imm & 0xfff); break;
case 2: rv64_sh(src1_rvidx, addr_rvidx_final, imm & 0xfff); break;
case 4: rv64_sw(src1_rvidx, addr_rvidx_final, imm & 0xfff); break;
case 8: rv64_sd(src1_rvidx, addr_rvidx_final, imm & 0xfff); break;
default: assert(0);
}
}
#ifdef __ISA_x86__
make_rtl(host_lm, rtlreg_t* dest, const void *addr, int len) {
#ifndef __ISA_x86__
panic("should not reach here");
#endif
uint32_t idx_dest = reg_ptr2idx(s, dest);
uint32_t idx_dest = dest2rvidx(s, dest);
// we assume that `addr` is only from cpu.gpr in x86
uintptr_t addr_align = (uintptr_t)addr & ~(sizeof(rtlreg_t) - 1);
uint32_t idx_r = reg_ptr2idx(s, (void *)addr_align);
uint32_t idx_r = src2rvidx(s, (void *)addr_align);
switch (len) {
case 1: ;
int is_high = (uintptr_t)addr & 1;
......@@ -302,15 +293,11 @@ make_rtl(host_lm, rtlreg_t* dest, const void *addr, int len) {
}
make_rtl(host_sm, void *addr, const rtlreg_t *src1, int len) {
#ifndef __ISA_x86__
panic("should not reach here");
#endif
uint32_t idx_src1 = reg_ptr2idx(s, src1);
uint32_t idx_src1 = dest2rvidx(s, src1);
// we assume that `addr` is only from cpu.gpr in x86
uintptr_t addr_align = (uintptr_t)addr & ~(sizeof(rtlreg_t) - 1);
uint32_t idx_r = reg_ptr2idx(s, (void *)addr_align);
uint32_t idx_r = src2rvidx(s, (void *)addr_align);
spm(sw, idx_r, SPM_X86_REG);
if (len == 1) spm(sb, idx_src1, SPM_X86_REG + ((uintptr_t)addr & 1));
......@@ -318,21 +305,42 @@ make_rtl(host_sm, void *addr, const rtlreg_t *src1, int len) {
else assert(0);
spm(lwu, idx_r, SPM_X86_REG);
}
#else
make_rtl(host_lm, rtlreg_t* dest, const void *addr, int len) {
panic("only used in x86\n");
}
make_rtl(host_sm, void *addr, const rtlreg_t *src1, int len) {
panic("only used in x86\n");
}
#endif
// we use tmp0 to store x86.pc of the next basic block
make_rtl(j, vaddr_t target) {
if (!load_imm_big(tmp0, target)) rv64_addiw(tmp0, tmp0, target & 0xfff);
#ifdef REG_SPILLING
spill_writeback_all();
#endif
load_imm(tmp0, target);
tran_next_pc = NEXT_PC_JMP;
}
make_rtl(jr, rtlreg_t *target) {
rv64_addi(tmp0, reg_ptr2idx(s, target), 0);
uint32_t rvidx = src2rvidx(s, target);
rv64_addi(tmp0, rvidx, 0);
#ifdef REG_SPILLING
spill_writeback_all();
#endif
tran_next_pc = NEXT_PC_JMP;
}
make_rtl(jrelop, uint32_t relop, const rtlreg_t *src1, const rtlreg_t *src2, vaddr_t target) {
uint32_t rs1 = reg_ptr2idx(s, src1);
uint32_t rs2 = reg_ptr2idx(s, src2);
uint32_t ret = rtlreg2rvidx_pair(s, src1, true, src2, true);
uint32_t rs1 = ret >> 16;
uint32_t rs2 = ret & 0xffff;
#ifdef REG_SPILLING
spill_writeback_all();
#endif
uint32_t offset = 12; // branch two instructions
extern int trans_buffer_index;
int old_idx = trans_buffer_index;
......
#include "spill.h"
#include "tran.h"
#include "rv64-backend/rv_ins_def.h"
#include "rtl/rtl.h"
#define TMP_REG_NUM 2
typedef struct {
uint32_t rvidx;
uint32_t spmidx;
bool dirty;
} Tmp_reg;
static Tmp_reg tmp_regs[TMP_REG_NUM];
void spill_init() {
assert(TMP_REG_NUM == 2);
tmp_regs[0].rvidx = tmp_reg1;
tmp_regs[1].rvidx = tmp_reg2;
}
void spill_flush(int tmpidx) {
tmp_regs[tmpidx].spmidx = 0;
tmp_regs[tmpidx].dirty = 0;
}
void spill_reset() {
spill_flush(0);
spill_flush(1);
}
int spmidx2tmpidx(uint32_t spmidx) {
if (tmp_regs[0].spmidx == spmidx) return 0;
if (tmp_regs[1].spmidx == spmidx) return 1;
return -1;
}
int rvidx2tmpidx(uint32_t rvidx) {
if (tmp_regs[0].rvidx == rvidx) return 0;
if (tmp_regs[1].rvidx == rvidx) return 1;
return -1;
}
uint32_t spmidx2rvidx(uint32_t spmidx) {
int tmpidx = spmidx2tmpidx(spmidx);
if (tmpidx == -1) return 0;
return tmp_regs[tmpidx].rvidx;
}
uint32_t varidx2rvidx(uint32_t varidx) {
if (varidx & ~SPMIDX_MASK) return varidx;
int tmpidx = spmidx2tmpidx(varidx);
assert(tmpidx != -1);
return tmp_regs[tmpidx].rvidx;
}
void spill_writeback(uint32_t i) {
if (tmp_regs[i].spmidx != 0 && tmp_regs[i].dirty) {
spm(sw, tmp_regs[i].rvidx, 4 * (tmp_regs[i].spmidx & ~SPMIDX_MASK));
tmp_regs[i].dirty = false;
}
}
void spill_writeback_all() {
spill_writeback(0);
spill_writeback(1);
}
// replace tmp_regs[tmpidx] with spmidx
void spill_replace(uint32_t tmpidx, uint32_t spmidx, int load_val) {
spill_writeback(tmpidx);
if (load_val) spm(lw, tmp_regs[tmpidx].rvidx, 4 * (spmidx & ~SPMIDX_MASK));
tmp_regs[tmpidx].spmidx = spmidx;
tmp_regs[tmpidx].dirty = false;
}
// find a clean tmpreg and map it to spmidx
uint32_t spill_alloc(uint32_t spmidx, int load_val) {
uint32_t tmpidx = (tmp_regs[1].dirty ? 0 : 1);
spill_replace(tmpidx, spmidx, load_val);
return tmpidx;
}
uint32_t rtlreg2varidx(DecodeExecState *s, const rtlreg_t* dest);
static uint32_t rtlreg2rvidx_internal(DecodeExecState *s, const rtlreg_t *r, int is_dest) {
uint32_t varidx = rtlreg2varidx(s, r);
if (varidx & SPMIDX_MASK) {
uint32_t tmpidx = spmidx2tmpidx(varidx);
if (tmpidx == -1) tmpidx = spill_alloc(varidx, !is_dest);
varidx = tmp_regs[tmpidx].rvidx;
tmp_regs[tmpidx].dirty = is_dest;
}
return varidx;
}
uint32_t src2rvidx(DecodeExecState *s, const rtlreg_t *src) {
return rtlreg2rvidx_internal(s, src, false);
}
uint32_t dest2rvidx(DecodeExecState *s, const rtlreg_t *dest) {
return rtlreg2rvidx_internal(s, dest, true);
}
uint32_t rtlreg2rvidx_pair(DecodeExecState *s,
const rtlreg_t *src1, int load_src1, const rtlreg_t *src2, int load_src2) {
uint32_t src1_varidx = rtlreg2varidx(s, src1);
uint32_t src2_varidx = rtlreg2varidx(s, src2);
if ((src1_varidx & SPMIDX_MASK) && (src2_varidx & SPMIDX_MASK)) {
// check whether they are already mapped
uint32_t src1_tmpidx = spmidx2tmpidx(src1_varidx);
uint32_t src2_tmpidx = spmidx2tmpidx(src2_varidx);
if (src1_tmpidx == -1 && src2_tmpidx != -1) {
src1_tmpidx = !src2_tmpidx;
spill_replace(src1_tmpidx, src1_varidx, load_src1);
} else if (src1_tmpidx != -1 && src2_tmpidx == -1) {
src2_tmpidx = !src1_tmpidx;
spill_replace(src2_tmpidx, src2_varidx, load_src2);
} else if (src1_tmpidx == -1 && src2_tmpidx == -1) {
src1_tmpidx = 0;
src2_tmpidx = 1;
spill_replace(src1_tmpidx, src1_varidx, load_src1);
spill_replace(src2_tmpidx, src2_varidx, load_src2);
}
src1_varidx = tmp_regs[src1_tmpidx].rvidx;
src2_varidx = tmp_regs[src2_tmpidx].rvidx;
} else if (src1_varidx & SPMIDX_MASK) {
uint32_t src1_tmpidx = spmidx2tmpidx(src1_varidx);
if (src1_tmpidx == -1) src1_tmpidx = spill_alloc(src1_varidx, load_src1);
src1_varidx = tmp_regs[src1_tmpidx].rvidx;
} else if (src2_varidx & SPMIDX_MASK) {
uint32_t src2_tmpidx = spmidx2tmpidx(src2_varidx);
if (src2_tmpidx == -1) src2_tmpidx = spill_alloc(src2_varidx, load_src2);
src2_varidx = tmp_regs[src2_tmpidx].rvidx;
}
return (src1_varidx << 16) | src2_varidx;
}
void spill_set_dirty(uint32_t tmpidx) {
tmp_regs[tmpidx].dirty = true;
}
void spill_set_dirty_rvidx(uint32_t rvidx) {
int tmpidx = rvidx2tmpidx(rvidx);
if (tmpidx != -1) spill_set_dirty(tmpidx);
}
// this will be called after every translation of an instruction
// to flush RTL tmp registers, since their life-cycle is only
// valid during the translation of a single instruction
static void spill_flush_local_internal(DecodeExecState *s, const rtlreg_t *dest) {
uint32_t varidx = rtlreg2varidx(s, dest);
if (tmp_regs[0].spmidx == varidx && tmp_regs[0].dirty) spill_flush(0);
if (tmp_regs[1].spmidx == varidx && tmp_regs[1].dirty) spill_flush(1);
}
void spill_flush_local() {
DecodeExecState state; // only used in rtlreg2varidx()
DecodeExecState *s = &state;
spill_flush_local_internal(s, s0);
spill_flush_local_internal(s, s1);
}
#ifndef __SPILL_H__
#define __SPILL_H__
#include <common.h>
#include <cpu/decode.h>
uint32_t spmidx2rvidx(uint32_t);
uint32_t spill_out_and_remap(DecodeExecState*, uint32_t);
void spill_flush_all();
void cal_suffix_inst();
void spill_writeback_all();
void spill_set_spmidx(uint32_t tmpidx, uint32_t new_spmidx);
int rvidx2tmpidx(uint32_t rvidx);
void spill_set_dirty_rvidx(uint32_t rvidx);
uint32_t varidx2rvidx(uint32_t varidx);
void spill_set_dirty(uint32_t tmpidx);
void spill_writeback(uint32_t i);
uint32_t rtlreg2rvidx_pair(DecodeExecState *s, const rtlreg_t *src1, int load_src1, const rtlreg_t *src2, int load_src2);
#endif
......@@ -17,6 +17,8 @@ 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_trans_buffer(void *buf, int nr_instr, int npc_type);
void guest_getregs(CPU_state *cpu);
void spill_reset();
void spill_flush_local();
typedef struct TB {
vaddr_t pc;
......@@ -94,6 +96,7 @@ void mainloop() {
TB *tb = find_tb(tb_start);
if (tb == NULL) {
clear_trans_buffer();
spill_reset();
tran_next_pc = NEXT_PC_SEQ;
int guest_nr_instr = 0;
while (1) {
......@@ -101,6 +104,8 @@ void mainloop() {
__attribute__((unused)) vaddr_t seq_pc = isa_exec_once();
guest_nr_instr ++;
spill_flush_local();
if (nemu_state.state != NEMU_RUNNING) tran_next_pc = NEXT_PC_END;
#ifdef DEBUG
......
......@@ -13,19 +13,34 @@ extern void (*backend_exec)(uint64_t n);
#define BBL_MAX_SIZE (16 * 1024)
// scratch pad memory, whose address space is [0, 64)
#define spm(op, reg, offset) concat(rv64_, op)(reg, x0, offset)
// There are 4 types of indices.
// * rvidx - the index of rv64 register, can be zero.
// used to construct rv instructions
// * spmidx - the index of variable in SPM masked with SPM_IDX_MASK, which is non-zero.
// used to allocate rtl registers which can not be mapped to rv64 registers
// * varidx - (mapped_to_spm ? smpidx : rvidx)
// * tmpidx - the index of record of temporal registers in spill.c
#define SPMIDX_MASK 0x20
// scratch pad memory, whose address space is [riscv64_PMEM_BASE, riscv64_PMEM_BASE + 64)
#define spm(op, reg, offset) concat(rv64_, op)(reg, spm_base, offset)
#define SPM_X86_REG 0 // x86 byte/word register write
enum { x0 = 0 };
// static register allocation
#if defined(__ISA_x86__)
enum { tmp0 = 30, mask32 = 24, mask16 = 25 };
enum { tmp0 = 30, mask32 = 24, mask16 = 25, spm_base = 0, tmp_reg1 = 0, tmp_reg2 = 0 };
#elif defined(__ISA_mips32__)
enum { tmp0 = 1, mask32 = 28, mask16 = 0 };
enum { tmp0 = 1, mask32 = 28, mask16 = 0, spm_base = 25, tmp_reg1 = 26, tmp_reg2 = 27 };
#define REG_SPILLING
#elif defined(__ISA_riscv32__)
enum { tmp0 = 3, mask32 = 4, mask16 = 0 };
enum { tmp0 = 31, mask32 = 27, mask16 = 0, spm_base = 26, tmp_reg1 = 3, tmp_reg2 = 4 };
#define REG_SPILLING
#elif defined(__ISA_riscv64__)
enum { tmp0 = 31, mask32 = 0, mask16 = 0, spm_base = 27, tmp_reg1 = 3, tmp_reg2 = 4 };
#define REG_SPILLING
#endif
#endif
......@@ -145,7 +145,7 @@ static inline make_EHelper(srlw) {
}
else {
// srlw
rtl_andi(s, s1, dsrc1, 0xffffffffu);
rtl_zext(s, s1, dsrc1, 4);
rtl_shr(s, s0, s1, s0);
print_asm_template3(srlw);
}
......@@ -178,7 +178,7 @@ static inline make_EHelper(srliw) {
}
else {
// srlw
rtl_andi(s, s0, dsrc1, 0xffffffffu);
rtl_zext(s, s0, dsrc1, 4);
rtl_shri(s, s0, s0, id_src2->imm & 0x1f);
print_asm_template3(srliw);
}
......
......@@ -37,45 +37,45 @@ static inline make_EHelper(mulhsu) {
}
static inline make_EHelper(div) {
if (*dsrc2 == 0) {
rtl_li(s, ddest, ~0lu);
} else if (*dsrc1 == 0x8000000000000000LL && *dsrc2 == -1) {
rtl_mv(s, ddest, dsrc1);
} else {
//if (*dsrc2 == 0) {
// rtl_li(s, ddest, ~0lu);
//} else if (*dsrc1 == 0x8000000000000000LL && *dsrc2 == -1) {
// rtl_mv(s, ddest, dsrc1);
//} else {
rtl_idiv_q(s, ddest, dsrc1, dsrc2);
}
//}
print_asm_template3(div);
}
static inline make_EHelper(divu) {
if (*dsrc2 == 0) {
rtl_li(s, ddest, ~0lu);
} else {
//if (*dsrc2 == 0) {
// rtl_li(s, ddest, ~0lu);
//} else {
rtl_div_q(s, ddest, dsrc1, dsrc2);
}
//}
print_asm_template3(divu);
}
static inline make_EHelper(rem) {
if (*dsrc2 == 0) {
rtl_mv(s, ddest, dsrc1);
} else if (*dsrc1 == 0x8000000000000000LL && *dsrc2 == -1) {
rtl_mv(s, ddest, rz);
} else {
//if (*dsrc2 == 0) {
// rtl_mv(s, ddest, dsrc1);
//} else if (*dsrc1 == 0x8000000000000000LL && *dsrc2 == -1) {
// rtl_mv(s, ddest, rz);
//} else {
rtl_idiv_r(s, ddest, dsrc1, dsrc2);
}
//}
print_asm_template3(rem);
}
static inline make_EHelper(remu) {
if (*dsrc2 == 0) {
rtl_mv(s, ddest, dsrc1);
} else {
//if (*dsrc2 == 0) {
// rtl_mv(s, ddest, dsrc1);
//} else {
rtl_div_r(s, ddest, dsrc1, dsrc2);
}
//}
print_asm_template3(remu);
}
......@@ -89,13 +89,13 @@ static inline make_EHelper(mulw) {
static inline make_EHelper(divw) {
rtl_sext(s, s0, dsrc1, 4);
rtl_sext(s, s1, dsrc2, 4);
if (*s1 == 0) {
rtl_li(s, s0, ~0lu);
} else if (*s0 == 0x80000000 && *s1 == -1) {
//rtl_mv(s, s0, s0);
} else {
//if (*s1 == 0) {
// rtl_li(s, s0, ~0lu);
//} else if (*s0 == 0x80000000 && *s1 == -1) {
// //rtl_mv(s, s0, s0);
//} else {
rtl_idiv_q(s, s0, s0, s1);
}
//}
rtl_sext(s, ddest, s0, 4);
print_asm_template3(divw);
......@@ -104,39 +104,39 @@ static inline make_EHelper(divw) {
static inline make_EHelper(remw) {
rtl_sext(s, s0, dsrc1, 4);
rtl_sext(s, s1, dsrc2, 4);
if (*s1 == 0) {
//rtl_mv(s, s0, s0);
} else if (*s0 == 0x80000000 && *s1 == -1) {
rtl_mv(s, s0, rz);
} else {
//if (*s1 == 0) {
// //rtl_mv(s, s0, s0);
//} else if (*s0 == 0x80000000 && *s1 == -1) {
// rtl_mv(s, s0, rz);
//} else {
rtl_idiv_r(s, s0, s0, s1);
}
//}
rtl_sext(s, ddest, s0, 4);
print_asm_template3(remw);
}
static inline make_EHelper(divuw) {
rtl_andi(s, s0, dsrc1, 0xffffffffu);
rtl_andi(s, s1, dsrc2, 0xffffffffu);
if (*s1 == 0) {
rtl_li(s, s0, ~0lu);
} else {
rtl_zext(s, s0, dsrc1, 4);
rtl_zext(s, s1, dsrc2, 4);
//if (*s1 == 0) {
// rtl_li(s, s0, ~0lu);
//} else {
rtl_div_q(s, s0, s0, s1);
}
//}
rtl_sext(s, ddest, s0, 4);
print_asm_template3(divuw);
}
static inline make_EHelper(remuw) {
rtl_andi(s, s0, dsrc1, 0xffffffffu);
rtl_andi(s, s1, dsrc2, 0xffffffffu);
if (*s1 == 0) {
//rtl_mv(s, s0, s0);
} else {
rtl_zext(s, s0, dsrc1, 4);
rtl_zext(s, s1, dsrc2, 4);
//if (*s1 == 0) {
// //rtl_mv(s, s0, s0);
//} else {
rtl_div_r(s, s0, s0, s1);
}
//}
rtl_sext(s, ddest, s0, 4);
print_asm_template3(remuw);
......
......@@ -186,8 +186,9 @@ static int cmd_load(char *args) {
else {
FILE *fp = fopen(arg, "r");
assert(fp != NULL);
fread(&cpu, sizeof(cpu), 1, fp);
fread(guest_to_host(0), PMEM_SIZE, 1, fp);
__attribute__((unused)) int ret;
ret = fread(&cpu, sizeof(cpu), 1, fp);
ret = fread(guest_to_host(0), PMEM_SIZE, 1, fp);
fclose(fp);
}
return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册