提交 22d7ad05 编写于 作者: Z Zihao Yu

monitor,diff-test: check eflags

上级 f67f7357
......@@ -2,6 +2,7 @@
#define __CPU_EXEC_H__
#include "nemu.h"
#include "monitor/diff-test.h"
#define make_EHelper(name) void concat(exec_, name) (vaddr_t *eip)
typedef void (*EHelper) (vaddr_t *);
......
......@@ -8,6 +8,22 @@ 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 };
#define EFLAGS_BIT_CF 0
#define EFLAGS_BIT_ZF 6
#define EFLAGS_BIT_SF 7
#define EFLAGS_BIT_IF 9
#define EFLAGS_BIT_OF 11
#define __map_eflags(f) f(OF) f(IF) f(SF) f(ZF) f(CF)
#define __f(X) concat(EFLAGS_MASK_, X) = 1 << concat(EFLAGS_BIT_, X),
enum {
__map_eflags(__f)
#undef __f
#define __f(X) | concat(EFLAGS_MASK_, X)
EFLAGS_MASK_ALL = 0 __map_eflags(__f)
#undef __f
};
/* TODO: Re-organize the `CPU_state' structure to match the register
* encoding scheme in i386 instruction format. For example, if we
* access cpu.gpr[3]._16, we will get the `bx' register; if we access
......@@ -34,6 +50,7 @@ typedef struct {
};
vaddr_t eip;
uint32_t eflags;
uint16_t cs;
rtlreg_t OF, CF, SF, ZF, IF;
......
......@@ -3,4 +3,8 @@
#define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 9) // GRPs + EIP
void difftest_skip_ref(void);
void difftest_skip_dut(void);
void difftest_skip_eflags(uint32_t mask);
#endif
......@@ -140,6 +140,7 @@ make_EHelper(mul) {
default: assert(0);
}
difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template1(mul);
}
......@@ -165,6 +166,7 @@ make_EHelper(imul1) {
default: assert(0);
}
difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template1(imul);
}
......@@ -176,6 +178,7 @@ make_EHelper(imul2) {
rtl_imul_lo(&t2, &t1, &t0);
operand_write(id_dest, &t2);
difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template2(imul);
}
......@@ -188,6 +191,7 @@ make_EHelper(imul3) {
rtl_imul_lo(&t2, &t1, &t0);
operand_write(id_dest, &t2);
difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template3(imul);
}
......@@ -219,6 +223,7 @@ make_EHelper(div) {
default: assert(0);
}
difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template1(div);
}
......@@ -250,5 +255,6 @@ make_EHelper(idiv) {
default: assert(0);
}
difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template1(idiv);
}
......@@ -2,37 +2,24 @@
void rtl_compute_eflags(rtlreg_t *dest) {
rtl_li(dest, 0);
rtl_shli(&at, &cpu.OF, 11);
rtl_or(dest, dest, &at);
rtl_shli(&at, &cpu.IF, 9);
#define __f(X) \
rtl_shli(&at, &cpu.X, concat(EFLAGS_BIT_, X)); \
rtl_or(dest, dest, &at);
rtl_shli(&at, &cpu.SF, 7);
rtl_or(dest, dest, &at);
__map_eflags(__f)
rtl_shli(&at, &cpu.ZF, 6);
rtl_or(dest, dest, &at);
rtl_shli(&at, &cpu.CF, 0);
rtl_or(dest, dest, &at);
#undef __f
rtl_ori(dest, dest, 0x2);
}
void rtl_set_eflags(const rtlreg_t *src) {
rtl_shri(&at, src, 11);
rtl_andi(&cpu.OF, &at, 0x1);
rtl_shri(&at, src, 9);
rtl_andi(&cpu.IF, &at, 0x1);
rtl_shri(&at, src, 7);
rtl_andi(&cpu.SF, &at, 0x1);
#define __f(X) \
rtl_shri(&at, src, concat(EFLAGS_BIT_, X)); \
rtl_andi(&cpu.X, &at, 0x1);
rtl_shri(&at, src, 6);
rtl_andi(&cpu.ZF, &at, 0x1);
__map_eflags(__f)
rtl_shri(&at, src, 0);
rtl_andi(&cpu.CF, &at, 0x1);
#undef __f
}
......@@ -44,6 +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);
print_asm_template2(sar);
}
......@@ -52,6 +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);
print_asm_template2(shl);
}
......@@ -60,6 +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);
print_asm_template2(shr);
}
......@@ -71,8 +74,8 @@ make_EHelper(rol) {
rtl_or(&t2, &t1, &t2);
operand_write(id_dest, &t2);
rtl_update_ZFSF(&t2, id_dest->width);
// unnecessary to update CF and OF in NEMU
// unnecessary to update eflags in NEMU
difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm_template2(rol);
}
......@@ -104,6 +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);
print_asm_template3(shld);
}
......@@ -119,5 +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);
print_asm_template3(shrd);
}
......@@ -38,7 +38,6 @@ make_EHelper(inv) {
make_EHelper(nemu_trap) {
#if defined(DIFF_TEST)
void difftest_skip_ref();
difftest_skip_ref();
#endif
......
#include "cpu/exec.h"
void difftest_skip_ref();
void difftest_skip_dut();
make_EHelper(lidt) {
cpu.idtr.limit = vaddr_read(id_dest->addr, 2);
cpu.idtr.base = vaddr_read(id_dest->addr + 2, 4);
......@@ -52,6 +49,8 @@ make_EHelper(iret) {
rtl_jr(&t0);
difftest_skip_eflags(EFLAGS_MASK_ALL);
print_asm("iret");
}
......
......@@ -2,7 +2,7 @@
#include "nemu.h"
#include "monitor/monitor.h"
#include "diff-test.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);
......@@ -11,9 +11,11 @@ static void (*ref_difftest_exec)(uint64_t n);
static bool is_skip_ref;
static bool is_skip_dut;
static uint32_t eflags_skip_mask;
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 init_difftest(char *ref_so_file, long img_size) {
#ifndef DIFF_TEST
......@@ -57,6 +59,22 @@ void init_difftest(char *ref_so_file, long img_size) {
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) {
CPU_state ref_r;
......@@ -67,6 +85,8 @@ 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;
......@@ -91,4 +111,13 @@ void difftest_step(uint32_t 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;
}
}
#include "nemu.h"
#include "diff-test.h"
#include "monitor/diff-test.h"
void cpu_exec(uint64_t);
......
......@@ -3,7 +3,7 @@
#include <signal.h>
typedef uint32_t paddr_t;
#define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 9) // GPRs + EIP
#define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 10) // GPRs + EIP + EFLAGS
bool gdb_connect_qemu(void);
bool gdb_memcpy_to_qemu(uint32_t, void *, int);
......@@ -113,9 +113,6 @@ void difftest_init(void) {
assert(ok == 1);
// execute enough instructions to enter protected mode
int i;
for (i = 0; i < 20; i ++) {
gdb_si();
}
difftest_exec(20);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册