lkml.org 
[lkml]   [1999]   [May]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subjectmemmove (was Re: [PATCH] New TGA Framebuffer Driver (1.11))
On Sun, 30 May 1999, Aaron Tiensivu wrote:

> Yep. It works fine. I had to back out the memmove change because it no
> longer served network packets correctly for some reason, but I'm still
> running on the new TGA buffer and I can hit Ctrl-L all I want and it
> redraws correctly.

Aaron, did you try the 'ab^Ac' test in bash? Are you running TGA fb in
more than 8bpp?

Here is a memmove that works fine for me. No redrawing problems, and no
network problems (which I was also seeing before). I've renamed the
existing memcpy bits 'xxx_up', and written new 'xxx_dn' functions to do
the copy from top to bottom. memcpy uses the existing routines, and
memmove decides which ones to use.

Please test it out. The routine to do optimised moving from top to bottom
with src and dest unaligned is left as an exercise for the programmer. ;-)

Tim.
*/

--- linux/arch/alpha/lib/memcpy.c.orig Mon May 31 12:32:38 1999
+++ linux/arch/alpha/lib/memcpy.c Mon May 31 13:28:29 1999
@@ -21,30 +21,44 @@
* 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(d,s,n) \
+#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(d,s,n) \
+#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(d,s,n) DO_REST(d,s,n)
+#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
@@ -53,9 +67,10 @@
*
* Note the ordering to try to avoid load (and address generation) latencies.
*/
-static inline void __memcpy_unaligned(unsigned long d, unsigned long s, long n)
+static inline void __memcpy_unaligned_up (unsigned long d, unsigned long s,
+ long n)
{
- ALIGN_DEST_TO8(d,s,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;
@@ -77,7 +92,17 @@
} while (n >= 0);
}
n += 8;
- DO_REST(d,s,n);
+ 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;
}

/*
@@ -88,9 +113,10 @@
*
* Note the ordering to try to avoid load (and address generation) latencies.
*/
-static inline void __memcpy_aligned(unsigned long d, unsigned long s, long n)
+static inline void __memcpy_aligned_up (unsigned long d, unsigned long s,
+ long n)
{
- ALIGN_DEST_TO8(d,s,n);
+ ALIGN_DEST_TO8_UP(d,s,n);
n -= 8;
while (n >= 0) {
unsigned long tmp;
@@ -101,18 +127,58 @@
d += 8;
}
n += 8;
- DO_REST_ALIGNED(d,s,n);
+ 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((unsigned long) dest, (unsigned long) src, n);
+ __memcpy_aligned_up ((unsigned long) dest, (unsigned long) src,
+ n);
return dest;
}
- __memcpy_unaligned((unsigned long) dest, (unsigned long) src, n);
+ __memcpy_unaligned_up ((unsigned long) dest, (unsigned long) src, n);
return dest;
}

/* For backward modules compatibility, define __memcpy. */
asm("__memcpy = memcpy; .globl __memcpy");
+
+void *memmove (void *dest, const void *src, size_t n)
+{
+ if (dest <= src) {
+ if (!(((unsigned long) dest ^ (unsigned long) src) & 7))
+ __memcpy_aligned_up ((unsigned long) dest,
+ (unsigned long) src, n);
+ else
+ __memcpy_unaligned_up ((unsigned long) dest,
+ (unsigned long) src, n);
+ }
+ else {
+ if (!(((unsigned long) dest ^ (unsigned long) src) & 7))
+ __memcpy_aligned_dn ((unsigned long) dest,
+ (unsigned long) src, n);
+ else
+ __memcpy_unaligned_dn ((unsigned long) dest,
+ (unsigned long) src, n);
+ }
+ return dest;
+}
--- linux/include/asm-alpha/string.h.orig Mon May 31 13:37:31 1999
+++ linux/include/asm-alpha/string.h Sun May 30 16:11:03 1999
@@ -11,6 +11,7 @@
*/

#define __HAVE_ARCH_MEMCPY
+#define __HAVE_ARCH_MEMMOVE
/* For backward compatibility with modules. Unused otherwise. */
extern void * __memcpy(void *, const void *, size_t);


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:52    [W:0.342 / U:0.092 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site