diff --git a/nemu/include/cpu/decode.h b/nemu/include/cpu/decode.h index df6a347449c99e58c281cf196487cd8a0b3b1dac..720c93fa456ec0ecb72c79c68d9329fc61130f23 100644 --- a/nemu/include/cpu/decode.h +++ b/nemu/include/cpu/decode.h @@ -75,47 +75,48 @@ extern DecodeInfo decoding; #define id_src2 (&decoding.src2) #define id_dest (&decoding.dest) -#define make_DHelper_funcname(name) concat(decode_, name) -#define make_DHelper(name) void make_DHelper_funcname(name) (vaddr_t *eip) +#define make_DHelper(name) void 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(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); +namespace DHelperImpl { + 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(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 diff --git a/nemu/include/cpu/exec.h b/nemu/include/cpu/exec.h index a11fff15cb0438a4aeed861d71fdc79b39328c00..77668713f53a0233a8214c9f4f821246301de46b 100644 --- a/nemu/include/cpu/exec.h +++ b/nemu/include/cpu/exec.h @@ -3,8 +3,7 @@ #include "nemu.h" -#define make_EHelper_funcname(name) concat(exec_, name) -#define make_EHelper(name) void make_EHelper_funcname(name) (vaddr_t *eip) +#define make_EHelper(name) void name(vaddr_t *eip) typedef void (*EHelper) (vaddr_t *); #include "cpu/decode.h" diff --git a/nemu/include/cpu/rtl.h b/nemu/include/cpu/rtl.h index 1e029edaa6d02beb432d24a851a7d54941ef5441..4dd9aac5131ac9768bad082e9e15d7e54648fde6 100644 --- a/nemu/include/cpu/rtl.h +++ b/nemu/include/cpu/rtl.h @@ -217,7 +217,7 @@ static inline void rtl_update_ZF(const rtlreg_t* result, int width) { // eflags.ZF <- is_zero(result[width * 8 - 1 .. 0]) RLIB_MACRO_DEBUG_ASSERT((unsigned)width < 5); static const uint32_t niddles [5] {0, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff}; - cpu_eflags::get<cpu_eflags::ZF>() = (*result & niddles[width]); + cpu_eflags::get<cpu_eflags::ZF>() = !(*result & niddles[width]); } static inline void rtl_update_SF(const rtlreg_t* result, int width) { diff --git a/nemu/src/cpu/decode/decode.cc b/nemu/src/cpu/decode/decode.cc index ecd0665f7c24898bd243bad3f792cc5f6f233c0e..94c08abfe26486fe974ff618736ff234f133c232 100644 --- a/nemu/src/cpu/decode/decode.cc +++ b/nemu/src/cpu/decode/decode.cc @@ -9,320 +9,327 @@ void decoding_set_jmp(bool is_jmp) { decoding.is_jmp = is_jmp; } -#define make_DopHelper_funcname(name) concat(decode_op_, name) -#define make_DopHelper(name) void make_DopHelper_funcname(name) (vaddr_t *eip, Operand *op, bool load_val) - -/* Refer to Appendix A in i386 manual for the explanations of these abbreviations */ - -/* Ib, Iv */ -static inline make_DopHelper(I) { - /* eip here is pointing to the immediate */ - op->type = OP_TYPE_IMM; - op->imm = instr_fetch(eip, op->width); - rtl_li(&op->val, op->imm); - -#ifdef DEBUG - snprintf(op->str, OP_STR_SIZE, "$0x%x", op->imm); -#endif -} - -/* I386 manual does not contain this abbreviation, but it is different from - * the one above from the view of implementation. So we use another helper - * function to decode it. - */ -/* sign immediate */ -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 `eip'. Interpret the result as a signed immediate, - * and assign it to op->simm. - * - op->simm = ??? +#define make_DopHelper_funcname(name) DopHelperImpl::name +#define make_DopHelper(name) void name (vaddr_t *eip, Operand *op, bool load_val) + +namespace DopHelperImpl { + /* Refer to Appendix A in i386 manual for the explanations of these abbreviations */ + + /* Ib, Iv */ + static inline make_DopHelper(I) { + /* eip here is pointing to the immediate */ + op->type = OP_TYPE_IMM; + op->imm = instr_fetch(eip, op->width); + rtl_li(&op->val, op->imm); + + #ifdef DEBUG + snprintf(op->str, OP_STR_SIZE, "$0x%x", op->imm); + #endif + } + + /* I386 manual does not contain this abbreviation, but it is different from + * the one above from the view of implementation. So we use another helper + * function to decode it. */ - op->simm = instr_fetch(eip, op->width); - - rtl_li(&op->val, op->simm); - -#ifdef DEBUG - snprintf(op->str, OP_STR_SIZE, "$0x%x", op->simm); -#endif -} - -/* I386 manual does not contain this abbreviation. - * It is convenient to merge them into a single helper function. - */ -/* AL/eAX */ -static inline make_DopHelper(a) { - op->type = OP_TYPE_REG; - op->reg = R_EAX; - if (load_val) { - rtl_lr(&op->val, R_EAX, op->width); + /* sign immediate */ + 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 `eip'. Interpret the result as a signed immediate, + * and assign it to op->simm. + * + op->simm = ??? + */ + op->simm = instr_fetch(eip, op->width); + + rtl_li(&op->val, op->simm); + + #ifdef DEBUG + snprintf(op->str, OP_STR_SIZE, "$0x%x", op->simm); + #endif } - -#ifdef DEBUG - snprintf(op->str, OP_STR_SIZE, "%%%s", reg_name(R_EAX, op->width)); -#endif -} - -/* This helper function is use to decode register encoded in the opcode. */ -/* XX: AL, AH, BL, BH, CL, CH, DL, DH - * eXX: eAX, eCX, eDX, eBX, eSP, eBP, eSI, eDI - */ -static inline make_DopHelper(r) { - op->type = OP_TYPE_REG; - op->reg = decoding.opcode & 0x7; - if (load_val) { - rtl_lr(&op->val, op->reg, op->width); + + /* I386 manual does not contain this abbreviation. + * It is convenient to merge them into a single helper function. + */ + /* AL/eAX */ + static inline make_DopHelper(a) { + op->type = OP_TYPE_REG; + op->reg = R_EAX; + if (load_val) { + rtl_lr(&op->val, R_EAX, op->width); + } + + #ifdef DEBUG + snprintf(op->str, OP_STR_SIZE, "%%%s", reg_name(R_EAX, op->width)); + #endif } - -#ifdef DEBUG - snprintf(op->str, OP_STR_SIZE, "%%%s", reg_name(op->reg, op->width)); -#endif -} - -/* I386 manual does not contain this abbreviation. - * We decode everything of modR/M byte by one time. - */ -/* Eb, Ew, Ev - * Gb, Gv - * Cd, - * M - * Rd - * Sw - */ -static inline void make_DopHelper_funcname(rm)(vaddr_t *eip, Operand *rm, bool load_rm_val, Operand *reg, bool load_reg_val) { - read_ModR_M(eip, rm, load_rm_val, reg, load_reg_val); -} - -/* Ob, Ov */ -static inline make_DopHelper(O) { - op->type = OP_TYPE_MEM; - rtl_li(&op->addr, instr_fetch(eip, 4)); - if (load_val) { - rtl_lm(&op->val, &op->addr, op->width); + + /* This helper function is use to decode register encoded in the opcode. */ + /* XX: AL, AH, BL, BH, CL, CH, DL, DH + * eXX: eAX, eCX, eDX, eBX, eSP, eBP, eSI, eDI + */ + static inline make_DopHelper(r) { + op->type = OP_TYPE_REG; + op->reg = decoding.opcode & 0x7; + if (load_val) { + rtl_lr(&op->val, op->reg, op->width); + } + + #ifdef DEBUG + snprintf(op->str, OP_STR_SIZE, "%%%s", reg_name(op->reg, op->width)); + #endif } - -#ifdef DEBUG - snprintf(op->str, OP_STR_SIZE, "0x%x", op->addr); -#endif -} - -/* Eb <- Gb - * Ev <- Gv - */ -make_DHelper(G2E) { - make_DopHelper_funcname(rm)(eip, id_dest, true, id_src, true); -} - -make_DHelper(mov_G2E) { - make_DopHelper_funcname(rm)(eip, id_dest, false, id_src, true); -} - -/* Gb <- Eb - * Gv <- Ev - */ -make_DHelper(E2G) { - make_DopHelper_funcname(rm)(eip, id_src, true, id_dest, true); -} - -make_DHelper(mov_E2G) { - make_DopHelper_funcname(rm)(eip, id_src, true, id_dest, false); -} - -make_DHelper(lea_M2G) { - make_DopHelper_funcname(rm)(eip, id_src, false, id_dest, false); -} - -/* AL <- Ib - * eAX <- Iv - */ -make_DHelper(I2a) { - make_DopHelper_funcname(a)(eip, id_dest, true); - make_DopHelper_funcname(I)(eip, id_src, true); -} - -/* Gv <- EvIb - * Gv <- EvIv - * use for imul */ -make_DHelper(I_E2G) { - make_DopHelper_funcname(rm)(eip, id_src2, true, id_dest, false); - make_DopHelper_funcname(I)(eip, id_src, true); -} - -/* Eb <- Ib - * Ev <- Iv - */ -make_DHelper(I2E) { - make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); - make_DopHelper_funcname(I)(eip, id_src, true); -} - -make_DHelper(mov_I2E) { - make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false); - make_DopHelper_funcname(I)(eip, id_src, true); -} - -/* XX <- Ib - * eXX <- Iv - */ -make_DHelper(I2r) { - make_DopHelper_funcname(r)(eip, id_dest, true); - make_DopHelper_funcname(I)(eip, id_src, true); -} - -make_DHelper(mov_I2r) { - make_DopHelper_funcname(r)(eip, id_dest, false); - make_DopHelper_funcname(I)(eip, id_src, true); -} - -/* used by unary operations */ -make_DHelper(I) { - make_DopHelper_funcname(I)(eip, id_dest, true); -} - -make_DHelper(r) { - make_DopHelper_funcname(r)(eip, id_dest, true); -} - -make_DHelper(E) { - make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); -} - -make_DHelper(setcc_E) { - make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false); -} - -make_DHelper(gp7_E) { - make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false); -} - -/* used by test in group3 */ -make_DHelper(test_I) { - make_DopHelper_funcname(I)(eip, id_src, true); -} - -make_DHelper(SI2E) { - assert(id_dest->width == 2 || id_dest->width == 4); - make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); - id_src->width = 1; - make_DopHelper_funcname(SI)(eip, id_src, true); - if (id_dest->width == 2) { - id_src->val &= 0xffff; + + /* I386 manual does not contain this abbreviation. + * We decode everything of modR/M byte by one time. + */ + /* Eb, Ew, Ev + * Gb, Gv + * Cd, + * M + * Rd + * Sw + */ + static inline void rm(vaddr_t *eip, Operand *rm, bool load_rm_val, Operand *reg, bool load_reg_val) { + read_ModR_M(eip, rm, load_rm_val, reg, load_reg_val); } -} - -make_DHelper(SI_E2G) { - assert(id_dest->width == 2 || id_dest->width == 4); - make_DopHelper_funcname(rm)(eip, id_src2, true, id_dest, false); - id_src->width = 1; - make_DopHelper_funcname(SI)(eip, id_src, true); - if (id_dest->width == 2) { - id_src->val &= 0xffff; + + /* Ob, Ov */ + static inline make_DopHelper(O) { + op->type = OP_TYPE_MEM; + rtl_li(&op->addr, instr_fetch(eip, 4)); + if (load_val) { + rtl_lm(&op->val, &op->addr, op->width); + } + + #ifdef DEBUG + snprintf(op->str, OP_STR_SIZE, "0x%x", op->addr); + #endif } -} +} // end namespace DopHelperImpl -make_DHelper(gp2_1_E) { - make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); - id_src->type = OP_TYPE_IMM; - id_src->imm = 1; - rtl_li(&id_src->val, 1); -#ifdef DEBUG - sprintf(id_src->str, "$1"); -#endif -} - -make_DHelper(gp2_cl2E) { - make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); - id_src->type = OP_TYPE_REG; - id_src->reg = R_CL; - rtl_lr(&id_src->val, R_CL, 1); -#ifdef DEBUG - sprintf(id_src->str, "%%cl"); -#endif -} - -make_DHelper(gp2_Ib2E) { - make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); - id_src->width = 1; - make_DopHelper_funcname(I)(eip, id_src, true); -} - -/* Ev <- GvIb - * use for shld/shrd */ -make_DHelper(Ib_G2E) { - make_DopHelper_funcname(rm)(eip, id_dest, true, id_src2, true); - id_src->width = 1; - make_DopHelper_funcname(I)(eip, id_src, true); -} - -/* Ev <- GvCL - * use for shld/shrd */ -make_DHelper(cl_G2E) { - make_DopHelper_funcname(rm)(eip, id_dest, true, id_src2, true); - id_src->type = OP_TYPE_REG; - id_src->reg = R_CL; - rtl_lr(&id_src->val, R_CL, 1); -#ifdef DEBUG - sprintf(id_src->str, "%%cl"); -#endif -} - -make_DHelper(O2a) { - make_DopHelper_funcname(O)(eip, id_src, true); - make_DopHelper_funcname(a)(eip, id_dest, false); -} - -make_DHelper(a2O) { - make_DopHelper_funcname(a)(eip, id_src, true); - make_DopHelper_funcname(O)(eip, id_dest, false); -} - -make_DHelper(J) { - make_DopHelper_funcname(SI)(eip, id_dest, false); - // the target address can be computed in the decode stage - decoding.jmp_eip = id_dest->simm + *eip; -} - -make_DHelper(push_SI) { - make_DopHelper_funcname(SI)(eip, id_dest, true); -} - -make_DHelper(in_I2a) { - id_src->width = 1; - make_DopHelper_funcname(I)(eip, id_src, true); - make_DopHelper_funcname(a)(eip, id_dest, false); -} - -make_DHelper(in_dx2a) { - id_src->type = OP_TYPE_REG; - id_src->reg = R_DX; - rtl_lr(&id_src->val, R_DX, 2); -#ifdef DEBUG - sprintf(id_src->str, "(%%dx)"); -#endif - - make_DopHelper_funcname(a)(eip, id_dest, false); -} - -make_DHelper(out_a2I) { - make_DopHelper_funcname(a)(eip, id_src, true); - id_dest->width = 1; - make_DopHelper_funcname(I)(eip, id_dest, true); -} +namespace DHelperImpl { -make_DHelper(out_a2dx) { - make_DopHelper_funcname(a)(eip, id_src, true); - - id_dest->type = OP_TYPE_REG; - id_dest->reg = R_DX; - rtl_lr(&id_dest->val, R_DX, 2); -#ifdef DEBUG - sprintf(id_dest->str, "(%%dx)"); -#endif -} + /* Eb <- Gb + * Ev <- Gv + */ + make_DHelper(G2E) { + make_DopHelper_funcname(rm)(eip, id_dest, true, id_src, true); + } + + make_DHelper(mov_G2E) { + make_DopHelper_funcname(rm)(eip, id_dest, false, id_src, true); + } + + /* Gb <- Eb + * Gv <- Ev + */ + make_DHelper(E2G) { + make_DopHelper_funcname(rm)(eip, id_src, true, id_dest, true); + } + + make_DHelper(mov_E2G) { + make_DopHelper_funcname(rm)(eip, id_src, true, id_dest, false); + } + + make_DHelper(lea_M2G) { + make_DopHelper_funcname(rm)(eip, id_src, false, id_dest, false); + } + + /* AL <- Ib + * eAX <- Iv + */ + make_DHelper(I2a) { + make_DopHelper_funcname(a)(eip, id_dest, true); + make_DopHelper_funcname(I)(eip, id_src, true); + } + + /* Gv <- EvIb + * Gv <- EvIv + * use for imul */ + make_DHelper(I_E2G) { + make_DopHelper_funcname(rm)(eip, id_src2, true, id_dest, false); + make_DopHelper_funcname(I)(eip, id_src, true); + } + + /* Eb <- Ib + * Ev <- Iv + */ + make_DHelper(I2E) { + make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); + make_DopHelper_funcname(I)(eip, id_src, true); + } + + make_DHelper(mov_I2E) { + make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false); + make_DopHelper_funcname(I)(eip, id_src, true); + } + + /* XX <- Ib + * eXX <- Iv + */ + make_DHelper(I2r) { + make_DopHelper_funcname(r)(eip, id_dest, true); + make_DopHelper_funcname(I)(eip, id_src, true); + } + + make_DHelper(mov_I2r) { + make_DopHelper_funcname(r)(eip, id_dest, false); + make_DopHelper_funcname(I)(eip, id_src, true); + } + + /* used by unary operations */ + make_DHelper(I) { + make_DopHelper_funcname(I)(eip, id_dest, true); + } + + make_DHelper(r) { + make_DopHelper_funcname(r)(eip, id_dest, true); + } + + make_DHelper(E) { + make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); + } + + make_DHelper(setcc_E) { + make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false); + } + + make_DHelper(gp7_E) { + make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false); + } + + /* used by test in group3 */ + make_DHelper(test_I) { + make_DopHelper_funcname(I)(eip, id_src, true); + } + + make_DHelper(SI2E) { + assert(id_dest->width == 2 || id_dest->width == 4); + make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); + id_src->width = 1; + make_DopHelper_funcname(SI)(eip, id_src, true); + if (id_dest->width == 2) { + id_src->val &= 0xffff; + } + } + + make_DHelper(SI_E2G) { + assert(id_dest->width == 2 || id_dest->width == 4); + make_DopHelper_funcname(rm)(eip, id_src2, true, id_dest, false); + id_src->width = 1; + make_DopHelper_funcname(SI)(eip, id_src, true); + if (id_dest->width == 2) { + id_src->val &= 0xffff; + } + } + + make_DHelper(gp2_1_E) { + make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); + id_src->type = OP_TYPE_IMM; + id_src->imm = 1; + rtl_li(&id_src->val, 1); + #ifdef DEBUG + sprintf(id_src->str, "$1"); + #endif + } + + make_DHelper(gp2_cl2E) { + make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); + id_src->type = OP_TYPE_REG; + id_src->reg = R_CL; + rtl_lr(&id_src->val, R_CL, 1); + #ifdef DEBUG + sprintf(id_src->str, "%%cl"); + #endif + } + + make_DHelper(gp2_Ib2E) { + make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false); + id_src->width = 1; + make_DopHelper_funcname(I)(eip, id_src, true); + } + + /* Ev <- GvIb + * use for shld/shrd */ + make_DHelper(Ib_G2E) { + make_DopHelper_funcname(rm)(eip, id_dest, true, id_src2, true); + id_src->width = 1; + make_DopHelper_funcname(I)(eip, id_src, true); + } + + /* Ev <- GvCL + * use for shld/shrd */ + make_DHelper(cl_G2E) { + make_DopHelper_funcname(rm)(eip, id_dest, true, id_src2, true); + id_src->type = OP_TYPE_REG; + id_src->reg = R_CL; + rtl_lr(&id_src->val, R_CL, 1); + #ifdef DEBUG + sprintf(id_src->str, "%%cl"); + #endif + } + + make_DHelper(O2a) { + make_DopHelper_funcname(O)(eip, id_src, true); + make_DopHelper_funcname(a)(eip, id_dest, false); + } + + make_DHelper(a2O) { + make_DopHelper_funcname(a)(eip, id_src, true); + make_DopHelper_funcname(O)(eip, id_dest, false); + } + + make_DHelper(J) { + make_DopHelper_funcname(SI)(eip, id_dest, false); + rlib::println("debug: J decoder: id_dest=", *id_dest); + rtl_sext(&id_dest->imm, &id_dest->imm, id_dest->width); + // the target address can be computed in the decode stage + decoding.jmp_eip = id_dest->simm + *eip; + } + + make_DHelper(push_SI) { + make_DopHelper_funcname(SI)(eip, id_dest, true); + } + + make_DHelper(in_I2a) { + id_src->width = 1; + make_DopHelper_funcname(I)(eip, id_src, true); + make_DopHelper_funcname(a)(eip, id_dest, false); + } + + make_DHelper(in_dx2a) { + id_src->type = OP_TYPE_REG; + id_src->reg = R_DX; + rtl_lr(&id_src->val, R_DX, 2); + #ifdef DEBUG + sprintf(id_src->str, "(%%dx)"); + #endif + + make_DopHelper_funcname(a)(eip, id_dest, false); + } + + make_DHelper(out_a2I) { + make_DopHelper_funcname(a)(eip, id_src, true); + id_dest->width = 1; + make_DopHelper_funcname(I)(eip, id_dest, true); + } + + make_DHelper(out_a2dx) { + make_DopHelper_funcname(a)(eip, id_src, true); + + id_dest->type = OP_TYPE_REG; + id_dest->reg = R_DX; + rtl_lr(&id_dest->val, R_DX, 2); + #ifdef DEBUG + sprintf(id_dest->str, "(%%dx)"); + #endif + } +} // end namespace DHelperIMpl void operand_write(Operand *op, rtlreg_t* src) { if (op->type == OP_TYPE_REG) { rtl_sr(op->reg, src, op->width); } diff --git a/nemu/src/cpu/exec/all-instr.h b/nemu/src/cpu/exec/all-instr.h index 617030fc01fddd9a22fb28cd20ab6b67197acc36..9f47be6a63d25b5da666879a2cbfca54c997495d 100644 --- a/nemu/src/cpu/exec/all-instr.h +++ b/nemu/src/cpu/exec/all-instr.h @@ -1,5 +1,7 @@ #include "cpu/exec.h" +namespace EHelperImpl { + make_EHelper(mov); make_EHelper(push); make_EHelper(pop); @@ -27,12 +29,12 @@ make_EHelper(imul3); make_EHelper(div); make_EHelper(idiv); -make_EHelper(xor); +make_EHelper(xor_); make_EHelper(test); -make_EHelper(and); -make_EHelper(or); +make_EHelper(and_); +make_EHelper(or_); make_EHelper(setcc); -make_EHelper(not); +make_EHelper(not_); make_EHelper(sar); make_EHelper(shr); make_EHelper(shl); @@ -47,6 +49,7 @@ make_EHelper(jcc); make_EHelper(in); make_EHelper(out); +make_EHelper(int_); make_EHelper(nop); @@ -54,3 +57,5 @@ make_EHelper(operand_size); make_EHelper(inv); make_EHelper(nemu_trap); + +} diff --git a/nemu/src/cpu/exec/arith.cc b/nemu/src/cpu/exec/arith.cc index 3ecaa30b891bdf4cdccbdc8662ab9d8af01792c6..8f6c9cbcc0bbb2670167ab3a90af5e589fd2e9a0 100644 --- a/nemu/src/cpu/exec/arith.cc +++ b/nemu/src/cpu/exec/arith.cc @@ -2,262 +2,265 @@ #include <util/util.h> -make_EHelper(add) { - rtl_sext(&t1, &id_dest->val, id_dest->width); - rtl_sext(&t2, &id_src->val, id_src->width); - - rtl_add(&t0, &t1, &t2); - t3 = (t0 < t1); - rtl_set_CF(&t3); - t3 = ((((int32_t)(t1) >= 0) ^ (((int32_t)(t2) >= 0 ))) && (((int32_t)(t0) < 0) ^ (((int32_t)(t2) >= 0 )) )); - rtl_set_OF(&t3); - rtl_update_ZFSF(&t0, 4); - operand_write(id_dest, &t0); - - print_asm_template2(add); -} - -make_EHelper(sub) { - rtl_sext(&t1, &id_dest->val, id_dest->width); - rtl_sext(&t2, &id_src->val, id_src->width); - - rtl_sub(&t0, &t1, &t2); - t3 = (t0 > t1); - rtl_set_CF(&t3); - t3 = ((((int32_t)(t1) < 0) == (((int32_t)(t2) >> 31) == 0)) && (((int32_t)(t0) < 0) != ((int32_t)(t1) < 0))); - rtl_set_OF(&t3); - rtl_update_ZFSF(&t0, 4); - operand_write(id_dest, &t0); - - print_asm_template2(sub); -} - - - -make_EHelper(cmp) { - rtl_sext(&t1, &id_dest->val, id_dest->width); - rtl_sext(&t2, &id_src->val, id_src->width); - - rtl_sub(&t0, &t1, &t2); - t3 = (t0 > t1); - rtl_set_CF(&t3); - t3 = ((((int32_t)(t1) < 0) == (((int32_t)(t2) >> 31) == 0)) && (((int32_t)(t0) < 0) != ((int32_t)(t1) < 0))); - rtl_set_OF(&t3); - rtl_update_ZFSF(&t0, 4); - - print_asm_template2(cmp); -} - -make_EHelper(inc) { - rtl_addi(&t2, &id_dest->val, 1); - operand_write(id_dest, &t2); - rtl_update_ZFSF(&t2, id_dest->width); - rtl_xor(&t0, &id_dest->val, &id_src->val); - rtl_not(&t0, &t0); - rtl_xor(&t1, &id_dest->val, &t2); - rtl_and(&t0, &t0, &t1); - rtl_msb(&t0, &t0, id_dest->width); - rtl_set_OF(&t0); - - print_asm_template1(inc); -} - -make_EHelper(dec) { - rtl_subi(&t2, &id_dest->val, 1); - operand_write(id_dest, &t2); - - rtl_update_ZFSF(&t2, id_dest->width); - - rtl_xor(&t0, &id_dest->val, &id_src->val); - rtl_xor(&t1, &id_dest->val, &t2); - rtl_and(&t0, &t0, &t1); - rtl_msb(&t0, &t0, id_dest->width); - rtl_set_OF(&t0); - - print_asm_template1(dec); -} - -make_EHelper(neg) { - TODO(); - - print_asm_template1(neg); -} - -make_EHelper(adc) { - rtl_add(&t2, &id_dest->val, &id_src->val); - rtl_setrelop(RELOP_LTU, &t3, &t2, &id_dest->val); - rtl_get_CF(&t1); - rtl_add(&t2, &t2, &t1); - operand_write(id_dest, &t2); - - rtl_update_ZFSF(&t2, id_dest->width); - - rtl_setrelop(RELOP_LTU, &t0, &t2, &id_dest->val); - rtl_or(&t0, &t3, &t0); - rtl_set_CF(&t0); - - rtl_xor(&t0, &id_dest->val, &id_src->val); - rtl_not(&t0, &t0); - rtl_xor(&t1, &id_dest->val, &t2); - rtl_and(&t0, &t0, &t1); - rtl_msb(&t0, &t0, id_dest->width); - rtl_set_OF(&t0); - - print_asm_template2(adc); -} - -make_EHelper(sbb) { - rtl_sub(&t2, &id_dest->val, &id_src->val); - rtl_setrelop(RELOP_LTU, &t3, &id_dest->val, &t2); - rtl_get_CF(&t1); - rtl_sub(&t2, &t2, &t1); - operand_write(id_dest, &t2); - - rtl_update_ZFSF(&t2, id_dest->width); - - rtl_setrelop(RELOP_LTU, &t0, &id_dest->val, &t2); - rtl_or(&t0, &t3, &t0); - rtl_set_CF(&t0); - - rtl_xor(&t0, &id_dest->val, &id_src->val); - rtl_xor(&t1, &id_dest->val, &t2); - rtl_and(&t0, &t0, &t1); - rtl_msb(&t0, &t0, id_dest->width); - rtl_set_OF(&t0); - - print_asm_template2(sbb); -} - -make_EHelper(mul) { - rtl_lr(&t0, R_EAX, id_dest->width); - rtl_mul_lo(&t1, &id_dest->val, &t0); - - switch (id_dest->width) { - case 1: - rtl_sr(R_AX, &t1, 2); - break; - case 2: - rtl_sr(R_AX, &t1, 2); - rtl_shri(&t1, &t1, 16); - rtl_sr(R_DX, &t1, 2); - break; - case 4: - rtl_mul_hi(&t2, &id_dest->val, &t0); - rtl_sr(R_EDX, &t2, 4); - rtl_sr(R_EAX, &t1, 4); - break; - default: assert(0); +namespace EHelperImpl { + make_EHelper(add) { + rtl_sext(&t1, &id_dest->val, id_dest->width); + rtl_sext(&t2, &id_src->val, id_src->width); + + rtl_add(&t0, &t1, &t2); + t3 = (t0 < t1); + rtl_set_CF(&t3); + t3 = ((((int32_t)(t1) >= 0) ^ (((int32_t)(t2) >= 0 ))) && (((int32_t)(t0) < 0) ^ (((int32_t)(t2) >= 0 )) )); + rtl_set_OF(&t3); + rtl_update_ZFSF(&t0, 4); + operand_write(id_dest, &t0); + + print_asm_template2(add); } - - print_asm_template1(mul); -} - -// imul with one operand -make_EHelper(imul1) { - rtl_lr(&t0, R_EAX, id_dest->width); - rtl_imul_lo(&t1, &id_dest->val, &t0); - - switch (id_dest->width) { - case 1: - rtl_sr(R_AX, &t1, 2); - break; - case 2: - rtl_sr(R_AX, &t1, 2); - rtl_shri(&t1, &t1, 16); - rtl_sr(R_DX, &t1, 2); - break; - case 4: - rtl_imul_hi(&t2, &id_dest->val, &t0); - rtl_sr(R_EDX, &t2, 4); - rtl_sr(R_EAX, &t1, 4); - break; - default: assert(0); + + make_EHelper(sub) { + rtl_sext(&t1, &id_dest->val, id_dest->width); + rtl_sext(&t2, &id_src->val, id_src->width); + + rtl_sub(&t0, &t1, &t2); + t3 = (t0 > t1); + rtl_set_CF(&t3); + t3 = ((((int32_t)(t1) < 0) == (((int32_t)(t2) >> 31) == 0)) && (((int32_t)(t0) < 0) != ((int32_t)(t1) < 0))); + rtl_set_OF(&t3); + rtl_update_ZFSF(&t0, 4); + operand_write(id_dest, &t0); + + print_asm_template2(sub); } - - print_asm_template1(imul); -} - -// imul with two operands -make_EHelper(imul2) { - rtl_sext(&t0, &id_src->val, id_src->width); - rtl_sext(&t1, &id_dest->val, id_dest->width); - - rtl_imul_lo(&t2, &t1, &t0); - operand_write(id_dest, &t2); - - print_asm_template2(imul); -} - -// imul with three operands -make_EHelper(imul3) { - rtl_sext(&t0, &id_src->val, id_src->width); - rtl_sext(&t1, &id_src2->val, id_src->width); - rtl_sext(&id_dest->val, &id_dest->val, id_dest->width); - - rtl_imul_lo(&t2, &t1, &t0); - operand_write(id_dest, &t2); - - print_asm_template3(imul); -} - -make_EHelper(div) { - switch (id_dest->width) { - case 1: - rtl_lr(&t0, R_AX, 2); - rtl_div_q(&t2, &t0, &id_dest->val); - rtl_div_r(&t3, &t0, &id_dest->val); - rtl_sr(R_AL, &t2, 1); - rtl_sr(R_AH, &t3, 1); - break; - case 2: - rtl_lr(&t0, R_AX, 2); - rtl_lr(&t1, R_DX, 2); - rtl_shli(&t1, &t1, 16); - rtl_or(&t0, &t0, &t1); - rtl_div_q(&t2, &t0, &id_dest->val); - rtl_div_r(&t3, &t0, &id_dest->val); - rtl_sr(R_AX, &t2, 2); - rtl_sr(R_DX, &t3, 2); - break; - case 4: - rtl_lr(&t0, R_EAX, 4); - rtl_lr(&t1, R_EDX, 4); - rtl_div64_q(&cpu.eax, &t1, &t0, &id_dest->val); - rtl_div64_r(&cpu.edx, &t1, &t0, &id_dest->val); - break; - default: assert(0); + + + + make_EHelper(cmp) { + rtl_sext(&t1, &id_dest->val, id_dest->width); + rtl_sext(&t2, &id_src->val, id_src->width); + + rtl_sub(&t0, &t1, &t2); + t3 = (t0 > t1); + rtl_set_CF(&t3); + t3 = ((((int32_t)(t1) < 0) == (((int32_t)(t2) >> 31) == 0)) && (((int32_t)(t0) < 0) != ((int32_t)(t1) < 0))); + rtl_set_OF(&t3); + rtl_update_ZFSF(&t0, 4); + + print_asm_template2(cmp); } - - print_asm_template1(div); -} - -make_EHelper(idiv) { - switch (id_dest->width) { - case 1: - rtl_lr(&t0, R_AX, 2); - rtl_idiv_q(&t2, &t0, &id_dest->val); - rtl_idiv_r(&t3, &t0, &id_dest->val); - rtl_sr(R_AL, &t2, 1); - rtl_sr(R_AH, &t3, 1); - break; - case 2: - rtl_lr(&t0, R_AX, 2); - rtl_lr(&t1, R_DX, 2); - rtl_shli(&t1, &t1, 16); - rtl_or(&t0, &t0, &t1); - rtl_idiv_q(&t2, &t0, &id_dest->val); - rtl_idiv_r(&t3, &t0, &id_dest->val); - rtl_sr(R_AX, &t2, 2); - rtl_sr(R_DX, &t3, 2); - break; - case 4: - rtl_lr(&t0, R_EAX, 4); - rtl_lr(&t1, R_EDX, 4); - rtl_idiv64_q(&cpu.eax, &t1, &t0, &id_dest->val); - rtl_idiv64_r(&cpu.edx, &t1, &t0, &id_dest->val); - break; - default: assert(0); + + make_EHelper(inc) { + rtl_addi(&t2, &id_dest->val, 1); + operand_write(id_dest, &t2); + rtl_update_ZFSF(&t2, id_dest->width); + rtl_xor(&t0, &id_dest->val, &id_src->val); + rtl_not(&t0, &t0); + rtl_xor(&t1, &id_dest->val, &t2); + rtl_and(&t0, &t0, &t1); + rtl_msb(&t0, &t0, id_dest->width); + rtl_set_OF(&t0); + + print_asm_template1(inc); + } + + make_EHelper(dec) { + rtl_subi(&t2, &id_dest->val, 1); + operand_write(id_dest, &t2); + + rtl_update_ZFSF(&t2, id_dest->width); + + rtl_xor(&t0, &id_dest->val, &id_src->val); + rtl_xor(&t1, &id_dest->val, &t2); + rtl_and(&t0, &t0, &t1); + rtl_msb(&t0, &t0, id_dest->width); + rtl_set_OF(&t0); + + print_asm_template1(dec); + } + + make_EHelper(neg) { + TODO(); + + print_asm_template1(neg); + } + + make_EHelper(adc) { + rtl_add(&t2, &id_dest->val, &id_src->val); + rtl_setrelop(RELOP_LTU, &t3, &t2, &id_dest->val); + rtl_get_CF(&t1); + rtl_add(&t2, &t2, &t1); + operand_write(id_dest, &t2); + + rtl_update_ZFSF(&t2, id_dest->width); + + rtl_setrelop(RELOP_LTU, &t0, &t2, &id_dest->val); + rtl_or(&t0, &t3, &t0); + rtl_set_CF(&t0); + + rtl_xor(&t0, &id_dest->val, &id_src->val); + rtl_not(&t0, &t0); + rtl_xor(&t1, &id_dest->val, &t2); + rtl_and(&t0, &t0, &t1); + rtl_msb(&t0, &t0, id_dest->width); + rtl_set_OF(&t0); + + print_asm_template2(adc); + } + + make_EHelper(sbb) { + rtl_sub(&t2, &id_dest->val, &id_src->val); + rtl_setrelop(RELOP_LTU, &t3, &id_dest->val, &t2); + rtl_get_CF(&t1); + rtl_sub(&t2, &t2, &t1); + operand_write(id_dest, &t2); + + rtl_update_ZFSF(&t2, id_dest->width); + + rtl_setrelop(RELOP_LTU, &t0, &id_dest->val, &t2); + rtl_or(&t0, &t3, &t0); + rtl_set_CF(&t0); + + rtl_xor(&t0, &id_dest->val, &id_src->val); + rtl_xor(&t1, &id_dest->val, &t2); + rtl_and(&t0, &t0, &t1); + rtl_msb(&t0, &t0, id_dest->width); + rtl_set_OF(&t0); + + print_asm_template2(sbb); + } + + make_EHelper(mul) { + rtl_lr(&t0, R_EAX, id_dest->width); + rtl_mul_lo(&t1, &id_dest->val, &t0); + + switch (id_dest->width) { + case 1: + rtl_sr(R_AX, &t1, 2); + break; + case 2: + rtl_sr(R_AX, &t1, 2); + rtl_shri(&t1, &t1, 16); + rtl_sr(R_DX, &t1, 2); + break; + case 4: + rtl_mul_hi(&t2, &id_dest->val, &t0); + rtl_sr(R_EDX, &t2, 4); + rtl_sr(R_EAX, &t1, 4); + break; + default: assert(0); + } + + print_asm_template1(mul); + } + + // imul with one operand + make_EHelper(imul1) { + rtl_lr(&t0, R_EAX, id_dest->width); + rtl_imul_lo(&t1, &id_dest->val, &t0); + + switch (id_dest->width) { + case 1: + rtl_sr(R_AX, &t1, 2); + break; + case 2: + rtl_sr(R_AX, &t1, 2); + rtl_shri(&t1, &t1, 16); + rtl_sr(R_DX, &t1, 2); + break; + case 4: + rtl_imul_hi(&t2, &id_dest->val, &t0); + rtl_sr(R_EDX, &t2, 4); + rtl_sr(R_EAX, &t1, 4); + break; + default: assert(0); + } + + print_asm_template1(imul); + } + + // imul with two operands + make_EHelper(imul2) { + rtl_sext(&t0, &id_src->val, id_src->width); + rtl_sext(&t1, &id_dest->val, id_dest->width); + + rtl_imul_lo(&t2, &t1, &t0); + operand_write(id_dest, &t2); + + print_asm_template2(imul); + } + + // imul with three operands + make_EHelper(imul3) { + rtl_sext(&t0, &id_src->val, id_src->width); + rtl_sext(&t1, &id_src2->val, id_src->width); + rtl_sext(&id_dest->val, &id_dest->val, id_dest->width); + + rtl_imul_lo(&t2, &t1, &t0); + operand_write(id_dest, &t2); + + print_asm_template3(imul); + } + + make_EHelper(div) { + switch (id_dest->width) { + case 1: + rtl_lr(&t0, R_AX, 2); + rtl_div_q(&t2, &t0, &id_dest->val); + rtl_div_r(&t3, &t0, &id_dest->val); + rtl_sr(R_AL, &t2, 1); + rtl_sr(R_AH, &t3, 1); + break; + case 2: + rtl_lr(&t0, R_AX, 2); + rtl_lr(&t1, R_DX, 2); + rtl_shli(&t1, &t1, 16); + rtl_or(&t0, &t0, &t1); + rtl_div_q(&t2, &t0, &id_dest->val); + rtl_div_r(&t3, &t0, &id_dest->val); + rtl_sr(R_AX, &t2, 2); + rtl_sr(R_DX, &t3, 2); + break; + case 4: + rtl_lr(&t0, R_EAX, 4); + rtl_lr(&t1, R_EDX, 4); + rtl_div64_q(&cpu.eax, &t1, &t0, &id_dest->val); + rtl_div64_r(&cpu.edx, &t1, &t0, &id_dest->val); + break; + default: assert(0); + } + + print_asm_template1(div); + } + + make_EHelper(idiv) { + switch (id_dest->width) { + case 1: + rtl_lr(&t0, R_AX, 2); + rtl_idiv_q(&t2, &t0, &id_dest->val); + rtl_idiv_r(&t3, &t0, &id_dest->val); + rtl_sr(R_AL, &t2, 1); + rtl_sr(R_AH, &t3, 1); + break; + case 2: + rtl_lr(&t0, R_AX, 2); + rtl_lr(&t1, R_DX, 2); + rtl_shli(&t1, &t1, 16); + rtl_or(&t0, &t0, &t1); + rtl_idiv_q(&t2, &t0, &id_dest->val); + rtl_idiv_r(&t3, &t0, &id_dest->val); + rtl_sr(R_AX, &t2, 2); + rtl_sr(R_DX, &t3, 2); + break; + case 4: + rtl_lr(&t0, R_EAX, 4); + rtl_lr(&t1, R_EDX, 4); + rtl_idiv64_q(&cpu.eax, &t1, &t0, &id_dest->val); + rtl_idiv64_r(&cpu.edx, &t1, &t0, &id_dest->val); + break; + default: assert(0); + } + + print_asm_template1(idiv); } - print_asm_template1(idiv); -} +} // end namespace diff --git a/nemu/src/cpu/exec/control.cc b/nemu/src/cpu/exec/control.cc index 51c9f23f52862e6d4f306ad377cf608da7b013f0..b4a157d9392fa3a1b4f17700ebf1e8c4abdf59a0 100644 --- a/nemu/src/cpu/exec/control.cc +++ b/nemu/src/cpu/exec/control.cc @@ -1,70 +1,72 @@ #include "cpu/exec.h" #include "cpu/cc.h" -make_EHelper(jmp) { - // the target address is calculated at the decode stage - rtl_j(decoding.jmp_eip); - - print_asm("jmp %x", decoding.jmp_eip); -} - -make_EHelper(jcc) { - // the target address is calculated at the decode stage - uint32_t cc = decoding.opcode & 0xf; - rtl_setcc(&t0, cc); - rtl_li(&t1, 0); - rtl_jrelop(RELOP_NE, &t0, &t1, decoding.jmp_eip); - - print_asm("j%s %x", get_cc_name(cc), decoding.jmp_eip); -} - -make_EHelper(jmp_rm) { - rtl_jr(&id_dest->val); - - print_asm("jmp *%s", id_dest->str); -} - -make_EHelper(call) { - // the target address is calculated at the decode stage - const bool near = true; - if(near) { - if(decoding.is_operand_size_16) { - throw std::runtime_error("call operand size 16 not implemented."); - } - else { - // operand size 32b - rtl_push<4>(&decoding.seq_eip); - rtl_j(decoding.jmp_eip); - } - decoding_set_jmp(true); +namespace EHelperImpl { + make_EHelper(jmp) { + // the target address is calculated at the decode stage + rtl_j(decoding.jmp_eip); + + print_asm("jmp %x", decoding.jmp_eip); } - // TODO: support far call - // TODO(); - - print_asm("call %x", decoding.jmp_eip); -} - -make_EHelper(ret) { - const bool near = true; - if(near) { - if(decoding.is_operand_size_16) { - throw std::runtime_error("call operand size 16 not implemented."); + + make_EHelper(jcc) { + // the target address is calculated at the decode stage + uint32_t cc = decoding.opcode & 0xf; + rtl_setcc(&t0, cc); + rtl_li(&t1, 0); + rtl_jrelop(RELOP_NE, &t0, &t1, decoding.jmp_eip); + + print_asm("j%s %x", get_cc_name(cc), decoding.jmp_eip); + } + + make_EHelper(jmp_rm) { + rtl_jr(&id_dest->val); + + print_asm("jmp *%s", id_dest->str); + } + + make_EHelper(call) { + // the target address is calculated at the decode stage + const bool near = true; + if(near) { + if(decoding.is_operand_size_16) { + throw std::runtime_error("call operand size 16 not implemented."); + } + else { + // operand size 32b + rtl_push<4>(&decoding.seq_eip); + rtl_j(decoding.jmp_eip); + } + decoding_set_jmp(true); } - else { - // operand size 32b - rtl_pop<4>(&cpu.eip); + // TODO: support far call + // TODO(); + + print_asm("call %x", decoding.jmp_eip); + } + + make_EHelper(ret) { + const bool near = true; + if(near) { + if(decoding.is_operand_size_16) { + throw std::runtime_error("call operand size 16 not implemented."); + } + else { + // operand size 32b + rtl_pop<4>(&cpu.eip); + } + decoding_set_jmp(true); } - decoding_set_jmp(true); + + // TODO: support far ret + // TODO(); + + print_asm("ret"); } - - // TODO: support far ret - // TODO(); - - print_asm("ret"); -} - -make_EHelper(call_rm) { - TODO(); - - print_asm("call *%s", id_dest->str); -} + + make_EHelper(call_rm) { + TODO(); + + print_asm("call *%s", id_dest->str); + } +} // end namespace diff --git a/nemu/src/cpu/exec/data-mov.cc b/nemu/src/cpu/exec/data-mov.cc index 6182edec56ccfff62d2833cd4febb6dba4872794..8e61839b7d80aaf0eec3ebb10bf4e299950259b8 100644 --- a/nemu/src/cpu/exec/data-mov.cc +++ b/nemu/src/cpu/exec/data-mov.cc @@ -1,101 +1,103 @@ #include "cpu/exec.h" -make_EHelper(mov) { - operand_write(id_dest, &id_src->val); - print_asm_template2(mov); -} - -make_EHelper(push) { - static_assert(sizeof(paddr_t) * 8 == 32); - if(decoding.is_operand_size_16) { - // 16b push - rtl_push<2>(&id_dest->val); +namespace EHelperImpl { + make_EHelper(mov) { + operand_write(id_dest, &id_src->val); + print_asm_template2(mov); } - else { - // 32b push - rtl_push<4>(&id_dest->val); + + make_EHelper(push) { + static_assert(sizeof(paddr_t) * 8 == 32); + if(decoding.is_operand_size_16) { + // 16b push + rtl_push<2>(&id_dest->val); + } + else { + // 32b push + rtl_push<4>(&id_dest->val); + } + + print_asm_template1(push); } - - print_asm_template1(push); -} - -make_EHelper(pop) { - static_assert(sizeof(paddr_t) * 8 == 32); - if(decoding.is_operand_size_16) { - // 16b - rtl_pop<2>(&id_dest->val); + + make_EHelper(pop) { + static_assert(sizeof(paddr_t) * 8 == 32); + if(decoding.is_operand_size_16) { + // 16b + rtl_pop<2>(&id_dest->val); + } + else { + // 32b + rtl_pop<4>(&id_dest->val); + } + operand_write(id_dest, &id_dest->val); + + print_asm_template1(pop); } - else { - // 32b - rtl_pop<4>(&id_dest->val); + + make_EHelper(pusha) { + TODO(); + + print_asm("pusha"); } - operand_write(id_dest, &id_dest->val); - - print_asm_template1(pop); -} - -make_EHelper(pusha) { - TODO(); - - print_asm("pusha"); -} - -make_EHelper(popa) { - TODO(); - - print_asm("popa"); -} - -make_EHelper(leave) { - rtl_mv(&cpu.esp, &cpu.ebp); - if(decoding.is_operand_size_16) { - rtlreg_t tmpReg; - rtl_pop<2>(&tmpReg); - reg_w(R_BP) = (uint16_t)tmpReg; + + make_EHelper(popa) { + TODO(); + + print_asm("popa"); } - else { - rtl_pop<4>(&cpu.ebp); + + make_EHelper(leave) { + rtl_mv(&cpu.esp, &cpu.ebp); + if(decoding.is_operand_size_16) { + rtlreg_t tmpReg; + rtl_pop<2>(&tmpReg); + reg_w(R_BP) = (uint16_t)tmpReg; + } + else { + rtl_pop<4>(&cpu.ebp); + } + + print_asm("leave"); } - - print_asm("leave"); -} - -make_EHelper(cltd) { - if (decoding.is_operand_size_16) { - TODO(); + + make_EHelper(cltd) { + if (decoding.is_operand_size_16) { + TODO(); + } + else { + TODO(); + } + + print_asm(decoding.is_operand_size_16 ? "cwtl" : "cltd"); } - else { - TODO(); + + make_EHelper(cwtl) { + if (decoding.is_operand_size_16) { + TODO(); + } + else { + TODO(); + } + + print_asm(decoding.is_operand_size_16 ? "cbtw" : "cwtl"); } - - print_asm(decoding.is_operand_size_16 ? "cwtl" : "cltd"); -} - -make_EHelper(cwtl) { - if (decoding.is_operand_size_16) { - TODO(); + + make_EHelper(movsx) { + id_dest->width = decoding.is_operand_size_16 ? 2 : 4; + rtl_sext(&t0, &id_src->val, id_src->width); + operand_write(id_dest, &t0); + print_asm_template2(movsx); } - else { - TODO(); + + make_EHelper(movzx) { + id_dest->width = decoding.is_operand_size_16 ? 2 : 4; + operand_write(id_dest, &id_src->val); + print_asm_template2(movzx); } - - print_asm(decoding.is_operand_size_16 ? "cbtw" : "cwtl"); -} - -make_EHelper(movsx) { - id_dest->width = decoding.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; - operand_write(id_dest, &id_src->val); - print_asm_template2(movzx); -} - -make_EHelper(lea) { - operand_write(id_dest, &id_src->addr); - print_asm_template2(lea); -} + + make_EHelper(lea) { + operand_write(id_dest, &id_src->addr); + print_asm_template2(lea); + } +} // end namespace diff --git a/nemu/src/cpu/exec/exec.cc b/nemu/src/cpu/exec/exec.cc index a211be92913343040e491a21307cd3f8e8020aef..67ab9e7c1f81db6de5243a2b58826a7988a19fcc 100644 --- a/nemu/src/cpu/exec/exec.cc +++ b/nemu/src/cpu/exec/exec.cc @@ -7,9 +7,9 @@ typedef struct { int width; // ByteWidth. If width is 0, using its default value: OperandSize (2Byte or 4Byte) } opcode_entry; -#define IDEXW(id, ex, w) {make_DHelper_funcname(id), make_EHelper_funcname(ex), w} +#define IDEXW(id, ex, w) {DHelperImpl::id, EHelperImpl::ex, w} #define IDEX(id, ex) IDEXW(id, ex, 0) -#define EXW(ex, w) {NULL, make_EHelper_funcname(ex), w} +#define EXW(ex, w) {NULL, EHelperImpl::ex, w} #define EX(ex) EXW(ex, 0) #define EMPTY EX(inv) @@ -28,21 +28,21 @@ static inline void idex(vaddr_t *eip, opcode_entry *e) { e->execute(eip); } -static make_EHelper(2byte_esc); +namespace EHelperImpl {static make_EHelper(_2byte_esc);} #define make_group(name, item0, item1, item2, item3, item4, item5, item6, item7) \ static opcode_entry concat(opcode_table_, name) [8] = { \ /* 0x00 */ item0, item1, item2, item3, \ /* 0x04 */ item4, item5, item6, item7 \ }; \ -static make_EHelper(name) { \ +namespace EHelperImpl { static make_EHelper(name) { \ idex(eip, &concat(opcode_table_, name)[decoding.ext_opcode]); \ -} +}} /* 0x80, 0x81, 0x83 */ make_group(gp1, - EX(add), EX(or), EX(adc), EX(sbb), - EX(and), EX(sub),EX(xor), EX(cmp)) + EX(add), EX(or_), EX(adc), EX(sbb), + EX(and_), EX(sub),EX(xor_), EX(cmp)) /* 0xc0, 0xc1, 0xd0, 0xd1, 0xd2, 0xd3 */ make_group(gp2, @@ -51,7 +51,7 @@ make_group(gp2, /* 0xf6, 0xf7 */ make_group(gp3, - IDEX(test_I,test), EMPTY, EX(not), EX(neg), + IDEX(test_I,test), EMPTY, EX(not_), EX(neg), EX(mul), EX(imul1), EX(div), EX(idiv)) /* 0xfe */ @@ -72,18 +72,18 @@ make_group(gp7, opcode_entry opcode_table [512] = { /* 0x00 */ IDEXW(G2E,add,1),IDEX(G2E,add), IDEXW(E2G,add,1), IDEX(E2G,add), /* 0x04 */ IDEXW(I2a,add,1), IDEX(I2a,add), EMPTY, EMPTY, - /* 0x08 */ IDEXW(G2E,or,1), IDEX(G2E,or), IDEXW(E2G,or,1), IDEX(E2G,or), - /* 0x0c */ IDEXW(I2a,or,1), IDEX(I2a,or), EMPTY, EX(2byte_esc), + /* 0x08 */ IDEXW(G2E,or_,1), IDEX(G2E,or_), IDEXW(E2G,or_,1), IDEX(E2G,or_), + /* 0x0c */ IDEXW(I2a,or_,1), IDEX(I2a,or_), EMPTY, EX(_2byte_esc), /* 0x10 */ IDEXW(G2E,adc,1), IDEX(G2E,adc), IDEXW(E2G,adc,1), IDEX(E2G,adc), /* 0x14 */ IDEXW(I2a,adc,1), IDEX(I2a,adc), EMPTY, EMPTY, /* 0x18 */ IDEXW(G2E,sbb,1), IDEX(G2E,sbb), IDEXW(E2G,sbb,1), IDEX(E2G,sbb), /* 0x1c */ IDEXW(I2a,sbb,1), IDEX(I2a,sbb), EMPTY, EMPTY, - /* 0x20 */ IDEXW(G2E,and,1), IDEX(G2E,and),IDEXW(E2G,and,1), IDEX(E2G,and), - /* 0x24 */ IDEXW(I2a,and,1), IDEX(I2a,and), EMPTY, EMPTY, + /* 0x20 */ IDEXW(G2E,and_,1), IDEX(G2E,and_),IDEXW(E2G,and_,1), IDEX(E2G,and_), + /* 0x24 */ IDEXW(I2a,and_,1), IDEX(I2a,and_), EMPTY, EMPTY, /* 0x28 */ IDEXW(G2E,sub,1), IDEX(G2E,sub), IDEXW(E2G,sub,1), IDEX(E2G,sub), /* 0x2c */ IDEXW(I2a,sub,1),IDEX(I2a,sub), EMPTY, EMPTY, - /* 0x30 */ IDEXW(G2E,xor,1), IDEX(G2E,xor), IDEXW(E2G,xor,1),IDEX(E2G,xor), - /* 0x34 */ IDEXW(I2a,xor,1), IDEX(I2a,xor), EMPTY, EMPTY, + /* 0x30 */ IDEXW(G2E,xor_,1), IDEX(G2E,xor_), IDEXW(E2G,xor_,1),IDEX(E2G,xor_), + /* 0x34 */ IDEXW(I2a,xor_,1), IDEX(I2a,xor_), EMPTY, EMPTY, /* 0x38 */ IDEXW(G2E,cmp,1), IDEX(G2E,cmp), IDEXW(E2G,cmp,1), IDEX(E2G,cmp), /* 0x3c */ IDEXW(I2a,cmp,1), IDEX(I2a,cmp), EMPTY, EMPTY, /* 0x40 */ IDEX(r,inc), IDEX(r,inc), IDEX(r,inc), IDEX(r,inc), @@ -203,186 +203,20 @@ opcode_entry opcode_table [512] = { /* 0xfc */ EMPTY, EMPTY, EMPTY, EMPTY }; -///* -///* 0x80, 0x81, 0x83 */ -//make_group(gp1, -// EMPTY, EMPTY, EMPTY, EMPTY, -// EMPTY, EMPTY, EMPTY, EMPTY) -// -// /* 0xc0, 0xc1, 0xd0, 0xd1, 0xd2, 0xd3 */ -//make_group(gp2, -// EMPTY, EMPTY, EMPTY, EMPTY, -// EMPTY, EMPTY, EMPTY, EMPTY) -// -// /* 0xf6, 0xf7 */ -//make_group(gp3, -// EMPTY, EMPTY, EMPTY, EMPTY, -// EMPTY, EMPTY, EMPTY, EMPTY) -// -// /* 0xfe */ -//make_group(gp4, -// EMPTY, EMPTY, EMPTY, EMPTY, -// EMPTY, EMPTY, EMPTY, EMPTY) -// -// /* 0xff */ -//make_group(gp5, -// EMPTY, EMPTY, EMPTY, EMPTY, -// EMPTY, EMPTY, EMPTY, EMPTY) -// -// /* 0x0f 0x01*/ -//make_group(gp7, -// EMPTY, EMPTY, EMPTY, EMPTY, -// EMPTY, EMPTY, EMPTY, EMPTY) -// -///* TODO: Add more instructions!!! */ -// -//opcode_entry opcode_table [512] = { -// /* 0x00 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x04 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x08 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x0c */ EMPTY, EMPTY, EMPTY, EX(2byte_esc), -// /* 0x10 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x14 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x18 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x1c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x20 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x24 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x28 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x2c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x30 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x34 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x38 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x3c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x40 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x44 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x48 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x4c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x50 */ IDEX(r, push), IDEX(r, push), IDEX(r, push), IDEX(r, push), -// /* 0x54 */ IDEX(r, push), IDEX(r, push), IDEX(r, push), IDEX(r, push), -// /* 0x58 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x5c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x60 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x64 */ EMPTY, EMPTY, EX(operand_size), EMPTY, -// /* 0x68 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x6c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x70 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x74 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x78 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x7c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x80 */ IDEXW(I2E, gp1, 1), IDEX(I2E, gp1), EMPTY, IDEX(SI2E, gp1), -// /* 0x84 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x88 */ IDEXW(mov_G2E, mov, 1), IDEX(mov_G2E, mov), IDEXW(mov_E2G, mov, 1), IDEX(mov_E2G, mov), -// /* 0x8c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x90 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x94 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x98 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x9c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xa0 */ IDEXW(O2a, mov, 1), IDEX(O2a, mov), IDEXW(a2O, mov, 1), IDEX(a2O, mov), -// /* 0xa4 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xa8 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xac */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xb0 */ IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1), -// /* 0xb4 */ IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1), -// /* 0xb8 */ IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), -// /* 0xbc */ IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), -// /* 0xc0 */ IDEXW(gp2_Ib2E, gp2, 1), IDEX(gp2_Ib2E, gp2), IDEX(I, ret), EX(ret), -// /* 0xc4 */ EMPTY, EMPTY, IDEXW(mov_I2E, mov, 1), IDEX(mov_I2E, mov), -// /* 0xc8 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xcc */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xd0 */ IDEXW(gp2_1_E, gp2, 1), IDEX(gp2_1_E, gp2), IDEXW(gp2_cl2E, gp2, 1), IDEX(gp2_cl2E, gp2), -// /* 0xd4 */ EMPTY, EMPTY, EX(nemu_trap), EMPTY, -// /* 0xd8 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xdc */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xe0 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xe4 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xe8 */ IDEX(J, call), EMPTY, EMPTY, EMPTY, -// /* 0xec */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xf0 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xf4 */ EMPTY, EMPTY, IDEXW(E, gp3, 1), IDEX(E, gp3), -// /* 0xf8 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xfc */ EMPTY, EMPTY, IDEXW(E, gp4, 1), IDEX(E, gp5), -// -// /*2 byte_opcode_table */ -// -// /* 0x00 */ EMPTY, IDEX(gp7_E, gp7), EMPTY, EMPTY, -// /* 0x04 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x08 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x0c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x10 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x14 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x18 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x1c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x20 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x24 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x28 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x2c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x30 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x34 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x38 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x3c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x40 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x44 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x48 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x4c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x50 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x54 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x58 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x5c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x60 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x64 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x68 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x6c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x70 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x74 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x78 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x7c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x80 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x84 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x88 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x8c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x90 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x94 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x98 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0x9c */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xa0 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xa4 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xa8 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xac */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xb0 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xb4 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xb8 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xbc */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xc0 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xc4 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xc8 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xcc */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xd0 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xd4 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xd8 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xdc */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xe0 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xe4 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xe8 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xec */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xf0 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xf4 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xf8 */ EMPTY, EMPTY, EMPTY, EMPTY, -// /* 0xfc */ EMPTY, EMPTY, EMPTY, EMPTY -//}; - - -static make_EHelper(2byte_esc) { - uint32_t opcode = instr_fetch(eip, 1) | 0x100; - decoding.opcode = opcode; - set_width(opcode_table[opcode].width); - idex(eip, &opcode_table[opcode]); -} +namespace EHelperImpl { + static make_EHelper(_2byte_esc) { + uint32_t opcode = instr_fetch(eip, 1) | 0x100; + decoding.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; - set_width(opcode_table[opcode].width); - idex(eip, &opcode_table[opcode]); + make_EHelper(real) { + uint32_t opcode = instr_fetch(eip, 1); + decoding.opcode = opcode; + set_width(opcode_table[opcode].width); + idex(eip, &opcode_table[opcode]); + } } static inline void update_eip(void) { @@ -399,7 +233,7 @@ void exec_wrapper(bool print_flag) { #endif decoding.seq_eip = ori_eip; - make_EHelper_funcname(real)(&decoding.seq_eip); + EHelperImpl::real(&decoding.seq_eip); #ifdef DEBUG int instr_len = decoding.seq_eip - ori_eip; diff --git a/nemu/src/cpu/exec/logic.cc b/nemu/src/cpu/exec/logic.cc index 70add1b5557e7343951aa5e8dfc2fcc0f8293332..764b95e172458912e9436ae50ebbaf5c178f867a 100644 --- a/nemu/src/cpu/exec/logic.cc +++ b/nemu/src/cpu/exec/logic.cc @@ -9,87 +9,92 @@ void sign_extend_if_required(const Operand &dest, Operand &src) { } } -make_EHelper(test) { - // `and` without write_back. - sign_extend_if_required(*id_dest, *id_src); - rtl_and(&t1, &id_dest->val, &id_src->val); - - rtl_update_ZFSF(&t1, id_dest->width); - cpu_eflags::get<cpu_eflags::CF>() = cpu_eflags::get<cpu_eflags::OF>() = false; - - print_asm_template2(test); -} - -make_EHelper(and) { - rlib::printfln("before test, id_dest={}, src={}", *id_dest, *id_src); - sign_extend_if_required(*id_dest, *id_src); - rlib::printfln("after test, id_dest={}, src={}", *id_dest, *id_src); - - rtl_and(&id_dest->val, &id_dest->val, &id_src->val); - operand_write(id_dest, &id_dest->val); - - rtl_update_ZFSF(&id_dest->val, id_dest->width); - cpu_eflags::get<cpu_eflags::CF>() = cpu_eflags::get<cpu_eflags::OF>() = false; - - print_asm_template2(and); -} - -make_EHelper(xor) { - sign_extend_if_required(*id_dest, *id_src); - - rtl_xor(&id_dest->val, &id_dest->val, &id_src->val); - operand_write(id_dest, &id_dest->val); - - rtl_update_ZFSF(&id_dest->val, id_dest->width); - cpu_eflags::get<cpu_eflags::CF>() = cpu_eflags::get<cpu_eflags::OF>() = false; - - print_asm_template2(xor); -} - -make_EHelper(or) { - TODO(); - - print_asm_template2(or); -} - -make_EHelper(sar) { - TODO(); - // unnecessary to update CF and OF in NEMU - - print_asm_template2(sar); -} - -make_EHelper(shl) { - TODO(); - // unnecessary to update CF and OF in NEMU - - print_asm_template2(shl); -} - -make_EHelper(shr) { - TODO(); - // unnecessary to update CF and OF in NEMU - - print_asm_template2(shr); -} - -make_EHelper(setcc) { - uint32_t cc = decoding.opcode & 0xf; - - rtl_setcc(&t2, cc); - operand_write(id_dest, &t2); - - print_asm("set%s %s", get_cc_name(cc), id_dest->str); -} - -make_EHelper(not) { - TODO(); - - print_asm_template1(not); -} - -make_EHelper(rol) { - TODO(); +namespace EHelperImpl { + using vaddr_t = uint32_t; + + make_EHelper(test) { + // `and` without write_back. + sign_extend_if_required(*id_dest, *id_src); + rtl_and(&t1, &id_dest->val, &id_src->val); + + rtl_update_ZFSF(&t1, id_dest->width); + cpu_eflags::get<cpu_eflags::CF>() = cpu_eflags::get<cpu_eflags::OF>() = false; + + print_asm_template2(test); + } + + make_EHelper(and_) { + rlib::printfln("before test, id_dest={}, src={}", *id_dest, *id_src); + sign_extend_if_required(*id_dest, *id_src); + rlib::printfln("after test, id_dest={}, src={}", *id_dest, *id_src); + + rtl_and(&id_dest->val, &id_dest->val, &id_src->val); + operand_write(id_dest, &id_dest->val); + + rtl_update_ZFSF(&id_dest->val, id_dest->width); + cpu_eflags::get<cpu_eflags::CF>() = cpu_eflags::get<cpu_eflags::OF>() = false; + + print_asm_template2(and); + } + + make_EHelper(xor_) { + sign_extend_if_required(*id_dest, *id_src); + + rtl_xor(&id_dest->val, &id_dest->val, &id_src->val); + operand_write(id_dest, &id_dest->val); + + rtl_update_ZFSF(&id_dest->val, id_dest->width); + cpu_eflags::get<cpu_eflags::CF>() = cpu_eflags::get<cpu_eflags::OF>() = false; + + print_asm_template2(xor); + } + + make_EHelper(or_) { + TODO(); + + print_asm_template2(or); + } + + make_EHelper(sar) { + TODO(); + // unnecessary to update CF and OF in NEMU + + print_asm_template2(sar); + } + + make_EHelper(shl) { + TODO(); + // unnecessary to update CF and OF in NEMU + + print_asm_template2(shl); + } + + make_EHelper(shr) { + TODO(); + // unnecessary to update CF and OF in NEMU + + print_asm_template2(shr); + } + + make_EHelper(setcc) { + uint32_t cc = decoding.opcode & 0xf; + + rtl_setcc(&t2, cc); + operand_write(id_dest, &t2); + + print_asm("set%s %s", get_cc_name(cc), id_dest->str); + } + + make_EHelper(not_) { + TODO(); + + print_asm_template1(not); + } + + make_EHelper(rol) { + TODO(); + + print_asm_template1(rol); + } - print_asm_template1(rol); -} +} // end namespace ehelperimpl diff --git a/nemu/src/cpu/exec/prefix.cc b/nemu/src/cpu/exec/prefix.cc index 4e8898b449a3f258beacf90b9a010408acf7f1c0..a1be99df9ad87c1b6a824bfc5384d1d90bfb54d6 100644 --- a/nemu/src/cpu/exec/prefix.cc +++ b/nemu/src/cpu/exec/prefix.cc @@ -1,9 +1,11 @@ #include "cpu/exec.h" -make_EHelper(real); +namespace EHelperImpl { + make_EHelper(real); -make_EHelper(operand_size) { - decoding.is_operand_size_16 = true; - make_EHelper_funcname(real)(eip); - decoding.is_operand_size_16 = false; -} + make_EHelper(operand_size) { + decoding.is_operand_size_16 = true; + EHelperImpl::real(eip); + decoding.is_operand_size_16 = false; + } +} \ No newline at end of file diff --git a/nemu/src/cpu/exec/special.cc b/nemu/src/cpu/exec/special.cc index 9580a48167cbbd22f4e3b12ae0f65367d1b618dd..63c2c3e893db14bfb9ac6125c1ed7f138efa0113 100644 --- a/nemu/src/cpu/exec/special.cc +++ b/nemu/src/cpu/exec/special.cc @@ -5,45 +5,49 @@ void interpret_rtl_exit(int state) { nemu_state = state; } -make_EHelper(nop) { - print_asm("nop"); -} - -make_EHelper(inv) { - /* invalid opcode */ - - uint32_t temp[2]; - vaddr_t ori_eip = cpu.eip; - *eip = ori_eip; - temp[0] = instr_fetch(eip, 4); - temp[1] = instr_fetch(eip, 4); - - uint8_t *p = (uint8_t *)temp; - printf("invalid opcode(eip = 0x%08x): %02x %02x %02x %02x %02x %02x %02x %02x ...\n\n", - ori_eip, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); - - extern char logo []; - printf("There are two cases which will trigger this unexpected exception:\n" - "1. The instruction at eip = 0x%08x is not implemented.\n" - "2. Something is implemented incorrectly.\n", ori_eip); - printf("Find this eip(0x%08x) in the disassembling result to distinguish which case it is.\n\n", ori_eip); - printf("\33[1;31mIf it is the first case, see\n%s\nfor more details.\n\nIf it is the second case, remember:\n" - "* The machine is always right!\n" - "* Every line of untested code is always wrong!\33[0m\n\n", logo); - - rtl_exit(NEMU_ABORT); - - print_asm("invalid opcode"); -} - -make_EHelper(nemu_trap) { -#if defined(DIFF_TEST) - void difftest_skip_ref(); - difftest_skip_ref(); -#endif - - rtl_exit(NEMU_END); - - print_asm("nemu trap"); - return; -} +extern char logo []; + +namespace EHelperImpl { + + make_EHelper(nop) { + print_asm("nop"); + } + + make_EHelper(inv) { + /* invalid opcode */ + + uint32_t temp[2]; + vaddr_t ori_eip = cpu.eip; + *eip = ori_eip; + temp[0] = instr_fetch(eip, 4); + temp[1] = instr_fetch(eip, 4); + + uint8_t *p = (uint8_t *)temp; + printf("invalid opcode(eip = 0x%08x): %02x %02x %02x %02x %02x %02x %02x %02x ...\n\n", + ori_eip, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + + printf("There are two cases which will trigger this unexpected exception:\n" + "1. The instruction at eip = 0x%08x is not implemented.\n" + "2. Something is implemented incorrectly.\n", ori_eip); + printf("Find this eip(0x%08x) in the disassembling result to distinguish which case it is.\n\n", ori_eip); + printf("\33[1;31mIf it is the first case, see\n%s\nfor more details.\n\nIf it is the second case, remember:\n" + "* The machine is always right!\n" + "* Every line of untested code is always wrong!\33[0m\n\n", logo); + + rtl_exit(NEMU_ABORT); + + print_asm("invalid opcode"); + } + + make_EHelper(nemu_trap) { + #if defined(DIFF_TEST) + void difftest_skip_ref(); + difftest_skip_ref(); + #endif + + rtl_exit(NEMU_END); + + print_asm("nemu trap"); + return; + } +} // end namespace diff --git a/nemu/src/cpu/exec/system.cc b/nemu/src/cpu/exec/system.cc index 5e13fef56e9dcb665de95f9535bede392f490e12..c1876cf6a13a644399072f7b7066dd6e5377cb13 100644 --- a/nemu/src/cpu/exec/system.cc +++ b/nemu/src/cpu/exec/system.cc @@ -3,60 +3,62 @@ void difftest_skip_ref(); void difftest_skip_dut(); -make_EHelper(lidt) { - TODO(); - - print_asm_template1(lidt); -} - -make_EHelper(mov_r2cr) { - TODO(); - - print_asm("movl %%%s,%%cr%d", reg_name(id_src->reg, 4), id_dest->reg); -} - -make_EHelper(mov_cr2r) { - TODO(); - - print_asm("movl %%cr%d,%%%s", id_src->reg, reg_name(id_dest->reg, 4)); - -#if defined(DIFF_TEST) - difftest_skip_ref(); -#endif -} - -make_EHelper(int) { - TODO(); - - print_asm("int %s", id_dest->str); - -#if defined(DIFF_TEST) && defined(DIFF_TEST_QEMU) - difftest_skip_dut(); -#endif -} - -make_EHelper(iret) { - TODO(); - - print_asm("iret"); -} - -make_EHelper(in) { - TODO(); - - print_asm_template2(in); - -#if defined(DIFF_TEST) - difftest_skip_ref(); -#endif -} - -make_EHelper(out) { - TODO(); - - print_asm_template2(out); - -#if defined(DIFF_TEST) - difftest_skip_ref(); -#endif -} +namespace EHelperImpl { + make_EHelper(lidt) { + TODO(); + + print_asm_template1(lidt); + } + + make_EHelper(mov_r2cr) { + TODO(); + + print_asm("movl %%%s,%%cr%d", reg_name(id_src->reg, 4), id_dest->reg); + } + + make_EHelper(mov_cr2r) { + TODO(); + + print_asm("movl %%cr%d,%%%s", id_src->reg, reg_name(id_dest->reg, 4)); + + #if defined(DIFF_TEST) + difftest_skip_ref(); + #endif + } + + make_EHelper(int_) { + TODO(); + + print_asm("int %s", id_dest->str); + + #if defined(DIFF_TEST) && defined(DIFF_TEST_QEMU) + difftest_skip_dut(); + #endif + } + + make_EHelper(iret) { + TODO(); + + print_asm("iret"); + } + + make_EHelper(in) { + TODO(); + + print_asm_template2(in); + + #if defined(DIFF_TEST) + difftest_skip_ref(); + #endif + } + + make_EHelper(out) { + TODO(); + + print_asm_template2(out); + + #if defined(DIFF_TEST) + difftest_skip_ref(); + #endif + } +} // end namespace diff --git a/nexus-am/Makefile.compile b/nexus-am/Makefile.compile index ea0da9d5fe5bfd958993e06ca25971ac86a50d98..2b3409963624dd1a8f46aee74bd39a850b699e70 100644 --- a/nexus-am/Makefile.compile +++ b/nexus-am/Makefile.compile @@ -19,8 +19,8 @@ ISA_DEF = __ISA_$(shell echo $(ISA) | tr a-z A-Z)__ INCLUDES = $(addprefix -I, $(INC_DIR)) -I$(AM_HOME)/am/ INCLUDES += -I$(AM_HOME)/am/arch/$(ARCH)/include -CFLAGS += -std=gnu11 -O2 -MMD -Wall -Werror -ggdb $(INCLUDES) -D$(ISA_DEF) -fno-builtin -CXXFLAGS += -std=c++11 -O2 -MMD -Wall -Werror -ggdb $(INCLUDES) -D$(ISA_DEF) -fno-builtin +CFLAGS += -std=gnu11 -O2 -MMD -Wall -ggdb $(INCLUDES) -D$(ISA_DEF) -fno-builtin +CXXFLAGS += -std=c++11 -O2 -MMD -Wall -ggdb $(INCLUDES) -D$(ISA_DEF) -fno-builtin ASFLAGS += -MMD $(INCLUDES) -D$(ISA_DEF) ifeq ($(ISA), native) diff --git a/nexus-am/tests/cputest/tests/r.c b/nexus-am/tests/cputest/tests/r.c new file mode 100644 index 0000000000000000000000000000000000000000..ca756700f451a916b07f3f740e93a11657241c98 --- /dev/null +++ b/nexus-am/tests/cputest/tests/r.c @@ -0,0 +1,24 @@ +#include "trap.h" + +int add(int a, int b) { + int c = a + b; + return c; +} + +int test_data[] = {0, 1, 2}; +int ans[] = {0, 1, 2,1,2,3,2,3,4}; + +#define NR_DATA (sizeof(test_data) / sizeof(test_data[0])) + +int main() { + int i, j, ans_idx = 0; + for(i = 0; i < NR_DATA; i ++) { + for(j = 0; j < NR_DATA; j ++) { + nemu_assert(1); + } + nemu_assert(j == NR_DATA); + } + nemu_assert(i == NR_DATA); + + return 0; +}