diff --git a/src/codegen.c b/src/codegen.c index 653834c..5e3bc13 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -7,6 +7,7 @@ #include "386_common.h" #include "codegen_accumulate.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_ir.h" #include "codegen_ops.h" diff --git a/src/codegen.h b/src/codegen.h index e0e8760..e76391b 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -59,14 +59,18 @@ typedef struct codeblock_t present in two pages.*/ uint16_t prev, next; uint16_t prev_2, next_2; + + /*First mem_block_t used by this block. Any subsequent mem_block_ts + will be in the list starting at head_mem_block->next.*/ + struct mem_block_t *head_mem_block; } codeblock_t; -uint8_t *codeblock_data; - extern codeblock_t *codeblock; extern uint16_t *codeblock_hash; +extern uint8_t *block_write_data; + /*Code block uses FPU*/ #define CODEBLOCK_HAS_FPU 1 /*Code block is always entered with the same FPU top-of-stack*/ @@ -300,6 +304,10 @@ x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fe void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); +/*Delete a random code block to free memory. This is obviously quite expensive, and + will only be called when the allocator is out of memory*/ +void codegen_delete_random_block(); + extern int cpu_block_end; extern uint32_t codegen_endpc; diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 500230d..db786b2 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -11,10 +11,13 @@ #include "codegen.h" #include "codegen_accumulate.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_ir.h" #include "codegen_reg.h" +uint8_t *block_write_data = NULL; + int codegen_flat_ds, codegen_flat_ss; int mmx_ebx_ecx_loaded; int codegen_flags_changed = 0; @@ -52,6 +55,7 @@ uint32_t instr_counts[256*256]; void codegen_init() { + codegen_allocator_init(); codegen_backend_init(); #ifdef DEBUG_EXTRA memset(instr_counts, 0, sizeof(instr_counts)); @@ -96,10 +100,7 @@ void codegen_reset() mem_reset_page_blocks(); for (c = 0; c < BLOCK_SIZE; c++) - { codeblock[c].pc = BLOCK_PC_INVALID; - codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; - } } void dump_block() @@ -220,6 +221,28 @@ static void delete_block(codeblock_t *block) codeblock_tree_delete(block); remove_from_block_list(block, old_pc); + if (block->head_mem_block) + codegen_allocator_free(block->head_mem_block); + block->head_mem_block = NULL; +} + +void codegen_delete_random_block() +{ + while (1) + { + int block_nr = rand() & BLOCK_MASK; + + if (block_nr && block_nr != block_current) + { + codeblock_t *block = &codeblock[block_nr]; + + if (block->pc != BLOCK_PC_INVALID && block->head_mem_block) + { + delete_block(block); + return; + } + } + } } void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) @@ -318,6 +341,9 @@ void codegen_block_start_recompile(codeblock_t *block) if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED)) fatal("Recompile to used block!\n"); + block->head_mem_block = codegen_allocator_allocate(NULL); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block->status = cpu_cur_status; cpu_block_end = 0; diff --git a/src/codegen_backend.h b/src/codegen_backend.h index df6fcea..7a5c5c0 100644 --- a/src/codegen_backend.h +++ b/src/codegen_backend.h @@ -16,45 +16,6 @@ void codegen_backend_init(); void codegen_backend_prologue(codeblock_t *block); void codegen_backend_epilogue(codeblock_t *block); -static inline void addbyte(uint8_t val) -{ - codeblock[block_current].data[block_pos++] = val; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - -static inline void addword(uint16_t val) -{ - *(uint16_t *)(void *)&codeblock[block_current].data[block_pos] = val; - block_pos += 2; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - -static inline void addlong(uint32_t val) -{ - *(uint32_t *)&codeblock[block_current].data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - -static inline void addquad(uint64_t val) -{ - *(uint64_t *)&codeblock[block_current].data[block_pos] = val; - block_pos += 8; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - struct ir_data_t; struct uop_t; diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index d2b0fe4..bb861ae 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -3,6 +3,7 @@ #include #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_arm_defs.h" #include "codegen_backend_arm_ops.h" @@ -126,8 +127,6 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); - - block_pos = (block_pos + 63) & ~63; } static void build_store_routine(codeblock_t *block, int size, int is_float) @@ -199,8 +198,6 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) fatal("build_store_routine - unknown size %i\n", size); host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); - - block_pos = (block_pos + 63) & ~63; } static void build_loadstore_routines(codeblock_t *block) @@ -246,13 +243,13 @@ static void build_fp_round_routine(codeblock_t *block) host_arm_MOV_REG(block, REG_LR, REG_TEMP2); host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state); host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP); - addlong(0); + host_arm_NOP(block); jump_table = (uint32_t *)&block->data[block_pos]; - addlong(0); - addlong(0); - addlong(0); - addlong(0); + host_arm_NOP(block); + host_arm_NOP(block); + host_arm_NOP(block); + host_arm_NOP(block); jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block->data[block_pos]; //tie even host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); @@ -279,12 +276,11 @@ static void build_fp_round_routine(codeblock_t *block) jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //zero host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP); host_arm_MOV_REG(block, REG_PC, REG_LR); - - block_pos = (block_pos + 63) & ~63; } void codegen_backend_init() { + codeblock_t *block; int c; #if defined(__linux__) || defined(__APPLE__) void *start; @@ -293,13 +289,6 @@ void codegen_backend_init() long pagemask = ~(pagesize - 1); #endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#else - codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE); -#endif - if (!codeblock_data) - fatal("codeblock_data failed to alloc - %i\n", (BLOCK_SIZE+1) * BLOCK_DATA_SIZE); codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); @@ -307,29 +296,24 @@ void codegen_backend_init() memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); for (c = 0; c < BLOCK_SIZE; c++) - { codeblock[c].pc = BLOCK_PC_INVALID; - codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; - } -#if defined(__linux__) || defined(__APPLE__) - start = (void *)((long)codeblock_data & pagemask); - len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask; - if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) - { - perror("mprotect"); - exit(-1); - } -#endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); block_current = 0; block_pos = 0; + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; build_loadstore_routines(&codeblock[block_current]); +printf("block_pos=%i\n", block_pos); codegen_fp_round = &codeblock[block_current].data[block_pos]; build_fp_round_routine(&codeblock[block_current]); + block_write_data = NULL; + asm("vmrs %0, fpscr\n" : "=r" (cpu_state.old_fp_control) ); @@ -380,10 +364,7 @@ void codegen_backend_epilogue(codeblock_t *block) host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); - if (block_pos > ARM_LITERAL_POOL_OFFSET) - fatal("Over limit!\n"); - - __clear_cache(&block->data[0], &block->data[block_pos]); + codegen_allocator_clean_blocks(block->head_mem_block); } #endif diff --git a/src/codegen_backend_arm.h b/src/codegen_backend_arm.h index 67d18e6..f8b330b 100644 --- a/src/codegen_backend_arm.h +++ b/src/codegen_backend_arm.h @@ -9,17 +9,10 @@ #define HASH(l) ((l) & 0x1ffff) -/*Hack until better memory management written*/ -/*#define BLOCK_EXIT_OFFSET 0x7f0*/ - #define BLOCK_GPF_OFFSET 0 #define BLOCK_EXIT_OFFSET 32 -#define ARM_LITERAL_POOL_OFFSET 0x10000 - -/*#define BLOCK_MAX 1720*/ -#define BLOCK_MAX 65208 - +#define BLOCK_MAX 0x3c0 void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask); @@ -30,6 +23,3 @@ void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm void host_arm_call(codeblock_t *block, void *dst_addr); void host_arm_nop(codeblock_t *block); - -void codegen_reset_literal_pool(codeblock_t *block); -int add_literal(codeblock_t *block, uint32_t data); diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 534df5c..ba08ca8 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -3,6 +3,7 @@ #include #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_arm64_defs.h" #include "codegen_backend_arm64_ops.h" @@ -83,9 +84,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) LDP X29, X30, [SP, #-16] RET */ + codegen_alloc(block, 80); host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12); - offset = add_literal_q(block, (uintptr_t)readlookup2); - host_arm64_LDR_LITERAL_X(block, REG_X2, offset); + host_arm64_MOVX_IMM(block, REG_X2, (uint64_t)readlookup2); host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1); if (size != 1) { @@ -107,9 +108,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm64_MOVZ_IMM(block, REG_W1, 0); host_arm64_RET(block, REG_X30); - host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]); + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); if (size != 1) - host_arm64_branch_set_offset(misaligned_offset, &block->data[block_pos]); + host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); if (size == 1) host_arm64_call(block, (uintptr_t)readmemb386l); @@ -128,8 +129,6 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0); host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); host_arm64_RET(block, REG_X30); - - block_pos = (block_pos + 63) & ~63; } static void build_store_routine(codeblock_t *block, int size, int is_float) @@ -154,9 +153,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) LDP X29, X30, [SP, #-16] RET */ + codegen_alloc(block, 80); host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12); - offset = add_literal_q(block, (uintptr_t)writelookup2); - host_arm64_LDR_LITERAL_X(block, REG_X3, offset); + host_arm64_MOVX_IMM(block, REG_X3, (uint64_t)writelookup2); host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2); if (size != 1) { @@ -178,9 +177,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_arm64_MOVZ_IMM(block, REG_X1, 0); host_arm64_RET(block, REG_X30); - host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]); + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); if (size != 1) - host_arm64_branch_set_offset(misaligned_offset, &block->data[block_pos]); + host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); if (size == 4 && is_float) host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP); @@ -199,36 +198,34 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); host_arm64_RET(block, REG_X30); - - block_pos = (block_pos + 63) & ~63; } static void build_loadstore_routines(codeblock_t *block) { - codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + codegen_mem_load_byte = &block_write_data[block_pos]; build_load_routine(block, 1, 0); - codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + codegen_mem_load_word = &block_write_data[block_pos]; build_load_routine(block, 2, 0); - codegen_mem_load_long = &codeblock[block_current].data[block_pos]; + codegen_mem_load_long = &block_write_data[block_pos]; build_load_routine(block, 4, 0); - codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + codegen_mem_load_quad = &block_write_data[block_pos]; build_load_routine(block, 8, 0); - codegen_mem_load_single = &codeblock[block_current].data[block_pos]; + codegen_mem_load_single = &block_write_data[block_pos]; build_load_routine(block, 4, 1); - codegen_mem_load_double = &codeblock[block_current].data[block_pos]; + codegen_mem_load_double = &block_write_data[block_pos]; build_load_routine(block, 8, 1); - codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + codegen_mem_store_byte = &block_write_data[block_pos]; build_store_routine(block, 1, 0); - codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + codegen_mem_store_word = &block_write_data[block_pos]; build_store_routine(block, 2, 0); - codegen_mem_store_long = &codeblock[block_current].data[block_pos]; + codegen_mem_store_long = &block_write_data[block_pos]; build_store_routine(block, 4, 0); - codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; + codegen_mem_store_quad = &block_write_data[block_pos]; build_store_routine(block, 8, 0); - codegen_mem_store_single = &codeblock[block_current].data[block_pos]; + codegen_mem_store_single = &block_write_data[block_pos]; build_store_routine(block, 4, 1); - codegen_mem_store_double = &codeblock[block_current].data[block_pos]; + codegen_mem_store_double = &block_write_data[block_pos]; build_store_routine(block, 8, 1); } @@ -236,50 +233,47 @@ static void build_fp_round_routine(codeblock_t *block, int is_quad) { uint64_t *jump_table; + codegen_alloc(block, 80); host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state); host_arm64_ADR(block, REG_TEMP2, 12); host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP); host_arm64_BR(block, REG_TEMP2); - jump_table = &block->data[block_pos]; - addquad(0); - addquad(0); - addquad(0); - addquad(0); + jump_table = &block_write_data[block_pos]; + block_pos += 4*8; - jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block->data[block_pos]; //tie even + jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even if (is_quad) host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP); else host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP); host_arm64_RET(block, REG_X30); - jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //pos inf + jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf if (is_quad) host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP); else host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP); host_arm64_RET(block, REG_X30); - jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block->data[block_pos]; //neg inf + jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf if (is_quad) host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP); else host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP); host_arm64_RET(block, REG_X30); - jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //zero + jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero if (is_quad) host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP); else host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP); host_arm64_RET(block, REG_X30); - - block_pos = (block_pos + 63) & ~63; } void codegen_backend_init() { + codeblock_t *block; int c; #if defined(__linux__) || defined(__APPLE__) void *start; @@ -288,13 +282,6 @@ void codegen_backend_init() long pagemask = ~(pagesize - 1); #endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#else - codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE); -#endif - if (!codeblock_data) - fatal("codeblock_data failed to alloc - %i\n", (BLOCK_SIZE+1) * BLOCK_DATA_SIZE); codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); @@ -304,29 +291,24 @@ void codegen_backend_init() for (c = 0; c < BLOCK_SIZE; c++) { codeblock[c].pc = BLOCK_PC_INVALID; - codeblock[c].data = &codeblock_data[c * BLOCK_SIZE]; } -#if defined(__linux__) || defined(__APPLE__) - start = (void *)((long)codeblock_data & pagemask); - len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask; - if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) - { - perror("mprotect"); - exit(-1); - } -#endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); block_current = 0; block_pos = 0; - codegen_reset_literal_pool(&codeblock[block_current]); - build_loadstore_routines(&codeblock[block_current]); + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + build_loadstore_routines(block); - codegen_fp_round = &codeblock[block_current].data[block_pos]; - build_fp_round_routine(&codeblock[block_current], 0); - codegen_fp_round_quad = &codeblock[block_current].data[block_pos]; - build_fp_round_routine(&codeblock[block_current], 1); + codegen_fp_round = &block_write_data[block_pos]; + build_fp_round_routine(block, 0); + codegen_fp_round_quad = &block_write_data[block_pos]; + build_fp_round_routine(block, 1); + + block_write_data = NULL; asm("mrs %0, fpcr\n" : "=r" (cpu_state.old_fp_control) @@ -340,14 +322,11 @@ void codegen_set_rounding_mode(int mode) cpu_state.new_fp_control = mode << 3; } -/*R11 - literal pool - R10 - cpu_state*/ +/*R10 - cpu_state*/ void codegen_backend_prologue(codeblock_t *block) { int offset; - codegen_reset_literal_pool(block); - block_pos = 0; block_pos = BLOCK_GPF_OFFSET; @@ -378,8 +357,7 @@ void codegen_backend_prologue(codeblock_t *block) host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_SP, -16); host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -64); - offset = add_literal_q(block, (uintptr_t)&cpu_state); - host_arm64_LDR_LITERAL_X(block, REG_CPUSTATE, offset); + host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t)&cpu_state); if (block->flags & CODEBLOCK_HAS_FPU) { @@ -399,12 +377,7 @@ void codegen_backend_epilogue(codeblock_t *block) host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); host_arm64_RET(block, REG_X30); - if (block_pos > ARM_LITERAL_POOL_OFFSET) - fatal("Over limit!\n"); - - - - __clear_cache(&block->data[0], &block->data[block_pos]); + codegen_allocator_clean_blocks(block->head_mem_block); } #endif diff --git a/src/codegen_backend_arm64.h b/src/codegen_backend_arm64.h index 21bef6d..74586fb 100644 --- a/src/codegen_backend_arm64.h +++ b/src/codegen_backend_arm64.h @@ -9,16 +9,10 @@ #define HASH(l) ((l) & 0x1ffff) -/*Hack until better memory management written*/ -/*#define BLOCK_EXIT_OFFSET 0x7f0*/ - #define BLOCK_GPF_OFFSET 0 #define BLOCK_EXIT_OFFSET 32 -#define ARM_LITERAL_POOL_OFFSET 0xf000 - -/*#define BLOCK_MAX 1720*/ -#define BLOCK_MAX 65208 +#define BLOCK_MAX 0x3c0 void host_arm64_BLR(codeblock_t *block, int addr_reg); @@ -36,7 +30,3 @@ void host_arm64_STRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int o void host_arm64_call(codeblock_t *block, void *dst_addr); void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); - -void codegen_reset_literal_pool(codeblock_t *block); -int add_literal(codeblock_t *block, uint32_t data); -int add_literal_q(codeblock_t *block, uint64_t data); diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 7d71d31..1184a0a 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -2,22 +2,12 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_arm64_defs.h" #include "codegen_backend_arm64_ops.h" -static inline void codegen_addlong(codeblock_t *block, uint32_t val) -{ - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - #define Rt(x) (x) #define Rd(x) (x) #define Rn(x) ((x) << 5) @@ -53,21 +43,23 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_B (0x14 << OPCODE_SHIFT) #define OPCODE_BCOND (0x54 << OPCODE_SHIFT) #define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) +#define OPCODE_CBZ (0xb4 << OPCODE_SHIFT) #define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT) #define OPCODE_CMNX_IMM (0xb1 << OPCODE_SHIFT) #define OPCODE_CMP_IMM (0x71 << OPCODE_SHIFT) #define OPCODE_CMPX_IMM (0xf1 << OPCODE_SHIFT) -#define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT) -#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) #define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) #define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT) #define OPCODE_TBNZ (0x37 << OPCODE_SHIFT) +#define OPCODE_TBZ (0x36 << OPCODE_SHIFT) #define OPCODE_AND_IMM (0x024 << 23) #define OPCODE_ANDS_IMM (0x0e4 << 23) #define OPCODE_EOR_IMM (0x0a4 << 23) #define OPCODE_MOVK_W (0x0e5 << 23) +#define OPCODE_MOVK_X (0x1e5 << 23) #define OPCODE_MOVZ_W (0x0a5 << 23) +#define OPCODE_MOVZ_X (0x1a5 << 23) #define OPCODE_ORR_IMM (0x064 << 23) #define OPCODE_BFI (0x0cc << 22) @@ -225,6 +217,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define BIT_TBxZ(bit) ((((bit) & 0x1f) << 19) | (((bit) & 0x20) ? (1 << 31) : 0)) +#define OFFSET14(offset) (((offset >> 2) << 5) & 0x0007ffe0) #define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) #define OFFSET20(offset) (((offset & 3) << 29) | ((((offset) & 0x1fffff) >> 2) << 5)) #define OFFSET26(offset) ((offset >> 2) & 0x03ffffff) @@ -242,12 +235,6 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define DUP_ELEMENT(element) ((element) << 19) -static int literal_offset = 0; -void codegen_reset_literal_pool(codeblock_t *block) -{ - literal_offset = 0; -} - /*Returns true if offset fits into 19 bits*/ static int offset_is_19bit(int offset) { @@ -268,33 +255,6 @@ static int offset_is_26bit(int offset) return 1; } -int add_literal(codeblock_t *block, uint32_t data) -{ - if (literal_offset >= 4096) - fatal("add_literal - literal pool full\n"); - - *(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; - - literal_offset += 4; - - return literal_offset - 4; -} - -int add_literal_q(codeblock_t *block, uint64_t data) -{ - if (literal_offset & 4) - literal_offset += 4; - - if (literal_offset >= 4096-4) - fatal("add_literal - literal pool full\n"); - - *(uint64_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; - - literal_offset += 8; - - return literal_offset - 8; -} - static inline int imm_is_imm16(uint32_t imm_data) { if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff)) @@ -308,6 +268,39 @@ static inline int imm_is_imm12(uint32_t imm_data) return 0; } +static void codegen_allocate_new_block(codeblock_t *block); + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + if (block_pos >= (BLOCK_MAX-4)) + codegen_allocate_new_block(block); + *(uint32_t *)&block_write_data[block_pos] = val; + block_pos += 4; +} + +static void codegen_allocate_new_block(codeblock_t *block) +{ + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + uint32_t offset = (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos]; + + if (!offset_is_26bit(offset)) + fatal("codegen_allocate_new_block - offset out of range %x\n", offset); + /*Add a jump instruction to the new block*/ + *(uint32_t *)&block_write_data[block_pos] = OPCODE_B | OFFSET26(offset); + + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; +} + +void codegen_alloc(codeblock_t *block, int size) +{ + if (block_pos >= (BLOCK_MAX-size)) + codegen_allocate_new_block(block); +} + void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { if (!imm_data) @@ -462,7 +455,10 @@ void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_re void host_arm64_B(codeblock_t *block, void *dest) { - int offset = (uintptr_t)dest - (uintptr_t)&block->data[block_pos]; + int offset; + + codegen_alloc(block, 4); + offset = (uintptr_t)dest - (uintptr_t)&block_write_data[block_pos]; if (!offset_is_26bit(offset)) fatal("host_arm64_B - offset out of range %x\n", offset); @@ -481,79 +477,107 @@ void host_arm64_BLR(codeblock_t *block, int addr_reg) uint32_t *host_arm64_BCC_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_CC); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_CS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BCS_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_CS); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_CC | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BEQ_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_EQ); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_NE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BGE_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_GE); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LT | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BGT_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_GT); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BHI_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_HI); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BLE_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_LE); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_GT | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BLS_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_LS); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_HI | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BLT_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_LT); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_GE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BMI_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_MI); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_PL | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BNE_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_NE); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_EQ | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BPL_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_PL); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_MI | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BVC_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_VC); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_VS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BVS_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_VS); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_VC | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } void host_arm64_branch_set_offset(uint32_t *opcode, void *dest) { int offset = (uintptr_t)dest - (uintptr_t)opcode; - *opcode |= OFFSET19(offset); + *opcode |= OFFSET26(offset); } void host_arm64_BR(codeblock_t *block, int addr_reg) @@ -574,10 +598,16 @@ void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) { - int offset = dest - (uintptr_t)&block->data[block_pos]; - if (!offset_is_19bit(offset)) - fatal("host_arm64_CBNZ - offset out of range %x\n", offset); - codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); + int offset = dest - (uintptr_t)&block_write_data[block_pos]; + if (offset_is_19bit(offset)) + codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); + else + { + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_CBZ | OFFSET19(8) | Rt(reg)); + offset = (uintptr_t)dest - (uintptr_t)&block_write_data[block_pos]; + codegen_addlong(block, OPCODE_B | OFFSET26(offset)); + } } void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) @@ -880,24 +910,6 @@ void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int of codegen_addlong(block, OPCODE_LDR_IMM_X | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset) -{ - int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos; - - if (!offset_is_19bit(offset)) - fatal("host_arm64_CBNZ - offset out of range %x\n", offset); - - codegen_addlong(block, OPCODE_LDR_LITERAL_W | OFFSET19(offset) | Rt(dest_reg)); -} -void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset) -{ - int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos; - - if (!offset_is_19bit(offset)) - fatal("host_arm64_CBNZ - offset out of range %x\n", offset); - - codegen_addlong(block, OPCODE_LDR_LITERAL_X | OFFSET19(offset) | Rt(dest_reg)); -} void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); @@ -977,6 +989,16 @@ void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data) +{ + codegen_addlong(block, OPCODE_MOVZ_X | MOV_WIDE_HW(0) | IMM16(imm_data & 0xffff) | Rd(reg)); + if ((imm_data >> 16) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(1) | IMM16((imm_data >> 16) & 0xffff) | Rd(reg)); + if ((imm_data >> 32) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(2) | IMM16((imm_data >> 32) & 0xffff) | Rd(reg)); + if ((imm_data >> 48) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(3) | IMM16((imm_data >> 48) & 0xffff) | Rd(reg)); +} void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { if (dst_reg != src_m_reg) @@ -1265,8 +1287,10 @@ void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_ uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit) { - codegen_addlong(block, OPCODE_TBNZ | Rt(reg) | BIT_TBxZ(bit)); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_TBZ | Rt(reg) | BIT_TBxZ(bit) | OFFSET14(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) @@ -1346,15 +1370,13 @@ void host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src void host_arm64_call(codeblock_t *block, void *dst_addr) { - int offset = add_literal_q(block, (uintptr_t)dst_addr); - host_arm64_LDR_LITERAL_X(block, REG_X16, offset); + host_arm64_MOVX_IMM(block, REG_X16, (uint64_t)dst_addr); host_arm64_BLR(block, REG_X16); } void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr) { - int offset = add_literal_q(block, (uintptr_t)dst_addr); - host_arm64_LDR_LITERAL_X(block, REG_X16, offset); + host_arm64_MOVX_IMM(block, REG_X16, (uint64_t)dst_addr); host_arm64_BR(block, REG_X16); } diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index a8c3fc2..42760dd 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -121,8 +121,6 @@ void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, in void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset); -void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset); -void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset); void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); @@ -146,6 +144,7 @@ void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); +void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data); void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data); @@ -170,6 +169,8 @@ void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_SCVTF_V2S(codeblock_t *block, int dst_reg, int src_reg); + void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); @@ -253,4 +254,4 @@ void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); -int add_literal_q(codeblock_t *block, uint64_t data); +void codegen_alloc(codeblock_t *block, int size); \ No newline at end of file diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 703a7e5..c2c5033 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -779,7 +779,7 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) host_arm64_call(block, x86_int); host_arm64_B(block, &block->data[BLOCK_EXIT_OFFSET]); - host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]); + host_arm64_branch_set_offset(branch_ptr, &block_write_data[block_pos]); return 0; } @@ -876,12 +876,11 @@ static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) { int src_reg = HOST_REG_GET(uop->src_reg_a_real); int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - int offset = add_literal_q(block, (uintptr_t)uop->p); if (!REG_IS_W(src_size)) fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); - host_arm64_LDR_LITERAL_X(block, REG_ARG1, offset); + host_arm64_MOVX_IMM(block, REG_ARG1, (uint64_t)uop->p); host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); host_arm64_call(block, (void *)loadseg); host_arm64_CBNZ(block, REG_X0, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); @@ -1229,8 +1228,7 @@ static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) } static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) { - int offset = add_literal_q(block, (uintptr_t)uop->p); - host_arm64_LDR_LITERAL_X(block, uop->dest_reg_a_real, offset); + host_arm64_MOVX_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p); return 0; } @@ -1371,7 +1369,7 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) host_arm64_call(block, codegen_fp_round_quad); host_arm64_FMOV_D_Q(block, dest_reg, REG_TEMP); - host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]); + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); } else fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -3031,8 +3029,6 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int void codegen_set_jump_dest(codeblock_t *block, void *p) { - int offset = (uintptr_t)&block->data[block_pos] - (uintptr_t)p; - - *(uint32_t *)p |= OFFSET19(offset); + host_arm64_branch_set_offset(p, &block_write_data[block_pos]); } #endif diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 85ffd9d..3e17433 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -2,21 +2,11 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_arm_defs.h" #include "codegen_backend_arm_ops.h" -static inline void codegen_addlong(codeblock_t *block, uint32_t val) -{ - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - #define Rm(x) (x) #define Rs(x) ((x) << 8) #define Rd(x) ((x) << 12) @@ -207,6 +197,37 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define VDUP_32_IMM(imm) ((imm) << 19) +static void codegen_allocate_new_block(codeblock_t *block); + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + if (block_pos >= (BLOCK_MAX-4)) + codegen_allocate_new_block(block); + *(uint32_t *)&block_write_data[block_pos] = val; + block_pos += 4; +} + +static void codegen_allocate_new_block(codeblock_t *block) +{ + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + uint32_t offset = ((uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos]) - 8; + + /*Add a jump instruction to the new block*/ + *(uint32_t *)&block_write_data[block_pos] = COND_AL | OPCODE_B | B_OFFSET(offset); + + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; +} + +static inline void codegen_alloc_4(codeblock_t *block) +{ + if (block_pos >= (BLOCK_MAX-4)) + codegen_allocate_new_block(block); +} + static inline uint32_t arm_data_offset(int offset) { if (offset < -0xffc || offset > 0xffc) @@ -321,7 +342,10 @@ void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int sr void host_arm_B(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { @@ -366,7 +390,10 @@ void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int sr void host_arm_BL(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { @@ -378,7 +405,10 @@ void host_arm_BL(codeblock_t *block, uintptr_t dest_addr) } void host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { @@ -397,90 +427,93 @@ uint32_t *host_arm_BCC_(codeblock_t *block) { codegen_addlong(block, COND_CC | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BCS_(codeblock_t *block) { codegen_addlong(block, COND_CS | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BEQ_(codeblock_t *block) { codegen_addlong(block, COND_EQ | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BGE_(codeblock_t *block) { codegen_addlong(block, COND_GE | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BGT_(codeblock_t *block) { codegen_addlong(block, COND_GT | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BHI_(codeblock_t *block) { codegen_addlong(block, COND_HI | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BLE_(codeblock_t *block) { codegen_addlong(block, COND_LE | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BLS_(codeblock_t *block) { codegen_addlong(block, COND_LS | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BLT_(codeblock_t *block) { codegen_addlong(block, COND_LT | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BMI_(codeblock_t *block) { codegen_addlong(block, COND_MI | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BNE_(codeblock_t *block) { codegen_addlong(block, COND_NE | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BPL_(codeblock_t *block) { codegen_addlong(block, COND_PL | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BVC_(codeblock_t *block) { codegen_addlong(block, COND_VC | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BVS_(codeblock_t *block) { codegen_addlong(block, COND_VS | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) fatal("host_arm_BEQ - out of range %08x %i\n", offset, offset); @@ -489,7 +522,10 @@ void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr) } void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) fatal("host_arm_BNE - out of range %08x %i\n", offset, offset); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 3c2ae77..94d9a9b 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -94,6 +94,8 @@ void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm); void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift); +#define host_arm_NOP(block) host_arm_MOV_REG(block, REG_R0, REG_R0) + void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm); void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 1a5d4e2..e65816f 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -6,6 +6,7 @@ #include "x87.h" #include "386_common.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_arm_defs.h" #include "codegen_backend_arm_ops.h" @@ -849,7 +850,7 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) host_arm_call(block, x86_int); host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); - *branch_ptr |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; + *branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; return 0; } @@ -870,7 +871,7 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) host_arm_call(block, x86_int); host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); - *branch_ptr |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; + *branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; host_arm_MOV_IMM(block, REG_TEMP, 0); host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state); @@ -1489,7 +1490,7 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) host_arm_call(block, x87_fround64); host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); - *branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; + *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; } else fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -3165,6 +3166,6 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int void codegen_set_jump_dest(codeblock_t *block, void *p) { - *(uint32_t *)p |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)p) - 8) & 0x3fffffc) >> 2; + *(uint32_t *)p |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)p) - 8) & 0x3fffffc) >> 2; } #endif diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 29ca83a..86ed609 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -2,6 +2,7 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_x86-64_defs.h" #include "codegen_backend_x86-64_ops.h" @@ -101,9 +102,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; host_x86_PUSH(block, REG_RAX); host_x86_PUSH(block, REG_RDX); #if WIN64 @@ -145,7 +146,6 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_POP(block, REG_RAX); host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); host_x86_RET(block); - block_pos = (block_pos + 63) & ~63; } static void build_store_routine(codeblock_t *block, int size, int is_float) @@ -200,9 +200,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; host_x86_PUSH(block, REG_RAX); host_x86_PUSH(block, REG_RDX); #if WIN64 @@ -241,7 +241,6 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_POP(block, REG_RAX); host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); host_x86_RET(block); - block_pos = (block_pos + 63) & ~63; } static void build_loadstore_routines(codeblock_t *block) @@ -283,11 +282,6 @@ void codegen_backend_init() long pagemask = ~(pagesize - 1); #endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#else - codeblock_data = mmap(0, BLOCK_SIZE * BLOCK_DATA_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0); -#endif codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); @@ -295,16 +289,17 @@ void codegen_backend_init() memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); for (c = 0; c < BLOCK_SIZE; c++) - { - codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; codeblock[c].pc = BLOCK_PC_INVALID; - } + // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); block_current = 0; block_pos = 0; + codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL); + codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block); + block_write_data = codeblock[block_current].data; build_loadstore_routines(&codeblock[block_current]); -// fatal("Here\n"); + block_write_data = NULL; asm( "stmxcsr %0\n" @@ -318,47 +313,46 @@ void codegen_set_rounding_mode(int mode) cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); } -static inline void call(codeblock_t *block, uintptr_t func) -{ - uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; - - if (diff >= -0x80000000 && diff < 0x7fffffff) - { - addbyte(0xE8); /*CALL*/ - addlong((uint32_t)diff); - } - else - { - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); - } -} - void codegen_backend_prologue(codeblock_t *block) { - block_pos = 0; /*Entry code*/ - addbyte(0x53); /*PUSH RBX*/ - addbyte(0x55); /*PUSH RBP*/ - addbyte(0x56); /*PUSH RSI*/ - addbyte(0x57); /*PUSH RDI*/ - addbyte(0x41); /*PUSH R12*/ - addbyte(0x54); - addbyte(0x41); /*PUSH R13*/ - addbyte(0x55); - addbyte(0x41); /*PUSH R14*/ - addbyte(0x56); - addbyte(0x41); /*PUSH R15*/ - addbyte(0x57); - addbyte(0x48); /*SUBL $40,%rsp*/ - addbyte(0x83); - addbyte(0xEC); - addbyte(0x38); - addbyte(0x48); /*MOVL RBP, &cpu_state*/ - addbyte(0xBD); - addquad(((uintptr_t)&cpu_state) + 128); + block_pos = BLOCK_GPF_OFFSET; +#if WIN64 + host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX, REG_ECX); + host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX, REG_EDX); +#else + host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI, REG_EDI); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); +#endif + host_x86_CALL(block, (uintptr_t)x86gpf); + while (block_pos < BLOCK_EXIT_OFFSET) + host_x86_NOP(block); + if (block_pos > BLOCK_EXIT_OFFSET) + fatal("block_pos > BLOCK_EXIT_OFFSET\n"); + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x38); + host_x86_POP(block, REG_R15); + host_x86_POP(block, REG_R14); + host_x86_POP(block, REG_R13); + host_x86_POP(block, REG_R12); + host_x86_POP(block, REG_RDI); + host_x86_POP(block, REG_RSI); + host_x86_POP(block, REG_RBP); + host_x86_POP(block, REG_RDX); + host_x86_RET(block); + if (block_pos > BLOCK_START) + fatal("block_pos > BLOCK_START\n"); + + block_pos = BLOCK_START; /*Entry code*/ + host_x86_PUSH(block, REG_RBX); + host_x86_PUSH(block, REG_RBP); + host_x86_PUSH(block, REG_RSI); + host_x86_PUSH(block, REG_RDI); + host_x86_PUSH(block, REG_R12); + host_x86_PUSH(block, REG_R13); + host_x86_PUSH(block, REG_R14); + host_x86_PUSH(block, REG_R15); + host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 0x38); + host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t)&cpu_state) + 128); if (block->flags & CODEBLOCK_HAS_FPU) { host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); @@ -369,62 +363,15 @@ void codegen_backend_prologue(codeblock_t *block) void codegen_backend_epilogue(codeblock_t *block) { - addbyte(0x48); /*ADDL $40,%rsp*/ - addbyte(0x83); - addbyte(0xC4); - addbyte(0x38); - addbyte(0x41); /*POP R15*/ - addbyte(0x5f); - addbyte(0x41); /*POP R14*/ - addbyte(0x5e); - addbyte(0x41); /*POP R13*/ - addbyte(0x5d); - addbyte(0x41); /*POP R12*/ - addbyte(0x5c); - addbyte(0x5f); /*POP RDI*/ - addbyte(0x5e); /*POP RSI*/ - addbyte(0x5d); /*POP RBP*/ - addbyte(0x5b); /*POP RDX*/ - addbyte(0xC3); /*RET*/ - - if (block_pos > BLOCK_GPF_OFFSET) - fatal("Over limit!\n"); - - block_pos = BLOCK_GPF_OFFSET; -#if WIN64 - addbyte(0x48); /*XOR RCX, RCX*/ - addbyte(0x31); - addbyte(0xc9); - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); -#else - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); -#endif - call(block, (uintptr_t)x86gpf); - while (block_pos < BLOCK_EXIT_OFFSET) - addbyte(0x90); /*NOP*/ - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x48); /*ADDL $40,%rsp*/ - addbyte(0x83); - addbyte(0xC4); - addbyte(0x38); - addbyte(0x41); /*POP R15*/ - addbyte(0x5f); - addbyte(0x41); /*POP R14*/ - addbyte(0x5e); - addbyte(0x41); /*POP R13*/ - addbyte(0x5d); - addbyte(0x41); /*POP R12*/ - addbyte(0x5c); - addbyte(0x5f); /*POP RDI*/ - addbyte(0x5e); /*POP RSI*/ - addbyte(0x5d); /*POP RBP*/ - addbyte(0x5b); /*POP RDX*/ - addbyte(0xC3); /*RET*/ + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x38); + host_x86_POP(block, REG_R15); + host_x86_POP(block, REG_R14); + host_x86_POP(block, REG_R13); + host_x86_POP(block, REG_R12); + host_x86_POP(block, REG_RDI); + host_x86_POP(block, REG_RSI); + host_x86_POP(block, REG_RBP); + host_x86_POP(block, REG_RDX); + host_x86_RET(block); } - #endif diff --git a/src/codegen_backend_x86-64.h b/src/codegen_backend_x86-64.h index 4e9ec51..de52c3c 100644 --- a/src/codegen_backend_x86-64.h +++ b/src/codegen_backend_x86-64.h @@ -2,17 +2,14 @@ #define BLOCK_SIZE 0x4000 #define BLOCK_MASK 0x3fff -#define BLOCK_START 0 +#define BLOCK_START 40 #define HASH_SIZE 0x20000 #define HASH_MASK 0x1ffff #define HASH(l) ((l) & 0x1ffff) -/*Hack until better memory management written*/ -#define BLOCK_EXIT_OFFSET (BLOCK_DATA_SIZE - 32) -/*#define BLOCK_EXIT_OFFSET 0x7f0*/ -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) +#define BLOCK_EXIT_OFFSET 20 +#define BLOCK_GPF_OFFSET 0 -/*#define BLOCK_MAX 1720*/ -#define BLOCK_MAX 65208 +#define BLOCK_MAX 0x3c0 diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 0992683..956f4eb 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -2,6 +2,7 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_x86-64_defs.h" #include "codegen_backend_x86-64_ops.h" @@ -17,80 +18,100 @@ #define RM_OP_SHR 0x28 #define RM_OP_SAR 0x38 +#define JMP_LEN_BYTES 5 + static inline void codegen_addbyte(codeblock_t *block, uint8_t val) { - block->data[block_pos++] = val; if (block_pos >= BLOCK_MAX) { fatal("codegen_addbyte over! %i\n", block_pos); // CPU_BLOCK_END(); } + block_write_data[block_pos++] = val; } static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-2)) { fatal("codegen_addbyte2 over! %i\n", block_pos); CPU_BLOCK_END(); } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; } static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-3)) { fatal("codegen_addbyte3 over! %i\n", block_pos); CPU_BLOCK_END(); } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; } static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - block->data[block_pos++] = vald; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-4)) { fatal("codegen_addbyte4 over! %i\n", block_pos); CPU_BLOCK_END(); } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; + block_write_data[block_pos++] = vald; } static inline void codegen_addword(codeblock_t *block, uint16_t val) { - *(uint16_t *)&block->data[block_pos] = val; - block_pos += 2; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-2)) { fatal("codegen_addword over! %i\n", block_pos); CPU_BLOCK_END(); } + *(uint16_t *)&block_write_data[block_pos] = val; + block_pos += 2; } static inline void codegen_addlong(codeblock_t *block, uint32_t val) { - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-4)) { fatal("codegen_addlong over! %i\n", block_pos); CPU_BLOCK_END(); } + *(uint32_t *)&block_write_data[block_pos] = val; + block_pos += 4; } static inline void codegen_addquad(codeblock_t *block, uint64_t val) { - *(uint64_t *)&block->data[block_pos] = val; - block_pos += 8; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-8)) { fatal("codegen_addquad over! %i\n", block_pos); CPU_BLOCK_END(); } + *(uint64_t *)&block_write_data[block_pos] = val; + block_pos += 8; +} + +static inline void codegen_alloc_bytes(codeblock_t *block, int size) +{ + if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) + { + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + + /*Add a jump instruction to the new block*/ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); + + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; + } } static int is_imm8(uint32_t imm_data) @@ -102,7 +123,10 @@ static int is_imm8(uint32_t imm_data) static inline void call(codeblock_t *block, uintptr_t func) { - uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; + uintptr_t diff; + + codegen_alloc_bytes(block, 5); + diff = func - (uintptr_t)&block_write_data[block_pos + 5]; if (diff >= -0x80000000 && diff < 0x7fffffff) { @@ -111,6 +135,7 @@ static inline void call(codeblock_t *block, uintptr_t func) } else { + codegen_alloc_bytes(block, 13); codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ codegen_addquad(block, func); codegen_addbyte3(block, 0x41, 0xff, 0xd1); /*CALL R9*/ @@ -119,7 +144,10 @@ static inline void call(codeblock_t *block, uintptr_t func) static inline void jmp(codeblock_t *block, uintptr_t func) { - uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; + uintptr_t diff; + + codegen_alloc_bytes(block, 5); + diff = func - (uintptr_t)&block_write_data[block_pos + 5]; if (diff >= -0x80000000 && diff < 0x7fffffff) { @@ -128,6 +156,7 @@ static inline void jmp(codeblock_t *block, uintptr_t func) } else { + codegen_alloc_bytes(block, 13); codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ codegen_addquad(block, func); codegen_addbyte3(block, 0x41, 0xff, 0xe1); /*JMP R9*/ @@ -140,9 +169,15 @@ void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/ + } } void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -150,14 +185,19 @@ void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -168,14 +208,19 @@ void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -186,7 +231,10 @@ void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) fatal("host_x86_ADD64_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else fatal("ADD64_REG_IMM !is_imm8 %016llx\n", imm_data); } @@ -195,6 +243,7 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_ADD8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -202,6 +251,7 @@ void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_ADD16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -209,15 +259,18 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_ADD32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ } void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); } @@ -227,9 +280,15 @@ void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/ + } } void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -237,14 +296,19 @@ void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -255,14 +319,19 @@ void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -272,6 +341,7 @@ void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -279,6 +349,7 @@ void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -286,6 +357,7 @@ void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ } @@ -297,14 +369,19 @@ void host_x86_CALL(codeblock_t *block, void *p) void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -312,14 +389,19 @@ void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -327,87 +409,107 @@ void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) { if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else fatal("CMP64_REG_IMM not 8-bit imm\n"); } void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ } void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); } void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ } void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ } void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ } void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/ codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/ codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ } @@ -418,118 +520,138 @@ void host_x86_JMP(codeblock_t *block, void *p) void host_x86_JNZ(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } void host_x86_JZ(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } uint8_t *host_x86_JNZ_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x75, 0); /*JNZ*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint8_t *host_x86_JS_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x78, 0); /*JS*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint8_t *host_x86_JZ_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x74, 0); /*JZ*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint32_t *host_x86_JNB_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNBE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNL_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNLE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNO_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNS_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNZ_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JB_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JBE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JL_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JLE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JO_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JS_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JZ_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } void host_x86_LAHF(codeblock_t *block) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0x9f); /*LAHF*/ } @@ -539,10 +661,12 @@ void host_x86_LDMXCSR(codeblock_t *block, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/ codegen_addlong(block, offset); } @@ -556,17 +680,22 @@ void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t { if (offset) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ codegen_addlong(block, offset); } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ + } } void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_LEA_REG_REG - bad reg\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b]*/ ((src_reg_b & 7) << 3) | (src_reg_a & 7)); } @@ -575,12 +704,14 @@ void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/ (shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7)); } void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ } @@ -590,6 +721,7 @@ void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/ codegen_addbyte(block, imm_data); } @@ -597,6 +729,7 @@ void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { if ((uintptr_t)p >> 32) fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p); + codegen_alloc_bytes(block, 8); codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/ codegen_addlong(block, (uint32_t)(uintptr_t)p); codegen_addbyte(block, imm_data); @@ -608,6 +741,7 @@ void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ codegen_addlong(block, imm_data); } @@ -615,6 +749,7 @@ void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { if ((uintptr_t)p >> 32) fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); + codegen_alloc_bytes(block, 11); codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ codegen_addlong(block, (uint32_t)(uintptr_t)p); codegen_addlong(block, imm_data); @@ -630,12 +765,14 @@ void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/ } else { if ((uintptr_t)p >> 32) fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); codegen_addlong(block, (uint32_t)(uintptr_t)p); @@ -650,10 +787,12 @@ void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x66, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ codegen_addlong(block, offset); } @@ -672,10 +811,12 @@ void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ codegen_addlong(block, offset); } @@ -683,6 +824,7 @@ void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) { if ((uintptr_t)p >> 32) fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); codegen_addlong(block, (uint32_t)(uintptr_t)p); @@ -697,12 +839,14 @@ void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ } else { if ((uintptr_t)p >> 32) fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/ codegen_addlong(block, (uint32_t)(uintptr_t)p); } @@ -714,10 +858,12 @@ void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ codegen_addlong(block, addr); } @@ -727,18 +873,21 @@ void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_re { if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV B[base_reg + index_reg], src_reg*/ } void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) { if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV W[base_reg + index_reg], src_reg*/ } void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) { if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV L[base_reg + index_reg], src_reg*/ } @@ -751,10 +900,12 @@ void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8a, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x8a, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ codegen_addlong(block, offset); } @@ -772,10 +923,12 @@ void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x66, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ codegen_addlong(block, offset); } @@ -793,16 +946,19 @@ void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ codegen_addlong(block, offset); } else { fatal("host_x86_MOV32_REG_ABS - out of range\n"); + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3)); codegen_addlong(block, (uint32_t)(uintptr_t)p); @@ -817,10 +973,12 @@ void host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x48, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ codegen_addlong(block, offset); } @@ -834,10 +992,12 @@ void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32 fatal("host_x86_MOV8_REG_ABS_REG_REG_SHIFT reg & 8\n"); if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ codegen_addlong(block, addr); } @@ -847,6 +1007,7 @@ void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg { if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV32_REG_BASE_INDEX reg & 8\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); /*MOV dst_reg, Q[base_reg + index_reg]*/ } @@ -854,6 +1015,7 @@ void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int ba { if ((dst_reg & 8) || (index_reg & 8)) fatal("host_x86_MOV64_REG_BASE_INDEX_SHIFT reg & 8\n"); + codegen_alloc_bytes(block, 4); if (base_reg & 8) codegen_addbyte4(block, 0x49, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ else @@ -869,11 +1031,15 @@ void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x66); codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } } else fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); @@ -887,10 +1053,14 @@ void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } } else fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); @@ -904,11 +1074,15 @@ void host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x48); codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } } else fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); @@ -923,10 +1097,14 @@ void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } } else fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); @@ -940,11 +1118,15 @@ void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x48); codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } } else fatal("MOV64_BASE_OFFSET_REG - offset %i\n", offset); @@ -954,12 +1136,14 @@ void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) { if (reg >= 8) fatal("host_x86_MOV8_REG_IMM reg >= 4\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/ } void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) { if (reg & 8) fatal("host_x86_MOV16_REG_IMM reg & 8\n"); + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ codegen_addword(block, imm_data); } @@ -967,6 +1151,7 @@ void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) { if (reg & 8) fatal("host_x86_MOV32_REG_IMM reg & 8\n"); + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -975,11 +1160,13 @@ void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data) { if (reg & 8) { + codegen_alloc_bytes(block, 10); codegen_addbyte2(block, 0x49, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ codegen_addquad(block, imm_data); } else { + codegen_alloc_bytes(block, 10); codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ codegen_addquad(block, imm_data); } @@ -990,6 +1177,7 @@ void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOV8_REG_REG - bad reg\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) @@ -997,6 +1185,7 @@ void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOV16_REG_REG - bad reg\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) @@ -1004,6 +1193,7 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOV32_REG_REG - bad reg\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } @@ -1011,16 +1201,19 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d { if (!offset) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ codegen_addlong(block, imm_data); } else if (offset >= -80 || offset < 0x80) { + codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 11); codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ codegen_addlong(block, offset); codegen_addlong(block, imm_data); @@ -1029,20 +1222,24 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); } void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1055,6 +1252,7 @@ void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ codegen_addbyte(block, offset); } @@ -1062,6 +1260,7 @@ void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) { if ((uintptr_t)p >> 32) fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/ codegen_addbyte(block, 0x25); codegen_addlong(block, (uint32_t)(uintptr_t)p); @@ -1072,13 +1271,16 @@ void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n"); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); } else { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); codegen_addlong(block, addr); } @@ -1086,6 +1288,7 @@ void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } @@ -1095,11 +1298,13 @@ void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/ codegen_addbyte2(block, 0x24, offset); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ codegen_addbyte(block, offset); } @@ -1117,6 +1322,7 @@ void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ codegen_addbyte(block, offset); } @@ -1124,6 +1330,7 @@ void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) { if ((uintptr_t)p >> 32) fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p); + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ codegen_addbyte(block, 0x25); codegen_addlong(block, (uint32_t)(uintptr_t)p); @@ -1134,19 +1341,23 @@ void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint3 if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n"); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); } else { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); codegen_addlong(block, addr); } } void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } @@ -1156,11 +1367,13 @@ void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ codegen_addbyte2(block, 0x24, offset); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ codegen_addbyte(block, offset); } @@ -1171,30 +1384,36 @@ void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ } void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/ codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3)); } void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/ codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } @@ -1202,12 +1421,16 @@ void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_re { if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOVZX_BASE_INDEX_32_8 reg & 8\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); } void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg) { if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOVZX_BASE_INDEX_32_16 reg & 8\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); } @@ -1215,18 +1438,24 @@ void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) { if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOVZX_REG_32_8 - bad reg\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) { if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } @@ -1240,8 +1469,16 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { if (dst_reg & 8) + { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x44); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } + else + { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } } else fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset); @@ -1249,31 +1486,47 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ } void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ } void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ } void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); } +void host_x86_NOP(codeblock_t *block) +{ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x90); /*NOP*/ +} + void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/ + } } void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1281,14 +1534,19 @@ void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_ fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1299,14 +1557,19 @@ void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_ fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1316,6 +1579,7 @@ void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int sr if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ } void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1323,6 +1587,7 @@ void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ } void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1330,23 +1595,27 @@ void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ } void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); } void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); } void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); @@ -1354,210 +1623,267 @@ void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ } void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ } void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ } void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ } void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ } void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ } void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ } void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ } void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ } void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ } void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ } void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ } void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ } void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ } void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ } void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ } void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ } void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ } void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ } void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ } void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ } void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ } void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ } void host_x86_POP(codeblock_t *block, int dst_reg) { if (dst_reg & 8) - fatal("POP reg & 8\n"); - codegen_addbyte(block, 0x58 | dst_reg); /*POP reg*/ + { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x41, 0x58 | (dst_reg & 7)); /*POP reg*/ + } + else + { + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x58 | dst_reg); /*POP reg*/ + } } void host_x86_PUSH(codeblock_t *block, int src_reg) { if (src_reg & 8) - fatal("PUSH reg & 8\n"); - codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ + { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x41, 0x50 | (src_reg & 7)); /*PUSH reg*/ + } + else + { + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ + } } void host_x86_RET(codeblock_t *block) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0xc3); /*RET*/ } @@ -1565,18 +1891,24 @@ void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SAR8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } void host_x86_SAR16_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SAR16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } void host_x86_SAR32_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SAR32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } @@ -1584,18 +1916,23 @@ void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SAR8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SAR16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SAR32 imm & 8\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } @@ -1603,18 +1940,24 @@ void host_x86_SHL8_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHL8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_SHL16_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHL16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_SHL32_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHL32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } @@ -1622,18 +1965,24 @@ void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHL8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHL16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHL32 imm & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } @@ -1641,18 +1990,24 @@ void host_x86_SHR8_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHR8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_SHR16_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHR16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_SHR32_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHR32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } @@ -1660,27 +2015,34 @@ void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHR8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHR16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHR32 imm & 8\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ } void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ } @@ -1690,9 +2052,15 @@ void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/ + } } void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1700,14 +2068,19 @@ void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1718,14 +2091,19 @@ void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1736,7 +2114,10 @@ void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) fatal("host_x86_SUB64_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else fatal("SUB64_REG_IMM !is_imm8 %016llx\n", imm_data); } @@ -1745,6 +2126,7 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1752,6 +2134,7 @@ void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1759,15 +2142,18 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ } void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1775,16 +2161,20 @@ void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) { if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_TEST32_REG - bad reg\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) @@ -1793,11 +2183,13 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) fatal("TEST32_REG_IMM reg & 8\n"); if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1805,6 +2197,7 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1814,9 +2207,15 @@ void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/ + } } void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1824,14 +2223,19 @@ void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1842,14 +2246,19 @@ void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1859,6 +2268,7 @@ void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ } void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1866,6 +2276,7 @@ void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ } void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1873,6 +2284,7 @@ void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ } diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index ea2eede..209e270 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -163,6 +163,8 @@ void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_NOP(codeblock_t *block); + void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index dd164d6..e49fe7f 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -715,11 +715,11 @@ static int codegen_FSUB(codeblock_t *block, uop_t *uop) static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) { - uint8_t *branch_offset; + uint32_t *branch_offset; host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_short(block); + branch_offset = host_x86_JZ_long(block); host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); #if WIN64 host_x86_MOV32_REG_IMM(block, REG_ECX, 7); @@ -728,17 +728,17 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) #endif host_x86_CALL(block, x86_int); host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; return 0; } static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) { - uint8_t *branch_offset; + uint32_t *branch_offset; host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_short(block); + branch_offset = host_x86_JZ_long(block); host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); #if WIN64 host_x86_MOV32_REG_IMM(block, REG_ECX, 7); @@ -747,7 +747,7 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) #endif host_x86_CALL(block, x86_int); host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0); host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0); host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); @@ -1269,19 +1269,19 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { - uint8_t *branch_offset; + uint32_t *branch_offset; /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); host_x86_TEST8_REG(block, tag_reg, tag_reg); - branch_offset = host_x86_JS_short(block); + branch_offset = host_x86_JS_long(block); host_x86_LDMXCSR(block, &cpu_state.new_fp_control); host_x86_CVTSD2SI_REG64_XREG(block, REG_RCX, src_reg); host_x86_LDMXCSR(block, &cpu_state.old_fp_control); host_x86_MOVQ_XREG_REG(block, dest_reg, REG_RCX); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; } else fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -2763,7 +2763,7 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int void codegen_set_jump_dest(codeblock_t *block, void *p) { - *(uint32_t *)p = (uintptr_t)&block->data[block_pos] - ((uintptr_t)p + 4); + *(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4); } #endif diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 82c1d87..68d9a36 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -3,6 +3,7 @@ #include #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" #include "codegen_backend_x86_ops.h" @@ -100,9 +101,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; host_x86_PUSH(block, REG_EAX); host_x86_PUSH(block, REG_EDX); host_x86_PUSH(block, REG_ECX); @@ -190,9 +191,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; if (size == 4 && is_float) host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP); host_x86_PUSH(block, REG_EAX); @@ -254,6 +255,7 @@ static void build_loadstore_routines(codeblock_t *block) void codegen_backend_init() { + codeblock_t *block; int c; #if defined(__linux__) || defined(__APPLE__) void *start; @@ -283,48 +285,33 @@ pclog(" offsetof(codeblock_t, next)=%i\n", offsetof(codeblock_t, next)); pclog(" offsetof(codeblock_t, prev_2)=%i\n", offsetof(codeblock_t, prev_2)); pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2)); codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); -#if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#else - codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE; -#endif codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); for (c = 0; c < BLOCK_SIZE; c++) - { - codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; codeblock[c].pc = BLOCK_PC_INVALID; - } -#if defined(__linux__) || defined(__APPLE__) - start = (void *)((long)codeblock_data & pagemask); - len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask; - if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) - { - perror("mprotect"); - exit(-1); - } -#endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); block_current = 0; block_pos = 0; - mem_abrt_rout = &codeblock[block_current].data[block_pos]; - addbyte(0x83); /*ADDL $16+4,%esp*/ - addbyte(0xC4); - addbyte(0x10+4); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + mem_abrt_rout = &block->data[block_pos]; + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x10+4); + host_x86_POP(block, REG_EDI); + host_x86_POP(block, REG_ESI); + host_x86_POP(block, REG_EBP); + host_x86_POP(block, REG_EDX); + host_x86_RET(block); + block_pos = 64; - build_loadstore_routines(&codeblock[block_current]); - //fatal("Here\n"); + build_loadstore_routines(block); + block_write_data = NULL; cpu_state.old_fp_control = 0; asm( @@ -346,16 +333,25 @@ void codegen_set_rounding_mode(int mode) void codegen_backend_prologue(codeblock_t *block) { - block_pos = 0; /*Entry code*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0x55); /*PUSH EBP*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0x57); /*PUSH EDI*/ - addbyte(0x83); /*SUBL $64,%esp*/ - addbyte(0xEC); - addbyte(0x40); - addbyte(0xBD); /*MOVL EBP, &cpu_state*/ - addlong(((uintptr_t)&cpu_state) + 128); + block_pos = BLOCK_GPF_OFFSET; + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0); + host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0); + host_x86_CALL(block, (void *)x86gpf); + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 64); + host_x86_POP(block, REG_EDI); + host_x86_POP(block, REG_ESI); + host_x86_POP(block, REG_EBP); + host_x86_POP(block, REG_EDX); + host_x86_RET(block); + + block_pos = BLOCK_START; /*Entry code*/ + host_x86_PUSH(block, REG_EBX); + host_x86_PUSH(block, REG_EBP); + host_x86_PUSH(block, REG_ESI); + host_x86_PUSH(block, REG_EDI); + host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 64); + host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t)&cpu_state) + 128); if (block->flags & CODEBLOCK_HAS_FPU) { host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); @@ -366,39 +362,12 @@ void codegen_backend_prologue(codeblock_t *block) void codegen_backend_epilogue(codeblock_t *block) { - addbyte(0x83); /*ADDL $64,%esp*/ - addbyte(0xC4); - addbyte(0x40); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - - if (block_pos > BLOCK_GPF_OFFSET) - fatal("Over limit!\n"); - - block_pos = BLOCK_GPF_OFFSET; - addbyte(0xc7); /*MOV [ESP],0*/ - addbyte(0x04); - addbyte(0x24); - addlong(0); - addbyte(0xc7); /*MOV [ESP+4],0*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x04); - addlong(0); - addbyte(0xe8); /*CALL x86gpf*/ - addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x83); /*ADDL $64,%esp*/ - addbyte(0xC4); - addbyte(0x40); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 64); + host_x86_POP(block, REG_EDI); + host_x86_POP(block, REG_ESI); + host_x86_POP(block, REG_EBP); + host_x86_POP(block, REG_EDX); + host_x86_RET(block); } #endif diff --git a/src/codegen_backend_x86.h b/src/codegen_backend_x86.h index 13ccfab..52df734 100644 --- a/src/codegen_backend_x86.h +++ b/src/codegen_backend_x86.h @@ -2,18 +2,14 @@ #define BLOCK_SIZE 0x4000 #define BLOCK_MASK 0x3fff -#define BLOCK_START 0 +#define BLOCK_START 32 #define HASH_SIZE 0x20000 #define HASH_MASK 0x1ffff #define HASH(l) ((l) & 0x1ffff) -/*Hack until better memory management written*/ -#define BLOCK_EXIT_OFFSET (BLOCK_DATA_SIZE - 16) -//#define BLOCK_EXIT_OFFSET 0xfff0 -/*#define BLOCK_EXIT_OFFSET 0x7f0*/ -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) +#define BLOCK_EXIT_OFFSET 20 +#define BLOCK_GPF_OFFSET 0 -/*#define BLOCK_MAX 1720*/ -#define BLOCK_MAX 65208 +#define BLOCK_MAX 0x3c0 diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h index 03b2a2e..0c9eb1d 100644 --- a/src/codegen_backend_x86_defs.h +++ b/src/codegen_backend_x86_defs.h @@ -39,4 +39,9 @@ extern void *codegen_mem_store_quad; extern void *codegen_mem_store_single; extern void *codegen_mem_store_double; +#define STACK_ARG0 (0) +#define STACK_ARG1 (4) +#define STACK_ARG2 (8) +#define STACK_ARG3 (12) + #endif diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 97ba65f..56bd27a 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -2,6 +2,7 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" #include "codegen_backend_x86_ops.h" @@ -17,80 +18,82 @@ #define RM_OP_SHR 0x28 #define RM_OP_SAR 0x38 +#define JMP_LEN_BYTES 5 + static inline void codegen_addbyte(codeblock_t *block, uint8_t val) { - block->data[block_pos++] = val; if (block_pos >= BLOCK_MAX) - { fatal("codegen_addbyte over! %i\n", block_pos); -// CPU_BLOCK_END(); - } + block_write_data[block_pos++] = val; } static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-2)) fatal("codegen_addbyte2 over! %i\n", block_pos); - CPU_BLOCK_END(); - } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; } static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-3)) fatal("codegen_addbyte3 over! %i\n", block_pos); - CPU_BLOCK_END(); - } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; } static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - block->data[block_pos++] = vald; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-4)) fatal("codegen_addbyte4 over! %i\n", block_pos); - CPU_BLOCK_END(); - } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; + block_write_data[block_pos++] = vald; } static inline void codegen_addword(codeblock_t *block, uint16_t val) { - *(uint16_t *)&block->data[block_pos] = val; - block_pos += 2; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-2)) fatal("codegen_addword over! %i\n", block_pos); - CPU_BLOCK_END(); - } + *(uint16_t *)&block_write_data[block_pos] = val; + block_pos += 2; } static inline void codegen_addlong(codeblock_t *block, uint32_t val) { - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-4)) fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } + *(uint32_t *)&block_write_data[block_pos] = val; + block_pos += 4; } static inline void codegen_addquad(codeblock_t *block, uint64_t val) { - *(uint64_t *)&block->data[block_pos] = val; - block_pos += 8; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-8)) fatal("codegen_addquad over! %i\n", block_pos); - CPU_BLOCK_END(); - } + *(uint64_t *)&block_write_data[block_pos] = val; + block_pos += 8; +} + +static void codegen_allocate_new_block(codeblock_t *block) +{ + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + + /*Add a jump instruction to the new block*/ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); + + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; +} + +static inline void codegen_alloc_bytes(codeblock_t *block, int size) +{ + if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) + codegen_allocate_new_block(block); } static int is_imm8(uint32_t imm_data) @@ -106,10 +109,12 @@ void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, int src_reg, void * if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x03, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x03); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | (dst_reg << 3)); codegen_addlong(block, (uint32_t)p); @@ -122,9 +127,15 @@ void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/ + } } void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -132,14 +143,19 @@ void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -150,14 +166,19 @@ void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -168,6 +189,7 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_ADD8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -175,6 +197,7 @@ void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_ADD16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -182,15 +205,18 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_ADD32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ } void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); } @@ -200,9 +226,15 @@ void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/ + } } void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -210,14 +242,19 @@ void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -228,14 +265,19 @@ void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -246,6 +288,7 @@ void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -253,6 +296,7 @@ void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -260,26 +304,33 @@ void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_CALL(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xe8); /*CALL*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -287,14 +338,19 @@ void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -302,205 +358,243 @@ void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ } void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); } void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ } void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ } void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ } void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/ } void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/ } void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ } void host_x86_INC32_ABS(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0xff, 0x05); /*INC p*/ codegen_addlong(block, (uint32_t)p); } void host_x86_JMP(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } uint32_t *host_x86_JMP_long(codeblock_t *block) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xe9); /*JMP*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } void host_x86_JNZ(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } void host_x86_JZ(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } uint8_t *host_x86_JNZ_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x75, 0); /*JNZ*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint8_t *host_x86_JS_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x78, 0); /*JS*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint8_t *host_x86_JZ_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x74, 0); /*JZ*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint32_t *host_x86_JNB_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNBE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNL_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNLE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNO_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNS_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNZ_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JB_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JBE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JL_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JLE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JO_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JS_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JZ_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } void host_x86_LAHF(codeblock_t *block) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0x9f); /*LAHF*/ } @@ -510,10 +604,12 @@ void host_x86_LDMXCSR(codeblock_t *block, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/ codegen_addlong(block, (uint32_t)p); } @@ -523,24 +619,31 @@ void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t { if (offset) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ codegen_addlong(block, offset); } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ + } } void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b]*/ } void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/ } void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ } @@ -550,11 +653,13 @@ void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/ codegen_addbyte(block, imm_data); } else { + codegen_alloc_bytes(block, 7); codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/ codegen_addlong(block, (uint32_t)p); codegen_addbyte(block, imm_data); @@ -566,11 +671,13 @@ void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 10); codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/ codegen_addlong(block, (uint32_t)p); codegen_addlong(block, imm_data); @@ -583,10 +690,12 @@ void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ codegen_addbyte(block, 0x05 | (src_reg << 3)); codegen_addlong(block, (uint32_t)p); @@ -598,10 +707,12 @@ void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x66, 0x89, 0x05 | (src_reg << 3)); /*MOV [p], src_reg*/ codegen_addlong(block, (uint32_t)p); } @@ -612,10 +723,12 @@ void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | (src_reg << 3)); codegen_addlong(block, (uint32_t)p); @@ -626,10 +739,12 @@ void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int { if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ codegen_addlong(block, addr); } @@ -637,14 +752,17 @@ void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV B[base_reg + idx_reg], src_reg*/ } void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV W[base_reg + idx_reg], src_reg*/ } void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV L[base_reg + idx_reg], src_reg*/ } @@ -654,10 +772,12 @@ void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8a, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x8a); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | (dst_reg << 3)); codegen_addlong(block, (uint32_t)p); @@ -669,10 +789,12 @@ void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x66, 0x8b, 0x05 | (dst_reg << 3)); /*MOV [p], src_reg*/ codegen_addlong(block, (uint32_t)p); } @@ -683,10 +805,12 @@ void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | (dst_reg << 3)); codegen_addlong(block, (uint32_t)p); @@ -695,6 +819,7 @@ void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (shift << 6) | (idx_reg << 3) | 0x05); /*MOV dst_reg, [p + idx_reg << shift]*/ codegen_addlong(block, (uint32_t)p); } @@ -703,10 +828,12 @@ void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32 { if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ codegen_addlong(block, addr); } @@ -714,6 +841,7 @@ void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32 void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/ } @@ -723,11 +851,15 @@ void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x66); codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } } else fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); @@ -738,10 +870,14 @@ void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } } else fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); @@ -753,11 +889,15 @@ void host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x66); codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } } else fatal("MOV16_BASE_OFFSET_REG - offset %i\n", offset); @@ -768,10 +908,14 @@ void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } } else fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); @@ -779,16 +923,19 @@ void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/ } void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { if (!imm_data) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/ codegen_addword(block, imm_data); } @@ -797,10 +944,12 @@ void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (!imm_data) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ } else { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xb8 + dst_reg); /*MOV reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -808,14 +957,17 @@ void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3)); } void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3)); } void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3)); } @@ -823,16 +975,19 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d { if (!offset) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ codegen_addlong(block, imm_data); } else if (offset >= -80 || offset < 0x80) { + codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 11); codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ codegen_addlong(block, offset); codegen_addlong(block, imm_data); @@ -841,20 +996,24 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); } void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); } @@ -864,30 +1023,36 @@ void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ codegen_addbyte(block, offset); } else { + codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/ codegen_addlong(block, (uint32_t)p); } } void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) { - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); } else { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); codegen_addlong(block, addr); } } void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } @@ -897,11 +1062,13 @@ void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/ codegen_addbyte2(block, 0x24, offset); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ codegen_addbyte(block, offset); } @@ -913,16 +1080,19 @@ void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg { if (!offset) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/ codegen_addbyte(block, 0x24); } else if (offset >= -80 || offset < 0x80) { + codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ codegen_addbyte2(block, 0x24, offset & 0xff); } else { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ codegen_addbyte(block, 0x24); codegen_addlong(block, offset); @@ -936,30 +1106,36 @@ void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ codegen_addbyte(block, offset); } else { + codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ codegen_addlong(block, (uint32_t)p); } } void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) { - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); } else { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); codegen_addlong(block, addr); } } void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } @@ -969,11 +1145,13 @@ void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ codegen_addbyte2(block, 0x24, offset); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ codegen_addbyte(block, offset); } @@ -983,19 +1161,23 @@ void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re } void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ } void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } @@ -1005,10 +1187,12 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ codegen_addlong(block, (uint32_t)p); } @@ -1019,10 +1203,12 @@ void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x0f, 0xb7, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ codegen_addlong(block, (uint32_t)p); } @@ -1030,41 +1216,50 @@ void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, B[base_reg + idx_reg]*/ } void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/ } void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ } void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ } void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ } void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1073,6 +1268,7 @@ void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int sr if (dst_reg != src_reg_a) fatal("host_x86_OR8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ } void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1080,6 +1276,7 @@ void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_OR16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ } void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1087,6 +1284,7 @@ void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ } @@ -1096,9 +1294,15 @@ void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/ + } } void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1106,14 +1310,19 @@ void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_ fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1124,14 +1333,19 @@ void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_ fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1139,18 +1353,21 @@ void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_ void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); } void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); } void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); @@ -1158,206 +1375,251 @@ void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ } void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ } void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ } void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ } void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ } void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ } void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ } void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ } void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ } void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ } void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ } void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ } void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ } void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ } void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ } void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ } void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ } void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ } void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ } void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ } void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ } void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ } void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ } void host_x86_POP(codeblock_t *block, int src_reg) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/ } void host_x86_PUSH(codeblock_t *block, int src_reg) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ } void host_x86_RET(codeblock_t *block) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0xc3); /*RET*/ } @@ -1365,88 +1627,108 @@ void host_x86_RET(codeblock_t *block) void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } void host_x86_SAR16_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } void host_x86_SAR32_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } void host_x86_SHL8_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_SHL16_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_SHL32_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_SHR8_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_SHR16_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_SHR32_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ } void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ } @@ -1456,9 +1738,15 @@ void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/ + } } void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1466,14 +1754,19 @@ void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1484,14 +1777,19 @@ void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1502,6 +1800,7 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1509,6 +1808,7 @@ void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1516,39 +1816,47 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ } void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1556,6 +1864,7 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1564,6 +1873,7 @@ void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_XOR8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ } void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1571,6 +1881,7 @@ void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_XOR16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ } void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1578,6 +1889,7 @@ void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ } @@ -1587,9 +1899,15 @@ void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/ + } } void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1597,14 +1915,19 @@ void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1615,14 +1938,19 @@ void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1631,16 +1959,28 @@ void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 void host_x87_FILDq_BASE(codeblock_t *block, int base_reg) { if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/ + } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/ + } } void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg) { if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/ + } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/ + } } void host_x87_FLDCW(codeblock_t *block, void *p) { @@ -1648,10 +1988,12 @@ void host_x87_FLDCW(codeblock_t *block, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/ codegen_addlong(block, (uint32_t)p); } @@ -1659,16 +2001,28 @@ void host_x87_FLDCW(codeblock_t *block, void *p) void host_x87_FLDd_BASE(codeblock_t *block, int base_reg) { if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/ + } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/ + } } void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg) { if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/ + } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/ + } } #endif diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index aa1c885..b0a54af 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -5,16 +5,12 @@ #include "x87.h" #include "386_common.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" #include "codegen_backend_x86_ops.h" #include "codegen_ir_defs.h" -#define STACK_ARG0 (0) -#define STACK_ARG1 (4) -#define STACK_ARG2 (8) -#define STACK_ARG3 (12) - /*void codegen_debug() { pclog(" %04x:%04x : %08x %08x %08x %08x\n", CS, cpu_state.pc, AX, BX, CX, DX); @@ -726,32 +722,32 @@ static int codegen_FSUB(codeblock_t *block, uop_t *uop) static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) { - uint8_t *branch_offset; + uint32_t *branch_offset; host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_short(block); + branch_offset = host_x86_JZ_long(block); host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); host_x86_CALL(block, x86_int); host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; return 0; } static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) { - uint8_t *branch_offset; + uint32_t *branch_offset; host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_short(block); + branch_offset = host_x86_JZ_long(block); host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); host_x86_CALL(block, x86_int); host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0); host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0); host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); @@ -1268,12 +1264,12 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { - uint8_t *branch_offset; + uint32_t *branch_offset; /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); host_x86_TEST8_REG(block, tag_reg, tag_reg); - branch_offset = host_x86_JS_short(block); + branch_offset = host_x86_JS_long(block); /*There is no SSE instruction to convert a floating point value to a 64-bit integer. Instead we have to bounce through memory via x87.*/ @@ -1284,7 +1280,7 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); host_x87_FLDCW(block, &cpu_state.old_fp_control2); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; } else fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -2769,7 +2765,7 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int void codegen_set_jump_dest(codeblock_t *block, void *p) { - *(uint32_t *)p = (uintptr_t)&block->data[block_pos] - ((uintptr_t)p + 4); + *(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4); } #endif diff --git a/src/codegen_ir.c b/src/codegen_ir.c index bd0e541..97a2dc1 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -1,5 +1,6 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_ir.h" #include "codegen_reg.h" @@ -20,6 +21,8 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) int jump_target_at_end = -1; int c; + block_write_data = codeblock_allocator_get_ptr(block->head_mem_block); + block_pos = 0; codegen_backend_prologue(block); for (c = 0; c < ir->wr_pos; c++) @@ -114,7 +117,7 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) } codegen_backend_epilogue(block); - + block_write_data = NULL; // if (has_ea) // fatal("IR compilation complete\n"); } diff --git a/src/wx-sdl2-status.c b/src/wx-sdl2-status.c index 735fa44..71c01ac 100644 --- a/src/wx-sdl2-status.c +++ b/src/wx-sdl2-status.c @@ -14,6 +14,7 @@ #include "ide.h" #include "cdrom-image.h" #include "scsi_zip.h" +#include "codegen_allocator.h" #include "wx-common.h" drive_info_t drive_info[10]; @@ -135,7 +136,7 @@ int get_status(char* machine, char* device) "\n" "New blocks : %i\nOld blocks : %i\nRecompiled speed : %f MIPS\nAverage size : %f\n" - "Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS" + "Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS\nMem blocks used : %i (%g MB)" // "\nFully recompiled ins %% : %f%%" ,mips, flops, @@ -158,7 +159,9 @@ int get_status(char* machine, char* device) cpu_recomp_flushes_latched, cpu_recomp_evicted_latched, cpu_recomp_reuse_latched, cpu_recomp_removed_latched, - ((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq) + ((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq), + codegen_allocator_usage, + (double)(codegen_allocator_usage * MEM_BLOCK_SIZE) / (1024.0*1024.0) // ((double)cpu_recomp_full_ins_latched / (double)cpu_recomp_ins_latched) * 100.0 // cpu_reps_latched, cpu_notreps_latched );