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:
193
src/mem.c
193
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)
|
||||
|
Reference in New Issue
Block a user