--- np2/i386c/ia32/paging.c 2004/03/08 12:56:22 1.15 +++ np2/i386c/ia32/paging.c 2004/03/23 22:39:40 1.20 @@ -1,7 +1,7 @@ -/* $Id: paging.c,v 1.15 2004/03/08 12:56:22 monaka Exp $ */ +/* $Id: paging.c,v 1.20 2004/03/23 22:39:40 yui Exp $ */ /* - * Copyright (c) 2003 NONAKA Kimihiro + * Copyright (c) 2003-2004 NONAKA Kimihiro * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -184,15 +184,15 @@ static const UINT8 page_access_bit[32] = * +- CR3(物理アドレス) */ -static UINT32 paging(UINT32 laddr, int crw, int user_mode); +static UINT32 paging(const UINT32 laddr, const int crw, const int user_mode); #if defined(IA32_SUPPORT_TLB) -static BOOL tlb_lookup(UINT32 vaddr, int crw, UINT32 *paddr); -static void tlb_update(UINT32 laddr, UINT entry, int crw); +static BOOL tlb_lookup(const UINT32 vaddr, const int crw, UINT32 *paddr); +static void tlb_update(const UINT32 laddr, const UINT entry, const int crw); #endif void MEMCALL -cpu_memory_access_la_region(UINT32 laddr, UINT length, int crw, int user_mode, BYTE *data) +cpu_memory_access_la_region(UINT32 laddr, UINT length, const int crw, const int user_mode, BYTE *data) { UINT32 paddr; UINT remain; /* page remain */ @@ -231,112 +231,347 @@ cpu_memory_access_la_region(UINT32 laddr } UINT32 MEMCALL -cpu_linear_memory_read(UINT32 laddr, UINT length, int crw, int user_mode) +cpu_memory_access_la_RMW(UINT32 laddr, UINT length, const int user_mode, UINT32 (*func)(UINT32, void *), void *arg) { - UINT32 value = 0; - UINT32 paddr; - UINT remain; /* page remain */ - UINT r; - int shift = 0; + const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); + UINT32 result, value; + UINT32 paddr[2]; + UINT remain; + paddr[0] = paging(laddr, crw, user_mode); remain = 0x1000 - (laddr & 0x00000fff); - for (;;) { - paddr = paging(laddr, crw, user_mode); - - r = (remain > length) ? length : remain; - switch (r) { + if (remain >= length) { + /* fast mode */ + switch (length) { case 4: - value = cpu_memoryread_d(paddr); + value = cpu_memoryread_d(paddr[0]); + result = (*func)(value, arg); + cpu_memorywrite_d(paddr[0], result); break; - case 3: - value += (UINT32)cpu_memoryread(paddr) << shift; - shift += 8; - paddr++; - /*FALLTHROUGH*/ case 2: - value += (UINT32)cpu_memoryread_w(paddr) << shift; - shift += 16; + value = cpu_memoryread_w(paddr[0]); + result = (*func)(value, arg); + cpu_memorywrite_w(paddr[0], (UINT16)result); break; case 1: - value += (UINT32)cpu_memoryread(paddr) << shift; - shift += 8; + value = cpu_memoryread(paddr[0]); + result = (*func)(value, arg); + cpu_memorywrite(paddr[0], (UINT8)result); break; default: - ia32_panic("cpu_linear_memory_read(): out of range (r = %d)\n", r); + ia32_panic("cpu_memory_access_la_RMW(): invalid length (length = %d)\n", length); + value = 0; /* compiler happy */ break; } + return value; + } - length -= r; - if (length == 0) - break; + /* slow mode */ + paddr[1] = paging(laddr + remain, crw, user_mode); + switch (remain) { + case 3: + value = cpu_memoryread(paddr[0]); + value += (UINT32)cpu_memoryread_w(paddr[0] + 1) << 8; + value += (UINT32)cpu_memoryread(paddr[1]) << 24; + result = (*func)(value, arg); + cpu_memorywrite(paddr[0], (UINT8)result); + cpu_memorywrite_w(paddr[0] + 1, (UINT16)(result >> 8)); + cpu_memorywrite(paddr[1], (BYTE)(result >> 24)); + break; + + case 2: + value = cpu_memoryread_w(paddr[0]); + value += (UINT32)cpu_memoryread_w(paddr[1]) << 16; + result = (*func)(value, arg); + cpu_memorywrite_w(paddr[0], (UINT16)result); + cpu_memorywrite_w(paddr[1], (UINT16)(result >> 16)); + break; + + case 1: + value = cpu_memoryread(paddr[0]); + value += (UINT32)cpu_memoryread(paddr[1]) << 8; + if (length == 4) { + value += (UINT32)cpu_memoryread_w(paddr[1] + 1) << 16; + } + result = (*func)(value, arg); + cpu_memorywrite(paddr[0], (UINT8)result); + cpu_memorywrite(paddr[1], (UINT8)(result >> 8)); + if (length == 4) { + cpu_memorywrite_w(paddr[1] + 1, (UINT16)(result >> 16)); + } + break; + + default: + ia32_panic("cpu_memory_access_la_RMW(): out of range (remain = %d)\n", remain); + value = 0; /* compiler happy */ + break; + } + return value; +} - laddr += r; - remain -= r; - if (remain <= 0) { - /* next page */ - remain += 0x1000; + +#if defined(IA32_PAGING_EACHSIZE) +UINT8 MEMCALL +cpu_linear_memory_read_b(UINT32 laddr, const int crw, const int user_mode) +{ + UINT32 addr; + + addr = paging(laddr, crw, user_mode); + return(cpu_memoryread(addr)); +} + +UINT16 MEMCALL +cpu_linear_memory_read_w(UINT32 laddr, const int crw, const int user_mode) +{ + UINT32 addr; + UINT32 addr2; + UINT16 value; + + addr = paging(laddr, crw, user_mode); + if ((laddr + 1) & 0x00000fff) { + return(cpu_memoryread_w(addr)); + } + else { + addr2 = paging(laddr + 1, crw, user_mode); + value = cpu_memoryread_b(addr); + value += (UINT16)cpu_memoryread_b(addr2) << 8; + return(value); + } +} + +UINT32 MEMCALL +cpu_linear_memory_read_d(UINT32 laddr, const int crw, const int user_mode) +{ + UINT32 addr; + UINT remain; + UINT32 addr2; + UINT32 value; + + addr = paging(laddr, crw, user_mode); + remain = 0x1000 - (laddr & 0x00000fff); + if (remain >= 4) { + return(cpu_memoryread_d(addr)); + } + else { + addr2 = paging(laddr + remain, crw, user_mode); + switch (remain) { + case 3: + value = cpu_memoryread(addr); + value += (UINT32)cpu_memoryread_w(addr + 1) << 8; + value += (UINT32)cpu_memoryread(addr2) << 24; + break; + + case 2: + value = cpu_memoryread_w(addr); + value += (UINT32)cpu_memoryread_w(addr2) << 16; + break; + + case 1: + value = cpu_memoryread(addr); + value += (UINT32)cpu_memoryread(addr2) << 8; + value += (UINT32)cpu_memoryread_w(addr2 + 1) << 16; + break; + + default: + ia32_panic("cpu_linear_memory_read_d(): out of range (remain = %d)\n", remain); + value = 0; /* compiler happy */ + break; } + return value; } +} - return value; +void MEMCALL +cpu_linear_memory_write_b(UINT32 laddr, UINT8 value, const int user_mode) +{ + const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); + UINT32 addr; + + addr = paging(laddr, crw, user_mode); + cpu_memorywrite(addr, value); } void MEMCALL -cpu_linear_memory_write(UINT32 laddr, UINT32 value, UINT length, int user_mode) +cpu_linear_memory_write_w(UINT32 laddr, UINT16 value, const int user_mode) { - UINT32 paddr; - UINT remain; /* page remain */ - UINT r; - int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); + const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); + UINT32 addr; + UINT32 addr2; + + addr = paging(laddr, crw, user_mode); + if ((laddr + 1) & 0x00000fff) { + cpu_memorywrite_w(addr, value); + } + else { + addr2 = paging(laddr + 1, crw, user_mode); + cpu_memorywrite(addr, (UINT8)value); + cpu_memorywrite(addr2, (UINT8)(value >> 8)); + } +} + +void MEMCALL +cpu_linear_memory_write_d(UINT32 laddr, UINT32 value, const int user_mode) +{ + const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); + UINT32 addr; + UINT remain; + UINT32 addr2; + addr = paging(laddr, crw, user_mode); remain = 0x1000 - (laddr & 0x00000fff); - for (;;) { - paddr = paging(laddr, crw, user_mode); + if (remain >= 4) { + cpu_memorywrite_d(addr, value); + } + else { + addr2 = paging(laddr + remain, crw, user_mode); + switch (remain) { + case 3: + cpu_memorywrite(addr, (UINT8)value); + cpu_memorywrite_w(addr + 1, (UINT16)(value >> 8)); + cpu_memorywrite(addr2, (UINT8)(value >> 24)); + break; + + case 2: + cpu_memorywrite_w(addr, (UINT16)value); + cpu_memorywrite_w(addr2, (UINT16)(value >> 16)); + break; + + case 1: + cpu_memorywrite(addr, (UINT8)value); + cpu_memorywrite(addr2, (UINT8)(value >> 8)); + cpu_memorywrite_w(addr2 + 1, (UINT16)(value >> 16)); + break; + } + } +} +#else // IA32_PAGING_EACHSIZE +UINT32 MEMCALL +cpu_linear_memory_read(UINT32 laddr, UINT length, const int crw, const int user_mode) +{ + UINT32 value; + UINT32 paddr[2]; + UINT remain; - r = (remain > length) ? length : remain; - switch (r) { + paddr[0] = paging(laddr, crw, user_mode); + remain = 0x1000 - (laddr & 0x00000fff); + if (remain >= length) { + /* fast mode */ + switch (length) { case 4: - cpu_memorywrite_d(paddr, value); + value = cpu_memoryread_d(paddr[0]); break; - case 3: - cpu_memorywrite(paddr, value & 0xff); - value >>= 8; - paddr++; - /*FALLTHROUGH*/ case 2: - cpu_memorywrite_w(paddr, value & 0xffff); - value >>= 16; + value = cpu_memoryread_w(paddr[0]); break; case 1: - cpu_memorywrite(paddr, value & 0xff); - value >>= 8; + value = cpu_memoryread(paddr[0]); break; default: - ia32_panic("cpu_linear_memory_write(): out of range (r = %d)\n", r); + ia32_panic("cpu_linear_memory_read(): invalid length (length = %d)\n", length); + value = 0; /* compiler happy */ break; } + return value; + } - length -= r; - if (length == 0) + /* slow mode */ + paddr[1] = paging(laddr + remain, crw, user_mode); + switch (remain) { + case 3: + value = cpu_memoryread(paddr[0]); + value += (UINT32)cpu_memoryread_w(paddr[0] + 1) << 8; + value += (UINT32)cpu_memoryread(paddr[1]) << 24; + break; + + case 2: + value = cpu_memoryread_w(paddr[0]); + value += (UINT32)cpu_memoryread_w(paddr[1]) << 16; + break; + + case 1: + value = cpu_memoryread(paddr[0]); + value += (UINT32)cpu_memoryread(paddr[1]) << 8; + if (length == 4) { + value += (UINT32)cpu_memoryread_w(paddr[1] + 1) << 16; + } + break; + + default: + ia32_panic("cpu_linear_memory_read(): out of range (remain = %d)\n", remain); + value = 0; /* compiler happy */ + break; + } + return value; +} + +void MEMCALL +cpu_linear_memory_write(UINT32 laddr, UINT32 value, UINT length, const int user_mode) +{ + const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); + UINT32 paddr[2]; + UINT remain; + + paddr[0] = paging(laddr, crw, user_mode); + remain = 0x1000 - (laddr & 0x00000fff); + if (remain >= length) { + /* fast mode */ + switch (length) { + case 4: + cpu_memorywrite_d(paddr[0], value); break; - laddr += r; - remain -= r; - if (remain <= 0) { - /* next page */ - remain += 0x1000; + case 2: + cpu_memorywrite_w(paddr[0], (UINT16)value); + break; + + case 1: + cpu_memorywrite(paddr[0], (UINT8)value); + break; + + default: + ia32_panic("cpu_linear_memory_write(): invalid length (length = %d)\n", length); + break; } + return; + } + + /* slow mode */ + paddr[1] = paging(laddr + remain, crw, user_mode); + switch (remain) { + case 3: + cpu_memorywrite(paddr[0], (UINT8)value); + cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); + cpu_memorywrite(paddr[1], (UINT8)(value >> 24)); + break; + + case 2: + cpu_memorywrite_w(paddr[0], (UINT16)value); + cpu_memorywrite_w(paddr[1], (UINT16)(value >> 16)); + break; + + case 1: + cpu_memorywrite(paddr[0], (UINT8)value); + cpu_memorywrite(paddr[1], (UINT8)(value >> 8)); + if (length == 4) { + cpu_memorywrite_w(paddr[1] + 1, (UINT16)(value >> 16)); + } + break; + + default: + ia32_panic("cpu_linear_memory_write(): out of range (remain = %d)\n", remain); + break; } } +#endif // IA32_PAGING_EACHSIZE void MEMCALL -paging_check(UINT32 laddr, UINT length, int crw, int user_mode) +paging_check(UINT32 laddr, UINT length, const int crw, const int user_mode) { UINT32 paddr; UINT remain; /* page remain */ @@ -362,7 +597,7 @@ paging_check(UINT32 laddr, UINT length, } static UINT32 -paging(UINT32 laddr, int crw, int user_mode) +paging(const UINT32 laddr, const int crw, const int user_mode) { UINT32 paddr; /* physical address */ UINT32 pde_addr; /* page directory entry address */ @@ -575,7 +810,7 @@ tlb_flush_page(UINT32 laddr) } static BOOL -tlb_lookup(UINT32 laddr, int crw, UINT32 *paddr) +tlb_lookup(const UINT32 laddr, const int crw, UINT32 *paddr) { TLB_ENTRY_T *ep; int idx; @@ -601,7 +836,7 @@ tlb_lookup(UINT32 laddr, int crw, UINT32 } static void -tlb_update(UINT32 laddr, UINT entry, int crw) +tlb_update(const UINT32 laddr, const UINT entry, const int crw) { TLB_ENTRY_T *ep; int idx;