aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchandramouli narayanan <mouli@linux.intel.com>2012-06-25 12:34:46 -0700
committerchandramouli narayanan <mouli@linux.intel.com>2012-06-25 12:34:46 -0700
commit5caee9aeaf89dbbc45269737cc1dac7de070b867 (patch)
tree5284cfb67697c00d34cfca692e2da52f22e9716d
parentc53187e1adc326c3246917cb936cbab020b4d820 (diff)
downloadsyslinux-5caee9aeaf89dbbc45269737cc1dac7de070b867.tar.gz
syslinux-5caee9aeaf89dbbc45269737cc1dac7de070b867.tar.xz
syslinux-5caee9aeaf89dbbc45269737cc1dac7de070b867.zip
This patch implements the setjmp/longjmp, memcpy, memmove, memset and mempcpy functions
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.
-rw-r--r--com32/lib/i386/setjmp.S63
-rw-r--r--com32/lib/libgcc/__muldi3.S49
-rw-r--r--com32/lib/memcpy.c29
-rw-r--r--com32/lib/memmove.c36
-rw-r--r--com32/lib/mempcpy.c14
-rw-r--r--com32/lib/memset.c30
-rw-r--r--com32/lib/setjmp.S11
-rw-r--r--com32/lib/sys/farcall.c10
-rw-r--r--com32/lib/sys/i386/x86_init_fpu.c58
-rw-r--r--com32/lib/sys/x86_64/x86_init_fpu.c58
-rw-r--r--com32/lib/sys/x86_init_fpu.c22
-rw-r--r--com32/lib/x86_64/setjmp.S54
12 files changed, 432 insertions, 2 deletions
diff --git a/com32/lib/i386/setjmp.S b/com32/lib/i386/setjmp.S
new file mode 100644
index 00000000..658df485
--- /dev/null
+++ b/com32/lib/i386/setjmp.S
@@ -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
diff --git a/com32/lib/libgcc/__muldi3.S b/com32/lib/libgcc/__muldi3.S
index 648a88ad..424787c8 100644
--- a/com32/lib/libgcc/__muldi3.S
+++ b/com32/lib/libgcc/__muldi3.S
@@ -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
index 00000000..5ce206d0
--- /dev/null
+++ b/com32/lib/memcpy.c
@@ -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
index 00000000..a398cd8d
--- /dev/null
+++ b/com32/lib/memmove.c
@@ -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
index 00000000..be23b667
--- /dev/null
+++ b/com32/lib/mempcpy.c
@@ -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
index 00000000..aa00b5b1
--- /dev/null
+++ b/com32/lib/memset.c
@@ -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;
+}
diff --git a/com32/lib/setjmp.S b/com32/lib/setjmp.S
index 658df485..2fb5c234 100644
--- a/com32/lib/setjmp.S
+++ b/com32/lib/setjmp.S
@@ -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
+
diff --git a/com32/lib/sys/farcall.c b/com32/lib/sys/farcall.c
index 988ee6d2..2749083e 100644
--- a/com32/lib/sys/farcall.c
+++ b/com32/lib/sys/farcall.c
@@ -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
index 00000000..cf336932
--- /dev/null
+++ b/com32/lib/sys/i386/x86_init_fpu.c
@@ -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
index 00000000..c5d3946c
--- /dev/null
+++ b/com32/lib/sys/x86_64/x86_init_fpu.c
@@ -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;
+}
diff --git a/com32/lib/sys/x86_init_fpu.c b/com32/lib/sys/x86_init_fpu.c
index cf336932..cacb4ea3 100644
--- a/com32/lib/sys/x86_init_fpu.c
+++ b/com32/lib/sys/x86_init_fpu.c
@@ -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
index 00000000..45f547b4
--- /dev/null
+++ b/com32/lib/x86_64/setjmp.S
@@ -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