diff options
Diffstat (limited to 'euler/source/syscall.cpp')
-rw-r--r-- | euler/source/syscall.cpp | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/euler/source/syscall.cpp b/euler/source/syscall.cpp new file mode 100644 index 0000000..b3ed3a8 --- /dev/null +++ b/euler/source/syscall.cpp @@ -0,0 +1,397 @@ +#include <euler/syscall.hpp> + +extern "C" void __euler_do_syscall( + uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx); + +namespace euler::syscall { + + encoded_color encode_color( + uint8_t r, uint8_t g, uint8_t b) { + + uint64_t rax = 0; + uint64_t rdi = (uint32_t)r | ((uint32_t)g << 8) | ((uint32_t)b << 16); + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + return (encoded_color)(rax & 0xffffffff); + + } + + void get_framebuffer( + encoded_color *&buffer_out, uint32_t &width_out, + uint32_t &height_out, uint32_t &pitch_out) { + + uint64_t rax = 1; + uint64_t rdi; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + buffer_out = (encoded_color *)rax; + width_out = rdi & 0xffffffff; + height_out = rdi >> 32; + pitch_out = rsi & 0xffffffff; + + } + + stream_result open_file( + const std::string &file_path, bool allow_creation, + bool only_allow_creation, stream_handle &handle_out) { + + uint64_t rax = 2; + uint64_t rdi = (uint64_t)file_path.data(); + uint64_t rsi = file_path.size(); + uint64_t rdx = + ( allow_creation ? 0x1 : 0x0) | + (only_allow_creation ? 0x2 : 0x0); + + __euler_do_syscall(rax, rdi, rsi, rdx); + + handle_out = rdi; + return (stream_result)rax; + + } + + [[noreturn]] void end_this_thread(int32_t exit_code) { + + uint64_t rax = 3; + uint64_t rdi = (uint32_t)exit_code; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + __builtin_unreachable(); + + } + + void *get_new_pages(uint64_t n_pages) { + + uint64_t rax = 4; + uint64_t rdi = n_pages; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + return (void *)rax; + + } + + std::variant<mouse_packet, key_packet> get_input_packet() { + + uint64_t rax = 5; + uint64_t rdi; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + if (rax & 0x80) + return (mouse_packet){ + . left_button_down = (rax & 0x01) != 0, + . right_button_down = (rax & 0x02) != 0, + .middle_button_down = (rax & 0x04) != 0, + .x_changed = (int16_t)(rdi & 0xffff), + .y_changed = (int16_t)(rsi & 0xffff) + }; + + return (key_packet){ + .was_key_up_event = (rdi & 0x40000) != 0, + . num_lock = (rdi & 0x20000) != 0, + . caps_lock = (rdi & 0x10000) != 0, + . right_win = (rdi & 0x8000) != 0, + . left_win = (rdi & 0x4000) != 0, + . right_alt = (rdi & 0x2000) != 0, + . left_alt = (rdi & 0x1000) != 0, + . right_ctrl = (rdi & 0x800) != 0, + . left_ctrl = (rdi & 0x400) != 0, + . right_shift = (rdi & 0x200) != 0, + . left_shift = (rdi & 0x100) != 0, + . key_code = (uint8_t)(rdi & 0xff) + }; + + } + + void create_private_socket( + stream_handle &end_1_out, stream_handle &end_2_out) { + + uint64_t rax = 6; + uint64_t rdi; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + end_1_out = rax; + end_2_out = rdi; + + } + + stream_result create_socket_listener( + const std::string &id, listener_handle &handle_out) { + + uint64_t rax = 7; + uint64_t rdi = (uint64_t)id.data(); + uint64_t rsi = id.size(); + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + handle_out = rdi; + return (stream_result)rax; + + } + + void stop_socket_listener(listener_handle handle) { + + uint64_t rax = 8; + uint64_t rdi = handle; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + } + + stream_result accept_socket_connection( + listener_handle listener, stream_handle &stream_out) { + + uint64_t rax = 9; + uint64_t rdi = listener; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + stream_out = rdi; + return (stream_result)rax; + + } + + stream_result connect_to_socket( + const std::string &id, stream_handle &handle_out) { + + uint64_t rax = 10; + uint64_t rdi = (uint64_t)id.data(); + uint64_t rsi = id.size(); + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + handle_out = rdi; + return (stream_result)rax; + + } + + void close_stream(stream_handle handle) { + + uint64_t rax = 11; + uint64_t rdi = handle; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + } + + stream_result seek_stream( + stream_handle handle, seek_from from, int64_t offset) { + + uint64_t rax = 12; + uint64_t rdi = (uint64_t)handle; + uint64_t rsi = (uint8_t)from; + uint64_t rdx = (uint64_t)offset; + + __euler_do_syscall(rax, rdi, rsi, rdx); + return (stream_result)rax; + + } + + stream_result read_from_stream( + stream_handle handle, uint64_t bytes, void *into) { + + uint64_t rax = 13; + uint64_t rdi = (uint64_t)handle; + uint64_t rsi = bytes; + uint64_t rdx = (uint64_t)into; + + __euler_do_syscall(rax, rdi, rsi, rdx); + return (stream_result)rax; + + } + + stream_result write_to_stream( + stream_handle handle, uint64_t bytes, const void *from) { + + uint64_t rax = 14; + uint64_t rdi = (uint64_t)handle; + uint64_t rsi = bytes; + uint64_t rdx = (uint64_t)from; + + __euler_do_syscall(rax, rdi, rsi, rdx); + return (stream_result)rax; + + } + + stream_result get_stream_length( + stream_handle handle, uint64_t &length_out) { + + uint64_t rax = 15; + uint64_t rdi = (uint64_t)handle; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + length_out = rdi; + return (stream_result)rax; + + } + + stream_result start_process( + const std::string &file_path, + const std::vector<std::pair<std::string, std::string>> &environment_variables, + const std::vector<std::pair<stream_handle, stream_result>> &gifted_streams, + process_handle &handle_out) { + + std::vector<uint64_t> ev_structs(environment_variables.size() * 4); + for (size_t i = 0; i < environment_variables.size(); ++i) { + ev_structs[i * 4] = environment_variables[i]. first.size(); + ev_structs[i * 4 + 1] = (uint64_t)environment_variables[i]. first.data(); + ev_structs[i * 4 + 2] = environment_variables[i].second.size(); + ev_structs[i * 4 + 3] = (uint64_t)environment_variables[i].second.data(); + } + + std::vector<uint64_t> gs_structs(gifted_streams.size() * 2); + for (size_t i = 0; i < environment_variables.size(); ++i) { + gs_structs[i * 2] = (uint64_t)gifted_streams[i]. first; + gs_structs[i * 2 + 1] = (uint64_t)gifted_streams[i].second; + } + + uint64_t psi_struct[] = { + file_path.size(), (uint64_t) file_path.data(), + environment_variables.size(), (uint64_t)ev_structs.data(), + gifted_streams.size(), (uint64_t)gs_structs.data() + }; + + uint64_t rax = 16; + uint64_t rdi = (uint64_t)psi_struct; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + handle_out = rdi; + return (stream_result)rax; + + } + + [[noreturn]] void end_this_process(int32_t exit_code) { + + uint64_t rax = 17; + uint64_t rdi = (uint32_t)exit_code; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + __builtin_unreachable(); + + } + + stream_result set_stream_length( + stream_handle handle, uint64_t new_length) { + + uint64_t rax = 18; + uint64_t rdi = (uint64_t)handle; + uint64_t rsi = new_length; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + return (stream_result)rax; + + } + + stream_result get_other_end_process_handle( + stream_handle stream, process_handle &process_out) { + + uint64_t rax = 19; + uint64_t rdi = (uint64_t)stream; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + process_out = (process_handle)rdi; + return (stream_result)rax; + + } + + //entry_point must not return + void start_thread(void (*entry_point)(uint64_t), uint64_t arg) { + + uint64_t rax = 20; + uint64_t rdi = (uint64_t)entry_point; + uint64_t rsi = arg; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + } + + //entry_point must not return + void start_thread(void (*entry_point)()) { + + uint64_t rax = 20; + uint64_t rdi = (uint64_t)entry_point; + uint64_t rsi = 0; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + } + + //return value is number of bytes cleared + uint64_t clear_socket_read_queue(stream_handle handle) { + + uint64_t rax = 21; + uint64_t rdi = handle; + uint64_t rsi; + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + return rax; + + } + + //this function has a race condition if the variable is changed + //or unset by another thread between the two syscalls. + std::optional<std::string> try_get_environment_variable( + const std::string &name) { + + uint64_t rax = 22; + uint64_t rdi = (uint64_t)name.data(); + uint64_t rsi = name.size(); + uint64_t rdx; + + __euler_do_syscall(rax, rdi, rsi, rdx); + + if (rax == (uint64_t)-1) + return {}; + + std::string s; + s.resize(rax); + + rax = 23; + rdi = (uint64_t)name.data(); + rsi = name.size(); + rdx = (uint64_t)s.data(); + + __euler_do_syscall(rax, rdi, rsi, rdx); + //do i need to tell gcc that s is modified? + + return s; + + } + +} |