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:
parent
063ffb4eab
commit
ab124776a0
36 changed files with 1719 additions and 233 deletions
|
|
@ -1,3 +1,6 @@
|
|||
#ifndef _386_COMMON_H_
|
||||
#define _386_COMMON_H_
|
||||
|
||||
#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1)?readmembl((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) )
|
||||
#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
|
||||
#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
|
||||
|
|
@ -128,6 +131,17 @@ static inline uint32_t fastreadl(uint32_t a)
|
|||
return val;
|
||||
}
|
||||
|
||||
static inline void *get_ram_ptr(uint32_t a)
|
||||
{
|
||||
if ((a >> 12) == pccache)
|
||||
return &pccache2[a];
|
||||
else
|
||||
{
|
||||
uint8_t *t = getpccache(a);
|
||||
return &t[a];
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint8_t getbyte()
|
||||
{
|
||||
cpu_state.pc++;
|
||||
|
|
@ -219,3 +233,5 @@ static inline void seteaq(uint64_t v)
|
|||
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
|
||||
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
|
||||
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -320,8 +320,10 @@ void exec386_dynarec(int cycs)
|
|||
if (!valid_block)
|
||||
{
|
||||
uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
|
||||
|
||||
if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask)
|
||||
int byte_offset = (phys_addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
|
||||
uint64_t byte_mask = 1ull << (PAGE_BYTE_MASK_MASK & 0x3f);
|
||||
|
||||
if ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_mask))
|
||||
{
|
||||
/*Walk page tree to see if we find the correct block*/
|
||||
codeblock_t *new_block = codeblock_tree_find(phys_addr, cs);
|
||||
|
|
@ -339,12 +341,21 @@ void exec386_dynarec(int cycs)
|
|||
}
|
||||
}
|
||||
|
||||
if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST))
|
||||
{
|
||||
block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
|
||||
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||
block->flags |= CODEBLOCK_NO_IMMEDIATES;
|
||||
else
|
||||
block->flags |= CODEBLOCK_BYTE_MASK;
|
||||
}
|
||||
if (valid_block && (block->page_mask & *block->dirty_mask))
|
||||
{
|
||||
codegen_check_flush(page, page->dirty_mask[(phys_addr >> 10) & 3], phys_addr);
|
||||
page->dirty_mask[(phys_addr >> 10) & 3] = 0;
|
||||
codegen_check_flush(page, page->dirty_mask, phys_addr);
|
||||
if (block->pc == BLOCK_PC_INVALID)
|
||||
valid_block = 0;
|
||||
else if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||
block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
|
||||
}
|
||||
if (valid_block && block->page_mask2)
|
||||
{
|
||||
|
|
@ -355,16 +366,17 @@ void exec386_dynarec(int cycs)
|
|||
allow the first page to be interpreted and for
|
||||
the page fault to occur when the page boundary
|
||||
is actually crossed.*/
|
||||
uint32_t phys_addr_2 = get_phys_noabrt(block->pc + 0x400);
|
||||
uint32_t phys_addr_2 = get_phys_noabrt(block->pc + ((block->flags & CODEBLOCK_BYTE_MASK) ? 0x40 : 0x400));
|
||||
page_t *page_2 = &pages[phys_addr_2 >> 12];
|
||||
if ((block->phys_2 ^ phys_addr_2) & ~0xfff)
|
||||
valid_block = 0;
|
||||
else if (block->page_mask2 & *block->dirty_mask2)
|
||||
{
|
||||
codegen_check_flush(page_2, page_2->dirty_mask[(phys_addr_2 >> 10) & 3], phys_addr_2);
|
||||
page_2->dirty_mask[(phys_addr_2 >> 10) & 3] = 0;
|
||||
codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2);
|
||||
if (block->pc == BLOCK_PC_INVALID)
|
||||
valid_block = 0;
|
||||
else if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||
block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
|
||||
}
|
||||
}
|
||||
if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7))
|
||||
|
|
@ -390,7 +402,8 @@ void exec386_dynarec(int cycs)
|
|||
else if (valid_block && !cpu_state.abrt)
|
||||
{
|
||||
uint32_t start_pc = cpu_state.pc;
|
||||
|
||||
const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000;
|
||||
|
||||
cpu_block_end = 0;
|
||||
x86_was_reset = 0;
|
||||
|
||||
|
|
@ -434,7 +447,7 @@ void exec386_dynarec(int cycs)
|
|||
will prevent any block from spanning more than
|
||||
2 pages. In practice this limit will never be
|
||||
hit, as host block size is only 2kB*/
|
||||
if ((cpu_state.pc - start_pc) > 1000)
|
||||
if ((cpu_state.pc - start_pc) >= max_block_size)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (trap)
|
||||
|
|
@ -465,6 +478,7 @@ void exec386_dynarec(int cycs)
|
|||
{
|
||||
/*Mark block but do not recompile*/
|
||||
uint32_t start_pc = cpu_state.pc;
|
||||
const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000;
|
||||
|
||||
cpu_block_end = 0;
|
||||
x86_was_reset = 0;
|
||||
|
|
@ -505,7 +519,7 @@ void exec386_dynarec(int cycs)
|
|||
will prevent any block from spanning more than
|
||||
2 pages. In practice this limit will never be
|
||||
hit, as host block size is only 2kB*/
|
||||
if ((cpu_state.pc - start_pc) > 1000)
|
||||
if ((cpu_state.pc - start_pc) >= max_block_size)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (trap)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ wx-resources.cpp : pc.xrc
|
|||
|
||||
# PCem
|
||||
pcem_SOURCES = 386.c 386_common.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_allocator.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_3dnow.c codegen_ops_arith.c codegen_ops_branch.c codegen_ops_fpu_arith.c codegen_ops_fpu_constant.c codegen_ops_fpu_loadstore.c codegen_ops_fpu_misc.c codegen_ops_jump.c codegen_ops_logic.c codegen_ops_shift.c \
|
||||
cmd640.c codegen.c codegen_accumulate.c codegen_allocator.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_3dnow.c codegen_ops_arith.c codegen_ops_branch.c codegen_ops_fpu_arith.c codegen_ops_fpu_constant.c codegen_ops_fpu_loadstore.c codegen_ops_fpu_misc.c codegen_ops_helpers.c codegen_ops_jump.c codegen_ops_logic.c codegen_ops_shift.c \
|
||||
codegen_ops_misc.c codegen_ops_mov.c codegen_ops_stack.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_k6.c codegen_timing_pentium.c codegen_timing_winchip.c codegen_timing_winchip2.c compaq.c config.c cpu.c \
|
||||
cpu_tables.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 ide_sff8038i.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ CPP = g++
|
|||
CC = gcc
|
||||
WINDRES = windres.exe
|
||||
WXVERSION = 31
|
||||
WXINCLUDE = C:/MinGW/include/wx/
|
||||
WXINCLUDE = e:/MinGWget/include/wx/
|
||||
CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Werror -fno-strict-aliasing
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o \
|
||||
|
|
@ -11,7 +11,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer38
|
|||
codegen_backend.o codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o \
|
||||
codegen_backend_x86_ops_sse.o codegen_backend_x86_uops.o codegen_ir.o codegen_ops.o \
|
||||
codegen_ops_3dnow.o codegen_ops_branch.o codegen_ops_arith.o codegen_ops_fpu_arith.o \
|
||||
codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_jump.o \
|
||||
codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_helpers.o codegen_ops_jump.o \
|
||||
codegen_ops_logic.o codegen_ops_misc.o codegen_ops_mmx_arith.o codegen_ops_mmx_cmp.o \
|
||||
codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \
|
||||
codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o codegen_timing_486.o \
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "codegen_backend.h"
|
||||
#include "codegen_ir.h"
|
||||
#include "codegen_ops.h"
|
||||
#include "codegen_ops_helpers.h"
|
||||
|
||||
int has_ea;
|
||||
|
||||
|
|
@ -85,6 +86,7 @@ void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg)
|
|||
|
||||
static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc)
|
||||
{
|
||||
uint32_t old_pc = *op_pc;
|
||||
// pclog("codegen - mod=%i rm=%i reg=%i fetchdat=%08x\n", cpu_mod, cpu_rm, cpu_reg, fetchdat);
|
||||
if (!cpu_mod && cpu_rm == 6)
|
||||
{
|
||||
|
|
@ -145,12 +147,16 @@ static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uin
|
|||
}
|
||||
}
|
||||
|
||||
codegen_mark_code_present(ir->block, cs+old_pc, (*op_pc)-old_pc);
|
||||
return op_ea_seg;
|
||||
}
|
||||
|
||||
static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset)
|
||||
{
|
||||
codeblock_t *block = ir->block;
|
||||
uint32_t old_pc = (*op_pc) + 1;
|
||||
uint32_t new_eaaddr;
|
||||
int extra_bytes = 0;
|
||||
|
||||
if (cpu_rm == 4)
|
||||
{
|
||||
|
|
@ -162,13 +168,23 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin
|
|||
case 0:
|
||||
if ((sib & 7) == 5)
|
||||
{
|
||||
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
|
||||
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||
{
|
||||
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
|
||||
extra_bytes = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
|
||||
extra_bytes = 5;
|
||||
}
|
||||
(*op_pc) += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
uop_MOV(ir, IREG_eaaddr, sib & 7);
|
||||
extra_bytes = 1;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
|
|
@ -176,12 +192,22 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin
|
|||
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
|
||||
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7);
|
||||
(*op_pc)++;
|
||||
extra_bytes = 2;
|
||||
break;
|
||||
case 2:
|
||||
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
|
||||
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7);
|
||||
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||
{
|
||||
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
|
||||
extra_bytes = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
|
||||
extra_bytes = 5;
|
||||
}
|
||||
(*op_pc) += 4;
|
||||
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7);
|
||||
break;
|
||||
}
|
||||
if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/
|
||||
|
|
@ -215,29 +241,54 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin
|
|||
{
|
||||
if (!cpu_mod && cpu_rm == 5)
|
||||
{
|
||||
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
|
||||
(*op_pc) += 4;
|
||||
return op_ea_seg;
|
||||
}
|
||||
uop_MOV(ir, IREG_eaaddr, cpu_rm);
|
||||
if (cpu_mod)
|
||||
{
|
||||
if (cpu_rm == 5 && !op_ssegs)
|
||||
op_ea_seg = &cpu_state.seg_ss;
|
||||
if (cpu_mod == 1)
|
||||
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||
{
|
||||
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t)(int8_t)(fetchdat >> 8));
|
||||
(*op_pc)++;
|
||||
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr);
|
||||
(*op_pc) += 4;
|
||||
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
|
||||
extra_bytes = 4;
|
||||
}
|
||||
|
||||
(*op_pc) += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
uop_MOV(ir, IREG_eaaddr, cpu_rm);
|
||||
if (cpu_mod)
|
||||
{
|
||||
if (cpu_rm == 5 && !op_ssegs)
|
||||
op_ea_seg = &cpu_state.seg_ss;
|
||||
if (cpu_mod == 1)
|
||||
{
|
||||
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t)(int8_t)(fetchdat >> 8));
|
||||
(*op_pc)++;
|
||||
extra_bytes = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||
{
|
||||
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + (*op_pc) + 1);
|
||||
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_temp0);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr);
|
||||
extra_bytes = 4;
|
||||
}
|
||||
(*op_pc) += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (extra_bytes)
|
||||
codegen_mark_code_present(ir->block, cs+old_pc, extra_bytes);
|
||||
|
||||
return op_ea_seg;
|
||||
}
|
||||
|
||||
|
|
@ -583,6 +634,7 @@ generate_call:
|
|||
opcode_mask = 0xff;
|
||||
}
|
||||
}
|
||||
codegen_mark_code_present(block, cs+old_pc, (op_pc - old_pc) - pc_off);
|
||||
// pclog("%04x:%08x : %02x\n", CS, new_pc, opcode);
|
||||
if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask])
|
||||
{
|
||||
|
|
@ -654,6 +706,7 @@ generate_call:
|
|||
uop_MOV_IMM(ir, IREG_ssegs, op_ssegs);
|
||||
uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat);
|
||||
uop_CALL_INSTRUCTION_FUNC(ir, op);
|
||||
codegen_mark_code_present(block, cs+cpu_state.pc, 8);
|
||||
|
||||
last_op_32 = op_32;
|
||||
last_op_ea_seg = op_ea_seg;
|
||||
|
|
|
|||
|
|
@ -73,6 +73,14 @@ extern uint8_t *block_write_data;
|
|||
#define CODEBLOCK_WAS_RECOMPILED 4
|
||||
/*Code block is in free list and is not valid*/
|
||||
#define CODEBLOCK_IN_FREE_LIST 8
|
||||
/*Code block spans two pages, page_mask2 and dirty_mask2 are valid*/
|
||||
#define CODEBLOCK_HAS_PAGE2 0x10
|
||||
/*Code block is using a byte mask for code present and dirty*/
|
||||
#define CODEBLOCK_BYTE_MASK 0x20
|
||||
/*Code block is in dirty list*/
|
||||
#define CODEBLOCK_IN_DIRTY_LIST 0x40
|
||||
/*Code block is not inlining immediate parameters, parameters must be fetched from memory*/
|
||||
#define CODEBLOCK_NO_IMMEDIATES 0x80
|
||||
|
||||
#define BLOCK_PC_INVALID 0xffffffff
|
||||
|
||||
|
|
@ -277,10 +285,33 @@ static inline void codeblock_tree_delete(codeblock_t *block)
|
|||
}
|
||||
}
|
||||
|
||||
#define PAGE_MASK_INDEX_MASK 3
|
||||
#define PAGE_MASK_INDEX_SHIFT 10
|
||||
#define PAGE_MASK_MASK 63
|
||||
#define PAGE_MASK_SHIFT 4
|
||||
#define PAGE_MASK_SHIFT 6
|
||||
|
||||
void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len);
|
||||
|
||||
static inline void codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len)
|
||||
{
|
||||
if (len == 1)
|
||||
{
|
||||
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||
{
|
||||
if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/
|
||||
block->page_mask |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
|
||||
else
|
||||
block->page_mask2 |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/
|
||||
block->page_mask |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
|
||||
else
|
||||
block->page_mask2 |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
|
||||
}
|
||||
}
|
||||
else
|
||||
codegen_mark_code_present_multibyte(block, start_pc, len);
|
||||
}
|
||||
|
||||
void codegen_init();
|
||||
void codegen_close();
|
||||
|
|
|
|||
|
|
@ -55,9 +55,22 @@ uint32_t instr_counts[256*256];
|
|||
|
||||
static uint16_t block_free_list;
|
||||
static void delete_block(codeblock_t *block);
|
||||
static void delete_dirty_block(codeblock_t *block);
|
||||
|
||||
/*Temporary list of code blocks that have recently been evicted. This allows for
|
||||
some historical state to be kept when a block is the target of self-modifying
|
||||
code.
|
||||
|
||||
The size of this list is limited to DIRTY_LIST_MAX_SIZE blocks. When this is
|
||||
exceeded the oldest entry will be moved to the free list.*/
|
||||
static uint16_t block_dirty_list_head, block_dirty_list_tail;
|
||||
static int dirty_list_size = 0;
|
||||
#define DIRTY_LIST_MAX_SIZE 64
|
||||
|
||||
static void block_free_list_add(codeblock_t *block)
|
||||
{
|
||||
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||
fatal("block_free_list_add: block=%p in dirty list\n", block);
|
||||
if (block_free_list)
|
||||
block->next = block_free_list;
|
||||
else
|
||||
|
|
@ -67,23 +80,92 @@ static void block_free_list_add(codeblock_t *block)
|
|||
// pclog("block_free_list_add: %p %p\n", block, block->next);
|
||||
}
|
||||
|
||||
static void block_dirty_list_add(codeblock_t *block)
|
||||
{
|
||||
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||
fatal("block_dirty_list_add: block=%p already in dirty list\n", block);
|
||||
// pclog("block_dirty_list_add: block=%i size=%i %i head=%i tail=%i\n", get_block_nr(block), dirty_list_size, dirty_list_check_size(), block_dirty_list_head, block_dirty_list_tail);
|
||||
if (block_dirty_list_head != BLOCK_INVALID)
|
||||
{
|
||||
codeblock_t *old_head = &codeblock[block_dirty_list_head];
|
||||
|
||||
block->next = block_dirty_list_head;
|
||||
block->prev = BLOCK_INVALID;
|
||||
block_dirty_list_head = old_head->prev = get_block_nr(block);
|
||||
// pclog(" next=%p,%i prev=%i\n", old_head, block->next, old_head->prev);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*List empty*/
|
||||
block->prev = block->next = BLOCK_INVALID;
|
||||
block_dirty_list_head = block_dirty_list_tail = get_block_nr(block);
|
||||
}
|
||||
block->flags |= CODEBLOCK_IN_DIRTY_LIST;
|
||||
// pclog(" block_dirty_list_add: %p flags = %x\n", block, block->flags);
|
||||
dirty_list_size++;
|
||||
if (dirty_list_size > DIRTY_LIST_MAX_SIZE)
|
||||
{
|
||||
/*Evict oldest block to the free list*/
|
||||
codeblock_t *evict_block = &codeblock[block_dirty_list_tail];
|
||||
|
||||
if (!(evict_block->flags & CODEBLOCK_IN_DIRTY_LIST))
|
||||
fatal("block_dirty_list_add: evict_block=%p %x %x not in dirty list\n", evict_block, evict_block->phys, evict_block->flags);
|
||||
if (!block_dirty_list_tail)
|
||||
fatal("block_dirty_list_add - !block_dirty_list_tail\n");
|
||||
if (evict_block->prev == BLOCK_INVALID)
|
||||
fatal("block_dirty_list_add - evict_block->prev == BLOCK_INVALID\n");
|
||||
|
||||
block_dirty_list_tail = evict_block->prev;
|
||||
codeblock[evict_block->prev].next = BLOCK_INVALID;
|
||||
|
||||
dirty_list_size--;
|
||||
evict_block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
|
||||
// pclog(" block_dirty_list_add: %p flags = %x\n", evict_block, evict_block->flags);
|
||||
delete_dirty_block(evict_block);
|
||||
}
|
||||
|
||||
// pclog("block_free_list_add: %p %p\n", block, block->next);
|
||||
}
|
||||
|
||||
static void block_dirty_list_remove(codeblock_t *block)
|
||||
{
|
||||
codeblock_t *prev_block = &codeblock[block->prev];
|
||||
codeblock_t *next_block = &codeblock[block->next];
|
||||
|
||||
if (!(block->flags & CODEBLOCK_IN_DIRTY_LIST))
|
||||
fatal("block_dirty_list_remove: block=%p not in dirty list\n", block);
|
||||
|
||||
/*Is block head of list*/
|
||||
if (block->prev == BLOCK_INVALID)
|
||||
block_dirty_list_head = block->next;
|
||||
else
|
||||
prev_block->next = block->next;
|
||||
|
||||
/*Is block tail of list?*/
|
||||
if (block->next == BLOCK_INVALID)
|
||||
block_dirty_list_tail = block->prev;
|
||||
else
|
||||
next_block->prev = block->prev;
|
||||
|
||||
dirty_list_size--;
|
||||
if (dirty_list_size < 0)
|
||||
fatal("remove - dirty_list_size < 0!\n");
|
||||
block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
|
||||
// pclog(" block_dirty_list_remove: %p flags = %x\n", block, block->flags);
|
||||
}
|
||||
|
||||
int codegen_purge_purgable_list()
|
||||
{
|
||||
if (purgable_page_list_head)
|
||||
{
|
||||
page_t *page = &pages[purgable_page_list_head];
|
||||
int c;
|
||||
// pclog("Purge page %08x\n", purgable_page_list_head);
|
||||
for (c = 0; c < 4; c++)
|
||||
|
||||
if (page->code_present_mask & page->dirty_mask)
|
||||
{
|
||||
// pclog(" Check %016llx %016llx\n", page->code_present_mask[c], page->dirty_mask[c]);
|
||||
if (page->code_present_mask[c] & page->dirty_mask[c])
|
||||
{
|
||||
codegen_check_flush(page, page->dirty_mask[c], (purgable_page_list_head << 12) + (c << 10));
|
||||
// pclog(" Check %08x %i\n", (purgable_page_list_head << 12) + (c << 10), block_free_list);
|
||||
if (block_free_list)
|
||||
return 1;
|
||||
}
|
||||
codegen_check_flush(page, page->dirty_mask, purgable_page_list_head << 12);
|
||||
|
||||
if (block_free_list)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -95,6 +177,27 @@ static codeblock_t *block_free_list_get()
|
|||
|
||||
while (!block_free_list)
|
||||
{
|
||||
/*Free list is empty, check the dirty list*/
|
||||
if (block_dirty_list_tail)
|
||||
{
|
||||
if (dirty_list_size <= 0)
|
||||
fatal("get - dirty_list_size <= 0!\n");
|
||||
|
||||
/*Reuse oldest block*/
|
||||
block = &codeblock[block_dirty_list_tail];
|
||||
|
||||
// pclog("block_free_list_get: remove block=%p size=%i\n", block, dirty_list_size);
|
||||
block_dirty_list_tail = block->prev;
|
||||
if (block->prev == BLOCK_INVALID)
|
||||
block_dirty_list_head = BLOCK_INVALID;
|
||||
else
|
||||
codeblock[block->prev].next = BLOCK_INVALID;
|
||||
dirty_list_size--;
|
||||
block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
|
||||
delete_dirty_block(block);
|
||||
block_free_list = get_block_nr(block);
|
||||
break;
|
||||
}
|
||||
/*Free list is empty - free up a block*/
|
||||
if (!codegen_purge_purgable_list())
|
||||
codegen_delete_random_block(0);
|
||||
|
|
@ -103,6 +206,7 @@ static codeblock_t *block_free_list_get()
|
|||
block = &codeblock[block_free_list];
|
||||
block_free_list = block->next;
|
||||
block->flags &= ~CODEBLOCK_IN_FREE_LIST;
|
||||
// pclog(" block_free_list_get: %p flags = %x\n", block, block->flags);
|
||||
block->next = 0;
|
||||
// pclog("block_free_list_get: %p %p\n", block, block_free_list);
|
||||
return block;
|
||||
|
|
@ -118,6 +222,8 @@ void codegen_init()
|
|||
block_free_list = 0;
|
||||
for (c = 0; c < BLOCK_SIZE; c++)
|
||||
block_free_list_add(&codeblock[c]);
|
||||
block_dirty_list_head = block_dirty_list_tail = 0;
|
||||
dirty_list_size = 0;
|
||||
#ifdef DEBUG_EXTRA
|
||||
memset(instr_counts, 0, sizeof(instr_counts));
|
||||
#endif
|
||||
|
|
@ -200,22 +306,23 @@ void dump_block()
|
|||
|
||||
static void add_to_block_list(codeblock_t *block)
|
||||
{
|
||||
uint16_t block_prev_nr = pages[block->phys >> 12].block[(block->phys >> 10) & 3];
|
||||
uint16_t block_prev_nr = pages[block->phys >> 12].block;
|
||||
uint16_t block_nr = get_block_nr(block);
|
||||
//pclog("Add to block list %p %08x %llx %x\n", block, block->phys, block->page_mask2, block->flags);
|
||||
|
||||
if (!block->page_mask)
|
||||
fatal("add_to_block_list - mask = 0\n");
|
||||
fatal("add_to_block_list - mask = 0 %llx %llx\n", block->page_mask,block->page_mask2);
|
||||
|
||||
if (block_prev_nr)
|
||||
{
|
||||
block->next = block_prev_nr;
|
||||
codeblock[block_prev_nr].prev = block_nr;
|
||||
pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block_nr;
|
||||
pages[block->phys >> 12].block = block_nr;
|
||||
}
|
||||
else
|
||||
{
|
||||
block->next = BLOCK_INVALID;
|
||||
pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block_nr;
|
||||
pages[block->phys >> 12].block = block_nr;
|
||||
}
|
||||
|
||||
if (block->next)
|
||||
|
|
@ -226,26 +333,31 @@ static void add_to_block_list(codeblock_t *block)
|
|||
|
||||
if (block->page_mask2)
|
||||
{
|
||||
block_prev_nr = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3];
|
||||
block->flags |= CODEBLOCK_HAS_PAGE2;
|
||||
|
||||
block_prev_nr = pages[block->phys_2 >> 12].block_2;
|
||||
|
||||
if (block_prev_nr)
|
||||
{
|
||||
block->next_2 = block_prev_nr;
|
||||
codeblock[block_prev_nr].prev_2 = block_nr;
|
||||
pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block_nr;
|
||||
pages[block->phys_2 >> 12].block_2 = block_nr;
|
||||
}
|
||||
else
|
||||
{
|
||||
block->next_2 = BLOCK_INVALID;
|
||||
pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block_nr;
|
||||
pages[block->phys_2 >> 12].block_2 = block_nr;
|
||||
}
|
||||
}
|
||||
// pclog(" add_to_block_list: %p flags = %x\n", block, block->flags);
|
||||
}
|
||||
|
||||
static void remove_from_block_list(codeblock_t *block, uint32_t pc)
|
||||
{
|
||||
if (!block->page_mask)
|
||||
return;
|
||||
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||
fatal("remove_from_block_list: in dirty list\n");
|
||||
|
||||
if (block->prev)
|
||||
{
|
||||
|
|
@ -255,18 +367,21 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc)
|
|||
}
|
||||
else
|
||||
{
|
||||
pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next;
|
||||
pages[block->phys >> 12].block = block->next;
|
||||
if (block->next)
|
||||
codeblock[block->next].prev = BLOCK_INVALID;
|
||||
else
|
||||
mem_flush_write_page(block->phys, 0);
|
||||
}
|
||||
if (!block->page_mask2)
|
||||
|
||||
if (!(block->flags & CODEBLOCK_HAS_PAGE2))
|
||||
{
|
||||
if (block->prev_2 || block->next_2)
|
||||
fatal("Invalid block_2\n");
|
||||
fatal("Invalid block_2 %x %p %08x\n", block->flags, block, block->phys);
|
||||
return;
|
||||
}
|
||||
block->flags &= ~CODEBLOCK_HAS_PAGE2;
|
||||
// pclog(" remove_from_block_list: %p flags = %x\n", block, block->flags);
|
||||
|
||||
if (block->prev_2)
|
||||
{
|
||||
|
|
@ -277,7 +392,7 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc)
|
|||
else
|
||||
{
|
||||
// pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2);
|
||||
pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2;
|
||||
pages[block->phys_2 >> 12].block_2 = block->next_2;
|
||||
if (block->next_2)
|
||||
codeblock[block->next_2].prev_2 = BLOCK_INVALID;
|
||||
else
|
||||
|
|
@ -285,6 +400,22 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc)
|
|||
}
|
||||
}
|
||||
|
||||
static void invalidate_block(codeblock_t *block)
|
||||
{
|
||||
uint32_t old_pc = block->pc;
|
||||
|
||||
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||
fatal("invalidate_block: already in dirty list\n");
|
||||
if (block->pc == BLOCK_PC_INVALID)
|
||||
fatal("Invalidating deleted block\n");
|
||||
|
||||
remove_from_block_list(block, old_pc);
|
||||
block_dirty_list_add(block);
|
||||
if (block->head_mem_block)
|
||||
codegen_allocator_free(block->head_mem_block);
|
||||
block->head_mem_block = NULL;
|
||||
}
|
||||
|
||||
static void delete_block(codeblock_t *block)
|
||||
{
|
||||
uint32_t old_pc = block->pc;
|
||||
|
|
@ -297,13 +428,29 @@ static void delete_block(codeblock_t *block)
|
|||
block->pc = BLOCK_PC_INVALID;
|
||||
|
||||
codeblock_tree_delete(block);
|
||||
remove_from_block_list(block, old_pc);
|
||||
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||
block_dirty_list_remove(block);
|
||||
else
|
||||
remove_from_block_list(block, old_pc);
|
||||
if (block->head_mem_block)
|
||||
codegen_allocator_free(block->head_mem_block);
|
||||
block->head_mem_block = NULL;
|
||||
block_free_list_add(block);
|
||||
}
|
||||
|
||||
static void delete_dirty_block(codeblock_t *block)
|
||||
{
|
||||
if (block == &codeblock[codeblock_hash[HASH(block->phys)]])
|
||||
codeblock_hash[HASH(block->phys)] = BLOCK_INVALID;
|
||||
|
||||
if (block->pc == BLOCK_PC_INVALID)
|
||||
fatal("Deleting deleted block\n");
|
||||
block->pc = BLOCK_PC_INVALID;
|
||||
|
||||
codeblock_tree_delete(block);
|
||||
block_free_list_add(block);
|
||||
}
|
||||
|
||||
void codegen_delete_block(codeblock_t *block)
|
||||
{
|
||||
if (block->pc != BLOCK_PC_INVALID)
|
||||
|
|
@ -332,16 +479,19 @@ void codegen_delete_random_block(int required_mem_block)
|
|||
|
||||
void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
|
||||
{
|
||||
uint16_t block_nr = page->block[(phys_addr >> 10) & 3];
|
||||
uint16_t block_nr = page->block;
|
||||
int remove_from_evict_list = 0;
|
||||
int c;
|
||||
|
||||
while (block_nr)
|
||||
{
|
||||
codeblock_t *block = &codeblock[block_nr];
|
||||
uint16_t next_block = block->next;
|
||||
|
||||
if (mask & block->page_mask)
|
||||
if (*block->dirty_mask & block->page_mask)
|
||||
{
|
||||
delete_block(block);
|
||||
// pclog("Delete block from codegen_check_flush %08x %08x %016llx %016llx %016llx %02x\n", phys_addr, block->pc, *block->dirty_mask, block->page_mask, *block->dirty_mask & block->page_mask, block->flags);
|
||||
invalidate_block(block);
|
||||
cpu_recomp_evicted++;
|
||||
}
|
||||
if (block_nr == next_block)
|
||||
|
|
@ -349,16 +499,17 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
|
|||
block_nr = next_block;
|
||||
}
|
||||
|
||||
block_nr = page->block_2[(phys_addr >> 10) & 3];
|
||||
block_nr = page->block_2;
|
||||
|
||||
while (block_nr)
|
||||
{
|
||||
codeblock_t *block = &codeblock[block_nr];
|
||||
uint16_t next_block = block->next_2;
|
||||
|
||||
if (mask & block->page_mask2)
|
||||
|
||||
if (*block->dirty_mask2 & block->page_mask2)
|
||||
{
|
||||
delete_block(block);
|
||||
// pclog("Delete block from codegen_check_flush2 %08x %08x\n", phys_addr, block->pc);*/
|
||||
invalidate_block(block);
|
||||
cpu_recomp_evicted++;
|
||||
}
|
||||
if (block_nr == next_block)
|
||||
|
|
@ -366,13 +517,19 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
|
|||
block_nr = next_block;
|
||||
}
|
||||
|
||||
page->code_present_mask[(phys_addr >> 10) & 3] &= ~mask;
|
||||
page->dirty_mask[(phys_addr >> 10) & 3] &= ~mask;
|
||||
if (page->code_present_mask & page->dirty_mask)
|
||||
remove_from_evict_list = 1;
|
||||
page->code_present_mask &= ~page->dirty_mask;
|
||||
page->dirty_mask = 0;
|
||||
|
||||
if (!(page->code_present_mask[0] & page->dirty_mask[0]) &&
|
||||
!(page->code_present_mask[1] & page->dirty_mask[1]) &&
|
||||
!(page->code_present_mask[2] & page->dirty_mask[2]) &&
|
||||
!(page->code_present_mask[3] & page->dirty_mask[3]))
|
||||
for (c = 0; c < 64; c++)
|
||||
{
|
||||
if (page->byte_code_present_mask[c] & page->byte_dirty_mask[c])
|
||||
remove_from_evict_list = 0;
|
||||
page->byte_code_present_mask[c] &= ~page->byte_dirty_mask[c];
|
||||
page->byte_dirty_mask[c] = 0;
|
||||
}
|
||||
if (remove_from_evict_list)
|
||||
page_remove_from_evict_list(page);
|
||||
}
|
||||
|
||||
|
|
@ -380,10 +537,9 @@ void codegen_block_init(uint32_t phys_addr)
|
|||
{
|
||||
codeblock_t *block;
|
||||
page_t *page = &pages[phys_addr >> 12];
|
||||
|
||||
if (!page->block[(phys_addr >> 10) & 3])
|
||||
mem_flush_write_page(phys_addr, cs+cpu_state.pc);
|
||||
|
||||
if (!page->block)
|
||||
mem_flush_write_page(phys_addr, cs+cpu_state.pc);
|
||||
block = block_free_list_get();
|
||||
if (!block)
|
||||
fatal("codegen_block_init: block_free_list_get() returned NULL\n");
|
||||
|
|
@ -396,16 +552,17 @@ void codegen_block_init(uint32_t phys_addr)
|
|||
block->pc = cs + cpu_state.pc;
|
||||
block->_cs = cs;
|
||||
block->phys = phys_addr;
|
||||
block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK];
|
||||
block->dirty_mask = &page->dirty_mask;
|
||||
block->dirty_mask2 = NULL;
|
||||
block->next = block->prev = BLOCK_INVALID;
|
||||
block->next_2 = block->prev_2 = BLOCK_INVALID;
|
||||
block->page_mask = 0;
|
||||
block->page_mask = block->page_mask2 = 0;
|
||||
block->flags = CODEBLOCK_STATIC_TOP;
|
||||
// pclog(" block_init: %p flags = %x\n", block, block->flags);
|
||||
block->status = cpu_cur_status;
|
||||
|
||||
recomp_page = block->phys & ~0xfff;
|
||||
|
||||
// pclog("codegen_block_init: %08x\n", block->pc);
|
||||
codeblock_tree_add(block);
|
||||
}
|
||||
|
||||
|
|
@ -419,8 +576,8 @@ ir_data_t *codegen_get_ir_data()
|
|||
void codegen_block_start_recompile(codeblock_t *block)
|
||||
{
|
||||
page_t *page = &pages[block->phys >> 12];
|
||||
|
||||
if (!page->block[(block->phys >> 10) & 3])
|
||||
|
||||
if (!page->block)
|
||||
mem_flush_write_page(block->phys, cs+cpu_state.pc);
|
||||
|
||||
block_num = HASH(block->phys);
|
||||
|
|
@ -433,6 +590,9 @@ void codegen_block_start_recompile(codeblock_t *block)
|
|||
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||
|
||||
block->status = cpu_cur_status;
|
||||
|
||||
block->page_mask = block->page_mask2 = 0;
|
||||
block->ins = 0;
|
||||
|
||||
cpu_block_end = 0;
|
||||
|
||||
|
|
@ -465,7 +625,14 @@ void codegen_block_start_recompile(codeblock_t *block)
|
|||
codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS);
|
||||
codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS);
|
||||
|
||||
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||
{
|
||||
block->dirty_mask = &page->byte_dirty_mask[(block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK];
|
||||
block->dirty_mask2 = NULL;
|
||||
}
|
||||
|
||||
ir_data = codegen_ir_init();
|
||||
ir_data->block = block;
|
||||
codegen_reg_reset();
|
||||
codegen_accumulate_reset();
|
||||
codegen_generate_reset();
|
||||
|
|
@ -482,40 +649,104 @@ void codegen_block_remove()
|
|||
recomp_page = -1;
|
||||
}
|
||||
|
||||
void codegen_block_generate_end_mask()
|
||||
void codegen_block_generate_end_mask_recompile()
|
||||
{
|
||||
codeblock_t *block = &codeblock[block_current];
|
||||
page_t *p;
|
||||
//pclog("gen_end_mask: %08x %08x %016llx %016llx\n", block->pc, codegen_endpc, block->page_mask,block->page_mask2);
|
||||
|
||||
p = &pages[block->phys >> 12];
|
||||
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||
{
|
||||
int offset = (block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
|
||||
|
||||
p->byte_code_present_mask[offset] |= block->page_mask;
|
||||
}
|
||||
else
|
||||
p->code_present_mask |= block->page_mask;
|
||||
|
||||
if ((*(block->dirty_mask) & block->page_mask) && !page_in_evict_list(p))
|
||||
page_add_to_evict_list(p);
|
||||
|
||||
block->phys_2 = -1;
|
||||
block->next_2 = block->prev_2 = BLOCK_INVALID;
|
||||
if (block->page_mask2)
|
||||
{
|
||||
block->phys_2 = get_phys_noabrt(codegen_endpc);
|
||||
if (block->phys_2 != -1)
|
||||
{
|
||||
page_t *page_2 = &pages[block->phys_2 >> 12];
|
||||
|
||||
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||
{
|
||||
int offset = (block->phys_2 >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
|
||||
|
||||
page_2->byte_code_present_mask[offset] |= block->page_mask2;
|
||||
block->dirty_mask2 = &page_2->byte_dirty_mask[offset];
|
||||
}
|
||||
else
|
||||
{
|
||||
page_2->code_present_mask |= block->page_mask2;
|
||||
block->dirty_mask2 = &page_2->dirty_mask;
|
||||
}
|
||||
if (((*block->dirty_mask2) & block->page_mask2) && !page_in_evict_list(page_2))
|
||||
page_add_to_evict_list(page_2);
|
||||
|
||||
if (!pages[block->phys_2 >> 12].block_2)
|
||||
mem_flush_write_page(block->phys_2, codegen_endpc);
|
||||
|
||||
if (!block->page_mask2)
|
||||
fatal("!page_mask2\n");
|
||||
if (block->next_2)
|
||||
{
|
||||
// pclog(" next_2->pc=%08x\n", block->next_2->pc);
|
||||
if (codeblock[block->next_2].pc == BLOCK_PC_INVALID)
|
||||
fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pclog("block_end: %08x %08x %016llx\n", block->pc, codegen_endpc, block->page_mask);
|
||||
recomp_page = -1;
|
||||
}
|
||||
|
||||
void codegen_block_generate_end_mask_mark()
|
||||
{
|
||||
codeblock_t *block = &codeblock[block_current];
|
||||
uint32_t start_pc;
|
||||
uint32_t end_pc;
|
||||
page_t *p;
|
||||
|
||||
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||
fatal("codegen_block_generate_end_mask2() - BYTE_MASK\n");
|
||||
|
||||
block->page_mask = 0;
|
||||
start_pc = (block->pc & 0x3ff) & ~15;
|
||||
if ((block->pc ^ codegen_endpc) & ~0x3ff)
|
||||
end_pc = 0x3ff & ~15;
|
||||
start_pc = (block->pc & 0xfff) & ~63;
|
||||
if ((block->pc ^ codegen_endpc) & ~0xfff)
|
||||
end_pc = 0xfff & ~63;
|
||||
else
|
||||
end_pc = (codegen_endpc & 0x3ff) & ~15;
|
||||
end_pc = (codegen_endpc & 0xfff) & ~63;
|
||||
if (end_pc < start_pc)
|
||||
end_pc = 0x3ff;
|
||||
end_pc = 0xfff;
|
||||
start_pc >>= PAGE_MASK_SHIFT;
|
||||
end_pc >>= PAGE_MASK_SHIFT;
|
||||
|
||||
|
||||
// pclog("block_end: %08x %08x\n", start_pc, end_pc);
|
||||
for (; start_pc <= end_pc; start_pc++)
|
||||
{
|
||||
{
|
||||
block->page_mask |= ((uint64_t)1 << start_pc);
|
||||
// pclog(" %08x %llx\n", start_pc, block->page_mask);
|
||||
}
|
||||
|
||||
|
||||
p = &pages[block->phys >> 12];
|
||||
p->code_present_mask[(block->phys >> 10) & 3] |= block->page_mask;
|
||||
if ((p->dirty_mask[(block->phys >> 10) & 3] & block->page_mask) && !page_in_evict_list(p))
|
||||
p->code_present_mask |= block->page_mask;
|
||||
if ((p->dirty_mask & block->page_mask) && !page_in_evict_list(p))
|
||||
page_add_to_evict_list(p);
|
||||
|
||||
block->phys_2 = -1;
|
||||
block->page_mask2 = 0;
|
||||
block->next_2 = block->prev_2 = BLOCK_INVALID;
|
||||
if ((block->pc ^ codegen_endpc) & ~0x3ff)
|
||||
if ((block->pc ^ codegen_endpc) & ~0xfff)
|
||||
{
|
||||
block->phys_2 = get_phys_noabrt(codegen_endpc);
|
||||
if (block->phys_2 != -1)
|
||||
|
|
@ -523,14 +754,15 @@ void codegen_block_generate_end_mask()
|
|||
page_t *page_2 = &pages[block->phys_2 >> 12];
|
||||
|
||||
start_pc = 0;
|
||||
end_pc = (codegen_endpc & 0x3ff) >> PAGE_MASK_SHIFT;
|
||||
end_pc = (codegen_endpc & 0xfff) >> PAGE_MASK_SHIFT;
|
||||
for (; start_pc <= end_pc; start_pc++)
|
||||
block->page_mask2 |= ((uint64_t)1 << start_pc);
|
||||
page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2;
|
||||
if ((page_2->dirty_mask[(block->phys_2 >> 10) & 3] & block->page_mask2) && !page_in_evict_list(page_2))
|
||||
|
||||
page_2->code_present_mask |= block->page_mask2;
|
||||
if ((page_2->dirty_mask & block->page_mask2) && !page_in_evict_list(page_2))
|
||||
page_add_to_evict_list(page_2);
|
||||
|
||||
if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3])
|
||||
if (!pages[block->phys_2 >> 12].block_2)
|
||||
mem_flush_write_page(block->phys_2, codegen_endpc);
|
||||
|
||||
if (!block->page_mask2)
|
||||
|
|
@ -542,7 +774,7 @@ void codegen_block_generate_end_mask()
|
|||
fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]);
|
||||
}
|
||||
|
||||
block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK];
|
||||
block->dirty_mask2 = &page_2->dirty_mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -554,7 +786,7 @@ void codegen_block_end()
|
|||
{
|
||||
codeblock_t *block = &codeblock[block_current];
|
||||
|
||||
codegen_block_generate_end_mask();
|
||||
codegen_block_generate_end_mask_mark();
|
||||
add_to_block_list(block);
|
||||
}
|
||||
|
||||
|
|
@ -562,10 +794,13 @@ void codegen_block_end_recompile(codeblock_t *block)
|
|||
{
|
||||
codegen_timing_block_end();
|
||||
|
||||
remove_from_block_list(block, block->pc);
|
||||
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||
block_dirty_list_remove(block);
|
||||
else
|
||||
remove_from_block_list(block, block->pc);
|
||||
block->next = block->prev = BLOCK_INVALID;
|
||||
block->next_2 = block->prev_2 = BLOCK_INVALID;
|
||||
codegen_block_generate_end_mask();
|
||||
codegen_block_generate_end_mask_recompile();
|
||||
add_to_block_list(block);
|
||||
// pclog("End block %i\n", block_num);
|
||||
|
||||
|
|
@ -580,3 +815,60 @@ void codegen_flush()
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len)
|
||||
{
|
||||
if (len)
|
||||
{
|
||||
uint32_t end_pc = start_pc + (len-1);
|
||||
|
||||
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||
{
|
||||
uint32_t start_pc_masked = start_pc & PAGE_MASK_MASK;
|
||||
uint32_t end_pc_masked = start_pc & PAGE_MASK_MASK;
|
||||
|
||||
if ((start_pc ^ block->pc) & ~0x3f) /*Starts in second page*/
|
||||
{
|
||||
for (; start_pc_masked <= end_pc_masked; start_pc_masked++)
|
||||
block->page_mask2 |= ((uint64_t)1 << start_pc_masked);
|
||||
}
|
||||
else if (((start_pc + (len-1)) ^ block->pc) & ~0x3f) /*Crosses both pages*/
|
||||
{
|
||||
for (; start_pc_masked <= 63; start_pc_masked++)
|
||||
block->page_mask |= ((uint64_t)1 << start_pc_masked);
|
||||
for (start_pc_masked = 0; start_pc_masked <= end_pc_masked; start_pc_masked++)
|
||||
block->page_mask2 |= ((uint64_t)1 << start_pc_masked);
|
||||
}
|
||||
else /*First page only*/
|
||||
{
|
||||
for (; start_pc_masked <= end_pc_masked; start_pc_masked++)
|
||||
block->page_mask |= ((uint64_t)1 << start_pc_masked);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t start_pc_shifted = start_pc >> PAGE_MASK_SHIFT;
|
||||
uint32_t end_pc_shifted = end_pc >> PAGE_MASK_SHIFT;
|
||||
start_pc_shifted &= PAGE_MASK_MASK;
|
||||
end_pc_shifted &= PAGE_MASK_MASK;
|
||||
|
||||
if ((start_pc ^ block->pc) & ~0xfff) /*Starts in second page*/
|
||||
{
|
||||
for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
|
||||
block->page_mask2 |= ((uint64_t)1 << start_pc_shifted);
|
||||
}
|
||||
else if (((start_pc + (len-1)) ^ block->pc) & ~0xfff) /*Crosses both pages*/
|
||||
{
|
||||
for (; start_pc_shifted <= 63; start_pc_shifted++)
|
||||
block->page_mask |= ((uint64_t)1 << start_pc_shifted);
|
||||
for (start_pc_shifted = 0; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
|
||||
block->page_mask2 |= ((uint64_t)1 << start_pc_shifted);
|
||||
}
|
||||
else /*First page only*/
|
||||
{
|
||||
for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
|
||||
block->page_mask |= ((uint64_t)1 << start_pc_shifted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1413,6 +1413,66 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop)
|
|||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p);
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm64_LDR_IMM_W(block, dest_reg, REG_TEMP, 0);
|
||||
}
|
||||
else
|
||||
fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p);
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm64_LDRB_IMM_W(block, dest_reg, REG_TEMP, 0);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0);
|
||||
host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16);
|
||||
}
|
||||
else if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0);
|
||||
host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8);
|
||||
}
|
||||
else
|
||||
fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p);
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm64_LDRH_IMM(block, dest_reg, REG_TEMP, 0);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm64_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0);
|
||||
host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16);
|
||||
}
|
||||
else
|
||||
fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_OR(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
|
|
@ -2765,6 +2825,8 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
||||
[UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE,
|
||||
[UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64,
|
||||
[UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR,
|
||||
[UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8,
|
||||
|
||||
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
||||
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
||||
|
|
|
|||
|
|
@ -1534,6 +1534,66 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop)
|
|||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p);
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm_LDR_IMM(block, dest_reg, REG_TEMP, 0);
|
||||
}
|
||||
else
|
||||
fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p);
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm_LDRB_IMM(block, dest_reg, REG_TEMP, 0);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0);
|
||||
host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16);
|
||||
}
|
||||
else if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0);
|
||||
host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8);
|
||||
}
|
||||
else
|
||||
fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p);
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm_LDRH_IMM(block, dest_reg, REG_TEMP, 0);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0);
|
||||
host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16);
|
||||
}
|
||||
else
|
||||
fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_OR(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
|
|
@ -2914,6 +2974,9 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
||||
[UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE,
|
||||
[UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64,
|
||||
[UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR,
|
||||
[UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8,
|
||||
[UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16,
|
||||
|
||||
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
||||
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
||||
|
|
|
|||
|
|
@ -1058,6 +1058,29 @@ void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg)
|
|||
codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (dst_reg & 8)
|
||||
fatal("host_x86_MOVZX_REG_ABS_16_8 - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_alloc_bytes(block, 5);
|
||||
codegen_addbyte(block, 0x66);
|
||||
codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_alloc_bytes(block, 10);
|
||||
codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/
|
||||
codegen_addquad(block, (uintptr_t)p);
|
||||
codegen_alloc_bytes(block, 5);
|
||||
codegen_addbyte(block, 0x66);
|
||||
codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/
|
||||
}
|
||||
}
|
||||
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
|
@ -1080,7 +1103,37 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p)
|
|||
}
|
||||
}
|
||||
else
|
||||
fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset);
|
||||
{
|
||||
if (dst_reg & 8)
|
||||
fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n");
|
||||
|
||||
codegen_alloc_bytes(block, 10);
|
||||
codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/
|
||||
codegen_addquad(block, (uintptr_t)p);
|
||||
codegen_alloc_bytes(block, 4);
|
||||
codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/
|
||||
}
|
||||
}
|
||||
void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (dst_reg & 8)
|
||||
fatal("host_x86_MOVZX_REG_ABS_32_16 - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_alloc_bytes(block, 4);
|
||||
codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_alloc_bytes(block, 10);
|
||||
codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/
|
||||
codegen_addquad(block, (uintptr_t)p);
|
||||
codegen_alloc_bytes(block, 4);
|
||||
codegen_addbyte4(block, 0x41, 0x0f, 0xb7, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_NOP(codeblock_t *block)
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@ void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
|
|||
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p);
|
||||
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
|
||||
void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p);
|
||||
|
||||
void host_x86_NOP(codeblock_t *block);
|
||||
|
||||
|
|
|
|||
|
|
@ -1269,6 +1269,60 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop)
|
|||
host_x86_MOV64_REG_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p);
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_MOV32_REG_ABS(block, dest_reg, uop->p);
|
||||
}
|
||||
else
|
||||
fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p);
|
||||
}
|
||||
else if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_x86_MOV8_REG_ABS(block, dest_reg, uop->p);
|
||||
}
|
||||
else
|
||||
fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_MOV16_REG_ABS(block, dest_reg, uop->p);
|
||||
}
|
||||
else
|
||||
fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOVSX(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
|
|
@ -2681,7 +2735,10 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
||||
[UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE,
|
||||
[UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64,
|
||||
|
||||
[UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR,
|
||||
[UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8,
|
||||
[UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16,
|
||||
|
||||
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
||||
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
||||
[UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT,
|
||||
|
|
|
|||
|
|
@ -788,6 +788,23 @@ void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg)
|
|||
codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_alloc_bytes(block, 5);
|
||||
codegen_addbyte(block, 0x66);
|
||||
codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_alloc_bytes(block, 8);
|
||||
codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
}
|
||||
}
|
||||
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
|
|
|||
|
|
@ -108,7 +108,9 @@ void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
|
|||
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p);
|
||||
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
|
||||
void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p);
|
||||
|
||||
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||
|
|
|
|||
|
|
@ -1256,6 +1256,60 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop)
|
|||
host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, (uint32_t)uop->p);
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_MOV32_REG_ABS(block, dest_reg, uop->p);
|
||||
}
|
||||
else
|
||||
fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p);
|
||||
}
|
||||
else if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_x86_MOV8_REG_ABS(block, dest_reg, uop->p);
|
||||
}
|
||||
else
|
||||
fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_MOV16_REG_ABS(block, dest_reg, uop->p);
|
||||
}
|
||||
else
|
||||
fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MOVSX(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
|
|
@ -2680,7 +2734,10 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
||||
[UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE,
|
||||
[UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64,
|
||||
|
||||
[UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR,
|
||||
[UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8,
|
||||
[UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16,
|
||||
|
||||
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
||||
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
||||
[UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT,
|
||||
|
|
|
|||
|
|
@ -76,6 +76,12 @@
|
|||
#define UOP_MOV_INT_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x26)
|
||||
/*UOP_MOV_INT_DOUBLE_64 - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/
|
||||
#define UOP_MOV_INT_DOUBLE_64 (UOP_TYPE_PARAMS_REGS | 0x27)
|
||||
/*UOP_MOV_REG_PTR - dest_reg = *p*/
|
||||
#define UOP_MOV_REG_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x28)
|
||||
/*UOP_MOVZX_REG_PTR_8 - dest_reg = *(uint8_t *)p*/
|
||||
#define UOP_MOVZX_REG_PTR_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x29)
|
||||
/*UOP_MOVZX_REG_PTR_16 - dest_reg = *(uint16_t *)p*/
|
||||
#define UOP_MOVZX_REG_PTR_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x2a)
|
||||
/*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/
|
||||
#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30)
|
||||
/*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/
|
||||
|
|
@ -338,6 +344,7 @@ typedef struct ir_data_t
|
|||
{
|
||||
uop_t uops[UOP_NR_MAX];
|
||||
int wr_pos;
|
||||
struct codeblock_t *block;
|
||||
} ir_data_t;
|
||||
|
||||
static inline uop_t *uop_alloc(ir_data_t *ir, uint32_t uop_type)
|
||||
|
|
@ -667,6 +674,9 @@ static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, in
|
|||
#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg)
|
||||
#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm)
|
||||
#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p)
|
||||
#define uop_MOV_REG_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_REG_PTR, ir, reg, p)
|
||||
#define uop_MOVZX_REG_PTR_8(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_8, ir, reg, p)
|
||||
#define uop_MOVZX_REG_PTR_16(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_16, ir, reg, p)
|
||||
#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg)
|
||||
#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg)
|
||||
#define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
int dest_reg = (fetchdat >> 3) & 7; \
|
||||
\
|
||||
uop_MMX_ENTER(ir); \
|
||||
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||
if ((fetchdat & 0xc0) == 0xc0) \
|
||||
{ \
|
||||
int src_reg = fetchdat & 7; \
|
||||
|
|
@ -32,6 +33,7 @@ uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
|
||||
} \
|
||||
\
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1); \
|
||||
return op_pc + 2; \
|
||||
}
|
||||
|
||||
|
|
@ -49,6 +51,7 @@ uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -65,6 +68,7 @@ uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||
}
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
|
|
@ -73,6 +77,7 @@ uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f
|
|||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -89,6 +94,7 @@ uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f
|
|||
uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg));
|
||||
}
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
|
|
@ -97,6 +103,7 @@ uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -113,6 +120,7 @@ uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||
}
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
|
|
@ -121,6 +129,7 @@ uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -136,6 +145,7 @@ uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
}
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
return op_pc + 2;
|
||||
}
|
||||
uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -143,6 +153,7 @@ uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -159,6 +170,7 @@ uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||
}
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
return op_pc + 2;
|
||||
}
|
||||
uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -166,6 +178,7 @@ uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -182,6 +195,7 @@ uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||
}
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
|
|
@ -189,5 +203,6 @@ uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
{
|
||||
uop_MMX_ENTER(ir);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -529,6 +529,7 @@ uint32_t ropJ ## cond ## _8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, u
|
|||
dest_addr &= 0xffff; \
|
||||
ropJ ## cond ## _common(block, ir, dest_addr); \
|
||||
\
|
||||
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||
return op_pc+1; \
|
||||
} \
|
||||
uint32_t ropJ ## cond ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||
|
|
@ -538,6 +539,7 @@ uint32_t ropJ ## cond ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode,
|
|||
\
|
||||
ropJ ## cond ## _common(block, ir, dest_addr); \
|
||||
\
|
||||
codegen_mark_code_present(block, cs+op_pc, 2); \
|
||||
return op_pc+2; \
|
||||
} \
|
||||
uint32_t ropJ ## cond ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||
|
|
@ -547,6 +549,7 @@ uint32_t ropJ ## cond ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode,
|
|||
\
|
||||
ropJ ## cond ## _common(block, ir, dest_addr); \
|
||||
\
|
||||
codegen_mark_code_present(block, cs+op_pc, 4); \
|
||||
return op_pc+4; \
|
||||
}
|
||||
|
||||
|
|
@ -585,6 +588,7 @@ uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
uop_JMP(ir, codegen_exit_rout);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
return op_pc+1;
|
||||
}
|
||||
|
||||
|
|
@ -611,6 +615,7 @@ uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
uop_JMP(ir, codegen_exit_rout);
|
||||
uop_set_jump_dest(ir, jump_uop);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
return op_pc+1;
|
||||
}
|
||||
|
||||
|
|
@ -647,6 +652,7 @@ uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
uop_set_jump_dest(ir, jump_uop);
|
||||
uop_set_jump_dest(ir, jump_uop2);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
return op_pc+1;
|
||||
}
|
||||
uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -682,5 +688,6 @@ uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f
|
|||
uop_set_jump_dest(ir, jump_uop);
|
||||
uop_set_jump_dest(ir, jump_uop2);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
return op_pc+1;
|
||||
}
|
||||
|
|
|
|||
26
src/codegen_ops_helpers.c
Normal file
26
src/codegen_ops_helpers.c
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#include "ibm.h"
|
||||
#include "x86.h"
|
||||
#include "386_common.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_ir_defs.h"
|
||||
#include "codegen_reg.h"
|
||||
#include "codegen_ops_helpers.h"
|
||||
|
||||
void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
|
||||
{
|
||||
/*Word access that crosses two pages. Perform reads from both pages, shift and combine*/
|
||||
uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr));
|
||||
uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr+1));
|
||||
uop_SHL_IMM(ir, IREG_temp3_W, IREG_temp3_W, 8);
|
||||
uop_OR(ir, dest_reg, dest_reg, IREG_temp3_W);
|
||||
}
|
||||
|
||||
void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
|
||||
{
|
||||
/*Dword access that crosses two pages. Perform reads from both pages, shift and combine*/
|
||||
uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr & ~3));
|
||||
uop_MOV_REG_PTR(ir, IREG_temp3, get_ram_ptr((addr + 4) & ~3));
|
||||
uop_SHR_IMM(ir, dest_reg, dest_reg, (addr & 3) * 8);
|
||||
uop_SHL_IMM(ir, IREG_temp3, IREG_temp3, (4 - (addr & 3)) * 8);
|
||||
uop_OR(ir, dest_reg, dest_reg, IREG_temp3);
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
#include "386_common.h"
|
||||
#include "codegen_backend.h"
|
||||
|
||||
static inline int LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset)
|
||||
|
|
@ -85,3 +86,26 @@ static inline void CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *s
|
|||
else
|
||||
uop_CMP_JNBE(ir, addr_reg, ireg_seg_limit_high(seg), codegen_gpf_rout);
|
||||
}
|
||||
|
||||
static inline void LOAD_IMMEDIATE_FROM_RAM_8(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
|
||||
{
|
||||
uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr));
|
||||
}
|
||||
|
||||
void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr);
|
||||
static inline void LOAD_IMMEDIATE_FROM_RAM_16(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
|
||||
{
|
||||
if ((addr & 0xfff) == 0xfff)
|
||||
LOAD_IMMEDIATE_FROM_RAM_16_unaligned(block, ir, dest_reg, addr);
|
||||
else
|
||||
uop_MOVZX_REG_PTR_16(ir, dest_reg, get_ram_ptr(addr));
|
||||
}
|
||||
|
||||
void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr);
|
||||
static inline void LOAD_IMMEDIATE_FROM_RAM_32(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
|
||||
{
|
||||
if ((addr & 0xfff) >= 0xffd)
|
||||
LOAD_IMMEDIATE_FROM_RAM_32_unaligned(block, ir, dest_reg, addr);
|
||||
else
|
||||
uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f
|
|||
dest_addr &= 0xffff;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_pc, dest_addr);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
return -1;
|
||||
}
|
||||
uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -27,6 +28,7 @@ uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
dest_addr &= 0xffff;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_pc, dest_addr);
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return -1;
|
||||
}
|
||||
uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -35,6 +37,7 @@ uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
uint32_t dest_addr = op_pc+4+offset;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_pc, dest_addr);
|
||||
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -49,6 +52,7 @@ uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
|
|||
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4);
|
||||
uop_CALL_FUNC(ir, loadcsjmp);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||
return -1;
|
||||
}
|
||||
uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -62,6 +66,7 @@ uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
|
|||
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4);
|
||||
uop_CALL_FUNC(ir, loadcsjmp);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 6);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -80,6 +85,7 @@ uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
SUB_SP(ir, 2);
|
||||
uop_MOV_IMM(ir, IREG_pc, dest_addr);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return -1;
|
||||
}
|
||||
uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -95,6 +101,7 @@ uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
SUB_SP(ir, 4);
|
||||
uop_MOV_IMM(ir, IREG_pc, dest_addr);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -146,6 +153,7 @@ uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
|
|||
ADD_SP(ir, 2+offset);
|
||||
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return -1;
|
||||
}
|
||||
uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -163,6 +171,7 @@ uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
|
|||
}
|
||||
ADD_SP(ir, 4+offset);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -243,6 +252,7 @@ uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
uop_CALL_FUNC(ir, loadcs);
|
||||
ADD_SP(ir, 4+offset);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return -1;
|
||||
}
|
||||
uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -271,5 +281,6 @@ uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
uop_CALL_FUNC(ir, loadcs);
|
||||
ADD_SP(ir, 8+offset);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "codegen.h"
|
||||
#include "codegen_ir.h"
|
||||
#include "codegen_ops.h"
|
||||
#include "codegen_ops_helpers.h"
|
||||
#include "codegen_ops_logic.h"
|
||||
|
||||
uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -17,6 +18,7 @@ uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
|
|||
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
return op_pc + 1;
|
||||
}
|
||||
uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -28,13 +30,23 @@ uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
|
|||
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return op_pc + 2;
|
||||
}
|
||||
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);
|
||||
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||
{
|
||||
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
|
||||
uop_AND(ir, IREG_EAX, IREG_EAX, IREG_temp0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||
uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
@ -45,6 +57,7 @@ uint32_t ropAND_b_rm(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;
|
||||
|
|
@ -72,6 +85,7 @@ uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
{
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
|
@ -102,6 +116,7 @@ uint32_t ropAND_w_rm(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;
|
||||
|
|
@ -129,6 +144,7 @@ uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
{
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
|
@ -159,6 +175,7 @@ uint32_t ropAND_l_rm(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;
|
||||
|
|
@ -186,6 +203,7 @@ uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
{
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
|
@ -222,6 +240,7 @@ uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
return op_pc + 1;
|
||||
}
|
||||
uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -233,23 +252,35 @@ uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return op_pc + 2;
|
||||
}
|
||||
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);
|
||||
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||
{
|
||||
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
|
||||
uop_OR(ir, IREG_EAX, IREG_EAX, IREG_temp0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||
uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
|
||||
}
|
||||
|
||||
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;
|
||||
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||
return op_pc + 4;
|
||||
}
|
||||
uint32_t ropOR_b_rm(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;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -277,6 +308,7 @@ uint32_t ropOR_b_rmw(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;
|
||||
|
|
@ -307,6 +339,7 @@ uint32_t ropOR_w_rm(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;
|
||||
|
|
@ -334,6 +367,7 @@ uint32_t ropOR_w_rmw(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;
|
||||
|
|
@ -364,6 +398,7 @@ uint32_t ropOR_l_rm(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;
|
||||
|
|
@ -391,6 +426,7 @@ uint32_t ropOR_l_rmw(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;
|
||||
|
|
@ -426,6 +462,7 @@ uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
return op_pc + 1;
|
||||
}
|
||||
uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -436,22 +473,34 @@ uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return op_pc + 2;
|
||||
}
|
||||
uint32_t ropTEST_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);
|
||||
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||
{
|
||||
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
|
||||
uop_AND(ir, IREG_flags_res, IREG_EAX, IREG_temp0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||
uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat);
|
||||
}
|
||||
|
||||
uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat);
|
||||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||
return op_pc + 4;
|
||||
}
|
||||
uint32_t ropTEST_b_rm(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;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -479,6 +528,7 @@ uint32_t ropTEST_w_rm(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;
|
||||
|
|
@ -506,6 +556,7 @@ uint32_t ropTEST_l_rm(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;
|
||||
|
|
@ -538,6 +589,7 @@ uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
|
|||
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
return op_pc + 1;
|
||||
}
|
||||
uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -549,23 +601,35 @@ uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
|
|||
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return op_pc + 2;
|
||||
}
|
||||
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);
|
||||
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||
{
|
||||
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
|
||||
uop_XOR(ir, IREG_EAX, IREG_EAX, IREG_temp0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||
uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
|
||||
}
|
||||
|
||||
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;
|
||||
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||
return op_pc + 4;
|
||||
}
|
||||
uint32_t ropXOR_b_rm(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;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -593,6 +657,7 @@ uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
{
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
|
@ -623,6 +688,7 @@ uint32_t ropXOR_w_rm(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;
|
||||
|
|
@ -650,6 +716,7 @@ uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
{
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
|
@ -680,6 +747,7 @@ uint32_t ropXOR_l_rm(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;
|
||||
|
|
@ -707,6 +775,7 @@ uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
{
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f
|
|||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
uop_MOV(ir, IREG_16(dest_reg), IREG_eaaddr_W);
|
||||
|
||||
|
|
@ -28,6 +29,7 @@ uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f
|
|||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
uop_MOV(ir, IREG_32(dest_reg), IREG_eaaddr);
|
||||
|
||||
|
|
@ -43,6 +45,7 @@ uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch
|
|||
if (fetchdat & 0x20)
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
reg = IREG_8(fetchdat & 7);
|
||||
else
|
||||
|
|
@ -67,6 +70,7 @@ uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch
|
|||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
return op_pc+2;
|
||||
|
||||
case 0x10: /*NOT*/
|
||||
|
|
@ -111,6 +115,7 @@ uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
if (fetchdat & 0x20)
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
reg = IREG_16(fetchdat & 7);
|
||||
else
|
||||
|
|
@ -135,6 +140,7 @@ uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 2);
|
||||
return op_pc+3;
|
||||
|
||||
case 0x10: /*NOT*/
|
||||
|
|
@ -179,6 +185,7 @@ uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
if (fetchdat & 0x20)
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
reg = IREG_32(fetchdat & 7);
|
||||
else
|
||||
|
|
@ -202,6 +209,7 @@ uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 4);
|
||||
return op_pc+5;
|
||||
|
||||
case 0x10: /*NOT*/
|
||||
|
|
@ -267,6 +275,7 @@ uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30)
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
if ((fetchdat & 0x38) == 0x28)
|
||||
|
|
@ -284,7 +293,7 @@ uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
src_reg = IREG_temp0_W;
|
||||
}
|
||||
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*INC*/
|
||||
|
|
@ -373,6 +382,7 @@ uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30)
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
if ((fetchdat & 0x38) == 0x28)
|
||||
|
|
@ -510,6 +520,7 @@ uint32_t rop ## name ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, u
|
|||
if ((fetchdat & 0xc0) == 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||
codegen_check_seg_read(block, ir, target_seg); \
|
||||
|
|
@ -531,6 +542,7 @@ uint32_t rop ## name ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, u
|
|||
if ((fetchdat & 0xc0) == 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||
codegen_check_seg_read(block, ir, target_seg); \
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
int dest_reg = (fetchdat >> 3) & 7; \
|
||||
\
|
||||
uop_MMX_ENTER(ir); \
|
||||
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||
if ((fetchdat & 0xc0) == 0xc0) \
|
||||
{ \
|
||||
int src_reg = fetchdat & 7; \
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
int dest_reg = (fetchdat >> 3) & 7; \
|
||||
\
|
||||
uop_MMX_ENTER(ir); \
|
||||
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||
if ((fetchdat & 0xc0) == 0xc0) \
|
||||
{ \
|
||||
int src_reg = fetchdat & 7; \
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -32,13 +33,13 @@ uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
}
|
||||
|
||||
return op_pc + 1;
|
||||
|
||||
}
|
||||
uint32_t ropMOVD_d_r(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;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
|
@ -64,6 +65,7 @@ uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -80,7 +82,6 @@ uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
}
|
||||
|
||||
return op_pc + 1;
|
||||
|
||||
}
|
||||
|
||||
uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -88,6 +89,7 @@ uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
int src_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -32,13 +33,13 @@ uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
}
|
||||
|
||||
return op_pc + 1;
|
||||
|
||||
}
|
||||
uint32_t ropPANDN(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;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -56,13 +57,13 @@ uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
}
|
||||
|
||||
return op_pc + 1;
|
||||
|
||||
}
|
||||
uint32_t ropPOR(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;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -80,13 +81,13 @@ uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetc
|
|||
}
|
||||
|
||||
return op_pc + 1;
|
||||
|
||||
}
|
||||
uint32_t ropPXOR(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;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
|
|
@ -104,5 +105,4 @@ uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
}
|
||||
|
||||
return op_pc + 1;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
int dest_reg = (fetchdat >> 3) & 7; \
|
||||
\
|
||||
uop_MMX_ENTER(ir); \
|
||||
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||
if ((fetchdat & 0xc0) == 0xc0) \
|
||||
{ \
|
||||
int src_reg = fetchdat & 7; \
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
int shift = fastreadb(cs + op_pc + 1);
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
switch (op)
|
||||
{
|
||||
case 0x10: /*PSRLW*/
|
||||
|
|
@ -33,6 +34,7 @@ uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
|
||||
}
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
return op_pc + 2;
|
||||
}
|
||||
uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -42,6 +44,7 @@ uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
int shift = fastreadb(cs + op_pc + 1);
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
switch (op)
|
||||
{
|
||||
case 0x10: /*PSRLD*/
|
||||
|
|
@ -58,6 +61,7 @@ uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
|
||||
}
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
return op_pc + 2;
|
||||
}
|
||||
uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -67,6 +71,7 @@ uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
int shift = fastreadb(cs + op_pc + 1);
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
switch (op)
|
||||
{
|
||||
case 0x10: /*PSRLQ*/
|
||||
|
|
@ -83,5 +88,6 @@ uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_
|
|||
|
||||
}
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "codegen_backend.h"
|
||||
#include "codegen_ir.h"
|
||||
#include "codegen_ops.h"
|
||||
#include "codegen_ops_helpers.h"
|
||||
#include "codegen_ops_shift.h"
|
||||
|
||||
static uint32_t shift_common_8(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count)
|
||||
|
|
@ -236,6 +237,81 @@ static uint32_t shift_common_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc
|
|||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t shift_common_variable_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count_reg)
|
||||
{
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x20: case 0x30: /*SHL*/
|
||||
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
|
||||
uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg);
|
||||
uop_MOV(ir, IREG_flags_op2, count_reg);
|
||||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32);
|
||||
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
|
||||
break;
|
||||
|
||||
case 0x28: /*SHR*/
|
||||
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
|
||||
uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg);
|
||||
uop_MOV(ir, IREG_flags_op2, count_reg);
|
||||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32);
|
||||
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
|
||||
break;
|
||||
|
||||
case 0x38: /*SAR*/
|
||||
uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg));
|
||||
uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg);
|
||||
uop_MOV(ir, IREG_flags_op2, count_reg);
|
||||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32);
|
||||
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x20: case 0x30: /*SHL*/
|
||||
uop_SHL(ir, IREG_temp1, IREG_temp0, count_reg);
|
||||
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
|
||||
uop_MOV(ir, IREG_flags_op1, IREG_temp0);
|
||||
uop_MOV(ir, IREG_flags_op2, count_reg);
|
||||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32);
|
||||
uop_MOV(ir, IREG_flags_res, IREG_temp1);
|
||||
break;
|
||||
|
||||
case 0x28: /*SHR*/
|
||||
uop_SHR(ir, IREG_temp1, IREG_temp0, count_reg);
|
||||
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
|
||||
uop_MOV(ir, IREG_flags_op1, IREG_temp0);
|
||||
uop_MOV(ir, IREG_flags_op2, count_reg);
|
||||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32);
|
||||
uop_MOV(ir, IREG_flags_res, IREG_temp1);
|
||||
break;
|
||||
|
||||
case 0x38: /*SAR*/
|
||||
uop_SAR(ir, IREG_temp1, IREG_temp0, count_reg);
|
||||
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
|
||||
uop_MOV(ir, IREG_flags_op1, IREG_temp0);
|
||||
uop_MOV(ir, IREG_flags_op2, count_reg);
|
||||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32);
|
||||
uop_MOV(ir, IREG_flags_res, IREG_temp1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
|
|
@ -245,6 +321,7 @@ uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch
|
|||
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
|
|
@ -253,7 +330,8 @@ uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch
|
|||
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
}
|
||||
imm = fastreadb(cs + op_pc + 1) & 0x1f;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
|
||||
if (imm)
|
||||
return shift_common_8(ir, fetchdat, op_pc, target_seg, imm) + 1;
|
||||
return op_pc+1;
|
||||
|
|
@ -266,6 +344,7 @@ uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
|
|
@ -274,7 +353,8 @@ uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
}
|
||||
imm = fastreadb(cs + op_pc + 1) & 0x1f;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
|
||||
if (imm)
|
||||
return shift_common_16(ir, fetchdat, op_pc, target_seg, imm) + 1;
|
||||
return op_pc+1;
|
||||
|
|
@ -282,11 +362,11 @@ uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
x86seg *target_seg = NULL;
|
||||
uint8_t imm;
|
||||
|
||||
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
|
|
@ -294,10 +374,23 @@ uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
codegen_check_seg_write(block, ir, target_seg);
|
||||
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
}
|
||||
imm = fastreadb(cs + op_pc + 1) & 0x1f;
|
||||
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||
{
|
||||
LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp2, cs + op_pc + 1);
|
||||
|
||||
if (imm)
|
||||
return shift_common_32(ir, fetchdat, op_pc, target_seg, imm) + 1;
|
||||
uop_AND_IMM(ir, IREG_temp2, IREG_temp2, 0x1f);
|
||||
uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout);
|
||||
|
||||
return shift_common_variable_32(ir, fetchdat, op_pc, target_seg, IREG_temp2) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t imm = fastreadb(cs + op_pc + 1) & 0x1f;
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
|
||||
if (imm)
|
||||
return shift_common_32(ir, fetchdat, op_pc, target_seg, imm) + 1;
|
||||
}
|
||||
return op_pc+1;
|
||||
}
|
||||
|
||||
|
|
@ -308,6 +401,7 @@ uint32_t ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch
|
|||
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
|
|
@ -325,6 +419,7 @@ uint32_t ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
|
|
@ -342,6 +437,7 @@ uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/
|
||||
return 0;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
|
|
@ -363,7 +459,8 @@ uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch
|
|||
|
||||
uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f);
|
||||
uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout);
|
||||
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
|
@ -455,6 +552,7 @@ uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f);
|
||||
uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
|
@ -546,6 +644,7 @@ uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
|
|||
uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f);
|
||||
uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
|
@ -633,13 +732,15 @@ uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
int src_reg = (fetchdat >> 3) & 7;
|
||||
uint8_t imm;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
}
|
||||
imm = fastreadb(cs + op_pc + 1) & 0x1f;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
|
||||
if (!imm)
|
||||
return op_pc+2;
|
||||
|
||||
|
|
@ -670,6 +771,7 @@ uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
uop_MOV_IMM(ir, IREG_flags_op2, imm);
|
||||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16);
|
||||
}
|
||||
|
||||
return op_pc+2;
|
||||
}
|
||||
uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -678,13 +780,15 @@ uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
int src_reg = (fetchdat >> 3) & 7;
|
||||
uint8_t imm;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
}
|
||||
imm = fastreadb(cs + op_pc + 1) & 0x1f;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
|
||||
if (!imm)
|
||||
return op_pc+2;
|
||||
|
||||
|
|
@ -715,6 +819,7 @@ uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
uop_MOV_IMM(ir, IREG_flags_op2, imm);
|
||||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32);
|
||||
}
|
||||
|
||||
return op_pc+2;
|
||||
}
|
||||
uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -723,13 +828,15 @@ uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
int src_reg = (fetchdat >> 3) & 7;
|
||||
uint8_t imm;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
}
|
||||
imm = fastreadb(cs + op_pc + 1) & 0x1f;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
|
||||
if (!imm)
|
||||
return op_pc+2;
|
||||
|
||||
|
|
@ -760,6 +867,7 @@ uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
uop_MOV_IMM(ir, IREG_flags_op2, imm);
|
||||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16);
|
||||
}
|
||||
|
||||
return op_pc+2;
|
||||
}
|
||||
uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -768,13 +876,15 @@ uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
int src_reg = (fetchdat >> 3) & 7;
|
||||
uint8_t imm;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
}
|
||||
imm = fastreadb(cs + op_pc + 1) & 0x1f;
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||
|
||||
if (!imm)
|
||||
return op_pc+2;
|
||||
|
||||
|
|
@ -805,5 +915,6 @@ uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
uop_MOV_IMM(ir, IREG_flags_op2, imm);
|
||||
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32);
|
||||
}
|
||||
|
||||
return op_pc+2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ uint32_t ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm);
|
||||
SUB_SP(ir, 2);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||
return op_pc + 2;
|
||||
}
|
||||
uint32_t ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -87,6 +88,7 @@ uint32_t ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3
|
|||
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm);
|
||||
SUB_SP(ir, 4);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||
return op_pc + 4;
|
||||
}
|
||||
|
||||
|
|
@ -100,6 +102,7 @@ uint32_t ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uin
|
|||
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm);
|
||||
SUB_SP(ir, 2);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
return op_pc + 1;
|
||||
}
|
||||
uint32_t ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
|
|
@ -112,6 +115,7 @@ uint32_t ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uin
|
|||
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm);
|
||||
SUB_SP(ir, 4);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
|
|
@ -119,6 +123,7 @@ uint32_t ropPOP_W(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
if (stack32)
|
||||
|
|
@ -154,6 +159,7 @@ uint32_t ropPOP_L(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
|||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
|
||||
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
if (stack32)
|
||||
|
|
|
|||
|
|
@ -167,10 +167,12 @@ enum
|
|||
IREG_temp0_W = IREG_temp0 + IREG_SIZE_W,
|
||||
IREG_temp1_W = IREG_temp1 + IREG_SIZE_W,
|
||||
IREG_temp2_W = IREG_temp2 + IREG_SIZE_W,
|
||||
IREG_temp3_W = IREG_temp3 + IREG_SIZE_W,
|
||||
|
||||
IREG_temp0_B = IREG_temp0 + IREG_SIZE_B,
|
||||
IREG_temp1_B = IREG_temp1 + IREG_SIZE_B,
|
||||
IREG_temp2_B = IREG_temp2 + IREG_SIZE_B,
|
||||
IREG_temp3_B = IREG_temp3 + IREG_SIZE_B,
|
||||
|
||||
IREG_temp0_D = IREG_temp0d + IREG_SIZE_D,
|
||||
IREG_temp1_D = IREG_temp1d + IREG_SIZE_D,
|
||||
|
|
|
|||
85
src/mem.c
85
src/mem.c
|
|
@ -46,6 +46,9 @@ int cachesize=256;
|
|||
uint8_t *ram, *rom = NULL;
|
||||
uint8_t romext[32768];
|
||||
|
||||
uint64_t *byte_dirty_mask;
|
||||
uint64_t *byte_code_present_mask;
|
||||
|
||||
uint32_t mem_logical_addr;
|
||||
|
||||
int mmuflush=0;
|
||||
|
|
@ -401,7 +404,7 @@ void addwritelookup(uint32_t virt, uint32_t phys)
|
|||
// if (page_lookup[virt >> 12] && (writelookup2[virt>>12] != 0xffffffff))
|
||||
// fatal("Bad write mapping\n");
|
||||
|
||||
if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3] || (phys & ~0xfff) == recomp_page)
|
||||
if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page)
|
||||
page_lookup[virt >> 12] = &pages[phys >> 12];//(uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)];
|
||||
else
|
||||
writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)];
|
||||
|
|
@ -926,15 +929,23 @@ void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p)
|
|||
if (val != p->mem[addr & 0xfff] || codegen_in_recompile)
|
||||
{
|
||||
uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
|
||||
int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK;
|
||||
int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
|
||||
uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK);
|
||||
|
||||
// pclog("mem_write_ramb_page: %08x %02x %08x %llx %llx\n", addr, val, cs+cpu_state.pc, p->dirty_mask, mask);
|
||||
p->mem[addr & 0xfff] = val;
|
||||
p->dirty_mask[index] |= mask;
|
||||
if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p))
|
||||
p->dirty_mask |= mask;
|
||||
if ((p->code_present_mask & mask) && !page_in_evict_list(p))
|
||||
{
|
||||
// pclog("ramb add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
|
||||
page_add_to_evict_list(p);
|
||||
}
|
||||
p->byte_dirty_mask[byte_offset] |= byte_mask;
|
||||
if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p))
|
||||
{
|
||||
// pclog(" ramb add %08x %016llx %016llx\n", addr, p->byte_code_present_mask[byte_offset], byte_mask);
|
||||
page_add_to_evict_list(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p)
|
||||
|
|
@ -942,13 +953,34 @@ void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p)
|
|||
if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile)
|
||||
{
|
||||
uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
|
||||
int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK;
|
||||
int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
|
||||
uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK);
|
||||
|
||||
if ((addr & 0xf) == 0xf)
|
||||
mask |= (mask << 1);
|
||||
// pclog("mem_write_ramw_page: %08x %04x %08x %016llx %016llx %016llx %08x %08x %p\n", addr, val, cs+cpu_state.pc, p->dirty_mask[index], p->code_present_mask[index], mask, p->evict_prev, p->evict_next, p);
|
||||
*(uint16_t *)&p->mem[addr & 0xfff] = val;
|
||||
p->dirty_mask[index] |= mask;
|
||||
if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p))
|
||||
p->dirty_mask |= mask;
|
||||
if ((p->code_present_mask & mask) && !page_in_evict_list(p))
|
||||
{
|
||||
// pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
|
||||
page_add_to_evict_list(p);
|
||||
}
|
||||
if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK)
|
||||
{
|
||||
p->byte_dirty_mask[byte_offset+1] |= 1;
|
||||
if ((p->byte_code_present_mask[byte_offset+1] & 1) && !page_in_evict_list(p))
|
||||
{
|
||||
// pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
|
||||
page_add_to_evict_list(p);
|
||||
}
|
||||
}
|
||||
else
|
||||
byte_mask |= (byte_mask << 1);
|
||||
|
||||
p->byte_dirty_mask[byte_offset] |= byte_mask;
|
||||
|
||||
if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p))
|
||||
{
|
||||
// pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
|
||||
page_add_to_evict_list(p);
|
||||
|
|
@ -960,17 +992,31 @@ void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p)
|
|||
if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile)
|
||||
{
|
||||
uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
|
||||
int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK;
|
||||
int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
|
||||
uint64_t byte_mask = (uint64_t)0xf << (addr & PAGE_BYTE_MASK_MASK);
|
||||
|
||||
if ((addr & 0xf) >= 0xd)
|
||||
mask |= (mask << 1);
|
||||
// pclog("mem_write_raml_page: %08x %08x %08x %016llx %016llx %016llx\n", addr, val, cs+cpu_state.pc, p->dirty_mask[index], p->code_present_mask[index], mask);
|
||||
*(uint32_t *)&p->mem[addr & 0xfff] = val;
|
||||
p->dirty_mask[index] |= mask;
|
||||
if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p))
|
||||
p->dirty_mask |= mask;
|
||||
p->byte_dirty_mask[byte_offset] |= byte_mask;
|
||||
if (!page_in_evict_list(p) && ((p->code_present_mask & mask) || (p->byte_code_present_mask[byte_offset] & byte_mask)))
|
||||
{
|
||||
// pclog("raml add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
|
||||
page_add_to_evict_list(p);
|
||||
}
|
||||
if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK-3))
|
||||
{
|
||||
uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3));
|
||||
|
||||
p->byte_dirty_mask[byte_offset+1] |= byte_mask_2;
|
||||
if ((p->byte_code_present_mask[byte_offset+1] & byte_mask_2) && !page_in_evict_list(p))
|
||||
{
|
||||
// pclog("raml add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
|
||||
page_add_to_evict_list(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1082,10 +1128,10 @@ void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr)
|
|||
{
|
||||
uint64_t mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
|
||||
page_t *p = &pages[start_addr >> 12];
|
||||
int index = (start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK;
|
||||
|
||||
//pclog("mem_invalidate: %08x\n", start_addr);
|
||||
p->dirty_mask[index] |= mask;
|
||||
if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p))
|
||||
p->dirty_mask |= mask;
|
||||
if ((p->code_present_mask & mask) && !page_in_evict_list(p))
|
||||
{
|
||||
// pclog("invalidate add %08x %016llx %016llx\n", start_addr, p->code_present_mask[index], mask);
|
||||
page_add_to_evict_list(p);
|
||||
|
|
@ -1371,6 +1417,13 @@ void mem_alloc()
|
|||
ram = malloc(mem_size * 1024);
|
||||
memset(ram, 0, mem_size * 1024);
|
||||
|
||||
free(byte_dirty_mask);
|
||||
byte_dirty_mask = malloc((mem_size * 1024) / 8);
|
||||
memset(byte_dirty_mask, 0, (mem_size * 1024) / 8);
|
||||
free(byte_code_present_mask);
|
||||
byte_code_present_mask = malloc((mem_size * 1024) / 8);
|
||||
memset(byte_code_present_mask, 0, (mem_size * 1024) / 8);
|
||||
|
||||
free(pages);
|
||||
pages = malloc((((mem_size + 384) * 1024) >> 12) * sizeof(page_t));
|
||||
memset(pages, 0, (((mem_size + 384) * 1024) >> 12) * sizeof(page_t));
|
||||
|
|
@ -1381,6 +1434,8 @@ void mem_alloc()
|
|||
pages[c].write_w = mem_write_ramw_page;
|
||||
pages[c].write_l = mem_write_raml_page;
|
||||
pages[c].evict_prev = EVICT_NOT_IN_LIST;
|
||||
pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64];
|
||||
pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64];
|
||||
}
|
||||
|
||||
memset(page_lookup, 0, (1 << 20) * sizeof(page_t *));
|
||||
|
|
@ -1431,8 +1486,8 @@ void mem_reset_page_blocks()
|
|||
pages[c].write_b = mem_write_ramb_page;
|
||||
pages[c].write_w = mem_write_ramw_page;
|
||||
pages[c].write_l = mem_write_raml_page;
|
||||
pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = BLOCK_INVALID;
|
||||
pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = BLOCK_INVALID;
|
||||
pages[c].block = BLOCK_INVALID;
|
||||
pages[c].block_2 = BLOCK_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
14
src/mem.h
14
src/mem.h
|
|
@ -112,6 +112,13 @@ mem_mapping_t bios_high_mapping[8];
|
|||
extern mem_mapping_t ram_high_mapping;
|
||||
extern mem_mapping_t ram_remapped_mapping;
|
||||
|
||||
extern uint64_t *byte_dirty_mask;
|
||||
extern uint64_t *byte_code_present_mask;
|
||||
|
||||
#define PAGE_BYTE_MASK_SHIFT 6
|
||||
#define PAGE_BYTE_MASK_OFFSET_MASK 63
|
||||
#define PAGE_BYTE_MASK_MASK 63
|
||||
|
||||
#define EVICT_NOT_IN_LIST ((uint32_t)-1)
|
||||
typedef struct page_t
|
||||
{
|
||||
|
|
@ -121,14 +128,17 @@ typedef struct page_t
|
|||
|
||||
uint8_t *mem;
|
||||
|
||||
uint16_t block[4], block_2[4];
|
||||
uint16_t block, block_2;
|
||||
|
||||
/*Head of codeblock tree associated with this page*/
|
||||
uint16_t head;
|
||||
|
||||
uint64_t code_present_mask[4], dirty_mask[4];
|
||||
uint64_t code_present_mask, dirty_mask;
|
||||
|
||||
uint32_t evict_prev, evict_next;
|
||||
|
||||
uint64_t *byte_dirty_mask;
|
||||
uint64_t *byte_code_present_mask;
|
||||
} page_t;
|
||||
|
||||
extern page_t *pages;
|
||||
|
|
|
|||
Loading…
Reference in a new issue