minimalc/arch/x86_64.c

277 lines
5.9 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_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__ */