From f676051522eb5fe6a59b3c295f49cb8c79f898a6 Mon Sep 17 00:00:00 2001 From: Recolic Keghart <root@recolic.net> Date: Fri, 27 Dec 2019 00:18:05 -0800 Subject: [PATCH] > Manual commit: Finished DHelper/EHelper naming reconstruct. U201614531 recolic Linux RECOLICMPC 4.19.84-1-MANJARO #1 SMP PREEMPT Wed Nov 13 00:07:37 UTC 2019 x86_64 GNU/Linux 00:18:05 up 21 days, 1:46, 1 user, load average: 0.45, 0.49, 0.43 87ec359498ee755c2b1a53bde2e7ccb52afc8541 --- nemu/include/cpu/exec.h | 2 +- nemu/src/cpu/decode/decode.cc | 621 +++++++++++++++++----------------- nemu/src/cpu/exec/all-instr.h | 13 +- nemu/src/cpu/exec/arith.cc | 512 ++++++++++++++-------------- nemu/src/cpu/exec/control.cc | 128 +++---- nemu/src/cpu/exec/data-mov.cc | 180 +++++----- nemu/src/cpu/exec/exec.cc | 35 +- nemu/src/cpu/exec/logic.cc | 170 +++++----- nemu/src/cpu/exec/special.cc | 88 ++--- nemu/src/cpu/exec/system.cc | 116 +++---- 10 files changed, 940 insertions(+), 925 deletions(-) diff --git a/nemu/include/cpu/exec.h b/nemu/include/cpu/exec.h index 363039e..7766871 100644 --- a/nemu/include/cpu/exec.h +++ b/nemu/include/cpu/exec.h @@ -3,7 +3,7 @@ #include "nemu.h" -#define make_EHelper(name) void 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/src/cpu/decode/decode.cc b/nemu/src/cpu/decode/decode.cc index 73aab67..94c08ab 100644 --- a/nemu/src/cpu/decode/decode.cc +++ b/nemu/src/cpu/decode/decode.cc @@ -9,322 +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); - 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); -} +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 31cb2fa..9f47be6 100644 --- a/nemu/src/cpu/exec/all-instr.h +++ b/nemu/src/cpu/exec/all-instr.h @@ -2,8 +2,6 @@ namespace EHelperImpl { -make_EHelper(_2byte_esc); - make_EHelper(mov); make_EHelper(push); make_EHelper(pop); @@ -31,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); @@ -51,6 +49,7 @@ make_EHelper(jcc); make_EHelper(in); make_EHelper(out); +make_EHelper(int_); make_EHelper(nop); @@ -59,4 +58,4 @@ make_EHelper(operand_size); make_EHelper(inv); make_EHelper(nemu_trap); -} \ No newline at end of file +} diff --git a/nemu/src/cpu/exec/arith.cc b/nemu/src/cpu/exec/arith.cc index 409c19f..8f6c9cb 100644 --- a/nemu/src/cpu/exec/arith.cc +++ b/nemu/src/cpu/exec/arith.cc @@ -3,264 +3,264 @@ #include <util/util.h> 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); -} - -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); + 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 \ No newline at end of file +} // end namespace diff --git a/nemu/src/cpu/exec/control.cc b/nemu/src/cpu/exec/control.cc index 51c9f23..b4a157d 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 6182ede..8e61839 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 6698332..67ab9e7 100644 --- a/nemu/src/cpu/exec/exec.cc +++ b/nemu/src/cpu/exec/exec.cc @@ -28,20 +28,21 @@ static inline void idex(vaddr_t *eip, opcode_entry *e) { e->execute(eip); } +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 \ }; \ -namespace EHelperImpl {static 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, @@ -50,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 */ @@ -71,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), @@ -202,14 +203,14 @@ opcode_entry opcode_table [512] = { /* 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; diff --git a/nemu/src/cpu/exec/logic.cc b/nemu/src/cpu/exec/logic.cc index 6f0d429..764b95e 100644 --- a/nemu/src/cpu/exec/logic.cc +++ b/nemu/src/cpu/exec/logic.cc @@ -12,89 +12,89 @@ void sign_extend_if_required(const Operand &dest, Operand &src) { 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); -} + 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); + } -} // end namespace ehelperimpl \ No newline at end of file +} // end namespace ehelperimpl diff --git a/nemu/src/cpu/exec/special.cc b/nemu/src/cpu/exec/special.cc index 9580a48..63c2c3e 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 5e13fef..c1876cf 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 -- GitLab