Files
minimalc/arch/x86_64.c

268 lines
7.3 KiB
C

#if defined(__x86_64__)
#include "../int.h"
#include "../sys.h"
// Start code
#ifndef _START_DEFINED
#define _START_DEFINED
extern int main(int argc, char **argv);
void _start() {
void *fp = __builtin_frame_address(0);
register int argc asm("rdi") = *(uint64_t *)(fp + 8);
register char **argv asm("rsi") = fp + 16;
exit(main(argc, argv));
}
#endif /* ifndef _START_DEFINED */
// include other generic functions
#include "generic.h"
//
// syscall functions
#define SYS_EXIT 60
void exit(int8_t status) {
asm volatile("syscall" : : "a"(SYS_EXIT), "D"(status) :);
for (;;)
;
}
#define SYS_WRITE 1
intptr_t write(int32_t fd, const void *buf, intptr_t size) {
intptr_t n_written = 0;
asm volatile("syscall\n"
"movq %0, %%rax\n"
: "=r"(n_written)
: "a"(SYS_WRITE), "D"(fd), "S"(buf),
"d"(size) // RDI, RSI, RDX are used in x86-64 for write args
: "rcx", "r11");
return n_written;
}
#define SYS_READ 0
intptr_t read(int32_t fd, const void *buf, intptr_t size) {
intptr_t n_read = 0;
asm volatile("syscall\n"
"movq %0, %%rax\n"
: "=r"(n_read)
: "a"(SYS_READ), "D"(fd), "S"(buf),
"d"(size) // RDI, RSI, RDX are used in x86-64 for write args
: "rcx", "r11", "memory");
return n_read;
}
#define SYS_FORK 57
uint32_t fork() {
uint64_t rtn;
asm volatile("syscall\n" // syscall
"movq %0, %%rax\n" // save return value
: "=r"(rtn)
: "a"(SYS_FORK)
:);
return (uint32_t)rtn;
}
#define SYS_EXECVE 59
int32_t execve(const char *filename, const char *argv[], const char *envp[]) {
int64_t rtn;
asm volatile("syscall\n"
: "=r"(rtn)
: "a"(SYS_EXECVE), "D"(filename), "S"(argv), "d"(envp)
: "rcx", "r11");
return (int32_t)rtn;
}
#define SYS_WAIT4 61
uint32_t wait4(uint32_t pid, int *wstatus, int options, void *rusage) {
uint32_t child_pid;
asm volatile("mov %5, %%r10\n"
"syscall\n"
: "=a"(child_pid)
: "a"(SYS_WAIT4), "D"(pid), "S"(wstatus), "d"(options),
"r"(rusage)
: "rcx", "r10", "r11", "memory");
return child_pid;
}
uint32_t waitpid(uint32_t pid, int *wstatus, int options) {
return wait4(pid, wstatus, options, 0);
}
#define SYS_OPENAT 257
int32_t openat(int32_t fd, const char *filename, uint32_t flags,
uint32_t mode) {
int32_t file;
asm volatile(
"mov %5, %%r10\n"
"syscall\n"
: "=a"(file)
: "a"(SYS_OPENAT), "D"(fd), "S"(filename), "d"(flags),
"r"((uint64_t)mode) // RDI, RSI, RDX are used in x86-64 for write args
: "rcx", "r10", "r11");
return file;
}
#define SYS_CLOSE 3
int close(unsigned int fd) {
int rtn;
asm volatile("syscall" : "=a"(rtn) : "a"(SYS_CLOSE), "D"(fd) : "rcx", "r11");
return rtn;
}
#define SYS_FSYNC 74
int fsync(unsigned int fd) {
int rtn;
asm volatile("syscall" : "=a"(rtn) : "a"(SYS_FSYNC), "D"(fd) : "rcx", "r11");
return rtn;
}
#define SYS_SOCKET 41
int socket(int domain, int type, int protocol) {
int32_t fd;
asm volatile("syscall\n"
: "=a"(fd)
: "a"(SYS_SOCKET), "D"(domain), "S"(type), "d"(protocol)
: "rcx", "r11");
return fd;
}
#define SYS_SETSOCKOPT 54
int setsockopt(int fd, int level, int optname, const void *optval,
socklen_t optlen) {
int rtn;
asm volatile("mov %5, %%r10\n"
"mov %6, %%r8\n"
"syscall\n"
: "=a"(rtn)
: "a"(SYS_SETSOCKOPT), "D"(fd), "S"(level), "d"(optname),
"r"(optval), "r"((uint64_t)optlen)
: "rcx", "r11");
return rtn;
}
#define SYS_BIND 49
int bind(int fd, const void *sockaddr, socklen_t addrlen) {
int rtn;
asm volatile("syscall\n"
: "=a"(rtn)
: "a"(SYS_BIND), "D"(fd), "S"(sockaddr), "d"(addrlen)
: "rcx", "r11");
return rtn;
}
#define SYS_LISTEN 50
int listen(int fd, int backlog) {
int rtn;
asm volatile("syscall\n"
: "=a"(rtn)
: "a"(SYS_LISTEN), "D"(fd), "S"(backlog)
: "rcx", "r11");
return rtn;
}
#define SYS_ACCEPT 43
int accept(int fd, void *addr, socklen_t *addrlen) {
int rtn;
asm volatile("syscall\n"
: "=a"(rtn)
: "a"(SYS_ACCEPT), "D"(fd), "S"(addr), "d"(addrlen)
: "rcx", "r11", "memory");
return rtn;
}
#define SYS_CONNECT 42
int connect(int fd, void *addr, socklen_t addrlen) {
int rtn;
asm volatile("syscall\n"
: "=a"(rtn)
: "a"(SYS_CONNECT), "D"(fd), "S"(addr), "d"(addrlen)
: "rcx", "r11");
return rtn;
}
#define SYS_SENDTO 44
ssize_t sendto(int fd, const void *buf, size_t size, int flags,
const void *sockaddr, socklen_t addrlen) {
ssize_t nsent;
asm volatile("mov %5, %%r10\n"
"mov %6, %%r8\n"
"mov %7, %%r9\n"
"syscall\n"
: "=a"(nsent)
: "a"(SYS_SENDTO), "D"(fd), "S"(buf), "d"(size),
"r"((int64_t)flags), "r"(sockaddr), "r"((uint64_t)addrlen)
: "rcx", "r11");
return nsent;
}
#define SYS_RECVFROM 45
ssize_t recvfrom(int fd, const void *buf, size_t size, int flags,
const void *sockaddr, socklen_t addrlen) {
ssize_t nrecv;
asm volatile("mov %5, %%r10\n"
"mov %6, %%r8\n"
"mov %7, %%r9\n"
"syscall\n"
: "=a"(nrecv)
: "a"(SYS_RECVFROM), "D"(fd), "S"(buf), "d"(size),
"r"((int64_t)flags), "r"(sockaddr), "r"((int64_t)addrlen)
: "rcx", "r11", "memory");
return nrecv;
}
#define SYS_CLOCK_SETTIME 227
int clock_settime(clockid_t clockid, const struct timespec *tp) {
int rtn;
asm volatile("syscall\n"
: "=a"(rtn)
: "a"(SYS_CLOCK_SETTIME), "D"(clockid), "S"(tp)
: "rcx", "r11");
return rtn;
}
#define SYS_CLOCK_GETTIME 228
int clock_gettime(clockid_t clockid, struct timespec *tp) {
int rtn;
asm volatile("syscall\n"
: "=a"(rtn)
: "a"(SYS_CLOCK_GETTIME), "D"(clockid), "S"(tp)
: "rcx", "r11", "memory");
return rtn;
}
#define SYS_CLOCK_GETRES 229
int clock_getres(clockid_t clockid, struct timespec *res) {
int rtn;
asm volatile("syscall\n"
: "=a"(rtn)
: "a"(SYS_CLOCK_GETRES), "D"(clockid), "S"(res)
: "rcx", "r11", "memory");
return rtn;
}
#define SYS_CLOCK_NANOSLEEP 230
int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *t,
struct timespec *remain) {
int rtn;
asm volatile("mov %5, %%r10\n"
"syscall\n"
: "=a"(rtn)
: "a"(SYS_CLOCK_NANOSLEEP), "D"(clockid), "S"(flags), "d"(t),
"r"(remain)
: "rcx", "r11", "memory");
return rtn;
}
#define SYS_RT_SIGACTION 13
int rt_sigaction(int signum, const void *act, void *oldact, size_t sigset_len) {
int rtn;
asm volatile("mov %5, %%r10\n"
"syscall\n"
: "=a"(rtn)
: "a"(SYS_RT_SIGACTION), "D"(signum), "S"(act), "d"(oldact),
"r"(sigset_len)
: "rcx", "r11", "memory");
return rtn;
}
#endif /* ifdef __x86_64__ */