diff options
Diffstat (limited to 'qemu/roms/qemu-palcode/memcpy.c')
-rw-r--r-- | qemu/roms/qemu-palcode/memcpy.c | 160 |
1 files changed, 0 insertions, 160 deletions
diff --git a/qemu/roms/qemu-palcode/memcpy.c b/qemu/roms/qemu-palcode/memcpy.c deleted file mode 100644 index b6bbb7434..000000000 --- a/qemu/roms/qemu-palcode/memcpy.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * linux/arch/alpha/lib/memcpy.c - * - * Copyright (C) 1995 Linus Torvalds - */ - -/* - * This is a reasonably optimized memcpy() routine. - */ - -#include <string.h> - -/* - * Note that the C code is written to be optimized into good assembly. However, - * at this point gcc is unable to sanely compile "if (n >= 0)", resulting in a - * explicit compare against 0 (instead of just using the proper "blt reg, xx" or - * "bge reg, xx"). I hope alpha-gcc will be fixed to notice this eventually.. - */ - -/* - * This should be done in one go with ldq_u*2/mask/stq_u. Do it - * with a macro so that we can fix it up later.. - */ -#define ALIGN_DEST_TO8_UP(d,s,n) \ - while (d & 7) { \ - if (n <= 0) return; \ - n--; \ - *(char *) d = *(char *) s; \ - d++; s++; \ - } -#define ALIGN_DEST_TO8_DN(d,s,n) \ - while (d & 7) { \ - if (n <= 0) return; \ - n--; \ - d--; s--; \ - *(char *) d = *(char *) s; \ - } - -/* - * This should similarly be done with ldq_u*2/mask/stq. The destination - * is aligned, but we don't fill in a full quad-word - */ -#define DO_REST_UP(d,s,n) \ - while (n > 0) { \ - n--; \ - *(char *) d = *(char *) s; \ - d++; s++; \ - } -#define DO_REST_DN(d,s,n) \ - while (n > 0) { \ - n--; \ - d--; s--; \ - *(char *) d = *(char *) s; \ - } - -/* - * This should be done with ldq/mask/stq. The source and destination are - * aligned, but we don't fill in a full quad-word - */ -#define DO_REST_ALIGNED_UP(d,s,n) DO_REST_UP(d,s,n) -#define DO_REST_ALIGNED_DN(d,s,n) DO_REST_DN(d,s,n) - -/* - * This does unaligned memory copies. We want to avoid storing to - * an unaligned address, as that would do a read-modify-write cycle. - * We also want to avoid double-reading the unaligned reads. - * - * Note the ordering to try to avoid load (and address generation) latencies. - */ -static inline void __memcpy_unaligned_up (unsigned long d, unsigned long s, - long n) -{ - ALIGN_DEST_TO8_UP(d,s,n); - n -= 8; /* to avoid compare against 8 in the loop */ - if (n >= 0) { - unsigned long low_word, high_word; - __asm__("ldq_u %0,%1":"=r" (low_word):"m" (*(unsigned long *) s)); - do { - unsigned long tmp; - __asm__("ldq_u %0,%1":"=r" (high_word):"m" (*(unsigned long *)(s+8))); - n -= 8; - __asm__("extql %1,%2,%0" - :"=r" (low_word) - :"r" (low_word), "r" (s)); - __asm__("extqh %1,%2,%0" - :"=r" (tmp) - :"r" (high_word), "r" (s)); - s += 8; - *(unsigned long *) d = low_word | tmp; - d += 8; - low_word = high_word; - } while (n >= 0); - } - n += 8; - DO_REST_UP(d,s,n); -} - -static inline void __memcpy_unaligned_dn (unsigned long d, unsigned long s, - long n) -{ - /* I don't understand AXP assembler well enough for this. -Tim */ - s += n; - d += n; - while (n--) - * (char *) --d = * (char *) --s; -} - -/* - * Hmm.. Strange. The __asm__ here is there to make gcc use an integer register - * for the load-store. I don't know why, but it would seem that using a floating - * point register for the move seems to slow things down (very small difference, - * though). - * - * Note the ordering to try to avoid load (and address generation) latencies. - */ -static inline void __memcpy_aligned_up (unsigned long d, unsigned long s, - long n) -{ - ALIGN_DEST_TO8_UP(d,s,n); - n -= 8; - while (n >= 0) { - unsigned long tmp; - __asm__("ldq %0,%1":"=r" (tmp):"m" (*(unsigned long *) s)); - n -= 8; - s += 8; - *(unsigned long *) d = tmp; - d += 8; - } - n += 8; - DO_REST_ALIGNED_UP(d,s,n); -} -static inline void __memcpy_aligned_dn (unsigned long d, unsigned long s, - long n) -{ - s += n; - d += n; - ALIGN_DEST_TO8_DN(d,s,n); - n -= 8; - while (n >= 0) { - unsigned long tmp; - s -= 8; - __asm__("ldq %0,%1":"=r" (tmp):"m" (*(unsigned long *) s)); - n -= 8; - d -= 8; - *(unsigned long *) d = tmp; - } - n += 8; - DO_REST_ALIGNED_DN(d,s,n); -} - -void * memcpy(void * dest, const void *src, size_t n) -{ - if (!(((unsigned long) dest ^ (unsigned long) src) & 7)) { - __memcpy_aligned_up ((unsigned long) dest, (unsigned long) src, - n); - return dest; - } - __memcpy_unaligned_up ((unsigned long) dest, (unsigned long) src, n); - return dest; -} |