summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiegoisawesome <diego@domoreaweso.me>2016-11-01 10:17:40 -0500
committerDiegoisawesome <diego@domoreaweso.me>2016-11-01 10:17:40 -0500
commit442002dada4183c96b5ec09fcde8486aa5ba29b1 (patch)
treed5c101175f54d6490d37b99a2af1a09eae793899
parent0f6ec6492c7e07e7744ae80b76e84318cbd7ed4a (diff)
Ported libc from pokeruby
-rw-r--r--Makefile6
-rw-r--r--asm/libc.s213
-rw-r--r--asm/rom_80093CC.s2
-rw-r--r--ld_script.txt2
-rw-r--r--src/libc.c173
5 files changed, 179 insertions, 217 deletions
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 <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);
+}
+
+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;
+}
+