From b07319133dcbd3da318cd7559f0dc95305b19c43 Mon Sep 17 00:00:00 2001
From: Recolic Keghart <root@recolic.net>
Date: Thu, 26 Dec 2019 17:50:19 +0800
Subject: [PATCH] >  Manual commit:  [DO NOT BUILD] tmp save my work U201614531
 recolic Linux RECOLICPC 5.4.2-arch1-1 #1 SMP PREEMPT Thu, 05 Dec 2019
 12:29:40 +0000 x86_64 GNU/Linux  17:50:19 up 3 days, 22:58,  1 user,  load
 average: 0.86, 0.51, 0.48 66e2b24dcce06cb614c08d513ef02c8b8d206c20

---
 nemu/Makefile                 |  2 +-
 nemu/include/cpu/rtl.h        | 13 ++++++-
 nemu/include/util.h           | 12 ------
 nemu/include/util/util.h      | 18 +++++++++
 nemu/src/cpu/exec/arith.cc    | 73 ++++++++++++++++++++++-------------
 nemu/src/cpu/exec/cc.cc       | 29 ++++++++++----
 nemu/src/cpu/exec/data-mov.cc | 10 ++++-
 nemu/src/cpu/exec/logic.cc    | 12 +++++-
 8 files changed, 118 insertions(+), 51 deletions(-)
 delete mode 100644 nemu/include/util.h
 create mode 100644 nemu/include/util/util.h

diff --git a/nemu/Makefile b/nemu/Makefile
index 6c8e56e..2a7eb67 100644
--- a/nemu/Makefile
+++ b/nemu/Makefile
@@ -19,7 +19,7 @@ include Makefile.git
 CXX ?= g++
 LD = $(CXX)
 INCLUDES  = $(addprefix -I, $(INC_DIR))
-CFLAGS   += -O2 -MMD -Wall -ggdb3 $(INCLUDES) -fomit-frame-pointer
+CFLAGS   += -O2 -MMD -Wall -ggdb3 $(INCLUDES) -fomit-frame-pointer -std=c++17
 CFLAGS   += -DDIFF_TEST_QEMU
 
 # Files to be compiled
diff --git a/nemu/include/cpu/rtl.h b/nemu/include/cpu/rtl.h
index ef1f014..273f134 100644
--- a/nemu/include/cpu/rtl.h
+++ b/nemu/include/cpu/rtl.h
@@ -5,6 +5,7 @@
 #include "util/c_op.h"
 #include "cpu/relop.h"
 #include "cpu/rtl-wrapper.h"
+#include <util/util.h>
 
 extern rtlreg_t t0, t1, t2, t3, at;
 
@@ -159,7 +160,17 @@ static inline void rtl_not(rtlreg_t *dest, const rtlreg_t* src1) {
 
 static inline void rtl_sext(rtlreg_t* dest, const rtlreg_t* src1, int width) {
   // dest <- signext(src1[(width * 8 - 1) .. 0])
-  TODO();
+  switch(width) {
+    case 1:
+      *dest = rlib::signed_extend_low_bytes<1>(*src1);
+      return;
+    case 2:
+      *dest = rlib::signed_extend_low_bytes<2>(*src1);
+      return;
+    case 4:
+      *dest = rlib::signed_extend_low_bytes<4>(*src1);
+      return;
+  }
 }
 
 template <int OperandBytes>
diff --git a/nemu/include/util.h b/nemu/include/util.h
deleted file mode 100644
index b46505e..0000000
--- a/nemu/include/util.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#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/include/util/util.h b/nemu/include/util/util.h
new file mode 100644
index 0000000..330a1d9
--- /dev/null
+++ b/nemu/include/util/util.h
@@ -0,0 +1,18 @@
+#ifndef RLIB_HUST_UTIL_HPP_
+#define RLIB_HUST_UTIL_HPP_ 1
+
+#include <common.h>
+
+namespace rlib {
+  template <size_t BytesCount>
+  static inline int32_t signed_extend_low_bytes(const int32_t &val) {
+    static_assert(BytesCount == 1 || BytesCount == 2 || BytesCount == 4);
+    if constexpr(BytesCount == 1)
+      return (int8_t)val;
+    else if constexpr(BytesCount == 2)
+      return (int16_t)val;
+    else return val;
+  }
+}
+
+#endif
diff --git a/nemu/src/cpu/exec/arith.cc b/nemu/src/cpu/exec/arith.cc
index f3a983c..0a10a39 100644
--- a/nemu/src/cpu/exec/arith.cc
+++ b/nemu/src/cpu/exec/arith.cc
@@ -1,36 +1,32 @@
 #include "cpu/exec.h"
 
-#include <util.h>
+#include <util/util.h>
 
 make_EHelper(add) {
-  TODO();
+	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) {
-  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_sext(&t1, &id_dest->val, id_dest->width);
+	rtl_sext(&t2, &id_src->val, id_src->width);
 
-  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);
+	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);
 }
@@ -38,19 +34,44 @@ make_EHelper(sub) {
 
 
 make_EHelper(cmp) {
-  TODO();
+	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) {
-  TODO();
+	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) {
-  TODO();
+  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);
 }
diff --git a/nemu/src/cpu/exec/cc.cc b/nemu/src/cpu/exec/cc.cc
index 793991b..3af0622 100644
--- a/nemu/src/cpu/exec/cc.cc
+++ b/nemu/src/cpu/exec/cc.cc
@@ -14,14 +14,27 @@ void rtl_setcc(rtlreg_t* dest, uint8_t subcode) {
   // TODO: Query EFLAGS to determine whether the condition code is satisfied.
   // dest <- ( cc is satisfied ? 1 : 0)
   switch (subcode & 0xe) {
-    case CC_O:
-    case CC_B:
-    case CC_E:
-    case CC_BE:
-    case CC_S:
-    case CC_L:
-    case CC_LE:
-      TODO();
+		case CC_O:  //0
+			*dest = cpu_eflags::get<cpu_eflags::OF>();
+			break;
+		case CC_B:  //2
+			*dest = cpu_eflags::get<cpu_eflags::CF>();
+			break;
+		case CC_E:  //4
+			*dest = cpu_eflags::get<cpu_eflags::ZF>();
+			break;
+		case CC_BE: //6
+			*dest = ((cpu_eflags::get<cpu_eflags::CF>()) || (cpu_eflags::get<cpu_eflags::ZF>()));
+			break;
+		case CC_S:  //8
+			*dest = cpu_eflags::get<cpu_eflags::SF>();
+			break;
+		case CC_L:  //12 c
+			*dest = (cpu_eflags::get<cpu_eflags::SF>() != cpu_eflags::get<cpu_eflags::OF>());
+			break;
+		case CC_LE: //14 e
+			*dest = ((cpu_eflags::get<cpu_eflags::ZF>()) || (cpu_eflags::get<cpu_eflags::SF>() != cpu_eflags::get<cpu_eflags::OF>()));
+			break;
     default: panic("should not reach here");
     case CC_P: panic("n86 does not have PF");
   }
diff --git a/nemu/src/cpu/exec/data-mov.cc b/nemu/src/cpu/exec/data-mov.cc
index bff93e3..6182ede 100644
--- a/nemu/src/cpu/exec/data-mov.cc
+++ b/nemu/src/cpu/exec/data-mov.cc
@@ -47,7 +47,15 @@ make_EHelper(popa) {
 }
 
 make_EHelper(leave) {
-  TODO();
+  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");
 }
diff --git a/nemu/src/cpu/exec/logic.cc b/nemu/src/cpu/exec/logic.cc
index 50d56e2..dd28dfc 100644
--- a/nemu/src/cpu/exec/logic.cc
+++ b/nemu/src/cpu/exec/logic.cc
@@ -2,13 +2,21 @@
 #include "cpu/cc.h"
 
 make_EHelper(test) {
-  TODO();
+  // `and` without write_back.
+  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) {
-  TODO();
+  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);
 }
-- 
GitLab