From 3d37ed73cd73ddd2a3a1214002aff92ea25a2d3f Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 7 Feb 2018 23:44:51 +0100 Subject: [PATCH] Replaced the mmutranslate functions in mem.c with slightly altered versions of Sarah's, should increase performance even slightly more. --- src/mem.c | 193 +++++++++++++++++++++++------------------------------- 1 file changed, 82 insertions(+), 111 deletions(-) diff --git a/src/mem.c b/src/mem.c index 2b08cb2a6..18a0d6700 100644 --- a/src/mem.c +++ b/src/mem.c @@ -196,124 +196,95 @@ int pctrans=0; extern uint32_t testr[9]; -static __inline__ int mem_cpl3_check(void) -{ - if ((CPL == 3) && !cpl_override) - { - return 1; - } - return 0; -} - -static __inline__ void mmu_page_fault(uint32_t addr, uint32_t error_code) -{ - cr2 = addr; - cpu_state.abrt = ABRT_PF; - abrt_error = error_code; -} - -static __inline__ int mmu_page_fault_check(uint32_t addr, int rw, uint32_t flags, int pde, int is_abrt) -{ - uint8_t error_code = 0; - - uint8_t is_page_fault = 0; - - if (CPL == 3) error_code = 4; /* If the page fault has occurred at CPL 3, this should be set. */ - if (rw) error_code |= 2; /* If the page has occurred during a write, this should be set. */ - - /* Apparently, this check should not be done on PSE. */ - if (!(flags & 1)) - is_page_fault = 1; - else - error_code |= 1; /* If the page is present, the error must indicate that it is. */ - - if (!(flags & 4) && mem_cpl3_check()) { - /* The user/supervisor check needs to be checked for the table as well, *before* checking it for the page. */ - is_page_fault = 1; - } - - /* Only check the write-protect flag if this is a page directory entry. */ - if (pde && rw && !(flags & 2) && ((cr0 & WP_FLAG) || mem_cpl3_check())) - is_page_fault = 1; - - if (is_page_fault) { - if (is_abrt) - mmu_page_fault(addr, error_code); - return -1; - } - - return 0; -} - -#define PAGE_DIRTY_AND_ACCESSED 0x60 -#define PAGE_DIRTY 0x40 -#define PAGE_ACCESSED 0x20 - -/* rw means 0 = read, 1 = write */ -uint32_t mmutranslate(uint32_t addr, int rw, int is_abrt) -{ - /* Mask out the lower 12 bits. */ - uint32_t dir_base = 0; - - uint32_t table_addr = 0; - uint32_t page_addr = 0; - - uint32_t table_flags = 0; - uint32_t page_flags = 0; - - if (cpu_state.abrt) - return -1; - - dir_base = cr3 & ~0xfff; - table_addr = dir_base + ((addr >> 20) & 0xffc); - - /* First check the flags of the page directory entry. */ - table_flags = *(uint32_t *) &_mem_exec[table_addr >> 14][table_addr & 0x3fff]; - - if ((table_flags & 0x80) && (cr4 & CR4_PSE)) { - /* Do a PDE-style page fault check. */ - if (mmu_page_fault_check(addr, rw, table_flags & 7, 1, is_abrt) == -1) - return -1; - - /* Since PSE is not enabled, there is no page table, so we do a slightly modified skip to the end. */ - if (is_abrt) { - mmu_perm = table_flags & 4; - *(uint32_t *) &_mem_exec[table_addr >> 14][table_addr & 0x3fff] = table_flags | (rw ? PAGE_DIRTY_AND_ACCESSED : PAGE_ACCESSED); - } - - return (table_flags & ~0x3FFFFF) + (addr & 0x3FFFFF); - } else { - /* Do a non-PDE-style page fault check. */ - if (mmu_page_fault_check(addr, rw, table_flags & 7, 0, is_abrt) == -1) - return -1; - } - - page_addr = table_flags & ~0xfff; - page_addr += ((addr >> 10) & 0xffc); - - /* Then check the flags of the page table entry. */ - page_flags = *(uint32_t *) &_mem_exec[page_addr >> 14][page_addr & 0x3fff]; - - if (mmu_page_fault_check(addr, rw, page_flags & 7, 1, is_abrt) == -1) - return -1; - - if (is_abrt) { - mmu_perm = page_flags & 4; - *(uint32_t *) &_mem_exec[table_addr >> 14][table_addr & 0x3fff] = table_flags | PAGE_ACCESSED; - *(uint32_t *) &_mem_exec[page_addr >> 14][page_addr & 0x3fff] = page_flags | (rw ? PAGE_DIRTY_AND_ACCESSED : PAGE_ACCESSED); - } - - return (page_flags & ~0xFFF) + (addr & 0xFFF); -} +#define rammap(x) ((uint32_t *)(_mem_exec[(x) >> 14]))[((x) >> 2) & 0xfff] uint32_t mmutranslatereal(uint32_t addr, int rw) { - return mmutranslate(addr, rw, 1); + uint32_t addr2; + uint32_t temp,temp2,temp3; + + if (cpu_state.abrt) + return -1; + addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); + temp=temp2=rammap(addr2); + if (!(temp&1)) { + cr2=addr; + temp&=1; + if (CPL==3) temp|=4; + if (rw) temp|=2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return -1; + } + + if ((temp & 0x80) && (cr4 & CR4_PSE)) { + /*4MB page*/ + if ((CPL == 3 && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3 && !cpl_override) || cr0 & WP_FLAG))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + + return -1; + } + + mmu_perm = temp & 4; + rammap(addr2) |= 0x20; + + return (temp & ~0x3fffff) + (addr & 0x3fffff); + } + + temp=rammap((temp&~0xFFF)+((addr>>10)&0xFFC)); + temp3=temp&temp2; + if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && ((CPL == 3 && !cpl_override) || cr0&WP_FLAG))) { + cr2=addr; + temp&=1; + if (CPL==3) temp|=4; + if (rw) temp|=2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return -1; + } + mmu_perm=temp&4; + rammap(addr2)|=0x20; + rammap((temp2&~0xFFF)+((addr>>10)&0xFFC))|=(rw?0x60:0x20); + + return (temp&~0xFFF)+(addr&0xFFF); } uint32_t mmutranslate_noabrt(uint32_t addr, int rw) { - return mmutranslate(addr, rw, 0); + uint32_t addr2; + uint32_t temp,temp2,temp3; + + if (cpu_state.abrt) + return -1; + + addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); + temp=temp2=rammap(addr2); + + if (!(temp&1)) + return -1; + + if ((temp & 0x80) && (cr4 & CR4_PSE)) { + /*4MB page*/ + if ((CPL == 3 && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (CPL == 3 || cr0 & WP_FLAG))) + return -1; + + return (temp & ~0x3fffff) + (addr & 0x3fffff); + } + + temp=rammap((temp&~0xFFF)+((addr>>10)&0xFFC)); + temp3=temp&temp2; + + if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && (CPL==3 || cr0&WP_FLAG))) + return -1; + + return (temp&~0xFFF)+(addr&0xFFF); } void mmu_invalidate(uint32_t addr)