From 80d960579ce7e35f377a16b94b10505115adaf59 Mon Sep 17 00:00:00 2001
From: Recolic Keghart <root@recolic.net>
Date: Sun, 29 Dec 2019 02:03:11 +0800
Subject: [PATCH] >  Manual commit:  adjust scripts, implement libc::string
 U201614531 recolic Linux RECOLICPC 5.4.6-arch3-1 #1 SMP PREEMPT Tue, 24 Dec
 2019 04:36:53 +0000 x86_64 GNU/Linux  02:03:11 up  7:37,  1 user,  load
 average: 0.74, 0.61, 0.60 71103d2658dd78e677d785455f2d01a825c61e0e

---
 .gitlab-ci.yml                  |   2 +-
 nemu/runall.sh                  |   2 +-
 nexus-am/libs/klib/src/string.c | 472 ++++++++++++++++++++++++++++++--
 3 files changed, 456 insertions(+), 20 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3ba3997..4abebf8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -6,7 +6,7 @@ stages:
 build:
     stage: build
     script: 
-        - pacman -Sy && pacman -S --noconfirm bison flex gcc make gettext sdl2 lib32-glibc
+        - pacman -Sy && pacman -S --noconfirm bison flex gcc make gettext sdl2 lib32-glibc grep
         - export AM_HOME=$(pwd)/nexus-am/
         - cd nemu && make && show_log=1 ./runall.sh
 
diff --git a/nemu/runall.sh b/nemu/runall.sh
index 60c4a90..dcc05bd 100755
--- a/nemu/runall.sh
+++ b/nemu/runall.sh
@@ -43,7 +43,7 @@ for file in $files; do
       echo -e "\n\n===== the original log.txt =====\n" >> $logfile
       cat $ori_log >> $logfile
     fi
-    grep 'HIT GOOD TRAP' $logfile > /dev/null || head -n 512 $logfile >> $g_logfile
+    head -n 512 $logfile >> $g_logfile
   fi
   rm -f $logfile
 done
diff --git a/nexus-am/libs/klib/src/string.c b/nexus-am/libs/klib/src/string.c
index e02e2e8..5ac69f9 100644
--- a/nexus-am/libs/klib/src/string.c
+++ b/nexus-am/libs/klib/src/string.c
@@ -1,41 +1,477 @@
+/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
 #include "klib.h"
 
 #if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)
 
-size_t strlen(const char *s) {
-  return 0;
+static void abort() {
+    /* Simulate an C abort. */
+    assert(0);
+}
+
+/* Return the length of the null-terminated string STR.  Scan for
+   the null terminator quickly by testing four bytes at a time.  */
+size_t
+strlen (const char *str)
+{
+  const char *char_ptr;
+  const unsigned long int *longword_ptr;
+  unsigned long int longword, himagic, lomagic;
+
+  /* Handle the first few characters by reading one character at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = str; ((unsigned long int) char_ptr
+			& (sizeof (longword) - 1)) != 0;
+       ++char_ptr)
+    if (*char_ptr == '\0')
+      return char_ptr - str;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to 8-byte longwords.  */
+
+  longword_ptr = (unsigned long int *) char_ptr;
+
+  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
+     the "holes."  Note that there is a hole just to the left of
+     each byte, with an extra at the end:
+
+     bits:  01111110 11111110 11111110 11111111
+     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+     The 1-bits make sure that carries propagate to the next 0-bit.
+     The 0-bits provide holes for carries to fall into.  */
+  himagic = 0x80808080L;
+  lomagic = 0x01010101L;
+  if (sizeof (longword) > 4)
+    {
+      /* 64-bit version of the magic.  */
+      /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
+      himagic = ((himagic << 16) << 16) | himagic;
+      lomagic = ((lomagic << 16) << 16) | lomagic;
+    }
+  if (sizeof (longword) > 8)
+    abort ();
+
+  /* Instead of the traditional loop which tests each character,
+     we will test a longword at a time.  The tricky part is testing
+     if *any of the four* bytes in the longword in question are zero.  */
+  for (;;)
+    {
+      longword = *longword_ptr++;
+
+      if (((longword - lomagic) & ~longword & himagic) != 0)
+	{
+	  /* Which of the bytes was the zero?  If none of them were, it was
+	     a misfire; continue the search.  */
+
+	  const char *cp = (const char *) (longword_ptr - 1);
+
+	  if (cp[0] == 0)
+	    return cp - str;
+	  if (cp[1] == 0)
+	    return cp - str + 1;
+	  if (cp[2] == 0)
+	    return cp - str + 2;
+	  if (cp[3] == 0)
+	    return cp - str + 3;
+	  if (sizeof (longword) > 4)
+	    {
+	      if (cp[4] == 0)
+		return cp - str + 4;
+	      if (cp[5] == 0)
+		return cp - str + 5;
+	      if (cp[6] == 0)
+		return cp - str + 6;
+	      if (cp[7] == 0)
+		return cp - str + 7;
+	    }
+	}
+    }
+}
+
+/* Copy SRC to DEST.  */
+char *
+strcpy (char *dest, const char *src)
+{
+  return memcpy (dest, src, strlen (src) + 1);
 }
 
-char *strcpy(char* dst,const char* src) {
-  return NULL;
+size_t
+__strnlen (const char *str, size_t maxlen)
+{
+  const char *char_ptr, *end_ptr = str + maxlen;
+  const unsigned long int *longword_ptr;
+  unsigned long int longword, himagic, lomagic;
+
+  if (maxlen == 0)
+    return 0;
+
+  if (__glibc_unlikely (end_ptr < str))
+    end_ptr = (const char *) ~0UL;
+
+  /* Handle the first few characters by reading one character at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = str; ((unsigned long int) char_ptr
+			& (sizeof (longword) - 1)) != 0;
+       ++char_ptr)
+    if (*char_ptr == '\0')
+      {
+	if (char_ptr > end_ptr)
+	  char_ptr = end_ptr;
+	return char_ptr - str;
+      }
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to 8-byte longwords.  */
+
+  longword_ptr = (unsigned long int *) char_ptr;
+
+  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
+     the "holes."  Note that there is a hole just to the left of
+     each byte, with an extra at the end:
+
+     bits:  01111110 11111110 11111110 11111111
+     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+     The 1-bits make sure that carries propagate to the next 0-bit.
+     The 0-bits provide holes for carries to fall into.  */
+  himagic = 0x80808080L;
+  lomagic = 0x01010101L;
+  if (sizeof (longword) > 4)
+    {
+      /* 64-bit version of the magic.  */
+      /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
+      himagic = ((himagic << 16) << 16) | himagic;
+      lomagic = ((lomagic << 16) << 16) | lomagic;
+    }
+  if (sizeof (longword) > 8)
+    abort ();
+
+  /* Instead of the traditional loop which tests each character,
+     we will test a longword at a time.  The tricky part is testing
+     if *any of the four* bytes in the longword in question are zero.  */
+  while (longword_ptr < (unsigned long int *) end_ptr)
+    {
+      /* We tentatively exit the loop if adding MAGIC_BITS to
+	 LONGWORD fails to change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.  If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-30 is set, there will be a carry
+	 into bit 31, so all of the hole bits will be changed.
+
+	 The one misfire occurs when bits 24-30 are clear and bit
+	 31 is set; in this case, the hole at bit 31 is not
+	 changed.  If we had access to the processor carry flag,
+	 we could close this loophole by putting the fourth hole
+	 at bit 32!
+
+	 So it ignores everything except 128's, when they're aligned
+	 properly.  */
+
+      longword = *longword_ptr++;
+
+      if ((longword - lomagic) & himagic)
+	{
+	  /* Which of the bytes was the zero?  If none of them were, it was
+	     a misfire; continue the search.  */
+
+	  const char *cp = (const char *) (longword_ptr - 1);
+
+	  char_ptr = cp;
+	  if (cp[0] == 0)
+	    break;
+	  char_ptr = cp + 1;
+	  if (cp[1] == 0)
+	    break;
+	  char_ptr = cp + 2;
+	  if (cp[2] == 0)
+	    break;
+	  char_ptr = cp + 3;
+	  if (cp[3] == 0)
+	    break;
+	  if (sizeof (longword) > 4)
+	    {
+	      char_ptr = cp + 4;
+	      if (cp[4] == 0)
+		break;
+	      char_ptr = cp + 5;
+	      if (cp[5] == 0)
+		break;
+	      char_ptr = cp + 6;
+	      if (cp[6] == 0)
+		break;
+	      char_ptr = cp + 7;
+	      if (cp[7] == 0)
+		break;
+	    }
+	}
+      char_ptr = end_ptr;
+    }
+
+  if (char_ptr > end_ptr)
+    char_ptr = end_ptr;
+  return char_ptr - str;
 }
 
-char* strncpy(char* dst, const char* src, size_t n) {
-  return NULL;
+
+char *
+strncpy (char *s1, const char *s2, size_t n)
+{
+  size_t size = __strnlen (s2, n);
+  if (size != n)
+    memset (s1 + size, '\0', n - size);
+  return memcpy (s1, s2, size);
 }
 
-char* strcat(char* dst, const char* src) {
-  return NULL;
+/* Append SRC on the end of DEST.  */
+char *
+strcat (char *dest, const char *src)
+{
+  strcpy (dest + strlen (dest), src);
+  return dest;
 }
 
-int strcmp(const char* s1, const char* s2) {
-  return 0;
+/* Compare S1 and S2, returning less than, equal to or
+   greater than zero if S1 is lexicographically less than,
+   equal to or greater than S2.  */
+int
+strcmp (const char *p1, const char *p2)
+{
+  const unsigned char *s1 = (const unsigned char *) p1;
+  const unsigned char *s2 = (const unsigned char *) p2;
+  unsigned char c1, c2;
+
+  do
+    {
+      c1 = (unsigned char) *s1++;
+      c2 = (unsigned char) *s2++;
+      if (c1 == '\0')
+	return c1 - c2;
+    }
+  while (c1 == c2);
+
+  return c1 - c2;
 }
 
-int strncmp(const char* s1, const char* s2, size_t n) {
-  return 0;
+/* Compare no more than N characters of S1 and S2,
+   returning less than, equal to or greater than zero
+   if S1 is lexicographically less than, equal to or
+   greater than S2.  */
+int
+strncmp (const char *s1, const char *s2, size_t n)
+{
+  unsigned char c1 = '\0';
+  unsigned char c2 = '\0';
+
+  if (n >= 4)
+    {
+      size_t n4 = n >> 2;
+      do
+	{
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	} while (--n4 > 0);
+      n &= 3;
+    }
+
+  while (n > 0)
+    {
+      c1 = (unsigned char) *s1++;
+      c2 = (unsigned char) *s2++;
+      if (c1 == '\0' || c1 != c2)
+	return c1 - c2;
+      n--;
+    }
+
+  return c1 - c2;
 }
 
-void* memset(void* v,int c,size_t n) {
-  return NULL;
+/* Recolic: mem op begin */
+
+/* Type to use for aligned memory operations.
+   This should normally be the biggest type supported by a single load
+   and store.  */
+#define op_t    unsigned long int
+#define OPSIZ   (sizeof (op_t))
+
+/* Type to use for unaligned operations.  */
+typedef unsigned char byte;
+
+void *
+/* inhibit_loop_to_libcall */
+memset (void *dstpp, int c, size_t len)
+{
+  long int dstp = (long int) dstpp;
+
+  if (len >= 8)
+    {
+      size_t xlen;
+      op_t cccc;
+
+      cccc = (unsigned char) c;
+      cccc |= cccc << 8;
+      cccc |= cccc << 16;
+      if (OPSIZ > 4)
+	/* Do the shift in two steps to avoid warning if long has 32 bits.  */
+	cccc |= (cccc << 16) << 16;
+
+      /* There are at least some bytes to set.
+	 No need to test for LEN == 0 in this alignment loop.  */
+      while (dstp % OPSIZ != 0)
+	{
+	  ((byte *) dstp)[0] = c;
+	  dstp += 1;
+	  len -= 1;
+	}
+
+      /* Write 8 `op_t' per iteration until less than 8 `op_t' remain.  */
+      xlen = len / (OPSIZ * 8);
+      while (xlen > 0)
+	{
+	  ((op_t *) dstp)[0] = cccc;
+	  ((op_t *) dstp)[1] = cccc;
+	  ((op_t *) dstp)[2] = cccc;
+	  ((op_t *) dstp)[3] = cccc;
+	  ((op_t *) dstp)[4] = cccc;
+	  ((op_t *) dstp)[5] = cccc;
+	  ((op_t *) dstp)[6] = cccc;
+	  ((op_t *) dstp)[7] = cccc;
+	  dstp += 8 * OPSIZ;
+	  xlen -= 1;
+	}
+      len %= OPSIZ * 8;
+
+      /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain.  */
+      xlen = len / OPSIZ;
+      while (xlen > 0)
+	{
+	  ((op_t *) dstp)[0] = cccc;
+	  dstp += OPSIZ;
+	  xlen -= 1;
+	}
+      len %= OPSIZ;
+    }
+
+  /* Write the last few bytes.  */
+  while (len > 0)
+    {
+      ((byte *) dstp)[0] = c;
+      dstp += 1;
+      len -= 1;
+    }
+
+  return dstpp;
 }
 
-void* memcpy(void* out, const void* in, size_t n) {
-  return NULL;
+/*
+////////////////////////////////////// glibc end ////////////////////////////////
+//
+///////////////////////////////////// uclibc-ng begin ///////////////////////////
+*/
+
+#ifdef WANT_WIDE
+#undef WANT_WIDE
+#endif
+
+typedef void Wvoid;
+typedef char Wchar;
+typedef char Wuchar;
+
+/*
+ * Copyright (C) 2002     Manuel Novoa III
+ * Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#ifdef WANT_WIDE
+# define Wmemcpy wmemcpy
+#else
+# undef memcpy
+# define Wmemcpy memcpy
+#endif
+
+Wvoid *Wmemcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n)
+{
+	register Wchar *r1 = s1;
+	register const Wchar *r2 = s2;
+
+	while (n) {
+		*r1++ = *r2++;
+		--n;
+	}
+
+	return s1;
 }
 
-int memcmp(const void* s1, const void* s2, size_t n){
-  return 0;
+#ifdef WANT_WIDE
+# define Wmemcmp wmemcmp
+#else
+# define Wmemcmp memcmp
+#endif
+
+int Wmemcmp(const Wvoid *s1, const Wvoid *s2, size_t n)
+{
+	register const Wuchar *r1 = (const Wuchar *) s1;
+	register const Wuchar *r2 = (const Wuchar *) s2;
+
+#ifdef WANT_WIDE
+	while (n && (*r1 == *r2)) {
+		++r1;
+		++r2;
+		--n;
+	}
+
+	return (n == 0) ? 0 : ((*r1 < *r2) ? -1 : 1);
+#else
+	int r = 0;
+
+	while (n-- && ((r = ((int)(*r1++)) - *r2++) == 0));
+
+	return r;
+#endif
 }
 
 #endif
-- 
GitLab