From 1a4ad391764a7e160ad99e5fbf2b9d096ad25234 Mon Sep 17 00:00:00 2001
From: 181250012-Chen Lu <181250012@smail.nju.edu.cn>
Date: Mon, 12 Jul 2021 10:31:53 +0800
Subject: [PATCH 1/4] add riscv64-mycpu

---
 .gitignore                      |   1 +
 am/include/arch/riscv64-mycpu.h |   0
 am/src/mycpu/boot/start.S       |   8 +
 am/src/mycpu/include/mycpu.h    |   5 +
 am/src/mycpu/ioe/input.c        |   6 +
 am/src/mycpu/ioe/ioe.c          |  33 ++++
 am/src/mycpu/ioe/timer.c        |  13 ++
 am/src/mycpu/scripts/section.ld |  33 ++++
 am/src/mycpu/trm.c              |  24 +++
 klib/Makefile                   |   1 +
 klib/src/div.S                  | 140 ++++++++++++++++
 klib/src/int64.c                | 288 +++-----------------------------
 klib/src/muldi3.S               |  25 +++
 scripts/riscv64-mycpu.mk        |  22 +++
 14 files changed, 333 insertions(+), 266 deletions(-)
 create mode 100644 am/include/arch/riscv64-mycpu.h
 create mode 100644 am/src/mycpu/boot/start.S
 create mode 100644 am/src/mycpu/include/mycpu.h
 create mode 100644 am/src/mycpu/ioe/input.c
 create mode 100644 am/src/mycpu/ioe/ioe.c
 create mode 100644 am/src/mycpu/ioe/timer.c
 create mode 100644 am/src/mycpu/scripts/section.ld
 create mode 100644 am/src/mycpu/trm.c
 create mode 100644 klib/src/div.S
 create mode 100644 klib/src/muldi3.S
 create mode 100644 scripts/riscv64-mycpu.mk

diff --git a/.gitignore b/.gitignore
index 2f31ace..84c3ed2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,4 @@ _*
 *~
 build/
 !.gitignore
+.vscode
\ No newline at end of file
diff --git a/am/include/arch/riscv64-mycpu.h b/am/include/arch/riscv64-mycpu.h
new file mode 100644
index 0000000..e69de29
diff --git a/am/src/mycpu/boot/start.S b/am/src/mycpu/boot/start.S
new file mode 100644
index 0000000..3e56e5c
--- /dev/null
+++ b/am/src/mycpu/boot/start.S
@@ -0,0 +1,8 @@
+.section entry, "ax"
+.globl _start
+.type _start, @function
+
+_start:
+  mv s0, zero
+  la sp, _stack_pointer
+  jal _trm_init
diff --git a/am/src/mycpu/include/mycpu.h b/am/src/mycpu/include/mycpu.h
new file mode 100644
index 0000000..a4c20b8
--- /dev/null
+++ b/am/src/mycpu/include/mycpu.h
@@ -0,0 +1,5 @@
+#include <klib-macros.h>
+
+#define PMEM_SIZE (128 * 1024 * 1024)
+#define PMEM_END  ((uintptr_t)&_pmem_start + PMEM_SIZE)
+extern char _pmem_start;
diff --git a/am/src/mycpu/ioe/input.c b/am/src/mycpu/ioe/input.c
new file mode 100644
index 0000000..29a8662
--- /dev/null
+++ b/am/src/mycpu/ioe/input.c
@@ -0,0 +1,6 @@
+#include <am.h>
+
+void __am_input_keybrd(AM_INPUT_KEYBRD_T *kbd) {
+
+
+}
diff --git a/am/src/mycpu/ioe/ioe.c b/am/src/mycpu/ioe/ioe.c
new file mode 100644
index 0000000..97a306d
--- /dev/null
+++ b/am/src/mycpu/ioe/ioe.c
@@ -0,0 +1,33 @@
+#include <am.h>
+#include <klib-macros.h>
+
+void __am_timer_init();
+
+void __am_timer_rtc(AM_TIMER_RTC_T *);
+void __am_timer_uptime(AM_TIMER_UPTIME_T *);
+void __am_input_keybrd(AM_INPUT_KEYBRD_T *);
+void __am_timer_rtc(AM_TIMER_RTC_T *);
+
+static void __am_timer_config(AM_TIMER_CONFIG_T *cfg) { cfg->present = true; cfg->has_rtc = true; }
+static void __am_input_config(AM_INPUT_CONFIG_T *cfg) { cfg->present = true;  }
+
+typedef void (*handler_t)(void *buf);
+static void *lut[128] = {
+  [AM_TIMER_CONFIG] = __am_timer_config,
+  [AM_TIMER_RTC   ] = __am_timer_rtc,
+  [AM_TIMER_UPTIME] = __am_timer_uptime,
+  [AM_INPUT_CONFIG] = __am_input_config,
+  [AM_INPUT_KEYBRD] = __am_input_keybrd,
+};
+
+static void fail(void *buf) { panic("access nonexist register"); }
+
+bool ioe_init() {
+  for (int i = 0; i < LENGTH(lut); i++)
+    if (!lut[i]) lut[i] = fail;
+  __am_timer_init();
+  return true;
+}
+
+void ioe_read (int reg, void *buf) { ((handler_t)lut[reg])(buf); }
+void ioe_write(int reg, void *buf) { ((handler_t)lut[reg])(buf); }
diff --git a/am/src/mycpu/ioe/timer.c b/am/src/mycpu/ioe/timer.c
new file mode 100644
index 0000000..f176d94
--- /dev/null
+++ b/am/src/mycpu/ioe/timer.c
@@ -0,0 +1,13 @@
+#include <am.h>
+
+void __am_timer_init() {
+
+}
+
+void __am_timer_uptime(AM_TIMER_UPTIME_T *uptime) {
+
+}
+
+void __am_timer_rtc(AM_TIMER_RTC_T *rtc) {
+
+}
diff --git a/am/src/mycpu/scripts/section.ld b/am/src/mycpu/scripts/section.ld
new file mode 100644
index 0000000..a9f2688
--- /dev/null
+++ b/am/src/mycpu/scripts/section.ld
@@ -0,0 +1,33 @@
+_pmem_start = 0x80000000;
+
+ENTRY(_start)
+
+SECTIONS {
+  . = _pmem_start + 0x100000;
+  .text : {
+    *(entry)
+    *(.text*)
+  }
+  etext = .;
+  _etext = .;
+  .rodata : {
+    *(.rodata*)
+  }
+  .data : {
+    *(.data)
+  }
+  edata = .;
+  _data = .;
+  .bss : {
+	_bss_start = .;
+    *(.bss*)
+    *(.sbss*)
+    *(.scommon)
+  }
+  _stack_top = ALIGN(0x1000);
+  . = _stack_top + 0x8000;
+  _stack_pointer = .;
+  end = .;
+  _end = .;
+  _heap_start = ALIGN(0x1000);
+}
diff --git a/am/src/mycpu/trm.c b/am/src/mycpu/trm.c
new file mode 100644
index 0000000..f9a9b84
--- /dev/null
+++ b/am/src/mycpu/trm.c
@@ -0,0 +1,24 @@
+#include <am.h>
+#include <mycpu.h>
+
+extern char _heap_start;
+int main(const char *args);
+
+Area heap = RANGE(&_heap_start, PMEM_END);
+#ifndef MAINARGS
+#define MAINARGS ""
+#endif
+static const char mainargs[] = MAINARGS;
+
+void putch(char ch) {
+
+}
+
+void halt(int code) {
+  while (1);
+}
+
+void _trm_init() {
+  int ret = main(mainargs);
+  halt(ret);
+}
diff --git a/klib/Makefile b/klib/Makefile
index b117c60..068a023 100644
--- a/klib/Makefile
+++ b/klib/Makefile
@@ -1,3 +1,4 @@
 NAME = klib
 SRCS = $(shell find src/ -name "*.c")
+SRCS += $(shell find src/ -name "*.S")
 include $(AM_HOME)/Makefile
diff --git a/klib/src/div.S b/klib/src/div.S
new file mode 100644
index 0000000..0d394d2
--- /dev/null
+++ b/klib/src/div.S
@@ -0,0 +1,140 @@
+#define FUNC_TYPE(X)	.type X,@function
+#define FUNC_SIZE(X)	.size X,.-X
+
+#define FUNC_BEGIN(X)		\
+	.globl X;		\
+	FUNC_TYPE (X);		\
+X:
+
+#define FUNC_END(X)		\
+	FUNC_SIZE(X)
+
+#define FUNC_ALIAS(X,Y)		\
+	.globl X;		\
+	X = Y
+
+
+#define __riscv_xlen 64
+
+  .text
+  .align 2
+
+#if __riscv_xlen == 32
+/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines.  */
+# define __udivdi3 __udivsi3
+# define __umoddi3 __umodsi3
+# define __divdi3 __divsi3
+# define __moddi3 __modsi3
+#else
+FUNC_BEGIN (__udivsi3)
+  /* Compute __udivdi3(a0 << 32, a1 << 32); cast result to uint32_t.  */
+  sll    a0, a0, 32
+  sll    a1, a1, 32
+  move   t0, ra
+  jal    __udivdi3
+  sext.w a0, a0
+  jr     t0
+FUNC_END (__udivsi3)
+
+FUNC_BEGIN (__umodsi3)
+  /* Compute __udivdi3((uint32_t)a0, (uint32_t)a1); cast a1 to uint32_t.  */
+  sll    a0, a0, 32
+  sll    a1, a1, 32
+  srl    a0, a0, 32
+  srl    a1, a1, 32
+  move   t0, ra
+  jal    __udivdi3
+  sext.w a0, a1
+  jr     t0
+FUNC_END (__umodsi3)
+
+FUNC_ALIAS (__modsi3, __moddi3)
+
+FUNC_BEGIN( __divsi3)
+  /* Check for special case of INT_MIN/-1. Otherwise, fall into __divdi3.  */
+  li    t0, -1
+  beq   a1, t0, .L20
+#endif
+
+FUNC_BEGIN (__divdi3)
+  bltz  a0, .L10
+  bltz  a1, .L11
+  /* Since the quotient is positive, fall into __udivdi3.  */
+
+FUNC_BEGIN (__udivdi3)
+  mv    a2, a1
+  mv    a1, a0
+  li    a0, -1
+  beqz  a2, .L5
+  li    a3, 1
+  bgeu  a2, a1, .L2
+.L1:
+  blez  a2, .L2
+  slli  a2, a2, 1
+  slli  a3, a3, 1
+  bgtu  a1, a2, .L1
+.L2:
+  li    a0, 0
+.L3:
+  bltu  a1, a2, .L4
+  sub   a1, a1, a2
+  or    a0, a0, a3
+.L4:
+  srli  a3, a3, 1
+  srli  a2, a2, 1
+  bnez  a3, .L3
+.L5:
+  ret
+FUNC_END (__udivdi3)
+
+FUNC_BEGIN (__umoddi3)
+  /* Call __udivdi3(a0, a1), then return the remainder, which is in a1.  */
+  move  t0, ra
+  jal   __udivdi3
+  move  a0, a1
+  jr    t0
+FUNC_END (__umoddi3)
+
+  /* Handle negative arguments to __divdi3.  */
+.L10:
+  neg   a0, a0
+  /* Zero is handled as a negative so that the result will not be inverted.  */
+  bgtz  a1, .L12     /* Compute __udivdi3(-a0, a1), then negate the result.  */
+
+  neg   a1, a1
+  j     __udivdi3    /* Compute __udivdi3(-a0, -a1).  */
+.L11:                /* Compute __udivdi3(a0, -a1), then negate the result.  */
+  neg   a1, a1
+.L12:
+  move  t0, ra
+  jal   __udivdi3
+  neg   a0, a0
+  jr    t0
+FUNC_END (__divdi3)
+
+FUNC_BEGIN (__moddi3)
+  move   t0, ra
+  bltz   a1, .L31
+  bltz   a0, .L32
+.L30:
+  jal    __udivdi3    /* The dividend is not negative.  */
+  move   a0, a1
+  jr     t0
+.L31:
+  neg    a1, a1
+  bgez   a0, .L30
+.L32:
+  neg    a0, a0
+  jal    __udivdi3    /* The dividend is hella negative.  */
+  neg    a0, a1
+  jr     t0
+FUNC_END (__moddi3)
+
+#if __riscv_xlen == 64
+  /* continuation of __divsi3 */
+.L20:
+  sll   t0, t0, 31
+  bne   a0, t0, __divdi3
+  ret
+FUNC_END (__divsi3)
+#endif
diff --git a/klib/src/int64.c b/klib/src/int64.c
index b3b2876..8ef6d18 100644
--- a/klib/src/int64.c
+++ b/klib/src/int64.c
@@ -363,273 +363,7 @@ uint32_t __inline __builtin_clzll(uint64_t value) {
 
 #include <am.h>
 
-/* Returns: a / b */
 
-COMPILER_RT_ABI di_int
-__divdi3(di_int a, di_int b)
-{
-    const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1;
-    di_int s_a = a >> bits_in_dword_m1;           /* s_a = a < 0 ? -1 : 0 */
-    di_int s_b = b >> bits_in_dword_m1;           /* s_b = b < 0 ? -1 : 0 */
-    a = (a ^ s_a) - s_a;                         /* negate if s_a == -1 */
-    b = (b ^ s_b) - s_b;                         /* negate if s_b == -1 */
-    s_a ^= s_b;                                  /*sign of quotient */
-    return (__udivmoddi4(a, b, (du_int*)0) ^ s_a) - s_a;  /* negate if s_a == -1 */
-}
-
-/* Returns: a / b, *rem = a % b  */
-
-COMPILER_RT_ABI di_int
-__divmoddi4(di_int a, di_int b, di_int* rem)
-{
-  di_int d = __divdi3(a,b);
-  *rem = a - (d*b);
-  return d;
-}
-
-/* Returns: a % b */
-
-COMPILER_RT_ABI di_int
-__moddi3(di_int a, di_int b)
-{
-    const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1;
-    di_int s = b >> bits_in_dword_m1;  /* s = b < 0 ? -1 : 0 */
-    b = (b ^ s) - s;                   /* negate if s == -1 */
-    s = a >> bits_in_dword_m1;         /* s = a < 0 ? -1 : 0 */
-    a = (a ^ s) - s;                   /* negate if s == -1 */
-    du_int r;
-    __udivmoddi4(a, b, &r);
-    return ((di_int)r ^ s) - s;                /* negate if s == -1 */
-}
-
-/* Returns: a / b */
-
-COMPILER_RT_ABI du_int
-__udivdi3(du_int a, du_int b)
-{
-    return __udivmoddi4(a, b, 0);
-}
-
-
-COMPILER_RT_ABI du_int
-__udivmoddi4(du_int a, du_int b, du_int* rem)
-{
-    const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
-    const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
-    udwords n;
-    n.all = a;
-    udwords d;
-    d.all = b;
-    udwords q;
-    udwords r;
-    unsigned sr;
-    /* special cases, X is unknown, K != 0 */
-    if (n.s.high == 0)
-    {
-        if (d.s.high == 0)
-        {
-            /* 0 X
-             * ---
-             * 0 X
-             */
-            if (rem)
-                *rem = n.s.low % d.s.low;
-            return n.s.low / d.s.low;
-        }
-        /* 0 X
-         * ---
-         * K X
-         */
-        if (rem)
-            *rem = n.s.low;
-        return 0;
-    }
-    /* n.s.high != 0 */
-    if (d.s.low == 0)
-    {
-        if (d.s.high == 0)
-        {
-            /* K X
-             * ---
-             * 0 0
-             */
-            if (rem)
-                *rem = n.s.high % d.s.low;
-            return n.s.high / d.s.low;
-        }
-        /* d.s.high != 0 */
-        if (n.s.low == 0)
-        {
-            /* K 0
-             * ---
-             * K 0
-             */
-            if (rem)
-            {
-                r.s.high = n.s.high % d.s.high;
-                r.s.low = 0;
-                *rem = r.all;
-            }
-            return n.s.high / d.s.high;
-        }
-        /* K K
-         * ---
-         * K 0
-         */
-        if ((d.s.high & (d.s.high - 1)) == 0)     /* if d is a power of 2 */
-        {
-            if (rem)
-            {
-                r.s.low = n.s.low;
-                r.s.high = n.s.high & (d.s.high - 1);
-                *rem = r.all;
-            }
-            return n.s.high >> __builtin_ctz(d.s.high);
-        }
-        /* K K
-         * ---
-         * K 0
-         */
-        sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
-        /* 0 <= sr <= n_uword_bits - 2 or sr large */
-        if (sr > n_uword_bits - 2)
-        {
-           if (rem)
-                *rem = n.all;
-            return 0;
-        }
-        ++sr;
-        /* 1 <= sr <= n_uword_bits - 1 */
-        /* q.all = n.all << (n_udword_bits - sr); */
-        q.s.low = 0;
-        q.s.high = n.s.low << (n_uword_bits - sr);
-        /* r.all = n.all >> sr; */
-        r.s.high = n.s.high >> sr;
-        r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
-    }
-    else  /* d.s.low != 0 */
-    {
-        if (d.s.high == 0)
-        {
-            /* K X
-             * ---
-             * 0 K
-             */
-            if ((d.s.low & (d.s.low - 1)) == 0)     /* if d is a power of 2 */
-            {
-                if (rem)
-                    *rem = n.s.low & (d.s.low - 1);
-                if (d.s.low == 1)
-                    return n.all;
-                sr = __builtin_ctz(d.s.low);
-                q.s.high = n.s.high >> sr;
-                q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
-                return q.all;
-            }
-            /* K X
-             * ---
-             * 0 K
-             */
-            sr = 1 + n_uword_bits + __builtin_clz(d.s.low) - __builtin_clz(n.s.high);
-            /* 2 <= sr <= n_udword_bits - 1
-             * q.all = n.all << (n_udword_bits - sr);
-             * r.all = n.all >> sr;
-             */
-            if (sr == n_uword_bits)
-            {
-                q.s.low = 0;
-                q.s.high = n.s.low;
-                r.s.high = 0;
-                r.s.low = n.s.high;
-            }
-            else if (sr < n_uword_bits)  // 2 <= sr <= n_uword_bits - 1
-            {
-                q.s.low = 0;
-                q.s.high = n.s.low << (n_uword_bits - sr);
-                r.s.high = n.s.high >> sr;
-                r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
-            }
-            else              // n_uword_bits + 1 <= sr <= n_udword_bits - 1
-            {
-                q.s.low = n.s.low << (n_udword_bits - sr);
-                q.s.high = (n.s.high << (n_udword_bits - sr)) |
-                           (n.s.low >> (sr - n_uword_bits));
-                r.s.high = 0;
-                r.s.low = n.s.high >> (sr - n_uword_bits);
-            }
-        }
-        else
-        {
-            /* K X
-             * ---
-             * K K
-             */
-            sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
-            /* 0 <= sr <= n_uword_bits - 1 or sr large */
-            if (sr > n_uword_bits - 1)
-            {
-                if (rem)
-                    *rem = n.all;
-                return 0;
-            }
-            ++sr;
-            /* 1 <= sr <= n_uword_bits */
-            /*  q.all = n.all << (n_udword_bits - sr); */
-            q.s.low = 0;
-            if (sr == n_uword_bits)
-            {
-                q.s.high = n.s.low;
-                r.s.high = 0;
-                r.s.low = n.s.high;
-            }
-            else
-            {
-                q.s.high = n.s.low << (n_uword_bits - sr);
-                r.s.high = n.s.high >> sr;
-                r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
-            }
-        }
-    }
-    /* Not a special case
-     * q and r are initialized with:
-     * q.all = n.all << (n_udword_bits - sr);
-     * r.all = n.all >> sr;
-     * 1 <= sr <= n_udword_bits - 1
-     */
-    su_int carry = 0;
-    for (; sr > 0; --sr)
-    {
-        /* r:q = ((r:q)  << 1) | carry */
-        r.s.high = (r.s.high << 1) | (r.s.low  >> (n_uword_bits - 1));
-        r.s.low  = (r.s.low  << 1) | (q.s.high >> (n_uword_bits - 1));
-        q.s.high = (q.s.high << 1) | (q.s.low  >> (n_uword_bits - 1));
-        q.s.low  = (q.s.low  << 1) | carry;
-        /* carry = 0;
-         * if (r.all >= d.all)
-         * {
-         *      r.all -= d.all;
-         *      carry = 1;
-         * }
-         */
-        const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1);
-        carry = s & 1;
-        r.all -= d.all & s;
-    }
-    q.all = (q.all << 1) | carry;
-    if (rem)
-        *rem = r.all;
-    return q.all;
-}
-
-/* Returns: a % b */
-
-COMPILER_RT_ABI du_int
-__umoddi3(du_int a, du_int b)
-{
-    du_int r;
-    __udivmoddi4(a, b, &r);
-    return r;
-}
 
 // Returns: the number of leading 0-bits
 
@@ -705,3 +439,25 @@ COMPILER_RT_ABI si_int __ctzsi2(si_int a) {
   //     }
   return r + ((2 - (x >> 1)) & -((x & 1) == 0));
 }
+
+typedef int si_int;
+typedef long long di_int;
+typedef unsigned su_int;
+#define CHAR_BIT __CHAR_BIT__
+
+
+si_int __ctzdi2(di_int a) {
+  dwords x;
+  x.all = a;
+  const si_int f = -(x.s.low == 0);
+  return __ctzsi2((x.s.high & f) | (x.s.low & ~f)) +
+         (f & ((si_int)(sizeof(si_int) * CHAR_BIT)));
+}
+
+si_int __clzdi2(di_int a) {
+  dwords x;
+  x.all = a;
+  const si_int f = -(x.s.high == 0);
+  return __clzsi2((x.s.high & ~f) | (x.s.low & f)) +
+         (f & ((si_int)(sizeof(si_int) * CHAR_BIT)));
+}
diff --git a/klib/src/muldi3.S b/klib/src/muldi3.S
new file mode 100644
index 0000000..c9e131d
--- /dev/null
+++ b/klib/src/muldi3.S
@@ -0,0 +1,25 @@
+#define FUNC_TYPE(X)	.type X,@function
+#define FUNC_SIZE(X)	.size X,.-X
+
+#define FUNC_BEGIN(X)		\
+	.globl X;		\
+	FUNC_TYPE (X);		\
+X:
+
+#define FUNC_END(X)		\
+	FUNC_SIZE(X)
+
+
+FUNC_BEGIN (__muldi3)
+  mv     a2, a0
+  li     a0, 0
+.L1:
+  andi   a3, a1, 1
+  beqz   a3, .L2
+  add    a0, a0, a2
+.L2:
+  srli   a1, a1, 1
+  slli   a2, a2, 1
+  bnez   a1, .L1
+  ret
+FUNC_END (__muldi3)
\ No newline at end of file
diff --git a/scripts/riscv64-mycpu.mk b/scripts/riscv64-mycpu.mk
new file mode 100644
index 0000000..d20c8fc
--- /dev/null
+++ b/scripts/riscv64-mycpu.mk
@@ -0,0 +1,22 @@
+CROSS_COMPILE := riscv64-linux-gnu-
+COMMON_FLAGS  := -fno-pic -march=rv64ifd -mcmodel=medany
+CFLAGS        += $(COMMON_FLAGS) -static
+ASFLAGS       += $(COMMON_FLAGS) -O0
+LDFLAGS       += -melf64lriscv
+
+AM_SRCS := mycpu/boot/start.S \
+           mycpu/trm.c \
+		   mycpu/ioe/timer.c \
+		   mycpu/ioe/ioe.c \
+		   mycpu/ioe/input.c
+
+CFLAGS    += -fdata-sections -ffunction-sections
+LDFLAGS   += -T $(AM_HOME)/am/src/mycpu/scripts/section.ld
+LDFLAGS   += --gc-sections -e _start
+CFLAGS += -DMAINARGS=\"$(mainargs)\"
+CFLAGS += -I$(AM_HOME)/am/src/mycpu/include
+
+image: $(IMAGE).elf
+	@$(OBJDUMP) -d $(IMAGE).elf > $(IMAGE).txt
+	@echo + OBJCOPY "->" $(IMAGE_REL).bin
+	@$(OBJCOPY) -S --set-section-flags .bss=alloc,contents -O binary $(IMAGE).elf $(IMAGE).bin

From 17037fabb0d877f2568490cdc035e3a28085848d Mon Sep 17 00:00:00 2001
From: Zihao Yu <yuzihao@ict.ac.cn>
Date: Tue, 13 Jul 2021 16:20:49 +0800
Subject: [PATCH 2/4] am,mycpu: refactor directory structure

---
 am/src/mycpu/include/mycpu.h    |  5 -----
 am/src/mycpu/{ioe => }/input.c  |  4 ++--
 am/src/mycpu/{ioe => }/ioe.c    |  0
 am/src/mycpu/scripts/section.ld | 33 ---------------------------------
 am/src/mycpu/{boot => }/start.S |  0
 am/src/mycpu/{ioe => }/timer.c  | 10 +++++++---
 am/src/mycpu/trm.c              |  7 +++++--
 scripts/riscv64-mycpu.mk        | 12 ++++++------
 8 files changed, 20 insertions(+), 51 deletions(-)
 delete mode 100644 am/src/mycpu/include/mycpu.h
 rename am/src/mycpu/{ioe => }/input.c (57%)
 rename am/src/mycpu/{ioe => }/ioe.c (100%)
 delete mode 100644 am/src/mycpu/scripts/section.ld
 rename am/src/mycpu/{boot => }/start.S (100%)
 rename am/src/mycpu/{ioe => }/timer.c (51%)

diff --git a/am/src/mycpu/include/mycpu.h b/am/src/mycpu/include/mycpu.h
deleted file mode 100644
index a4c20b8..0000000
--- a/am/src/mycpu/include/mycpu.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <klib-macros.h>
-
-#define PMEM_SIZE (128 * 1024 * 1024)
-#define PMEM_END  ((uintptr_t)&_pmem_start + PMEM_SIZE)
-extern char _pmem_start;
diff --git a/am/src/mycpu/ioe/input.c b/am/src/mycpu/input.c
similarity index 57%
rename from am/src/mycpu/ioe/input.c
rename to am/src/mycpu/input.c
index 29a8662..0460fa4 100644
--- a/am/src/mycpu/ioe/input.c
+++ b/am/src/mycpu/input.c
@@ -1,6 +1,6 @@
 #include <am.h>
 
 void __am_input_keybrd(AM_INPUT_KEYBRD_T *kbd) {
-
-
+  kbd->keydown = 0;
+  kbd->keycode = AM_KEY_NONE;
 }
diff --git a/am/src/mycpu/ioe/ioe.c b/am/src/mycpu/ioe.c
similarity index 100%
rename from am/src/mycpu/ioe/ioe.c
rename to am/src/mycpu/ioe.c
diff --git a/am/src/mycpu/scripts/section.ld b/am/src/mycpu/scripts/section.ld
deleted file mode 100644
index a9f2688..0000000
--- a/am/src/mycpu/scripts/section.ld
+++ /dev/null
@@ -1,33 +0,0 @@
-_pmem_start = 0x80000000;
-
-ENTRY(_start)
-
-SECTIONS {
-  . = _pmem_start + 0x100000;
-  .text : {
-    *(entry)
-    *(.text*)
-  }
-  etext = .;
-  _etext = .;
-  .rodata : {
-    *(.rodata*)
-  }
-  .data : {
-    *(.data)
-  }
-  edata = .;
-  _data = .;
-  .bss : {
-	_bss_start = .;
-    *(.bss*)
-    *(.sbss*)
-    *(.scommon)
-  }
-  _stack_top = ALIGN(0x1000);
-  . = _stack_top + 0x8000;
-  _stack_pointer = .;
-  end = .;
-  _end = .;
-  _heap_start = ALIGN(0x1000);
-}
diff --git a/am/src/mycpu/boot/start.S b/am/src/mycpu/start.S
similarity index 100%
rename from am/src/mycpu/boot/start.S
rename to am/src/mycpu/start.S
diff --git a/am/src/mycpu/ioe/timer.c b/am/src/mycpu/timer.c
similarity index 51%
rename from am/src/mycpu/ioe/timer.c
rename to am/src/mycpu/timer.c
index f176d94..6ea0ffa 100644
--- a/am/src/mycpu/ioe/timer.c
+++ b/am/src/mycpu/timer.c
@@ -1,13 +1,17 @@
 #include <am.h>
 
 void __am_timer_init() {
-
 }
 
 void __am_timer_uptime(AM_TIMER_UPTIME_T *uptime) {
-
+  uptime->us = 0;
 }
 
 void __am_timer_rtc(AM_TIMER_RTC_T *rtc) {
-
+  rtc->second = 0;
+  rtc->minute = 0;
+  rtc->hour   = 0;
+  rtc->day    = 0;
+  rtc->month  = 0;
+  rtc->year   = 1900;
 }
diff --git a/am/src/mycpu/trm.c b/am/src/mycpu/trm.c
index f9a9b84..0efe6e7 100644
--- a/am/src/mycpu/trm.c
+++ b/am/src/mycpu/trm.c
@@ -1,9 +1,13 @@
 #include <am.h>
-#include <mycpu.h>
+#include <klib-macros.h>
 
 extern char _heap_start;
 int main(const char *args);
 
+extern char _pmem_start;
+#define PMEM_SIZE (128 * 1024 * 1024)
+#define PMEM_END  ((uintptr_t)&_pmem_start + PMEM_SIZE)
+
 Area heap = RANGE(&_heap_start, PMEM_END);
 #ifndef MAINARGS
 #define MAINARGS ""
@@ -11,7 +15,6 @@ Area heap = RANGE(&_heap_start, PMEM_END);
 static const char mainargs[] = MAINARGS;
 
 void putch(char ch) {
-
 }
 
 void halt(int code) {
diff --git a/scripts/riscv64-mycpu.mk b/scripts/riscv64-mycpu.mk
index d20c8fc..8da161b 100644
--- a/scripts/riscv64-mycpu.mk
+++ b/scripts/riscv64-mycpu.mk
@@ -4,17 +4,17 @@ CFLAGS        += $(COMMON_FLAGS) -static
 ASFLAGS       += $(COMMON_FLAGS) -O0
 LDFLAGS       += -melf64lriscv
 
-AM_SRCS := mycpu/boot/start.S \
+AM_SRCS := mycpu/start.S \
            mycpu/trm.c \
-		   mycpu/ioe/timer.c \
-		   mycpu/ioe/ioe.c \
-		   mycpu/ioe/input.c
+           mycpu/ioe.c \
+           mycpu/timer.c \
+           mycpu/input.c
 
 CFLAGS    += -fdata-sections -ffunction-sections
-LDFLAGS   += -T $(AM_HOME)/am/src/mycpu/scripts/section.ld
+LDFLAGS   += -T $(AM_HOME)/scripts/platform/nemu.ld --defsym=_pmem_start=0x80000000 --defsym=_entry_offset=0x0
 LDFLAGS   += --gc-sections -e _start
 CFLAGS += -DMAINARGS=\"$(mainargs)\"
-CFLAGS += -I$(AM_HOME)/am/src/mycpu/include
+.PHONY: $(AM_HOME)/am/src/mycpu/trm.c
 
 image: $(IMAGE).elf
 	@$(OBJDUMP) -d $(IMAGE).elf > $(IMAGE).txt

From 07eb9ba416c5207013d10c4b57667fce9ca4f809 Mon Sep 17 00:00:00 2001
From: Zihao Yu <yuzihao@ict.ac.cn>
Date: Tue, 13 Jul 2021 16:41:40 +0800
Subject: [PATCH 3/4] klib: move muldi3.S and div.S to riscv64-mycpu

* they will cause compile error with other ARCHs
---
 {klib/src => am/src/mycpu/libgcc}/div.S    |   0
 {klib/src => am/src/mycpu/libgcc}/muldi3.S |   0
 klib/Makefile                              |   1 -
 klib/src/int64.c                           | 266 +++++++++++++++++++++
 scripts/riscv64-mycpu.mk                   |   2 +
 5 files changed, 268 insertions(+), 1 deletion(-)
 rename {klib/src => am/src/mycpu/libgcc}/div.S (100%)
 rename {klib/src => am/src/mycpu/libgcc}/muldi3.S (100%)

diff --git a/klib/src/div.S b/am/src/mycpu/libgcc/div.S
similarity index 100%
rename from klib/src/div.S
rename to am/src/mycpu/libgcc/div.S
diff --git a/klib/src/muldi3.S b/am/src/mycpu/libgcc/muldi3.S
similarity index 100%
rename from klib/src/muldi3.S
rename to am/src/mycpu/libgcc/muldi3.S
diff --git a/klib/Makefile b/klib/Makefile
index 068a023..b117c60 100644
--- a/klib/Makefile
+++ b/klib/Makefile
@@ -1,4 +1,3 @@
 NAME = klib
 SRCS = $(shell find src/ -name "*.c")
-SRCS += $(shell find src/ -name "*.S")
 include $(AM_HOME)/Makefile
diff --git a/klib/src/int64.c b/klib/src/int64.c
index 8ef6d18..51401f8 100644
--- a/klib/src/int64.c
+++ b/klib/src/int64.c
@@ -363,7 +363,273 @@ uint32_t __inline __builtin_clzll(uint64_t value) {
 
 #include <am.h>
 
+/* Returns: a / b */
 
+COMPILER_RT_ABI di_int
+__divdi3(di_int a, di_int b)
+{
+    const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1;
+    di_int s_a = a >> bits_in_dword_m1;           /* s_a = a < 0 ? -1 : 0 */
+    di_int s_b = b >> bits_in_dword_m1;           /* s_b = b < 0 ? -1 : 0 */
+    a = (a ^ s_a) - s_a;                         /* negate if s_a == -1 */
+    b = (b ^ s_b) - s_b;                         /* negate if s_b == -1 */
+    s_a ^= s_b;                                  /*sign of quotient */
+    return (__udivmoddi4(a, b, (du_int*)0) ^ s_a) - s_a;  /* negate if s_a == -1 */
+}
+
+/* Returns: a / b, *rem = a % b  */
+
+COMPILER_RT_ABI di_int
+__divmoddi4(di_int a, di_int b, di_int* rem)
+{
+  di_int d = __divdi3(a,b);
+  *rem = a - (d*b);
+  return d;
+}
+
+/* Returns: a % b */
+
+COMPILER_RT_ABI di_int
+__moddi3(di_int a, di_int b)
+{
+    const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1;
+    di_int s = b >> bits_in_dword_m1;  /* s = b < 0 ? -1 : 0 */
+    b = (b ^ s) - s;                   /* negate if s == -1 */
+    s = a >> bits_in_dword_m1;         /* s = a < 0 ? -1 : 0 */
+    a = (a ^ s) - s;                   /* negate if s == -1 */
+    du_int r;
+    __udivmoddi4(a, b, &r);
+    return ((di_int)r ^ s) - s;                /* negate if s == -1 */
+}
+
+/* Returns: a / b */
+
+COMPILER_RT_ABI du_int
+__udivdi3(du_int a, du_int b)
+{
+    return __udivmoddi4(a, b, 0);
+}
+
+
+COMPILER_RT_ABI du_int
+__udivmoddi4(du_int a, du_int b, du_int* rem)
+{
+    const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
+    const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
+    udwords n;
+    n.all = a;
+    udwords d;
+    d.all = b;
+    udwords q;
+    udwords r;
+    unsigned sr;
+    /* special cases, X is unknown, K != 0 */
+    if (n.s.high == 0)
+    {
+        if (d.s.high == 0)
+        {
+            /* 0 X
+             * ---
+             * 0 X
+             */
+            if (rem)
+                *rem = n.s.low % d.s.low;
+            return n.s.low / d.s.low;
+        }
+        /* 0 X
+         * ---
+         * K X
+         */
+        if (rem)
+            *rem = n.s.low;
+        return 0;
+    }
+    /* n.s.high != 0 */
+    if (d.s.low == 0)
+    {
+        if (d.s.high == 0)
+        {
+            /* K X
+             * ---
+             * 0 0
+             */
+            if (rem)
+                *rem = n.s.high % d.s.low;
+            return n.s.high / d.s.low;
+        }
+        /* d.s.high != 0 */
+        if (n.s.low == 0)
+        {
+            /* K 0
+             * ---
+             * K 0
+             */
+            if (rem)
+            {
+                r.s.high = n.s.high % d.s.high;
+                r.s.low = 0;
+                *rem = r.all;
+            }
+            return n.s.high / d.s.high;
+        }
+        /* K K
+         * ---
+         * K 0
+         */
+        if ((d.s.high & (d.s.high - 1)) == 0)     /* if d is a power of 2 */
+        {
+            if (rem)
+            {
+                r.s.low = n.s.low;
+                r.s.high = n.s.high & (d.s.high - 1);
+                *rem = r.all;
+            }
+            return n.s.high >> __builtin_ctz(d.s.high);
+        }
+        /* K K
+         * ---
+         * K 0
+         */
+        sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
+        /* 0 <= sr <= n_uword_bits - 2 or sr large */
+        if (sr > n_uword_bits - 2)
+        {
+           if (rem)
+                *rem = n.all;
+            return 0;
+        }
+        ++sr;
+        /* 1 <= sr <= n_uword_bits - 1 */
+        /* q.all = n.all << (n_udword_bits - sr); */
+        q.s.low = 0;
+        q.s.high = n.s.low << (n_uword_bits - sr);
+        /* r.all = n.all >> sr; */
+        r.s.high = n.s.high >> sr;
+        r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+    }
+    else  /* d.s.low != 0 */
+    {
+        if (d.s.high == 0)
+        {
+            /* K X
+             * ---
+             * 0 K
+             */
+            if ((d.s.low & (d.s.low - 1)) == 0)     /* if d is a power of 2 */
+            {
+                if (rem)
+                    *rem = n.s.low & (d.s.low - 1);
+                if (d.s.low == 1)
+                    return n.all;
+                sr = __builtin_ctz(d.s.low);
+                q.s.high = n.s.high >> sr;
+                q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+                return q.all;
+            }
+            /* K X
+             * ---
+             * 0 K
+             */
+            sr = 1 + n_uword_bits + __builtin_clz(d.s.low) - __builtin_clz(n.s.high);
+            /* 2 <= sr <= n_udword_bits - 1
+             * q.all = n.all << (n_udword_bits - sr);
+             * r.all = n.all >> sr;
+             */
+            if (sr == n_uword_bits)
+            {
+                q.s.low = 0;
+                q.s.high = n.s.low;
+                r.s.high = 0;
+                r.s.low = n.s.high;
+            }
+            else if (sr < n_uword_bits)  // 2 <= sr <= n_uword_bits - 1
+            {
+                q.s.low = 0;
+                q.s.high = n.s.low << (n_uword_bits - sr);
+                r.s.high = n.s.high >> sr;
+                r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+            }
+            else              // n_uword_bits + 1 <= sr <= n_udword_bits - 1
+            {
+                q.s.low = n.s.low << (n_udword_bits - sr);
+                q.s.high = (n.s.high << (n_udword_bits - sr)) |
+                           (n.s.low >> (sr - n_uword_bits));
+                r.s.high = 0;
+                r.s.low = n.s.high >> (sr - n_uword_bits);
+            }
+        }
+        else
+        {
+            /* K X
+             * ---
+             * K K
+             */
+            sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
+            /* 0 <= sr <= n_uword_bits - 1 or sr large */
+            if (sr > n_uword_bits - 1)
+            {
+                if (rem)
+                    *rem = n.all;
+                return 0;
+            }
+            ++sr;
+            /* 1 <= sr <= n_uword_bits */
+            /*  q.all = n.all << (n_udword_bits - sr); */
+            q.s.low = 0;
+            if (sr == n_uword_bits)
+            {
+                q.s.high = n.s.low;
+                r.s.high = 0;
+                r.s.low = n.s.high;
+            }
+            else
+            {
+                q.s.high = n.s.low << (n_uword_bits - sr);
+                r.s.high = n.s.high >> sr;
+                r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+            }
+        }
+    }
+    /* Not a special case
+     * q and r are initialized with:
+     * q.all = n.all << (n_udword_bits - sr);
+     * r.all = n.all >> sr;
+     * 1 <= sr <= n_udword_bits - 1
+     */
+    su_int carry = 0;
+    for (; sr > 0; --sr)
+    {
+        /* r:q = ((r:q)  << 1) | carry */
+        r.s.high = (r.s.high << 1) | (r.s.low  >> (n_uword_bits - 1));
+        r.s.low  = (r.s.low  << 1) | (q.s.high >> (n_uword_bits - 1));
+        q.s.high = (q.s.high << 1) | (q.s.low  >> (n_uword_bits - 1));
+        q.s.low  = (q.s.low  << 1) | carry;
+        /* carry = 0;
+         * if (r.all >= d.all)
+         * {
+         *      r.all -= d.all;
+         *      carry = 1;
+         * }
+         */
+        const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1);
+        carry = s & 1;
+        r.all -= d.all & s;
+    }
+    q.all = (q.all << 1) | carry;
+    if (rem)
+        *rem = r.all;
+    return q.all;
+}
+
+/* Returns: a % b */
+
+COMPILER_RT_ABI du_int
+__umoddi3(du_int a, du_int b)
+{
+    du_int r;
+    __udivmoddi4(a, b, &r);
+    return r;
+}
 
 // Returns: the number of leading 0-bits
 
diff --git a/scripts/riscv64-mycpu.mk b/scripts/riscv64-mycpu.mk
index 8da161b..2a0780d 100644
--- a/scripts/riscv64-mycpu.mk
+++ b/scripts/riscv64-mycpu.mk
@@ -6,6 +6,8 @@ LDFLAGS       += -melf64lriscv
 
 AM_SRCS := mycpu/start.S \
            mycpu/trm.c \
+           mycpu/libgcc/muldi3.S \
+           mycpu/libgcc/div.S \
            mycpu/ioe.c \
            mycpu/timer.c \
            mycpu/input.c

From 01d76dd0d56b00400cdeb89636a95d8a7ee6f0bf Mon Sep 17 00:00:00 2001
From: Zihao Yu <yuzihao@ict.ac.cn>
Date: Tue, 13 Jul 2021 16:59:47 +0800
Subject: [PATCH 4/4] riscv64-mycpu: pass compilation of am-tests

---
 am/include/arch/riscv64-mycpu.h | 16 +++++++++++
 am/src/mycpu/cte.c              | 45 +++++++++++++++++++++++++++++
 am/src/mycpu/mpe.c              | 17 +++++++++++
 am/src/mycpu/trap.S             | 51 +++++++++++++++++++++++++++++++++
 am/src/mycpu/vme.c              | 18 ++++++++++++
 scripts/riscv64-mycpu.mk        |  6 +++-
 6 files changed, 152 insertions(+), 1 deletion(-)
 create mode 100644 am/src/mycpu/cte.c
 create mode 100644 am/src/mycpu/mpe.c
 create mode 100644 am/src/mycpu/trap.S
 create mode 100644 am/src/mycpu/vme.c

diff --git a/am/include/arch/riscv64-mycpu.h b/am/include/arch/riscv64-mycpu.h
index e69de29..5c75646 100644
--- a/am/include/arch/riscv64-mycpu.h
+++ b/am/include/arch/riscv64-mycpu.h
@@ -0,0 +1,16 @@
+#ifndef ARCH_H__
+#define ARCH_H__
+
+struct Context {
+  // TODO: fix the order of these members to match trap.S
+  uintptr_t epc, cause, gpr[32], status;
+};
+
+#define GPR1 gpr[0]
+#define GPR2 gpr[0]
+#define GPR3 gpr[0]
+#define GPR4 gpr[0]
+#define GPRx gpr[0]
+
+#endif
+
diff --git a/am/src/mycpu/cte.c b/am/src/mycpu/cte.c
new file mode 100644
index 0000000..b94083f
--- /dev/null
+++ b/am/src/mycpu/cte.c
@@ -0,0 +1,45 @@
+#include <am.h>
+#include <klib.h>
+
+static Context* (*user_handler)(Event, Context*) = NULL;
+
+Context* __am_irq_handle(Context *c) {
+  if (user_handler) {
+    Event ev = {0};
+    switch (c->cause) {
+      default: ev.event = EVENT_ERROR; break;
+    }
+
+    c = user_handler(ev, c);
+    assert(c != NULL);
+  }
+
+  return c;
+}
+
+extern void __am_asm_trap(void);
+
+bool cte_init(Context*(*handler)(Event, Context*)) {
+  // initialize exception entry
+  asm volatile("csrw mtvec, %0" : : "r"(__am_asm_trap));
+
+  // register event handler
+  user_handler = handler;
+
+  return true;
+}
+
+Context *kcontext(Area kstack, void (*entry)(void *), void *arg) {
+  return NULL;
+}
+
+void yield() {
+  asm volatile("li a7, -1; ecall");
+}
+
+bool ienabled() {
+  return false;
+}
+
+void iset(bool enable) {
+}
diff --git a/am/src/mycpu/mpe.c b/am/src/mycpu/mpe.c
new file mode 100644
index 0000000..6715aa2
--- /dev/null
+++ b/am/src/mycpu/mpe.c
@@ -0,0 +1,17 @@
+#include <am.h>
+
+bool mpe_init(void (*entry)()) {
+  return false;
+}
+
+int cpu_count() {
+  return 1;
+}
+
+int cpu_current() {
+  return 0;
+}
+
+int atomic_xchg(int *addr, int newval) {
+  return 0;
+}
diff --git a/am/src/mycpu/trap.S b/am/src/mycpu/trap.S
new file mode 100644
index 0000000..bc64c53
--- /dev/null
+++ b/am/src/mycpu/trap.S
@@ -0,0 +1,51 @@
+
+#define concat_temp(x, y) x ## y
+#define concat(x, y) concat_temp(x, y)
+#define MAP(c, f) c(f)
+
+#define REGS(f) \
+      f( 1)       f( 3) f( 4) f( 5) f( 6) f( 7) f( 8) f( 9) \
+f(10) f(11) f(12) f(13) f(14) f(15) f(16) f(17) f(18) f(19) \
+f(20) f(21) f(22) f(23) f(24) f(25) f(26) f(27) f(28) f(29) \
+f(30) f(31)
+
+#define PUSH(n) sd concat(x, n), (n * 8)(sp);
+#define POP(n)  ld concat(x, n), (n * 8)(sp);
+
+#define CONTEXT_SIZE ((32 + 3) * 8)
+#define OFFSET_SP     ( 2 * 8)
+#define OFFSET_CAUSE  (32 * 8)
+#define OFFSET_STATUS (33 * 8)
+#define OFFSET_EPC    (34 * 8)
+
+.globl __am_asm_trap
+__am_asm_trap:
+  addi sp, sp, -CONTEXT_SIZE
+
+  MAP(REGS, PUSH)
+
+  mv t0, sp
+  addi t0, t0, CONTEXT_SIZE
+  sd t0, OFFSET_SP(sp)
+
+  csrr t0, mcause
+  csrr t1, mstatus
+  csrr t2, mepc
+
+  sd t0, OFFSET_CAUSE(sp)
+  sd t1, OFFSET_STATUS(sp)
+  sd t2, OFFSET_EPC(sp)
+
+  mv a0, sp
+  jal __am_irq_handle
+
+  ld t1, OFFSET_STATUS(sp)
+  ld t2, OFFSET_EPC(sp)
+  csrw mstatus, t1
+  csrw mepc, t2
+
+  MAP(REGS, POP)
+
+  addi sp, sp, CONTEXT_SIZE
+
+  mret
diff --git a/am/src/mycpu/vme.c b/am/src/mycpu/vme.c
new file mode 100644
index 0000000..5134154
--- /dev/null
+++ b/am/src/mycpu/vme.c
@@ -0,0 +1,18 @@
+#include <am.h>
+
+bool vme_init(void* (*pgalloc_f)(int), void (*pgfree_f)(void*)) {
+  return false;
+}
+
+void protect(AddrSpace *as) {
+}
+
+void unprotect(AddrSpace *as) {
+}
+
+void map(AddrSpace *as, void *va, void *pa, int prot) {
+}
+
+Context *ucontext(AddrSpace *as, Area kstack, void *entry) {
+  return NULL;
+}
diff --git a/scripts/riscv64-mycpu.mk b/scripts/riscv64-mycpu.mk
index 2a0780d..92a553f 100644
--- a/scripts/riscv64-mycpu.mk
+++ b/scripts/riscv64-mycpu.mk
@@ -10,7 +10,11 @@ AM_SRCS := mycpu/start.S \
            mycpu/libgcc/div.S \
            mycpu/ioe.c \
            mycpu/timer.c \
-           mycpu/input.c
+           mycpu/input.c \
+           mycpu/cte.c \
+           mycpu/trap.S \
+           mycpu/vme.c \
+           mycpu/mpe.c
 
 CFLAGS    += -fdata-sections -ffunction-sections
 LDFLAGS   += -T $(AM_HOME)/scripts/platform/nemu.ld --defsym=_pmem_start=0x80000000 --defsym=_entry_offset=0x0