Compare commits

..

18 Commits

Author SHA1 Message Date
f895accae6 day 8 2025-12-08 16:02:47 -06:00
2994837ebc day 7 2025-12-08 16:02:36 -06:00
d6f3266154 prettier 2025-12-06 19:17:27 -06:00
75a8e72093 prettify 2025-12-06 15:55:16 -06:00
e71c742863 day 6 2025-12-06 14:29:30 -06:00
f43acb06fe use that sort 2025-12-05 16:36:57 -06:00
e851e48f1e don't manually unroll your loops, kids 2025-12-05 16:35:26 -06:00
af2c148dc1 prettier 2025-12-05 15:19:05 -06:00
fda2b0d523 day 5, pretty blinkenlights mem, awful performance 2025-12-05 01:31:39 -06:00
1be8a18ccb fix for blinken 2025-12-05 01:30:30 -06:00
91f73e2aa5 pretty blinkenlights 2025-12-04 22:05:16 -06:00
5b71ad8ed0 somewhat optimized day 2. for fun 2025-12-04 16:33:55 -06:00
511bf09d65 linux syscall trashes rcx & r11 2025-12-04 01:02:29 -06:00
28d44f2bbf day 4 2025-12-04 00:45:42 -06:00
4ca5884255 target blinkenlights 2025-12-03 18:40:18 -06:00
137fd441e1 no more crash on day3 2025-12-03 17:33:25 -06:00
26dd9df8c7 day 3 2025-12-03 02:08:01 -06:00
06816c068c day 2 2025-12-03 00:52:18 -06:00
23 changed files with 3710 additions and 26 deletions

8
.gitignore vendored
View File

@@ -1,3 +1,5 @@
day1 *.txt
day1_input *.elf
day1_test *.o
blink.log
compile_commands.json

View File

@@ -1,4 +1,27 @@
all: day1 FILES = $(wildcard ./*)
SRCS = $(filter %.c,$(FILES))
BINS = $(SRCS:%.c=%.elf)
%: %.c MUSLFILES = $(wildcard ./musl/*)
gcc-tree -o $@ -Wall -Werror -pedantic -D_GNU_SOURCE -std=gnu2y -O3 -g $< MUSLOBJS = $(filter %.o,$(MUSLFILES))
CFLAGS = -Wall -Werror -pedantic -Wno-unused -std=gnu2y\
-O3 -c -g -fno-stack-protector -fno-pie\
-fno-semantic-interposition -fno-trapping-math\
-march=x86-64 -mprefer-vector-width=128 -mpopcnt -malign-data=compat -malign-stringops
LFLAGS = -Ttext=C475000 -static -nostdlib -no-pie
all: $(BINS)
%.elf: %.o start.o | %.c $(MUSLOBJS)
ld -o $@ $(LFLAGS) start.o $< $(MUSLOBJS)
start.o: start.s
nasm -f elf64 -o $@ $<
%.o: %.c | lib.h
gcc-tree -o $@ $(CFLAGS) $<
clean:
rm -f *.elf *.o

91
day0.h Normal file
View File

@@ -0,0 +1,91 @@
#include "lib.h"
#define DBG 0
static
ch input[] = {
#embed "day0_input.txt"
};
static
ch test[] = {
#embed "day0_test.txt"
};
alignas(0x40) static
struct {
line padstart[4];
struct { ch *s; num _extra[7]; };
union { line l; struct { ch s[16]; num n; }; } result;
line padend;
} m;
static_assert(offsetof(typeof(m),result) % 64 == 0);
static_assert(offsetof(typeof(m),padend) % 64 == 0);
static
num do_part1(size_t file_len, ch file[file_len]) {
m = (typeof(m)){ };
m.s = file;
m.result.n = 0;
#if DBG
print("\n");
#endif
do {
m.s++;
} while (m.s != &file[file_len]);
return m.result.n;
}
static
num do_part2(size_t file_len, ch file[file_len]) {
return 0;
}
#define RUN_TEST1 1
#define RUN_PART1 0
#define RUN_TEST2 0
#define RUN_PART2 0
#define TEST1_EXPECT -1
#define TEST2_EXPECT -1
void run() {
#if RUN_TEST1
print("PART 1 TEST: ");
if (num v = do_part1(countof(test), test); v != TEST1_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST1_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART1
print("PART 1 RESULT: ");
printd(do_part1(countof(input), input));
print("\n");
#endif
#if RUN_TEST2
print("PART 2 TEST: ");
if (num v = do_part2(countof(test), test); v != TEST2_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST2_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART2
print("PART 2 RESULT: ");
printd(do_part2(countof(input), input));
print("\n");
#endif
exit_group(0);
}

121
day1.c
View File

@@ -1,15 +1,58 @@
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdcountof.h> #include <stdcountof.h>
#include <stdint.h>
#include <string.h>
char input[] = { #define SYS_write 1
#embed "day1_input" #define SYS_exit_group 231
};
char test[] = { #define STDOUT_FILENO 1
#embed "day1_test"
};
static
void write(uint64_t fileno, void *buffer, size_t len) {
uint64_t a,d;
asm volatile("syscall"
:"=a"(a),"=d"(d):"a"(SYS_write),"D"(fileno),"S"(buffer),"d"(len):"memory");
}
[[noreturn]] static
void exit_group() {
asm volatile(
"syscall\n"
"ud2"
::"a"(SYS_exit_group),"D"(0));
for (;;);
}
#define xstr(s) str(s)
#define str(s) #s
static
void print_many_char(size_t len, char chars[len]) {
write(STDOUT_FILENO, chars, len);
}
#define print(string) print_many_char(sizeof(string)-1, string)
static
void printd(unsigned long v) {
if (!v) {
print("0");
return;
}
char buf[32];
char *p = buf+32;
unsigned count = 0;
while (v) {
p--;
*p = '0' + (v % 10);
v /= 10;
count++;
}
write(STDOUT_FILENO, p, count);
}
static
unsigned grabnum(const char *s, const char **end) { unsigned grabnum(const char *s, const char **end) {
unsigned r = 0; unsigned r = 0;
for (; *s >= '0' && *s <= '9'; s++) for (; *s >= '0' && *s <= '9'; s++)
@@ -18,6 +61,27 @@ unsigned grabnum(const char *s, const char **end) {
return r; return r;
} }
#define DBG 1
#define RUN_PART1 1
#define RUN_PART2 1
#define RUN_TEST1 1
#define RUN_TEST2 1
#define TEST1_EXPECT 3
#define TEST2_EXPECT 6
static
char input[] = {
#embed "day1_input.txt"
};
static
char test[] = {
#embed "day1_test.txt"
};
static
unsigned long do_part1(size_t src_len, const char src[src_len]) { unsigned long do_part1(size_t src_len, const char src[src_len]) {
const char *s = src; const char *s = src;
unsigned long count = 0; unsigned long count = 0;
@@ -36,6 +100,7 @@ unsigned long do_part1(size_t src_len, const char src[src_len]) {
return count; return count;
} }
static
unsigned do_part2(size_t src_len, const char src[src_len]) { unsigned do_part2(size_t src_len, const char src[src_len]) {
const char *s = src, *ns = s + 1; const char *s = src, *ns = s + 1;
unsigned count = 0; unsigned count = 0;
@@ -70,24 +135,40 @@ unsigned do_part2(size_t src_len, const char src[src_len]) {
return count; return count;
} }
int main() { void run() {
printf("PART 1 TEST: "); #if RUN_TEST1
if (unsigned long v = do_part1(countof(test), test); v != 3) { print("PART 1 TEST: ");
printf("FAILED (got %lu, expected 3)\n", v); if (unsigned long v = do_part1(countof(test), test); v != TEST1_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST1_EXPECT) ")\n");
} else { } else {
printf("PASSED\n"); print("PASSED\n");
} }
#endif
printf("PART 1 RESULT: %lu\n", #if RUN_PART1
do_part1(countof(input), input)); print("PART 1 RESULT: ");
printd(do_part1(countof(input), input));
print("\n");
#endif
printf("PART 2 TEST: "); #if RUN_TEST2
if (unsigned v = do_part2(countof(test), test); v != 6) { print("PART 2 TEST: ");
printf("FAILED (got %u, expected 6)\n", v); if (unsigned v = do_part2(countof(test), test); v != TEST2_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST2_EXPECT) ")\n");
} else { } else {
printf("PASSED\n"); print("PASSED\n");
} }
#endif
printf("PART 2 RESULT: %u\n", #if RUN_PART2
do_part2(countof(input), input)); print("PART 2 RESULT: ");
printd(do_part2(countof(input), input));
print("\n");
#endif
exit_group();
} }

296
day2.c Normal file
View File

@@ -0,0 +1,296 @@
#include "lib.h"
#define DBG 0
static
unsigned char input[] = {
#embed "day2_input.txt"
};
static
unsigned char test[] = {
#embed "day2_test.txt"
};
struct id {
size_t len;
bcdint v;
};
static
struct id next_palindrome_part1(struct id s) {
if (s.len % 2 == 1) {
size_t len = s.len + 1;
unsigned high_shift = (len / 2) * 4;
bcdint high = 1 << (high_shift - 4);
return (struct id) {
.len = len,
.v = (high << high_shift) | high
};
}
unsigned high_shift = (s.len / 2) * 4;
bcdint low_mask = (1 << high_shift) - 1;
bcdint high = s.v >> high_shift;
bcdint low = s.v & low_mask;
if (low > high)
high = bcdadd(high, 1);
return (struct id) {
.len = s.len,
.v = (high << high_shift) | high
};
}
static
bcdint do_part1(size_t file_len, unsigned char file[file_len]) {
unsigned char *src = file, *tmp;
bcdint result = 0;
#if DBG
print("\n");
#endif
do {
#if DBG
print_watch_ptr(src);
print("\t");
print(str(src) ":");
for (size_t i = 0; i < 2; i++) {
print(" ");
print_hex_char(src[i]);
}
print("\n");
#endif
tmp = src;
bcdint rs = grabbcd(src, &src);
struct id first = {
.len = src - tmp,
.v = rs
};
src++;
tmp = src;
bcdint re = grabbcd(src, &src);
src++;
#if DBG
printh(rs);
print(" to ");
printh(re);
print("\n");
#endif
struct id next = first;
do {
next = next_palindrome_part1(next);
if (next.v <= re) {
result = bcdadd(result, next.v);
#if DBG
print_watch_hex(next.v);
print("\t");
print_watch_hex(next.len);
print("\t");
print_watch_hex(result);
print("\n");
#endif
}
bcdint tmp = bcdadd(next.v, 1);
for (bcdint chk = next.v; chk > 0; chk >>= 4) {
if ((chk & 0xF) != 9) goto no_len_change;
}
next.len++;
no_len_change:
next.v = tmp;
} while (next.v <= re);
#if DBG
print("reached ");
printh(re);
print("\n");
#endif
} while (src != &file[file_len]);
return result;
}
static
struct id next_palindrome_part2(struct id s) {
bcdint best = -1;
for (unsigned i = 2; i <= s.len; i++) {
if (s.len % i == 0) {
unsigned high_shift = (s.len / i) * 4;
bcdint high = s.v >> (high_shift * (i - 1));
for (int j = i - 2; j >= 0; j--) {
bcdint low = (s.v >> (high_shift * (j))) & ((1 << high_shift) - 1);
if (low < high) {
break;
} else if (low > high) {
high = bcdadd(high, 1);
break;
}
}
bcdint next = 0;
for (unsigned j = 0; j < i; j++) {
next |= high << (high_shift * j);
}
if (next < best) {
best = next;
}
}
}
if (best != -1) {
return (struct id) {
.len = s.len,
.v = best
};
}
size_t len = s.len + 1;
unsigned high_shift = (len / 2) * 4;
bcdint high = 1 << (high_shift - 4);
return (struct id) {
.len = len,
.v = (high << high_shift) | high
};
}
static
bcdint do_part2(size_t file_len, unsigned char file[file_len]) {
unsigned char *src = file, *tmp;
bcdint result = 0;
#if DBG
print("\n");
#endif
do {
#if DBG
print_watch_ptr(src);
print("\t");
print(str(src) ":");
for (size_t i = 0; i < 2; i++) {
print(" ");
print_hex_char(src[i]);
}
print("\n");
#endif
tmp = src;
bcdint rs = grabbcd(src, &src);
struct id first = {
.len = src - tmp,
.v = rs
};
src++;
tmp = src;
bcdint re = grabbcd(src, &src);
src++;
#if DBG
printh(rs);
print(" to ");
printh(re);
print("\n");
#endif
struct id next = first;
do {
next = next_palindrome_part2(next);
if (next.v <= re) {
result = bcdadd(result, next.v);
#if DBG
print_watch_hex(next.v);
print("\t");
print_watch_hex(next.len);
print("\t");
print_watch_hex(result);
print("\n");
#endif
}
bcdint tmp = bcdadd(next.v, 1);
for (bcdint chk = next.v; chk > 0; chk >>= 4) {
if ((chk & 0xF) != 9) goto no_len_change;
}
next.len++;
no_len_change:
next.v = tmp;
} while (next.v <= re);
#if DBG
print("reached ");
printh(re);
print("\n");
#endif
} while (src != &file[file_len]);
return result;
}
#define RUN_TEST1 0
#define RUN_PART1 0
#define RUN_TEST2 0
#define RUN_PART2 1
#define TEST1_EXPECT 0x1227775554l
#define TEST2_EXPECT 0x4174379265l
void run() {
#if RUN_TEST1
print("PART 1 TEST: ");
if (bcdint v = do_part1(countof(test), test); v != TEST1_EXPECT) {
print("FAILED (got ");
printh(v);
print(", expected " xstr(TEST1_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART1
print("PART 1 RESULT: ");
printh(do_part1(countof(input), input));
print("\n");
#endif
#if RUN_TEST2
print("PART 2 TEST: ");
if (bcdint v = do_part2(countof(test), test); v != TEST2_EXPECT) {
print("FAILED (got ");
printh(v);
print(", expected " xstr(TEST2_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART2
print("PART 2 RESULT: ");
printh(do_part2(countof(input), input));
print("\n");
#endif
exit_group(0);
}

130
day2_plasl.c Normal file
View File

@@ -0,0 +1,130 @@
#include "lib.h"
#define DBG 0
static
unsigned char input[] = {
#embed "day2_input.txt"
};
static
unsigned char test[] = {
#embed "day2_test.txt"
};
uint64_t ipow(uint64_t a, uint64_t b) {
uint64_t m = a;
for (;b;b--) m += a;
return m;
}
static
uint64_t range(uint64_t start, uint64_t end, uint64_t len) {
#if DBG
print("==\n");
printd(start); print(" "); printd(end); print("\n");
#endif
if ((len & 1) == 1) {
return 0;
}
uint64_t divisor = ipow(10, len / 2);
uint64_t first = (start + divisor - 1) / divisor;
uint64_t second = end / divisor;
#if DBG
print("\n");
printd(divisor); print("\n");
printd(first); print(" "); printd(second); print("\n");
#endif
uint64_t r = (((second + first) * (second + 1 - first)) / 2) * divisor;
#if DBG
printd(r); print("\n");
#endif
return r;
}
static
uint64_t do_part1(size_t file_len, unsigned char file[file_len]) {
unsigned char buffer[65535];
memcpy(buffer, file, file_len);
size_t size = file_len;
buffer[file_len-1] = ',';
uint64_t out = 0;
uint64_t i = 0;
while (i < size) {
#if DBG
print("--------------\n");
#endif
uint64_t startlen = 0, endlen = 0;
uint64_t start = grabnum(buffer+i, NULL);
while (buffer[i] != '-') {
i++;
startlen++;
}
i++;
uint64_t end = grabnum(buffer+i, NULL);
while (buffer[i] != ',') {
i++;
endlen++;
}
i++;
#if DBG
printd(startlen); print(" "); printd(start); print((char[]){ 10 });
printd(startlen); print(" "); printd(start); print((char[]){ 10 });
#endif
if (endlen != startlen) {
out += range(start, ipow(10, startlen) - 1, startlen)
+ range(ipow(10, startlen), end, endlen);
} else {
out += range(start, end, startlen);
}
#if DBG
print((char[]) { 10 });
#endif
}
return out;
}
#define RUN_TEST1 1
#define RUN_PART1 1
#define TEST1_EXPECT 0x1227775554l
void run() {
volatile uintptr_t s = (uintptr_t)&s;
printh(s);
print("\n");
#if RUN_TEST1
print("PART 1 TEST: ");
if (uint64_t v = do_part1(countof(test), test); v != TEST1_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST1_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART1
print("PART 1 RESULT: ");
printd(do_part1(countof(input), input));
print("\n");
#endif
exit_group(0);
}

257
day2opt.c Normal file
View File

@@ -0,0 +1,257 @@
#include "lib.h"
#define DBG 0
static
alignas(0x40) unsigned char input[] = {
#embed "day2_input.txt"
};
struct id {
size_t len;
bcdint v;
};
static
bcdint next_palindrome_len2(bcdint in) {
bcdint low = in & 0xF;
bcdint high = in >> 4;
bcdint higher = high + 1;
bcdint high_pd = 0x11 * high;
bcdint higher_pd = 0x11 * higher;
return low > high ? higher_pd : high_pd;
}
static
bcdint next_palindrome_len3(bcdint in) {
bcdint nib0 = in & 0xF;
bcdint nib1 = (in >> 4) & 0xF;
bcdint high = in >> 8;
bcdint higher = high + 1;
bcdint high_pd = 0x111 * high;
bcdint higher_pd = 0x111 * higher;
if (nib1 < high) return high_pd;
return nib0 > high ? higher_pd : high_pd;
}
static
bcdint next_palindrome_len4(bcdint in) {
bcdint nib0 = in & 0xF;
bcdint nib1 = (in >> 4) & 0xF;
bcdint nib2 = (in >> 8) & 0xF;
bcdint nib3 = in >> 12;
bcdint nib3er = nib3 + 1;
bcdint nib3_pd = 0x1111 * nib3;
bcdint nib3er_pd = 0x1111 * nib3er;
bcdint nib10 = in & 0xFF;
bcdint nib32 = in >> 8;
bcdint nib32er = bcdadd(nib32, 1);
bcdint nib32_pd = 0x0101 * nib32;
bcdint nib32er_pd = 0x0101 * nib32er;
bcdint r = nib3er_pd;
if (nib3_pd > in) r = nib3_pd;
if (nib32er_pd > in) r = nib32er_pd;
if (nib32_pd > in) r = nib32_pd;
return r;
}
static
bcdint next_palindrome_len6(bcdint in) {
bcdint nib0 = in & 0xF;
bcdint nib1 = (in >> 4) & 0xF;
bcdint nib2 = (in >> 8) & 0xF;
bcdint nib3 = (in >> 12) & 0xF;
bcdint nib4 = (in >> 16) & 0xF;
bcdint nib5 = in >> 20;
bcdint nib5er = nib5 + 1;
bcdint nib5_pd = 0x111111 * nib5;
bcdint nib5er_pd = 0x111111 * nib5er;
bcdint nib10 = in & 0xFF;
bcdint nib32 = (in >> 8) & 0xFF;
bcdint nib54 = in >> 16;
bcdint nib54er = bcdadd(nib54, 1);
bcdint nib54_pd = 0x010101 * nib54;
bcdint nib54er_pd = 0x010101 * nib54er;
bcdint nib210 = in & 0xFFF;
bcdint nib543 = in >> 12;
bcdint nib543er = bcdadd(nib543, 1);
bcdint nib543_pd = 0x001001 * nib543;
bcdint nib543er_pd = 0x001001 * nib543er;
bcdint r = nib5er_pd;
if (nib5_pd > in) r = MIN(r,nib5_pd);
if (nib54er_pd > in) r = MIN(r,nib54er_pd);
if (nib54_pd > in) r = MIN(r,nib54_pd);
if (nib543er_pd > in) r = MIN(r,nib543er_pd);
if (nib543_pd > in) r = MIN(r,nib543_pd);
return r;
}
static
bcdint next_palindrome_len8(bcdint in) {
bcdint nib0 = in & 0xF;
bcdint nib1 = (in >> 4) & 0xF;
bcdint nib2 = (in >> 8) & 0xF;
bcdint nib3 = (in >> 12) & 0xF;
bcdint nib4 = (in >> 16) & 0xF;
bcdint nib5 = (in >> 20) & 0xF;
bcdint nib6 = (in >> 24) & 0xF;
bcdint nib7 = in >> 28;
bcdint nib7er = nib7 + 1;
bcdint nib7_pd = 0x11111111 * nib7;
bcdint nib7er_pd = 0x11111111 * nib7er;
bcdint nib10 = in & 0xFF;
bcdint nib32 = (in >> 8) & 0xFF;
bcdint nib54 = (in >> 16) & 0xFF;
bcdint nib76 = in >> 24;
bcdint nib76er = bcdadd(nib76, 1);
bcdint nib76_pd = 0x01010101 * nib76;
bcdint nib76er_pd = 0x01010101 * nib76er;
bcdint nib3210 = in & 0xFFFF;
bcdint nib7654 = in >> 16;
bcdint nib7654er = bcdadd(nib7654, 1);
bcdint nib7654_pd = 0x00010001 * nib7654;
bcdint nib7654er_pd = 0x00010001 * nib7654er;
bcdint r = nib7er_pd;
if (nib7_pd > in) r = MIN(r,nib7_pd);
if (nib76er_pd > in) r = MIN(r,nib76er_pd);
if (nib76_pd > in) r = MIN(r,nib76_pd);
if (nib7654er_pd > in) r = MIN(r,nib7654er_pd);
if (nib7654_pd > in) r = MIN(r,nib7654_pd);
return r;
}
static
bcdint next_palindrome_part2(struct id s) {
if (s.len == 2) return next_palindrome_len2(s.v);
else if (s.len == 3) return next_palindrome_len3(s.v);
else if (s.len == 4) return next_palindrome_len4(s.v);
else if (s.len == 6) return next_palindrome_len6(s.v);
else if (s.len == 8) return next_palindrome_len8(s.v);
unsigned len = s.len;
bcdint in = s.v;
bcdint best = -1;
for (unsigned i = 2; i <= len; i++) {
if (len % i == 0) {
unsigned high_shift = (len / i) * 4;
bcdint high = in >> (high_shift * (i - 1));
for (int j = i - 2; j >= 0; j--) {
bcdint low = (in >> (high_shift * (j))) & ((1 << high_shift) - 1);
if (low < high) {
break;
} else if (low > high) {
high = bcdadd(high, 1);
break;
}
}
bcdint next = 0;
for (unsigned j = 0; j < i; j++) {
next |= high << (high_shift * j);
}
if (next < best) {
best = next;
}
}
}
return best;
}
static
bcdint do_part2(size_t file_len, unsigned char file[file_len]) {
unsigned char *src = file;
bcdint result = 0;
alignas(0x40) struct id ranges[128];
size_t range_count = 0;
do {
unsigned char *tmp;
bcdint rs = grabbcd(src, &tmp);
ranges[range_count * 2 + 0] = (struct id) {
.len = tmp - src,
.v = rs
};
src = tmp + 1;
bcdint re = grabbcd(src, &tmp);
ranges[range_count * 2 + 1] = (struct id) {
.v = re
};
src = tmp + 1;
range_count++;
} while (src != &file[file_len]);
do {
range_count--;
struct id next = ranges[range_count * 2 + 0];
bcdint re = ranges[range_count * 2 + 1].v;
do {
if (next.len == 1) {
next = (struct id) { .len = 2, .v = 0x11 };
} else {
next.v = next_palindrome_part2(next);
}
if (next.v <= re) {
result = bcdadd(result, next.v);
}
bcdint tmp = bcdadd(next.v, 1);
for (bcdint chk = next.v; chk > 0; chk >>= 4) {
if ((chk & 0xF) != 9) goto no_len_change;
}
next.len++;
no_len_change:
next.v = tmp;
} while (next.v <= re);
} while (range_count);
return result;
}
void run() {
print("PART 2 RESULT: ");
printh(do_part2(countof(input), input));
print("\n");
exit_group(0);
}

125
day3.c Normal file
View File

@@ -0,0 +1,125 @@
#include "lib.h"
#define DBG 0
static
unsigned char input[] = {
#embed "day3_input.txt"
};
static
unsigned char test_input[] = {
#embed "day3_test.txt"
};
static
unsigned long do_part1(size_t file_len, unsigned char file[file_len]) {
unsigned long result = 0;
unsigned char *s = file;
do {
unsigned char n0 = 0, n1 = 0;
unsigned char *n0p = NULL;
do {
if (s[0] > n0) {
n0 = s[0];
n0p = s;
}
s++;
} while (s[1] != '\n');
s = n0p+1;
do {
if (s[0] > n1) {
n1 = s[0];
}
s++;
} while (s[0] != '\n');
s++;
unsigned n = (n0 - '0') * 10 + (n1 - '0');
result += n;
} while(s < &file[file_len]);
return result;
}
static
unsigned long do_part2(size_t file_len, unsigned char file[file_len]) {
unsigned long result = 0;
unsigned char *s = file;
do {
unsigned char n[12] = { };
unsigned char *np = NULL;
for (int i = 0; i < 12; i++) {
do {
if (s[0] > n[i]) {
n[i] = s[0];
np = s;
}
s++;
} while (s[11-i] != '\n');
s = np+1;
}
unsigned long v = 0;
for (int i = 0; i < 12; i++) {
v = v * 10 + (n[i] - '0');
}
#if DBG
print("got ");
printd(v);
print("\n");
#endif
result += v;
while (*s != '\n') s++;
s++;
} while(s < &file[file_len]);
return result;
}
#define RUN_TEST1 0
#define RUN_PART1 0
#define RUN_TEST2 1
#define RUN_PART2 1
#define TEST1_EXPECT 357
#define TEST2_EXPECT 3121910778619l
void run() {
#if RUN_TEST1
print("PART 1 TEST: ");
if (unsigned long v = do_part1(countof(test), test); v != TEST1_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST1_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART1
print("PART 1 RESULT: ");
printd(do_part1(countof(input), input));
print("\n");
#endif
#if RUN_TEST2
print("PART 2 TEST: ");
if (unsigned long v = do_part2(countof(test_input), test_input); v != TEST2_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST2_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART2
print("PART 2 RESULT: ");
printd(do_part2(countof(input), input));
print("\n");
#endif
exit_group(0);
}

216
day4.c Normal file
View File

@@ -0,0 +1,216 @@
#include "lib.h"
#define DBG 0
static
unsigned char input[] = {
#embed "day4_input.txt"
};
static
unsigned char test[] = {
#embed "day4_test.txt"
};
alignas (0x40) static
unsigned char buf[UINT16_MAX];
static
unsigned long do_part1(size_t file_len, unsigned char file[file_len]) {
unsigned char *s = file, *d = buf;
unsigned long result = 0;
#if DBG
print("\n");
#endif
unsigned file_stride;
while (*s != '\n') s++;
file_stride = s - file + 1;
s = file;
unsigned line_count = file_len / file_stride;
unsigned line_stride = MAX(file_stride + 1, 0x40);
memset(d, 0, sizeof(buf));
#if DBG
printh(file_stride); print("\n");
printh(line_stride * (line_count + 2)); print("\n");
#endif
#if DBG
printns(line_stride, d); print("\n");
#endif
d += line_stride;
do {
memcpy(d + 1, s, file_stride - 1);
#if DBG
printns(line_stride, d); print("\n");
#endif
d += line_stride;
s += file_stride;
} while (s != &file[file_len]);
#if DBG
printns(line_stride, d); print("\n");
#endif
unsigned char *l = buf + line_stride + 1;
for (unsigned i = line_count; i; i--) {
d = l;
for (unsigned j = file_stride - 1; j; j--) {
if (*d == '@') {
unsigned neighbors = 0
+ (*(d - 1 - line_stride) == '@')
+ (*(d - 0 - line_stride) == '@')
+ (*(d + 1 - line_stride) == '@')
+ (*(d - 1 - 0) == '@')
+ (*(d + 1 - 0) == '@')
+ (*(d - 1 + line_stride) == '@')
+ (*(d - 0 + line_stride) == '@')
+ (*(d + 1 + line_stride) == '@')
+ (*(d - 1 - line_stride) == 'X')
+ (*(d - 0 - line_stride) == 'X')
+ (*(d + 1 - line_stride) == 'X')
+ (*(d - 1 - 0) == 'X')
+ (*(d + 1 - 0) == 'X')
+ (*(d - 1 + line_stride) == 'X')
+ (*(d - 0 + line_stride) == 'X')
+ (*(d + 1 + line_stride) == 'X');
if (neighbors < 4) {
result++;
*d = 'X';
}
}
d++;
}
l += line_stride;
}
return result;
}
static
unsigned long do_part2(size_t file_len, unsigned char file[file_len]) {
unsigned char *s = file, *d = buf;
unsigned long result = 0;
#if DBG
print("\n");
#endif
unsigned file_stride;
while (*s != '\n') s++;
file_stride = s - file + 1;
s = file;
unsigned line_count = file_len / file_stride;
unsigned line_stride = MAX(file_stride + 1, 0x40);
memset(d, 0, sizeof(buf));
#if DBG
printh(file_stride); print("\n");
printh(line_stride * (line_count + 2)); print("\n");
#endif
#if DBG
printns(line_stride, d); print("\n");
#endif
d += line_stride;
do {
memcpy(d + 1, s, file_stride - 1);
#if DBG
printns(line_stride, d); print("\n");
#endif
d += line_stride;
s += file_stride;
} while (s != &file[file_len]);
#if DBG
printns(line_stride, d); print("\n");
#endif
unsigned char *l = buf + line_stride + 1;
for (unsigned i = line_count; i; i--) {
line_start:
d = l;
for (unsigned j = file_stride - 1; j; j--) {
if (*d == '@') {
unsigned neighbors = 0
+ (*(d - 1 - line_stride) == '@')
+ (*(d - 0 - line_stride) == '@')
+ (*(d + 1 - line_stride) == '@')
+ (*(d - 1 - 0) == '@')
+ (*(d + 1 - 0) == '@')
+ (*(d - 1 + line_stride) == '@')
+ (*(d - 0 + line_stride) == '@')
+ (*(d + 1 + line_stride) == '@');
if (neighbors < 4) {
(*((volatile unsigned long *)&result))++;
*(volatile unsigned char *)d = '.';
if (i > line_count-1) {
i = line_count;
l = buf + line_stride + 1;
goto line_start;
} else {
i += 1;
l -= line_stride * 1;
goto line_start;
}
}
}
d++;
}
l += line_stride;
}
return result;
}
#define RUN_TEST1 1
#define RUN_PART1 0
#define RUN_TEST2 1
#define RUN_PART2 0
#define TEST1_EXPECT 13
#define TEST2_EXPECT 43
void run() {
#if RUN_TEST1
print("PART 1 TEST: ");
if (unsigned long v = do_part1(countof(test), test); v != TEST1_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST1_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART1
print("PART 1 RESULT: ");
printd(do_part1(countof(input), input));
print("\n");
#endif
#if RUN_TEST2
print("PART 2 TEST: ");
if (unsigned long v = do_part2(countof(test), test); v != TEST2_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST2_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART2
print("PART 2 RESULT: ");
printd(do_part2(countof(input), input));
print("\n");
#endif
exit_group(0);
}

236
day5.c Normal file
View File

@@ -0,0 +1,236 @@
#include "lib.h"
#include <stdlib.h>
#define DBG 0
#define PRETTY 1
static
unsigned char input[] = {
#embed "day5_input.txt"
};
static
unsigned char test[] = {
#embed "day5_test.txt"
};
#if PRETTY
struct line {
union {
unsigned char l[64];
struct {
unsigned char s[16];
unsigned char pad0[4];
unsigned char e[16];
unsigned char pad1[4];
num sv;
num ev;
};
};
};
static_assert(sizeof(struct line) == 0x40);
#else
struct line {
num sv;
num ev;
};
#endif
alignas(0x40) static
struct line ranges[256];
static
int linecmp(const void *av, const void *bv) {
const struct line *a = av;
const struct line *b = bv;
if (a->sv < b->sv) return -1;
else if (a->sv > b->sv) return 1;
else return 0;
}
static
unsigned long do_part1(size_t file_len, unsigned char file[file_len]) {
unsigned char *s = file;
unsigned long result = 0;
memset(ranges, 0, sizeof(ranges));
#if DBG
print("\n");
#endif
struct line *d = ranges;
do {
unsigned char *tmp;
d->sv = grabbcd(s, &tmp);
#if PRETTY
memcpy(d->s, s, tmp - s);
#endif
s = tmp;
s++;
d->ev = grabbcd(s, &tmp);
#if PRETTY
memcpy(d->e, s, tmp - s);
#endif
s = tmp;
s++;
d++;
} while (*s != '\n');
#if PRETTY
size_t range_cnt = d - ranges;
qsort(ranges, range_cnt, sizeof(*ranges), linecmp);
#endif
d->sv = 0;
s++;
do {
bcdint id = grabbcd(s, &s);
for (d = ranges; d->sv; d++) {
bcdint ds = d->sv;
bcdint de = d->ev;
if (id >= ds && id <= de) {
result++;
goto next_id;
}
}
next_id:
s++;
} while (s != &file[file_len]);
return result;
}
static
unsigned long do_part2(size_t file_len, unsigned char file[file_len]) {
unsigned char *s = file;
unsigned long result = 0;
memset(ranges, 0, sizeof(ranges));
#if DBG
print("\n");
#endif
struct line *d = ranges;
do {
unsigned char *tmp;
d->sv = grabbcd(s, &tmp);
#if PRETTY
snprinth(d->sv, sizeof(d->s), d->s);
#endif
s = tmp;
s++;
d->ev = grabbcd(s, &tmp);
#if PRETTY
snprinth(d->ev, sizeof(d->e), d->e);
#endif
s = tmp;
s++;
d++;
} while (*s != '\n');
size_t range_cnt = d - ranges;
qsort(ranges, range_cnt, sizeof(*ranges), linecmp);
d->sv = 0;
outer:
for (struct line *di = ranges; di->sv; di++) {
bcdint dis = di->sv;
bcdint die = di->ev;
if (dis == -1) continue;
for (struct line *dj = di+1; dj->sv; dj++) {
bcdint djs = dj->sv;
bcdint dje = dj->ev;
if (djs == -1) continue;
if (djs > die) continue outer;
if (djs <= die && djs >= dis) {
djs = bcdadd(die, 1);
}
if (djs == dj->sv && dje == dj->ev)
continue;
if (dje < djs) {
#if DBG
print("FOR: "); printd(dis); print(" "); printd(die); print("\n");
print(" "); printd(dj->sv); print(" "); printd(dj->ev); print("\n");
print(" -> "); printd(djs); print(" "); printd(dje); print(" BAD\n");
#endif
dj->sv = -1;
dj->ev = -1;
#if PRETTY
snprinth(dj->sv, sizeof(dj->s), dj->s);
snprinth(dj->ev, sizeof(dj->e), dj->e);
#endif
} else {
#if DBG
print("FOR: "); printd(dis); print(" "); printd(die); print("\n");
print(" "); printd(dj->sv); print(" "); printd(dj->ev); print("\n");
print(" -> "); printd(djs); print(" "); printd(dje); print("\n");
#endif
dj->sv = djs;
dj->ev = dje;
#if PRETTY
snprinth(dj->sv, sizeof(dj->s), dj->s);
snprinth(dj->ev, sizeof(dj->e), dj->e);
#endif
}
}
}
for (struct line *di = ranges; di->sv; di++) {
if (di->sv == -1) continue;
unsigned long dis = bcdtonum(di->sv);
unsigned long die = bcdtonum(di->ev);
result += die - dis + 1;
}
return result;
}
#define RUN_TEST1 1
#define RUN_PART1 1
#define RUN_TEST2 1
#define RUN_PART2 1
#define TEST1_EXPECT 3
#define TEST2_EXPECT 14
void run() {
#if RUN_TEST1
print("PART 1 TEST: ");
if (unsigned long v = do_part1(countof(test), test); v != TEST1_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST1_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART1
print("PART 1 RESULT: ");
printd(do_part1(countof(input), input));
print("\n");
#endif
#if RUN_TEST2
print("PART 2 TEST: ");
if (unsigned long v = do_part2(countof(test), test); v != TEST2_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST2_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART2
print("PART 2 RESULT: ");
printd(do_part2(countof(input), input));
print("\n");
#endif
exit_group(0);
}

228
day6.c Normal file
View File

@@ -0,0 +1,228 @@
#include "lib.h"
#define DBG 0
static
ch input[] = {
#embed "day6_input.txt"
};
static
ch test[] = {
#embed "day6_test.txt"
};
static
num do_part1(size_t file_len, ch file[file_len]) {
ch *s = file;
num result = 0;
s = memchr(s, '\n', file_len);
num stride = s - file;
s = file;
while (*s != '+' && *s != '*') s += stride;
num heightb = (s - file);
num height = (s - file) / stride;
ch *op = s;
// constructing a pointer more than 1 past the end of an array
// is UB, sadly, so we'll use offsets
num op_off = op - file;
s = file;
do {
num ledge_off = op_off - heightb;
if (s[op_off] == '+') {
num a = 0;
num rem = height;
do {
ch *t = s + ledge_off;
while (*t < '0') t++;
num b = grabnum(t, NULL);
a += b;
ledge_off += stride;
rem--;
} while (rem);
result += a;
} else if (s[op_off] == '*') {
num a = 1;
num rem = height;
do {
ch *t = s + ledge_off;
while (*t < '0') t++;
num b = grabnum(t, NULL);
#if DBG
if (rem < height) { print("\t*\t"); }
printd(b);
#endif
a *= b;
ledge_off += stride;
rem--;
} while (rem);
result += a;
#if DBG
print("\t= "); printd(a); print("\n");
#endif
}
#if DBG
else {
print("INVALID OP\n");
exit_group(-1);
}
#endif
op_off++;
while (op_off < file_len) {
if (s[op_off] == '+' || s[op_off] == '*')
break;
op_off++;
}
} while (op_off < file_len);
return result;
}
static
num do_part2(size_t file_len, unsigned char file[file_len]) {
ch *s = file;
num result = 0;
#if DBG
print("\n");
#endif
s = memchr(s, '\n', file_len);
num stride = s - file;
s = file;
while (*s != '+' && *s != '*') s += stride;
num heightb = (s - file);
num height = (s - file) / stride;
ch *op = s;
#if DBG
print("STRIDE\t"); printd(stride); print("\n");
print("HEIGHT\t"); printd(height); print("\n");
#endif
// constructing a pointer more than 1 past the end of an array
// is UB, sadly, so we'll use offsets
num fop_off = op - file;
num prev_op_off = fop_off + stride - 1;
s = file;
do {
// we don't need to do these in the same order as the example
// because both these operations are commutative.
// but you know what? we can anyway. for fun. and pretty output
num op_off = prev_op_off - 1;
while (s[op_off] != '+' && s[op_off] != '*' && s[op_off] != '\n')
op_off--;
num ledge_off = op_off - heightb;
num redge_off = (s[prev_op_off] == '\n' ? -1 : -2) + prev_op_off - heightb;
if (s[op_off] == '+') {
num a = 0;
num rem = redge_off - ledge_off + 1;
num frem = rem;
do {
num b = 0;
ch *t = s + redge_off;
for (num i = height; i; i--,t+=stride) {
if (*t >= '0') {
b *= 10;
b += *t - '0';
}
}
#if DBG
if (rem < frem) { print("\t+\t"); }
printd(b);
#endif
a += b;
redge_off--;
rem--;
} while (rem);
result += a;
#if DBG
print("\t=\t"); printd(a); print("\n");
#endif
} else if (s[op_off] == '*') {
num a = 1;
num rem = redge_off - ledge_off + 1;
num frem = rem;
do {
num b = 0;
ch *t = s + redge_off;
for (num i = height; i; i--,t+=stride) {
if (*t >= '0') {
b *= 10;
b += *t - '0';
}
}
#if DBG
if (rem < frem) { print("\t*\t"); }
printd(b);
#endif
a *= b;
redge_off--;
rem--;
} while (rem);
result += a;
#if DBG
print("\t=\t"); printd(a); print("\n");
#endif
}
#if DBG
else {
print("INVALID OP\n");
exit_group(-1);
}
#endif
prev_op_off = op_off;
} while (prev_op_off != fop_off);
return result;
}
#define RUN_TEST1 1
#define RUN_PART1 1
#define RUN_TEST2 1
#define RUN_PART2 1
#define TEST1_EXPECT 4277556
#define TEST2_EXPECT 3263827
void run() {
#if RUN_TEST1
print("PART 1 TEST: ");
if (num v = do_part1(countof(test), test); v != TEST1_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST1_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART1
print("PART 1 RESULT: ");
printd(do_part1(countof(input), input));
print("\n");
#endif
#if RUN_TEST2
print("PART 2 TEST: ");
if (num v = do_part2(countof(test), test); v != TEST2_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST2_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART2
print("PART 2 RESULT: ");
printd(do_part2(countof(input), input));
print("\n");
#endif
exit_group(0);
}

228
day6pretty.c Normal file
View File

@@ -0,0 +1,228 @@
#include "lib.h"
static
ch input[] = {
#embed "day6_input.txt"
};
static
ch test[] = {
#embed "day6_test.txt"
};
typedef struct { ch l[64]; } line;
static_assert(sizeof(line) == 0x40);
alignas(0x40) static
struct {
line padstart[4];
struct { num pad[3]; num prev_op_off, op_off, ledge_off, redge_off, rem; };
union { line l; struct { ch s[16]; num op, pad0, pad1, v; }; } b;
union { line l; struct { ch s[16], pad0, sr[16], pad1; num v, vr; }; } a;
line padend;
} m;
static_assert(offsetof(typeof(m),b) % 64 == 0);
static_assert(sizeof(m.b) == 64);
static_assert(sizeof(m.a) == 64);
static_assert(offsetof(typeof(m),padend) % 64 == 0);
static
num do_part1(size_t file_len, ch file[file_len]) {
ch *s = file;
m = (typeof(m)){ };
s = memchr(s, '\n', file_len);
const num stride = s - file;
s = file;
while (*s != '+' && *s != '*') s += stride;
const num heightb = (s - file);
const num height = (s - file) / stride;
ch *const op = s;
// constructing a pointer more than 1 past the end of an array
// is UB, sadly, so we'll use offsets
m.op_off = op - file;
s = file;
do {
m.ledge_off = m.op_off - heightb;
if (s[m.op_off] == '+') {
m.a.v = 0;
m.rem = height;
m.b.op = '+' << 8;
snprintd(m.a.v, 16, m.a.s);
do {
ch *t = s + m.ledge_off;
while (*t < '0') t++;
m.b.v = grabnum(t, NULL);
snprintd(m.b.v, 16, m.b.s);
m.a.v += m.b.v;
snprintd(m.a.v, 16, m.a.s);
m.ledge_off += stride;
m.rem--;
} while (m.rem);
m.a.vr += m.a.v;
snprintd(m.a.vr, 16, m.a.sr);
} else if (s[m.op_off] == '*') {
m.a.v = 1;
m.rem = height;
m.b.op = '*' << 8;
snprintd(m.a.v, 16, m.a.s);
do {
ch *t = s + m.ledge_off;
while (*t < '0') t++;
m.b.v = grabnum(t, NULL);
snprintd(m.b.v, 16, m.b.s);
m.a.v *= m.b.v;
snprintd(m.a.v, 16, m.a.s);
m.ledge_off += stride;
m.rem--;
} while (m.rem);
m.a.vr += m.a.v;
snprintd(m.a.vr, 16, m.a.sr);
}
m.op_off++;
while (m.op_off < file_len) {
if (s[m.op_off] == '+' || s[m.op_off] == '*')
break;
m.op_off++;
}
} while (m.op_off < file_len);
return m.a.vr;
}
static
num do_part2(size_t file_len, unsigned char file[file_len]) {
ch *s = file;
m = (typeof(m)){ };
s = memchr(s, '\n', file_len);
const num stride = s - file;
s = file;
while (*s != '+' && *s != '*') s += stride;
const num heightb = (s - file);
const num height = (s - file) / stride;
ch *const op = s;
// constructing a pointer more than 1 past the end of an array
// is UB, sadly, so we'll use offsets
const num fop_off = op - file;
m.prev_op_off = fop_off + stride - 1;
s = file;
do {
// we don't need to do these in the same order as the example
// because both these operations are commutative.
// but you know what? we can anyway. for fun. and pretty output
{
num op_off = m.prev_op_off - 1;
while (s[op_off] != '+' && s[op_off] != '*' && s[op_off] != '\n')
op_off--;
m.op_off = op_off;
}
m.ledge_off = m.op_off - heightb;
m.redge_off = (s[m.prev_op_off] == '\n' ? -1 : -2) + m.prev_op_off - heightb;
if (s[m.op_off] == '+') {
m.a.v = 0;
m.rem = m.redge_off - m.ledge_off + 1;
const num frem = m.rem;
m.b.op = '+' << 8;
snprintd(m.a.v, 16, m.a.s);
do {
m.b.v = 0;
ch *t = s + m.redge_off;
for (num i = height; i; i--,t+=stride) {
if (*t >= '0') {
m.b.v *= 10;
m.b.v += *t - '0';
}
}
snprintd(m.b.v, 16, m.b.s);
m.a.v += m.b.v;
snprintd(m.a.v, 16, m.a.s);
m.redge_off--;
m.rem--;
} while (m.rem);
m.a.vr += m.a.v;
snprintd(m.a.vr, 16, m.a.sr);
} else if (s[m.op_off] == '*') {
m.a.v = 1;
m.rem = m.redge_off - m.ledge_off + 1;
const num frem = m.rem;
m.b.op = '*' << 8;
snprintd(m.a.v, 16, m.a.s);
do {
m.b.v = 0;
ch *t = s + m.redge_off;
for (num i = height; i; i--,t+=stride) {
if (*t >= '0') {
m.b.v *= 10;
m.b.v += *t - '0';
}
}
snprintd(m.b.v, 16, m.b.s);
m.a.v *= m.b.v;
snprintd(m.a.v, 16, m.a.s);
m.redge_off--;
m.rem--;
} while (m.rem);
m.a.vr += m.a.v;
snprintd(m.a.vr, 16, m.a.sr);
}
m.prev_op_off = m.op_off;
} while (m.prev_op_off != fop_off);
return m.a.vr;
}
#define RUN_TEST1 1
#define RUN_PART1 1
#define RUN_TEST2 1
#define RUN_PART2 1
#define TEST1_EXPECT 4277556
#define TEST2_EXPECT 3263827
void run() {
#if RUN_TEST1
print("PART 1 TEST: ");
if (num v = do_part1(countof(test), test); v != TEST1_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST1_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART1
print("PART 1 RESULT: ");
printd(do_part1(countof(input), input));
print("\n");
#endif
#if RUN_TEST2
print("PART 2 TEST: ");
if (num v = do_part2(countof(test), test); v != TEST2_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST2_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART2
print("PART 2 RESULT: ");
printd(do_part2(countof(input), input));
print("\n");
#endif
exit_group(0);
}

178
day7.c Normal file
View File

@@ -0,0 +1,178 @@
#include "lib.h"
#define DBG 0
static
ch input[32768] = {
#embed "day7_input.txt"
};
static
ch test[512] = {
#embed "day7_test.txt"
};
typedef struct { ch l[64]; } line;
static_assert(sizeof(line) == 0x40);
alignas(0x40) static
struct {
line padstart[4];
num file_stride;
num stride;
num _extra[6];
union { line l; struct { ch s[16]; num n; }; } result;
line padend;
} m;
static_assert(offsetof(typeof(m),result) % 64 == 0);
static_assert(offsetof(typeof(m),padend) % 64 == 0);
alignas(4096) ch buf1[256];
alignas(4096) num buf[256];
static
num do_part1(size_t file_len, ch file[file_len]) {
m = (typeof(m)){ };
m.result.n = 0;
#if DBG
pnl();
#endif
memset(buf1, 0, sizeof(buf1));
m.file_stride = findc(file, '\n', file_len) - file;
num linecnt = (findc(file, 0, file_len) - file) / m.file_stride;
#if DBG
print("stride "); printd(m.file_stride); pnl();
print("lines "); printd(linecnt); pnl();
#endif
num s_pos = findc(file, 'S', - 1) - 1 - file;
buf1[s_pos] = '|';
num line = 2;
do {
ch *l = file + line * m.file_stride;
for (num col = 0; col < m.file_stride - 1; col++) {
ch c = l[col];
if (c == '^') {
m.result.n += buf1[col] > 0;
buf1[col-1] |= buf1[col];
buf1[col+1] |= buf1[col];
buf1[col] = 0;
}
}
#if DBG
for (num col = 0; col < m.file_stride; col++) {
if (buf1[col] == '|') print("|");
else if (l[col] == '^') print("^");
else print(" ");
}
pnl();
#endif
line+=2;
} while (line < linecnt);
return m.result.n;
}
static
num do_part2(size_t file_len, ch file[file_len]) {
m = (typeof(m)){ };
#if DBG
pnl();
#endif
memset(buf, 0, sizeof(buf));
m.file_stride = findc(file, '\n', file_len) - file;
num linecnt = (findc(file, 0, file_len) - file) / m.file_stride;
#if DBG
print("stride "); printd(m.file_stride); pnl();
print("lines "); printd(linecnt); pnl();
#endif
num s_pos = findc(file, 'S', - 1) - 1 - file;
buf[s_pos] = 1;
num line = 2;
do {
ch *l = file + line * m.file_stride;
for (num col = 0; col < m.file_stride - 1; col++) {
ch c = l[col];
if (c == '^') {
buf[col-1] += buf[col];
buf[col+1] += buf[col];
buf[col] = 0;
}
}
for (num col = 0; col < m.file_stride; col++) {
num v = buf[col];
#if DBG
if (l[col] == '^') print(" ");
else if (v >> 32) print("");
else if (v >> 16) print("");
else if (v >> 8) print("");
else if (v >> 4) print("");
else if (v >> 2) print("-");
else if (v >> 0) print(".");
else print(" ");
#endif
}
#if DBG
pnl();
#endif
line+=2;
} while (line < linecnt);
m.result.n = 0;
for (num col = 0; col < m.file_stride; col++) {
m.result.n += buf[col];
}
return m.result.n;
}
#define RUN_TEST1 1
#define RUN_PART1 1
#define RUN_TEST2 1
#define RUN_PART2 1
#define TEST1_EXPECT 21
#define TEST2_EXPECT 40
void run() {
#if RUN_TEST1
print("PART 1 TEST: ");
if (num v = do_part1(countof(test), test); v != TEST1_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST1_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART1
print("PART 1 RESULT: ");
printd(do_part1(countof(input), input));
print("\n");
#endif
#if RUN_TEST2
print("PART 2 TEST: ");
if (num v = do_part2(countof(test), test); v != TEST2_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST2_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART2
print("PART 2 RESULT: ");
printd(do_part2(countof(input), input));
print("\n");
#endif
exit_group(0);
}

317
day8.c Normal file
View File

@@ -0,0 +1,317 @@
#include "lib.h"
#include <stdlib.h>
#define DBG 0
static
ch input[] = {
#embed "day8_input.txt"
};
static
ch test[] = {
#embed "day8_test.txt"
};
typedef num point __attribute__((vector_size(4*sizeof(num))));
alignas(64) static
point positions[1000];
alignas(64) static
unsigned short circuits[1000];
alignas(1024) static
struct { num min_dist; unsigned short min_target; } targets[1000][1024];
alignas(64) static
unsigned short next_targets[1000];
alignas(64) static
num next_dists[1000];
alignas(64) static
unsigned short next_indices[1000];
static
int targetcompar(const void *a, const void *b) {
const num ad = ((typeof(**targets)*)a)->min_dist;
const num bd = ((typeof(**targets)*)b)->min_dist;
if (ad > bd) return 1;
else if (ad < bd) return -1;
else return 0;
}
static
num do_part1(size_t file_len, ch file[file_len], bool istest) {
const num iters = istest ? 10 : 1000;
const num pointcount = istest ? 20 : 1000;
num iter = 0;
#if DBG
pnl();
#endif
// read in positions from file
{ ch *s = file;
for (num i = 0; i < pointcount; i++) {
unsigned x = grabnum(s, &s);
s++;
unsigned y = grabnum(s, &s);
s++;
unsigned z = grabnum(s, &s);
s++;
positions[i] = (point){ x,y,z };
} }
// set up initial circuits
for (num i = 0; i < pointcount; i += 4) {
circuits[i+0] = i+0;
circuits[i+1] = i+1;
circuits[i+2] = i+2;
circuits[i+3] = i+3;
}
// find distances between all points
for (num i = 0; i < pointcount; i++) {
point pi = positions[i];
for (num j = 0; j < pointcount; j += 4) {
point pj0 = positions[j+0];
point pj1 = positions[j+1];
point pj2 = positions[j+2];
point pj3 = positions[j+3];
point dvp0 = (pi - pj0) * (pi - pj0);
point dvp1 = (pi - pj1) * (pi - pj1);
point dvp2 = (pi - pj2) * (pi - pj2);
point dvp3 = (pi - pj3) * (pi - pj3);
num d0 = dvp0[0] + dvp0[1] + dvp0[2] + dvp0[3];
num d1 = dvp1[0] + dvp1[1] + dvp1[2] + dvp1[3];
num d2 = dvp2[0] + dvp2[1] + dvp2[2] + dvp2[3];
num d3 = dvp3[0] + dvp3[1] + dvp3[2] + dvp3[3];
targets[i][j+0] = (typeof(**targets)) { d0, j+0 };
targets[i][j+1] = (typeof(**targets)) { d1, j+1 };
targets[i][j+2] = (typeof(**targets)) { d2, j+2 };
targets[i][j+3] = (typeof(**targets)) { d3, j+3 };
}
// sort targets. slow.
qsort(targets[i], pointcount, sizeof(**targets), targetcompar);
}
// set up initial next targets
for (num i = 0; i < pointcount; i++) {
next_targets[i] = targets[i][1].min_target;
next_dists[i] = targets[i][1].min_dist;
next_indices[i] = 1;
}
// FIXED JOIN ITERATIONS
do {
// find min dist
num min_dist = -1;
num min_i = 0;
for (num i = 0; i < pointcount; i++)
if (next_dists[i] < min_dist)
min_dist = next_dists[min_i = i];
num min_j = next_targets[min_i];
// -- join the pair --
#if DBG
point ipos = positions[min_i];
point jpos = positions[min_j];
printd(ipos[0]); print(","); printd(ipos[1]); print(","); printd(ipos[2]);
print("\t->\t");
printd(jpos[0]); print(","); printd(jpos[1]); print(","); printd(jpos[2]);
pnl();
#endif
// update circuits
unsigned old_circuit = circuits[min_j];
unsigned new_circuit = circuits[min_i];
if (old_circuit != new_circuit) {
for (num c = 0; c < pointcount; c++)
if (circuits[c] == old_circuit)
circuits[c] = new_circuit;
}
// update targets
unsigned niidx = ++next_indices[min_i];
unsigned njidx = ++next_indices[min_j];
next_targets[min_i] = targets[min_i][niidx].min_target;
next_targets[min_j] = targets[min_j][njidx].min_target;
next_dists[min_i] = targets[min_i][niidx].min_dist;
next_dists[min_j] = targets[min_j][njidx].min_dist;
iter++;
} while(iter < iters);
// reuse next_targets to store circuit counts
for (num i = 0; i < pointcount; i++) {
next_targets[i] = 0;
}
for (num i = 0; i < pointcount; i++) {
next_targets[circuits[i]]++;
}
num circ0 = 0, circ1 = 0, circ2 = 0;
for (num i = 0; i < pointcount; i++) {
if (next_targets[i] > circ0) {
circ2 = circ1;
circ1 = circ0;
circ0 = next_targets[i];
} else if (next_targets[i] > circ1) {
circ2 = circ1;
circ1 = next_targets[i];
} else if (next_targets[i] > circ2) {
circ2 = next_targets[i];
}
}
return circ0 * circ1 * circ2;
}
static
num do_part2(size_t file_len, ch file[file_len], bool istest) {
const num pointcount = istest ? 20 : 1000;
#if DBG
pnl();
#endif
// read in positions from file
{ ch *s = file;
for (num i = 0; i < pointcount; i++) {
unsigned x = grabnum(s, &s);
s++;
unsigned y = grabnum(s, &s);
s++;
unsigned z = grabnum(s, &s);
s++;
positions[i] = (point){ x,y,z };
} }
// set up initial circuits
for (num i = 0; i < pointcount; i += 4) {
circuits[i+0] = i+0;
circuits[i+1] = i+1;
circuits[i+2] = i+2;
circuits[i+3] = i+3;
}
// find distances between all points
for (num i = 0; i < pointcount; i++) {
point pi = positions[i];
for (num j = 0; j < pointcount; j += 4) {
point pj0 = positions[j+0];
point pj1 = positions[j+1];
point pj2 = positions[j+2];
point pj3 = positions[j+3];
point dvp0 = (pi - pj0) * (pi - pj0);
point dvp1 = (pi - pj1) * (pi - pj1);
point dvp2 = (pi - pj2) * (pi - pj2);
point dvp3 = (pi - pj3) * (pi - pj3);
num d0 = dvp0[0] + dvp0[1] + dvp0[2] + dvp0[3];
num d1 = dvp1[0] + dvp1[1] + dvp1[2] + dvp1[3];
num d2 = dvp2[0] + dvp2[1] + dvp2[2] + dvp2[3];
num d3 = dvp3[0] + dvp3[1] + dvp3[2] + dvp3[3];
targets[i][j+0] = (typeof(**targets)) { d0, j+0 };
targets[i][j+1] = (typeof(**targets)) { d1, j+1 };
targets[i][j+2] = (typeof(**targets)) { d2, j+2 };
targets[i][j+3] = (typeof(**targets)) { d3, j+3 };
}
// sort targets. slow.
qsort(targets[i], pointcount, sizeof(**targets), targetcompar);
}
// set up initial next targets
for (num i = 0; i < pointcount; i++) {
next_targets[i] = targets[i][1].min_target;
next_dists[i] = targets[i][1].min_dist;
next_indices[i] = 1;
}
unsigned last_i = 0, last_j = 0;
// main iterations
do {
// find min dist
num min_dist = -1;
num min_i = 0;
for (num i = 0; i < pointcount; i++)
if (next_dists[i] < min_dist)
min_dist = next_dists[min_i = i];
num min_j = next_targets[min_i];
last_i = min_i;
last_j = min_j;
// -- join the pair --
#if DBG
point ipos = positions[min_i];
point jpos = positions[min_j];
printd(ipos[0]); print(","); printd(ipos[1]); print(","); printd(ipos[2]);
print("\t->\t");
printd(jpos[0]); print(","); printd(jpos[1]); print(","); printd(jpos[2]);
pnl();
#endif
// update circuits
unsigned old_circuit = circuits[min_j];
unsigned new_circuit = circuits[min_i];
if (old_circuit != new_circuit) {
bool done = true;
for (num c = 0; c < pointcount; c++) {
if (circuits[c] == old_circuit)
circuits[c] = new_circuit;
if (circuits[c] != new_circuit)
done = false;
}
if (done) break;
}
// update targets
unsigned niidx = ++next_indices[min_i];
unsigned njidx = ++next_indices[min_j];
next_targets[min_i] = targets[min_i][niidx].min_target;
next_targets[min_j] = targets[min_j][njidx].min_target;
next_dists[min_i] = targets[min_i][niidx].min_dist;
next_dists[min_j] = targets[min_j][njidx].min_dist;
} while(true);
return positions[last_i][0] * positions[last_j][0];
}
#define RUN_TEST1 1
#define RUN_PART1 1
#define RUN_TEST2 1
#define RUN_PART2 1
#define TEST1_EXPECT 40
#define TEST2_EXPECT 25272
void run() {
#if RUN_TEST1
print("PART 1 TEST: ");
if (num v = do_part1(countof(test), test, true); v != TEST1_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST1_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART1
print("PART 1 RESULT: ");
printd(do_part1(countof(input), input, false));
print("\n");
#endif
#if RUN_TEST2
print("PART 2 TEST: ");
if (num v = do_part2(countof(test), test, true); v != TEST2_EXPECT) {
print("FAILED (got ");
printd(v);
print(", expected " xstr(TEST2_EXPECT) ")\n");
} else {
print("PASSED\n");
}
#endif
#if RUN_PART2
print("PART 2 RESULT: ");
printd(do_part2(countof(input), input, false));
print("\n");
#endif
exit_group(0);
}

288
lib.h Normal file
View File

@@ -0,0 +1,288 @@
#pragma once
#include <stddef.h>
#include <stdcountof.h>
#include <stdint.h>
#include <string.h>
#define SYS_write 1
#define SYS_exit_group 231
#define STDOUT_FILENO 1
static
void write(uint64_t fileno, void *buffer, size_t len) {
uint64_t a,d;
asm volatile("syscall"
:"=a"(a),"=d"(d)
:"a"(SYS_write),"D"(fileno),"S"(buffer),"d"(len)
:"cc","memory","%rcx","%r11");
}
[[noreturn]] static
void exit_group(uint64_t code) {
asm volatile(
"syscall\n"
"ud2"
::"a"(SYS_exit_group),"D"(code));
for (;;);
}
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define xstr(s) str(s)
#define str(s) #s
typedef uint64_t bcdint;
typedef uint64_t num;
typedef unsigned char ch;
__attribute__((always_inline)) inline
ch *findc(const ch *s, ch c, size_t n) {
uint64_t dispose;
void *d;
asm("repnz scasb":"=D"(d),"=c"(dispose):"D"(s),"c"(n),"a"(c):"memory","cc");
return d;
}
__attribute__((always_inline)) inline
num *findnum(const num *s, num c, size_t n) {
uint64_t dispose;
void *d;
asm("repnz scasq":"=D"(d),"=c"(dispose):"D"(s),"c"(n),"a"(c):"memory","cc");
return d;
}
__attribute__((always_inline)) inline
num *findnotnum(const num *s, num c, size_t n) {
uint64_t dispose;
void *d;
asm("repz scasq":"=D"(d),"=c"(dispose):"D"(s),"c"(n),"a"(c):"memory","cc");
return d;
}
static inline num alignnum(num v, num align) {
num extra = v % align;
num adjust = (align - extra) % align;
return v + adjust;
}
static
void printns(size_t len, unsigned char chars[len]) {
write(STDOUT_FILENO, chars, len);
}
static
void printptr(uintptr_t v) {
char buf[sizeof(uintptr_t)*2] = { };
char *p = buf+countof(buf);
for (size_t i = 0; i < countof(buf); i++) {
p--;
if ((v & 0x0F) < 0xA) {
*p = '0' + (v & 0x0F);
} else {
*p = 'A' - 0xA + (v & 0x0F);
}
v >>= 4;
}
write(STDOUT_FILENO, p, countof(buf));
}
static
void print_many_char(size_t len, char chars[len]) {
write(STDOUT_FILENO, chars, len);
}
#define print(string) print_many_char(sizeof(string)-1, string)
#define pnl() print("\n")
static
void printd(unsigned long v) {
if (!v) {
print("0");
return;
}
char buf[32];
char *p = buf+32;
unsigned count = 0;
while (v) {
p--;
*p = '0' + (v % 10);
v /= 10;
count++;
}
write(STDOUT_FILENO, p, count);
}
static
void snprintd(unsigned long v, size_t n, unsigned char d[n]) {
memset(d, 0, n);
if (!v) {
d[n-1] = '0';
return;
}
unsigned char *p = d+n;
unsigned count = 0;
while (v) {
p--;
*p = '0' + (v % 10);
v /= 10;
if (p == d) return;
}
}
static
void printh(unsigned long v) {
if (!v) {
print("0");
return;
}
char buf[32];
char *p = buf+32;
unsigned count = 0;
while (v) {
p--;
if ((v & 0x0F) < 0xA) {
*p = '0' + (v & 0x0F);
} else {
*p = 'A' - 0xA + (v & 0x0F);
}
v >>= 4;
count++;
}
write(STDOUT_FILENO, p, count);
}
static
void snprinth(unsigned long v, size_t n, unsigned char d[n]) {
memset(d, 0, n);
if (!v) {
d[n-1] = '0';
return;
}
unsigned char *p = d+n;
unsigned count = 0;
while (v) {
p--;
if ((v & 0x0F) < 0xA) {
*p = '0' + (v & 0x0F);
} else {
*p = 'A' - 0xA + (v & 0x0F);
}
v >>= 4;
if (p == d) return;
}
}
static
void print_hex_char(unsigned char v) {
char buf[2];
if ((v >> 4) < 0x0A) {
buf[0] = '0' + (v >> 4);
} else {
buf[0] = 'A' - 0xA + (v >> 4);
}
if ((v & 0x0F) < 0xA) {
buf[1] = '0' + (v & 0x0F);
} else {
buf[1] = 'A' - 0xA + (v & 0x0F);
}
write(STDOUT_FILENO, buf, sizeof(buf));
}
static
void print_pre_hex(size_t len, unsigned char prefix[len], unsigned long v) {
printns(len, prefix);
printh(v);
}
static
void print_pre_ptr(size_t len, unsigned char prefix[len], void *ptr) {
printns(len, prefix);
printptr((uintptr_t)ptr);
}
#define print_watch_ptr(expr) print_pre_ptr(\
sizeof(#expr ": ")-1, (unsigned char*)(#expr ": "), expr)
#define print_watch_hex(expr) print_pre_hex(\
sizeof(#expr ": ")-1, (unsigned char*)(#expr ": "), expr)
static
bcdint grabbcd(unsigned char *s, unsigned char **end) {
bcdint r = 0;
for (; *s >= '0' && *s <= '9'; s++)
r = (r << 4) + (*s - '0');
if (end) *end = s;
return r;
}
static
unsigned long grabnum(unsigned char *s, unsigned char **end) {
unsigned long r = 0;
for (; *s >= '0' && *s <= '9'; s++)
r = r * 10 + (*s - '0');
if (end) *end = s;
return r;
}
// from wikipedia, the free encyclopedia
// https://en.wikipedia.org/wiki/Binary-coded_decimal
static bcdint bcdadd(bcdint a, bcdint b) {
bcdint t1, t2;
t1 = a + 0x0666666666666666;
t2 = t1 ^ b;
t1 = t1 + b;
t2 = t1 ^ t2;
t2 = ~t2 & 0x1111111111111110;
t2 = (t2 >> 2) | (t2 >> 3);
return t1 - t2;
}
// https://homepage.cs.uiowa.edu/~jones/bcd/bcd.html
static bcdint bcdcomp(bcdint a) {
bcdint t1, t2, t3, t4, t5, t6;
t1 = 0xFFFFFFFFFFFFFFFF - a;
t2 = - a;
t3 = t1 ^ 0x0000000000000001;
t4 = t2 ^ t3;
t5 = ~t4 & 0x1111111111111110;
t6 = (t5 >> 2) | (t5 >> 3);
return t2 - t6;
}
static bcdint bcdsub(bcdint a, bcdint b) {
return bcdadd(a, bcdcomp(b));
}
static num bcdtonum(bcdint a) {
return 0
+ ((a >> 0) & 0xF) * 1
+ ((a >> 4) & 0xF) * 10
+ ((a >> 8) & 0xF) * 100
+ ((a >> 12) & 0xF) * 1000
+ ((a >> 16) & 0xF) * 10000
+ ((a >> 20) & 0xF) * 100000
+ ((a >> 24) & 0xF) * 1000000
+ ((a >> 28) & 0xF) * 10000000
+ ((a >> 32) & 0xF) * 100000000
+ ((a >> 36) & 0xF) * 1000000000
+ ((a >> 40) & 0xF) * 10000000000
+ ((a >> 44) & 0xF) * 100000000000
+ ((a >> 48) & 0xF) * 1000000000000
+ ((a >> 52) & 0xF) * 10000000000000
+ ((a >> 56) & 0xF) * 100000000000000
+ ((a >> 60) & 0xF) * 1000000000000000;
}
static bcdint numtobcd(num a) {
bcdint r = 0;
while (a) {
r <<= 4;
r |= (a % 10);
a /= 10;
}
return r;
}

193
musl/COPYRIGHT Normal file
View File

@@ -0,0 +1,193 @@
musl as a whole is licensed under the following standard MIT license:
----------------------------------------------------------------------
Copyright © 2005-2020 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------
Authors/contributors include:
A. Wilcox
Ada Worcester
Alex Dowad
Alex Suykov
Alexander Monakov
Andre McCurdy
Andrew Kelley
Anthony G. Basile
Aric Belsito
Arvid Picciani
Bartosz Brachaczek
Benjamin Peterson
Bobby Bingham
Boris Brezillon
Brent Cook
Chris Spiegel
Clément Vasseur
Daniel Micay
Daniel Sabogal
Daurnimator
David Carlier
David Edelsohn
Denys Vlasenko
Dmitry Ivanov
Dmitry V. Levin
Drew DeVault
Emil Renner Berthing
Fangrui Song
Felix Fietkau
Felix Janda
Gianluca Anzolin
Hauke Mehrtens
He X
Hiltjo Posthuma
Isaac Dunham
Jaydeep Patil
Jens Gustedt
Jeremy Huntwork
Jo-Philipp Wich
Joakim Sindholt
John Spencer
Julien Ramseier
Justin Cormack
Kaarle Ritvanen
Khem Raj
Kylie McClain
Leah Neukirchen
Luca Barbato
Luka Perkov
Lynn Ochs
M Farkas-Dyck (Strake)
Mahesh Bodapati
Markus Wichmann
Masanori Ogino
Michael Clark
Michael Forney
Mikhail Kremnyov
Natanael Copa
Nicholas J. Kain
orc
Pascal Cuoq
Patrick Oppenlander
Petr Hosek
Petr Skocik
Pierre Carrier
Reini Urban
Rich Felker
Richard Pennington
Ryan Fairfax
Samuel Holland
Segev Finer
Shiz
sin
Solar Designer
Stefan Kristiansson
Stefan O'Rear
Szabolcs Nagy
Timo Teräs
Trutz Behn
Will Dietz
William Haddon
William Pitcock
Portions of this software are derived from third-party works licensed
under terms compatible with the above MIT license:
The TRE regular expression implementation (src/regex/reg* and
src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed
under a 2-clause BSD license (license text in the source files). The
included version has been heavily modified by Rich Felker in 2012, in
the interests of size, simplicity, and namespace cleanliness.
Much of the math library code (src/math/* and src/complex/*) is
Copyright © 1993,2004 Sun Microsystems or
Copyright © 2003-2011 David Schultz or
Copyright © 2003-2009 Steven G. Kargl or
Copyright © 2003-2009 Bruce D. Evans or
Copyright © 2008 Stephen L. Moshier or
Copyright © 2017-2018 Arm Limited
and labelled as such in comments in the individual source files. All
have been licensed under extremely permissive terms.
The ARM memcpy code (src/string/arm/memcpy.S) is Copyright © 2008
The Android Open Source Project and is licensed under a two-clause BSD
license. It was taken from Bionic libc, used on Android.
The AArch64 memcpy and memset code (src/string/aarch64/*) are
Copyright © 1999-2019, Arm Limited.
The implementation of DES for crypt (src/crypt/crypt_des.c) is
Copyright © 1994 David Burren. It is licensed under a BSD license.
The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was
originally written by Solar Designer and placed into the public
domain. The code also comes with a fallback permissive license for use
in jurisdictions that may not recognize the public domain.
The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
Lynn Ochs and is licensed under an MIT-style license.
The x86_64 port was written by Nicholas J. Kain and is licensed under
the standard MIT terms.
The mips and microblaze ports were originally written by Richard
Pennington for use in the ellcc project. The original code was adapted
by Rich Felker for build system and code conventions during upstream
integration. It is licensed under the standard MIT terms.
The mips64 port was contributed by Imagination Technologies and is
licensed under the standard MIT terms.
The powerpc port was also originally written by Richard Pennington,
and later supplemented and integrated by John Spencer. It is licensed
under the standard MIT terms.
All other files which have no copyright comments are original works
produced specifically for use as part of this library, written either
by Rich Felker, the main author of the library, or by one or more
contibutors listed above. Details on authorship of individual files
can be found in the git version control history of the project. The
omission of copyright and license comments in each file is in the
interest of source tree size.
In addition, permission is hereby granted for all public header files
(include/* and arch/*/bits/*) and crt files intended to be linked into
applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit
the copyright notice and permission notice otherwise required by the
license, and to use these files without any requirement of
attribution. These files include substantial contributions from:
Bobby Bingham
John Spencer
Nicholas J. Kain
Rich Felker
Richard Pennington
Stefan Kristiansson
Szabolcs Nagy
all of whom have explicitly granted such permission.
This file previously contained text expressing a belief that most of
the files covered by the above exception were sufficiently trivial not
to be subject to copyright, resulting in confusion over whether it
negated the permissions granted in the license. In the spirit of
permissive licensing, and of not having licensing issues being an
obstacle to adoption, that text has been removed.

333
musl/atomic.h Normal file
View File

@@ -0,0 +1,333 @@
#ifndef _ATOMIC_H
#define _ATOMIC_H
#include <stdint.h>
#include "atomic_arch.h"
#ifdef a_ll
#ifndef a_pre_llsc
#define a_pre_llsc()
#endif
#ifndef a_post_llsc
#define a_post_llsc()
#endif
#ifndef a_cas
#define a_cas a_cas
static inline int a_cas(volatile int *p, int t, int s)
{
int old;
a_pre_llsc();
do old = a_ll(p);
while (old==t && !a_sc(p, s));
a_post_llsc();
return old;
}
#endif
#ifndef a_swap
#define a_swap a_swap
static inline int a_swap(volatile int *p, int v)
{
int old;
a_pre_llsc();
do old = a_ll(p);
while (!a_sc(p, v));
a_post_llsc();
return old;
}
#endif
#ifndef a_fetch_add
#define a_fetch_add a_fetch_add
static inline int a_fetch_add(volatile int *p, int v)
{
int old;
a_pre_llsc();
do old = a_ll(p);
while (!a_sc(p, (unsigned)old + v));
a_post_llsc();
return old;
}
#endif
#ifndef a_fetch_and
#define a_fetch_and a_fetch_and
static inline int a_fetch_and(volatile int *p, int v)
{
int old;
a_pre_llsc();
do old = a_ll(p);
while (!a_sc(p, old & v));
a_post_llsc();
return old;
}
#endif
#ifndef a_fetch_or
#define a_fetch_or a_fetch_or
static inline int a_fetch_or(volatile int *p, int v)
{
int old;
a_pre_llsc();
do old = a_ll(p);
while (!a_sc(p, old | v));
a_post_llsc();
return old;
}
#endif
#endif
#ifdef a_ll_p
#ifndef a_cas_p
#define a_cas_p a_cas_p
static inline void *a_cas_p(volatile void *p, void *t, void *s)
{
void *old;
a_pre_llsc();
do old = a_ll_p(p);
while (old==t && !a_sc_p(p, s));
a_post_llsc();
return old;
}
#endif
#endif
#ifndef a_cas
#error missing definition of a_cas
#endif
#ifndef a_swap
#define a_swap a_swap
static inline int a_swap(volatile int *p, int v)
{
int old;
do old = *p;
while (a_cas(p, old, v) != old);
return old;
}
#endif
#ifndef a_fetch_add
#define a_fetch_add a_fetch_add
static inline int a_fetch_add(volatile int *p, int v)
{
int old;
do old = *p;
while (a_cas(p, old, (unsigned)old+v) != old);
return old;
}
#endif
#ifndef a_fetch_and
#define a_fetch_and a_fetch_and
static inline int a_fetch_and(volatile int *p, int v)
{
int old;
do old = *p;
while (a_cas(p, old, old&v) != old);
return old;
}
#endif
#ifndef a_fetch_or
#define a_fetch_or a_fetch_or
static inline int a_fetch_or(volatile int *p, int v)
{
int old;
do old = *p;
while (a_cas(p, old, old|v) != old);
return old;
}
#endif
#ifndef a_and
#define a_and a_and
static inline void a_and(volatile int *p, int v)
{
a_fetch_and(p, v);
}
#endif
#ifndef a_or
#define a_or a_or
static inline void a_or(volatile int *p, int v)
{
a_fetch_or(p, v);
}
#endif
#ifndef a_inc
#define a_inc a_inc
static inline void a_inc(volatile int *p)
{
a_fetch_add(p, 1);
}
#endif
#ifndef a_dec
#define a_dec a_dec
static inline void a_dec(volatile int *p)
{
a_fetch_add(p, -1);
}
#endif
#ifndef a_store
#define a_store a_store
static inline void a_store(volatile int *p, int v)
{
#ifdef a_barrier
a_barrier();
*p = v;
a_barrier();
#else
a_swap(p, v);
#endif
}
#endif
#ifndef a_barrier
#define a_barrier a_barrier
static inline void a_barrier()
{
volatile int tmp = 0;
a_cas(&tmp, 0, 0);
}
#endif
#ifndef a_spin
#define a_spin a_barrier
#endif
#ifndef a_and_64
#define a_and_64 a_and_64
static inline void a_and_64(volatile uint64_t *p, uint64_t v)
{
union { uint64_t v; uint32_t r[2]; } u = { v };
if (u.r[0]+1) a_and((int *)p, u.r[0]);
if (u.r[1]+1) a_and((int *)p+1, u.r[1]);
}
#endif
#ifndef a_or_64
#define a_or_64 a_or_64
static inline void a_or_64(volatile uint64_t *p, uint64_t v)
{
union { uint64_t v; uint32_t r[2]; } u = { v };
if (u.r[0]) a_or((int *)p, u.r[0]);
if (u.r[1]) a_or((int *)p+1, u.r[1]);
}
#endif
#ifndef a_cas_p
typedef char a_cas_p_undefined_but_pointer_not_32bit[-sizeof(char) == 0xffffffff ? 1 : -1];
#define a_cas_p a_cas_p
static inline void *a_cas_p(volatile void *p, void *t, void *s)
{
return (void *)a_cas((volatile int *)p, (int)t, (int)s);
}
#endif
#ifndef a_or_l
#define a_or_l a_or_l
static inline void a_or_l(volatile void *p, long v)
{
if (sizeof(long) == sizeof(int)) a_or(p, v);
else a_or_64(p, v);
}
#endif
#ifndef a_crash
#define a_crash a_crash
static inline void a_crash()
{
*(volatile char *)0=0;
}
#endif
#ifndef a_ctz_32
#define a_ctz_32 a_ctz_32
static inline int a_ctz_32(uint32_t x)
{
#ifdef a_clz_32
return 31-a_clz_32(x&-x);
#else
static const char debruijn32[32] = {
0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
};
return debruijn32[(x&-x)*0x076be629 >> 27];
#endif
}
#endif
#ifndef a_ctz_64
#define a_ctz_64 a_ctz_64
static inline int a_ctz_64(uint64_t x)
{
static const char debruijn64[64] = {
0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
};
if (sizeof(long) < 8) {
uint32_t y = x;
if (!y) {
y = x>>32;
return 32 + a_ctz_32(y);
}
return a_ctz_32(y);
}
return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58];
}
#endif
static inline int a_ctz_l(unsigned long x)
{
return (sizeof(long) < 8) ? a_ctz_32(x) : a_ctz_64(x);
}
#ifndef a_clz_64
#define a_clz_64 a_clz_64
static inline int a_clz_64(uint64_t x)
{
#ifdef a_clz_32
if (x>>32)
return a_clz_32(x>>32);
return a_clz_32(x) + 32;
#else
uint32_t y;
int r;
if (x>>32) y=x>>32, r=0; else y=x, r=32;
if (y>>16) y>>=16; else r |= 16;
if (y>>8) y>>=8; else r |= 8;
if (y>>4) y>>=4; else r |= 4;
if (y>>2) y>>=2; else r |= 2;
return r | !(y>>1);
#endif
}
#endif
#ifndef a_clz_32
#define a_clz_32 a_clz_32
static inline int a_clz_32(uint32_t x)
{
x >>= 1;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
x++;
return 31-a_ctz_32(x);
}
#endif
#endif

123
musl/atomic_arch.h Normal file
View File

@@ -0,0 +1,123 @@
#define a_cas a_cas
static inline int a_cas(volatile int *p, int t, int s)
{
__asm__ __volatile__ (
"lock ; cmpxchg %3, %1"
: "=a"(t), "=m"(*p) : "a"(t), "r"(s) : "memory" );
return t;
}
#define a_cas_p a_cas_p
static inline void *a_cas_p(volatile void *p, void *t, void *s)
{
__asm__( "lock ; cmpxchg %3, %1"
: "=a"(t), "=m"(*(void *volatile *)p)
: "a"(t), "r"(s) : "memory" );
return t;
}
#define a_swap a_swap
static inline int a_swap(volatile int *p, int v)
{
__asm__ __volatile__(
"xchg %0, %1"
: "=r"(v), "=m"(*p) : "0"(v) : "memory" );
return v;
}
#define a_fetch_add a_fetch_add
static inline int a_fetch_add(volatile int *p, int v)
{
__asm__ __volatile__(
"lock ; xadd %0, %1"
: "=r"(v), "=m"(*p) : "0"(v) : "memory" );
return v;
}
#define a_and a_and
static inline void a_and(volatile int *p, int v)
{
__asm__ __volatile__(
"lock ; and %1, %0"
: "=m"(*p) : "r"(v) : "memory" );
}
#define a_or a_or
static inline void a_or(volatile int *p, int v)
{
__asm__ __volatile__(
"lock ; or %1, %0"
: "=m"(*p) : "r"(v) : "memory" );
}
#define a_and_64 a_and_64
static inline void a_and_64(volatile uint64_t *p, uint64_t v)
{
__asm__ __volatile(
"lock ; and %1, %0"
: "=m"(*p) : "r"(v) : "memory" );
}
#define a_or_64 a_or_64
static inline void a_or_64(volatile uint64_t *p, uint64_t v)
{
__asm__ __volatile__(
"lock ; or %1, %0"
: "=m"(*p) : "r"(v) : "memory" );
}
#define a_inc a_inc
static inline void a_inc(volatile int *p)
{
__asm__ __volatile__(
"lock ; incl %0"
: "=m"(*p) : "m"(*p) : "memory" );
}
#define a_dec a_dec
static inline void a_dec(volatile int *p)
{
__asm__ __volatile__(
"lock ; decl %0"
: "=m"(*p) : "m"(*p) : "memory" );
}
#define a_store a_store
static inline void a_store(volatile int *p, int x)
{
__asm__ __volatile__(
"mov %1, %0 ; lock ; orl $0,(%%rsp)"
: "=m"(*p) : "r"(x) : "memory" );
}
#define a_barrier a_barrier
static inline void a_barrier()
{
__asm__ __volatile__( "" : : : "memory" );
}
#define a_spin a_spin
static inline void a_spin()
{
__asm__ __volatile__( "pause" : : : "memory" );
}
#define a_crash a_crash
static inline void a_crash()
{
__asm__ __volatile__( "hlt" : : : "memory" );
}
#define a_ctz_64 a_ctz_64
static inline int a_ctz_64(uint64_t x)
{
__asm__( "bsf %1,%0" : "=r"(x) : "r"(x) );
return x;
}
#define a_clz_64 a_clz_64
static inline int a_clz_64(uint64_t x)
{
__asm__( "bsr %1,%0 ; xor $63,%0" : "=r"(x) : "r"(x) );
return x;
}

25
musl/memcpy.s Normal file
View File

@@ -0,0 +1,25 @@
.global memcpy
.global __memcpy_fwd
.hidden __memcpy_fwd
.type memcpy,@function
memcpy:
__memcpy_fwd:
mov %rdi,%rax
cmp $8,%rdx
jc 1f
test $7,%edi
jz 1f
2: movsb
dec %rdx
test $7,%edi
jnz 2b
1: mov %rdx,%rcx
shr $3,%rcx
rep
movsq
and $7,%edx
jz 1f
2: movsb
dec %edx
jnz 2b
1: ret

72
musl/memset.s Normal file
View File

@@ -0,0 +1,72 @@
.global memset
.type memset,@function
memset:
movzbq %sil,%rax
mov $0x101010101010101,%r8
imul %r8,%rax
cmp $126,%rdx
ja 2f
test %edx,%edx
jz 1f
mov %sil,(%rdi)
mov %sil,-1(%rdi,%rdx)
cmp $2,%edx
jbe 1f
mov %ax,1(%rdi)
mov %ax,(-1-2)(%rdi,%rdx)
cmp $6,%edx
jbe 1f
mov %eax,(1+2)(%rdi)
mov %eax,(-1-2-4)(%rdi,%rdx)
cmp $14,%edx
jbe 1f
mov %rax,(1+2+4)(%rdi)
mov %rax,(-1-2-4-8)(%rdi,%rdx)
cmp $30,%edx
jbe 1f
mov %rax,(1+2+4+8)(%rdi)
mov %rax,(1+2+4+8+8)(%rdi)
mov %rax,(-1-2-4-8-16)(%rdi,%rdx)
mov %rax,(-1-2-4-8-8)(%rdi,%rdx)
cmp $62,%edx
jbe 1f
mov %rax,(1+2+4+8+16)(%rdi)
mov %rax,(1+2+4+8+16+8)(%rdi)
mov %rax,(1+2+4+8+16+16)(%rdi)
mov %rax,(1+2+4+8+16+24)(%rdi)
mov %rax,(-1-2-4-8-16-32)(%rdi,%rdx)
mov %rax,(-1-2-4-8-16-24)(%rdi,%rdx)
mov %rax,(-1-2-4-8-16-16)(%rdi,%rdx)
mov %rax,(-1-2-4-8-16-8)(%rdi,%rdx)
1: mov %rdi,%rax
ret
2: test $15,%edi
mov %rdi,%r8
mov %rax,-8(%rdi,%rdx)
mov %rdx,%rcx
jnz 2f
1: shr $3,%rcx
rep
stosq
mov %r8,%rax
ret
2: xor %edx,%edx
sub %edi,%edx
and $15,%edx
mov %rax,(%rdi)
mov %rax,8(%rdi)
sub %rdx,%rcx
add %rdx,%rdi
jmp 1b

219
musl/qsort.c Normal file
View File

@@ -0,0 +1,219 @@
/* Copyright (C) 2011 by Lynn Ochs
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/* Minor changes by Rich Felker for integration in musl, 2011-04-27. */
/* Smoothsort, an adaptive variant of Heapsort. Memory usage: O(1).
Run time: Worst case O(n log n), close to O(n) in the mostly-sorted case. */
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "atomic.h"
#define ntz(x) a_ctz_l((x))
typedef int (*cmpfun)(const void *, const void *, void *);
static inline int pntz(size_t p[2]) {
int r = ntz(p[0] - 1);
if(r != 0 || (r = 8*sizeof(size_t) + ntz(p[1])) != 8*sizeof(size_t)) {
return r;
}
return 0;
}
static void cycle(size_t width, unsigned char* ar[], int n)
{
unsigned char tmp[256];
size_t l;
int i;
if(n < 2) {
return;
}
ar[n] = tmp;
while(width) {
l = sizeof(tmp) < width ? sizeof(tmp) : width;
memcpy(ar[n], ar[0], l);
for(i = 0; i < n; i++) {
memcpy(ar[i], ar[i + 1], l);
ar[i] += l;
}
width -= l;
}
ar[n] = 0;
}
/* shl() and shr() need n > 0 */
static inline void shl(size_t p[2], int n)
{
if(n >= 8 * sizeof(size_t)) {
n -= 8 * sizeof(size_t);
p[1] = p[0];
p[0] = 0;
}
p[1] <<= n;
p[1] |= p[0] >> (sizeof(size_t) * 8 - n);
p[0] <<= n;
}
static inline void shr(size_t p[2], int n)
{
if(n >= 8 * sizeof(size_t)) {
n -= 8 * sizeof(size_t);
p[0] = p[1];
p[1] = 0;
}
p[0] >>= n;
p[0] |= p[1] << (sizeof(size_t) * 8 - n);
p[1] >>= n;
}
static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int pshift, size_t lp[])
{
unsigned char *rt, *lf;
unsigned char *ar[14 * sizeof(size_t) + 1];
int i = 1;
ar[0] = head;
while(pshift > 1) {
rt = head - width;
lf = head - width - lp[pshift - 2];
if(cmp(ar[0], lf, arg) >= 0 && cmp(ar[0], rt, arg) >= 0) {
break;
}
if(cmp(lf, rt, arg) >= 0) {
ar[i++] = lf;
head = lf;
pshift -= 1;
} else {
ar[i++] = rt;
head = rt;
pshift -= 2;
}
}
cycle(width, ar, i);
}
static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, size_t pp[2], int pshift, int trusty, size_t lp[])
{
unsigned char *stepson,
*rt, *lf;
size_t p[2];
unsigned char *ar[14 * sizeof(size_t) + 1];
int i = 1;
int trail;
p[0] = pp[0];
p[1] = pp[1];
ar[0] = head;
while(p[0] != 1 || p[1] != 0) {
stepson = head - lp[pshift];
if(cmp(stepson, ar[0], arg) <= 0) {
break;
}
if(!trusty && pshift > 1) {
rt = head - width;
lf = head - width - lp[pshift - 2];
if(cmp(rt, stepson, arg) >= 0 || cmp(lf, stepson, arg) >= 0) {
break;
}
}
ar[i++] = stepson;
head = stepson;
trail = pntz(p);
shr(p, trail);
pshift += trail;
trusty = 0;
}
if(!trusty) {
cycle(width, ar, i);
sift(head, width, cmp, arg, pshift, lp);
}
}
void qsort_r(void *base, size_t nel, size_t width, cmpfun cmp, void *arg)
{
size_t lp[12*sizeof(size_t)];
size_t i, size = width * nel;
unsigned char *head, *high;
size_t p[2] = {1, 0};
int pshift = 1;
int trail;
if (!size) return;
head = base;
high = head + size - width;
/* Precompute Leonardo numbers, scaled by element width */
for(lp[0]=lp[1]=width, i=2; (lp[i]=lp[i-2]+lp[i-1]+width) < size; i++);
while(head < high) {
if((p[0] & 3) == 3) {
sift(head, width, cmp, arg, pshift, lp);
shr(p, 2);
pshift += 2;
} else {
if(lp[pshift - 1] >= high - head) {
trinkle(head, width, cmp, arg, p, pshift, 0, lp);
} else {
sift(head, width, cmp, arg, pshift, lp);
}
if(pshift == 1) {
shl(p, 1);
pshift = 0;
} else {
shl(p, pshift - 1);
pshift = 1;
}
}
p[0] |= 1;
head += width;
}
trinkle(head, width, cmp, arg, p, pshift, 0, lp);
while(pshift != 1 || p[0] != 1 || p[1] != 0) {
if(pshift <= 1) {
trail = pntz(p);
shr(p, trail);
pshift += trail;
} else {
shl(p, 2);
pshift -= 2;
p[0] ^= 7;
shr(p, 1);
trinkle(head - lp[pshift] - width, width, cmp, arg, p, pshift + 1, 1, lp);
shl(p, 1);
p[0] |= 1;
trinkle(head - width, width, cmp, arg, p, pshift, 1, lp);
}
head -= width;
}
}

16
musl/qsort_nr.c Normal file
View File

@@ -0,0 +1,16 @@
#include <stdlib.h>
typedef int (*cmpfun)(const void *, const void *);
typedef int (*cmpfun_r)(const void *, const void *, cmpfun);
void qsort_r(void *base, size_t nel, size_t width, cmpfun_r cmp, cmpfun arg);
static int wrapper_cmp(const void *v1, const void *v2, cmpfun cmp)
{
return cmp(v1, v2);
}
void qsort(void *base, size_t nel, size_t width, cmpfun cmp)
{
qsort_r(base, nel, width, wrapper_cmp, cmp);
}

7
start.s Normal file
View File

@@ -0,0 +1,7 @@
extern run
global _start
_start:
sub rsp,0x1000
and rsp,~0xfff
call run
ud2