Replaced the mmutranslate functions in mem.c with slightly altered versions of Sarah's, should increase performance even slightly more.

This commit is contained in:
OBattler
2018-02-07 23:44:51 +01:00
parent f18cd3d89e
commit 3d37ed73cd

193
src/mem.c
View File

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