diff options
author | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-10-08 04:16:27 +0330 |
---|---|---|
committer | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-10-08 04:17:08 +0330 |
commit | addd54dc31603dc204773d3108dba4e000cd7657 (patch) | |
tree | 621620c4ca5634680d7655e3474cf0b0bcec8e01 /src/fasm/runner | |
parent | bf84010e01bb11874689ce53ea4df853b2e41c2b (diff) |
added fasm support
added compiler options
tried to compile to fasm first
Diffstat (limited to 'src/fasm/runner')
-rw-r--r-- | src/fasm/runner/runner.c | 646 | ||||
-rw-r--r-- | src/fasm/runner/runner.h | 36 |
2 files changed, 682 insertions, 0 deletions
diff --git a/src/fasm/runner/runner.c b/src/fasm/runner/runner.c new file mode 100644 index 0000000..c01db18 --- /dev/null +++ b/src/fasm/runner/runner.c @@ -0,0 +1,646 @@ +#include "runner.h" + +#include <fasm/lexer/lexer.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syscall.h> +#include <unistd.h> +#include <utils/memory/memory.h> + +#define PUSHN(bits) \ + pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, \ + getNext##bits##Bits(&ip)); \ + ip += bits / 8 + +#define LOADN(bits) \ + pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, \ + *((uint##bits##_t *)popFromStack64Bits( \ + &stack, &stack_size, &stack_filled))) + +#define POPN(bits) \ + { \ + uint##bits##_t *pointer = (uint##bits##_t *)popFromStack64Bits( \ + &stack, &stack_size, &stack_filled); \ + *pointer = popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \ + } + +#define DUPN(bits) \ + { \ + const uint##bits##_t a = \ + popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \ + pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, a); \ + pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, a); \ + } + +#define SWAPN(bits) \ + { \ + const uint##bits##_t a = \ + popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \ + const uint##bits##_t b = \ + popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \ + pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, a); \ + pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, b); \ + } + +#define DROPN(bits) \ + popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); + +#define OPERATION(type, bits, op) \ + { \ + const type a = \ + popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \ + const type b = \ + popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \ + const type result = a op b; \ + pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, \ + *(uint##bits##_t *)&result); \ + } + +#define ADD(type, bits) OPERATION(type, bits, +) + +#define SUB(type, bits) OPERATION(type, bits, -) + +#define NEG(type, bits) \ + { \ + const type a = \ + popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \ + const type result = -a; \ + pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, \ + *(uint##bits##_t *)&result); \ + } + +#define MUL(type, bits) OPERATION(type, bits, *) + +#define DIV(type, bits) OPERATION(type, bits, /) + +#define REM(type, bits) OPERATION(type, bits, %) + +#define CAST(from, from_bits, to, to_bits) \ + { \ + const from a = \ + popFromStack##from_bits##Bits(&stack, &stack_size, &stack_filled); \ + const to result = a; \ + pushToStack##to_bits##Bits(&stack, &stack_size, &stack_filled, \ + *(uint##to_bits##_t *)&result); \ + } + +#define COND_JUMP(type, bits, op) \ + { \ + const uint##bits##_t a = \ + popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \ + \ + if (*((type *)&a)op 0) { \ + ip = (uint8_t *)popFromStack64Bits(&stack, &stack_size, &stack_filled); \ + } \ + } + +int fasmRunner(ByteCode bytecode) { + uint8_t *data = a404m_malloc(bytecode.data_size); + size_t data_size = bytecode.data_size; + memcpy(data, bytecode.data, data_size); + + size_t stack_size = 0; + size_t stack_filled = 0; + uint8_t *stack = a404m_malloc(stack_size); + + size_t functions_size = 0; + size_t functions_index = -1; + FasmFunction *functions = a404m_malloc(functions_size * sizeof(*functions)); + + uint8_t *ip = bytecode.code; + + while (true) { + const FasmToken instruction = *ip; + ++ip; + switch (instruction) { + case FASM_TOKEN_NOOP: + break; + case FASM_TOKEN_PUSH8: + PUSHN(8); + break; + case FASM_TOKEN_PUSH16: + PUSHN(16); + break; + case FASM_TOKEN_PUSH32: + PUSHN(32); + break; + case FASM_TOKEN_PUSH64: + PUSHN(64); + break; + case FASM_TOKEN_LOAD8: + LOADN(8); + break; + case FASM_TOKEN_LOAD16: + LOADN(16); + break; + case FASM_TOKEN_LOAD32: + LOADN(32); + break; + case FASM_TOKEN_LOAD64: + LOADN(64); + break; + case FASM_TOKEN_POP8: + POPN(8); + break; + case FASM_TOKEN_POP16: + POPN(16); + break; + case FASM_TOKEN_POP32: + POPN(32); + break; + case FASM_TOKEN_POP64: + POPN(64); + break; + case FASM_TOKEN_DUP8: + DUPN(8); + break; + case FASM_TOKEN_DUP16: + DUPN(16); + break; + case FASM_TOKEN_DUP32: + DUPN(32); + break; + case FASM_TOKEN_DUP64: + DUPN(64); + break; + case FASM_TOKEN_SWAP8: + SWAPN(8); + break; + case FASM_TOKEN_SWAP16: + SWAPN(16); + break; + case FASM_TOKEN_SWAP32: + SWAPN(32); + break; + case FASM_TOKEN_SWAP64: + SWAPN(64); + break; + case FASM_TOKEN_DROP8: + DROPN(8); + break; + case FASM_TOKEN_DROP16: + DROPN(16); + break; + case FASM_TOKEN_DROP32: + DROPN(32); + break; + case FASM_TOKEN_DROP64: + DROPN(64); + break; + case FASM_TOKEN_ADD_I8: + ADD(uint8_t, 8); + break; + case FASM_TOKEN_ADD_I16: + ADD(uint16_t, 16); + break; + case FASM_TOKEN_ADD_I32: + ADD(uint32_t, 32); + break; + case FASM_TOKEN_ADD_I64: + ADD(uint64_t, 64); + break; + case FASM_TOKEN_ADD_F32: + ADD(float, 32); + break; + case FASM_TOKEN_ADD_F64: + ADD(double, 64); + break; + case FASM_TOKEN_SUB_I8: + SUB(uint8_t, 8); + break; + case FASM_TOKEN_SUB_I16: + SUB(uint16_t, 16); + break; + case FASM_TOKEN_SUB_I32: + SUB(uint32_t, 32); + break; + case FASM_TOKEN_SUB_I64: + SUB(uint64_t, 64); + break; + case FASM_TOKEN_SUB_F32: + SUB(float, 32); + break; + case FASM_TOKEN_SUB_F64: + SUB(double, 64); + break; + case FASM_TOKEN_NEG_I8: + NEG(int8_t, 8); + break; + case FASM_TOKEN_NEG_I16: + NEG(int16_t, 16); + break; + case FASM_TOKEN_NEG_I32: + NEG(int32_t, 32); + break; + case FASM_TOKEN_NEG_I64: + NEG(int64_t, 64); + break; + case FASM_TOKEN_NEG_F32: + NEG(float, 32); + break; + case FASM_TOKEN_NEG_F64: + NEG(double, 64); + break; + case FASM_TOKEN_MUL_I8: + MUL(int8_t, 8); + break; + case FASM_TOKEN_MUL_I16: + MUL(int16_t, 16); + break; + case FASM_TOKEN_MUL_I32: + MUL(int32_t, 32); + break; + case FASM_TOKEN_MUL_I64: + MUL(int64_t, 64); + break; + case FASM_TOKEN_MUL_U8: + MUL(uint8_t, 8); + break; + case FASM_TOKEN_MUL_U16: + MUL(uint16_t, 16); + break; + case FASM_TOKEN_MUL_U32: + MUL(uint32_t, 32); + break; + case FASM_TOKEN_MUL_U64: + MUL(uint64_t, 64); + break; + case FASM_TOKEN_MUL_F32: + MUL(float, 32); + break; + case FASM_TOKEN_MUL_F64: + MUL(double, 64); + break; + case FASM_TOKEN_DIV_I8: + DIV(int8_t, 8); + break; + case FASM_TOKEN_DIV_I16: + DIV(int16_t, 16); + break; + case FASM_TOKEN_DIV_I32: + DIV(int32_t, 32); + break; + case FASM_TOKEN_DIV_I64: + DIV(int64_t, 64); + break; + case FASM_TOKEN_DIV_U8: + DIV(uint8_t, 8); + break; + case FASM_TOKEN_DIV_U16: + DIV(uint16_t, 16); + break; + case FASM_TOKEN_DIV_U32: + DIV(uint32_t, 32); + break; + case FASM_TOKEN_DIV_U64: + DIV(uint64_t, 64); + break; + case FASM_TOKEN_DIV_F32: + DIV(float, 32); + break; + case FASM_TOKEN_DIV_F64: + DIV(double, 64); + break; + case FASM_TOKEN_REM_I8: + REM(int8_t, 8); + break; + case FASM_TOKEN_REM_I16: + REM(int16_t, 16); + break; + case FASM_TOKEN_REM_I32: + REM(int32_t, 32); + break; + case FASM_TOKEN_REM_I64: + REM(int64_t, 64); + break; + case FASM_TOKEN_REM_U8: + REM(uint8_t, 8); + break; + case FASM_TOKEN_REM_U16: + REM(uint16_t, 16); + break; + case FASM_TOKEN_REM_U32: + REM(uint32_t, 32); + break; + case FASM_TOKEN_REM_U64: + REM(uint64_t, 64); + break; + case FASM_TOKEN_CAST_I8_I64: + CAST(int8_t, 8, int64_t, 64); + break; + case FASM_TOKEN_CAST_I16_I64: + CAST(int16_t, 16, int64_t, 64); + break; + case FASM_TOKEN_CAST_I32_I64: + CAST(int32_t, 32, int64_t, 64); + break; + case FASM_TOKEN_CAST_I64_I8: + CAST(int64_t, 64, int8_t, 8); + break; + case FASM_TOKEN_CAST_I64_I16: + CAST(int64_t, 64, int16_t, 16); + break; + case FASM_TOKEN_CAST_I64_I32: + CAST(int64_t, 64, int32_t, 32); + break; + case FASM_TOKEN_CAST_F64_I64: + CAST(double, 64, int64_t, 64); + break; + case FASM_TOKEN_CAST_I64_F64: + CAST(int64_t, 64, double, 64); + break; + case FASM_TOKEN_CAST_U8_U64: + CAST(uint8_t, 8, uint64_t, 64); + break; + case FASM_TOKEN_CAST_U16_U64: + CAST(uint16_t, 16, uint64_t, 64); + break; + case FASM_TOKEN_CAST_U32_U64: + CAST(uint32_t, 32, uint64_t, 64); + break; + case FASM_TOKEN_CAST_U64_U8: + CAST(uint64_t, 64, uint8_t, 8); + break; + case FASM_TOKEN_CAST_U64_U16: + CAST(uint64_t, 64, uint16_t, 16); + break; + case FASM_TOKEN_CAST_U64_U32: + CAST(uint64_t, 64, uint32_t, 32); + break; + case FASM_TOKEN_CAST_F64_U64: + CAST(double, 64, uint64_t, 64); + break; + case FASM_TOKEN_CAST_U64_F64: + CAST(uint64_t, 64, double, 64); + break; + case FASM_TOKEN_CAST_F32_F64: + CAST(float, 32, double, 64); + break; + case FASM_TOKEN_CAST_F64_F32: + CAST(double, 64, float, 32); + break; + case FASM_TOKEN_JUMP: + ip = (uint8_t *)popFromStack64Bits(&stack, &stack_size, &stack_filled); + break; + case FASM_TOKEN_JZ_I8: + COND_JUMP(int8_t, 8, ==); + break; + case FASM_TOKEN_JNZ_I8: + COND_JUMP(int8_t, 8, !=); + break; + case FASM_TOKEN_JN_I8: + COND_JUMP(int8_t, 8, <); + break; + case FASM_TOKEN_JNN_I8: + COND_JUMP(int8_t, 8, >=); + break; + case FASM_TOKEN_JP_I8: + COND_JUMP(int8_t, 8, >); + break; + case FASM_TOKEN_JNP_I8: + COND_JUMP(int8_t, 8, <=); + break; + case FASM_TOKEN_JZ_I16: + COND_JUMP(int16_t, 16, ==); + break; + case FASM_TOKEN_JNZ_I16: + COND_JUMP(int16_t, 16, !=); + break; + case FASM_TOKEN_JN_I16: + COND_JUMP(int16_t, 16, <); + break; + case FASM_TOKEN_JNN_I16: + COND_JUMP(int16_t, 16, >=); + break; + case FASM_TOKEN_JP_I16: + COND_JUMP(int16_t, 16, >); + break; + case FASM_TOKEN_JNP_I16: + COND_JUMP(int16_t, 16, <=); + break; + case FASM_TOKEN_JZ_I32: + COND_JUMP(int32_t, 32, ==); + break; + case FASM_TOKEN_JNZ_I32: + COND_JUMP(int32_t, 32, !=); + break; + case FASM_TOKEN_JN_I32: + COND_JUMP(int32_t, 32, <); + break; + case FASM_TOKEN_JNN_I32: + COND_JUMP(int32_t, 32, >=); + break; + case FASM_TOKEN_JP_I32: + COND_JUMP(int32_t, 32, >); + break; + case FASM_TOKEN_JNP_I32: + COND_JUMP(int32_t, 32, <=); + break; + case FASM_TOKEN_JZ_I64: + COND_JUMP(int64_t, 64, ==); + break; + case FASM_TOKEN_JNZ_I64: + COND_JUMP(int64_t, 64, !=); + break; + case FASM_TOKEN_JN_I64: + COND_JUMP(int64_t, 64, <); + break; + case FASM_TOKEN_JNN_I64: + COND_JUMP(int64_t, 64, >=); + break; + case FASM_TOKEN_JP_I64: + COND_JUMP(int64_t, 64, >); + break; + case FASM_TOKEN_JNP_I64: + COND_JUMP(int64_t, 64, <=); + break; + case FASM_TOKEN_JZ_F32: + COND_JUMP(float, 32, ==); + break; + case FASM_TOKEN_JNZ_F32: + COND_JUMP(float, 32, !=); + break; + case FASM_TOKEN_JN_F32: + COND_JUMP(float, 32, <); + break; + case FASM_TOKEN_JNN_F32: + COND_JUMP(float, 32, >=); + break; + case FASM_TOKEN_JP_F32: + COND_JUMP(float, 32, >); + break; + case FASM_TOKEN_JNP_F32: + COND_JUMP(float, 32, <=); + break; + case FASM_TOKEN_JZ_F64: + COND_JUMP(double, 64, ==); + break; + case FASM_TOKEN_JNZ_F64: + COND_JUMP(double, 64, !=); + break; + case FASM_TOKEN_JN_F64: + COND_JUMP(double, 64, <); + break; + case FASM_TOKEN_JNN_F64: + COND_JUMP(double, 64, >=); + break; + case FASM_TOKEN_JP_F64: + COND_JUMP(double, 64, >); + break; + case FASM_TOKEN_JNP_F64: + COND_JUMP(double, 64, <=); + break; + case FASM_TOKEN_ALLOC_HEAP: + pushToStack64Bits(&stack, &stack_size, &stack_filled, + (uint64_t)a404m_malloc(popFromStack64Bits( + &stack, &stack_size, &stack_filled))); + break; + case FASM_TOKEN_ALLOC_STACK: + functions[functions_index].stack_size = + popFromStack64Bits(&stack, &stack_size, &stack_filled); + functions[functions_index].stack = + a404m_malloc(functions[functions_index].stack_size); + break; + case FASM_TOKEN_FREE_HEAP: + free((void *)popFromStack64Bits(&stack, &stack_size, &stack_filled)); + break; + case FASM_TOKEN_GET_STACK_ADDRESS: + pushToStack64Bits(&stack, &stack_size, &stack_filled, + (uint64_t)functions[functions_index].stack); + break; + case FASM_TOKEN_GET_GLOBAL_ADDRESS: + pushToStack64Bits(&stack, &stack_size, &stack_filled, (uint64_t)data); + break; + case FASM_TOKEN_CALL: { + uint8_t *const newIp = + (uint8_t *)popFromStack64Bits(&stack, &stack_size, &stack_filled); + ++functions_index; + if (functions_index == functions_size) { + functions_size += functions_size / 2 + 1; + functions = + a404m_realloc(functions, functions_size * sizeof(*functions)); + } + FasmFunction function = { + .returnTo = ip, + .stack = a404m_malloc(0), + .stack_size = 0, + }; + functions[functions_index] = function; + ip = newIp; + } break; + case FASM_TOKEN_RET: { + FasmFunction function = functions[functions_index]; + free(function.stack); + ip = function.returnTo; + --functions_index; + if (functions_index + sizeof(*functions) < functions_size / 2) { + functions_size = functions_size / 2; + functions = + a404m_realloc(functions, functions_size * sizeof(*functions)); + } + } break; + case FASM_TOKEN_SYSCALL: { + switch ((FasmSyscall)popFromStack8Bits(&stack, &stack_size, + &stack_filled)) { + case FASM_SYSCALL_READ: { + uint32_t fd = + popFromStack32Bits(&stack, &stack_size, &stack_filled); + int8_t *buf = (int8_t *)popFromStack64Bits(&stack, &stack_size, + &stack_filled); + uint64_t count = + popFromStack64Bits(&stack, &stack_size, &stack_filled); + syscall(SYS_read, fd, buf, count); + } break; + case FASM_SYSCALL_WRITE: { + uint32_t fd = + popFromStack32Bits(&stack, &stack_size, &stack_filled); + int8_t *buf = (int8_t *)popFromStack64Bits(&stack, &stack_size, + &stack_filled); + uint64_t count = + popFromStack64Bits(&stack, &stack_size, &stack_filled); + syscall(SYS_write, fd, buf, count); + } break; + case FASM_SYSCALL_OPEN: { + int8_t *filename = (int8_t *)popFromStack64Bits(&stack, &stack_size, + &stack_filled); + uint32_t flags = + popFromStack32Bits(&stack, &stack_size, &stack_filled); + uint32_t mode = + popFromStack32Bits(&stack, &stack_size, &stack_filled); + syscall(SYS_open, filename, flags, mode); + } break; + case FASM_SYSCALL_CLOSE: { + uint32_t fd = + popFromStack32Bits(&stack, &stack_size, &stack_filled); + syscall(SYS_close, fd); + } break; + case FASM_SYSCALL_EXIT: + for (size_t i = functions_index; i != (size_t)-1; ++i) { + free(functions[i].stack); + } + const uint32_t status = + popFromStack32Bits(&stack, &stack_size, &stack_filled); + free(functions); + free(stack); + free(data); + return status; + } + } break; + case FASM_TOKEN_DEFINE_BYTE: + case FASM_TOKEN_DEFINE_WORD: + case FASM_TOKEN_DEFINE_DWORD: + case FASM_TOKEN_DEFINE_QWORD: + case FASM_TOKEN_NONE: + default: + fprintf(stderr, "Bad fasm instruction %d", instruction); + exit(1); + } + } +} + +#define getNextNBits(bits) \ + uint##bits##_t getNext##bits##Bits(uint8_t **pos) { \ + uint##bits##_t *p = *((uint##bits##_t **)pos); \ + pos += sizeof(*p); \ + return *p; \ + } + +getNextNBits(8); +getNextNBits(16); +getNextNBits(32); +getNextNBits(64); + +#define pushToStackNBits(bits) \ + void pushToStack##bits##Bits(uint8_t **stack, size_t *stack_size, \ + size_t *stack_filled, uint##bits##_t value) { \ + const size_t new_stack_size = *stack_filled + sizeof(value); \ + if (new_stack_size >= *stack_size) { \ + *stack_size = new_stack_size + new_stack_size / 2 + 1; \ + *stack = a404m_realloc(*stack, *stack_size); \ + } \ + *((uint##bits##_t *)(*stack + *stack_filled)) = value; \ + *stack_filled = new_stack_size; \ + } +pushToStackNBits(8); +pushToStackNBits(16); +pushToStackNBits(32); +pushToStackNBits(64); + +#define popFromStackNBit(bits) \ + uint##bits##_t popFromStack##bits##Bits(uint8_t **stack, size_t *stack_size, \ + size_t *stack_filled) { \ + uint##bits##_t value; \ + *stack_filled -= sizeof(value); \ + value = *((uint##bits##_t *)(*stack + *stack_filled)); \ + if (*stack_filled < *stack_size / 2) { \ + *stack_size = *stack_filled; \ + *stack = a404m_realloc(*stack, *stack_size); \ + } \ + return value; \ + } +popFromStackNBit(8); +popFromStackNBit(16); +popFromStackNBit(32); +popFromStackNBit(64); diff --git a/src/fasm/runner/runner.h b/src/fasm/runner/runner.h new file mode 100644 index 0000000..0dfa338 --- /dev/null +++ b/src/fasm/runner/runner.h @@ -0,0 +1,36 @@ +#pragma once + +#include <fasm/code_generator/code_generator.h> +#include <stdint.h> + +typedef struct FasmFunction { + uint8_t *returnTo; + uint8_t *stack; + size_t stack_size; +}FasmFunction; + +extern int fasmRunner(ByteCode bytecode); + +#define getNextNBitsHeader(bits) \ + extern uint##bits##_t getNext##bits##Bits(uint8_t **pos) +getNextNBitsHeader(8); +getNextNBitsHeader(16); +getNextNBitsHeader(32); +getNextNBitsHeader(64); + +#define pushToStackNBitsHeader(bits) \ + extern void pushToStack##bits##Bits(uint8_t **stack, size_t *stack_size, \ + size_t *stack_filled, \ + uint##bits##_t value) +pushToStackNBitsHeader(8); +pushToStackNBitsHeader(16); +pushToStackNBitsHeader(32); +pushToStackNBitsHeader(64); + +#define popFromStackNBitsHeader(bits) \ + extern uint##bits##_t popFromStack##bits##Bits( \ + uint8_t **stack, size_t *stack_size, size_t *stack_filled) +popFromStackNBitsHeader(8); +popFromStackNBitsHeader(16); +popFromStackNBitsHeader(32); +popFromStackNBitsHeader(64); |