diff options
author | camthesaxman <cameronghall@cox.net> | 2016-07-23 14:18:19 -0500 |
---|---|---|
committer | YamaArashi <YamaArashi@users.noreply.github.com> | 2016-07-23 12:18:19 -0700 |
commit | 2b4143ce6891e2c15db4c9188fd80002a0f7e248 (patch) | |
tree | 750fd4109b43720a302c944b508342b9f443bed1 | |
parent | aae9a50849c7d5a71005062f32545fce0e2ccf55 (diff) |
decompile libc (#24)
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | ld_script.txt | 2 | ||||
-rw-r--r-- | src/libc.c | 143 |
3 files changed, 148 insertions, 2 deletions
@@ -37,7 +37,7 @@ C_SRCS := $(wildcard src/*.c) C_OBJS := $(C_SRCS:%.c=%.o) ASM_OBJS := asm/crt0.o asm/rom3.o asm/rom4.o asm/rom_8074BAC.o asm/rom5.o \ - asm/libgcnmultiboot.o asm/m4a_1.o asm/m4a_3.o asm/libagbsyscall.o asm/libc.o + asm/libgcnmultiboot.o asm/m4a_1.o asm/m4a_3.o asm/libagbsyscall.o DATA_ASM_OBJS := data/data1.o data/data2.o data/graphics.o data/sound_data.o \ data/event_scripts.o data/battle_anim_scripts.o @@ -85,6 +85,9 @@ include misc.mk %.gbapal: %.pal ; $(GFX) $< $@ %.lz: % ; $(GFX) $< $@ +src/libc_ruby.o src/libc_sapphire.o: CC1 := tools/agbcc/bin/old_agbcc +src/libc_ruby.o src/libc_sapphire.o: CFLAGS := -O2 + src/siirtc_ruby.o src/siirtc_sapphire.o: CFLAGS := -mthumb-interwork src/agb_flash_ruby.o src/agb_flash_sapphire.o: CFLAGS := -O -mthumb-interwork diff --git a/ld_script.txt b/ld_script.txt index 89dff1a5d..ed3aa449d 100644 --- a/ld_script.txt +++ b/ld_script.txt @@ -109,7 +109,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..e408ba51e --- /dev/null +++ b/src/libc.c @@ -0,0 +1,143 @@ +#include "global.h" +#include <stddef.h> + +#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); +} |