diff options
author | chandramouli narayanan <mouli@linux.intel.com> | 2012-06-25 12:47:24 -0700 |
---|---|---|
committer | chandramouli narayanan <mouli@linux.intel.com> | 2012-06-25 12:47:24 -0700 |
commit | 6dcc24c818de73fcf54e1cae57f560cb5f01f125 (patch) | |
tree | 70c52c82d3a343151067e341a7d353f1399403d5 | |
parent | 38e58635d3868c23537fc5dce87b152a52df34ad (diff) | |
download | syslinux-6dcc24c818de73fcf54e1cae57f560cb5f01f125.tar.gz syslinux-6dcc24c818de73fcf54e1cae57f560cb5f01f125.tar.xz syslinux-6dcc24c818de73fcf54e1cae57f560cb5f01f125.zip |
This patch implements architecture-dependent code in memdisk to support for i386 and x86_64.
The memcpy, memset and memmove routines originated from klibc.
Remanants of the unused old i386-only files, if any, need to be pruned.
-rw-r--r-- | memdisk/memcpy.c | 29 | ||||
-rw-r--r-- | memdisk/memdisk.h | 3 | ||||
-rw-r--r-- | memdisk/memmove.c | 36 | ||||
-rw-r--r-- | memdisk/memset.c | 30 | ||||
-rw-r--r-- | memdisk/setup.c | 6 | ||||
-rw-r--r-- | memdisk/start32.S | 6 |
6 files changed, 110 insertions, 0 deletions
diff --git a/memdisk/memcpy.c b/memdisk/memcpy.c new file mode 100644 index 00000000..5ce206d0 --- /dev/null +++ b/memdisk/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/memdisk/memdisk.h b/memdisk/memdisk.h index b6b277a8..6da5aff9 100644 --- a/memdisk/memdisk.h +++ b/memdisk/memdisk.h @@ -24,7 +24,10 @@ /* We use the com32 interface for calling 16-bit code */ #include <com32.h> +/* define it only for i386 */ +#if __SIZEOF_POINTER__ == 4 #define __cdecl __attribute__((cdecl,regparm(0))) +#endif void __cdecl intcall(uint8_t, com32sys_t *, com32sys_t *); diff --git a/memdisk/memmove.c b/memdisk/memmove.c new file mode 100644 index 00000000..a398cd8d --- /dev/null +++ b/memdisk/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/memdisk/memset.c b/memdisk/memset.c new file mode 100644 index 00000000..aa00b5b1 --- /dev/null +++ b/memdisk/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/memdisk/setup.c b/memdisk/setup.c index bc79e127..b6093b7a 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -671,7 +671,13 @@ static void relocate_rm_code(uint32_t newbase) set_seg_base(gdt_base, 0x10, rm_args.rm_base); set_seg_base(gdt_base, 0x18, rm_args.rm_base); +#if __SIZEOF_POINTER__ == 4 asm volatile ("lgdtl %0"::"m" (*(char *)gdt_base)); +#elif __SIZEOF_POINTER__ == 8 + asm volatile ("lgdt %0"::"m" (*(char *)gdt_base)); +#else +#error "unsupported architecture" +#endif *(uint32_t *) rm_args.rm_pmjmp += delta; *(uint16_t *) rm_args.rm_rmjmp += delta >> 4; diff --git a/memdisk/start32.S b/memdisk/start32.S index 4fb05374..ecebe684 100644 --- a/memdisk/start32.S +++ b/memdisk/start32.S @@ -62,7 +62,13 @@ _start: addl $8, %edi loop 1b +#if __SIZEOF_POINTER__ == 4 lidtl idt_ptr +#elif __SIZEOF_POINTER__ == 8 + lidt idt_ptr +#else +#error "unsupported architecture" +#endif /* Save arguments, switch stacks */ movl %esp, %eax /* Pointer to arguments */ |