From ab124776a021ebce5e841836d06f8c456c3cbc86 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 16 Mar 2019 14:53:26 +0000 Subject: [PATCH] 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. --- src/386_common.h | 16 + src/386_dynarec.c | 34 +- src/Makefile.am | 2 +- src/Makefile.mingw-wx-sdl2 | 4 +- src/codegen.c | 93 ++++-- src/codegen.h | 37 ++- src/codegen_backend.c | 420 +++++++++++++++++++++---- src/codegen_backend_arm64_uops.c | 62 ++++ src/codegen_backend_arm_uops.c | 63 ++++ src/codegen_backend_x86-64_ops.c | 55 +++- src/codegen_backend_x86-64_ops.h | 2 + src/codegen_backend_x86-64_uops.c | 59 +++- src/codegen_backend_x86_ops.c | 17 + src/codegen_backend_x86_ops.h | 2 + src/codegen_backend_x86_uops.c | 59 +++- src/codegen_ir_defs.h | 10 + src/codegen_ops_3dnow.c | 15 + src/codegen_ops_arith.c | 501 +++++++++++++++++++++++++----- src/codegen_ops_branch.c | 7 + src/codegen_ops_helpers.c | 26 ++ src/codegen_ops_helpers.h | 24 ++ src/codegen_ops_jump.c | 11 + src/codegen_ops_logic.c | 85 ++++- src/codegen_ops_misc.c | 14 +- src/codegen_ops_mmx_arith.c | 1 + src/codegen_ops_mmx_cmp.c | 1 + src/codegen_ops_mmx_loadstore.c | 6 +- src/codegen_ops_mmx_logic.c | 8 +- src/codegen_ops_mmx_pack.c | 1 + src/codegen_ops_mmx_shift.c | 6 + src/codegen_ops_mov.c | 71 ++++- src/codegen_ops_shift.c | 133 +++++++- src/codegen_ops_stack.c | 6 + src/codegen_reg.h | 2 + src/mem.c | 85 ++++- src/mem.h | 14 +- 36 files changed, 1719 insertions(+), 233 deletions(-) create mode 100644 src/codegen_ops_helpers.c diff --git a/src/386_common.h b/src/386_common.h index 9f092bf..80da16d 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -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 diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 3044b7c..2817727 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -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) diff --git a/src/Makefile.am b/src/Makefile.am index b9f82d8..9b2795b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index aab0c0d..435aaf5 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -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 \ diff --git a/src/codegen.c b/src/codegen.c index 3db8d60..23ea678 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -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; diff --git a/src/codegen.h b/src/codegen.h index 1438dab..9365e44 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -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(); diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 4874233..0f76cbe 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -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); + } + } + } +} diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 47a6b3a..0f56360 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -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, diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index a47488d..402a7d7 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -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, diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index a4a8680..cd634bd 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -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) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index eaee044..8d0c07a 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -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); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index da8e8e4..d0768a2 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -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, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index ce64b33..f6a9bda 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -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); diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 08b7e9f..1ef8df8 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -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); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index f3ace1e..096497c 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -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, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 74b0043..7880c7a 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -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) diff --git a/src/codegen_ops_3dnow.c b/src/codegen_ops_3dnow.c index ad846e4..7a2af83 100644 --- a/src/codegen_ops_3dnow.c +++ b/src/codegen_ops_3dnow.c @@ -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; } diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c index ca0b980..08bb5f1 100644 --- a/src/codegen_ops_arith.c +++ b/src/codegen_ops_arith.c @@ -7,6 +7,7 @@ #include "codegen_ir.h" #include "codegen_ops.h" #include "codegen_ops_arith.h" +#include "codegen_ops_helpers.h" static inline void get_cf(ir_data_t *ir, int dest_reg) { @@ -26,6 +27,7 @@ uint32_t ropADC_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 ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -41,6 +43,7 @@ uint32_t ropADC_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 ropADC_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -56,12 +59,14 @@ uint32_t ropADC_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 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 ropADC_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; -//return 0; + + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -95,6 +100,7 @@ uint32_t ropADC_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); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -131,6 +137,7 @@ uint32_t ropADC_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); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -164,6 +171,7 @@ uint32_t ropADC_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); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -200,6 +208,7 @@ uint32_t ropADC_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); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -232,6 +241,7 @@ uint32_t ropADC_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); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -276,6 +286,7 @@ uint32_t ropADD_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 ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -289,18 +300,29 @@ uint32_t ropADD_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 ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - fetchdat = fastreadl(cs + op_pc); - uop_MOV(ir, IREG_flags_op1, IREG_EAX); - uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_ADD(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + fetchdat = fastreadl(cs + op_pc); + uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + codegen_mark_code_present(block, cs+op_pc, 4); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_EAX); - codegen_flags_changed = 1; return op_pc + 4; } @@ -308,6 +330,7 @@ uint32_t ropADD_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; @@ -339,6 +362,7 @@ uint32_t ropADD_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; @@ -372,6 +396,7 @@ uint32_t ropADD_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; @@ -403,6 +428,7 @@ uint32_t ropADD_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; @@ -436,6 +462,7 @@ uint32_t ropADD_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; @@ -466,6 +493,7 @@ uint32_t ropADD_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; @@ -507,6 +535,7 @@ uint32_t ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -520,6 +549,7 @@ uint32_t ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -532,12 +562,14 @@ uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 4); return op_pc + 4; } uint32_t ropCMP_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; @@ -569,6 +601,7 @@ uint32_t ropCMP_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; @@ -600,6 +633,7 @@ uint32_t ropCMP_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; @@ -631,6 +665,7 @@ uint32_t ropCMP_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; @@ -662,6 +697,7 @@ uint32_t ropCMP_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; @@ -692,6 +728,7 @@ uint32_t ropCMP_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; @@ -732,6 +769,7 @@ uint32_t ropSBB_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 ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -747,6 +785,7 @@ uint32_t ropSBB_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 ropSBB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -762,12 +801,14 @@ uint32_t ropSBB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 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 ropSBB_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); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -801,6 +842,7 @@ uint32_t ropSBB_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); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -837,6 +879,7 @@ uint32_t ropSBB_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); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -870,6 +913,7 @@ uint32_t ropSBB_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); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -907,6 +951,7 @@ uint32_t ropSBB_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); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -939,6 +984,7 @@ uint32_t ropSBB_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); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -984,6 +1030,7 @@ uint32_t ropSUB_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 ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -997,15 +1044,27 @@ uint32_t ropSUB_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 ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - fetchdat = fastreadl(cs + op_pc); - uop_MOV(ir, IREG_flags_op1, IREG_EAX); - uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_SUB(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs+op_pc, 4); + uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); uop_MOV(ir, IREG_flags_res, IREG_EAX); @@ -1016,6 +1075,7 @@ uint32_t ropSUB_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; @@ -1047,6 +1107,7 @@ uint32_t ropSUB_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; @@ -1080,6 +1141,7 @@ uint32_t ropSUB_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; @@ -1111,6 +1173,7 @@ uint32_t ropSUB_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; @@ -1145,6 +1208,7 @@ uint32_t ropSUB_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; @@ -1175,6 +1239,7 @@ uint32_t ropSUB_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; @@ -1208,23 +1273,43 @@ uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + int skip_immediate = 0; + + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; uint8_t imm = fastreadb(cs + op_pc + 1); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp0_B, cs+op_pc+1); + } + switch (fetchdat & 0x38) { case 0x00: /*ADD*/ uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } + else + { + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; @@ -1232,8 +1317,16 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch case 0x10: /*ADC*/ get_cf(ir, IREG_temp1); uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } + else + { + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -1242,38 +1335,68 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch case 0x18: /*SBB*/ get_cf(ir, IREG_temp1); uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } + else + { + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; case 0x28: /*SUB*/ uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } + else + { + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; case 0x38: /*CMP*/ uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } + else + { + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); break; @@ -1372,27 +1495,49 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch } codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + int skip_immediate = 0; + + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; uint16_t imm = fastreadw(cs + op_pc + 1); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp0_W, cs+op_pc+1); + } + switch (fetchdat & 0x38) { case 0x00: /*ADD*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } + else + { + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; @@ -1400,8 +1545,16 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x10: /*ADC*/ get_cf(ir, IREG_temp1); uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } + else + { + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -1410,38 +1563,68 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x18: /*SBB*/ get_cf(ir, IREG_temp1); uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } + else + { + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; case 0x28: /*SUB*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } + else + { + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; case 0x38: /*CMP*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } + else + { + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); break; @@ -1462,65 +1645,103 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet codegen_check_seg_write(block, ir, target_seg); imm = fastreadw(cs + op_pc + 1); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp2_W, cs+op_pc+1); + } switch (fetchdat & 0x38) { case 0x00: /*ADD*/ - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); break; case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); break; case 0x10: /*ADC*/ - get_cf(ir, IREG_temp2); - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + get_cf(ir, IREG_temp3); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); break; case 0x18: /*SBB*/ - get_cf(ir, IREG_temp2); - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + get_cf(ir, IREG_temp3); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); break; case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); break; case 0x28: /*SUB*/ - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); break; case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); @@ -1528,8 +1749,16 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x38: /*CMP*/ uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_temp2_W); + } + else + { + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + } uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); break; @@ -1540,27 +1769,49 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs+op_pc+1, 2); return op_pc + 3; } uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + int skip_immediate = 0; + + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; uint32_t imm = fastreadl(cs + op_pc + 1); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs+op_pc+1); + } + switch (fetchdat & 0x38) { case 0x00: /*ADD*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; @@ -1568,8 +1819,16 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x10: /*ADC*/ get_cf(ir, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); @@ -1578,37 +1837,67 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x18: /*SBB*/ get_cf(ir, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; case 0x28: /*SUB*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; case 0x38: /*CMP*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); break; @@ -1630,19 +1919,34 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet imm = fastreadl(cs + op_pc + 1); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp2, cs+op_pc+1); + } + switch (fetchdat & 0x38) { case 0x00: /*ADD*/ - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_temp1); break; case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp2); + else + uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); uop_MOV(ir, IREG_flags_res, IREG_temp0); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); @@ -1650,44 +1954,68 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x10: /*ADC*/ get_cf(ir, IREG_temp2); - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp2); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); uop_MOV(ir, IREG_flags_res, IREG_temp1); break; case 0x18: /*SBB*/ get_cf(ir, IREG_temp2); - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp2); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); uop_MOV(ir, IREG_flags_res, IREG_temp1); break; case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_temp0, IREG_temp0, IREG_temp2); + else + uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); uop_MOV(ir, IREG_flags_res, IREG_temp0); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); break; case 0x28: /*SUB*/ - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); uop_MOV(ir, IREG_flags_res, IREG_temp1); break; case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_temp2); + else + uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); uop_MOV(ir, IREG_flags_res, IREG_temp0); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); @@ -1695,8 +2023,16 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x38: /*CMP*/ uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_temp2); + } + else + { + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); break; @@ -1706,11 +2042,14 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs+op_pc+1, 4); return op_pc + 5; } uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -1875,10 +2214,12 @@ uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -2041,6 +2382,7 @@ uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } @@ -2121,6 +2463,7 @@ uint32_t ropDEC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uint32_t ropINCDEC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + codegen_mark_code_present(block, cs+op_pc, 1); rebuild_c(ir); if ((fetchdat & 0xc0) == 0xc0) diff --git a/src/codegen_ops_branch.c b/src/codegen_ops_branch.c index fdc0569..35e5c46 100644 --- a/src/codegen_ops_branch.c +++ b/src/codegen_ops_branch.c @@ -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; } diff --git a/src/codegen_ops_helpers.c b/src/codegen_ops_helpers.c new file mode 100644 index 0000000..8ccd1fb --- /dev/null +++ b/src/codegen_ops_helpers.c @@ -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); +} diff --git a/src/codegen_ops_helpers.h b/src/codegen_ops_helpers.h index 0da73b6..e1e2bbc 100644 --- a/src/codegen_ops_helpers.h +++ b/src/codegen_ops_helpers.h @@ -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)); +} diff --git a/src/codegen_ops_jump.c b/src/codegen_ops_jump.c index c2c7eb6..dd417e4 100644 --- a/src/codegen_ops_jump.c +++ b/src/codegen_ops_jump.c @@ -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; } diff --git a/src/codegen_ops_logic.c b/src/codegen_ops_logic.c index 8f402f1..015031f 100644 --- a/src/codegen_ops_logic.c +++ b/src/codegen_ops_logic.c @@ -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; diff --git a/src/codegen_ops_misc.c b/src/codegen_ops_misc.c index 2db4c32..13e0e64 100644 --- a/src/codegen_ops_misc.c +++ b/src/codegen_ops_misc.c @@ -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); \ diff --git a/src/codegen_ops_mmx_arith.c b/src/codegen_ops_mmx_arith.c index cd23e3c..1629fe6 100644 --- a/src/codegen_ops_mmx_arith.c +++ b/src/codegen_ops_mmx_arith.c @@ -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; \ diff --git a/src/codegen_ops_mmx_cmp.c b/src/codegen_ops_mmx_cmp.c index f56f413..b7fe44d 100644 --- a/src/codegen_ops_mmx_cmp.c +++ b/src/codegen_ops_mmx_cmp.c @@ -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; \ diff --git a/src/codegen_ops_mmx_loadstore.c b/src/codegen_ops_mmx_loadstore.c index e3c33e0..ac591e8 100644 --- a/src/codegen_ops_mmx_loadstore.c +++ b/src/codegen_ops_mmx_loadstore.c @@ -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; diff --git a/src/codegen_ops_mmx_logic.c b/src/codegen_ops_mmx_logic.c index 428a591..744f22b 100644 --- a/src/codegen_ops_mmx_logic.c +++ b/src/codegen_ops_mmx_logic.c @@ -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; - } diff --git a/src/codegen_ops_mmx_pack.c b/src/codegen_ops_mmx_pack.c index 7bf1941..e625217 100644 --- a/src/codegen_ops_mmx_pack.c +++ b/src/codegen_ops_mmx_pack.c @@ -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; \ diff --git a/src/codegen_ops_mmx_shift.c b/src/codegen_ops_mmx_shift.c index ad0f597..3086f4d 100644 --- a/src/codegen_ops_mmx_shift.c +++ b/src/codegen_ops_mmx_shift.c @@ -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; } diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c index 669523d..26cd4e5 100644 --- a/src/codegen_ops_mov.c +++ b/src/codegen_ops_mov.c @@ -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); diff --git a/src/codegen_ops_shift.c b/src/codegen_ops_shift.c index d4b5b56..7410d4d 100644 --- a/src/codegen_ops_shift.c +++ b/src/codegen_ops_shift.c @@ -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; } diff --git a/src/codegen_ops_stack.c b/src/codegen_ops_stack.c index 29d2bda..c3c8a46 100644 --- a/src/codegen_ops_stack.c +++ b/src/codegen_ops_stack.c @@ -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) diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 01272bc..6be5cfe 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -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, diff --git a/src/mem.c b/src/mem.c index 9c6c536..dd3186d 100644 --- a/src/mem.c +++ b/src/mem.c @@ -46,6 +46,9 @@ int cachesize=256; uint8_t *ram, *rom = NULL; uint8_t romext[32768]; +uint64_t *byte_dirty_mask; +uint64_t *byte_code_present_mask; + uint32_t mem_logical_addr; int mmuflush=0; @@ -401,7 +404,7 @@ void addwritelookup(uint32_t virt, uint32_t phys) // if (page_lookup[virt >> 12] && (writelookup2[virt>>12] != 0xffffffff)) // fatal("Bad write mapping\n"); - if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3] || (phys & ~0xfff) == recomp_page) + if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page) page_lookup[virt >> 12] = &pages[phys >> 12];//(uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; else writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; @@ -926,15 +929,23 @@ void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) if (val != p->mem[addr & 0xfff] || codegen_in_recompile) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); + // pclog("mem_write_ramb_page: %08x %02x %08x %llx %llx\n", addr, val, cs+cpu_state.pc, p->dirty_mask, mask); p->mem[addr & 0xfff] = val; - p->dirty_mask[index] |= mask; - if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) { // pclog("ramb add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); page_add_to_evict_list(p); } + p->byte_dirty_mask[byte_offset] |= byte_mask; + if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) + { +// pclog(" ramb add %08x %016llx %016llx\n", addr, p->byte_code_present_mask[byte_offset], byte_mask); + page_add_to_evict_list(p); + } } } void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) @@ -942,13 +953,34 @@ void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); + if ((addr & 0xf) == 0xf) mask |= (mask << 1); // pclog("mem_write_ramw_page: %08x %04x %08x %016llx %016llx %016llx %08x %08x %p\n", addr, val, cs+cpu_state.pc, p->dirty_mask[index], p->code_present_mask[index], mask, p->evict_prev, p->evict_next, p); *(uint16_t *)&p->mem[addr & 0xfff] = val; - p->dirty_mask[index] |= mask; - if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) + { +// pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); + page_add_to_evict_list(p); + } + if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK) + { + p->byte_dirty_mask[byte_offset+1] |= 1; + if ((p->byte_code_present_mask[byte_offset+1] & 1) && !page_in_evict_list(p)) + { +// pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); + page_add_to_evict_list(p); + } + } + else + byte_mask |= (byte_mask << 1); + + p->byte_dirty_mask[byte_offset] |= byte_mask; + + if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) { // pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); page_add_to_evict_list(p); @@ -960,17 +992,31 @@ void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)0xf << (addr & PAGE_BYTE_MASK_MASK); + if ((addr & 0xf) >= 0xd) mask |= (mask << 1); // pclog("mem_write_raml_page: %08x %08x %08x %016llx %016llx %016llx\n", addr, val, cs+cpu_state.pc, p->dirty_mask[index], p->code_present_mask[index], mask); *(uint32_t *)&p->mem[addr & 0xfff] = val; - p->dirty_mask[index] |= mask; - if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + p->dirty_mask |= mask; + p->byte_dirty_mask[byte_offset] |= byte_mask; + if (!page_in_evict_list(p) && ((p->code_present_mask & mask) || (p->byte_code_present_mask[byte_offset] & byte_mask))) { // pclog("raml add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); page_add_to_evict_list(p); } + if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK-3)) + { + uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3)); + + p->byte_dirty_mask[byte_offset+1] |= byte_mask_2; + if ((p->byte_code_present_mask[byte_offset+1] & byte_mask_2) && !page_in_evict_list(p)) + { +// pclog("raml add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); + page_add_to_evict_list(p); + } + } } } @@ -1082,10 +1128,10 @@ void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) { uint64_t mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); page_t *p = &pages[start_addr >> 12]; - int index = (start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; + //pclog("mem_invalidate: %08x\n", start_addr); - p->dirty_mask[index] |= mask; - if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) { // pclog("invalidate add %08x %016llx %016llx\n", start_addr, p->code_present_mask[index], mask); page_add_to_evict_list(p); @@ -1371,6 +1417,13 @@ void mem_alloc() ram = malloc(mem_size * 1024); memset(ram, 0, mem_size * 1024); + free(byte_dirty_mask); + byte_dirty_mask = malloc((mem_size * 1024) / 8); + memset(byte_dirty_mask, 0, (mem_size * 1024) / 8); + free(byte_code_present_mask); + byte_code_present_mask = malloc((mem_size * 1024) / 8); + memset(byte_code_present_mask, 0, (mem_size * 1024) / 8); + free(pages); pages = malloc((((mem_size + 384) * 1024) >> 12) * sizeof(page_t)); memset(pages, 0, (((mem_size + 384) * 1024) >> 12) * sizeof(page_t)); @@ -1381,6 +1434,8 @@ void mem_alloc() pages[c].write_w = mem_write_ramw_page; pages[c].write_l = mem_write_raml_page; pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; } memset(page_lookup, 0, (1 << 20) * sizeof(page_t *)); @@ -1431,8 +1486,8 @@ void mem_reset_page_blocks() pages[c].write_b = mem_write_ramb_page; pages[c].write_w = mem_write_ramw_page; pages[c].write_l = mem_write_raml_page; - pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = BLOCK_INVALID; - pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = BLOCK_INVALID; + pages[c].block = BLOCK_INVALID; + pages[c].block_2 = BLOCK_INVALID; } } diff --git a/src/mem.h b/src/mem.h index 79d0da4..429973a 100644 --- a/src/mem.h +++ b/src/mem.h @@ -112,6 +112,13 @@ mem_mapping_t bios_high_mapping[8]; extern mem_mapping_t ram_high_mapping; extern mem_mapping_t ram_remapped_mapping; +extern uint64_t *byte_dirty_mask; +extern uint64_t *byte_code_present_mask; + +#define PAGE_BYTE_MASK_SHIFT 6 +#define PAGE_BYTE_MASK_OFFSET_MASK 63 +#define PAGE_BYTE_MASK_MASK 63 + #define EVICT_NOT_IN_LIST ((uint32_t)-1) typedef struct page_t { @@ -121,14 +128,17 @@ typedef struct page_t uint8_t *mem; - uint16_t block[4], block_2[4]; + uint16_t block, block_2; /*Head of codeblock tree associated with this page*/ uint16_t head; - uint64_t code_present_mask[4], dirty_mask[4]; + uint64_t code_present_mask, dirty_mask; uint32_t evict_prev, evict_next; + + uint64_t *byte_dirty_mask; + uint64_t *byte_code_present_mask; } page_t; extern page_t *pages;