This patch implements the setjmp/longjmp, memcpy, memmove, memset and mempcpy functions
authorchandramouli narayanan <mouli@linux.intel.com>
Mon, 25 Jun 2012 19:34:46 +0000 (12:34 -0700)
committerchandramouli narayanan <mouli@linux.intel.com>
Mon, 25 Jun 2012 19:34:46 +0000 (12:34 -0700)
as appropriate for the architecture. The code came from klibc. com32/lib has
i386 and x86_64 sub directories implementing the code.

The code in com32/lib/libgcc/__muldi3.S essentially has fixes for building x86_64.

The file x86_init_fpu.c is split into the respective architecture specific files and
reside under com32/lib/sys/i386 and com32/lib/sys/x86_64.

The file com32/lib/sys/farcall.c has fixes for architecture-specific code. The com32 lib
dependends on it.

Remanants of the unused old i386-only files, if any, need to be pruned.

12 files changed:
com32/lib/i386/setjmp.S [new file with mode: 0644]
com32/lib/libgcc/__muldi3.S
com32/lib/memcpy.c [new file with mode: 0644]
com32/lib/memmove.c [new file with mode: 0644]
com32/lib/mempcpy.c [new file with mode: 0644]
com32/lib/memset.c [new file with mode: 0644]
com32/lib/setjmp.S
com32/lib/sys/farcall.c
com32/lib/sys/i386/x86_init_fpu.c [new file with mode: 0644]
com32/lib/sys/x86_64/x86_init_fpu.c [new file with mode: 0644]
com32/lib/sys/x86_init_fpu.c
com32/lib/x86_64/setjmp.S [new file with mode: 0644]

diff --git a/com32/lib/i386/setjmp.S b/com32/lib/i386/setjmp.S
new file mode 100644 (file)
index 0000000..658df48
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * arch/i386/setjmp.S
+ *
+ * setjmp/longjmp for the i386 architecture
+ *
+ *
+ *
+ * The jmp_buf is assumed to contain the following, in order:
+ *     %ebx
+ *     %esp
+ *     %ebp
+ *     %esi
+ *     %edi
+ *     <return address>
+ */
+
+       .text
+       .align 4
+
+       .globl _setjmp
+       .type _setjmp, @function
+_setjmp:                               # gcc 4.0.1 wants this as an alias?
+
+       .globl setjmp
+       .type setjmp, @function
+setjmp:
+#ifdef REGPARM
+       movl %eax,%edx
+#else
+       movl 4(%esp),%edx
+#endif
+       popl %ecx                       # Return address, and adjust the stack
+       xorl %eax,%eax                  # Return value
+       movl %ebx,(%edx)
+       movl %esp,4(%edx)               # Post-return %esp!
+       pushl %ecx                      # Make the call/return stack happy
+       movl %ebp,8(%edx)
+       movl %esi,12(%edx)
+       movl %edi,16(%edx)
+       movl %ecx,20(%edx)              # Return address
+       ret
+
+       .size setjmp,.-setjmp
+
+       .text
+       .align 4
+       .globl longjmp
+       .type longjmp, @function
+longjmp:
+#ifdef REGPARM
+       xchgl %eax,%edx
+#else
+       movl 4(%esp),%edx               # jmp_ptr address
+       movl 8(%esp),%eax               # Return value
+#endif
+       movl (%edx),%ebx
+       movl 4(%edx),%esp
+       movl 8(%edx),%ebp
+       movl 12(%edx),%esi
+       movl 16(%edx),%edi
+       jmp *20(%edx)
+
+       .size longjmp,.-longjmp
index 648a88a..424787c 100644 (file)
@@ -9,6 +9,8 @@
        .globl __muldi3
        .type __muldi3,@function
 __muldi3:
+#if __SIZEOF_POINTER__ == 4
+       /* i386 */
        push  %esi
 #ifndef REGPARM
        movl  8(%esp),%eax
@@ -31,4 +33,51 @@ __muldi3:
 #endif
        pop   %esi
        ret
+#elif __SIZEOF_POINTER__ == 8
+       /* x86_64 */
+       push  %rsi
+#ifndef REGPARM
+/*
+       movl  8(%esp),%eax
+       movl %eax,%esi
+       movl  16(%esp),%ecx
+       mull  %ecx
+       imull 12(%esp),%ecx
+       imull 20(%esp),%esi
+       addl  %ecx,%edx
+       addl  %esi,%edx
+*/
+       movq  8(%rsp),%rax
+       movq %rax,%rsi
+       movq  16(%rsp),%rcx
+       mulq  %rcx
+       imulq 12(%rsp),%rcx
+       imulq 20(%rsp),%rsi
+       addq  %rcx,%rdx
+       addq  %rsi,%rdx
+#else
+/*
+       movl  %eax,%esi
+       push  %edx
+       mull  %ecx
+       imull 8(%esp),%esi
+       addl  %esi,%edx
+       pop   %rsi
+       imull %esi,%ecx
+       addl  %ecx,%edx
+*/
+       movq  %rax,%rsi
+       pushq  %rdx
+       mulq  %rcx
+       imulq 8(%rsp),%rsi
+       addq  %rsi,%rdx
+       popq  %rsi
+       imulq %rsi,%rcx
+       addq  %rcx,%rdx
+#endif
+       pop   %rsi
+       ret
+#else
+#error "Unsupported architecture for __muldi3.S"
+#endif
        .size __muldi3,.-__muldi3
diff --git a/com32/lib/memcpy.c b/com32/lib/memcpy.c
new file mode 100644 (file)
index 0000000..5ce206d
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * memcpy.c
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+void *memcpy(void *dst, const void *src, size_t n)
+{
+       const char *p = src;
+       char *q = dst;
+#if defined(__i386__)
+       size_t nl = n >> 2;
+       asm volatile ("cld ; rep ; movsl ; movl %3,%0 ; rep ; movsb":"+c" (nl),
+                     "+S"(p), "+D"(q)
+                     :"r"(n & 3));
+#elif defined(__x86_64__)
+       size_t nq = n >> 3;
+       asm volatile ("cld ; rep ; movsq ; movl %3,%%ecx ; rep ; movsb":"+c"
+                     (nq), "+S"(p), "+D"(q)
+                     :"r"((uint32_t) (n & 7)));
+#else
+       while (n--) {
+               *q++ = *p++;
+       }
+#endif
+
+       return dst;
+}
diff --git a/com32/lib/memmove.c b/com32/lib/memmove.c
new file mode 100644 (file)
index 0000000..a398cd8
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * memmove.c
+ */
+
+#include <string.h>
+
+void *memmove(void *dst, const void *src, size_t n)
+{
+       const char *p = src;
+       char *q = dst;
+#if defined(__i386__) || defined(__x86_64__)
+       if (q < p) {
+               asm volatile("cld; rep; movsb"
+                            : "+c" (n), "+S"(p), "+D"(q));
+       } else {
+               p += (n - 1);
+               q += (n - 1);
+               asm volatile("std; rep; movsb; cld"
+                            : "+c" (n), "+S"(p), "+D"(q));
+       }
+#else
+       if (q < p) {
+               while (n--) {
+                       *q++ = *p++;
+               }
+       } else {
+               p += n;
+               q += n;
+               while (n--) {
+                       *--q = *--p;
+               }
+       }
+#endif
+
+       return dst;
+}
diff --git a/com32/lib/mempcpy.c b/com32/lib/mempcpy.c
new file mode 100644 (file)
index 0000000..be23b66
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * mempcpy.c
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+/* simply a wrapper around memcpy implementation */
+
+void *mempcpy(void *dst, const void *src, size_t n)
+{
+
+       return (char *)memcpy(dst, src, n) + n;
+}
diff --git a/com32/lib/memset.c b/com32/lib/memset.c
new file mode 100644 (file)
index 0000000..aa00b5b
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * memset.c
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+void *memset(void *dst, int c, size_t n)
+{
+       char *q = dst;
+
+#if defined(__i386__)
+       size_t nl = n >> 2;
+       asm volatile ("cld ; rep ; stosl ; movl %3,%0 ; rep ; stosb"
+                     : "+c" (nl), "+D" (q)
+                     : "a" ((unsigned char)c * 0x01010101U), "r" (n & 3));
+#elif defined(__x86_64__)
+       size_t nq = n >> 3;
+       asm volatile ("cld ; rep ; stosq ; movl %3,%%ecx ; rep ; stosb"
+                     :"+c" (nq), "+D" (q)
+                     : "a" ((unsigned char)c * 0x0101010101010101U),
+                       "r" ((uint32_t) n & 7));
+#else
+       while (n--) {
+               *q++ = c;
+       }
+#endif
+
+       return dst;
+}
index 658df48..2fb5c23 100644 (file)
@@ -13,7 +13,7 @@
  *     %edi
  *     <return address>
  */
-
+/*
        .text
        .align 4
 
@@ -61,3 +61,12 @@ longjmp:
        jmp *20(%edx)
 
        .size longjmp,.-longjmp
+*/
+#if __SIZEOF_POINTER__ == 4
+#include <i386/setjmp.S>
+#elif __SIZEOF_POINTER__ == 8
+#include <x86_64/setjmp.S>
+#else
+#error "Unable to build for to-be-defined architecture type"
+#endif
+
index 988ee6d..2749083 100644 (file)
@@ -6,9 +6,17 @@
 
 static inline uint32_t eflags(void)
 {
-    uint32_t v;
+    //uint32_t v;
 
+#if __SIZEOF_POINTER__ == 4
+    uint32_t v;
     asm volatile("pushfl ; popl %0" : "=rm" (v));
+#elif __SIZEOF_POINTER__ == 8
+    uint64_t v;
+    asm volatile("pushfq ; pop %0" : "=rm" (v));
+#else
+#error "Unable to build for to-be-defined architecture type"
+#endif
     return v;
 }
 
diff --git a/com32/lib/sys/i386/x86_init_fpu.c b/com32/lib/sys/i386/x86_init_fpu.c
new file mode 100644 (file)
index 0000000..cf33693
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * x86_has_fpu.c
+ *
+ * Test for an x86 FPU, and do any necessary setup.
+ */
+
+#include <inttypes.h>
+#include <sys/fpu.h>
+
+static inline uint64_t get_cr0(void)
+{
+    uint32_t v;
+asm("movl %%cr0,%0":"=r"(v));
+    return v;
+}
+
+static inline void set_cr0(uint32_t v)
+{
+    asm volatile ("movl %0,%%cr0"::"r" (v));
+}
+
+#define CR0_PE 0x00000001
+#define CR0_MP  0x00000002
+#define CR0_EM  0x00000004
+#define CR0_TS  0x00000008
+#define CR0_ET  0x00000010
+#define CR0_NE  0x00000020
+#define CR0_WP  0x00010000
+#define CR0_AM  0x00040000
+#define CR0_NW  0x20000000
+#define CR0_CD  0x40000000
+#define CR0_PG  0x80000000
+
+int x86_init_fpu(void)
+{
+    uint32_t cr0;
+    uint16_t fsw = 0xffff;
+    uint16_t fcw = 0xffff;
+
+    cr0 = get_cr0();
+    cr0 &= ~(CR0_EM | CR0_TS);
+    cr0 |= CR0_MP;
+    set_cr0(cr0);
+
+    asm volatile ("fninit");
+    asm volatile ("fnstsw %0":"+m" (fsw));
+    if (fsw != 0)
+       return -1;
+
+    asm volatile ("fnstcw %0":"+m" (fcw));
+    if ((fcw & 0x103f) != 0x3f)
+       return -1;
+
+    /* Techically, this could be a 386 with a 287.  We could add a check
+       for that here... */
+
+    return 0;
+}
diff --git a/com32/lib/sys/x86_64/x86_init_fpu.c b/com32/lib/sys/x86_64/x86_init_fpu.c
new file mode 100644 (file)
index 0000000..c5d3946
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * x86_has_fpu.c
+ *
+ * Test for an x86 FPU, and do any necessary setup.
+ */
+
+#include <inttypes.h>
+#include <sys/fpu.h>
+
+static inline uint64_t get_cr0(void)
+{
+    uint64_t v;
+asm("movq %%cr0,%0":"=r"(v));
+    return v;
+}
+
+static inline void set_cr0(uint32_t v)
+{
+    asm volatile ("movq %0,%%cr0"::"r" ((uint64_t)v));
+}
+
+#define CR0_PE 0x00000001
+#define CR0_MP  0x00000002
+#define CR0_EM  0x00000004
+#define CR0_TS  0x00000008
+#define CR0_ET  0x00000010
+#define CR0_NE  0x00000020
+#define CR0_WP  0x00010000
+#define CR0_AM  0x00040000
+#define CR0_NW  0x20000000
+#define CR0_CD  0x40000000
+#define CR0_PG  0x80000000
+
+int x86_init_fpu(void)
+{
+    uint32_t cr0;
+    uint16_t fsw = 0xffff;
+    uint16_t fcw = 0xffff;
+
+    cr0 = get_cr0();
+    cr0 &= ~(CR0_EM | CR0_TS);
+    cr0 |= CR0_MP;
+    set_cr0(cr0);
+
+    asm volatile ("fninit");
+    asm volatile ("fnstsw %0":"+m" (fsw));
+    if (fsw != 0)
+       return -1;
+
+    asm volatile ("fnstcw %0":"+m" (fcw));
+    if ((fcw & 0x103f) != 0x3f)
+       return -1;
+
+    /* Techically, this could be a 386 with a 287.  We could add a check
+       for that here... */
+
+    return 0;
+}
index cf33693..cacb4ea 100644 (file)
@@ -4,19 +4,40 @@
  * Test for an x86 FPU, and do any necessary setup.
  */
 
+#if __SIZEOF_POINTER__ == 4
+#include <i386/x86_init_fpu.c>
+#elif __SIZEOF_POINTER__ == 8
+#include <x86_64/x86_init_fpu.c>
+#else
+#error "Unable to build for to-be-defined architecture type"
+#endif
+#if 0
 #include <inttypes.h>
 #include <sys/fpu.h>
 
 static inline uint64_t get_cr0(void)
 {
+#if __SIZEOF_POINTER__ == 4
     uint32_t v;
 asm("movl %%cr0,%0":"=r"(v));
+#elif __SIZEOF_POINTER__ == 8
+    uint64_t v;
+asm("movq %%cr0,%0":"=r"(v));
+#else
+#error "Unable to build for to-be-defined architecture type"
+#endif
     return v;
 }
 
 static inline void set_cr0(uint32_t v)
 {
+#if __SIZEOF_POINTER__ == 4
     asm volatile ("movl %0,%%cr0"::"r" (v));
+#elif __SIZEOF_POINTER__ == 8
+    asm volatile ("movq %0,%%cr0"::"r" ((uint64_t)v));
+#else
+#error "Unable to build for to-be-defined architecture type"
+#endif
 }
 
 #define CR0_PE 0x00000001
@@ -56,3 +77,4 @@ int x86_init_fpu(void)
 
     return 0;
 }
+#endif
diff --git a/com32/lib/x86_64/setjmp.S b/com32/lib/x86_64/setjmp.S
new file mode 100644 (file)
index 0000000..45f547b
--- /dev/null
@@ -0,0 +1,54 @@
+#
+# arch/x86_64/setjmp.S
+#
+# setjmp/longjmp for the x86-64 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+#      %rbx
+#      %rsp (post-return)
+#      %rbp
+#      %r12
+#      %r13
+#      %r14
+#      %r15
+#      <return address>
+#
+
+       .text
+       .align 4
+       .globl setjmp
+       .type setjmp, @function
+setjmp:
+       pop  %rsi                       # Return address, and adjust the stack
+       xorl %eax,%eax                  # Return value
+       movq %rbx,(%rdi)
+       movq %rsp,8(%rdi)               # Post-return %rsp!
+       push %rsi                       # Make the call/return stack happy
+       movq %rbp,16(%rdi)
+       movq %r12,24(%rdi)
+       movq %r13,32(%rdi)
+       movq %r14,40(%rdi)
+       movq %r15,48(%rdi)
+       movq %rsi,56(%rdi)              # Return address
+       ret
+
+       .size setjmp,.-setjmp
+
+       .text
+       .align 4
+       .globl longjmp
+       .type longjmp, @function
+longjmp:
+       movl %esi,%eax                  # Return value (int)
+       movq (%rdi),%rbx
+       movq 8(%rdi),%rsp
+       movq 16(%rdi),%rbp
+       movq 24(%rdi),%r12
+       movq 32(%rdi),%r13
+       movq 40(%rdi),%r14
+       movq 48(%rdi),%r15
+       jmp *56(%rdi)
+
+       .size longjmp,.-longjmp