Rework self modifying code handling.

Code blocks now have a varying level of granularity in the page and dirty masks.
Most blocks have 64-byte granularity, but blocks that are repeatedly modified
drop to 1-byte granularity. This reduces the maximum size of the affected block
significantly, but reduces recompilation due to data located too close to code.

If the block is still marked as dirty, then it is recompiled without any
immediate instruction parameters being baked into the recompiled code, instead
being fetched from the RAM array as needed. This severely reduces recompilation
rates on some SMC-heavy games, eg Duke Nukem 3D, System Shock, Screamer etc,
giving a major speedup.
This commit is contained in:
SarahW 2019-03-16 14:53:26 +00:00
commit ab124776a0
36 changed files with 1719 additions and 233 deletions

View file

@ -14,6 +14,7 @@ uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
uop_MOV_IMM(ir, IREG_8(opcode & 7), imm);
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
@ -22,14 +23,21 @@ uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
uop_MOV_IMM(ir, IREG_16(opcode & 7), imm);
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
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);
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_32(opcode & 7), cs + op_pc);
}
else
{
fetchdat = fastreadl(cs + op_pc);
uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat);
codegen_mark_code_present(block, cs+op_pc, 4);
}
return op_pc + 4;
}
@ -39,6 +47,9 @@ uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
{
int src_reg = (fetchdat >> 3) & 7;
// if (block->phys == 0x49a400)
// pclog("ropMOVb_rmarkcode %08x 1\n", cs+op_pc);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
@ -61,6 +72,7 @@ uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
@ -83,6 +95,7 @@ uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
@ -105,6 +118,7 @@ uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
@ -126,6 +140,7 @@ uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
@ -147,6 +162,7 @@ uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
@ -178,6 +194,7 @@ uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
codegen_check_seg_read(block, ir, op_ea_seg);
uop_MEM_LOAD_ABS(ir, IREG_AL, ireg_seg_base(op_ea_seg), addr);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
@ -193,20 +210,37 @@ uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
codegen_check_seg_read(block, ir, op_ea_seg);
uop_MEM_LOAD_ABS(ir, IREG_AX, ireg_seg_base(op_ea_seg), addr);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr;
uint32_t addr = 0;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + op_pc);
}
else
{
addr = fastreadl(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 4);
}
}
else
{
addr = fastreadw(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 2);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_read(block, ir, op_ea_seg);
uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr);
if ((block->flags & CODEBLOCK_NO_IMMEDIATES) && (op_32 & 0x200))
uop_MEM_LOAD_REG(ir, IREG_EAX, ireg_seg_base(op_ea_seg), IREG_eaaddr);
else
uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
@ -224,6 +258,7 @@ uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
codegen_check_seg_write(block, ir, op_ea_seg);
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AL);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
@ -239,6 +274,7 @@ uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
codegen_check_seg_write(block, ir, op_ea_seg);
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AX);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
@ -254,6 +290,7 @@ uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
codegen_check_seg_write(block, ir, op_ea_seg);
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_EAX);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
@ -262,6 +299,7 @@ uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
x86seg *target_seg;
uint8_t imm;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
@ -278,6 +316,7 @@ uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}
uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
@ -285,6 +324,7 @@ uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
x86seg *target_seg;
uint16_t imm;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
@ -301,6 +341,7 @@ uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
}
codegen_mark_code_present(block, cs+op_pc+1, 2);
return op_pc + 3;
}
uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
@ -308,6 +349,7 @@ uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
x86seg *target_seg;
uint32_t imm;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
@ -324,6 +366,7 @@ uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
}
codegen_mark_code_present(block, cs+op_pc+1, 4);
return op_pc + 5;
}
@ -331,6 +374,7 @@ uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
{
int src_reg;
codegen_mark_code_present(block, cs+op_pc, 1);
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
@ -377,6 +421,7 @@ uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
{
int src_reg;
codegen_mark_code_present(block, cs+op_pc, 1);
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
@ -423,7 +468,8 @@ uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
{
int src_reg;
x86seg *rseg;
codegen_mark_code_present(block, cs+op_pc, 1);
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
@ -468,6 +514,7 @@ uint32_t ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
@ -490,6 +537,7 @@ uint32_t ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
@ -512,6 +560,7 @@ uint32_t ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
@ -535,6 +584,7 @@ uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
@ -557,6 +607,7 @@ uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
@ -579,6 +630,7 @@ uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
@ -624,6 +676,7 @@ uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f
{
int reg1 = IREG_8((fetchdat >> 3) & 7);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int reg2 = IREG_8(fetchdat & 7);
@ -651,6 +704,7 @@ uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
{
int reg1 = IREG_16((fetchdat >> 3) & 7);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int reg2 = IREG_16(fetchdat & 7);
@ -678,6 +732,7 @@ uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
{
int reg1 = IREG_32((fetchdat >> 3) & 7);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int reg2 = IREG_32(fetchdat & 7);