Bug in memcpy() for m68k
Yuichi Nakamura via Newlib <[email protected]> Sat, 28 Mar 2026 10:35:38 +0900
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
Hi all,
I found the following issues in the m68k version of memcpy(). In
particular, issue #1 is critical because it causes incorrect behavior on
the 68000.
1. On CPUs that do not support misaligned access (MISALIGNED_OK=0), such
as the 68000, memcpy() does not correctly copy regions larger than 64 KB
when the destination is not long-word aligned.
2. The 68020 supports misaligned access, but this is not currently
implemented.
3. The 68000 can access long-word data at even addresses, but alignment
is checked as if the address must be a multiple of 4.
4. Because the loop count is checked using signed comparison, memcpy()
fails for data sizes larger than 2 GB.
The following patch fixes these issues.
Best regards,
Yuichi Nakamura
diff --git a/newlib/libc/machine/m68k/memcpy.S
b/newlib/libc/machine/m68k/memcpy.S
index 464da95ef..ecf1da611 100644
--- a/newlib/libc/machine/m68k/memcpy.S
+++ b/newlib/libc/machine/m68k/memcpy.S
@@ -15,7 +15,7 @@
#include "m68kasm.h"
-#if defined (__mcoldfire__) || defined (__mc68030__) || defined
(__mc68040__) || defined (__mc68060__)
+#if defined (__mcoldfire__) || defined (__mc68020__) || defined
(__mc68030__) || defined (__mc68040__) || defined (__mc68060__)
# define MISALIGNED_OK 1
#else
# define MISALIGNED_OK 0
@@ -49,10 +49,10 @@ SYM(memcpy):
#if !MISALIGNED_OK
/* Goto .Lresidue if either dest or src is not 4-byte aligned */
move.l a0,d0
- and.l #3,d0
+ and.l #1,d0
bne .Lresidue
move.l a1,d0
- and.l #3,d0
+ and.l #1,d0
bne .Lresidue
#else /* MISALIGNED_OK */
/* align dest */
@@ -95,7 +95,7 @@ SYM(memcpy):
#else
subq.l #1,d0
#endif
- bpl 1b
+ bcc 1b
bra .Lresidue
1:
@@ -104,9 +104,13 @@ SYM(memcpy):
.Lresidue:
#if !defined (__mcoldfire__)
dbra d1,1b | loop until done
+#if !MISALIGNED_OK
+ sub.l #0x10000,d1
+ bcc 1b
+#endif /* !MISALIGNED_OK */
#else
subq.l #1,d1
- bpl 1b
+ bcc 1b
#endif
move.l 4(sp),d0 | return value
rts