From 4d8283e14b0365038b01df4fab5dee75035007ed Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 25 Aug 2019 11:18:13 +0200 Subject: Remove number of branches in executor --- executor/x86_64/asm.c | 147 +++++++++++++------------------------------------- 1 file changed, 36 insertions(+), 111 deletions(-) (limited to 'executor/x86_64/asm.c') 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; } -- cgit v1.2.3