diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/linux.c | 92 | ||||
| -rw-r--r-- | src/backend/x86.c | 75 |
2 files changed, 167 insertions, 0 deletions
diff --git a/src/backend/linux.c b/src/backend/linux.c new file mode 100644 index 0000000..dfa5a80 --- /dev/null +++ b/src/backend/linux.c @@ -0,0 +1,92 @@ +#include <backend.h> + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <assert.h> + +#include "../sv.h" + +static FILE *src; +static FILE *dst; + +void die(const char *name, const char *file, size_t line, const char *fmt, ...) +{ + printf("ERROR %s(%s:%d): ", name, file, line); + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + printf("\nCompilation failed!\n"); + exit(1); +} + +void debug(const char *name, const char *file, size_t line, const char *fmt, ...) +{ + printf("LOG %s(%s:%d): ", name, file, line); + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} + +struct string_view backend_stream_init_src(const char *path) +{ + assert(path != NULL); + src = fopen(path, "r"); + fseek(src, 0, SEEK_END); + size_t size = ftell(src); + fseek(src, 0, SEEK_SET); + char *buf = malloc(size + 1); + if(fread(buf, size, 1, src) == 0) + DIE("Failed to read the file!\n"); + buf[size] = '\0'; + return (struct string_view){.buf = buf, .len = size}; +} + +void backend_stream_init_dst(const char *path) +{ + dst = fopen(path, "w"); +} + +void backend_stream_close_src() +{ + fclose(src); +} + +void backend_stream_close_dst() +{ + fclose(dst); +} + +void emit8(uint8_t out) +{ + fprintf(dst, "%02x", out); +} + +void emit16(uint16_t out) +{ + uint8_t test = 0; + for(int i = 0; i < 2; i++) { + test = (out >> (i * 8)) & 0xFF; + fprintf(dst, "%02x", test); + } +} + +void emit32(uint32_t out) +{ + uint8_t test = 0; + for(int i = 0; i < 4; i++) { + test = (out >> (i * 8)) & 0xFF; + fprintf(dst, "%02x", test); + } +} + +void emit64(uint64_t out) +{ + uint8_t test = 0; + for(int i = 0; i < 8; i++) { + test = (out >> (i * 8)) & 0xFF; + fprintf(dst, "%02x", test); + } +} diff --git a/src/backend/x86.c b/src/backend/x86.c new file mode 100644 index 0000000..05aafc1 --- /dev/null +++ b/src/backend/x86.c @@ -0,0 +1,75 @@ +#include <x86.h> + +#include <backend.h> + +#define REG_SAFETY(reg) \ + do { \ + if(reg > 15) DIE("Compiler error! Register %d is invalid!" \ + , reg); \ + } while(0) + +// TODO: Consider implementing a modrm backend that is rex-aware. + +//void x86_calc_modrm(uint16_t reg, uint16_t mod) + +void x86_mov_r_i64(uint8_t reg, uint64_t value) +{ + REG_SAFETY(reg); + emit8(REXW); + emit8(0xB8 + reg); + emit64(value); +} + +void x86_mov_rm_i64(uint8_t mode, uint16_t reg) +{ + DIE("TODO"); +} + +void x86_push_i32(uint32_t value) +{ + emit8(0x68); + emit32(value); +} + +/* + * @todo + */ +void x86_push_i16(uint16_t value) +{ + DIE("NOT IMPLEMENTED"); + // 66h + // PUSH 68 + // IMM value +} + +void x86_push_i8(uint8_t value) +{ + emit8(0x6A); + emit8(value); +} + +void x86_push_r64(uint8_t reg) +{ + REG_SAFETY(reg); + emit8(0x50 + reg); +} + +void x86_push_rm64(uint8_t mode, uint8_t r, uint64_t m) +{ + REG_SAFETY(r); + + if(r > 7) { + emit8(REXWR); + } else if (r < 7) { + emit8(REXW); + } + + emit8(0xFF); + + // Calculate MODRM + + // emit MODRM byte + // if mode = 1: + // disp + // done +} |
