diff --git a/Makefile b/Makefile index ea76364ed..4189cd33b 100644 --- a/Makefile +++ b/Makefile @@ -59,8 +59,7 @@ asm/libmks4agb.o \ asm/libagbbackup.o \ asm/librtc.o \ asm/librfu.o \ -asm/libagbsyscall.o \ -asm/libc.o +asm/libagbsyscall.o DATA_ASM_OBJS := data/data2.o data/anim_mon_front_pics.o \ data/graphics.o data/unknown_serial_data.o data/multiboot_berry_glitch_fix.o \ @@ -102,6 +101,9 @@ include graphics_file_rules.mk %.lz: % ; $(GFX) $< $@ %.rl: % ; $(GFX) $< $@ +src/libc.o: CC1 := tools/agbcc/bin/old_agbcc +src/libc.o: CFLAGS := -O2 + src/siirtc.o: CFLAGS := -mthumb-interwork src/agb_flash.o: CFLAGS := -O -mthumb-interwork diff --git a/asm/libc.s b/asm/libc.s deleted file mode 100644 index a7a233f83..000000000 --- a/asm/libc.s +++ /dev/null @@ -1,213 +0,0 @@ - .include "asm/macros.s" - - .syntax unified - - .text - - thumb_func_start memcpy -@ void *memcpy(void *dest, void *src, int size) -memcpy: @ 82E93D4 - push {r4,r5,lr} - adds r5, r0, 0 - adds r4, r5, 0 - adds r3, r1, 0 - cmp r2, 0xF - bls _082E9414 - adds r0, r3, 0 - orrs r0, r5 - movs r1, 0x3 - ands r0, r1 - cmp r0, 0 - bne _082E9414 - adds r1, r5, 0 -_082E93EE: - ldm r3!, {r0} - stm r1!, {r0} - ldm r3!, {r0} - stm r1!, {r0} - ldm r3!, {r0} - stm r1!, {r0} - ldm r3!, {r0} - stm r1!, {r0} - subs r2, 0x10 - cmp r2, 0xF - bhi _082E93EE - cmp r2, 0x3 - bls _082E9412 -_082E9408: - ldm r3!, {r0} - stm r1!, {r0} - subs r2, 0x4 - cmp r2, 0x3 - bhi _082E9408 -_082E9412: - adds r4, r1, 0 -_082E9414: - subs r2, 0x1 - movs r0, 0x1 - negs r0, r0 - cmp r2, r0 - beq _082E942E - adds r1, r0, 0 -_082E9420: - ldrb r0, [r3] - strb r0, [r4] - adds r3, 0x1 - adds r4, 0x1 - subs r2, 0x1 - cmp r2, r1 - bne _082E9420 -_082E942E: - adds r0, r5, 0 - pop {r4,r5,pc} - thumb_func_end memcpy - - thumb_func_start memset -@ void *memset(void *dest, char c, int size) -memset: @ 82E9434 - push {r4,r5,lr} - adds r5, r0, 0 - adds r4, r1, 0 - adds r3, r5, 0 - cmp r2, 0x3 - bls _082E947A - movs r0, 0x3 - ands r0, r5 - cmp r0, 0 - bne _082E947A - adds r1, r5, 0 - movs r0, 0xFF - ands r4, r0 - lsls r3, r4, 8 - orrs r3, r4 - lsls r0, r3, 16 - orrs r3, r0 - cmp r2, 0xF - bls _082E946E -_082E945A: - stm r1!, {r3} - stm r1!, {r3} - stm r1!, {r3} - stm r1!, {r3} - subs r2, 0x10 - cmp r2, 0xF - bhi _082E945A - b _082E946E -_082E946A: - stm r1!, {r3} - subs r2, 0x4 -_082E946E: - cmp r2, 0x3 - bhi _082E946A - adds r3, r1, 0 - b _082E947A -_082E9476: - strb r4, [r3] - adds r3, 0x1 -_082E947A: - adds r0, r2, 0 - subs r2, 0x1 - cmp r0, 0 - bne _082E9476 - adds r0, r5, 0 - pop {r4,r5,pc} - thumb_func_end memset - - thumb_func_start strcmp -@ int strcmp(char *s1, char *s2) -strcmp: @ 82E9488 - push {r4,r5,lr} - adds r2, r0, 0 - adds r3, r1, 0 - orrs r0, r3 - movs r1, 0x3 - ands r0, r1 - cmp r0, 0 - bne _082E94CE - ldr r1, [r2] - ldr r0, [r3] - cmp r1, r0 - bne _082E94CE - ldr r5, _082E94B4 - ldr r4, _082E94B8 -_082E94A4: - ldr r1, [r2] - adds r0, r1, r5 - bics r0, r1 - ands r0, r4 - cmp r0, 0 - beq _082E94BC - movs r0, 0 - b _082E94E0 - .align 2, 0 -_082E94B4: .4byte 0xfefefeff -_082E94B8: .4byte 0x80808080 -_082E94BC: - adds r2, 0x4 - adds r3, 0x4 - ldr r1, [r2] - ldr r0, [r3] - cmp r1, r0 - beq _082E94A4 - b _082E94CE -_082E94CA: - adds r2, 0x1 - adds r3, 0x1 -_082E94CE: - ldrb r0, [r2] - cmp r0, 0 - beq _082E94DA - ldrb r1, [r3] - cmp r0, r1 - beq _082E94CA -_082E94DA: - ldrb r2, [r2] - ldrb r3, [r3] - subs r0, r2, r3 -_082E94E0: - pop {r4,r5,pc} - thumb_func_end strcmp - - thumb_func_start strcat -strcat: @ 82E94E4 - push {r4-r6,lr} - adds r6, r0, 0 - adds r3, r6, 0 - adds r2, r1, 0 - adds r0, r2, 0 - orrs r0, r6 - movs r1, 0x3 - ands r0, r1 - cmp r0, 0 - bne _082E951C - ldr r1, [r2] - ldr r5, _082E9504 - adds r0, r1, r5 - bics r0, r1 - ldr r4, _082E9508 - b _082E9516 - .align 2, 0 -_082E9504: .4byte 0xfefefeff -_082E9508: .4byte 0x80808080 -_082E950C: - ldm r2!, {r0} - stm r3!, {r0} - ldr r1, [r2] - adds r0, r1, r5 - bics r0, r1 -_082E9516: - ands r0, r4 - cmp r0, 0 - beq _082E950C -_082E951C: - ldrb r0, [r2] - strb r0, [r3] - lsls r0, 24 - adds r2, 0x1 - adds r3, 0x1 - cmp r0, 0 - bne _082E951C - adds r0, r6, 0 - pop {r4-r6,pc} - - .align 2, 0 @ Don't pad with nop. diff --git a/asm/rom_80093CC.s b/asm/rom_80093CC.s index 5f6c92dc1..9587dcbc5 100644 --- a/asm/rom_80093CC.s +++ b/asm/rom_80093CC.s @@ -2523,7 +2523,7 @@ task00_link_test: @ 800A850 sub sp, 0x20 ldr r1, =gUnknown_082ED1E4 mov r0, sp - bl strcat + bl strcpy mov r0, sp movs r1, 0x5 movs r2, 0x2 diff --git a/ld_script.txt b/ld_script.txt index c56a3fd14..e9f36ffd7 100644 --- a/ld_script.txt +++ b/ld_script.txt @@ -86,7 +86,7 @@ SECTIONS { tools/agbcc/lib/libgcc.a:fp-bit.o(.text); tools/agbcc/lib/libgcc.a:_lshrdi3.o(.text); tools/agbcc/lib/libgcc.a:_negdi2.o(.text); - asm/libc.o(.text); + src/libc.o(.text); } =0 .rodata : diff --git a/src/libc.c b/src/libc.c new file mode 100644 index 000000000..d00c30e09 --- /dev/null +++ b/src/libc.c @@ -0,0 +1,173 @@ +#include "global.h" +#include + +#define LBLOCKSIZE (sizeof(long)) + +// Nonzero if (long)X contains a NULL byte. +#define CONTAINSNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) + +// Nonzero if X is not aligned on a "long" boundary. +#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) + +void *memcpy(void *dst0, const void *src0, size_t len0) +{ + char *dst = dst0; + const char *src = src0; + long *aligned_dst; + const long *aligned_src; + unsigned int len = len0; + + // If the size is small, or either src or dst is unaligned, + // then go to the byte copy loop. This should be rare. + if(len >= 16 && !(UNALIGNED(src) | UNALIGNED(dst))) + { + aligned_dst = (long *)dst; + aligned_src = (long *)src; + + // Copy 4X long words at a time if possible. + while(len >= 16) + { + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + len -= 16; + } + + // Copy one long word at a time if possible + while(len >= 4) + { + *aligned_dst++ = *aligned_src++; + len -= 4; + } + + dst = (char *)aligned_dst; + src = (char *)aligned_src; + } + + // Pick up any remaining bytes with a byte copier. + while(len--) + *dst++ = *src++; + + return dst0; +} + +void *memset(void *m, int c, size_t n) +{ + char *s = (char *)m; + int count, i; + unsigned long buffer; + unsigned long *aligned_addr; + unsigned char *unaligned_addr; + + // If the size is small or m is unaligned, + // then go to the byte copy loop. This should be rare. + if(n >= LBLOCKSIZE && !UNALIGNED(m)) + { + // We know that n is large and m is word-aligned. + aligned_addr = (unsigned long *)m; + + // Store C into each char sized location in buffer so that + // we can set large blocks quickly. + c &= 0xFF; + if(LBLOCKSIZE == 4) + { + buffer = (c << 8) | c; + buffer |= (buffer << 16); + } + else + { + buffer = 0; + for(i = 0; i < LBLOCKSIZE; i++) + buffer = (buffer << 8) | c; + } + + while(n >= LBLOCKSIZE * 4) + { + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + n -= LBLOCKSIZE * 4; + } + while(n >= LBLOCKSIZE) + { + *aligned_addr++ = buffer; + n -= LBLOCKSIZE; + } + + s = (char *)aligned_addr; + } + + // Pick up the remainder with a bytewise loop. + while(n--) + *s++ = (char)c; + + return m; +} + +int strcmp(const char *s1, const char *s2) +{ + unsigned long *a1; + unsigned long *a2; + + // If s1 or s2 are unaligned, then skip this and compare bytes. + if(!(UNALIGNED(s1) | UNALIGNED(s2))) + { + // Compare them a word at a time. + a1 = (unsigned long *)s1; + a2 = (unsigned long *)s2; + while(*a1 == *a2) + { + // If *a1 == *a2, and we find a null in *a1, + // then the strings must be equal, so return zero. + if(CONTAINSNULL(*a1)) + return 0; + + a1++; + a2++; + } + + s1 = (char *)a1; + s2 = (char *)a2; + } + + // Check the remaining few bytes. + while(*s1 != '\0' && *s1 == *s2) + { + s1++; + s2++; + } + + return (*(unsigned char *) s1) - (*(unsigned char *) s2); +} + +char* strcpy(char *dst0, const char *src0) +{ + char *dst = dst0; + const char *src = src0; + unsigned long *a1; + const unsigned long *a2; + + /* If SRC or DEST is unaligned, then copy bytes. */ + if(!(UNALIGNED(src) | UNALIGNED(dst))) + { + /* SRC and DEST are both "long int" aligned, try to do "long int" + sized copies. */ + a1 = (unsigned long *)dst; + a2 = (unsigned long *)src; + while(!CONTAINSNULL(*a2)) + { + *a1++ = *a2++; + } + + dst = (char *)a1; + src = (char *)a2; + } + + // Copy the remaining few bytes. + while(*dst++ = *src++); + + return dst0; +} +