diff --git a/src/codegen.h b/src/codegen.h index 5d758d9..23182b4 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -122,7 +122,7 @@ static inline void addword(uint16_t val) { *(uint16_t *)&codeblock[block_current].data[block_pos] = val; block_pos += 2; - if (block_pos >= 1760) + if (block_pos >= 1720) { CPU_BLOCK_END(); } @@ -132,7 +132,7 @@ static inline void addlong(uint32_t val) { *(uint32_t *)&codeblock[block_current].data[block_pos] = val; block_pos += 4; - if (block_pos >= 1760) + if (block_pos >= 1720) { CPU_BLOCK_END(); } @@ -142,7 +142,7 @@ static inline void addquad(uint64_t val) { *(uint64_t *)&codeblock[block_current].data[block_pos] = val; block_pos += 8; - if (block_pos >= 1760) + if (block_pos >= 1720) { CPU_BLOCK_END(); } diff --git a/src/codegen_ops.c b/src/codegen_ops.c index e3dc538..af46820 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -18,6 +18,7 @@ #include "codegen_ops_fpu.h" #include "codegen_ops_jump.h" #include "codegen_ops_logic.h" +#include "codegen_ops_misc.h" #include "codegen_ops_mov.h" #include "codegen_ops_shift.h" #include "codegen_ops_stack.h" @@ -27,8 +28,8 @@ RecompOpFn recomp_opcodes[512] = { /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, NULL, NULL, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, NULL, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_16, NULL, /*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL, /*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL, @@ -38,19 +39,19 @@ RecompOpFn recomp_opcodes[512] = /*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE, /*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_b, ropXCHG_w, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, ropLEA_w, NULL, NULL, -/*90*/ NULL, ropXCHG_AX_CX, ropXCHG_AX_DX, ropXCHG_AX_BX, ropXCHG_AX_SP, ropXCHG_AX_BP, ropXCHG_AX_SI, ropXCHG_AX_DI, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropNOP, ropXCHG_AX_CX, ropXCHG_AX_DX, ropXCHG_AX_BX, ropXCHG_AX_SP, ropXCHG_AX_BP, ropXCHG_AX_SI, ropXCHG_AX_DI, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropMOV_AL_a, ropMOV_AX_a, ropMOV_a_AL, ropMOV_a_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, /*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropD0, ropD1_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, NULL, NULL, ropCLD, ropSTD, NULL, ropFF_16, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, NULL, NULL, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, NULL, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_32, NULL, /*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL, /*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL, @@ -60,14 +61,14 @@ RecompOpFn recomp_opcodes[512] = /*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE, /*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_b, ropXCHG_l, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, ropLEA_l, NULL, NULL, -/*90*/ NULL, ropXCHG_EAX_ECX,ropXCHG_EAX_EDX,ropXCHG_EAX_EBX,ropXCHG_EAX_ESP,ropXCHG_EAX_EBP,ropXCHG_EAX_ESI,ropXCHG_EAX_EDI,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropNOP, ropXCHG_EAX_ECX,ropXCHG_EAX_EDX,ropXCHG_EAX_EBX,ropXCHG_EAX_ESP,ropXCHG_EAX_EBP,ropXCHG_EAX_ESI,ropXCHG_EAX_EDI,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropMOV_AL_a, ropMOV_EAX_a, ropMOV_a_AL, ropMOV_a_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, /*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropD0, ropD1_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, NULL, NULL, ropCLD, ropSTD, NULL, ropFF_32 }; RecompOpFn recomp_opcodes_0f[512] = diff --git a/src/codegen_ops_misc.h b/src/codegen_ops_misc.h new file mode 100644 index 0000000..4116acb --- /dev/null +++ b/src/codegen_ops_misc.h @@ -0,0 +1,115 @@ +static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + return op_pc; +} + +static uint32_t ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + CLEAR_BITS((uintptr_t)&flags, D_FLAG); + return op_pc; +} +static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + SET_BITS((uintptr_t)&flags, D_FLAG); + return op_pc; +} + +static uint32_t codegen_temp; +static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg; + + if ((fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20)// && (fetchdat & 0x38) != 0x30) + return 0; + + if ((fetchdat & 0xc0) == 0xc0) + { + host_reg = LOAD_REG_W(fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_W(target_seg); + host_reg = 0; + } + + switch (fetchdat & 0x38) + { + case 0x10: /*CALL*/ + STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, host_reg); + RELEASE_REG(host_reg); + + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + host_reg = LOAD_REG_IMM(op_pc + 1); + MEM_STORE_ADDR_EA_W(&_ss, host_reg); + SP_MODIFY(-2); + + host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp); + STORE_HOST_REG_ADDR_W((uintptr_t)&pc, host_reg); + return -1; + + case 0x20: /*JMP*/ + STORE_HOST_REG_ADDR((uintptr_t)&pc, host_reg); + return -1; + + case 0x30: /*PUSH*/ + if (!host_reg) + host_reg = LOAD_HOST_REG(host_reg); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + MEM_STORE_ADDR_EA_W(&_ss, host_reg); + SP_MODIFY(-2); + return op_pc + 1; + } +} +static uint32_t ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg; + + if ((fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20)// && (fetchdat & 0x38) != 0x30) + return 0; + + if ((fetchdat & 0xc0) == 0xc0) + { + host_reg = LOAD_REG_L(fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_L(target_seg); + host_reg = 0; + } + + switch (fetchdat & 0x38) + { + case 0x10: /*CALL*/ + STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, host_reg); + RELEASE_REG(host_reg); + + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + host_reg = LOAD_REG_IMM(op_pc + 1); + MEM_STORE_ADDR_EA_L(&_ss, host_reg); + SP_MODIFY(-4); + + host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp); + STORE_HOST_REG_ADDR((uintptr_t)&pc, host_reg); + return -1; + + case 0x20: /*JMP*/ + STORE_HOST_REG_ADDR((uintptr_t)&pc, host_reg); + return -1; + + case 0x30: /*PUSH*/ + if (!host_reg) + host_reg = LOAD_HOST_REG(host_reg); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + MEM_STORE_ADDR_EA_L(&_ss, host_reg); + SP_MODIFY(-4); + return op_pc + 1; + } +} diff --git a/src/codegen_ops_stack.h b/src/codegen_ops_stack.h index 6ac658f..712fde9 100644 --- a/src/codegen_ops_stack.h +++ b/src/codegen_ops_stack.h @@ -217,3 +217,34 @@ static uint32_t ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, u return op_pc; } + +#define ROP_PUSH_SEG(seg) \ +static uint32_t ropPUSH_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ +{ \ + int host_reg; \ + \ + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(-2); \ + host_reg = LOAD_VAR_W((uintptr_t)&seg); \ + MEM_STORE_ADDR_EA_W(&_ss, host_reg); \ + SP_MODIFY(-2); \ + \ + return op_pc; \ +} \ +static uint32_t ropPUSH_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ +{ \ + int host_reg; \ + \ + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(-4); \ + host_reg = LOAD_VAR_W((uintptr_t)&seg); \ + MEM_STORE_ADDR_EA_L(&_ss, host_reg); \ + SP_MODIFY(-4); \ + \ + return op_pc; \ +} + +ROP_PUSH_SEG(CS) +ROP_PUSH_SEG(DS) +ROP_PUSH_SEG(ES) +ROP_PUSH_SEG(SS) diff --git a/src/codegen_ops_x86-64.h b/src/codegen_ops_x86-64.h index 4561088..bbc7cd7 100644 --- a/src/codegen_ops_x86-64.h +++ b/src/codegen_ops_x86-64.h @@ -3008,6 +3008,16 @@ static int COPY_REG(int src_reg) return REG_ECX | (src_reg & 0x10); } +static int LOAD_HOST_REG(int host_reg) +{ + if (host_reg & 8) + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | REG_ECX | ((host_reg & 7) << 3)); + + return REG_ECX | (host_reg & 0x10); +} + static int ZERO_EXTEND_W_B(int reg) { if (reg & 0x10) @@ -4298,3 +4308,42 @@ static void FP_COMPARE_IL() addbyte(0xc8); FP_COMPARE_MEM(); } + +static void SET_BITS(uintptr_t addr, uint32_t val) +{ + if (val & ~0xff) + { + addbyte(0x81); + addbyte(0x0c); + addbyte(0x25); + addlong(addr); + addlong(val); + } + else + { + addbyte(0x80); + addbyte(0x0c); + addbyte(0x25); + addlong(addr); + addbyte(val); + } +} +static void CLEAR_BITS(uintptr_t addr, uint32_t val) +{ + if (val & ~0xff) + { + addbyte(0x81); + addbyte(0x24); + addbyte(0x25); + addlong(addr); + addlong(~val); + } + else + { + addbyte(0x80); + addbyte(0x24); + addbyte(0x25); + addlong(addr); + addbyte(~val); + } +} diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h index 110cb14..5b630b0 100644 --- a/src/codegen_ops_x86.h +++ b/src/codegen_ops_x86.h @@ -144,6 +144,17 @@ static int LOAD_REG_IMM(uint32_t imm) return host_reg; } +static int LOAD_HOST_REG(int host_reg) +{ + int new_host_reg = find_host_reg(); + host_reg_mapping[new_host_reg] = reg; + + addbyte(0x89); /*MOV new_host_reg, host_reg*/ + addbyte(0xc0 | (host_reg << 3) | new_host_reg); + + return new_host_reg; +} + static void STORE_REG_B_RELEASE(int host_reg) { addbyte(0x88); /*MOVB [reg],host_reg*/ @@ -2950,3 +2961,38 @@ static int COPY_REG(int src_reg) { return src_reg; } + +static void SET_BITS(uintptr_t addr, uint32_t val) +{ + if (val & ~0xff) + { + addbyte(0x81); + addbyte(0x0d); + addlong(addr); + addlong(val); + } + else + { + addbyte(0x80); + addbyte(0x0d); + addlong(addr); + addbyte(val); + } +} +static void CLEAR_BITS(uintptr_t addr, uint32_t val) +{ + if (val & ~0xff) + { + addbyte(0x81); + addbyte(0x25); + addlong(addr); + addlong(~val); + } + else + { + addbyte(0x80); + addbyte(0x25); + addlong(addr); + addbyte(~val); + } +}