Added recompiled versions of immediate->reg and reg->reg versions of MOV, ADD, SUB, CMP, AND, OR and XOR.

This commit is contained in:
SarahW 2018-07-08 16:36:11 +01:00
commit fc27be592c
17 changed files with 1150 additions and 52 deletions

View file

@ -24,7 +24,7 @@ wx-resources.cpp : pc.xrc
# PCem
pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \
cmd640.c codegen.c codegen_accumulate.c codegen_backend.c codegen_ir.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \
cmd640.c codegen.c codegen_accumulate.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_arith.c codegen_ops_logic.c codegen_ops_mov.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \
dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \
hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \
joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \

View file

@ -9,6 +9,7 @@
#include "codegen_accumulate.h"
#include "codegen_backend.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
int has_ea;
@ -252,6 +253,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
ir_data_t *ir = codegen_get_ir_data();
uint32_t op_pc = new_pc;
OpFn *op_table = x86_dynarec_opcodes;
RecompOpFn *recomp_op_table = recomp_opcodes;
int opcode_shift = 0;
int opcode_mask = 0x3ff;
uint32_t op_32 = use32;
@ -271,7 +273,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
{
case 0x0f:
op_table = x86_dynarec_opcodes_0f;
// recomp_op_table = recomp_opcodes_0f;
recomp_op_table = NULL;//recomp_opcodes_0f;
over = 1;
break;
@ -309,7 +311,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
case 0xd8:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16;
// recomp_op_table = recomp_opcodes_d8;
recomp_op_table = NULL;//recomp_opcodes_d8;
opcode_shift = 3;
opcode_mask = 0x1f;
over = 1;
@ -319,7 +321,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xd9:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16;
// recomp_op_table = recomp_opcodes_d9;
recomp_op_table = NULL;//recomp_opcodes_d9;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -328,7 +330,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xda:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16;
// recomp_op_table = recomp_opcodes_da;
recomp_op_table = NULL;//recomp_opcodes_da;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -337,7 +339,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xdb:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16;
// recomp_op_table = recomp_opcodes_db;
recomp_op_table = NULL;//recomp_opcodes_db;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -346,7 +348,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xdc:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16;
// recomp_op_table = recomp_opcodes_dc;
recomp_op_table = NULL;//recomp_opcodes_dc;
opcode_shift = 3;
opcode_mask = 0x1f;
over = 1;
@ -356,7 +358,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xdd:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16;
// recomp_op_table = recomp_opcodes_dd;
recomp_op_table = NULL;//recomp_opcodes_dd;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -365,7 +367,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xde:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16;
// recomp_op_table = recomp_opcodes_de;
recomp_op_table = NULL;//recomp_opcodes_de;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -374,7 +376,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xdf:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16;
// recomp_op_table = recomp_opcodes_df;
recomp_op_table = NULL;//recomp_opcodes_df;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -387,11 +389,11 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
case 0xf2: /*REPNE*/
op_table = x86_dynarec_opcodes_REPNE;
// recomp_op_table = recomp_opcodes_REPNE;
recomp_op_table = NULL;//recomp_opcodes_REPNE;
break;
case 0xf3: /*REPE*/
op_table = x86_dynarec_opcodes_REPE;
// recomp_op_table = recomp_opcodes_REPE;
recomp_op_table = NULL;//recomp_opcodes_REPE;
break;
default:
@ -421,8 +423,21 @@ generate_call:
(opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) ||
(op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80)))
codegen_accumulate_flush(ir);
// pclog("%04x:%08x : %02x\n", CS, new_pc, opcode);
if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff])
{
uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](block, ir, opcode, fetchdat, op_32, op_pc);
if (new_pc)
{
if (new_pc != -1)
uop_MOV_IMM(ir, IREG_pc, new_pc);
//pclog("%04x:%08x : %02x\n", CS, new_pc, opcode);
codegen_endpc = (cs + cpu_state.pc) + 8;
return;
}
}
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
if (!test_modrm ||

View file

@ -40,8 +40,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT)
#define OPCODE_AND_IMM (0x024 << 23)
#define OPCODE_EOR_IMM (0x0a4 << 23)
#define OPCODE_MOVK_W (0x0e5 << 23)
#define OPCODE_MOVZ_W (0x0a5 << 23)
#define OPCODE_ORR_IMM (0x064 << 23)
#define OPCODE_LDR_IMM_W (0x2e5 << 22)
#define OPCODE_LDP_POSTIDX_X (0x2a3 << 22)
@ -52,6 +54,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_ADD_LSL (0x058 << 21)
#define OPCODE_AND_LSL (0x050 << 21)
#define OPCODE_EOR_LSL (0x250 << 21)
#define OPCODE_ORR_LSL (0x150 << 21)
#define OPCODE_SUB_LSL (0x258 << 21)
@ -138,19 +141,26 @@ static inline int imm_is_imm12(uint32_t imm_data)
return 0;
}
void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
{
if ((int32_t)imm_data < 0)
if (!imm_data)
host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0);
else if ((int32_t)imm_data < 0 && imm_data != 0x80000000)
{
host_arm64_SUB_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data);
}
else if (!(imm_data & 0xff000000))
{
if (imm_data & 0xfff)
{
codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
if (imm_data & 0xfff000)
if (imm_data & 0xfff000)
codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
}
else if (imm_data & 0xfff000)
codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
}
else
@ -177,6 +187,10 @@ void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t
codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
}
}
void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
{
codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
}
void host_arm64_BLR(codeblock_t *block, int addr_reg)
{
@ -191,6 +205,23 @@ void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest)
codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg));
}
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
{
if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
{
codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f));
}
else
{
host_arm64_mov_imm(block, REG_W16, imm_data);
codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
}
}
void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
{
codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
}
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset)
{
if (!in_range7_x(offset))
@ -226,7 +257,8 @@ void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offs
void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift)
{
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
if (dst_reg != src_m_reg)
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
}
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data)
@ -262,6 +294,23 @@ void host_arm64_NOP(codeblock_t *block)
codegen_addlong(block, OPCODE_NOP);
}
void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
{
if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
{
codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f));
}
else
{
host_arm64_mov_imm(block, REG_W16, imm_data);
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
}
}
void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
{
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
}
void host_arm64_RET(codeblock_t *block, int reg)
{
codegen_addlong(block, OPCODE_RET | Rn(reg));
@ -295,15 +344,21 @@ void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int off
void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
{
if ((int32_t)imm_data < 0)
if (!imm_data)
host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0);
else if ((int32_t)imm_data < 0 && imm_data != 0x80000000)
{
host_arm64_ADD_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data);
}
else if (!(imm_data & 0xff000000))
{
if (imm_data & 0xfff)
{
codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
if (imm_data & 0xfff000)
if (imm_data & 0xfff000)
codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
}
else if (imm_data & 0xfff000)
codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
}
else
@ -313,6 +368,10 @@ void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t
codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
}
}
void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
{
codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
}
void host_arm64_call(codeblock_t *block, void *dst_addr)
{
@ -351,6 +410,11 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_AND(codeblock_t *block, uop_t *uop)
{
host_arm64_AND_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0);
return 0;
}
static int codegen_AND_IMM(codeblock_t *block, uop_t *uop)
{
host_arm64_AND_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
@ -410,6 +474,17 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_OR(codeblock_t *block, uop_t *uop)
{
host_arm64_ORR_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0);
return 0;
}
static int codegen_OR_IMM(codeblock_t *block, uop_t *uop)
{
host_arm64_ORR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
return 0;
}
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
{
host_arm64_mov_imm(block, REG_W16, uop->imm_data);
@ -433,6 +508,28 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_SUB(codeblock_t *block, uop_t *uop)
{
host_arm64_SUB_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0);
return 0;
}
static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop)
{
host_arm64_SUB_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
return 0;
}
static int codegen_XOR(codeblock_t *block, uop_t *uop)
{
host_arm64_EOR_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0);
return 0;
}
static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop)
{
host_arm64_EOR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
return 0;
}
const uOpFn uop_handlers[UOP_MAX] =
{
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
@ -452,7 +549,14 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_ADD & UOP_MASK] = codegen_ADD,
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
[UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT,
[UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM
[UOP_AND & UOP_MASK] = codegen_AND,
[UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM,
[UOP_OR & UOP_MASK] = codegen_OR,
[UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM,
[UOP_SUB & UOP_MASK] = codegen_SUB,
[UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM,
[UOP_XOR & UOP_MASK] = codegen_XOR,
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM
};
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)

View file

@ -34,10 +34,16 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT)
#define OPCODE_AND_REG (0x00 << OPCODE_SHIFT)
#define OPCODE_B (0xa0 << OPCODE_SHIFT)
#define OPCODE_BIC_IMM (0x3c << OPCODE_SHIFT)
#define OPCODE_BIC_REG (0x1c << OPCODE_SHIFT)
#define OPCODE_EOR_IMM (0x22 << OPCODE_SHIFT)
#define OPCODE_EOR_REG (0x02 << OPCODE_SHIFT)
#define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT)
#define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT)
#define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT)
#define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT)
#define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT)
#define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT)
#define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT)
#define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT)
#define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT)
@ -132,13 +138,15 @@ static inline int in_range(void *addr, void *base)
void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
{
uint32_t arm_imm;
if ((int32_t)imm < 0)
if ((int32_t)imm < 0 && imm != 0x80000000)
{
host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t)imm);
}
@ -167,6 +175,10 @@ void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm
{
codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
}
else if (get_arm_imm(~imm, &arm_imm))
{
codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
}
else
{
int offset = add_literal(block, imm);
@ -195,6 +207,27 @@ void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr)
codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset));
}
void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
{
uint32_t arm_imm;
if (get_arm_imm(imm, &arm_imm))
{
codegen_addlong(block, COND_AL | OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
}
else
{
int offset = add_literal(block, imm);
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
host_arm_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
}
}
void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_EOR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
}
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask)
{
codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask);
@ -225,6 +258,27 @@ void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shif
codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift));
}
void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
{
uint32_t arm_imm;
if (get_arm_imm(imm, &arm_imm))
{
codegen_addlong(block, COND_AL | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
}
else
{
int offset = add_literal(block, imm);
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
host_arm_ORR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
}
}
void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
{
codegen_addlong(block, COND_AL | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
}
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask)
{
codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask);
@ -244,7 +298,7 @@ void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm
{
uint32_t arm_imm;
if ((int32_t)imm < 0)
if ((int32_t)imm < 0 && imm != 0x80000000)
{
host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t)imm);
}
@ -288,19 +342,22 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop)
host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0);
return 0;
}
static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop)
{
host_arm_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
return 0;
}
static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop)
{
host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data);
return 0;
}
static int codegen_AND(codeblock_t *block, uop_t *uop)
{
host_arm_AND_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0);
return 0;
}
static int codegen_AND_IMM(codeblock_t *block, uop_t *uop)
{
host_arm_AND_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
@ -398,6 +455,17 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_OR(codeblock_t *block, uop_t *uop)
{
host_arm_ORR_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0);
return 0;
}
static int codegen_OR_IMM(codeblock_t *block, uop_t *uop)
{
host_arm_ORR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
return 0;
}
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
{
uint32_t arm_imm;
@ -427,6 +495,28 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_SUB(codeblock_t *block, uop_t *uop)
{
host_arm_SUB_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0);
return 0;
}
static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop)
{
host_arm_SUB_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
return 0;
}
static int codegen_XOR(codeblock_t *block, uop_t *uop)
{
host_arm_EOR_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0);
return 0;
}
static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop)
{
host_arm_EOR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
return 0;
}
const uOpFn uop_handlers[UOP_MAX] =
{
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
@ -446,7 +536,14 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_ADD & UOP_MASK] = codegen_ADD,
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
[UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT,
[UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM
[UOP_AND & UOP_MASK] = codegen_AND,
[UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM,
[UOP_OR & UOP_MASK] = codegen_OR,
[UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM,
[UOP_SUB & UOP_MASK] = codegen_SUB,
[UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM,
[UOP_XOR & UOP_MASK] = codegen_XOR,
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM
};
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)

View file

@ -11,6 +11,12 @@
#define STACK_ARG2 (8)
#define STACK_ARG3 (12)
#define RM_OP_ADD 0x00
#define RM_OP_OR 0x08
#define RM_OP_AND 0x20
#define RM_OP_SUB 0x28
#define RM_OP_XOR 0x30
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
{
block->data[block_pos++] = val;
@ -118,7 +124,7 @@ static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg,
if (is_imm8(imm_data))
{
codegen_addbyte3(block, 0x83, 0xc0 | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/
}
else
{
@ -129,11 +135,18 @@ static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg,
}
else
{
codegen_addbyte2(block, 0x81, 0xc0 | (dst_reg & 7)); /*ADD dst_reg, imm_data*/
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/
codegen_addlong(block, imm_data);
}
}
}
static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n");
codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/
}
static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
{
@ -142,7 +155,7 @@ static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg,
if (is_imm8(imm_data))
{
codegen_addbyte3(block, 0x83, 0xe0 | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/
}
else
{
@ -153,18 +166,17 @@ static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg,
}
else
{
codegen_addbyte2(block, 0x81, 0xe0 | (dst_reg & 7)); /*AND dst_reg, imm_data*/
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/
codegen_addlong(block, imm_data);
}
}
}
static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
static void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n");
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg_a\n");
codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | (src_reg_b & 7)); /*ADD dst_reg, src_reg_b*/
codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/
}
static void host_x86_CALL(codeblock_t *block, void *p)
@ -348,6 +360,68 @@ static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_
}
}
static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
{
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n");
if (is_imm8(imm_data))
{
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_addbyte(block, 0x0d); /*OR EAX, imm_data*/
codegen_addlong(block, imm_data);
}
else
{
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/
codegen_addlong(block, imm_data);
}
}
}
static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
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_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/
}
static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
{
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n");
if (is_imm8(imm_data))
{
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_addbyte(block, 0x2d); /*SUB EAX, imm_data*/
codegen_addlong(block, imm_data);
}
else
{
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/
codegen_addlong(block, imm_data);
}
}
}
static void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n");
codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/
}
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
static void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg)
@ -357,6 +431,37 @@ static void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg)
codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/
}
static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
{
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n");
if (is_imm8(imm_data))
{
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_addbyte(block, 0x35); /*XOR EAX, imm_data*/
codegen_addlong(block, imm_data);
}
else
{
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/
codegen_addlong(block, imm_data);
}
}
}
static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
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_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/
}
static int codegen_ADD(codeblock_t *block, uop_t *uop)
{
@ -382,6 +487,12 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_AND(codeblock_t *block, uop_t *uop)
{
host_x86_AND32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_AND_IMM(codeblock_t *block, uop_t *uop)
{
host_x86_AND32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
@ -442,6 +553,17 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_OR(codeblock_t *block, uop_t *uop)
{
host_x86_OR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_OR_IMM(codeblock_t *block, uop_t *uop)
{
host_x86_OR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
return 0;
}
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
{
if (((uintptr_t)uop->p) >> 32)
@ -457,6 +579,34 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_SUB(codeblock_t *block, uop_t *uop)
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real);
host_x86_SUB32_REG_REG(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop)
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real);
host_x86_SUB32_REG_IMM(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->imm_data);
return 0;
}
static int codegen_XOR(codeblock_t *block, uop_t *uop)
{
host_x86_XOR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop)
{
host_x86_XOR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
return 0;
}
const uOpFn uop_handlers[UOP_MAX] =
{
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
@ -476,7 +626,14 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_ADD & UOP_MASK] = codegen_ADD,
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
[UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT,
[UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM
[UOP_AND & UOP_MASK] = codegen_AND,
[UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM,
[UOP_OR & UOP_MASK] = codegen_OR,
[UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM,
[UOP_SUB & UOP_MASK] = codegen_SUB,
[UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM,
[UOP_XOR & UOP_MASK] = codegen_XOR,
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM
};
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)

View file

@ -11,6 +11,12 @@
#define STACK_ARG2 (8)
#define STACK_ARG3 (12)
#define RM_OP_ADD 0x00
#define RM_OP_OR 0x08
#define RM_OP_AND 0x20
#define RM_OP_SUB 0x28
#define RM_OP_XOR 0x30
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
{
block->data[block_pos++] = val;
@ -101,7 +107,7 @@ static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg,
if (is_imm8(imm_data))
{
codegen_addbyte3(block, 0x83, 0xc0 | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/
}
else
{
@ -112,31 +118,7 @@ static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg,
}
else
{
codegen_addbyte2(block, 0x81, 0xc0 | dst_reg); /*ADD dst_reg, imm_data*/
codegen_addlong(block, imm_data);
}
}
}
static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
{
if (dst_reg != src_reg)
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n");
if (is_imm8(imm_data))
{
codegen_addbyte3(block, 0x83, 0xe0 | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/
}
else
{
if (dst_reg == REG_EAX)
{
codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/
codegen_addlong(block, imm_data);
}
else
{
codegen_addbyte2(block, 0x81, 0xe0 | dst_reg); /*AND dst_reg, imm_data*/
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/
codegen_addlong(block, imm_data);
}
}
@ -147,7 +129,39 @@ static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_
if (dst_reg != src_reg_a)
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n");
codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | src_reg_b); /*ADD dst_reg, src_reg_b*/
codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/
}
static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
{
if (dst_reg != src_reg)
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n");
if (is_imm8(imm_data))
{
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_addbyte(block, 0x25); /*AND EAX, imm_data*/
codegen_addlong(block, imm_data);
}
else
{
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/
codegen_addlong(block, imm_data);
}
}
}
static void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
if (dst_reg != src_reg_a)
fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n");
codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/
}
static void host_x86_CALL(codeblock_t *block, void *p)
@ -284,13 +298,109 @@ static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_
}
}
static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
if (dst_reg != src_reg_a)
fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n");
codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/
}
static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
{
if (dst_reg != src_reg)
fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n");
if (is_imm8(imm_data))
{
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_addbyte(block, 0x0d); /*OR EAX, imm_data*/
codegen_addlong(block, imm_data);
}
else
{
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/
codegen_addlong(block, imm_data);
}
}
}
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
{
if (dst_reg != src_reg)
fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n");
if (is_imm8(imm_data))
{
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_addbyte(block, 0x2d); /*SUB EAX, imm_data*/
codegen_addlong(block, imm_data);
}
else
{
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/
codegen_addlong(block, imm_data);
}
}
}
static void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
if (dst_reg != src_reg_a)
fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg_a\n");
codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/
}
static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
{
codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/
}
static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
if (dst_reg != src_reg_a)
fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n");
codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/
}
static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
{
if (dst_reg != src_reg)
fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n");
if (is_imm8(imm_data))
{
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_addbyte(block, 0x35); /*XOR EAX, imm_data*/
codegen_addlong(block, imm_data);
}
else
{
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/
codegen_addlong(block, imm_data);
}
}
}
/*void codegen_debug()
{
pclog(" %04x:%04x : %08x %08x %08x %08x\n", CS, cpu_state.pc, AX, BX, CX, DX);
@ -320,6 +430,12 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_AND(codeblock_t *block, uop_t *uop)
{
host_x86_AND32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_AND_IMM(codeblock_t *block, uop_t *uop)
{
host_x86_AND32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
@ -373,6 +489,17 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_OR(codeblock_t *block, uop_t *uop)
{
host_x86_OR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_OR_IMM(codeblock_t *block, uop_t *uop)
{
host_x86_OR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
return 0;
}
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
{
host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data);
@ -384,6 +511,34 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_SUB(codeblock_t *block, uop_t *uop)
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real);
host_x86_SUB32_REG_REG(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop)
{
if (uop->dest_reg_a_real != uop->src_reg_a_real)
host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real);
host_x86_SUB32_REG_IMM(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->imm_data);
return 0;
}
static int codegen_XOR(codeblock_t *block, uop_t *uop)
{
host_x86_XOR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop)
{
host_x86_XOR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data);
return 0;
}
const uOpFn uop_handlers[UOP_MAX] =
{
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
@ -403,7 +558,14 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_ADD & UOP_MASK] = codegen_ADD,
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
[UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT,
[UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM
[UOP_AND & UOP_MASK] = codegen_AND,
[UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM,
[UOP_OR & UOP_MASK] = codegen_OR,
[UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM,
[UOP_SUB & UOP_MASK] = codegen_SUB,
[UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM,
[UOP_XOR & UOP_MASK] = codegen_XOR,
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM
};
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)

View file

@ -35,10 +35,17 @@
#define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22)
#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30)
#define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31)
#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32)
#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33)
#define UOP_AND (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32)
#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33)
#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x34)
#define UOP_OR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x35)
#define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36)
#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37)
#define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38)
#define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39)
#define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a)
#define UOP_MAX 0x34
#define UOP_MAX 0x3b
#define UOP_MASK 0xffff
@ -175,9 +182,16 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p
#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm)
#define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm)
#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm)
#define uop_ADD_LSHIFT(ir, dst_reg, src_reg_a, src_reg_b, shift) uop_gen_reg_dst_src2_imm(UOP_ADD_LSHIFT, ir, dst_reg, src_reg_a, src_reg_b, shift)
#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm)
#define uop_AND(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_AND, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm)
#define uop_OR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_OR, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_OR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_OR_IMM, ir, dst_reg, src_reg, imm)
#define uop_SUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_SUB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_SUB_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SUB_IMM, ir, dst_reg, src_reg, imm)
#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm)
#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p)
#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p)
@ -189,6 +203,7 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p
#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm)
#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm)
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p);
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg);

54
src/codegen_ops.c Normal file
View file

@ -0,0 +1,54 @@
#include "ibm.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_arith.h"
#include "codegen_ops_logic.h"
#include "codegen_ops_mov.h"
RecompOpFn recomp_opcodes[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, ropADD_l_rmw, NULL, ropADD_l_rm, NULL, ropADD_EAX_imm, NULL, NULL, NULL, ropOR_l_rmw, NULL, ropOR_l_rm, NULL, ropOR_EAX_imm, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, ropAND_l_rmw, NULL, ropAND_l_rm, NULL, ropAND_EAX_imm, NULL, NULL, NULL, ropSUB_l_rmw, NULL, ropSUB_l_rm, NULL, ropSUB_EAX_imm, NULL, NULL,
/*30*/ NULL, ropXOR_l_rmw, NULL, ropXOR_l_rm, NULL, ropXOR_EAX_imm, NULL, NULL, NULL, ropCMP_l_rmw, NULL, ropCMP_l_rm, NULL, ropCMP_EAX_imm, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, rop81_l, NULL, rop83_l, NULL, NULL, NULL, NULL, NULL, ropMOV_l_r, NULL, ropMOV_r_l, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 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*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};

View file

@ -3,10 +3,12 @@
#include "codegen.h"
typedef uint32_t (*RecompOpFn)(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block);
struct ir_data_t;
typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
extern RecompOpFn recomp_opcodes[512];
extern RecompOpFn recomp_opcodes_0f[512];
/*extern RecompOpFn recomp_opcodes_0f[512];
extern RecompOpFn recomp_opcodes_d8[512];
extern RecompOpFn recomp_opcodes_d9[512];
extern RecompOpFn recomp_opcodes_da[512];
@ -15,8 +17,8 @@ extern RecompOpFn recomp_opcodes_dc[512];
extern RecompOpFn recomp_opcodes_dd[512];
extern RecompOpFn recomp_opcodes_de[512];
extern RecompOpFn recomp_opcodes_df[512];
RecompOpFn recomp_opcodes_REPE[512];
RecompOpFn recomp_opcodes_REPNE[512];
extern RecompOpFn recomp_opcodes_REPE[512];
extern RecompOpFn recomp_opcodes_REPNE[512];*/
#define REG_EAX 0
#define REG_ECX 1

285
src/codegen_ops_arith.c Normal file
View file

@ -0,0 +1,285 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_arith.h"
uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
fetchdat = fastreadl(cs + op_pc);
uop_MOV(ir, IREG_flags_op1, IREG_EAX);
uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
uop_MOV_IMM(ir, IREG_flags_op2, fetchdat);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32);
uop_MOV(ir, IREG_flags_res, IREG_EAX);
codegen_flags_changed = 1;
return op_pc + 4;
}
uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg));
uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg));
uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
fetchdat = fastreadl(cs + op_pc);
uop_MOV(ir, IREG_flags_op1, IREG_EAX);
uop_SUB_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat);
uop_MOV_IMM(ir, IREG_flags_op2, fetchdat);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
codegen_flags_changed = 1;
return op_pc + 4;
}
uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg));
uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg));
uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
fetchdat = fastreadl(cs + op_pc);
uop_MOV(ir, IREG_flags_op1, IREG_EAX);
uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
uop_MOV_IMM(ir, IREG_flags_op2, fetchdat);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
uop_MOV(ir, IREG_flags_res, IREG_EAX);
codegen_flags_changed = 1;
return op_pc + 4;
}
uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg));
uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg));
uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uint32_t imm;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
switch (fetchdat & 0x38)
{
case 0x00: /*ADD*/
imm = fastreadl(cs + op_pc + 1);
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x08: /*OR*/
imm = fastreadl(cs + op_pc + 1);
uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x20: /*AND*/
imm = fastreadl(cs + op_pc + 1);
uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x28: /*SUB*/
imm = fastreadl(cs + op_pc + 1);
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x30: /*XOR*/
imm = fastreadl(cs + op_pc + 1);
uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x38: /*CMP*/
imm = fastreadl(cs + op_pc + 1);
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
break;
default:
return 0;
}
codegen_flags_changed = 1;
return op_pc + 5;
}
uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uint32_t imm;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
switch (fetchdat & 0x38)
{
case 0x00: /*ADD*/
imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1);
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x08: /*OR*/
imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1);
uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x20: /*AND*/
imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1);
uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x28: /*SUB*/
imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1);
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x30: /*XOR*/
imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1);
uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
break;
case 0x38: /*CMP*/
imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1);
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm);
uop_MOV_IMM(ir, IREG_flags_op2, imm);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
break;
default:
return 0;
}
codegen_flags_changed = 1;
return op_pc + 2;
}

14
src/codegen_ops_arith.h Normal file
View file

@ -0,0 +1,14 @@
uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

129
src/codegen_ops_logic.c Normal file
View file

@ -0,0 +1,129 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_logic.h"
uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
fetchdat = fastreadl(cs + op_pc);
uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_EAX);
codegen_flags_changed = 1;
return op_pc + 4;
}
uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
fetchdat = fastreadl(cs + op_pc);
uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_EAX);
codegen_flags_changed = 1;
return op_pc + 4;
}
uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
fetchdat = fastreadl(cs + op_pc);
uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_EAX);
codegen_flags_changed = 1;
return op_pc + 4;
}
uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}

11
src/codegen_ops_logic.h Normal file
View file

@ -0,0 +1,11 @@
uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

48
src/codegen_ops_mov.c Normal file
View file

@ -0,0 +1,48 @@
#include "ibm.h"
#include "x86.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_mov.h"
uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
fetchdat = fastreadl(cs + op_pc);
uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat);
return op_pc + 4;
}
uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = (fetchdat >> 3) & 7;
uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg));
}
else
return 0;
return op_pc + 1;
}
uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg));
}
else
return 0;
return op_pc + 1;
}

3
src/codegen_ops_mov.h Normal file
View file

@ -0,0 +1,3 @@
uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View file

@ -200,13 +200,13 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg)
host_regs_locked |= (1 << c);
// fatal("codegen_reg_alloc_read_reg - read %i.%i to %i\n", ir_reg.reg,ir_reg.version, c);
// codegen_reg_writeback(block, c);
host_reg_dirty[c] = 0;
}
reg_version_refcount[host_regs[c].reg][host_regs[c].version]--;
if (reg_version_refcount[host_regs[c].reg][host_regs[c].version] < 0)
fatal("codegen_reg_alloc_read_reg - refcount < 0\n");
host_reg_dirty[c] = 0;
// pclog(" codegen_reg_alloc_read_reg: %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]);
return codegen_host_reg_list[c];
}

View file

@ -48,6 +48,8 @@ enum
IREG_INVALID = 255
};
#define IREG_32(reg) ((reg) + IREG_EAX)
extern uint8_t reg_last_version[IREG_COUNT];
extern uint8_t reg_version_refcount[IREG_COUNT][256];