|
|
| version 1.15, 2004/03/08 12:56:22 | version 1.18, 2004/03/23 18:38:07 |
|---|---|
| Line 1 | Line 1 |
| /* $Id$ */ | /* $Id$ */ |
| /* | /* |
| * Copyright (c) 2003 NONAKA Kimihiro | * Copyright (c) 2003-2004 NONAKA Kimihiro |
| * All rights reserved. | * All rights reserved. |
| * | * |
| * Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without |
| Line 184 static const UINT8 page_access_bit[32] = | Line 184 static const UINT8 page_access_bit[32] = |
| * +- CR3(物理アドレス) | * +- 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) | #if defined(IA32_SUPPORT_TLB) |
| static BOOL tlb_lookup(UINT32 vaddr, int crw, UINT32 *paddr); | static BOOL tlb_lookup(const UINT32 vaddr, const int crw, UINT32 *paddr); |
| static void tlb_update(UINT32 laddr, UINT entry, int crw); | static void tlb_update(const UINT32 laddr, const UINT entry, const int crw); |
| #endif | #endif |
| void MEMCALL | 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; | UINT32 paddr; |
| UINT remain; /* page remain */ | UINT remain; /* page remain */ |
| Line 231 cpu_memory_access_la_region(UINT32 laddr | Line 231 cpu_memory_access_la_region(UINT32 laddr |
| } | } |
| UINT32 MEMCALL | 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; | const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); |
| UINT32 paddr; | UINT32 result, value; |
| UINT remain; /* page remain */ | UINT32 paddr[2]; |
| UINT r; | UINT remain; |
| int shift = 0; | |
| paddr[0] = paging(laddr, crw, user_mode); | |
| remain = 0x1000 - (laddr & 0x00000fff); | remain = 0x1000 - (laddr & 0x00000fff); |
| for (;;) { | if (remain >= length) { |
| paddr = paging(laddr, crw, user_mode); | /* fast mode */ |
| switch (length) { | |
| r = (remain > length) ? length : remain; | |
| switch (r) { | |
| case 4: | case 4: |
| value = cpu_memoryread_d(paddr); | value = cpu_memoryread_d(paddr[0]); |
| result = (*func)(value, arg); | |
| cpu_memorywrite_d(paddr[0], result); | |
| break; | break; |
| case 3: | |
| value += (UINT32)cpu_memoryread(paddr) << shift; | |
| shift += 8; | |
| paddr++; | |
| /*FALLTHROUGH*/ | |
| case 2: | case 2: |
| value += (UINT32)cpu_memoryread_w(paddr) << shift; | value = cpu_memoryread_w(paddr[0]); |
| shift += 16; | result = (*func)(value, arg); |
| cpu_memorywrite_w(paddr[0], (UINT16)result); | |
| break; | break; |
| case 1: | case 1: |
| value += (UINT32)cpu_memoryread(paddr) << shift; | value = cpu_memoryread(paddr[0]); |
| shift += 8; | result = (*func)(value, arg); |
| cpu_memorywrite(paddr[0], (UINT8)result); | |
| break; | break; |
| default: | 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; | break; |
| } | } |
| return value; | |
| } | |
| length -= r; | /* slow mode */ |
| if (length == 0) | 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; | |
| } | |
| UINT32 MEMCALL | |
| cpu_linear_memory_read(UINT32 laddr, UINT length, const int crw, const int user_mode) | |
| { | |
| UINT32 value; | |
| 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: | |
| value = cpu_memoryread_d(paddr[0]); | |
| break; | break; |
| laddr += r; | case 2: |
| remain -= r; | value = cpu_memoryread_w(paddr[0]); |
| if (remain <= 0) { | break; |
| /* next page */ | |
| remain += 0x1000; | case 1: |
| value = cpu_memoryread(paddr[0]); | |
| break; | |
| default: | |
| ia32_panic("cpu_linear_memory_read(): invalid length (length = %d)\n", length); | |
| value = 0; /* compiler happy */ | |
| 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; | |
| 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; | return value; |
| } | } |
| void MEMCALL | void MEMCALL |
| cpu_linear_memory_write(UINT32 laddr, UINT32 value, UINT length, int user_mode) | cpu_linear_memory_write(UINT32 laddr, UINT32 value, UINT length, const int user_mode) |
| { | { |
| UINT32 paddr; | const int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); |
| UINT remain; /* page remain */ | UINT32 paddr[2]; |
| UINT r; | UINT remain; |
| int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); | |
| paddr[0] = paging(laddr, crw, user_mode); | |
| remain = 0x1000 - (laddr & 0x00000fff); | remain = 0x1000 - (laddr & 0x00000fff); |
| for (;;) { | if (remain >= length) { |
| paddr = paging(laddr, crw, user_mode); | /* fast mode */ |
| switch (length) { | |
| r = (remain > length) ? length : remain; | |
| switch (r) { | |
| case 4: | case 4: |
| cpu_memorywrite_d(paddr, value); | cpu_memorywrite_d(paddr[0], value); |
| break; | break; |
| case 3: | |
| cpu_memorywrite(paddr, value & 0xff); | |
| value >>= 8; | |
| paddr++; | |
| /*FALLTHROUGH*/ | |
| case 2: | case 2: |
| cpu_memorywrite_w(paddr, value & 0xffff); | cpu_memorywrite_w(paddr[0], (UINT16)value); |
| value >>= 16; | |
| break; | break; |
| case 1: | case 1: |
| cpu_memorywrite(paddr, value & 0xff); | cpu_memorywrite(paddr[0], (UINT8)value); |
| value >>= 8; | |
| break; | break; |
| default: | default: |
| ia32_panic("cpu_linear_memory_write(): out of range (r = %d)\n", r); | ia32_panic("cpu_linear_memory_write(): invalid length (length = %d)\n", length); |
| break; | break; |
| } | } |
| return; | |
| } | |
| length -= r; | /* slow mode */ |
| if (length == 0) | paddr[1] = paging(laddr + remain, crw, user_mode); |
| break; | switch (remain) { |
| case 3: | |
| laddr += r; | cpu_memorywrite(paddr[0], (UINT8)value); |
| remain -= r; | cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); |
| if (remain <= 0) { | cpu_memorywrite(paddr[1], (BYTE)(value >> 24)); |
| /* next page */ | break; |
| remain += 0x1000; | |
| } | 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; | |
| } | } |
| } | } |
| void MEMCALL | 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; | UINT32 paddr; |
| UINT remain; /* page remain */ | UINT remain; /* page remain */ |
| Line 362 paging_check(UINT32 laddr, UINT length, | Line 460 paging_check(UINT32 laddr, UINT length, |
| } | } |
| static UINT32 | 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 paddr; /* physical address */ |
| UINT32 pde_addr; /* page directory entry address */ | UINT32 pde_addr; /* page directory entry address */ |
| Line 575 tlb_flush_page(UINT32 laddr) | Line 673 tlb_flush_page(UINT32 laddr) |
| } | } |
| static BOOL | static BOOL |
| tlb_lookup(UINT32 laddr, int crw, UINT32 *paddr) | tlb_lookup(const UINT32 laddr, const int crw, UINT32 *paddr) |
| { | { |
| TLB_ENTRY_T *ep; | TLB_ENTRY_T *ep; |
| int idx; | int idx; |
| Line 601 tlb_lookup(UINT32 laddr, int crw, UINT32 | Line 699 tlb_lookup(UINT32 laddr, int crw, UINT32 |
| } | } |
| static void | 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; | TLB_ENTRY_T *ep; |
| int idx; | int idx; |