From 5f391a199235b259243ce402e2a8242e65c501a1 Mon Sep 17 00:00:00 2001 From: TomW Date: Wed, 5 Aug 2015 20:31:20 +0100 Subject: [PATCH] Reduced number of unnecessary register loads in x86-64 recompiler. --- src/codegen.h | 1 + src/codegen_ops_arith.h | 6 ++-- src/codegen_ops_x86-64.h | 61 +++++++++++++++++++++++++++++++--------- src/codegen_x86-64.c | 4 +++ 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/codegen.h b/src/codegen.h index b6af088..04d5d00 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -164,5 +164,6 @@ extern int codegen_flags_changed; extern int codegen_fpu_entered; extern int codegen_fpu_loaded_iq[8]; +extern int codegen_reg_loaded[8]; #endif diff --git a/src/codegen_ops_arith.h b/src/codegen_ops_arith.h index 0a15d93..74f93f0 100644 --- a/src/codegen_ops_arith.h +++ b/src/codegen_ops_arith.h @@ -7,9 +7,8 @@ static uint32_t ropINC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin host_reg = LOAD_REG_W(opcode & 7); STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); - ADD_HOST_REG_IMM(host_reg, 1); + ADD_HOST_REG_IMM_W(host_reg, 1); STORE_IMM_ADDR_L((uint32_t)&flags_op2, 1); - AND_HOST_REG_IMM(host_reg, 0xffff); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_INC16); STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, host_reg); STORE_REG_W_RELEASE(host_reg); @@ -46,9 +45,8 @@ static uint32_t ropDEC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin host_reg = LOAD_REG_W(opcode & 7); STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, 1); + SUB_HOST_REG_IMM_W(host_reg, 1); STORE_IMM_ADDR_L((uint32_t)&flags_op2, 1); - AND_HOST_REG_IMM(host_reg, 0xffff); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_DEC16); STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, host_reg); STORE_REG_W_RELEASE(host_reg); diff --git a/src/codegen_ops_x86-64.h b/src/codegen_ops_x86-64.h index d4a0e1c..3b0ab9b 100644 --- a/src/codegen_ops_x86-64.h +++ b/src/codegen_ops_x86-64.h @@ -6,6 +6,9 @@ static void call(codeblock_t *block, uintptr_t func) { uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; + codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; + codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; + if (diff >= -0x80000000 && diff < 0x7fffffff) { addbyte(0xE8); /*CALL*/ @@ -23,6 +26,9 @@ static void call(codeblock_t *block, uintptr_t func) static void call_long(uintptr_t func) { + codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; + codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; + addbyte(0x48); /*MOV RAX, func*/ addbyte(0xb8); addquad(func); @@ -155,6 +161,9 @@ static void load_param_3_reg_64(int reg) static void CALL_FUNC(uintptr_t func) { + codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; + codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; + addbyte(0x48); /*MOV RAX, func*/ addbyte(0xb8); addquad(func); @@ -171,12 +180,16 @@ static int LOAD_REG_B(int reg) int host_reg = reg & 3; // host_reg_mapping[host_reg] = reg; - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint32_t)®s[reg & 3].w - (uint32_t)&EAX); + if (!codegen_reg_loaded[reg & 3]) + { + addbyte(0x44); /*MOVZX W[reg],host_reg*/ + addbyte(0x8b); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t)®s[host_reg & 3].b - (uint32_t)&EAX); + } + codegen_reg_loaded[reg & 3] = 1; + if (reg & 4) return host_reg | 0x18; @@ -187,12 +200,16 @@ static int LOAD_REG_W(int reg) int host_reg = reg; // host_reg_mapping[host_reg] = reg; - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint32_t)®s[reg & 7].w - (uint32_t)&EAX); + if (!codegen_reg_loaded[reg & 7]) + { + addbyte(0x44); /*MOVZX W[reg],host_reg*/ + addbyte(0x8b); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t)®s[reg & 7].w - (uint32_t)&EAX); + } + codegen_reg_loaded[reg & 7] = 1; + return host_reg | 8; } static int LOAD_REG_L(int reg) @@ -200,11 +217,16 @@ static int LOAD_REG_L(int reg) int host_reg = reg; // host_reg_mapping[host_reg] = reg; - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x8b); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint32_t)®s[reg & 7].w - (uint32_t)&EAX); + if (!codegen_reg_loaded[reg & 7])// || CS != 0x1ac7 || pc < 0x1340 || pc >= 0x1354) + { + addbyte(0x44); /*MOVZX W[reg],host_reg*/ + addbyte(0x8b); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t)®s[reg & 7].l - (uint32_t)&EAX); + } + codegen_reg_loaded[reg & 7] = 1; + return host_reg | 8; } @@ -282,12 +304,20 @@ static void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) addbyte(0x44); addbyte(0x89); addbyte(0xc0 | ((host_reg & 3) << 3)); + addbyte(0x88); /*MOV AL, AH*/ + addbyte(0xe0); + addbyte(0x41); /*MOV dest_reg, AL*/ + addbyte(0x88); + addbyte(0xc0 | (dest_reg & 7)); addbyte(0x88); /*MOVB regs[reg].b, AH*/ addbyte(0x65); addbyte((uint32_t)®s[guest_reg & 3].b - (uint32_t)&EAX); } else { + addbyte(0x45); /*MOVB dest_reg, host_reg*/ + addbyte(0x88); + addbyte(0xc0 | (dest_reg & 7) | ((host_reg & 7) << 3)); addbyte(0x44); /*MOVB regs[guest_reg].b, host_reg*/ addbyte(0x88); addbyte(0x45 | ((host_reg & 3) << 3)); @@ -302,6 +332,9 @@ static void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) addbyte(0xe8 | (host_reg & 7)); addbyte(8); } + addbyte(0x41); /*MOVB dest_reg, host_reg*/ + addbyte(0x88); + addbyte(0xc0 | (dest_reg & 7) | ((host_reg & 7) << 3)); addbyte(0x88); /*MOVB regs[guest_reg].b, host_reg*/ addbyte(0x45 | ((host_reg & 3) << 3)); addbyte((uint32_t)®s[guest_reg & 3].b - (uint32_t)&EAX); diff --git a/src/codegen_x86-64.c b/src/codegen_x86-64.c index 0b48fe4..c0f2388 100644 --- a/src/codegen_x86-64.c +++ b/src/codegen_x86-64.c @@ -28,6 +28,7 @@ int codegen_flags_changed = 0; int codegen_fpu_entered = 0; int codegen_fpu_loaded_iq[8]; +int codegen_reg_loaded[8]; x86seg *op_ea_seg; int op_ssegs; uint32_t op_old_pc; @@ -296,6 +297,9 @@ void codegen_block_init(uint32_t phys_addr) codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; _ds.checked = _es.checked = _fs.checked = _gs.checked = (cr0 & 1) ? 0 : 1; + + codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = + codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; } void codegen_block_remove()