From e24298c28ad7492a342693c904fbe5f4e6ac7a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Strohh=C3=A4cker?= Date: Thu, 26 Jan 2006 21:07:17 +0000 Subject: [PATCH] dynamic core: add memory checking stack functions (Descent1), move rarely executed blocks to end of cacheblock Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2435 --- src/cpu/core_dyn_x86/decoder.h | 169 +++++++++++++++++++++++++------- src/cpu/core_dyn_x86/risc_x86.h | 10 ++ src/cpu/core_dyn_x86/string.h | 24 +++-- 3 files changed, 153 insertions(+), 50 deletions(-) diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index 274df299..ecede836 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -135,13 +135,32 @@ static INLINE void dyn_set_eip_end(void) { gen_protectflags(); gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.code-decode.code_start); } - + +static INLINE void dyn_set_eip_end(DynReg * endreg) { + gen_protectflags(); + gen_dop_word(DOP_MOV,cpu.code.big,DREG(TMPW),DREG(EIP)); + gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(TMPW),decode.code-decode.code_start); +} + static INLINE void dyn_set_eip_last(void) { gen_protectflags(); gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.op_start-decode.code_start); } +enum save_info_type {exception, cycle_check, normal}; + +struct { + save_info_type type; + DynState state; + Bit8u * branch_pos; + Bit32u eip_change; + Bitu cycles; +} save_info[512]; + +Bitu used_save_info=0; + + static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub,Bit32u dflags) { reg_flags=(dflags&FMASK_TEST) | (reg_flags&(~FMASK_TEST)); reg_eip+=eip_add; @@ -152,31 +171,53 @@ static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub,Bit32u dflags } static void dyn_check_bool_exception(DynReg * check) { - Bit8u * branch;DynState state; gen_dop_byte(DOP_OR,check,0,check,0); - branch=gen_create_branch(BR_Z); - dyn_savestate(&state); + save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ); + dyn_savestate(&save_info[used_save_info].state); if (!decode.cycles) decode.cycles++; - dyn_save_critical_regs(); - if (cpu.code.big) gen_call_function((void *)&DynRunException,"%Id%Id%F",decode.op_start-decode.code_start,decode.cycles); - else gen_call_function((void *)&DynRunException,"%Iw%Id%F",(decode.op_start-decode.code_start)&0xffff,decode.cycles); - gen_return_fast(BR_Normal,true); - dyn_loadstate(&state); - gen_fill_branch(branch); + save_info[used_save_info].cycles=decode.cycles; + save_info[used_save_info].eip_change=decode.op_start-decode.code_start; + if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff; + save_info[used_save_info].type=exception; + used_save_info++; } static void dyn_check_bool_exception_al(void) { - Bit8u * branch;DynState state; cache_addw(0xc00a); // or al, al - branch=gen_create_branch(BR_Z); - dyn_savestate(&state); + save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ); + dyn_savestate(&save_info[used_save_info].state); if (!decode.cycles) decode.cycles++; - dyn_save_critical_regs(); - if (cpu.code.big) gen_call_function((void *)&DynRunException,"%Id%Id%F",decode.op_start-decode.code_start,decode.cycles); - else gen_call_function((void *)&DynRunException,"%Iw%Id%F",(decode.op_start-decode.code_start)&0xffff,decode.cycles); - gen_return_fast(BR_Normal,true); - dyn_loadstate(&state); - gen_fill_branch(branch); + save_info[used_save_info].cycles=decode.cycles; + save_info[used_save_info].eip_change=decode.op_start-decode.code_start; + if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff; + save_info[used_save_info].type=exception; + used_save_info++; +} + +static void dyn_fill_blocks(void) { + for (Bitu sct=0; sct> 6) & 3; @@ -903,10 +992,11 @@ static void dyn_load_seg_off_ea(SegNames seg) { dyn_get_modrm(); if (GCC_UNLIKELY(decode.modrm.mod<3)) { dyn_fill_ea(); - gen_lea(DREG(TMPW),DREG(EA),0,0,decode.big_op ? 4:2); - dyn_read_word(DREG(TMPW),DREG(TMPW),false); - dyn_read_word_release(DREG(EA),&DynRegs[decode.modrm.reg],decode.big_op); - dyn_load_seg(seg,DREG(TMPW));gen_releasereg(DREG(TMPW)); + gen_lea(DREG(TMPB),DREG(EA),0,0,decode.big_op ? 4:2); + dyn_read_word(DREG(TMPB),DREG(TMPB),false); + dyn_read_word_release(DREG(EA),DREG(TMPW),decode.big_op); + dyn_load_seg(seg,DREG(TMPB));gen_releasereg(DREG(TMPB)); + gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.reg],DREG(TMPW)); } else { IllegalOption("dyn_load_seg_off_ea"); } @@ -953,7 +1043,9 @@ static void dyn_pop_ev(void) { dyn_get_modrm(); if (decode.modrm.mod<3) { dyn_fill_ea(); - dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op); +// dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op); + if (decode.big_op) gen_call_function((void *)&mem_writed_dyncorex86,"%Ddr%Dd",DREG(EA),DREG(TMPW)); + else gen_call_function((void *)&mem_writew_dyncorex86,"%Ddr%Dd",DREG(EA),DREG(TMPW)); } else { gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW)); } @@ -976,7 +1068,7 @@ static void dyn_leave(void) { gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(EBP)); gen_dop_word(DOP_AND,true,DREG(TMPW),DREG(SMASK)); gen_dop_word(DOP_OR,true,DREG(ESP),DREG(TMPW)); - dyn_pop(DREG(EBP)); + dyn_pop_unchecked(DREG(EBP)); gen_releasereg(DREG(TMPW)); } @@ -988,6 +1080,7 @@ static void dyn_segprefix(SegNames seg) { static void dyn_closeblock(void) { //Shouldn't create empty block normally but let's do it like this gen_protectflags(); + dyn_fill_blocks(); cache_closeblock(); } @@ -1108,9 +1201,10 @@ static void dyn_call_near_imm(void) { Bits imm; if (decode.big_op) imm=(Bit32s)decode_fetchd(); else imm=(Bit16s)decode_fetchw(); - dyn_set_eip_end(); - dyn_push(DREG(EIP)); - gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),imm); + dyn_set_eip_end(DREG(TMPW)); + dyn_push(DREG(TMPW)); + gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(TMPW),imm); + gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),DREG(TMPW)); dyn_reduce_cycles(); dyn_save_critical_regs(); gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start)); @@ -1200,9 +1294,9 @@ static CacheBlock * CreateCacheBlock(CodePageHandler * codepage,PhysPt start,Bit /* Start with the cycles check */ gen_protectflags(); gen_dop_word_imm(DOP_CMP,true,DREG(CYCLES),0); - Bit8u * cyclebranch=gen_create_branch(BR_NLE); - gen_return(BR_Cycles); - gen_fill_branch(cyclebranch); + save_info[used_save_info].branch_pos=gen_create_branch_long(BR_LE); + save_info[used_save_info].type=cycle_check; + used_save_info++; gen_releasereg(DREG(CYCLES)); decode.cycles=0; while (max_opcodes--) { @@ -1344,13 +1438,13 @@ restart_prefix: case 0x60: /* PUSHA */ gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(ESP)); for (i=G_EAX;i<=G_EDI;i++) { - dyn_push((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW)); + dyn_push_unchecked((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW)); } gen_releasereg(DREG(TMPW)); break; case 0x61: /* POPA */ for (i=G_EDI;i>=G_EAX;i--) { - dyn_pop((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW)); + dyn_pop_unchecked((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW)); } gen_releasereg(DREG(TMPW)); break; @@ -1690,8 +1784,9 @@ restart_prefix: } break; case 0x2: /* CALL Ev */ - gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); - dyn_push(DREG(EIP)); + gen_lea(DREG(TMPB),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_push(DREG(TMPB)); + gen_releasereg(DREG(TMPB)); gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),src); goto core_close_block; case 0x4: /* JMP Ev */ diff --git a/src/cpu/core_dyn_x86/risc_x86.h b/src/cpu/core_dyn_x86/risc_x86.h index 65d1ab68..d3a2856a 100644 --- a/src/cpu/core_dyn_x86/risc_x86.h +++ b/src/cpu/core_dyn_x86/risc_x86.h @@ -765,6 +765,16 @@ static void gen_fill_branch(Bit8u * data,Bit8u * from=cache.pos) { *data=(from-data-1); } +static Bit8u * gen_create_branch_long(BranchTypes type) { + cache_addw(0x800f+(type<<8)); + cache_addd(0); + return (cache.pos-4); +} + +static void gen_fill_branch_long(Bit8u * data,Bit8u * from=cache.pos) { + *(Bit32u*)data=(from-data-4); +} + static Bit8u * gen_create_jump(Bit8u * to=0) { /* First free all registers */ cache_addb(0xe9); diff --git a/src/cpu/core_dyn_x86/string.h b/src/cpu/core_dyn_x86/string.h index 13748c56..48d61672 100644 --- a/src/cpu/core_dyn_x86/string.h +++ b/src/cpu/core_dyn_x86/string.h @@ -83,9 +83,7 @@ static void dyn_string(STRING_OP op) { /* Check if ECX!=zero */ if (decode.rep) { gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX)); - Bit8u * branch_ecx=gen_create_branch(BR_NZ); - rep_ecx_jmp=gen_create_jump(); - gen_fill_branch(branch_ecx); + rep_ecx_jmp=gen_create_branch_long(BR_Z); } if (usesi) { if (!decode.big_addr) { @@ -146,21 +144,21 @@ static void dyn_string(STRING_OP op) { if (usedi) gen_dop_word(DOP_ADD,decode.big_addr,DREG(EDI),DREG(TMPW)); if (decode.rep) { - DynState cycle_state; gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX)); gen_sop_word(SOP_DEC,true,DREG(CYCLES)); gen_releasereg(DREG(CYCLES)); - dyn_savestate(&cycle_state); - Bit8u * cycle_branch=gen_create_branch(BR_NLE); - gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start); - dyn_save_critical_regs(); - gen_return(BR_Cycles); - gen_fill_branch(cycle_branch); - dyn_loadstate(&cycle_state); - dyn_synchstate(&rep_state); + dyn_savestate(&save_info[used_save_info].state); + save_info[used_save_info].branch_pos=gen_create_branch_long(BR_LE); + save_info[used_save_info].eip_change=decode.op_start-decode.code_start; + save_info[used_save_info].type=normal; + used_save_info++; + /* Jump back to start of ECX check */ + dyn_synchstate(&rep_state); gen_create_jump(rep_start); - gen_fill_jump(rep_ecx_jmp); + + dyn_loadstate(&rep_state); + gen_fill_branch_long(rep_ecx_jmp); } gen_releasereg(DREG(TMPW)); }