Rework self modifying code handling.

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

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

View file

@ -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

View file

@ -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)

View file

@ -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 \

View file

@ -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 \

View file

@ -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;

View file

@ -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();

View file

@ -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);
}
}
}
}

View file

@ -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,

View file

@ -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,

View file

@ -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)

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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,

View file

@ -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)

View file

@ -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

View file

@ -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
View 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);
}

View file

@ -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));
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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); \

View file

@ -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; \

View file

@ -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; \

View file

@ -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;

View file

@ -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;
}

View file

@ -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; \

View file

@ -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;
}

View file

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

View file

@ -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;
}

View file

@ -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)

View file

@ -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,

View file

@ -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;
}
}

View file

@ -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;