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;
+}