From dc594e5e828e7c0b85bdeebe1b09e41d43e44ae0 Mon Sep 17 00:00:00 2001 From: veclavtlica Date: Thu, 8 Oct 2026 10:50:42 +0300 Subject: [PATCH] x86 support! --- Common/Std/linux-amd64.c | 4 +- Common/Std/linux-x86.c | 92 ++++++++++++++++++++++++++ Player/Main/{linux.c => linux-amd64.c} | 0 Player/Main/linux-x86.c | 26 ++++++++ Player/amalgam.c | 7 +- 5 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 Common/Std/linux-x86.c rename Player/Main/{linux.c => linux-amd64.c} (100%) create mode 100644 Player/Main/linux-x86.c diff --git a/Common/Std/linux-amd64.c b/Common/Std/linux-amd64.c index cd5fc43..60ac7f4 100644 --- a/Common/Std/linux-amd64.c +++ b/Common/Std/linux-amd64.c @@ -6,7 +6,6 @@ #include "../std.h" #include -#include #include #include #include @@ -20,7 +19,7 @@ inline com_std_fd com_std_open(char *path, uint32_t flags) { long ret; __asm__ volatile("syscall" : "=a"(ret) - : "a"(2), "D"(path), "S"(mode) + : "a"(2), "D"(path), "S"(mode), "d"(0) : "rcx", "r11", "memory"); if (ret <= 0) /* Mark NULL, removing error code */ ret = 0; @@ -90,4 +89,5 @@ inline void com_std_exit(uint32_t status) { inline void com_std_close(com_std_fd fd) { __asm__ volatile("syscall" : : "a"(3), "D"(fd) : "rcx", "r11", "memory"); + /* TODO: At least assert for bad descriptor for debug? */ } diff --git a/Common/Std/linux-x86.c b/Common/Std/linux-x86.c new file mode 100644 index 0000000..e5572ce --- /dev/null +++ b/Common/Std/linux-x86.c @@ -0,0 +1,92 @@ +/* + AMD64 specific Linux std parts. +*/ + +#include "linux.c" + +#include "../std.h" +#include +#include +#include +#include + +inline com_std_fd com_std_open(char *path, uint32_t flags) { + com_std_assert(flags != 0); + uint32_t mode = flags & COM_STD_OPEN_READ && flags & COM_STD_OPEN_WRITE + ? O_RDWR + : flags & COM_STD_OPEN_READ ? O_RDONLY + : O_WRONLY; + long ret; + __asm__ volatile("int $0x80" + : "=a"(ret) + : "a"(5), "b"(path), "c"(mode), "d"(0) + : "memory", "cc"); + if (ret <= 0) /* Mark NULL, removing error code */ + ret = 0; + return (void *)ret; +} + +inline bool com_std_write(com_std_fd fd, char const *data, uint32_t bytes) { + long ret; + __asm__ volatile("int $0x80" + : "=a"(ret) + : "a"(4), "b"(fd), "c"(data), "d"(bytes) + : "memory", "cc"); + return ret == bytes; +} + +inline int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto) { + long ret; + __asm__ volatile("int $0x80" + : "=a"(ret) + : "a"(3), "b"(fd), "c"(data), "d"(upto) + : "memory", "cc"); + return ret; +} + +inline bool com_std_sfwd(com_std_fd fd, uint32_t bytes) { + long ret; + __asm__ volatile("int $0x80" + : "=a"(ret) + : "a"(19), "b"(fd), "c"(bytes), "d"(SEEK_CUR) + : "memory", "cc"); + return ret >= 0; /* TODO: Check whether offset is bytes offset exactly? */ +} + +inline com_std_fd com_std_socket(bool isnetwork) { + if (!isnetwork) { + int32_t sockfd; + __asm__ volatile("int $0x80" + : "=a"(sockfd) + : "a"(359), "b"(AF_UNIX), "c"(SOCK_STREAM), "d"(0) + : "memory", "cc"); + if (sockfd < 0) + sockfd = 0; + return (void *)(int64_t)sockfd; + } else + return NULL; +} + +inline bool com_std_connect(com_std_fd fd, bool isnetwork, char *address) { + com_std_assert(address != NULL); + if (!isnetwork) { + struct sockaddr_un addr = {.sun_family = AF_UNIX}; + __builtin_memcpy(&addr.sun_path, address, com_str_ext_len(address)); + int32_t ret; + __asm__ volatile("int $0x80" + : "=a"(ret) + : "a"(362), "b"(fd), "c"(&addr), "d"(sizeof addr) + : "memory", "cc"); + return ret == 0; + } else + return NULL; +} + +inline void com_std_exit(uint32_t status) { + __asm__ volatile("int $0x80" : : "a"(1), "b"(status) : "memory", "cc"); + __builtin_unreachable(); +} + +inline void com_std_close(com_std_fd fd) { + __asm__ volatile("int $0x80" : : "a"(6), "b"(fd) : "memory", "cc"); +} diff --git a/Player/Main/linux.c b/Player/Main/linux-amd64.c similarity index 100% rename from Player/Main/linux.c rename to Player/Main/linux-amd64.c diff --git a/Player/Main/linux-x86.c b/Player/Main/linux-x86.c new file mode 100644 index 0000000..ee5f5b4 --- /dev/null +++ b/Player/Main/linux-x86.c @@ -0,0 +1,26 @@ + +/* No libc starting point. Jump straight into action! */ +__attribute__((naked)) __attribute__((force_align_arg_pointer)) +__attribute__((noreturn)) extern void +_start(void) { + __asm__ volatile("xorl %ebp, %ebp\n" + "movl (%esp), %ecx\n" + "leal 4(%esp), %edx\n" + + /* 3. Align the stack pointer to a 16-byte boundary */ + "andl $-16, %esp\n" + + /* 4. Reserve stack space for main's arguments + padding + We need to pass 2 arguments (8 bytes). + To keep %esp 16-byte aligned before the "call", + we allocate 16 bytes total. */ + "subl $16, %esp\n" + + /* 5. Place arguments onto the newly aligned stack */ + "movl %ecx, (%esp)\n" + "movl %edx, 4(%esp)\n" + "call plr_display_x11_main\n" + "movl %eax, %ebx\n" + "movl $1, %eax\n" + "int $0x80"); +} diff --git a/Player/amalgam.c b/Player/amalgam.c index 65d0217..afc5097 100644 --- a/Player/amalgam.c +++ b/Player/amalgam.c @@ -12,10 +12,15 @@ #include "./draw.c" #if COM_DEF_TARGET == COM_DEF_TARGET_LINUX +#if COM_DEF_CPU == COM_DEF_CPU_AMD64 #include "../Common/Std/linux-amd64.c" +#include "./Main/linux-amd64.c" +#elif COM_DEF_CPU == COM_DEF_CPU_X86 +#include "../Common/Std/linux-x86.c" +#include "./Main/linux-x86.c" +#endif #include "../Common/Timer/stub.c" #include "./Display/x11.c" -#include "./Main/linux.c" // #include "./Main/libc.c" #elif COM_DEF_TARGET == COM_DEF_TARGET_WASM #include "../Common/Std/stub.c"