|
|
| version 1.19, 2004/03/23 19:32:37 | version 1.22, 2004/03/24 14:34:23 |
|---|---|
| Line 184 static const UINT8 page_access_bit[32] = | Line 184 static const UINT8 page_access_bit[32] = |
| * +- CR3(物理アドレス) | * +- CR3(物理アドレス) |
| */ | */ |
| static UINT32 paging(const UINT32 laddr, const int crw, const int user_mode); | static UINT32 paging(const UINT32 laddr, const int ucrw); |
| #if defined(IA32_SUPPORT_TLB) | #if defined(IA32_SUPPORT_TLB) |
| static BOOL tlb_lookup(const UINT32 vaddr, const int crw, UINT32 *paddr); | 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); | static void tlb_update(const UINT32 laddr, const UINT entry, const int crw); |
| #endif | #endif |
| #if defined(IA32_PAGING_EACHSIZE) | |
| void MEMCALL | UINT8 MEMCALL |
| cpu_memory_access_la_region(UINT32 laddr, UINT length, const int crw, const int user_mode, BYTE *data) | cpu_memory_access_la_RMW_b(UINT32 laddr, UINT32 (*func)(UINT32, void *), void *arg) |
| { | { |
| const int ucrw = CPU_PAGE_WRITE|CPU_PAGE_DATA|CPU_STAT_USER_MODE; | |
| UINT32 result, value; | |
| UINT32 paddr; | UINT32 paddr; |
| UINT remain; /* page remain */ | |
| UINT r; | |
| if (length == 0) | |
| return; | |
| remain = 0x1000 - (laddr & 0x00000fff); | paddr = paging(laddr, ucrw); |
| for (;;) { | value = cpu_memoryread(paddr); |
| if (!CPU_STAT_PAGING) { | result = (*func)(value, arg); |
| paddr = laddr; | cpu_memorywrite(paddr, (UINT8)result); |
| } else { | |
| paddr = paging(laddr, crw, user_mode); | |
| } | |
| r = (remain > length) ? length : remain; | return value; |
| if (!(crw & CPU_PAGE_WRITE)) { | } |
| cpu_memoryread_region(paddr, data, r); | |
| } else { | |
| cpu_memorywrite_region(paddr, data, r); | |
| } | |
| length -= r; | UINT16 MEMCALL |
| if (length == 0) | cpu_memory_access_la_RMW_w(UINT32 laddr, UINT32 (*func)(UINT32, void *), void *arg) |
| break; | { |
| const int ucrw = CPU_PAGE_WRITE|CPU_PAGE_DATA|CPU_STAT_USER_MODE; | |
| UINT32 result, value; | |
| UINT32 paddr[2]; | |
| data += r; | paddr[0] = paging(laddr, ucrw); |
| laddr += r; | if ((laddr + 1) & 0x00000fff) { |
| remain -= r; | value = cpu_memoryread_w(paddr[0]); |
| if (remain <= 0) { | result = (*func)(value, arg); |
| /* next page */ | cpu_memorywrite_w(paddr[0], (UINT16)result); |
| remain += 0x1000; | } else { |
| } | paddr[1] = paging(laddr + 1, ucrw); |
| value = cpu_memoryread_b(paddr[0]); | |
| value += (UINT16)cpu_memoryread_b(paddr[1]) << 8; | |
| result = (*func)(value, arg); | |
| cpu_memorywrite(paddr[0], (UINT8)result); | |
| cpu_memorywrite(paddr[1], (UINT8)(result >> 8)); | |
| } | } |
| return value; | |
| } | } |
| UINT32 MEMCALL | UINT32 MEMCALL |
| cpu_memory_access_la_RMW(UINT32 laddr, UINT length, const int user_mode, UINT32 (*func)(UINT32, void *), void *arg) | cpu_memory_access_la_RMW_d(UINT32 laddr, UINT32 (*func)(UINT32, void *), void *arg) |
| { | { |
| const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); | const int ucrw = CPU_PAGE_WRITE|CPU_PAGE_DATA|CPU_STAT_USER_MODE; |
| UINT32 result, value; | UINT32 result, value; |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| UINT remain; | UINT remain; |
| paddr[0] = paging(laddr, crw, user_mode); | paddr[0] = paging(laddr, ucrw); |
| remain = 0x1000 - (laddr & 0x00000fff); | remain = 0x1000 - (laddr & 0x00000fff); |
| if (remain >= length) { | if (remain >= 4) { |
| /* fast mode */ | value = cpu_memoryread_d(paddr[0]); |
| switch (length) { | result = (*func)(value, arg); |
| case 4: | cpu_memorywrite_d(paddr[0], result); |
| value = cpu_memoryread_d(paddr[0]); | } else { |
| paddr[1] = paging(laddr + remain, ucrw); | |
| 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); | result = (*func)(value, arg); |
| cpu_memorywrite_d(paddr[0], result); | cpu_memorywrite(paddr[0], (UINT8)result); |
| cpu_memorywrite_w(paddr[0] + 1, (UINT16)(result >> 8)); | |
| cpu_memorywrite(paddr[1], (UINT8)(result >> 24)); | |
| break; | break; |
| case 2: | case 2: |
| value = cpu_memoryread_w(paddr[0]); | value = cpu_memoryread_w(paddr[0]); |
| value += (UINT32)cpu_memoryread_w(paddr[1]) << 16; | |
| result = (*func)(value, arg); | result = (*func)(value, arg); |
| cpu_memorywrite_w(paddr[0], (UINT16)result); | cpu_memorywrite_w(paddr[0], (UINT16)result); |
| cpu_memorywrite_w(paddr[1], (UINT16)(result >> 16)); | |
| break; | break; |
| case 1: | case 1: |
| value = cpu_memoryread(paddr[0]); | value = cpu_memoryread(paddr[0]); |
| value += (UINT32)cpu_memoryread_w(paddr[1]) << 8; | |
| value += (UINT32)cpu_memoryread(paddr[1] + 2) << 24; | |
| result = (*func)(value, arg); | result = (*func)(value, arg); |
| cpu_memorywrite(paddr[0], (UINT8)result); | cpu_memorywrite(paddr[0], (UINT8)result); |
| cpu_memorywrite_w(paddr[1], (UINT16)(result >> 8)); | |
| cpu_memorywrite(paddr[1] + 2, (UINT8)(result >> 24)); | |
| break; | break; |
| default: | default: |
| ia32_panic("cpu_memory_access_la_RMW(): invalid length (length = %d)\n", length); | ia32_panic("cpu_memory_access_la_RMW_d(): out of range (remain = %d)\n", remain); |
| value = 0; /* compiler happy */ | value = 0; /* compiler happy */ |
| break; | break; |
| } | } |
| return value; | |
| } | |
| /* 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; | return value; |
| } | } |
| #if defined(IA32_PAGING_EACHSIZE) | |
| UINT8 MEMCALL | UINT8 MEMCALL |
| cpu_linear_memory_read_b(UINT32 laddr, const int crw, const int user_mode) | cpu_linear_memory_read_b(UINT32 laddr, const int ucrw) |
| { | { |
| UINT32 addr; | UINT32 addr; |
| addr = paging(laddr, crw, user_mode); | addr = paging(laddr, ucrw); |
| return(cpu_memoryread(addr)); | return cpu_memoryread(addr); |
| } | } |
| UINT16 MEMCALL | UINT16 MEMCALL |
| cpu_linear_memory_read_w(UINT32 laddr, const int crw, const int user_mode) | cpu_linear_memory_read_w(UINT32 laddr, const int ucrw) |
| { | { |
| UINT32 addr; | UINT32 addr, addr2; |
| UINT32 addr2; | |
| UINT16 value; | UINT16 value; |
| addr = paging(laddr, crw, user_mode); | addr = paging(laddr, ucrw); |
| if ((laddr + 1) & 0x00000fff) { | if ((laddr + 1) & 0x00000fff) { |
| return(cpu_memoryread_w(addr)); | return cpu_memoryread_w(addr); |
| } | } else { |
| else { | addr2 = paging(laddr + 1, ucrw); |
| addr2 = paging(laddr + 1, crw, user_mode); | |
| value = cpu_memoryread_b(addr); | value = cpu_memoryread_b(addr); |
| value += (UINT16)cpu_memoryread_b(addr2) << 8; | value += (UINT16)cpu_memoryread_b(addr2) << 8; |
| return(value); | return value; |
| } | } |
| } | } |
| UINT32 MEMCALL | UINT32 MEMCALL |
| cpu_linear_memory_read_d(UINT32 laddr, const int crw, const int user_mode) | cpu_linear_memory_read_d(UINT32 laddr, const int ucrw) |
| { | { |
| UINT32 addr; | UINT32 addr, addr2; |
| UINT remain; | |
| UINT32 addr2; | |
| UINT32 value; | UINT32 value; |
| UINT remain; | |
| addr = paging(laddr, crw, user_mode); | addr = paging(laddr, ucrw); |
| remain = 0x1000 - (laddr & 0x00000fff); | remain = 0x1000 - (laddr & 0x00000fff); |
| if (remain >= 4) { | if (remain >= 4) { |
| return(cpu_memoryread_d(addr)); | return cpu_memoryread_d(addr); |
| } | } else { |
| else { | addr2 = paging(laddr + remain, ucrw); |
| addr2 = paging(laddr + remain, crw, user_mode); | |
| switch (remain) { | switch (remain) { |
| case 3: | case 3: |
| value = cpu_memoryread(addr); | value = cpu_memoryread(addr); |
| value += (UINT32)cpu_memoryread_w(addr + 1) << 8; | value += (UINT32)cpu_memoryread_w(addr + 1) << 8; |
| value += (UINT32)cpu_memoryread(addr2) << 24; | value += (UINT32)cpu_memoryread(addr2) << 24; |
| break; | break; |
| case 2: | case 2: |
| value = cpu_memoryread_w(addr); | value = cpu_memoryread_w(addr); |
| value += (UINT32)cpu_memoryread_w(addr2) << 16; | value += (UINT32)cpu_memoryread_w(addr2) << 16; |
| break; | break; |
| case 1: | case 1: |
| value = cpu_memoryread(addr); | value = cpu_memoryread(addr); |
| value += (UINT32)cpu_memoryread(addr2) << 8; | value += (UINT32)cpu_memoryread(addr2) << 8; |
| value += (UINT32)cpu_memoryread_w(addr2 + 1) << 16; | value += (UINT32)cpu_memoryread_w(addr2 + 1) << 16; |
| break; | break; |
| default: | default: |
| ia32_panic("cpu_linear_memory_read_d(): out of range (remain = %d)\n", remain); | ia32_panic("cpu_linear_memory_read_d(): out of range (remain = %d)\n", remain); |
| value = 0; /* compiler happy */ | value = 0; /* compiler happy */ |
| break; | break; |
| } | } |
| return value; | return value; |
| } | } |
| Line 387 cpu_linear_memory_read_d(UINT32 laddr, c | Line 352 cpu_linear_memory_read_d(UINT32 laddr, c |
| void MEMCALL | void MEMCALL |
| cpu_linear_memory_write_b(UINT32 laddr, UINT8 value, const int user_mode) | cpu_linear_memory_write_b(UINT32 laddr, UINT8 value, const int user_mode) |
| { | { |
| const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); | const int ucrw = CPU_PAGE_WRITE|CPU_PAGE_DATA|user_mode; |
| UINT32 addr; | UINT32 addr; |
| addr = paging(laddr, crw, user_mode); | addr = paging(laddr, ucrw); |
| cpu_memorywrite(addr, value); | cpu_memorywrite(addr, value); |
| } | } |
| void MEMCALL | void MEMCALL |
| cpu_linear_memory_write_w(UINT32 laddr, UINT16 value, const int user_mode) | cpu_linear_memory_write_w(UINT32 laddr, UINT16 value, const int user_mode) |
| { | { |
| const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); | const int ucrw = CPU_PAGE_WRITE|CPU_PAGE_DATA|user_mode; |
| UINT32 addr; | UINT32 addr, addr2; |
| UINT32 addr2; | |
| addr = paging(laddr, crw, user_mode); | addr = paging(laddr, ucrw); |
| if ((laddr + 1) & 0x00000fff) { | if ((laddr + 1) & 0x00000fff) { |
| cpu_memorywrite_w(addr, value); | cpu_memorywrite_w(addr, value); |
| } | } else { |
| else { | addr2 = paging(laddr + 1, ucrw); |
| addr2 = paging(laddr + 1, crw, user_mode); | |
| cpu_memorywrite(addr, (UINT8)value); | cpu_memorywrite(addr, (UINT8)value); |
| cpu_memorywrite(addr2, (UINT8)(value >> 8)); | cpu_memorywrite(addr2, (UINT8)(value >> 8)); |
| } | } |
| Line 415 cpu_linear_memory_write_w(UINT32 laddr, | Line 378 cpu_linear_memory_write_w(UINT32 laddr, |
| void MEMCALL | void MEMCALL |
| cpu_linear_memory_write_d(UINT32 laddr, UINT32 value, const int user_mode) | cpu_linear_memory_write_d(UINT32 laddr, UINT32 value, const int user_mode) |
| { | { |
| const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); | const int ucrw = CPU_PAGE_WRITE|CPU_PAGE_DATA|user_mode; |
| UINT32 addr; | UINT32 addr, addr2; |
| UINT remain; | UINT remain; |
| UINT32 addr2; | |
| addr = paging(laddr, crw, user_mode); | addr = paging(laddr, ucrw); |
| remain = 0x1000 - (laddr & 0x00000fff); | remain = 0x1000 - (laddr & 0x00000fff); |
| if (remain >= 4) { | if (remain >= 4) { |
| cpu_memorywrite_d(addr, value); | cpu_memorywrite_d(addr, value); |
| } | } else { |
| else { | addr2 = paging(laddr + remain, ucrw); |
| addr2 = paging(laddr + remain, crw, user_mode); | |
| switch (remain) { | switch (remain) { |
| case 3: | case 3: |
| cpu_memorywrite(addr, (UINT8)value); | cpu_memorywrite(addr, (UINT8)value); |
| cpu_memorywrite_w(addr + 1, (UINT16)(value >> 8)); | cpu_memorywrite_w(addr + 1, (UINT16)(value >> 8)); |
| cpu_memorywrite(addr2, (UINT8)(value >> 24)); | cpu_memorywrite(addr2, (UINT8)(value >> 24)); |
| break; | break; |
| case 2: | case 2: |
| cpu_memorywrite_w(addr, (UINT16)value); | cpu_memorywrite_w(addr, (UINT16)value); |
| cpu_memorywrite_w(addr2, (UINT16)(value >> 16)); | cpu_memorywrite_w(addr2, (UINT16)(value >> 16)); |
| break; | break; |
| case 1: | case 1: |
| cpu_memorywrite(addr, (UINT8)value); | cpu_memorywrite(addr, (UINT8)value); |
| cpu_memorywrite(addr2, (UINT8)(value >> 8)); | cpu_memorywrite(addr2, (UINT8)(value >> 8)); |
| cpu_memorywrite_w(addr2 + 1, (UINT16)(value >> 16)); | cpu_memorywrite_w(addr2 + 1, (UINT16)(value >> 16)); |
| break; | break; |
| } | } |
| } | } |
| } | } |
| #else // IA32_PAGING_EACHSIZE | |
| #else /* !IA32_PAGING_EACHSIZE */ | |
| UINT32 MEMCALL | UINT32 MEMCALL |
| cpu_linear_memory_read(UINT32 laddr, UINT length, const int crw, const int user_mode) | cpu_memory_access_la_RMW(UINT32 laddr, UINT length, UINT32 (*func)(UINT32, void *), void *arg) |
| { | |
| const int ucrw = CPU_PAGE_WRITE|CPU_PAGE_DATA|CPU_STAT_USER_MODE; | |
| UINT32 result, value; | |
| UINT32 paddr[2]; | |
| UINT remain; | |
| paddr[0] = paging(laddr, ucrw); | |
| remain = 0x1000 - (laddr & 0x00000fff); | |
| if (remain >= length) { | |
| /* fast mode */ | |
| switch (length) { | |
| case 4: | |
| value = cpu_memoryread_d(paddr[0]); | |
| result = (*func)(value, arg); | |
| cpu_memorywrite_d(paddr[0], result); | |
| break; | |
| case 2: | |
| value = cpu_memoryread_w(paddr[0]); | |
| result = (*func)(value, arg); | |
| cpu_memorywrite_w(paddr[0], (UINT16)result); | |
| break; | |
| case 1: | |
| value = cpu_memoryread(paddr[0]); | |
| result = (*func)(value, arg); | |
| cpu_memorywrite(paddr[0], (UINT8)result); | |
| break; | |
| default: | |
| ia32_panic("cpu_memory_access_la_RMW(): invalid length (length = %d)\n", length); | |
| value = 0; /* compiler happy */ | |
| break; | |
| } | |
| return value; | |
| } | |
| /* slow mode */ | |
| paddr[1] = paging(laddr + remain, ucrw); | |
| 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], (UINT8)(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; | |
| } | |
| UINT32 MEMCALL | |
| cpu_linear_memory_read(UINT32 laddr, UINT length, const int ucrw) | |
| { | { |
| UINT32 value; | UINT32 value; |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| UINT remain; | UINT remain; |
| paddr[0] = paging(laddr, crw, user_mode); | paddr[0] = paging(laddr, ucrw); |
| remain = 0x1000 - (laddr & 0x00000fff); | remain = 0x1000 - (laddr & 0x00000fff); |
| if (remain >= length) { | if (remain >= length) { |
| /* fast mode */ | /* fast mode */ |
| Line 481 cpu_linear_memory_read(UINT32 laddr, UIN | Line 526 cpu_linear_memory_read(UINT32 laddr, UIN |
| } | } |
| /* slow mode */ | /* slow mode */ |
| paddr[1] = paging(laddr + remain, crw, user_mode); | paddr[1] = paging(laddr + remain, ucrw); |
| switch (remain) { | switch (remain) { |
| case 3: | case 3: |
| value = cpu_memoryread(paddr[0]); | value = cpu_memoryread(paddr[0]); |
| Line 513 cpu_linear_memory_read(UINT32 laddr, UIN | Line 558 cpu_linear_memory_read(UINT32 laddr, UIN |
| void MEMCALL | void MEMCALL |
| cpu_linear_memory_write(UINT32 laddr, UINT32 value, UINT length, const int user_mode) | cpu_linear_memory_write(UINT32 laddr, UINT32 value, UINT length, const int user_mode) |
| { | { |
| const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); | const int ucrw = CPU_PAGE_WRITE|CPU_PAGE_DATA|user_mode; |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| UINT remain; | UINT remain; |
| paddr[0] = paging(laddr, crw, user_mode); | paddr[0] = paging(laddr, ucrw); |
| remain = 0x1000 - (laddr & 0x00000fff); | remain = 0x1000 - (laddr & 0x00000fff); |
| if (remain >= length) { | if (remain >= length) { |
| /* fast mode */ | /* fast mode */ |
| Line 542 cpu_linear_memory_write(UINT32 laddr, UI | Line 587 cpu_linear_memory_write(UINT32 laddr, UI |
| } | } |
| /* slow mode */ | /* slow mode */ |
| paddr[1] = paging(laddr + remain, crw, user_mode); | paddr[1] = paging(laddr + remain, ucrw); |
| switch (remain) { | switch (remain) { |
| case 3: | case 3: |
| cpu_memorywrite(paddr[0], (UINT8)value); | cpu_memorywrite(paddr[0], (UINT8)value); |
| cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); | cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); |
| cpu_memorywrite(paddr[1], (BYTE)(value >> 24)); | cpu_memorywrite(paddr[1], (UINT8)(value >> 24)); |
| break; | break; |
| case 2: | case 2: |
| Line 568 cpu_linear_memory_write(UINT32 laddr, UI | Line 613 cpu_linear_memory_write(UINT32 laddr, UI |
| break; | break; |
| } | } |
| } | } |
| #endif // IA32_PAGING_EACHSIZE | #endif /* IA32_PAGING_EACHSIZE */ |
| void MEMCALL | |
| cpu_memory_access_la_region(UINT32 laddr, UINT length, const int ucrw, BYTE *data) | |
| { | |
| UINT32 paddr; | |
| UINT remain; /* page remain */ | |
| UINT r; | |
| if (length == 0) | |
| return; | |
| remain = 0x1000 - (laddr & 0x00000fff); | |
| for (;;) { | |
| if (!CPU_STAT_PAGING) { | |
| paddr = laddr; | |
| } else { | |
| paddr = paging(laddr, ucrw); | |
| } | |
| r = (remain > length) ? length : remain; | |
| if (!(ucrw & CPU_PAGE_WRITE)) { | |
| cpu_memoryread_region(paddr, data, r); | |
| } else { | |
| cpu_memorywrite_region(paddr, data, r); | |
| } | |
| length -= r; | |
| if (length == 0) | |
| break; | |
| data += r; | |
| laddr += r; | |
| remain -= r; | |
| if (remain <= 0) { | |
| /* next page */ | |
| remain += 0x1000; | |
| } | |
| } | |
| } | |
| void MEMCALL | void MEMCALL |
| paging_check(UINT32 laddr, UINT length, const int crw, const int user_mode) | paging_check(UINT32 laddr, UINT length, const int ucrw) |
| { | { |
| UINT32 paddr; | UINT32 paddr; |
| UINT remain; /* page remain */ | UINT remain; /* page remain */ |
| Line 579 paging_check(UINT32 laddr, UINT length, | Line 663 paging_check(UINT32 laddr, UINT length, |
| remain = 0x1000 - (laddr & 0x00000fff); | remain = 0x1000 - (laddr & 0x00000fff); |
| for (;;) { | for (;;) { |
| paddr = paging(laddr, crw, user_mode); | paddr = paging(laddr, ucrw); |
| r = (remain > length) ? length : remain; | r = (remain > length) ? length : remain; |
| Line 597 paging_check(UINT32 laddr, UINT length, | Line 681 paging_check(UINT32 laddr, UINT length, |
| } | } |
| static UINT32 | static UINT32 |
| paging(const UINT32 laddr, const int crw, const int user_mode) | paging(const UINT32 laddr, const int ucrw) |
| { | { |
| UINT32 paddr; /* physical address */ | UINT32 paddr; /* physical address */ |
| UINT32 pde_addr; /* page directory entry address */ | UINT32 pde_addr; /* page directory entry address */ |
| Line 643 paging(const UINT32 laddr, const int crw | Line 727 paging(const UINT32 laddr, const int crw |
| /* make physical address */ | /* make physical address */ |
| paddr = (pte & CPU_PTE_BASEADDR_MASK) + (laddr & 0x00000fff); | paddr = (pte & CPU_PTE_BASEADDR_MASK) + (laddr & 0x00000fff); |
| bit = crw & CPU_PAGE_WRITE; | bit = ucrw & CPU_PAGE_WRITE; |
| bit |= (pde & pte & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE)); | bit |= (pde & pte & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE)); |
| bit |= (user_mode << 3); | bit |= ucrw & CPU_PAGE_USER_MODE; |
| bit |= CPU_STAT_WP; | bit |= CPU_STAT_WP; |
| #if !defined(USE_PAGE_ACCESS_TABLE) | #if !defined(USE_PAGE_ACCESS_TABLE) |
| Line 662 paging(const UINT32 laddr, const int crw | Line 746 paging(const UINT32 laddr, const int crw |
| goto pf_exception; | goto pf_exception; |
| } | } |
| if ((crw & CPU_PAGE_WRITE) && !(pte & CPU_PTE_DIRTY)) { | if ((ucrw & CPU_PAGE_WRITE) && !(pte & CPU_PTE_DIRTY)) { |
| pte |= CPU_PTE_DIRTY; | pte |= CPU_PTE_DIRTY; |
| cpu_memorywrite_d(pte_addr, pte); | cpu_memorywrite_d(pte_addr, pte); |
| } | } |
| #if defined(IA32_SUPPORT_TLB) | #if defined(IA32_SUPPORT_TLB) |
| tlb_update(laddr, pte, crw); | tlb_update(laddr, pte, ucrw); |
| #endif /* IA32_SUPPORT_TLB */ | #endif /* IA32_SUPPORT_TLB */ |
| return paddr; | return paddr; |
| pf_exception: | pf_exception: |
| CPU_CR2 = laddr; | CPU_CR2 = laddr; |
| err |= ((crw & CPU_PAGE_WRITE) << 1) | (user_mode << 2); | err |= (ucrw & CPU_PAGE_WRITE) << 1; |
| err |= (ucrw & CPU_PAGE_USER_MODE) >> 1; | |
| EXCEPTION(PF_EXCEPTION, err); | EXCEPTION(PF_EXCEPTION, err); |
| return 0; /* compiler happy */ | return 0; /* compiler happy */ |
| } | } |
| #if defined(IA32_SUPPORT_TLB) | #if defined(IA32_SUPPORT_TLB) |
| /* | /* |
| * TLB | * TLB |
| */ | */ |
| #if defined(IA32_PROFILE_TLB) | #if defined(IA32_PROFILE_TLB) |
| /* profiling */ | /* profiling */ |
| typedef struct { | typedef struct { |