From d2b63e1e5109b1cdd876e1400be8910b4c302a9f Mon Sep 17 00:00:00 2001
From: Recolic Keghart <root@recolic.net>
Date: Sun, 29 Dec 2019 20:09:31 +0800
Subject: [PATCH] fix problems about IO

---
 nemu/include/common.h                         |  2 +-
 nemu/include/device/port-io.h                 |  6 ++
 nemu/src/cpu/exec/control.cc                  |  2 +-
 nemu/src/cpu/exec/system.cc                   | 19 +++++-
 nemu/src/device/io/port-io.cc                 | 59 +++++++------------
 nemu/src/device/vga.cc                        |  7 +--
 nexus-am/am/arch/x86-nemu/src/devices/timer.c |  8 ++-
 nexus-am/libs/klib/src/printf-lib/printf.c    |  2 +
 nexus-am/libs/klib/src/stdio.c                |  3 -
 9 files changed, 55 insertions(+), 53 deletions(-)

diff --git a/nemu/include/common.h b/nemu/include/common.h
index d765817..b734ebc 100644
--- a/nemu/include/common.h
+++ b/nemu/include/common.h
@@ -11,7 +11,7 @@
 #endif
 
 /* You will define this macro in PA2 */
-//#define HAS_IOE
+#define HAS_IOE
 
 #include <stdint.h>
 #include <assert.h>
diff --git a/nemu/include/device/port-io.h b/nemu/include/device/port-io.h
index 84e2488..62969e3 100644
--- a/nemu/include/device/port-io.h
+++ b/nemu/include/device/port-io.h
@@ -7,4 +7,10 @@ typedef void(*pio_callback_t)(ioaddr_t, int, bool);
 
 void* add_pio_map(ioaddr_t, int, pio_callback_t);
 
+template <size_t Bytes>
+uint32_t pio_read_common(ioaddr_t addr);
+
+template <size_t Bytes>
+void pio_write_common(ioaddr_t addr, uint32_t data);
+
 #endif
diff --git a/nemu/src/cpu/exec/control.cc b/nemu/src/cpu/exec/control.cc
index 8c05bb9..f21343a 100644
--- a/nemu/src/cpu/exec/control.cc
+++ b/nemu/src/cpu/exec/control.cc
@@ -66,7 +66,7 @@ namespace EHelperImpl {
   
   make_EHelper(call_rm) {
     RLIB_MACRO_DEBUG_ASSERT(decoding.is_operand_size_16 == false);
-    rlib::println("Reach call_rm. WARNING: this instruction impl is heavily broken.");
+    // rlib::println("Reach call_rm. WARNING: this instruction impl is heavily broken.");
 
     rtl_push<4>(&decoding.seq_eip);
     rtl_jr(&id_dest->val);
diff --git a/nemu/src/cpu/exec/system.cc b/nemu/src/cpu/exec/system.cc
index c1876cf..7c820e9 100644
--- a/nemu/src/cpu/exec/system.cc
+++ b/nemu/src/cpu/exec/system.cc
@@ -1,4 +1,5 @@
 #include "cpu/exec.h"
+#include "device/port-io.h"
 
 void difftest_skip_ref();
 void difftest_skip_dut();
@@ -43,7 +44,14 @@ namespace EHelperImpl {
   }
   
   make_EHelper(in) {
-    TODO();
+    rtlreg_t tmp;
+  	switch(id_src->width)
+  	{
+  		case 1: tmp = pio_read_common<1>(id_src->val); break;
+  		case 2: tmp = pio_read_common<2>(id_src->val); break;
+  		case 4: tmp = pio_read_common<4>(id_src->val); break;
+  	}
+  	operand_write(id_dest, &tmp);
   
     print_asm_template2(in);
   
@@ -53,8 +61,13 @@ namespace EHelperImpl {
   }
   
   make_EHelper(out) {
-    TODO();
-  
+	  switch(id_src->width)
+	  {
+	  	case 1: pio_write_common<1>(id_dest->val, id_src->val); break;
+	  	case 2: pio_write_common<2>(id_dest->val, id_src->val); break;
+	  	case 4: pio_write_common<4>(id_dest->val, id_src->val); break;
+	  }
+
     print_asm_template2(out);
   
   #if defined(DIFF_TEST)
diff --git a/nemu/src/device/io/port-io.cc b/nemu/src/device/io/port-io.cc
index 0b0960b..cd9a62d 100644
--- a/nemu/src/device/io/port-io.cc
+++ b/nemu/src/device/io/port-io.cc
@@ -39,49 +39,30 @@ void* add_pio_map(ioaddr_t addr, int len, pio_callback_t callback) {
   return pio_space + addr;
 }
 
-static inline uint32_t pio_read_common(ioaddr_t addr, int len) {
-  assert(addr + len - 1 < PORT_IO_SPACE_MAX);
-  pio_callback(addr, len, false);		// prepare data to read
-  switch (len) {
-    case 4: return *(uint32_t *)(pio_space + addr);
-    case 2: return *(uint16_t *)(pio_space + addr);
-    case 1: return *(uint8_t *)(pio_space + addr);
-    default: assert(0);
-  }
-}
-
-static inline void pio_write_common(ioaddr_t addr, uint32_t data, int len) {
-  assert(addr + len - 1 < PORT_IO_SPACE_MAX);
-  switch (len) {
-    case 4: *(uint32_t *)(pio_space + addr) = data; break;
-    case 2: *(uint16_t *)(pio_space + addr) = data; break;
-    case 1: *(uint8_t *)(pio_space + addr) = data; break;
-    default: assert(0);
-  }
-  pio_callback(addr, len, true);
-}
+template <size_t Bytes>
+uint32_t pio_read_common(ioaddr_t addr) {
+  static_assert(Bytes == 4 || Bytes == 2 || Bytes == 1);
+  using result_type = std::conditional_t<Bytes == 4, uint32_t, std::conditional_t<Bytes == 2, uint16_t, uint8_t>>;
 
-/* CPU interface */
-uint32_t pio_read_l(ioaddr_t addr) {
-  return pio_read_common(addr, 4);
+  assert(addr + Bytes - 1 < PORT_IO_SPACE_MAX);
+  pio_callback(addr, Bytes, false);		// prepare data to read
+  return *(result_type *)(pio_space + addr);
 }
 
-uint32_t pio_read_w(ioaddr_t addr) {
-  return pio_read_common(addr, 2);
-}
+template <size_t Bytes>
+void pio_write_common(ioaddr_t addr, uint32_t data) {
+  static_assert(Bytes == 4 || Bytes == 2 || Bytes == 1);
+  using result_type = std::conditional_t<Bytes == 4, uint32_t, std::conditional_t<Bytes == 2, uint16_t, uint8_t>>;
 
-uint32_t pio_read_b(ioaddr_t addr) {
-  return pio_read_common(addr, 1);
+  assert(addr + Bytes - 1 < PORT_IO_SPACE_MAX);
+  *(result_type *)(pio_space + addr) = data;
+  pio_callback(addr, Bytes, true);
 }
 
-void pio_write_l(ioaddr_t addr, uint32_t data) {
-  pio_write_common(addr, data, 4);
-}
 
-void pio_write_w(ioaddr_t addr, uint32_t data) {
-  pio_write_common(addr, data, 2);
-}
-
-void pio_write_b(ioaddr_t addr, uint32_t data) {
-  pio_write_common(addr, data, 1);
-}
+template uint32_t pio_read_common<4>(ioaddr_t addr);
+template uint32_t pio_read_common<2>(ioaddr_t addr);
+template uint32_t pio_read_common<1>(ioaddr_t addr);
+template void pio_write_common<4>(ioaddr_t addr, uint32_t data);
+template void pio_write_common<2>(ioaddr_t addr, uint32_t data);
+template void pio_write_common<1>(ioaddr_t addr, uint32_t data);
diff --git a/nemu/src/device/vga.cc b/nemu/src/device/vga.cc
index 20c1678..6644584 100644
--- a/nemu/src/device/vga.cc
+++ b/nemu/src/device/vga.cc
@@ -7,8 +7,7 @@
 #include <SDL2/SDL.h>
 
 #define VMEM 0x40000
-
-#define SCREEN_PORT 0x100 // Note that this is not the standard
+#define SCREEN_PORT 0x100
 #define SCREEN_H 300
 #define SCREEN_W 400
 
@@ -33,8 +32,8 @@ void init_vga() {
   texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
       SDL_TEXTUREACCESS_STATIC, SCREEN_W, SCREEN_H);
 
-  screensize_port_base = add_pio_map(SCREEN_PORT, 4, NULL);
+  screensize_port_base = reinterpret_cast<decltype(screensize_port_base)>(add_pio_map(SCREEN_PORT, 4, nullptr));
   *screensize_port_base = ((SCREEN_W) << 16) | (SCREEN_H);
-  vmem = add_mmio_map(VMEM, 0x80000, NULL);
+  vmem = reinterpret_cast<decltype(vmem)>(add_mmio_map(VMEM, 0x80000, nullptr));
 }
 #endif	/* HAS_IOE */
diff --git a/nexus-am/am/arch/x86-nemu/src/devices/timer.c b/nexus-am/am/arch/x86-nemu/src/devices/timer.c
index b7c366c..9fd970c 100644
--- a/nexus-am/am/arch/x86-nemu/src/devices/timer.c
+++ b/nexus-am/am/arch/x86-nemu/src/devices/timer.c
@@ -3,11 +3,15 @@
 #include <amdev.h>
 
 size_t timer_read(uintptr_t reg, void *buf, size_t size) {
+  const size_t rtc_port_id = 0x48;
+  uint64_t curr_time;
+
   switch (reg) {
     case _DEVREG_TIMER_UPTIME: {
       _UptimeReg *uptime = (_UptimeReg *)buf;
-      uptime->hi = 0;
-      uptime->lo = 0;
+      curr_time = inl(rtc_port_id);
+      uptime->hi = curr_time >> 32;
+      uptime->lo = (uint32_t) curr_time;
       return sizeof(_UptimeReg);
     }
     case _DEVREG_TIMER_DATE: {
diff --git a/nexus-am/libs/klib/src/printf-lib/printf.c b/nexus-am/libs/klib/src/printf-lib/printf.c
index 8a700ad..23edb2d 100644
--- a/nexus-am/libs/klib/src/printf-lib/printf.c
+++ b/nexus-am/libs/klib/src/printf-lib/printf.c
@@ -35,6 +35,8 @@
 
 #include "printf.h"
 
+#include "am.h"
+void _putchar(char c) {_putc(c);}
 
 // define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
 // printf_config.h header file
diff --git a/nexus-am/libs/klib/src/stdio.c b/nexus-am/libs/klib/src/stdio.c
index 681f124..5807363 100644
--- a/nexus-am/libs/klib/src/stdio.c
+++ b/nexus-am/libs/klib/src/stdio.c
@@ -30,8 +30,5 @@ int vsprintf_(char *out, const char *fmt, va_list va) {
 //  return 0;
 //}
 
-void _putchar(char character) {
-    ;
-}
 
 #endif
-- 
GitLab