提交 1b89cf7f 编写于 作者: Z Zihao Yu

refactor to support multi-arch

上级 9cf49ad5
......@@ -18,7 +18,7 @@ include Makefile.git
# Compilation flags
CC = gcc
LD = gcc
INCLUDES = $(addprefix -I, $(INC_DIR))
INCLUDES = $(addprefix -I, $(INC_DIR)) -I./src/arch/x86/include
CFLAGS += -O2 -MMD -Wall -Werror -ggdb3 $(INCLUDES) -fomit-frame-pointer
CFLAGS += -DDIFF_TEST_QEMU
......
......@@ -3,11 +3,11 @@
#include "common.h"
#include "rtl.h"
enum { OP_TYPE_REG, OP_TYPE_MEM, OP_TYPE_IMM };
#define make_DHelper(name) void concat(decode_, name) (vaddr_t *eip)
typedef void (*DHelper) (vaddr_t *);
#define OP_STR_SIZE 40
enum { OP_TYPE_REG, OP_TYPE_MEM, OP_TYPE_IMM };
typedef struct {
uint32_t type;
......@@ -22,14 +22,15 @@ typedef struct {
char str[OP_STR_SIZE];
} Operand;
#include "arch/decode.h"
typedef struct {
uint32_t opcode;
vaddr_t seq_eip; // sequential eip
bool is_operand_size_16;
uint8_t ext_opcode;
vaddr_t seq_pc; // sequential pc
bool is_jmp;
vaddr_t jmp_eip;
vaddr_t jmp_pc;
Operand src, dest, src2;
struct CPUDecodeInfo arch;
#ifdef DEBUG
char assembly[80];
char asm_buf[128];
......@@ -37,83 +38,13 @@ typedef struct {
#endif
} DecodeInfo;
typedef union {
struct {
uint8_t R_M :3;
uint8_t reg :3;
uint8_t mod :2;
};
struct {
uint8_t dont_care :3;
uint8_t opcode :3;
};
uint8_t val;
} ModR_M;
typedef union {
struct {
uint8_t base :3;
uint8_t index :3;
uint8_t ss :2;
};
uint8_t val;
} SIB;
void load_addr(vaddr_t *, ModR_M *, Operand *);
void read_ModR_M(vaddr_t *, Operand *, bool, Operand *, bool);
void operand_write(Operand *, rtlreg_t *);
/* shared by all helper functions */
extern DecodeInfo decoding;
#define id_src (&decoding.src)
#define id_src2 (&decoding.src2)
#define id_dest (&decoding.dest)
#define make_DHelper(name) void concat(decode_, name) (vaddr_t *eip)
typedef void (*DHelper) (vaddr_t *);
make_DHelper(I2E);
make_DHelper(I2a);
make_DHelper(I2r);
make_DHelper(SI2E);
make_DHelper(SI_E2G);
make_DHelper(I_E2G);
make_DHelper(I_G2E);
make_DHelper(I);
make_DHelper(r);
make_DHelper(E);
make_DHelper(setcc_E);
make_DHelper(gp7_E);
make_DHelper(test_I);
make_DHelper(SI);
make_DHelper(G2E);
make_DHelper(E2G);
make_DHelper(mov_I2r);
make_DHelper(mov_I2E);
make_DHelper(mov_G2E);
make_DHelper(mov_E2G);
make_DHelper(lea_M2G);
make_DHelper(gp2_1_E);
make_DHelper(gp2_cl2E);
make_DHelper(gp2_Ib2E);
make_DHelper(Ib_G2E);
make_DHelper(cl_G2E);
make_DHelper(O2a);
make_DHelper(a2O);
make_DHelper(J);
make_DHelper(push_SI);
extern DecodeInfo decinfo;
make_DHelper(in_I2a);
make_DHelper(in_dx2a);
make_DHelper(out_a2I);
make_DHelper(out_a2dx);
#define id_src (&decinfo.src)
#define id_src2 (&decinfo.src2)
#define id_dest (&decinfo.dest)
#endif
......@@ -3,6 +3,7 @@
#include "nemu.h"
#include "monitor/diff-test.h"
#include "cpu/rtl.h"
#define make_EHelper(name) void concat(exec_, name) (vaddr_t *eip)
typedef void (*EHelper) (vaddr_t *);
......@@ -15,7 +16,7 @@ static inline uint32_t instr_fetch(vaddr_t *eip, int len) {
uint8_t *p_instr = (void *)&instr;
int i;
for (i = 0; i < len; i ++) {
decoding.p += sprintf(decoding.p, "%02x ", p_instr[i]);
decinfo.p += sprintf(decinfo.p, "%02x ", p_instr[i]);
}
#endif
(*eip) += len;
......@@ -23,12 +24,14 @@ static inline uint32_t instr_fetch(vaddr_t *eip, int len) {
}
#ifdef DEBUG
#define print_asm(...) Assert(snprintf(decoding.assembly, 80, __VA_ARGS__) < 80, "buffer overflow!")
#define print_asm(...) Assert(snprintf(decinfo.assembly, 80, __VA_ARGS__) < 80, "buffer overflow!")
#else
#define print_asm(...)
#endif
#define suffix_char(width) ((width) == 4 ? 'l' : ((width) == 1 ? 'b' : ((width) == 2 ? 'w' : '?')))
#ifndef suffix_char
#define suffix_char(width) ' '
#endif
#define print_asm_template1(instr) \
print_asm(str(instr) "%c %s", suffix_char(id_dest->width), id_dest->str)
......
......@@ -8,7 +8,7 @@
extern rtlreg_t t0, t1, t2, t3, at;
void decoding_set_jmp(bool is_jmp);
void decinfo_set_jmp(bool is_jmp);
bool interpret_relop(uint32_t relop, const rtlreg_t src1, const rtlreg_t src2);
/* RTL basic instructions */
......@@ -109,45 +109,27 @@ static inline void interpret_rtl_setrelop(uint32_t relop, rtlreg_t *dest,
}
static inline void interpret_rtl_j(vaddr_t target) {
cpu.eip = target;
decoding_set_jmp(true);
cpu.pc = target;
decinfo_set_jmp(true);
}
static inline void interpret_rtl_jr(rtlreg_t *target) {
cpu.eip = *target;
decoding_set_jmp(true);
cpu.pc = *target;
decinfo_set_jmp(true);
}
static inline void interpret_rtl_jrelop(uint32_t relop,
const rtlreg_t *src1, const rtlreg_t *src2, vaddr_t target) {
bool is_jmp = interpret_relop(relop, *src1, *src2);
if (is_jmp) cpu.eip = target;
decoding_set_jmp(is_jmp);
if (is_jmp) cpu.pc = target;
decinfo_set_jmp(is_jmp);
}
void interpret_rtl_exit(int state);
void interpret_rtl_exit(int state, vaddr_t halt_pc, uint32_t halt_ret);
/* RTL pseudo instructions */
static inline void rtl_lr(rtlreg_t* dest, int r, int width) {
switch (width) {
case 4: rtl_mv(dest, &reg_l(r)); return;
case 1: rtl_host_lm(dest, &reg_b(r), 1); return;
case 2: rtl_host_lm(dest, &reg_w(r), 2); return;
default: assert(0);
}
}
static inline void rtl_sr(int r, const rtlreg_t* src1, int width) {
switch (width) {
case 4: rtl_mv(&reg_l(r), src1); return;
case 1: rtl_host_sm(&reg_b(r), src1, 1); return;
case 2: rtl_host_sm(&reg_w(r), src1, 2); return;
default: assert(0);
}
}
static inline void rtl_not(rtlreg_t *dest, const rtlreg_t* src1) {
// dest <- ~src1
// TODO();
......@@ -167,22 +149,6 @@ static inline void rtl_sext(rtlreg_t* dest, const rtlreg_t* src1, int width) {
}
}
static inline void rtl_push(const rtlreg_t* src1) {
// esp <- esp - 4
// M[esp] <- src1
// TODO();
rtl_subi(&cpu.esp, &cpu.esp, 4);
rtl_sm(&cpu.esp, src1, 4);
}
static inline void rtl_pop(rtlreg_t* dest) {
// dest <- M[esp]
// esp <- esp + 4
// TODO();
rtl_lm(dest, &cpu.esp, 4);
rtl_addi(&cpu.esp, &cpu.esp, 4);
}
static inline void rtl_setrelopi(uint32_t relop, rtlreg_t *dest,
const rtlreg_t *src1, int imm) {
rtl_li(&at, imm);
......@@ -198,62 +164,6 @@ static inline void rtl_msb(rtlreg_t* dest, const rtlreg_t* src1, int width) {
}
}
static inline void rtl_is_sub_overflow(rtlreg_t* dest,
const rtlreg_t* res, const rtlreg_t* src1, const rtlreg_t* src2, int width) {
// res = src1 - src2
assert(dest != res && dest != src1 && dest != src2);
rtl_xor(dest, src1, src2);
rtl_xor(&at, src1, res);
rtl_and(dest, dest, &at);
rtl_msb(dest, dest, width);
}
static inline void rtl_is_sub_carry(rtlreg_t* dest,
const rtlreg_t* res, const rtlreg_t* src1) {
// res = src1 - src2
assert(dest != res && dest != src1);
rtl_setrelop(RELOP_LTU, dest, src1, res);
}
static inline void rtl_is_add_overflow(rtlreg_t* dest,
const rtlreg_t* res, const rtlreg_t* src1, const rtlreg_t* src2, int width) {
// res = src1 + src2
assert(dest != res && dest != src1 && dest != src2);
rtl_is_sub_overflow(dest, src1, res, src2, width);
}
static inline void rtl_is_add_carry(rtlreg_t* dest,
const rtlreg_t* res, const rtlreg_t* src1) {
// res = src1 + src2
assert(dest != res && dest != src1);
rtl_is_sub_carry(dest, src1, res);
}
static inline void rtl_update_ZF(const rtlreg_t* result, int width) {
// eflags.ZF <- is_zero(result[width * 8 - 1 .. 0])
// TODO();
if (width != 4) {
rtl_andi(&cpu.ZF, result, 0xffffffffu >> ((4 - width) * 8));
rtl_setrelopi(RELOP_EQ, &cpu.ZF, &cpu.ZF, 0);
}
else {
rtl_setrelopi(RELOP_EQ, &cpu.ZF, result, 0);
}
}
static inline void rtl_update_SF(const rtlreg_t* result, int width) {
// eflags.SF <- is_sign(result[width * 8 - 1 .. 0])
// TODO();
rtl_msb(&cpu.SF, result, width);
}
static inline void rtl_update_ZFSF(const rtlreg_t* result, int width) {
rtl_update_ZF(result, width);
rtl_update_SF(result, width);
}
#include "arch/rtl.h"
#endif
#ifndef __DIFF_TEST_H__
#define __DIFF_TEST_H__
#define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 9) // GRPs + EIP
#include "arch/diff-test.h"
void difftest_skip_ref(void);
void difftest_skip_dut(void);
void difftest_skip_eflags(uint32_t mask);
#endif
#ifndef __MONITOR_H__
#define __MONITOR_H__
#include "common.h"
enum { NEMU_STOP, NEMU_RUNNING, NEMU_END, NEMU_ABORT };
extern int nemu_state;
#define ENTRY_START 0x100000
typedef struct {
int state;
vaddr_t halt_pc;
uint32_t halt_ret;
} NEMUState;
extern NEMUState nemu_state;
#endif
......@@ -3,6 +3,8 @@
#include "common.h"
#include "memory/memory.h"
#include "cpu/reg.h"
#include "arch/reg.h"
extern CPU_state cpu;
#endif
#include "cpu/exec.h"
#include "cpu/rtl.h"
/* shared by all helper functions */
DecodeInfo decoding;
rtlreg_t t0, t1, t2, t3, at;
void decoding_set_jmp(bool is_jmp) {
decoding.is_jmp = is_jmp;
}
#define make_DopHelper(name) void concat(decode_op_, name) (vaddr_t *eip, Operand *op, bool load_val)
/* Refer to Appendix A in i386 manual for the explanations of these abbreviations */
......@@ -73,7 +65,7 @@ static inline make_DopHelper(a) {
*/
static inline make_DopHelper(r) {
op->type = OP_TYPE_REG;
op->reg = decoding.opcode & 0x7;
op->reg = decinfo.opcode & 0x7;
if (load_val) {
rtl_lr(&op->val, op->reg, op->width);
}
......@@ -283,7 +275,7 @@ make_DHelper(a2O) {
make_DHelper(J) {
decode_op_SI(eip, id_dest, false);
// the target address can be computed in the decode stage
decoding.jmp_eip = id_dest->simm + *eip;
decinfo.jmp_pc = id_dest->simm + *eip;
}
make_DHelper(push_SI) {
......@@ -323,9 +315,3 @@ make_DHelper(out_a2dx) {
sprintf(id_dest->str, "(%%dx)");
#endif
}
void operand_write(Operand *op, rtlreg_t* src) {
if (op->type == OP_TYPE_REG) { rtl_sr(op->reg, src, op->width); }
else if (op->type == OP_TYPE_MEM) { rtl_sm(&op->addr, src, op->width); }
else { assert(0); }
}
......@@ -81,7 +81,7 @@ void load_addr(vaddr_t *eip, ModR_M *m, Operand *rm) {
void read_ModR_M(vaddr_t *eip, Operand *rm, bool load_rm_val, Operand *reg, bool load_reg_val) {
ModR_M m;
m.val = instr_fetch(eip, 1);
decoding.ext_opcode = m.opcode;
decinfo.arch.ext_opcode = m.opcode;
if (reg != NULL) {
reg->type = OP_TYPE_REG;
reg->reg = m.reg;
......
#include "nemu.h"
#include "monitor/diff-test.h"
extern void (*ref_difftest_memcpy_from_dut)(paddr_t dest, void *src, size_t n);
extern void (*ref_difftest_getregs)(void *c);
extern void (*ref_difftest_setregs)(const void *c);
extern void (*ref_difftest_exec)(uint64_t n);
#define check_reg(regs, r) \
if (regs->r != cpu.r) { \
Log("%s is different after executing instruction at eip = 0x%08x, right = 0x%08x, wrong = 0x%08x", \
str(r), pc, regs->r, cpu.r); \
}
bool arch_difftest_check_reg(CPU_state *ref_r, vaddr_t pc) {
// TODO: Check the registers state with QEMU.
if (memcmp(&cpu, ref_r, DIFFTEST_REG_SIZE)) {
check_reg(ref_r, eax);
check_reg(ref_r, ecx);
check_reg(ref_r, edx);
check_reg(ref_r, ebx);
check_reg(ref_r, esp);
check_reg(ref_r, ebp);
check_reg(ref_r, esi);
check_reg(ref_r, edi);
check_reg(ref_r, eip);
return false;
}
return true;
// check_flag(ref_r, CF);
// check_flag(ref_r, OF);
// check_flag(ref_r, SF);
// check_flag(ref_r, ZF);
//
// if (eflags_skip_mask) {
// eflags_skip_mask = 0;
// }
}
void arch_difftest_arch_attach(void) {
// first copy the image
ref_difftest_memcpy_from_dut(PC_START, guest_to_host(PC_START), PMEM_SIZE - PC_START);
// then set some special registers
uint8_t code[] = {
// we put this code at 0x7e00
0xb8, 0x00, 0x00, 0x00, 0x00, // mov $0x0, %eax
0x0f, 0x22, 0xd8, // mov %eax, %cr3
0xb8, 0x00, 0x00, 0x00, 0x00, // mov $0x0, %eax
0x0f, 0x22, 0xc0, // mov %eax, %cr0
0x0f, 0x01, 0x1d, 0x40, 0x7e, 0x00, 0x00, // lidtl (0x7e40)
};
uint8_t idtdesc[6];
*(uint32_t *)(code + 1) = cpu.cr3.val;
*(uint32_t *)(code + 9) = cpu.cr0.val;
idtdesc[0] = cpu.idtr.limit & 0xff;
idtdesc[1] = cpu.idtr.limit >> 8;
*(uint32_t *)(idtdesc + 2) = cpu.idtr.base;
assert(sizeof(code) < 0x40);
ref_difftest_memcpy_from_dut(0x7e00, code, sizeof(code));
ref_difftest_memcpy_from_dut(0x7e40, idtdesc, sizeof(idtdesc));
CPU_state r = cpu;
r.eip = 0x7e00;
ref_difftest_setregs(&r);
ref_difftest_exec(5);
ref_difftest_setregs(&cpu);
}
......@@ -154,7 +154,7 @@ make_EHelper(mul) {
default: assert(0);
}
difftest_skip_eflags(EFLAGS_MASK_ALL);
//difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template1(mul);
}
......@@ -180,7 +180,7 @@ make_EHelper(imul1) {
default: assert(0);
}
difftest_skip_eflags(EFLAGS_MASK_ALL);
//difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template1(imul);
}
......@@ -192,7 +192,7 @@ make_EHelper(imul2) {
rtl_imul_lo(&t2, &t1, &t0);
operand_write(id_dest, &t2);
difftest_skip_eflags(EFLAGS_MASK_ALL);
//difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template2(imul);
}
......@@ -205,7 +205,7 @@ make_EHelper(imul3) {
rtl_imul_lo(&t2, &t1, &t0);
operand_write(id_dest, &t2);
difftest_skip_eflags(EFLAGS_MASK_ALL);
//difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template3(imul);
}
......@@ -237,7 +237,7 @@ make_EHelper(div) {
default: assert(0);
}
difftest_skip_eflags(EFLAGS_MASK_ALL);
//difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template1(div);
}
......@@ -269,6 +269,6 @@ make_EHelper(idiv) {
default: assert(0);
}
difftest_skip_eflags(EFLAGS_MASK_ALL);
//difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template1(idiv);
}
#include "cpu/exec.h"
#include "cpu/cc.h"
#include "cc.h"
make_EHelper(jmp) {
// the target address is calculated at the decode stage
rtl_j(decoding.jmp_eip);
rtl_j(decinfo.jmp_pc);
print_asm("jmp %x", decoding.jmp_eip);
print_asm("jmp %x", decinfo.jmp_pc);
}
make_EHelper(jcc) {
// the target address is calculated at the decode stage
uint32_t cc = decoding.opcode & 0xf;
uint32_t cc = decinfo.opcode & 0xf;
rtl_setcc(&t0, cc);
rtl_li(&t1, 0);
rtl_jrelop(RELOP_NE, &t0, &t1, decoding.jmp_eip);
rtl_jrelop(RELOP_NE, &t0, &t1, decinfo.jmp_pc);
print_asm("j%s %x", get_cc_name(cc), decoding.jmp_eip);
print_asm("j%s %x", get_cc_name(cc), decinfo.jmp_pc);
}
make_EHelper(jmp_rm) {
......@@ -27,11 +27,11 @@ make_EHelper(jmp_rm) {
make_EHelper(call) {
// the target address is calculated at the decode stage
// TODO();
rtl_li(&t2, decoding.seq_eip);
rtl_li(&t2, decinfo.seq_pc);
rtl_push(&t2);
rtl_j(decoding.jmp_eip);
rtl_j(decinfo.jmp_pc);
print_asm("call %x", decoding.jmp_eip);
print_asm("call %x", decinfo.jmp_pc);
}
make_EHelper(ret) {
......@@ -44,7 +44,7 @@ make_EHelper(ret) {
make_EHelper(call_rm) {
// TODO();
rtl_li(&t2, decoding.seq_eip);
rtl_li(&t2, decinfo.seq_pc);
rtl_push(&t2);
rtl_jr(&id_dest->val);
......
......@@ -60,18 +60,18 @@ make_EHelper(leave) {
}
make_EHelper(cltd) {
if (decoding.is_operand_size_16) {
if (decinfo.arch.is_operand_size_16) {
TODO();
}
else {
rtl_sari(&cpu.edx, &cpu.eax, 31);
}
print_asm(decoding.is_operand_size_16 ? "cwtl" : "cltd");
print_asm(decinfo.arch.is_operand_size_16 ? "cwtl" : "cltd");
}
make_EHelper(cwtl) {
if (decoding.is_operand_size_16) {
if (decinfo.arch.is_operand_size_16) {
TODO();
}
else {
......@@ -79,18 +79,18 @@ make_EHelper(cwtl) {
rtl_sext(&cpu.eax, &cpu.eax, 2);
}
print_asm(decoding.is_operand_size_16 ? "cbtw" : "cwtl");
print_asm(decinfo.arch.is_operand_size_16 ? "cbtw" : "cwtl");
}
make_EHelper(movsx) {
id_dest->width = decoding.is_operand_size_16 ? 2 : 4;
id_dest->width = decinfo.arch.is_operand_size_16 ? 2 : 4;
rtl_sext(&t0, &id_src->val, id_src->width);
operand_write(id_dest, &t0);
print_asm_template2(movsx);
}
make_EHelper(movzx) {
id_dest->width = decoding.is_operand_size_16 ? 2 : 4;
id_dest->width = decinfo.arch.is_operand_size_16 ? 2 : 4;
operand_write(id_dest, &id_src->val);
print_asm_template2(movzx);
}
......
......@@ -15,9 +15,9 @@ typedef struct {
static inline void set_width(int width) {
if (width == 0) {
width = decoding.is_operand_size_16 ? 2 : 4;
width = decinfo.arch.is_operand_size_16 ? 2 : 4;
}
decoding.src.width = decoding.dest.width = decoding.src2.width = width;
decinfo.src.width = decinfo.dest.width = decinfo.src2.width = width;
}
/* Instruction Decode and EXecute */
......@@ -36,7 +36,7 @@ static make_EHelper(2byte_esc);
/* 0x04 */ item4, item5, item6, item7 \
}; \
static make_EHelper(name) { \
idex(eip, &concat(opcode_table_, name)[decoding.ext_opcode]); \
idex(eip, &concat(opcode_table_, name)[decinfo.arch.ext_opcode]); \
}
/* 0x80, 0x81, 0x83 */
......@@ -207,41 +207,41 @@ make_group(gp7,
static make_EHelper(2byte_esc) {
uint32_t opcode = instr_fetch(eip, 1) | 0x100;
decoding.opcode = opcode;
decinfo.opcode = opcode;
set_width(opcode_table[opcode].width);
idex(eip, &opcode_table[opcode]);
}
make_EHelper(real) {
uint32_t opcode = instr_fetch(eip, 1);
decoding.opcode = opcode;
decinfo.opcode = opcode;
set_width(opcode_table[opcode].width);
idex(eip, &opcode_table[opcode]);
}
static inline void update_eip(void) {
if (decoding.is_jmp) { decoding.is_jmp = 0; }
else { cpu.eip = decoding.seq_eip; }
if (decinfo.is_jmp) { decinfo.is_jmp = 0; }
else { cpu.eip = decinfo.seq_pc; }
}
void exec_wrapper(bool print_flag) {
vaddr_t ori_eip = cpu.eip;
#ifdef DEBUG
decoding.p = decoding.asm_buf;
decoding.p += sprintf(decoding.p, "%8x: ", ori_eip);
decinfo.p = decinfo.asm_buf;
decinfo.p += sprintf(decinfo.p, "%8x: ", ori_eip);
#endif
decoding.seq_eip = ori_eip;
exec_real(&decoding.seq_eip);
decinfo.seq_pc = ori_eip;
exec_real(&decinfo.seq_pc);
#ifdef DEBUG
int instr_len = decoding.seq_eip - ori_eip;
sprintf(decoding.p, "%*.s", 50 - (12 + 3 * instr_len), "");
strcat(decoding.asm_buf, decoding.assembly);
Log_write("%s\n", decoding.asm_buf);
int instr_len = decinfo.seq_pc - ori_eip;
sprintf(decinfo.p, "%*.s", 50 - (12 + 3 * instr_len), "");
strcat(decinfo.asm_buf, decinfo.assembly);
Log_write("%s\n", decinfo.asm_buf);
if (print_flag) {
puts(decoding.asm_buf);
puts(decinfo.asm_buf);
}
#endif
......@@ -256,7 +256,7 @@ void exec_wrapper(bool print_flag) {
}
#if defined(DIFF_TEST)
void difftest_step(uint32_t);
void difftest_step(vaddr_t pc);
difftest_step(ori_eip);
#endif
}
#include "cpu/exec.h"
#include "cpu/cc.h"
#include "cc.h"
// dest <- and result
static inline void and_internal(rtlreg_t *dest) {
......@@ -44,7 +44,7 @@ make_EHelper(sar) {
operand_write(id_dest, &t2);
rtl_update_ZFSF(&t2, id_dest->width);
// unnecessary to update CF and OF in NEMU
difftest_skip_eflags(EFLAGS_MASK_CF | EFLAGS_MASK_OF);
//difftest_skip_eflags(EFLAGS_MASK_CF | EFLAGS_MASK_OF);
print_asm_template2(sar);
}
......@@ -53,7 +53,7 @@ make_EHelper(shl) {
operand_write(id_dest, &t2);
rtl_update_ZFSF(&t2, id_dest->width);
// unnecessary to update CF and OF in NEMU
difftest_skip_eflags(EFLAGS_MASK_CF | EFLAGS_MASK_OF | EFLAGS_MASK_ZF);
//difftest_skip_eflags(EFLAGS_MASK_CF | EFLAGS_MASK_OF | EFLAGS_MASK_ZF);
print_asm_template2(shl);
}
......@@ -62,7 +62,7 @@ make_EHelper(shr) {
operand_write(id_dest, &t2);
rtl_update_ZFSF(&t2, id_dest->width);
// unnecessary to update CF and OF in NEMU
difftest_skip_eflags(EFLAGS_MASK_CF | EFLAGS_MASK_OF);
//difftest_skip_eflags(EFLAGS_MASK_CF | EFLAGS_MASK_OF);
print_asm_template2(shr);
}
......@@ -75,12 +75,12 @@ make_EHelper(rol) {
operand_write(id_dest, &t2);
// unnecessary to update eflags in NEMU
difftest_skip_eflags(EFLAGS_MASK_ALL);
//difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template2(rol);
}
make_EHelper(setcc) {
uint32_t cc = decoding.opcode & 0xf;
uint32_t cc = decinfo.opcode & 0xf;
rtl_setcc(&t2, cc);
operand_write(id_dest, &t2);
......@@ -107,7 +107,7 @@ make_EHelper(shld) {
operand_write(id_dest, &t2);
rtl_update_ZFSF(&t2, id_dest->width);
// unnecessary to update CF and OF in NEMU
difftest_skip_eflags(EFLAGS_MASK_CF | EFLAGS_MASK_OF);
//difftest_skip_eflags(EFLAGS_MASK_CF | EFLAGS_MASK_OF);
print_asm_template3(shld);
}
......@@ -123,6 +123,6 @@ make_EHelper(shrd) {
operand_write(id_dest, &t2);
rtl_update_ZFSF(&t2, id_dest->width);
// unnecessary to update CF and OF in NEMU
difftest_skip_eflags(EFLAGS_MASK_CF | EFLAGS_MASK_OF);
//difftest_skip_eflags(EFLAGS_MASK_CF | EFLAGS_MASK_OF);
print_asm_template3(shrd);
}
......@@ -3,7 +3,7 @@
make_EHelper(real);
make_EHelper(operand_size) {
decoding.is_operand_size_16 = true;
decinfo.arch.is_operand_size_16 = true;
exec_real(eip);
decoding.is_operand_size_16 = false;
decinfo.arch.is_operand_size_16 = false;
}
#include "cpu/exec.h"
#include "monitor/monitor.h"
void interpret_rtl_exit(int state) {
nemu_state = state;
}
make_EHelper(nop) {
print_asm("nop");
}
......@@ -31,7 +27,7 @@ make_EHelper(inv) {
"* The machine is always right!\n"
"* Every line of untested code is always wrong!\33[0m\n\n", logo);
rtl_exit(NEMU_ABORT);
rtl_exit(NEMU_ABORT, cpu.pc, -1);
print_asm("invalid opcode");
}
......@@ -41,7 +37,7 @@ make_EHelper(nemu_trap) {
difftest_skip_ref();
#endif
rtl_exit(NEMU_END);
rtl_exit(NEMU_END, cpu.pc, cpu.eax);
print_asm("nemu trap");
return;
......
......@@ -49,7 +49,7 @@ make_EHelper(iret) {
rtl_jr(&t0);
difftest_skip_eflags(EFLAGS_MASK_ALL);
//difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm("iret");
}
......
#ifndef __X86_DECODE_H__
#define __X86_DECODE_H__
#include "common.h"
#include "cpu/decode.h"
struct CPUDecodeInfo {
bool is_operand_size_16;
uint8_t ext_opcode;
};
#define suffix_char(width) ((width) == 4 ? 'l' : ((width) == 1 ? 'b' : ((width) == 2 ? 'w' : '?')))
typedef union {
struct {
uint8_t R_M :3;
uint8_t reg :3;
uint8_t mod :2;
};
struct {
uint8_t dont_care :3;
uint8_t opcode :3;
};
uint8_t val;
} ModR_M;
typedef union {
struct {
uint8_t base :3;
uint8_t index :3;
uint8_t ss :2;
};
uint8_t val;
} SIB;
void load_addr(vaddr_t *, ModR_M *, Operand *);
void read_ModR_M(vaddr_t *, Operand *, bool, Operand *, bool);
make_DHelper(I2E);
make_DHelper(I2a);
make_DHelper(I2r);
make_DHelper(SI2E);
make_DHelper(SI_E2G);
make_DHelper(I_E2G);
make_DHelper(I_G2E);
make_DHelper(I);
make_DHelper(r);
make_DHelper(E);
make_DHelper(setcc_E);
make_DHelper(gp7_E);
make_DHelper(test_I);
make_DHelper(SI);
make_DHelper(G2E);
make_DHelper(E2G);
make_DHelper(mov_I2r);
make_DHelper(mov_I2E);
make_DHelper(mov_G2E);
make_DHelper(mov_E2G);
make_DHelper(lea_M2G);
make_DHelper(gp2_1_E);
make_DHelper(gp2_cl2E);
make_DHelper(gp2_Ib2E);
make_DHelper(Ib_G2E);
make_DHelper(cl_G2E);
make_DHelper(O2a);
make_DHelper(a2O);
make_DHelper(J);
make_DHelper(push_SI);
make_DHelper(in_I2a);
make_DHelper(in_dx2a);
make_DHelper(out_a2I);
make_DHelper(out_a2dx);
#endif
#ifndef __X86_DIFF_TEST_H__
#define __X86_DIFF_TEST_H__
#define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 9) // GRPs + EIP
#endif
......@@ -4,6 +4,8 @@
#include "common.h"
#include "memory/mmu.h"
#define PC_START 0x100000
enum { R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI };
enum { R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI };
enum { R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH };
......@@ -49,7 +51,10 @@ typedef struct {
};
};
vaddr_t eip;
union {
vaddr_t pc;
vaddr_t eip;
};
uint32_t eflags;
uint16_t cs;
......@@ -73,8 +78,6 @@ typedef struct {
bool INTR;
} CPU_state;
extern CPU_state cpu;
static inline int check_reg_index(int index) {
assert(index >= 0 && index < 8);
return index;
......
#ifndef __X86_RTL_H__
#define __X86_RTL_H__
#include "cpu/rtl.h"
/* RTL pseudo instructions */
static inline void rtl_lr(rtlreg_t* dest, int r, int width) {
switch (width) {
case 4: rtl_mv(dest, &reg_l(r)); return;
case 1: rtl_host_lm(dest, &reg_b(r), 1); return;
case 2: rtl_host_lm(dest, &reg_w(r), 2); return;
default: assert(0);
}
}
static inline void rtl_sr(int r, const rtlreg_t* src1, int width) {
switch (width) {
case 4: rtl_mv(&reg_l(r), src1); return;
case 1: rtl_host_sm(&reg_b(r), src1, 1); return;
case 2: rtl_host_sm(&reg_w(r), src1, 2); return;
default: assert(0);
}
}
static inline void rtl_push(const rtlreg_t* src1) {
// esp <- esp - 4
// M[esp] <- src1
// TODO();
rtl_subi(&cpu.esp, &cpu.esp, 4);
rtl_sm(&cpu.esp, src1, 4);
}
static inline void rtl_pop(rtlreg_t* dest) {
// dest <- M[esp]
// esp <- esp + 4
// TODO();
rtl_lm(dest, &cpu.esp, 4);
rtl_addi(&cpu.esp, &cpu.esp, 4);
}
static inline void rtl_is_sub_overflow(rtlreg_t* dest,
const rtlreg_t* res, const rtlreg_t* src1, const rtlreg_t* src2, int width) {
// res = src1 - src2
assert(dest != res && dest != src1 && dest != src2);
rtl_xor(dest, src1, src2);
rtl_xor(&at, src1, res);
rtl_and(dest, dest, &at);
rtl_msb(dest, dest, width);
}
static inline void rtl_is_sub_carry(rtlreg_t* dest,
const rtlreg_t* res, const rtlreg_t* src1) {
// res = src1 - src2
assert(dest != res && dest != src1);
rtl_setrelop(RELOP_LTU, dest, src1, res);
}
static inline void rtl_is_add_overflow(rtlreg_t* dest,
const rtlreg_t* res, const rtlreg_t* src1, const rtlreg_t* src2, int width) {
// res = src1 + src2
assert(dest != res && dest != src1 && dest != src2);
rtl_is_sub_overflow(dest, src1, res, src2, width);
}
static inline void rtl_is_add_carry(rtlreg_t* dest,
const rtlreg_t* res, const rtlreg_t* src1) {
// res = src1 + src2
assert(dest != res && dest != src1);
rtl_is_sub_carry(dest, src1, res);
}
static inline void rtl_update_ZF(const rtlreg_t* result, int width) {
// eflags.ZF <- is_zero(result[width * 8 - 1 .. 0])
// TODO();
if (width != 4) {
rtl_andi(&cpu.ZF, result, 0xffffffffu >> ((4 - width) * 8));
rtl_setrelopi(RELOP_EQ, &cpu.ZF, &cpu.ZF, 0);
}
else {
rtl_setrelopi(RELOP_EQ, &cpu.ZF, result, 0);
}
}
static inline void rtl_update_SF(const rtlreg_t* result, int width) {
// eflags.SF <- is_sign(result[width * 8 - 1 .. 0])
// TODO();
rtl_msb(&cpu.SF, result, width);
}
static inline void rtl_update_ZFSF(const rtlreg_t* result, int width) {
rtl_update_ZF(result, width);
rtl_update_SF(result, width);
}
#endif
#include "nemu.h"
int arch_load_default_img() {
const uint8_t img [] = {
0xb8, 0x34, 0x12, 0x00, 0x00, // 100000: movl $0x1234,%eax
0xb9, 0x27, 0x00, 0x10, 0x00, // 100005: movl $0x100027,%ecx
0x89, 0x01, // 10000a: movl %eax,(%ecx)
0x66, 0xc7, 0x41, 0x04, 0x01, 0x00, // 10000c: movw $0x1,0x4(%ecx)
0xbb, 0x02, 0x00, 0x00, 0x00, // 100012: movl $0x2,%ebx
0x66, 0xc7, 0x84, 0x99, 0x00, 0xe0, // 100017: movw $0x1,-0x2000(%ecx,%ebx,4)
0xff, 0xff, 0x01, 0x00,
0xb8, 0x00, 0x00, 0x00, 0x00, // 100021: movl $0x0,%eax
0xd6, // 100026: nemu_trap
};
memcpy(guest_to_host(PC_START), img, sizeof(img));
return sizeof(img);
}
void arch_restart() {
/* Set the initial instruction pointer. */
cpu.eip = PC_START;
cpu.cs = 0x8;
cpu.cr0.val = 0x60000011;
}
#include "cpu/exec.h"
#include "cpu/rtl.h"
#include "memory/mmu.h"
void raise_intr(uint8_t NO, vaddr_t ret_addr) {
......@@ -31,7 +31,3 @@ void raise_intr(uint8_t NO, vaddr_t ret_addr) {
rtl_or(&t0, &t0, &t1);
rtl_jr(&t0);
}
void dev_raise_intr() {
cpu.INTR = true;
}
......@@ -2,13 +2,11 @@
#include <stdlib.h>
#include <time.h>
CPU_state cpu;
const char *regsl[] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
const char *regsw[] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"};
const char *regsb[] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"};
void reg_test() {
void arch_reg_test() {
srand(time(0));
uint32_t sample[8];
uint32_t eip_sample = rand();
......@@ -42,7 +40,7 @@ void reg_test() {
assert(eip_sample == cpu.eip);
}
void display_reg() {
void arch_reg_display() {
int i;
for (i = 0; i < 8; i ++) {
printf("%s: 0x%08x\n", regsl[i], cpu.gpr[i]._32);
......
#include "cpu/rtl.h"
#include "cpu/decode.h"
CPU_state cpu;
rtlreg_t t0, t1, t2, t3, at;
/* shared by all helper functions */
DecodeInfo decinfo;
void decinfo_set_jmp(bool is_jmp) {
decinfo.is_jmp = is_jmp;
}
void operand_write(Operand *op, rtlreg_t* src) {
if (op->type == OP_TYPE_REG) { rtl_sr(op->reg, src, op->width); }
else if (op->type == OP_TYPE_MEM) { rtl_sm(&op->addr, src, op->width); }
else { assert(0); }
}
#include "nemu.h"
void dev_raise_intr() {
cpu.INTR = true;
}
......@@ -36,7 +36,7 @@ static int key_f = 0, key_r = 0;
#define KEYDOWN_MASK 0x8000
void send_key(uint8_t scancode, bool is_keydown) {
if (nemu_state == NEMU_RUNNING &&
if (nemu_state.state == NEMU_RUNNING &&
keymap[scancode] != _KEY_NONE) {
uint32_t am_scancode = keymap[scancode] | (is_keydown ? KEYDOWN_MASK : 0);
key_queue[key_r] = am_scancode;
......
......@@ -5,7 +5,7 @@
#define RTC_PORT 0x48 // Note that this is not the standard
void timer_intr() {
if (nemu_state == NEMU_RUNNING) {
if (nemu_state.state == NEMU_RUNNING) {
extern void dev_raise_intr(void);
dev_raise_intr();
}
......
......@@ -8,7 +8,11 @@
*/
#define MAX_INSTR_TO_PRINT 10
int nemu_state = NEMU_STOP;
NEMUState nemu_state = {.state = NEMU_STOP};
void interpret_rtl_exit(int state, vaddr_t halt_pc, uint32_t halt_ret) {
nemu_state = (NEMUState) { .state = state, .halt_pc = halt_pc, .halt_ret = halt_ret };
}
void exec_wrapper(bool);
......@@ -24,11 +28,11 @@ void monitor_statistic() {
/* Simulate how the CPU works. */
void cpu_exec(uint64_t n) {
if (nemu_state == NEMU_END || nemu_state == NEMU_ABORT) {
if (nemu_state.state == NEMU_END || nemu_state.state == NEMU_ABORT) {
printf("Program execution has ended. To restart the program, exit NEMU and run again.\n");
return;
}
nemu_state = NEMU_RUNNING;
nemu_state.state = NEMU_RUNNING;
bool print_flag = n < MAX_INSTR_TO_PRINT;
......@@ -48,19 +52,19 @@ void cpu_exec(uint64_t n) {
device_update();
#endif
if (nemu_state != NEMU_RUNNING) {
if (nemu_state == NEMU_END) {
if (nemu_state.state != NEMU_RUNNING) {
if (nemu_state.state == NEMU_END) {
printflog("\33[1;31mnemu: HIT %s TRAP\33[0m at eip = 0x%08x\n\n",
(cpu.eax == 0 ? "GOOD" : "BAD"), cpu.eip - 1);
(nemu_state.halt_ret == 0 ? "GOOD" : "BAD"), nemu_state.halt_pc);
monitor_statistic();
return;
}
else if (nemu_state == NEMU_ABORT) {
printflog("\33[1;31mnemu: ABORT\33[0m at eip = 0x%08x\n\n", cpu.eip);
else if (nemu_state.state == NEMU_ABORT) {
printflog("\33[1;31mnemu: ABORT\33[0m at eip = 0x%08x\n\n", nemu_state.halt_pc);
return;
}
}
}
if (nemu_state == NEMU_RUNNING) { nemu_state = NEMU_STOP; }
if (nemu_state.state == NEMU_RUNNING) { nemu_state.state = NEMU_STOP; }
}
......@@ -78,7 +78,7 @@ static int cmd_save(char *args) {
FILE *fp = fopen(arg, "w");
assert(fp != NULL);
fwrite(&cpu, sizeof(cpu), 1, fp);
fwrite(guest_to_host(ENTRY_START), PMEM_SIZE - ENTRY_START, 1, fp);
fwrite(guest_to_host(PC_START), PMEM_SIZE - PC_START, 1, fp);
fclose(fp);
}
return 0;
......@@ -96,7 +96,7 @@ static int cmd_load(char *args) {
FILE *fp = fopen(arg, "r");
assert(fp != NULL);
fread(&cpu, sizeof(cpu), 1, fp);
fread(guest_to_host(ENTRY_START), PMEM_SIZE - ENTRY_START, 1, fp);
fread(guest_to_host(PC_START), PMEM_SIZE - PC_START, 1, fp);
fclose(fp);
}
return 0;
......
......@@ -4,19 +4,22 @@
#include "monitor/monitor.h"
#include "monitor/diff-test.h"
static void (*ref_difftest_memcpy_from_dut)(paddr_t dest, void *src, size_t n);
static void (*ref_difftest_getregs)(void *c);
static void (*ref_difftest_setregs)(const void *c);
static void (*ref_difftest_exec)(uint64_t n);
void (*ref_difftest_memcpy_from_dut)(paddr_t dest, void *src, size_t n) = NULL;
void (*ref_difftest_getregs)(void *c) = NULL;
void (*ref_difftest_setregs)(const void *c) = NULL;
void (*ref_difftest_exec)(uint64_t n) = NULL;
static bool is_skip_ref;
static bool is_skip_dut;
static uint32_t eflags_skip_mask;
//static uint32_t eflags_skip_mask;
static bool is_detach;
void difftest_skip_ref() { is_skip_ref = true; }
void difftest_skip_dut() { is_skip_dut = true; }
void difftest_skip_eflags(uint32_t mask) { eflags_skip_mask = mask; }
//void difftest_skip_eflags(uint32_t mask) { eflags_skip_mask = mask; }
bool arch_difftest_check_reg(CPU_state *ref_r, vaddr_t pc);
void arch_difftest_attach(void);
void init_difftest(char *ref_so_file, long img_size) {
#ifndef DIFF_TEST
......@@ -50,33 +53,11 @@ void init_difftest(char *ref_so_file, long img_size) {
"If it is not necessary, you can turn it off in include/common.h.", ref_so_file);
ref_difftest_init();
ref_difftest_memcpy_from_dut(ENTRY_START, guest_to_host(ENTRY_START), img_size);
ref_difftest_memcpy_from_dut(PC_START, guest_to_host(PC_START), img_size);
ref_difftest_setregs(&cpu);
}
#define check_reg(regs, r) \
if (regs.r != cpu.r) { \
Log("%s is different after executing instruction at eip = 0x%08x, right = 0x%08x, wrong = 0x%08x", \
str(r), eip, regs.r, cpu.r); \
}
#define check_flag(regs, f) \
do { \
uint32_t mask = concat(EFLAGS_MASK_, f); \
uint32_t __flag = ((regs.eflags & mask) != 0); \
if (mask & eflags_skip_mask) { \
cpu.f = __flag; \
} \
else { \
if (__flag != cpu.f) { \
Log("%s is different after executing instruction at eip = 0x%08x, right = 0x%08x, wrong = 0x%08x", \
"eflags." str(f), eip, __flag, cpu.f); \
nemu_state = NEMU_ABORT; \
} \
} \
} while(0)
void difftest_step(uint32_t eip) {
void difftest_step(vaddr_t pc) {
CPU_state ref_r;
if (is_detach) return;
......@@ -89,7 +70,6 @@ void difftest_step(uint32_t eip) {
if (is_skip_ref) {
// to skip the checking of an instruction, just copy the reg state to reference design
ref_difftest_getregs(&ref_r);
cpu.eflags = ref_r.eflags;
ref_difftest_setregs(&cpu);
is_skip_ref = false;
return;
......@@ -98,30 +78,9 @@ void difftest_step(uint32_t eip) {
ref_difftest_exec(1);
ref_difftest_getregs(&ref_r);
// TODO: Check the registers state with QEMU.
// Set `diff` as `true` if they are not the same.
// TODO();
if (memcmp(&cpu, &ref_r, DIFFTEST_REG_SIZE)) {
check_reg(ref_r, eax);
check_reg(ref_r, ecx);
check_reg(ref_r, edx);
check_reg(ref_r, ebx);
check_reg(ref_r, esp);
check_reg(ref_r, ebp);
check_reg(ref_r, esi);
check_reg(ref_r, edi);
check_reg(ref_r, eip);
nemu_state = NEMU_ABORT;
}
check_flag(ref_r, CF);
check_flag(ref_r, OF);
check_flag(ref_r, SF);
check_flag(ref_r, ZF);
if (eflags_skip_mask) {
eflags_skip_mask = 0;
if (!arch_difftest_check_reg(&ref_r, pc)) {
nemu_state.state = NEMU_ABORT;
nemu_state.halt_pc = pc;
}
}
......@@ -138,43 +97,5 @@ void difftest_attach() {
is_skip_ref = false;
is_skip_dut = false;
// first copy the image
ref_difftest_memcpy_from_dut(ENTRY_START, guest_to_host(ENTRY_START), PMEM_SIZE - ENTRY_START);
// then set some special registers
uint8_t code[] = {
// we put this code at 0x7e00
0xb8, 0x00, 0x00, 0x00, 0x00, // mov $0x0, %eax
0x0f, 0x22, 0xd8, // mov %eax, %cr3
0xb8, 0x00, 0x00, 0x00, 0x00, // mov $0x0, %eax
0x0f, 0x22, 0xc0, // mov %eax, %cr0
0x0f, 0x01, 0x1d, 0x40, 0x7e, 0x00, 0x00, // lidtl (0x7e40)
};
uint8_t idtdesc[6];
*(uint32_t *)(code + 1) = cpu.cr3.val;
*(uint32_t *)(code + 9) = cpu.cr0.val;
idtdesc[0] = cpu.idtr.limit & 0xff;
idtdesc[1] = cpu.idtr.limit >> 8;
*(uint32_t *)(idtdesc + 2) = cpu.idtr.base;
assert(sizeof(code) < 0x40);
ref_difftest_memcpy_from_dut(0x7e00, code, sizeof(code));
ref_difftest_memcpy_from_dut(0x7e40, idtdesc, sizeof(idtdesc));
CPU_state r = cpu;
r.eip = 0x7e00;
ref_difftest_setregs(&r);
ref_difftest_exec(5);
//rtl_computer_eflags(&cpu.eflags);
cpu.eflags =
(cpu.OF << EFLAGS_BIT_OF) |
(cpu.CF << EFLAGS_BIT_CF) |
(cpu.IF << EFLAGS_BIT_IF) |
(cpu.SF << EFLAGS_BIT_SF) |
(cpu.CF << EFLAGS_BIT_CF);
ref_difftest_setregs(&cpu);
arch_difftest_attach();
}
......@@ -7,7 +7,9 @@ void init_regex();
void init_wp_pool();
void init_device();
void reg_test();
void arch_reg_test();
int arch_load_default_img();
void arch_restart();
FILE *log_fp = NULL;
static char *log_file = NULL;
......@@ -38,30 +40,11 @@ static inline void welcome() {
printf("For help, type \"help\"\n");
}
static inline int load_default_img() {
const uint8_t img [] = {
0xb8, 0x34, 0x12, 0x00, 0x00, // 100000: movl $0x1234,%eax
0xb9, 0x27, 0x00, 0x10, 0x00, // 100005: movl $0x100027,%ecx
0x89, 0x01, // 10000a: movl %eax,(%ecx)
0x66, 0xc7, 0x41, 0x04, 0x01, 0x00, // 10000c: movw $0x1,0x4(%ecx)
0xbb, 0x02, 0x00, 0x00, 0x00, // 100012: movl $0x2,%ebx
0x66, 0xc7, 0x84, 0x99, 0x00, 0xe0, // 100017: movw $0x1,-0x2000(%ecx,%ebx,4)
0xff, 0xff, 0x01, 0x00,
0xb8, 0x00, 0x00, 0x00, 0x00, // 100021: movl $0x0,%eax
0xd6, // 100026: nemu_trap
};
Log("No image is given. Use the default build-in image.");
memcpy(guest_to_host(ENTRY_START), img, sizeof(img));
return sizeof(img);
}
static inline long load_img() {
long size;
if (img_file == NULL) {
size = load_default_img();
Log("No image is given. Use the default build-in image.");
size = arch_load_default_img();
}
else {
int ret;
......@@ -75,7 +58,7 @@ static inline long load_img() {
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
ret = fread(guest_to_host(ENTRY_START), size, 1, fp);
ret = fread(guest_to_host(PC_START), size, 1, fp);
assert(ret == 1);
fclose(fp);
......@@ -83,13 +66,6 @@ static inline long load_img() {
return size;
}
static inline void restart() {
/* Set the initial instruction pointer. */
cpu.eip = ENTRY_START;
cpu.cs = 0x8;
cpu.cr0.val = 0x60000011;
}
static inline void parse_args(int argc, char *argv[]) {
int o;
while ( (o = getopt(argc, argv, "-bl:d:")) != -1) {
......@@ -117,13 +93,13 @@ int init_monitor(int argc, char *argv[]) {
init_log();
/* Test the implementation of the `CPU_state' structure. */
reg_test();
arch_reg_test();
/* Load the image to memory. */
long img_size = load_img();
/* Initialize this virtual computer system. */
restart();
arch_restart();
/* Compile the regular expressions. */
init_regex();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册