From 51489d031ceb729d9a2c38744eb02befc94ec254 Mon Sep 17 00:00:00 2001 From: TomW Date: Wed, 8 Jul 2015 20:40:37 +0100 Subject: [PATCH] Reduced number of segment/selector checks in recompiler - minor speedup. --- src/codegen_ops_x86.h | 22 ++++++++++++++++++++++ src/codegen_x86.c | 2 ++ src/ibm.h | 3 +++ src/x86seg.c | 6 ++++++ 4 files changed, 33 insertions(+) diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h index 3ba492b..8a136c2 100644 --- a/src/codegen_ops_x86.h +++ b/src/codegen_ops_x86.h @@ -462,6 +462,15 @@ static void SAR_L_IMM(int reg, int count) static void CHECK_SEG_READ(x86seg *seg) { + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &_cs || seg == &_ss) + return; + if (seg->checked) + return; + addbyte(0x83); /*CMP seg->base, -1*/ addbyte(0x05|0x38); addlong((uint32_t)&seg->base); @@ -469,9 +478,20 @@ static void CHECK_SEG_READ(x86seg *seg) addbyte(0x0f); addbyte(0x84); /*JE end*/ addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + + seg->checked = 1; } static void CHECK_SEG_WRITE(x86seg *seg) { + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &_cs || seg == &_ss) + return; + if (seg->checked) + return; + addbyte(0x83); /*CMP seg->base, -1*/ addbyte(0x05|0x38); addlong((uint32_t)&seg->base); @@ -479,6 +499,8 @@ static void CHECK_SEG_WRITE(x86seg *seg) addbyte(0x0f); addbyte(0x84); /*JE end*/ addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + + seg->checked = 1; } static void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) { diff --git a/src/codegen_x86.c b/src/codegen_x86.c index 1528590..b06859e 100644 --- a/src/codegen_x86.c +++ b/src/codegen_x86.c @@ -261,6 +261,8 @@ void codegen_block_init(uint32_t phys_addr) codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; + + _ds.checked = _es.checked = _fs.checked = _gs.checked = (cr0 & 1) ? 0 : 1; } void codegen_block_remove() diff --git a/src/ibm.h b/src/ibm.h index 4c5cd67..85e11d2 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -114,6 +114,9 @@ typedef struct uint8_t access; uint16_t seg; uint32_t limit_low, limit_high; +#ifdef DYNAREC + int checked; /*Non-zero if selector is known to be valid*/ +#endif } x86seg; x86seg gdt,ldt,idt,tr; diff --git a/src/x86seg.c b/src/x86seg.c index 0355b03..8de8923 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -395,6 +395,9 @@ void loadseg(uint16_t seg, x86seg *s) #endif #ifndef CS_ACCESSED } +#endif +#ifdef DYNAREC + s->checked = 0; #endif } else @@ -404,6 +407,9 @@ void loadseg(uint16_t seg, x86seg *s) s->seg = seg; if (s == &_ss) stack32 = 0; +#ifdef DYNAREC + s->checked = 1; +#endif } }