summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/linux.c92
-rw-r--r--src/backend/x86.c75
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
+}