aboutsummaryrefslogtreecommitdiff
path: root/executor/x86_64/asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'executor/x86_64/asm.c')
-rw-r--r--executor/x86_64/asm.c147
1 files changed, 36 insertions, 111 deletions
diff --git a/executor/x86_64/asm.c b/executor/x86_64/asm.c
index a6bf274..c2b00ef 100644
--- a/executor/x86_64/asm.c
+++ b/executor/x86_64/asm.c
@@ -224,7 +224,7 @@ int asm_execute(Asm *self, u32 offset) {
}
/* TODO: See how this can be optimized */
-static CHECK_RESULT int asm_ensure_capacity(Asm *self, usize size) {
+int asm_ensure_capacity(Asm *self, usize size) {
usize current_offset;
current_offset = (u8*)self->code_it - (u8*)self->code;
if(current_offset + size > self->allocated_size) {
@@ -249,12 +249,10 @@ static isize asm_get_capacity_left(Asm *self) {
}
#endif
-int asm_nop(Asm *self) {
+void asm_nop(Asm *self) {
ins_start(self);
- return_if_error(asm_ensure_capacity(self, 1));
*self->code_it++ = 0x90;
ins_end(self, "nop");
- return 0;
}
static i32 abs_i32(i32 value) {
@@ -331,152 +329,121 @@ static void asm_rr(Asm *self, Reg64 dst, Reg64 src) {
}
/* TODO: Implement 1 and 2 byte immediate? */
-int asm_mov_mi(Asm *self, AsmPtr *dst, i32 immediate) {
+void asm_mov_mi(Asm *self, AsmPtr *dst, i32 immediate) {
ins_start(self);
- /* 12 bytes is the maximum size of the instruction. We don't how how large it will be so we prepare for the largest size */
- return_if_error(asm_ensure_capacity(self, 12));
*self->code_it++ = REX_W;
*self->code_it++ = 0xC7;
asm_rm(self, dst, 0);
am_memcpy(self->code_it, &immediate, sizeof(immediate));
self->code_it += sizeof(immediate);
ins_end(self, "mov %s, 0x%x", asm_ptr_to_string(dst), immediate);
- return 0;
}
-int asm_mov_mr(Asm *self, AsmPtr *dst, Reg64 src) {
+void asm_mov_mr(Asm *self, AsmPtr *dst, Reg64 src) {
ins_start(self);
- /* 8 bytes is the maximum size of the instruction. We don't how how large it will be so we prepare for the largest size */
- return_if_error(asm_ensure_capacity(self, 8));
*self->code_it++ = REX_W;
*self->code_it++ = 0x89;
asm_rm(self, dst, src);
ins_end(self, "mov %s, %s", asm_ptr_to_string(dst), reg64_to_str(src));
- return 0;
}
-int asm_mov_rm(Asm *self, Reg64 dst, AsmPtr *src) {
+void asm_mov_rm(Asm *self, Reg64 dst, AsmPtr *src) {
ins_start(self);
- /* 8 bytes is the maximum size of the instruction. We don't how how large it will be so we prepare for the largest size */
- return_if_error(asm_ensure_capacity(self, 8));
*self->code_it++ = REX_W;
*self->code_it++ = 0x8B;
asm_rm(self, src, dst);
ins_end(self, "mov %s, %s", reg64_to_str(dst), asm_ptr_to_string(src));
- return 0;
}
/* Note: This shows as instruction movabs in intel assembly format */
-int asm_mov_ri(Asm *self, Reg64 dst, i64 immediate) {
+void asm_mov_ri(Asm *self, Reg64 dst, i64 immediate) {
ins_start(self);
- return_if_error(asm_ensure_capacity(self, 10));
*self->code_it++ = REX_W;
*self->code_it++ = 0xB8 + dst;
am_memcpy(self->code_it, &immediate, sizeof(immediate));
self->code_it += sizeof(immediate);
ins_end(self, "mov %s, 0x%x", reg64_to_str(dst), immediate);
- return 0;
}
-int asm_mov_rr(Asm *self, Reg64 dst, Reg64 src) {
+void asm_mov_rr(Asm *self, Reg64 dst, Reg64 src) {
ins_start(self);
- return_if_error(asm_ensure_capacity(self, 3));
*self->code_it++ = REX_W;
*self->code_it++ = 0x89;
asm_rr(self, dst, src);
ins_end(self, "mov %s, %s", reg64_to_str(dst), reg64_to_str(src));
- return 0;
}
-int asm_add_rr(Asm *self, Reg64 dst, Reg64 src) {
+void asm_add_rr(Asm *self, Reg64 dst, Reg64 src) {
ins_start(self);
- return_if_error(asm_ensure_capacity(self, 3));
*self->code_it++ = REX_W;
*self->code_it++ = 0x01;
asm_rr(self, dst, src);
ins_end(self, "add %s, %s", reg64_to_str(dst), reg64_to_str(src));
- return 0;
}
-int asm_sub_rr(Asm *self, Reg64 dst, Reg64 src) {
+void asm_sub_rr(Asm *self, Reg64 dst, Reg64 src) {
ins_start(self);
- return_if_error(asm_ensure_capacity(self, 3));
*self->code_it++ = REX_W;
*self->code_it++ = 0x29;
asm_rr(self, dst, src);
ins_end(self, "sub %s, %s", reg64_to_str(dst), reg64_to_str(src));
- return 0;
}
-int asm_imul_rr(Asm *self, Reg64 dst, Reg64 src) {
+void asm_imul_rr(Asm *self, Reg64 dst, Reg64 src) {
ins_start(self);
- return_if_error(asm_ensure_capacity(self, 4));
*self->code_it++ = REX_W;
*self->code_it++ = 0x0F;
*self->code_it++ = 0xAF;
asm_rr(self, dst, src);
ins_end(self, "imul %s, %s", reg64_to_str(dst), reg64_to_str(src));
- return 0;
}
-int asm_cqo(Asm *self) {
+void asm_cqo(Asm *self) {
ins_start(self);
- return_if_error(asm_ensure_capacity(self, 2));
*self->code_it++ = REX_W;
*self->code_it++ = 0x99;
ins_end(self, "cqo");
- return 0;
}
-int asm_idiv_rr(Asm *self, Reg64 src) {
+void asm_idiv_rr(Asm *self, Reg64 src) {
ins_start(self);
- return_if_error(asm_ensure_capacity(self, 4));
*self->code_it++ = REX_W;
*self->code_it++ = 0xF7;
asm_rr(self, src, 0x7);
ins_end(self, "idiv %s", reg64_to_str(src));
- return 0;
}
-int asm_pushr(Asm *self, Reg64 reg) {
+void asm_pushr(Asm *self, Reg64 reg) {
ins_start(self);
- return_if_error(asm_ensure_capacity(self, 1));
*self->code_it++ = 0x50 + reg;
ins_end(self, "push %s", reg64_to_str(reg));
- return 0;
}
-int asm_popr(Asm *self, Reg64 reg) {
+void asm_popr(Asm *self, Reg64 reg) {
ins_start(self);
- return_if_error(asm_ensure_capacity(self, 1));
*self->code_it++ = 0x58 + reg;
ins_end(self, "pop %s", reg64_to_str(reg));
- return 0;
}
-int asm_callr(Asm *self, Reg64 reg) {
+void asm_callr(Asm *self, Reg64 reg) {
ins_start(self);
- return_if_error(asm_ensure_capacity(self, 3));
*self->code_it++ = REX_W;
*self->code_it++ = 0xFF;
asm_rr(self, reg, 0x2);
ins_end(self, "call %s", reg64_to_str(reg));
- return 0;
}
/*
Note: This is sometimes called with @relative 0 (will print call -5), in which case it's most likely a dummy call until the relative position
is later changed with @asm_override_call_rel32. TODO: Update the ins_end debug print to take that into account somehow
*/
-int asm_call_rel32(Asm *self, i32 relative) {
+void asm_call_rel32(Asm *self, i32 relative) {
ins_start(self);
relative -= 5; /* In x86, the relative position starts from the next instruction */
- return_if_error(asm_ensure_capacity(self, 5));
*self->code_it++ = 0xE8;
am_memcpy(self->code_it, &relative, sizeof(relative));
self->code_it += sizeof(relative);
ins_end(self, "call 0x%x", relative);
- return 0;
}
void asm_override_call_rel32(Asm *self, u32 asm_index, i32 new_relative) {
@@ -485,39 +452,30 @@ void asm_override_call_rel32(Asm *self, u32 asm_index, i32 new_relative) {
am_memcpy((u8*)self->code + asm_index + 1, &new_relative, sizeof(new_relative));
}
-int asm_cmp_rm(Asm *self, Reg64 reg1, AsmPtr *reg2) {
+void asm_cmp_rm(Asm *self, Reg64 reg1, AsmPtr *reg2) {
ins_start(self);
- /* 8 bytes is the maximum size of the instruction. We don't how how large it will be so we prepare for the largest size */
- return_if_error(asm_ensure_capacity(self, 8));
*self->code_it++ = REX_W;
*self->code_it++ = 0x3B;
asm_rm(self, reg2, reg1);
ins_end(self, "cmp %s, %s", reg64_to_str(reg1), asm_ptr_to_string(reg2));
- return 0;
}
-int asm_sete_m(Asm *self, AsmPtr *dst) {
+void asm_sete_m(Asm *self, AsmPtr *dst) {
assert(dst->base != RSP && dst->base != RBP && dst->base != RSI && dst->base != RDI);
ins_start(self);
- /* 8 bytes is the maximum size of the instruction. We don't how how large it will be so we prepare for the largest size */
- return_if_error(asm_ensure_capacity(self, 8));
*self->code_it++ = 0x0F;
*self->code_it++ = 0x94;
asm_rm(self, dst, 0x0); /* the @src bits are not used */
ins_end(self, "sete %s", asm_ptr_to_string(dst));
- return 0;
}
-int asm_sete_r(Asm *self, Reg64 dst) {
+void asm_sete_r(Asm *self, Reg64 dst) {
assert(dst != RSP && dst != RBP && dst != RSI && dst != RDI);
ins_start(self);
- /* 8 bytes is the maximum size of the instruction. We don't how how large it will be so we prepare for the largest size */
- return_if_error(asm_ensure_capacity(self, 8));
*self->code_it++ = 0x0F;
*self->code_it++ = 0x94;
asm_rr(self, dst, 0x0); /* the @src bits are not used */
ins_end(self, "sete %s", reg64_to_str(dst));
- return 0;
}
/*
@@ -525,7 +483,7 @@ int asm_sete_r(Asm *self, Reg64 dst) {
jump until the relative position is later changed with @asm_override_jcc_rel32.
TODO: Update the ins_end debug print to take that into account somehow
*/
-int asm_jz(Asm *self, i32 relative) {
+void asm_jz(Asm *self, i32 relative) {
/*
Note: We dont use the 16-bit relative variant, as it will clear the upper two bytes of the EIP registers, resulting
in a maximum instruction pointer size of 16 bits
@@ -533,19 +491,16 @@ int asm_jz(Asm *self, i32 relative) {
ins_start(self);
if(abs(relative - 2) <= INT8_MAX) {
relative -= 2;
- return_if_error(asm_ensure_capacity(self, 2));
*self->code_it++ = 0x74;
*self->code_it++ = (i8)relative;
} else {
relative -= 6;
- return_if_error(asm_ensure_capacity(self, 6));
*self->code_it++ = 0x0F;
*self->code_it++ = 0x84;
am_memcpy(self->code_it, &relative, sizeof(relative));
self->code_it += sizeof(relative);
}
ins_end(self, "jz 0x%x", relative);
- return 0;
}
void asm_override_jcc_rel32(Asm *self, u32 asm_index, i32 new_relative) {
@@ -561,7 +516,7 @@ void asm_override_jcc_rel32(Asm *self, u32 asm_index, i32 new_relative) {
jump until the relative position is later changed with @asm_override_jmp_rel32.
TODO: Update the ins_end debug print to take that into account somehow
*/
-int asm_jmp(Asm *self, i32 relative) {
+void asm_jmp(Asm *self, i32 relative) {
/*
Note: We dont use the 16-bit relative variant, as it will clear the upper two bytes of the EIP registers, resulting
in a maximum instruction pointer size of 16 bits
@@ -569,18 +524,15 @@ int asm_jmp(Asm *self, i32 relative) {
ins_start(self);
if(abs(relative - 2) <= INT8_MAX) {
relative -= 2;
- return_if_error(asm_ensure_capacity(self, 2));
*self->code_it++ = 0xEB;
*self->code_it++ = (i8)relative;
} else {
relative -= 5;
- return_if_error(asm_ensure_capacity(self, 5));
*self->code_it++ = 0xE9;
am_memcpy(self->code_it, &relative, sizeof(relative));
self->code_it += sizeof(relative);
}
ins_end(self, "jmp 0x%x", relative);
- return 0;
}
void asm_override_jmp_rel32(Asm *self, u32 asm_index, i32 new_relative) {
@@ -594,29 +546,22 @@ void asm_override_jmp_rel32(Asm *self, u32 asm_index, i32 new_relative) {
/* /r */
#define DEFINE_INS_RM(mnemonic, opcode) \
-int asm_##mnemonic##_rmb(Asm *self, Reg32 dst, Reg32 src) { \
+void asm_##mnemonic##_rmb(Asm *self, Reg32 dst, Reg32 src) { \
*self->code_it++ = opcode; \
*self->code_it++ = 0xC0 + 8*dst + src; \
- return 0; \
} \
\
-int asm_##mnemonic##_rm32(Asm *self, Reg32 dst, Reg32 src) { \
- int result; \
+void asm_##mnemonic##_rm32(Asm *self, Reg32 dst, Reg32 src) { \
ins_start(self); \
- return_if_error(asm_ensure_capacity(self, 2)); \
- result = asm_##mnemonic##_rmb(self, (Reg32)dst, (Reg32)src); \
+ asm_##mnemonic##_rmb(self, (Reg32)dst, (Reg32)src); \
ins_end(self, #mnemonic" %s, %s", reg32_to_str(dst), reg32_to_str(src)); \
- return result; \
} \
\
-int asm_##mnemonic##_rm64(Asm *self, Reg64 dst, Reg64 src) { \
- int result; \
+void asm_##mnemonic##_rm64(Asm *self, Reg64 dst, Reg64 src) { \
ins_start(self); \
- return_if_error(asm_ensure_capacity(self, 3)); \
*self->code_it++ = REX_W; \
- result = asm_##mnemonic##_rmb(self, (Reg32)dst, (Reg32)src); \
+ asm_##mnemonic##_rmb(self, (Reg32)dst, (Reg32)src); \
ins_end(self, #mnemonic" %s, %s", reg64_to_str(dst), reg64_to_str(src)); \
- return result; \
}
DEFINE_INS_RM(mov, 0x8B)
@@ -634,38 +579,30 @@ DEFINE_INS_RM(cmp, 0x3B)
one register the other register can be encoded for that.
*/
#define DEFINE_INS_EXT_IMM(mnemonic, extension) \
-int asm_##mnemonic##_rmb_imm(Asm *self, Reg32 reg, i32 immediate) { \
+void asm_##mnemonic##_rmb_imm(Asm *self, Reg32 reg, i32 immediate) { \
if(abs_i32(immediate) <= INT8_MAX) { \
- return_if_error(asm_ensure_capacity(self, 3)); \
*self->code_it++ = 0x83; \
*self->code_it++ = 0xC0 + 8*extension + reg; \
*self->code_it++ = (u8)immediate; \
} else { \
- return_if_error(asm_ensure_capacity(self, 6)); \
*self->code_it++ = 0x81; \
*self->code_it++ = 0xC0 + 8*extension + reg; \
am_memcpy(self->code_it, &immediate, sizeof(immediate)); \
self->code_it += sizeof(immediate); \
} \
- return 0; \
} \
\
-int asm_##mnemonic##_rm32_imm(Asm *self, Reg32 reg, i32 immediate) { \
- int result; \
+void asm_##mnemonic##_rm32_imm(Asm *self, Reg32 reg, i32 immediate) { \
ins_start(self); \
- result = asm_##mnemonic##_rmb_imm(self, (Reg32)reg, immediate); \
+ asm_##mnemonic##_rmb_imm(self, (Reg32)reg, immediate); \
ins_end(self, #mnemonic" %s, 0x%x", reg32_to_str(reg), immediate); \
- return result; \
}\
\
-int asm_##mnemonic##_rm64_imm(Asm *self, Reg64 reg, i32 immediate) { \
- int result; \
+void asm_##mnemonic##_rm64_imm(Asm *self, Reg64 reg, i32 immediate) { \
ins_start(self); \
- return_if_error(asm_ensure_capacity(self, 1)); \
*self->code_it++ = REX_W; \
- result = asm_##mnemonic##_rmb_imm(self, (Reg32)reg, immediate); \
+ asm_##mnemonic##_rmb_imm(self, (Reg32)reg, immediate); \
ins_end(self, #mnemonic" %s, 0x%x", reg64_to_str(reg), immediate); \
- return result; \
}
DEFINE_INS_EXT_IMM(add, 0)
@@ -684,36 +621,27 @@ DEFINE_INS_EXT_IMM(cmp, 7)
one register the other register can be encoded for that.
*/
#define DEFINE_INS_SHIFT_IMM8(mnemonic, extension) \
-int asm_##mnemonic##_rmb_imm(Asm *self, Reg32 reg, i8 immediate) { \
+void asm_##mnemonic##_rmb_imm(Asm *self, Reg32 reg, i8 immediate) { \
if(immediate == 1) { \
- return_if_error(asm_ensure_capacity(self, 2)); \
*self->code_it++ = 0xC1; \
*self->code_it++ = 0xC0 + 8*reg + extension; \
} else { \
- return_if_error(asm_ensure_capacity(self, 3)); \
*self->code_it++ = 0xD1; \
*self->code_it++ = 0xC0 + 8*reg + extension; \
*self->code_it++ = immediate; \
} \
- return 0; \
} \
\
-int asm_##mnemonic##_rm32_imm(Asm *self, Reg32 reg, i8 immediate) { \
- int result; \
+void asm_##mnemonic##_rm32_imm(Asm *self, Reg32 reg, i8 immediate) { \
ins_start(self); \
- result = asm_##mnemonic##_rmb_imm(self, (Reg32)reg, immediate); \
ins_end(self, #mnemonic" %s, 0x%x", reg32_to_str(reg), immediate); \
- return result; \
} \
\
-int asm_##mnemonic##_rm64_imm(Asm *self, Reg64 reg, i8 immediate) { \
- int result; \
+void asm_##mnemonic##_rm64_imm(Asm *self, Reg64 reg, i8 immediate) { \
ins_start(self); \
- return_if_error(asm_ensure_capacity(self, 1)); \
*self->code_it++ = REX_W; \
- result = asm_##mnemonic##_rmb_imm(self, (Reg32)reg, immediate); \
+ asm_##mnemonic##_rmb_imm(self, (Reg32)reg, immediate); \
ins_end(self, #mnemonic" %s, 0x%x", reg64_to_str(reg), immediate); \
- return result; \
}
DEFINE_INS_SHIFT_IMM8(rol, 0)
@@ -725,17 +653,14 @@ DEFINE_INS_SHIFT_IMM8(shr, 5)
/*DEFINE_INS_SHIFT_IMM8(shl, 6)*/
DEFINE_INS_SHIFT_IMM8(sar, 7)
-int asm_ret(Asm *self, u16 bytes) {
+void asm_ret(Asm *self, u16 bytes) {
ins_start(self);
if(bytes == 0) {
- return_if_error(asm_ensure_capacity(self, 1));
*self->code_it++ = 0xC3;
ins_end(self, "ret");
} else {
- return_if_error(asm_ensure_capacity(self, 3));
*self->code_it++ = 0xC2;
am_memcpy(self->code_it, &bytes, sizeof(bytes));
ins_end(self, "ret 0x%x", bytes);
}
- return 0;
}