diff options
author | chandramouli narayanan <mouli@linux.intel.com> | 2012-06-25 12:34:46 -0700 |
---|---|---|
committer | chandramouli narayanan <mouli@linux.intel.com> | 2012-06-25 12:34:46 -0700 |
commit | 5caee9aeaf89dbbc45269737cc1dac7de070b867 (patch) | |
tree | 5284cfb67697c00d34cfca692e2da52f22e9716d | |
parent | c53187e1adc326c3246917cb936cbab020b4d820 (diff) | |
download | syslinux-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.S | 63 | ||||
-rw-r--r-- | com32/lib/libgcc/__muldi3.S | 49 | ||||
-rw-r--r-- | com32/lib/memcpy.c | 29 | ||||
-rw-r--r-- | com32/lib/memmove.c | 36 | ||||
-rw-r--r-- | com32/lib/mempcpy.c | 14 | ||||
-rw-r--r-- | com32/lib/memset.c | 30 | ||||
-rw-r--r-- | com32/lib/setjmp.S | 11 | ||||
-rw-r--r-- | com32/lib/sys/farcall.c | 10 | ||||
-rw-r--r-- | com32/lib/sys/i386/x86_init_fpu.c | 58 | ||||
-rw-r--r-- | com32/lib/sys/x86_64/x86_init_fpu.c | 58 | ||||
-rw-r--r-- | com32/lib/sys/x86_init_fpu.c | 22 | ||||
-rw-r--r-- | com32/lib/x86_64/setjmp.S | 54 |
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 |