From 91d2ca129e3d7cf8da841d9d0843b297f2c0b454 Mon Sep 17 00:00:00 2001
From: Recolic Keghart <root@recolic.net>
Date: Wed, 25 Dec 2019 20:22:59 +0800
Subject: [PATCH] >  Manual commit:  pa2.1 passed. debug ui bug fix(p command,
 lexer/parser error catching, better output); filled op_table; improved exec
 framework; implemented push/pop/call/sub/ret/xor... basic instructions;
 passing dummy.c; U201614531 recolic Linux RECOLICPC 5.4.2-arch1-1 #1 SMP
 PREEMPT Thu, 05 Dec 2019 12:29:40 +0000 x86_64 GNU/Linux  20:22:59 up 3 days,
  1:31,  1 user,  load average: 0.30, 0.44, 0.51
 f9cda9daeeb1166e65d35adca96e5bb9dfa19d11

---
 nemu/include/cpu/reg.h                    |  10 +-
 nemu/include/cpu/rtl.h                    |  18 +-
 nemu/include/util.h                       |  12 +
 nemu/src/cpu/exec/all-instr.h             |  55 +++-
 nemu/src/cpu/exec/arith.cc                |  27 +-
 nemu/src/cpu/exec/control.cc              |  12 +-
 nemu/src/cpu/exec/data-mov.cc             |   9 +-
 nemu/src/cpu/exec/exec.cc                 | 350 ++++++++++++++++------
 nemu/src/cpu/exec/logic.cc                |  12 +-
 nemu/src/monitor/debug/expr_impl/lexer.l  |   2 +
 nemu/src/monitor/debug/expr_impl/parser.y |   4 +-
 nemu/src/monitor/debug/ui.cc              |  17 +-
 12 files changed, 403 insertions(+), 125 deletions(-)
 create mode 100644 nemu/include/util.h

diff --git a/nemu/include/cpu/reg.h b/nemu/include/cpu/reg.h
index bcfa3f9..a0ee636 100644
--- a/nemu/include/cpu/reg.h
+++ b/nemu/include/cpu/reg.h
@@ -30,11 +30,19 @@ typedef union {
     rtlreg_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
     vaddr_t eip;
   };
-
 } CPU_state;
 
 extern CPU_state cpu;
 
+namespace cpu_eflags {
+  enum {CF = 0, PF, AF, ZF, SF, OF, SIZE_OF_EFLAGS};
+  template <size_t Which>
+  inline bool &get() {
+    static bool actual_buffer[SIZE_OF_EFLAGS];
+    return actual_buffer[Which];
+  }
+}
+
 static inline int check_reg_index(int index) {
   assert(index >= 0 && index < 8);
   return index;
diff --git a/nemu/include/cpu/rtl.h b/nemu/include/cpu/rtl.h
index 1352785..ef1f014 100644
--- a/nemu/include/cpu/rtl.h
+++ b/nemu/include/cpu/rtl.h
@@ -167,14 +167,14 @@ static inline void rtl_push(const rtlreg_t* src1) {
   // esp <- esp - 4
   // M[esp] <- src1
   rtl_subi(&cpu.esp, &cpu.esp, OperandBytes);
-  interpret_rtl_sm(&cpu.esp, src1, OperandBytes);
+  rtl_sm(&cpu.esp, src1, OperandBytes);
 }
 
 template <int OperandBytes>
 static inline void rtl_pop(rtlreg_t* dest) {
   // dest <- M[esp]
   // esp <- esp + 4
-  interpret_rtl_lm(dest, &cpu.esp, OperandBytes);
+  rtl_lm(dest, &cpu.esp, OperandBytes);
   rtl_addi(&cpu.esp, &cpu.esp, OperandBytes);
 }
 
@@ -186,15 +186,15 @@ static inline void rtl_setrelopi(uint32_t relop, rtlreg_t *dest,
 
 static inline void rtl_msb(rtlreg_t* dest, const rtlreg_t* src1, int width) {
   // dest <- src1[width * 8 - 1]
-  TODO();
+  *dest = ((*src1>>(width*8-1))==1);
 }
 
 #define make_rtl_setget_eflags(f) \
   static inline void concat(rtl_set_, f) (const rtlreg_t* src) { \
-    TODO(); \
+    cpu_eflags::get<cpu_eflags::f>() = (0 == *src); \
   } \
   static inline void concat(rtl_get_, f) (rtlreg_t* dest) { \
-    TODO(); \
+    *dest = cpu_eflags::get<cpu_eflags::f>() ? (uint32_t)1 : 0; \
   }
 
 make_rtl_setget_eflags(CF)
@@ -204,12 +204,16 @@ make_rtl_setget_eflags(SF)
 
 static inline void rtl_update_ZF(const rtlreg_t* result, int width) {
   // eflags.ZF <- is_zero(result[width * 8 - 1 .. 0])
-  TODO();
+  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]);
 }
 
 static inline void rtl_update_SF(const rtlreg_t* result, int width) {
   // eflags.SF <- is_sign(result[width * 8 - 1 .. 0])
-  TODO();
+  RLIB_MACRO_DEBUG_ASSERT((unsigned)width < 5);
+  static const uint32_t niddles [5] {0, 0x00000080, 0x00008000, 0x00800000, 0x80000000};
+  cpu_eflags::get<cpu_eflags::SF>() = (*result & niddles[width]);
 }
 
 static inline void rtl_update_ZFSF(const rtlreg_t* result, int width) {
diff --git a/nemu/include/util.h b/nemu/include/util.h
new file mode 100644
index 0000000..b46505e
--- /dev/null
+++ b/nemu/include/util.h
@@ -0,0 +1,12 @@
+#ifndef RLIB_HUST_UTIL_HPP_
+#define RLIB_HUST_UTIL_HPP_ 1
+
+#include <common.h>
+
+namespace rlib {
+  static inline int32_t signed_extend_low8b(const int32_t &val) {
+    return (int8_t)val;
+  }
+}
+
+#endif
diff --git a/nemu/src/cpu/exec/all-instr.h b/nemu/src/cpu/exec/all-instr.h
index d63f2ec..617030f 100644
--- a/nemu/src/cpu/exec/all-instr.h
+++ b/nemu/src/cpu/exec/all-instr.h
@@ -1,15 +1,56 @@
 #include "cpu/exec.h"
 
 make_EHelper(mov);
+make_EHelper(push);
+make_EHelper(pop);
+make_EHelper(pusha);
+make_EHelper(popa);
+make_EHelper(leave);
+make_EHelper(movsx);
+make_EHelper(movzx);
+make_EHelper(cltd);
+make_EHelper(cwtl);
+make_EHelper(lea);
+
+make_EHelper(add);
+make_EHelper(sub);
+make_EHelper(cmp);
+make_EHelper(inc);
+make_EHelper(dec);
+make_EHelper(neg);
+make_EHelper(adc);
+make_EHelper(sbb);
+make_EHelper(mul);
+make_EHelper(imul1);
+make_EHelper(imul2);
+make_EHelper(imul3);
+make_EHelper(div);
+make_EHelper(idiv);
+
+make_EHelper(xor);
+make_EHelper(test);
+make_EHelper(and);
+make_EHelper(or);
+make_EHelper(setcc);
+make_EHelper(not);
+make_EHelper(sar);
+make_EHelper(shr);
+make_EHelper(shl);
+make_EHelper(rol);
+
+make_EHelper(call);
+make_EHelper(call_rm);
+make_EHelper(ret);
+make_EHelper(jmp);
+make_EHelper(jmp_rm);
+make_EHelper(jcc);
+
+make_EHelper(in);
+make_EHelper(out);
+
+make_EHelper(nop);
 
 make_EHelper(operand_size);
 
 make_EHelper(inv);
 make_EHelper(nemu_trap);
-
-make_EHelper(ret);
-make_EHelper(call);
-make_EHelper(push);
-make_EHelper(pop);
-//make_EHelper();
-//make_EHelper();
diff --git a/nemu/src/cpu/exec/arith.cc b/nemu/src/cpu/exec/arith.cc
index 5aa37e1..f3a983c 100644
--- a/nemu/src/cpu/exec/arith.cc
+++ b/nemu/src/cpu/exec/arith.cc
@@ -1,5 +1,7 @@
 #include "cpu/exec.h"
 
+#include <util.h>
+
 make_EHelper(add) {
   TODO();
 
@@ -7,11 +9,34 @@ make_EHelper(add) {
 }
 
 make_EHelper(sub) {
-  TODO();
+  t1 = id_dest->val;
+
+  if(id_src->width == 1 && id_dest->width > 1) {
+    uint32_t extended = rlib::signed_extend_low8b(id_src->simm);
+    rtl_sub(&id_dest->val, &id_dest->val, &extended);
+  }
+  else {
+    rtl_sub(&id_dest->val, &id_dest->val, &id_src->imm);
+  }
+  //int sr = get_s(id_dest->val, id_dest->width);
+  operand_write(id_dest, &id_dest->val);
+
+  rtl_setrelop(RELOP_LTU, &t0, &t1, &id_dest->val);
+  rtl_set_CF(&t0);
+
+  rtl_xor(&t0, &t1, &id_src->val);
+  rtl_xor(&t2, &id_dest->val, &t1);
+  rtl_and(&t0, &t0, &t2);
+  rtl_msb(&t0, &t0, id_dest->width);
+  rtl_set_OF(&t0);
+
+  rtl_update_ZFSF(&id_dest->val, id_dest->width);
 
   print_asm_template2(sub);
 }
 
+
+
 make_EHelper(cmp) {
   TODO();
 
diff --git a/nemu/src/cpu/exec/control.cc b/nemu/src/cpu/exec/control.cc
index f58ec10..51c9f23 100644
--- a/nemu/src/cpu/exec/control.cc
+++ b/nemu/src/cpu/exec/control.cc
@@ -33,14 +33,12 @@ make_EHelper(call) {
     }
     else {
       // operand size 32b
-      rlib::println("debug: call touched.", std::hex);
-      rtl_push<4>(&cpu.eip);
-      rlib::println("debug: idsrc.val=", id_src->val, "eip from=", cpu.eip);
-      rtl_add(&cpu.eip, &cpu.eip, &id_src->val);
-      rlib::println("debug: idsrc.val=", id_src->val, "eip to=", cpu.eip);
+      rtl_push<4>(&decoding.seq_eip);
+      rtl_j(decoding.jmp_eip);
     }
+    decoding_set_jmp(true);
   }
- // TODO: support far call
+  // TODO: support far call
   // TODO();
 
   print_asm("call %x", decoding.jmp_eip);
@@ -56,7 +54,7 @@ make_EHelper(ret) {
       // operand size 32b
       rtl_pop<4>(&cpu.eip);
     }
-    rlib::println("debug: decoding.src=", decoding.src);
+    decoding_set_jmp(true);
   }
 
  // TODO: support far ret
diff --git a/nemu/src/cpu/exec/data-mov.cc b/nemu/src/cpu/exec/data-mov.cc
index 9bf9883..bff93e3 100644
--- a/nemu/src/cpu/exec/data-mov.cc
+++ b/nemu/src/cpu/exec/data-mov.cc
@@ -9,11 +9,11 @@ make_EHelper(push) {
   static_assert(sizeof(paddr_t) * 8 == 32);
   if(decoding.is_operand_size_16) {
     // 16b push
-    rtl_push<2>(&id_src->val);
+    rtl_push<2>(&id_dest->val);
   }
   else {
     // 32b push
-    rtl_push<4>(&id_src->val);
+    rtl_push<4>(&id_dest->val);
   }
 
   print_asm_template1(push);
@@ -23,12 +23,13 @@ make_EHelper(pop) {
   static_assert(sizeof(paddr_t) * 8 == 32);
   if(decoding.is_operand_size_16) {
     // 16b
-    rtl_pop<2>(&id_src->val);
+    rtl_pop<2>(&id_dest->val);
   }
   else {
     // 32b
-    rtl_pop<4>(&id_src->val);
+    rtl_pop<4>(&id_dest->val);
   }
+  operand_write(id_dest, &id_dest->val);
 
   print_asm_template1(pop);
 }
diff --git a/nemu/src/cpu/exec/exec.cc b/nemu/src/cpu/exec/exec.cc
index f05726b..a211be9 100644
--- a/nemu/src/cpu/exec/exec.cc
+++ b/nemu/src/cpu/exec/exec.cc
@@ -41,108 +41,106 @@ static make_EHelper(name) { \
 
 /* 0x80, 0x81, 0x83 */
 make_group(gp1,
-    EMPTY, EMPTY, EMPTY, EMPTY,
-    EMPTY, EMPTY, EMPTY, EMPTY)
+    EX(add), EX(or), EX(adc), EX(sbb),
+    EX(and), EX(sub),EX(xor), EX(cmp))
 
-  /* 0xc0, 0xc1, 0xd0, 0xd1, 0xd2, 0xd3 */
+/* 0xc0, 0xc1, 0xd0, 0xd1, 0xd2, 0xd3 */
 make_group(gp2,
-    EMPTY, EMPTY, EMPTY, EMPTY,
-    EMPTY, EMPTY, EMPTY, EMPTY)
+    EX(rol), EMPTY, EMPTY, EMPTY,
+    EX(shl), EX(shr), EMPTY, EX(sar))
 
-  /* 0xf6, 0xf7 */
+/* 0xf6, 0xf7 */
 make_group(gp3,
-    EMPTY, EMPTY, EMPTY, EMPTY,
-    EMPTY, EMPTY, EMPTY, EMPTY)
+    IDEX(test_I,test), EMPTY, EX(not), EX(neg),
+    EX(mul), EX(imul1), EX(div), EX(idiv))
 
-  /* 0xfe */
+/* 0xfe */
 make_group(gp4,
-    EMPTY, EMPTY, EMPTY, EMPTY,
+    EX(inc), EX(dec), EMPTY, EMPTY,
     EMPTY, EMPTY, EMPTY, EMPTY)
 
-  /* 0xff */
+/* 0xff */
 make_group(gp5,
-    EMPTY, EMPTY, EMPTY, EMPTY,
-    EMPTY, EMPTY, EMPTY, EMPTY)
+    EX(inc), EX(dec), EX(call_rm), EX(call_rm),
+    EX(jmp_rm), EX(jmp_rm), EX(push), EMPTY)
 
-  /* 0x0f 0x01*/
+/* 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 */	EMPTY, EMPTY, EMPTY, EMPTY,
-  /* 0x54 */	EMPTY, EMPTY, EMPTY, EMPTY,
-  /* 0x58 */	EMPTY, EMPTY, EMPTY, EMPTY,
-  /* 0x5c */	EMPTY, EMPTY, EMPTY, EMPTY,
-  /* 0x60 */	EMPTY, EMPTY, EMPTY, EMPTY,
+  /* 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),
+  /* 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,
+  /* 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,
+  /* 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),
+  /* 0x44 */	IDEX(r,inc), IDEX(r,inc), IDEX(r,inc), IDEX(r,inc), 
+  /* 0x48 */	IDEX(r,dec), IDEX(r,dec), IDEX(r,dec), IDEX(r,dec),
+  /* 0x4c */	IDEX(r,dec), IDEX(r,dec), IDEX(r,dec), IDEX(r,dec),
+  /* 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 */	IDEX(r,pop), IDEX(r,pop), IDEX(r,pop), IDEX(r,pop),
+  /* 0x5c */	IDEX(r,pop), IDEX(r,pop), IDEX(r,pop), IDEX(r,pop),
+  /* 0x60 */	EX(pusha), EX(popa), EMPTY, EMPTY,
   /* 0x64 */	EMPTY, EMPTY, EX(operand_size), EMPTY,
-  /* 0x68 */	EMPTY, EMPTY, EMPTY, EMPTY,
+  /* 0x68 */	IDEX(push_SI,push), IDEX(I_E2G,imul3), IDEXW(push_SI,push,1), IDEXW(I_E2G,imul3,1),
   /* 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,
+  /* 0x70 */	IDEXW(J,jcc,1), IDEXW(J,jcc,1), IDEXW(J,jcc,1), IDEXW(J,jcc,1),
+  /* 0x74 */	IDEXW(J,jcc,1), IDEXW(J,jcc,1), IDEXW(J,jcc,1), IDEXW(J,jcc,1),
+  /* 0x78 */	IDEXW(J,jcc,1), IDEXW(J,jcc,1), IDEXW(J,jcc,1), IDEXW(J,jcc,1),
+  /* 0x7c */	IDEXW(J,jcc,1), IDEXW(J,jcc,1), IDEXW(J,jcc,1), IDEXW(J,jcc,1),
   /* 0x80 */	IDEXW(I2E, gp1, 1), IDEX(I2E, gp1), EMPTY, IDEX(SI2E, gp1),
-  /* 0x84 */	EMPTY, EMPTY, EMPTY, EMPTY,
+  /* 0x84 */	IDEXW(G2E,test,1), IDEX(G2E,test), 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),
+	/* 0x8c */	EMPTY, IDEX(lea_M2G,lea), EMPTY, IDEX(E,pop),
+	/* 0x90 */	EX(nop), EMPTY, EMPTY, EMPTY,
+	/* 0x94 */	EMPTY, EMPTY, EMPTY, EMPTY,
+	/* 0x98 */	EX(cwtl), EX(cltd), IDEX(I,call), 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 */	IDEXW(I2a,test,1), IDEX(I2a,test), 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), IDEXW(I,ret,2), EX(ret),
+	/* 0xc4 */	EMPTY, EMPTY, IDEXW(mov_I2E, mov, 1), IDEX(mov_I2E, mov),
+	/* 0xc8 */	EMPTY, EX(leave), IDEXW(I,ret,2), EX(ret),
+	/* 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, IDEXW(J,jcc,1),
+	/* 0xe4 */	IDEXW(in_I2a,in,1), IDEX(in_I2a,in), IDEXW(out_a2I,out,1), IDEX(out_a2I,out),
+	/* 0xe8 */	IDEX(J,call), IDEX(J,jmp), IDEX(I,jmp_rm), IDEXW(J,jmp,1),
+	/* 0xec */	IDEXW(in_dx2a,in,1), IDEX(in_dx2a,in), IDEXW(out_a2dx,out,1), IDEX(out_a2dx,out),
+	/* 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 */
+	/*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,
+	/* 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,
@@ -171,22 +169,22 @@ opcode_entry opcode_table [512] = {
   /* 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,
+  /* 0x80 */	IDEX(J,jcc), IDEX(J,jcc), IDEX(J,jcc), IDEX(J,jcc),
+  /* 0x84 */	IDEX(J,jcc), IDEX(J,jcc), IDEX(J,jcc), IDEX(J,jcc),
+  /* 0x88 */	IDEX(J,jcc), IDEX(J,jcc), IDEX(J,jcc), IDEX(J,jcc),
+  /* 0x8c */	IDEX(J,jcc), IDEX(J,jcc), IDEX(J,jcc), IDEX(J,jcc),
+  /* 0x90 */	IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1),
+  /* 0x94 */	IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1),
+  /* 0x98 */	IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1),
+  /* 0x9c */	IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1), IDEXW(setcc_E,setcc,1),
   /* 0xa0 */	EMPTY, EMPTY, EMPTY, EMPTY,
   /* 0xa4 */	EMPTY, EMPTY, EMPTY, EMPTY,
   /* 0xa8 */	EMPTY, EMPTY, EMPTY, EMPTY,
-  /* 0xac */	EMPTY, EMPTY, EMPTY, EMPTY,
+  /* 0xac */	EMPTY, EMPTY, EMPTY, IDEX(E2G,imul2),
   /* 0xb0 */	EMPTY, EMPTY, EMPTY, EMPTY,
-  /* 0xb4 */	EMPTY, EMPTY, EMPTY, EMPTY,
+  /* 0xb4 */	EMPTY, EMPTY, IDEXW(mov_E2G,movzx,1),IDEXW(mov_E2G,movzx,2),
   /* 0xb8 */	EMPTY, EMPTY, EMPTY, EMPTY,
-  /* 0xbc */	EMPTY, EMPTY, EMPTY, EMPTY,
+  /* 0xbc */	EMPTY, EMPTY, IDEXW(mov_E2G,movsx,1), IDEXW(mov_E2G,movsx,2),
   /* 0xc0 */	EMPTY, EMPTY, EMPTY, EMPTY,
   /* 0xc4 */	EMPTY, EMPTY, EMPTY, EMPTY,
   /* 0xc8 */	EMPTY, EMPTY, EMPTY, EMPTY,
@@ -205,6 +203,174 @@ 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;
diff --git a/nemu/src/cpu/exec/logic.cc b/nemu/src/cpu/exec/logic.cc
index 9925b35..50d56e2 100644
--- a/nemu/src/cpu/exec/logic.cc
+++ b/nemu/src/cpu/exec/logic.cc
@@ -14,7 +14,11 @@ make_EHelper(and) {
 }
 
 make_EHelper(xor) {
-  TODO();
+  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);
 }
@@ -60,3 +64,9 @@ make_EHelper(not) {
 
   print_asm_template1(not);
 }
+
+make_EHelper(rol) {
+  TODO();
+
+  print_asm_template1(rol);
+}
diff --git a/nemu/src/monitor/debug/expr_impl/lexer.l b/nemu/src/monitor/debug/expr_impl/lexer.l
index f1cfff1..649ac3d 100644
--- a/nemu/src/monitor/debug/expr_impl/lexer.l
+++ b/nemu/src/monitor/debug/expr_impl/lexer.l
@@ -6,6 +6,7 @@
 
 #include "parser.tab.h"
 #include <stdint.h>
+#include <stdexcept>
 
 %}
 
@@ -20,5 +21,6 @@
 [-+*/()]      {return yytext[0];}
 
 "%"[a-z]{3}   {yylval.ival = ((uint32_t)yytext[2] << 8) + yytext[3]; return T_REG;}
+.             {throw std::runtime_error(std::string("lexer error around token: ") + yytext);}
 %%
 // Registers: eax='a'+'x', ebx='b'+'x', ...
diff --git a/nemu/src/monitor/debug/expr_impl/parser.y b/nemu/src/monitor/debug/expr_impl/parser.y
index f53b0b5..a1b1eea 100644
--- a/nemu/src/monitor/debug/expr_impl/parser.y
+++ b/nemu/src/monitor/debug/expr_impl/parser.y
@@ -54,6 +54,7 @@ expr: T_INT                     { $$ = $1; }
 %%
 
 #include "monitor/expr_impl/parser_interface.h"
+#include <stdexcept>
 
 int64_t parse_one(std::string expr) {
     yy_scan_string(expr.c_str());
@@ -70,8 +71,7 @@ int ryy_test_main() {
 }
 
 void yyerror(int64_t *result, std::string msg) {
-    rlib::println("Parse error:", msg);
-    exit(1);
+    throw std::runtime_error(std::string("Parse error:") + msg);
 }
 
 // v-cpu related code:
diff --git a/nemu/src/monitor/debug/ui.cc b/nemu/src/monitor/debug/ui.cc
index 253554a..74944d1 100644
--- a/nemu/src/monitor/debug/ui.cc
+++ b/nemu/src/monitor/debug/ui.cc
@@ -53,6 +53,7 @@ static int cmd_n(char *args) {
 static int cmd_info(char *args);
 static int cmd_x(char *args);
 static int cmd_w(char *args);
+static int cmd_p(char *args);
 static int cmd_d(char *args);
 
 static int cmd_q(char *args) {
@@ -72,6 +73,7 @@ static struct {
   { "info", "= GDB `info`, supporting `info r` / `info w`", cmd_info },
   { "x", "x <bytes> <start address>, dump memory content.", cmd_x },
   { "w", "w <expr>, add watchpoint for $expr", cmd_w },
+  { "p", "p <expr>, show value of $expr", cmd_p },
   { "d", "d <watchpoint id>, delete watchpoint by id", cmd_d },
   { "q", "Exit NEMU", cmd_q },
 
@@ -149,7 +151,7 @@ void ui_mainloop(int is_batch_mode) {
 
 // 3rdparty prettyprint will print rlib::string as array. Let's convert it to normal string.
 std::string dumpReg(uint32_t val) {
-  return string("{}{}[32b=0x{}{}, {}L16b=0x{}]").format(std::setfill('0'), std::setw(8), std::hex, val, std::setw(4), (uint16_t)val);
+  return string("{}{}[32b=0x{}{}, {}L16b=0x{}]{}").format(std::setfill('0'), std::setw(8), std::hex, val, std::setw(4), (uint16_t)val, std::dec);
 }
 auto dumpMem(uint32_t begin_addr, uint64_t size) {
   std::stringstream res;
@@ -161,6 +163,7 @@ auto dumpMem(uint32_t begin_addr, uint64_t size) {
     }
     res << std::setfill('0') << std::setw(8) << vaddr_read(begin_addr + cter, 4) << ' ';
   }
+  res << std::dec;
   return res.str();
 }
 
@@ -187,8 +190,7 @@ static int cmd_x(char *_args) {
   if(args.size() != 2)
     throw std::runtime_error("Usage: x <size> <startAddr>");
   
-  printfln("Dumping {}{} bytes from {}{}{}:{}", std::dec, args[0], std::hex, args[1], std::dec, dumpMem(std::stoull(args[1], 0, 16), args[0].as<uint64_t>()));
-  
+  println(dumpMem(std::stoull(args[1], 0, 16), args[0].as<uint64_t>()));
   return 0;
 }
 
@@ -202,6 +204,15 @@ static int cmd_w(char *_args) {
   return 0;
 }
 
+static int cmd_p(char *_args) {
+  if(_args == NULL)
+    throw std::invalid_argument("p <expr>");
+
+  auto result = evaluate_expr(_args);
+  rlib::printfln("$ = {} = 0x{}{}{}", result, std::hex, result, std::dec);
+  return 0;
+}
+
 static int cmd_d(char *_args) {
   if(_args == NULL)
     throw std::invalid_argument("d <wp id>");
-- 
GitLab