diff options
Diffstat (limited to 'euler/source')
-rw-r--r-- | euler/source/empty.asm | 0 | ||||
-rw-r--r-- | euler/source/euler/entry.cpp | 11 | ||||
-rw-r--r-- | euler/source/euler/gcc.asm | 53 | ||||
-rw-r--r-- | euler/source/euler/heap.cpp | 66 | ||||
-rw-r--r-- | euler/source/euler/stream.cpp | 151 | ||||
-rw-r--r-- | euler/source/euler/syscall.asm | 102 | ||||
-rw-r--r-- | euler/source/io/fclose.cpp | 10 | ||||
-rw-r--r-- | euler/source/io/fopen.cpp | 54 | ||||
-rw-r--r-- | euler/source/io/fread.cpp | 9 | ||||
-rw-r--r-- | euler/source/memory/delete.cpp | 17 | ||||
-rw-r--r-- | euler/source/memory/new.cpp | 13 | ||||
-rw-r--r-- | euler/source/strings/memcpy.cpp | 14 | ||||
-rw-r--r-- | euler/source/strings/strlen.cpp | 12 |
13 files changed, 512 insertions, 0 deletions
diff --git a/euler/source/empty.asm b/euler/source/empty.asm new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/euler/source/empty.asm diff --git a/euler/source/euler/entry.cpp b/euler/source/euler/entry.cpp new file mode 100644 index 0000000..69611b7 --- /dev/null +++ b/euler/source/euler/entry.cpp @@ -0,0 +1,11 @@ +#include <euler/syscall.hpp> + +int main(int argc, char **argv); + +extern "C" [[noreturn]] void _start() { + //TODO: call global constructors + //TODO: get argc, argv from environment + int exit_code = main(0, 0); + //TODO: call global destructors + __euler_end_this_thread(exit_code); +} diff --git a/euler/source/euler/gcc.asm b/euler/source/euler/gcc.asm new file mode 100644 index 0000000..6fc6fd5 --- /dev/null +++ b/euler/source/euler/gcc.asm @@ -0,0 +1,53 @@ +bits 64 + +global strlen + +section .text + +strlen: + xor rax, rax +.loop: + mov rdx, qword [rdi] + test edx, 0xff + jz .plus0 + test edx, 0xff00 + jz .plus1 + test edx, 0xff0000 + jz .plus2 + test edx, 0xff000000 + jz .plus3 + shr rdx, 32 + test edx, 0xff + jz .plus4 + test edx, 0xff00 + jz .plus5 + test edx, 0xff0000 + jz .plus6 + test edx, 0xff000000 + jz .plus7 + add rax, 8 + add rdi, 8 + jmp .loop +.plus0: + ret +.plus1: + add rax, 1 + ret +.plus2: + add rax, 2 + ret +.plus3: + add rax, 3 + ret +.plus4: + add rax, 4 + ret +.plus5: + add rax, 5 + ret +.plus6: + add rax, 6 + ret +.plus7: + add rax, 7 + ret diff --git a/euler/source/euler/heap.cpp b/euler/source/euler/heap.cpp new file mode 100644 index 0000000..f7d407f --- /dev/null +++ b/euler/source/euler/heap.cpp @@ -0,0 +1,66 @@ +#include <euler/syscall.hpp> +#include <euler/heap.hpp> + +namespace euler { + + static uint64_t *last_chunk_info_page = 0; + + void add_record(uint64_t start, uint64_t length) { + uint64_t dual_start = start ^ length; + for (uint64_t *cip = last_chunk_info_page; cip; cip = (uint64_t *)cip[510]) + for (int i = 0; i < 255; ++i) + if (cip[i * 2] == length && cip[i * 2 + 1] == dual_start) { + cip[i * 2] = length * 2; + cip[i * 2 + 1] &= start; + return; + } + for (uint64_t *cip = last_chunk_info_page; cip; cip = (uint64_t *)cip[510]) + for (int i = 0; i < 255; ++i) + if (cip[i * 2] == 0) { + cip[i * 2] = length; + cip[i * 2 + 1] = start; + return; + } + uint64_t *new_cip = (uint64_t *)__euler_get_new_pages(1); + new_cip[0] = length; + new_cip[1] = start; + for (int i = 1; i < 255; ++i) + new_cip[i * 2] = 0; + new_cip[510] = (uint64_t)last_chunk_info_page; + last_chunk_info_page = new_cip; + } + + void *alloc(uint64_t bytes) { + for (uint64_t *cip = last_chunk_info_page; cip; cip = (uint64_t *)cip[510]) + for (int i = 0; i < 255; ++i) + if (cip[i * 2] >= bytes) { + uint64_t start = cip[i * 2 + 1]; + uint64_t extra_length = cip[i * 2] - bytes; + cip[i * 2] = 0; + if (extra_length > 0) + dealloc((void *)(start + bytes), extra_length); + return (void *)start; + } + uint64_t pages_needed = (bytes - 1) / 4096 + 1; + uint64_t start = (uint64_t)__euler_get_new_pages(pages_needed); + if (bytes != pages_needed * 4096) + dealloc((void *)(start + bytes), pages_needed * 4096 - bytes); + return (void *)start; + } + + //this implementation is a little lazy + void dealloc(void *start, uint64_t bytes) { + uint64_t s = (uint64_t)start; + while (bytes > 0) { + uint64_t l = 1; + do + l *= 2; + while (l <= bytes && s % l == 0); + l /= 2; + add_record(s, l); + s += l; + bytes -= l; + } + } + +} diff --git a/euler/source/euler/stream.cpp b/euler/source/euler/stream.cpp new file mode 100644 index 0000000..950f3c5 --- /dev/null +++ b/euler/source/euler/stream.cpp @@ -0,0 +1,151 @@ +#include <euler/stream.hpp> +#include <cstring> + +namespace euler { + + stream::~stream() {} + + void file_stream::write_buffer() { + if (__euler_write_to_stream(handle, buffer_size, buffer) + != __EULER_SR_SUCCESS) + good = false;//TODO: more precise error reporting + else + buffer_dirty = false; + } + + file_stream::file_stream( + __euler_stream_handle handle, bool is_readable, bool is_writable, + bool clear, bool seek_to_end) + + : handle(handle), is_readable(is_readable), is_writable(is_writable), + buffer(0), good(true) { + + if (clear) { + if (__euler_set_stream_length(handle, 0) != __EULER_SR_SUCCESS) { + good = false; + return; + } + length = 0; + } + + else if (__euler_get_stream_length(handle, length) != __EULER_SR_SUCCESS) { + good = false; + return; + } + + if (seek_to_end) { + if (__euler_seek_stream(handle, __EULER_SF_END, 0) + != __EULER_SR_SUCCESS) { + good = false; + return; + } + offset = length; + } + + else + offset = 0; + + } + + file_stream::~file_stream() { + if (buffer) { + if (buffer_dirty) + write_buffer(); + delete[] buffer; + } + __euler_close_stream(handle); + } + + bool file_stream::try_read(void *into, uint64_t bytes) { + + if (bytes == 0) + return true; + + if (offset + bytes > length) + return false; + + if (buffer) { + uint64_t start = offset > buffer_offset ? offset : buffer_offset; + uint64_t end = offset + bytes < buffer_offset + buffer_size + ? offset + bytes : buffer_offset + buffer_size; + if (end > start) { + + uint64_t real_end = offset + bytes; + + std::memcpy( + (uint8_t *)into + start - offset, buffer + start - buffer_offset, + end - start); + if (start != offset) + if (!try_read(into, start - offset)) + return false; + + if (end != real_end) { + if (!try_seek(__EULER_SF_BEGINNING, end)) + return false; + if (!try_read((uint8_t *)into + end, real_end - end)) + return false; + } + + else if (offset != real_end) + if (!try_seek(__EULER_SF_BEGINNING, real_end)) + return false; + + return true; + + } + } + + if (buffer_dirty) { + write_buffer(); + if (!good) + return false; + } + + //1024 is arbitrary + buffer_size = length - offset < 1024 ? length - offset : 1024; + + if (buffer != 0) + delete[] buffer; + + buffer = new uint8_t[buffer_size]; + buffer_dirty = false; + buffer_offset = offset; + + if (__euler_read_from_stream(handle, buffer_size, buffer) + != __EULER_SR_SUCCESS) { + delete[] buffer; + buffer = 0; + return false; + } + + uint64_t read_this_buffer = buffer_size < bytes ? buffer_size : bytes; + std::memcpy(into, buffer, read_this_buffer); + offset += read_this_buffer; + + if (read_this_buffer == bytes) + return true; + + return try_read( + (uint8_t *)into + read_this_buffer, bytes - read_this_buffer); + + } + + bool file_stream::try_seek(__euler_seek_from from, int64_t offset) { + if (__euler_seek_stream(handle, from, offset) != __EULER_SR_SUCCESS) + return false; + switch (from) { + case __EULER_SF_BEGINNING: + this->offset = offset; + return true; + case __EULER_SF_END: + this->offset = length + offset; + return true; + case __EULER_SF_CURRENT_POSITION: + this->offset += offset; + return true; + default: + return false; + } + } + +} diff --git a/euler/source/euler/syscall.asm b/euler/source/euler/syscall.asm new file mode 100644 index 0000000..34f2735 --- /dev/null +++ b/euler/source/euler/syscall.asm @@ -0,0 +1,102 @@ +bits 64 + +global __euler_open_file +global __euler_close_stream +global __euler_get_new_pages +global __euler_write_to_stream +global __euler_seek_stream +global __euler_get_stream_length +global __euler_set_stream_length +global __euler_end_this_thread +global __euler_read_from_stream +global __euler_get_framebuffer +global __euler_encode_color +global __euler_read_key_packet + +section .text + +__euler_open_file: + mov rax, 2 + push rdx + xor rdx, rdx + or rdx, r8 + shl r9, 1 + or rdx, r9 + syscall + pop rdx + mov qword [rdx], rdi + ret + +__euler_close_stream: + mov rax, 11 + syscall + ret + +__euler_get_new_pages: + mov rax, 4 + syscall + ret + +__euler_write_to_stream: + mov rax, 14 + syscall + ret + +__euler_seek_stream: + mov rax, 12 + syscall + ret + +__euler_get_stream_length: + push rsi + mov rax, 15 + syscall + pop rsi + mov qword [rsi], rdi + ret + +__euler_set_stream_length: + mov rax, 18 + syscall + ret + +__euler_end_this_thread: + mov rax, 3 + syscall + +__euler_read_from_stream: + mov rax, 13 + syscall + ret + +__euler_get_framebuffer: + push rdi + push rsi + push rdx + mov rax, 1 + syscall + pop rdx + mov dword [rdx], esi + pop rdx + pop rsi + mov dword [rsi], edi + shr rdi, 32 + mov dword [rdx], edi + ret + +__euler_encode_color: + xor ah, ah + mov al, dl + shl ax, 8 + mov al, sil + shl eax, 8 + mov al, dil + mov edi, eax + xor rax, rax + syscall + ret + +__euler_read_key_packet: + mov rax, 5 + syscall + ret diff --git a/euler/source/io/fclose.cpp b/euler/source/io/fclose.cpp new file mode 100644 index 0000000..6f43f85 --- /dev/null +++ b/euler/source/io/fclose.cpp @@ -0,0 +1,10 @@ +#include <cstdio> + +namespace std { + + int fclose(FILE *stream) { + delete stream; + return 0; + } + +} diff --git a/euler/source/io/fopen.cpp b/euler/source/io/fopen.cpp new file mode 100644 index 0000000..8d47bf0 --- /dev/null +++ b/euler/source/io/fopen.cpp @@ -0,0 +1,54 @@ +#include <stdint.h> +#include <cstring> +#include <cstdio> + +namespace std { + + FILE *fopen(const char *filename, const char *mode) { + + bool read = false; + bool write = false; + bool append = false; + bool extended = false; + bool create = false; + + for (const char *p = mode; *p; ++p) + switch (*p) { + case 'r': + read = true; + continue; + case 'w': + write = true; + continue; + case 'a': + append = true; + continue; + case '+': + extended = true; + continue; + case 'x': + create = true; + continue; + default: + continue; + } + + __euler_stream_handle handle; + __euler_stream_result res = __euler_open_file( + filename, strlen(filename), handle, write || append, create); + + if (res != __EULER_SR_SUCCESS) + return 0; + + euler::file_stream *f = new euler::file_stream(handle, read || extended, + write || extended, write && !append, append); + + if (f->good) + return f; + + delete f; + return 0; + + } + +} diff --git a/euler/source/io/fread.cpp b/euler/source/io/fread.cpp new file mode 100644 index 0000000..e2d05b6 --- /dev/null +++ b/euler/source/io/fread.cpp @@ -0,0 +1,9 @@ +#include <cstdio> + +namespace std { + + size_t fread(void *buffer, size_t size, size_t count, FILE *stream) { + return stream->try_read(buffer, size * count) ? count : 0; + } + +} diff --git a/euler/source/memory/delete.cpp b/euler/source/memory/delete.cpp new file mode 100644 index 0000000..e4cc288 --- /dev/null +++ b/euler/source/memory/delete.cpp @@ -0,0 +1,17 @@ +#include <euler/heap.hpp> + +void operator delete(void *ptr) { + euler::dealloc((uint8_t *)ptr - 8, *(uint64_t *)((uint8_t *)ptr - 8)); +} + +void operator delete(void *ptr, uint64_t) { + euler::dealloc((uint8_t *)ptr - 8, *(uint64_t *)((uint8_t *)ptr - 8)); +} + +void operator delete[](void *ptr) { + euler::dealloc((uint8_t *)ptr - 8, *(uint64_t *)((uint8_t *)ptr - 8)); +} + +void operator delete[](void *ptr, uint64_t) { + euler::dealloc((uint8_t *)ptr - 8, *(uint64_t *)((uint8_t *)ptr - 8)); +} diff --git a/euler/source/memory/new.cpp b/euler/source/memory/new.cpp new file mode 100644 index 0000000..931328f --- /dev/null +++ b/euler/source/memory/new.cpp @@ -0,0 +1,13 @@ +#include <euler/heap.hpp> + +void *operator new(uint64_t size) { + void *ptr = euler::alloc(size + 8); + *(uint64_t *)ptr = size + 8; + return (uint8_t *)ptr + 8; +} + +void *operator new[](uint64_t size) { + void *ptr = euler::alloc(size + 8); + *(uint64_t *)ptr = size + 8; + return (uint8_t *)ptr + 8; +} diff --git a/euler/source/strings/memcpy.cpp b/euler/source/strings/memcpy.cpp new file mode 100644 index 0000000..d5a1d6c --- /dev/null +++ b/euler/source/strings/memcpy.cpp @@ -0,0 +1,14 @@ +#include <stdint.h> +#include <cstring> + +namespace std { + + void *memcpy(void *dest, const void *src, size_t count) { + uint8_t *d8 = (uint8_t *)dest; + const uint8_t *s8 = (const uint8_t *)src; + for (size_t i = 0; i < count; ++i) + d8[i] = s8[i]; + return dest; + } + +} diff --git a/euler/source/strings/strlen.cpp b/euler/source/strings/strlen.cpp new file mode 100644 index 0000000..7a6fe2a --- /dev/null +++ b/euler/source/strings/strlen.cpp @@ -0,0 +1,12 @@ +#include <cstring> + +namespace std { + + size_t strlen(const char *str) { + size_t len = 0; + while (str[len]) + ++len; + return len; + } + +} |