aboutsummaryrefslogtreecommitdiff
path: root/executor/x86_64/executor.c
diff options
context:
space:
mode:
Diffstat (limited to 'executor/x86_64/executor.c')
-rw-r--r--executor/x86_64/executor.c183
1 files changed, 99 insertions, 84 deletions
diff --git a/executor/x86_64/executor.c b/executor/x86_64/executor.c
index d35dbdc..9083e14 100644
--- a/executor/x86_64/executor.c
+++ b/executor/x86_64/executor.c
@@ -39,7 +39,9 @@ typedef struct {
int label_counter;
} amal_executor_impl;
-#define IMPL amal_executor_impl *impl = (amal_executor_impl*)self;
+#define IMPL_START \
+ amal_executor_impl *impl = (amal_executor_impl*)self; \
+ return_if_error(asm_ensure_capacity(&impl->asm, 256));
/*
@reg will be a positive value when accessing local variables, in which case the first
@@ -72,7 +74,7 @@ int amal_executor_init(amal_executor **self) {
}
void amal_executor_deinit(amal_executor *self) {
- IMPL
+ amal_executor_impl *impl = (amal_executor_impl*)self;
buffer_deinit(&impl->jump_defer);
buffer_deinit(&impl->call_defer);
am_free(impl->function_indices);
@@ -81,25 +83,24 @@ void amal_executor_deinit(amal_executor *self) {
}
int amal_executor_run(amal_executor *self, u32 offset) {
- IMPL
+ amal_executor_impl *impl = (amal_executor_impl*)self;
return asm_execute(&impl->asm, offset);
}
u32 amal_exec_get_code_offset(amal_executor *self) {
- IMPL
+ amal_executor_impl *impl = (amal_executor_impl*)self;
return asm_get_size(&impl->asm);
}
int amal_executor_instructions_start(amal_executor *self, u16 num_functions) {
- IMPL
+ amal_executor_impl *impl = (amal_executor_impl*)self;
return_if_error(am_realloc(impl->function_indices, num_functions * sizeof(usize), (void**)&impl->function_indices));
impl->num_functions = num_functions;
return 0;
}
int amal_executor_instructions_end(amal_executor *self) {
- IMPL
-
+ amal_executor_impl *impl = (amal_executor_impl*)self;
CallDefer *call_defer = buffer_begin(&impl->call_defer);
CallDefer *call_defer_end = buffer_end(&impl->call_defer);
for(; call_defer != call_defer_end; ++call_defer) {
@@ -117,99 +118,106 @@ int amal_executor_instructions_end(amal_executor *self) {
}
int amal_exec_nop(amal_executor *self) {
- IMPL
- return asm_nop(&impl->asm);
+ IMPL_START
+ asm_nop(&impl->asm);
+ return 0;
}
int amal_exec_setz(amal_executor *self, i8 dst_reg) {
AsmPtr dst;
- IMPL
+ IMPL_START
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
- return asm_mov_mi(&impl->asm, &dst, 0);
+ asm_mov_mi(&impl->asm, &dst, 0);
+ return 0;
}
int amal_exec_mov(amal_executor *self, i8 dst_reg, i8 src_reg) {
AsmPtr ptr;
- IMPL
+ IMPL_START
asm_ptr_init_disp(&ptr, RBP, get_register_stack_offset(src_reg));
- return_if_error(asm_mov_rm(&impl->asm, RAX, &ptr));
+ asm_mov_rm(&impl->asm, RAX, &ptr);
asm_ptr_init_disp(&ptr, RBP, get_register_stack_offset(dst_reg));
- return asm_mov_mr(&impl->asm, &ptr, RAX);
+ asm_mov_mr(&impl->asm, &ptr, RAX);
+ return 0;
}
int amal_exec_movi(amal_executor *self, i8 dst_reg, i64 imm) {
- IMPL
+ IMPL_START
/* TODO: if @number is a float then use float instructions */
if(abs_i64(imm) <= INT32_MAX) {
AsmPtr dst;
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
- return_if_error(asm_mov_mi(&impl->asm, &dst, imm));
+ asm_mov_mi(&impl->asm, &dst, imm);
} else {
AsmPtr dst;
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
- return_if_error(asm_mov_ri(&impl->asm, RAX, imm));
- return_if_error(asm_mov_mr(&impl->asm, &dst, RAX));
+ asm_mov_ri(&impl->asm, RAX, imm);
+ asm_mov_mr(&impl->asm, &dst, RAX);
}
return 0;
}
int amal_exec_movd(amal_executor *self, i8 dst_reg, BufferView data) {
AsmPtr dst;
- IMPL
+ IMPL_START
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
- return_if_error(asm_mov_ri(&impl->asm, RAX, (uintptr_t)data.data));
- return asm_mov_mr(&impl->asm, &dst, RAX);
+ asm_mov_ri(&impl->asm, RAX, (uintptr_t)data.data);
+ asm_mov_mr(&impl->asm, &dst, RAX);
+ return 0;
}
int amal_exec_add(amal_executor *self, i8 dst_reg, i8 src_reg1, i8 src_reg2) {
AsmPtr dst;
AsmPtr reg1;
AsmPtr reg2;
- IMPL
+ IMPL_START
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
asm_ptr_init_disp(&reg1, RBP, get_register_stack_offset(src_reg1));
asm_ptr_init_disp(&reg2, RBP, get_register_stack_offset(src_reg2));
- return_if_error(asm_mov_rm(&impl->asm, RAX, &reg1));
- return_if_error(asm_mov_rm(&impl->asm, RCX, &reg2));
- return_if_error(asm_add_rr(&impl->asm, RAX, RCX));
- return asm_mov_mr(&impl->asm, &dst, RAX);
+ asm_mov_rm(&impl->asm, RAX, &reg1);
+ asm_mov_rm(&impl->asm, RCX, &reg2);
+ asm_add_rr(&impl->asm, RAX, RCX);
+ asm_mov_mr(&impl->asm, &dst, RAX);
+ return 0;
}
int amal_exec_sub(amal_executor *self, i8 dst_reg, i8 src_reg1, i8 src_reg2) {
AsmPtr dst;
AsmPtr reg1;
AsmPtr reg2;
- IMPL
+ IMPL_START
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
asm_ptr_init_disp(&reg1, RBP, get_register_stack_offset(src_reg1));
asm_ptr_init_disp(&reg2, RBP, get_register_stack_offset(src_reg2));
- return_if_error(asm_mov_rm(&impl->asm, RAX, &reg1));
- return_if_error(asm_mov_rm(&impl->asm, RCX, &reg2));
- return_if_error(asm_sub_rr(&impl->asm, RAX, RCX));
- return asm_mov_mr(&impl->asm, &dst, RAX);
+ asm_mov_rm(&impl->asm, RAX, &reg1);
+ asm_mov_rm(&impl->asm, RCX, &reg2);
+ asm_sub_rr(&impl->asm, RAX, RCX);
+ asm_mov_mr(&impl->asm, &dst, RAX);
+ return 0;
}
int amal_exec_imul(amal_executor *self, i8 dst_reg, i8 src_reg1, i8 src_reg2) {
AsmPtr dst;
AsmPtr reg1;
AsmPtr reg2;
- IMPL
+ IMPL_START
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
asm_ptr_init_disp(&reg1, RBP, get_register_stack_offset(src_reg1));
asm_ptr_init_disp(&reg2, RBP, get_register_stack_offset(src_reg2));
- return_if_error(asm_mov_rm(&impl->asm, RAX, &reg1));
- return_if_error(asm_mov_rm(&impl->asm, RCX, &reg2));
- return_if_error(asm_imul_rr(&impl->asm, RAX, RCX));
- return asm_mov_mr(&impl->asm, &dst, RAX);
+ asm_mov_rm(&impl->asm, RAX, &reg1);
+ asm_mov_rm(&impl->asm, RCX, &reg2);
+ asm_imul_rr(&impl->asm, RAX, RCX);
+ asm_mov_mr(&impl->asm, &dst, RAX);
+ return 0;
}
int amal_exec_mul(amal_executor *self, i8 dst_reg, i8 src_reg1, i8 src_reg2) {
@@ -240,18 +248,19 @@ int amal_exec_idiv(amal_executor *self, i8 dst_reg, i8 src_reg1, i8 src_reg2) {
AsmPtr dst;
AsmPtr reg1;
AsmPtr reg2;
- IMPL
+ IMPL_START
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
asm_ptr_init_disp(&reg1, RBP, get_register_stack_offset(src_reg1));
asm_ptr_init_disp(&reg2, RBP, get_register_stack_offset(src_reg2));
- return_if_error(asm_mov_rm(&impl->asm, RAX, &reg1));
- return_if_error(asm_mov_rm(&impl->asm, RCX, &reg2));
- return_if_error(asm_cqo(&impl->asm));
+ asm_mov_rm(&impl->asm, RAX, &reg1);
+ asm_mov_rm(&impl->asm, RCX, &reg2);
+ asm_cqo(&impl->asm);
/* TODO: Preserve RDX if needed, since it's also used as a parameter in system-v x86_64 abi */
- return_if_error(asm_idiv_rr(&impl->asm, RCX));
- return asm_mov_mr(&impl->asm, &dst, RAX);
+ asm_idiv_rr(&impl->asm, RCX);
+ asm_mov_mr(&impl->asm, &dst, RAX);
+ return 0;
}
int amal_exec_div(amal_executor *self, i8 dst_reg, i8 src_reg1, i8 src_reg2) {
@@ -266,11 +275,12 @@ int amal_exec_div(amal_executor *self, i8 dst_reg, i8 src_reg1, i8 src_reg2) {
int amal_exec_push(amal_executor *self, i8 reg) {
AsmPtr reg_ptr;
- IMPL
+ IMPL_START
asm_ptr_init_disp(&reg_ptr, RBP, get_register_stack_offset(reg));
- return_if_error(asm_mov_rm(&impl->asm, RAX, &reg_ptr));
- return asm_pushr(&impl->asm, RAX);
+ asm_mov_rm(&impl->asm, RAX, &reg_ptr);
+ asm_pushr(&impl->asm, RAX);
+ return 0;
}
int amal_exec_pushi(amal_executor *self, i64 imm) {
@@ -290,13 +300,13 @@ int amal_exec_pushd(amal_executor *self, BufferView data) {
}
int amal_exec_call(amal_executor *self, u16 func_index, u8 num_args, i8 dst_reg) {
- IMPL
+ IMPL_START
/* TODO: Preserve necessary registers before call? */
/* TODO: This assumes all arguments are isize */
/* Do the function call */
isize asm_offset = asm_get_size(&impl->asm);
if(func_index < impl->func_counter) {
- return_if_error(asm_call_rel32(&impl->asm, (isize)impl->function_indices[func_index] - asm_offset));
+ asm_call_rel32(&impl->asm, (isize)impl->function_indices[func_index] - asm_offset);
} else {
/*
The location of the function has not been defined yet. Use call instruction with dummy data and change
@@ -306,7 +316,7 @@ int amal_exec_call(amal_executor *self, u16 func_index, u8 num_args, i8 dst_reg)
call_defer.asm_index = asm_offset;
call_defer.func_index = func_index;
return_if_error(buffer_append(&impl->call_defer, &call_defer, sizeof(call_defer)));
- return_if_error(asm_call_rel32(&impl->asm, 0));
+ asm_call_rel32(&impl->asm, 0);
}
/* Handle function result and cleanup */
@@ -314,10 +324,10 @@ int amal_exec_call(amal_executor *self, u16 func_index, u8 num_args, i8 dst_reg)
AsmPtr dst;
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
/* TODO: Make this work when result is not stored in RAX (multiple return results) */
- return_if_error(asm_mov_mr(&impl->asm, &dst, RAX));
+ asm_mov_mr(&impl->asm, &dst, RAX);
}
if(num_args > 0)
- return asm_add_rm64_imm(&impl->asm, RSP, num_args * sizeof(isize));
+ asm_add_rm64_imm(&impl->asm, RSP, num_args * sizeof(isize));
return 0;
}
@@ -333,7 +343,7 @@ const Reg64 SYS_V_PARAM_REGS[] = { RDI, RSI, RDX, RCX };
/* TODO: Make this work when function returns something else than a POD */
int amal_exec_calle(amal_executor *self, void *func, u8 num_args, i8 dst_reg) {
AsmPtr dst;
- IMPL
+ IMPL_START
/* TODO: Support R and XMM registers so more than 5 arguments can be used for functions */
assert(num_args < 5);
@@ -346,19 +356,19 @@ int amal_exec_calle(amal_executor *self, void *func, u8 num_args, i8 dst_reg) {
AsmPtr src;
asm_ptr_init_disp(&src, RSP, 0);
for(i = num_args - 1; i >= 0; --i) {
- return_if_error(asm_mov_rm(&impl->asm, SYS_V_PARAM_REGS[i], &src));
+ asm_mov_rm(&impl->asm, SYS_V_PARAM_REGS[i], &src);
src.disp += 0x8;
}
}
/* TODO: Preserve necessary registers before call? */
/* TODO: This assumes all arguments are isize */
- return_if_error(asm_mov_ri(&impl->asm, RAX, (intptr_t)func));
- return_if_error(asm_callr(&impl->asm, RAX));
+ asm_mov_ri(&impl->asm, RAX, (intptr_t)func);
+ asm_callr(&impl->asm, RAX);
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
- return_if_error(asm_mov_mr(&impl->asm, &dst, RAX));
+ asm_mov_mr(&impl->asm, &dst, RAX);
if(num_args > 0)
- return asm_add_rm64_imm(&impl->asm, RSP, num_args * sizeof(isize));
+ asm_add_rm64_imm(&impl->asm, RSP, num_args * sizeof(isize));
return 0;
}
@@ -369,34 +379,36 @@ int amal_exec_callr(i8 dst_reg, BufferView data) {
*/
int amal_exec_cmp(amal_executor *self, i8 dst_reg, i8 src_reg1, i8 src_reg2) {
- IMPL
+ IMPL_START
AsmPtr dst, src1, src2;
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
asm_ptr_init_disp(&src1, RBP, get_register_stack_offset(src_reg1));
asm_ptr_init_disp(&src2, RBP, get_register_stack_offset(src_reg2));
- return_if_error(asm_mov_rm(&impl->asm, RCX, &dst));
- return_if_error(asm_xor_rm64(&impl->asm, RCX, RCX));
+ asm_mov_rm(&impl->asm, RCX, &dst);
+ asm_xor_rm64(&impl->asm, RCX, RCX);
- return_if_error(asm_mov_rm(&impl->asm, RAX, &src1));
- return_if_error(asm_cmp_rm(&impl->asm, RAX, &src2));
- return_if_error(asm_sete_r(&impl->asm, RCX));
- return asm_mov_mr(&impl->asm, &dst, RCX);
+ asm_mov_rm(&impl->asm, RAX, &src1);
+ asm_cmp_rm(&impl->asm, RAX, &src2);
+ asm_sete_r(&impl->asm, RCX);
+ asm_mov_mr(&impl->asm, &dst, RCX);
+ return 0;
}
int amal_exec_jz(amal_executor *self, i8 reg, u16 target_label) {
AsmPtr ptr;
u32 asm_offset;
- IMPL
+ IMPL_START
asm_ptr_init_disp(&ptr, RBP, get_register_stack_offset(reg));
- return_if_error(asm_mov_rm(&impl->asm, RAX, &ptr));
- return_if_error(asm_cmp_rm64_imm(&impl->asm, RAX, 0));
+ asm_mov_rm(&impl->asm, RAX, &ptr);
+ asm_cmp_rm64_imm(&impl->asm, RAX, 0);
asm_offset = asm_get_size(&impl->asm);
if(target_label < impl->label_counter) {
- return asm_jz(&impl->asm, (i32)impl->label_asm_index[target_label] - (i32)asm_offset);
+ asm_jz(&impl->asm, (i32)impl->label_asm_index[target_label] - (i32)asm_offset);
+ return 0;
} else {
JumpDefer jump_defer;
jump_defer.asm_index = asm_offset;
@@ -406,16 +418,17 @@ int amal_exec_jz(amal_executor *self, i8 reg, u16 target_label) {
Insert dummy target, but it has to be above INT16_MAX, so the target can be replaced
no matter how large the jump will be
*/
- return_if_error(asm_jz(&impl->asm, INT32_MAX));
+ asm_jz(&impl->asm, INT32_MAX);
return buffer_append(&impl->jump_defer, &jump_defer, sizeof(jump_defer));
}
}
int amal_exec_jmp(amal_executor *self, u16 target_label) {
- IMPL
+ IMPL_START
u32 asm_offset = asm_get_size(&impl->asm);
if(target_label < impl->label_counter) {
- return asm_jmp(&impl->asm, (i32)impl->label_asm_index[target_label] - (i32)asm_offset);
+ asm_jmp(&impl->asm, (i32)impl->label_asm_index[target_label] - (i32)asm_offset);
+ return 0;
} else {
JumpDefer jump_defer;
jump_defer.asm_index = asm_offset;
@@ -425,18 +438,18 @@ int amal_exec_jmp(amal_executor *self, u16 target_label) {
Insert dummy target, but it has to be above INT16_MAX, so the target can be replaced
no matter how large the jump will be
*/
- return_if_error(asm_jmp(&impl->asm, INT32_MAX));
+ asm_jmp(&impl->asm, INT32_MAX);
return buffer_append(&impl->jump_defer, &jump_defer, sizeof(jump_defer));
}
}
int amal_exec_ret(amal_executor *self, i8 reg) {
AsmPtr ret_reg;
- IMPL
+ IMPL_START
asm_ptr_init_disp(&ret_reg, RBP, get_register_stack_offset(reg));
/* Result is returned in RAX register. TODO: Make this work when returning more than one result */
- return_if_error(asm_mov_rm(&impl->asm, RAX, &ret_reg));
+ asm_mov_rm(&impl->asm, RAX, &ret_reg);
return amal_exec_func_end(self);
}
@@ -452,16 +465,17 @@ int amal_exec_func_start(amal_executor *self, u16 num_regs) {
64-bit Windows: RBX, RSI, RDI, RBP, R12-R15, XMM6-XMM15
64-bit Linux,BSD,Mac: RBX, RBP, R12-R15
*/
- IMPL
+ IMPL_START
impl->function_indices[impl->func_counter++] = asm_get_size(&impl->asm);
- return_if_error(asm_pushr(&impl->asm, RBX));
- return_if_error(asm_pushr(&impl->asm, RBP));
- return_if_error(asm_mov_rr(&impl->asm, RBP, RSP));
- return asm_sub_rm64_imm(&impl->asm, RSP, num_regs * sizeof(isize));
+ asm_pushr(&impl->asm, RBX);
+ asm_pushr(&impl->asm, RBP);
+ asm_mov_rr(&impl->asm, RBP, RSP);
+ asm_sub_rm64_imm(&impl->asm, RSP, num_regs * sizeof(isize));
+ return 0;
}
int amal_exec_func_end(amal_executor *self) {
- IMPL
+ IMPL_START
JumpDefer *jump_defer = buffer_begin(&impl->jump_defer);
JumpDefer *jump_defer_end = buffer_end(&impl->jump_defer);
@@ -480,14 +494,15 @@ int amal_exec_func_end(amal_executor *self) {
buffer_clear(&impl->jump_defer);
impl->label_counter = 0;
- return_if_error(asm_mov_rr(&impl->asm, RSP, RBP));
- return_if_error(asm_popr(&impl->asm, RBP));
- return_if_error(asm_popr(&impl->asm, RBX));
- return asm_ret(&impl->asm, 0);
+ asm_mov_rr(&impl->asm, RSP, RBP);
+ asm_popr(&impl->asm, RBP);
+ asm_popr(&impl->asm, RBX);
+ asm_ret(&impl->asm, 0);
+ return 0;
}
int amal_exec_label(amal_executor *self) {
- IMPL
+ IMPL_START
assert(impl->label_counter < MAX_LABELS);
impl->label_asm_index[impl->label_counter++] = asm_get_size(&impl->asm);
return 0;