| version 1.35, 2011/12/29 13:32:12 | version 1.37, 2012/01/08 19:15:40 | 
| Line 180  static const UINT8 page_access_bit[32] = | Line 180  static const UINT8 page_access_bit[32] = | 
 | * +- CR3(物理アドレス) | * +- CR3(物理アドレス) | 
 | */ | */ | 
 |  |  | 
| static UINT32 MEMCALL paging(const UINT32 laddr, const int ucrw); | /* TLB */ | 
| static void MEMCALL tlb_update(const UINT32 laddr, const UINT entry, const int ucrw); | struct tlb_entry { | 
|  | UINT32  tag;    /* linear address */ | 
|  | #define TLB_ENTRY_TAG_VALID             (1 << 0) | 
|  | /*      pde & pte & CPU_PTE_WRITABLE    (1 << 1)        */ | 
|  | /*      pde & pte & CPU_PTE_USER_MODE   (1 << 2)        */ | 
|  | #define TLB_ENTRY_TAG_DIRTY             CPU_PTE_DIRTY           /* (1 << 6) */ | 
|  | #define TLB_ENTRY_TAG_GLOBAL            CPU_PTE_GLOBAL_PAGE     /* (1 << 8) */ | 
|  | #define TLB_ENTRY_TAG_MAX_SHIFT         12 | 
|  | UINT32  paddr;  /* physical address */ | 
|  | }; | 
|  | static void MEMCALL tlb_update(UINT32 laddr, UINT entry, int ucrw); | 
 |  |  | 
| #define PAGE_SIZE       0x1000 | /* paging */ | 
| #define PAGE_MASK       (PAGE_SIZE - 1) | static UINT32 MEMCALL paging(UINT32 laddr, int ucrw); | 
 |  |  | 
 |  | /* | 
 |  | * linear memory access | 
 |  | */ | 
 |  | /* RMW */ | 
 | UINT8 MEMCALL | UINT8 MEMCALL | 
 | cpu_memory_access_la_RMW_b(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) | cpu_memory_access_la_RMW_b(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) | 
 | { | { | 
| const int ucrw = CPU_PAGE_WRITE_DATA|CPU_STAT_USER_MODE; | const int ucrw = CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE; | 
| UINT32 result, value; | struct tlb_entry *ep; | 
 | UINT32 paddr; | UINT32 paddr; | 
 |  | UINT32 result; | 
 |  | UINT8 value; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep = tlb_lookup(laddr, ucrw); | 
 |  | if (ep != NULL) { | 
 |  | paddr = ep->paddr + (laddr & PAGE_MASK); | 
 |  | goto onepage; | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr = paging(laddr, ucrw); | paddr = paging(laddr, ucrw); | 
 |  | onepage: | 
 | value = cpu_memoryread(paddr); | value = cpu_memoryread(paddr); | 
 | result = (*func)(value, arg); | result = (*func)(value, arg); | 
 | cpu_memorywrite(paddr, (UINT8)result); | cpu_memorywrite(paddr, (UINT8)result); | 
 |  |  | 
 | return value; | return value; | 
 | } | } | 
 |  |  | 
 | UINT16 MEMCALL | UINT16 MEMCALL | 
 | cpu_memory_access_la_RMW_w(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) | cpu_memory_access_la_RMW_w(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) | 
 | { | { | 
| const int ucrw = CPU_PAGE_WRITE_DATA|CPU_STAT_USER_MODE; | const int ucrw = CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE; | 
| UINT32 result, value; | struct tlb_entry *ep[2]; | 
 | UINT32 paddr[2]; | UINT32 paddr[2]; | 
 |  | UINT32 result; | 
 |  | UINT16 value; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep[0] = tlb_lookup(laddr, ucrw); | 
 |  | if (ep[0] != NULL) { | 
 |  | paddr[0] = ep[0]->paddr + (laddr & PAGE_MASK); | 
 |  | if ((laddr + 1) & PAGE_MASK) | 
 |  | goto onepage; | 
 |  |  | 
 |  | ep[1] = tlb_lookup(laddr + 1, ucrw); | 
 |  | if (ep[1] != NULL) { | 
 |  | paddr[1] = ep[1]->paddr + (laddr & PAGE_MASK); | 
 |  | goto separate; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); | 
 | if ((laddr + 1) & PAGE_MASK) { | if ((laddr + 1) & PAGE_MASK) { | 
 |  | onepage: | 
 | value = cpu_memoryread_w(paddr[0]); | value = cpu_memoryread_w(paddr[0]); | 
 | result = (*func)(value, arg); | result = (*func)(value, arg); | 
 | cpu_memorywrite_w(paddr[0], (UINT16)result); | cpu_memorywrite_w(paddr[0], (UINT16)result); | 
| } else { | return value; | 
| 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)); |  | 
 | } | } | 
 |  |  | 
 |  | paddr[1] = paging(laddr + 1, ucrw); | 
 |  | separate: | 
 |  | 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; | return value; | 
 | } | } | 
 |  |  | 
 | UINT32 MEMCALL | UINT32 MEMCALL | 
 | cpu_memory_access_la_RMW_d(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) | cpu_memory_access_la_RMW_d(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) | 
 | { | { | 
| const int ucrw = CPU_PAGE_WRITE_DATA|CPU_STAT_USER_MODE; | const int ucrw = CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE; | 
| UINT32 result, value; | struct tlb_entry *ep[2]; | 
 | UINT32 paddr[2]; | UINT32 paddr[2]; | 
| UINT remain; | UINT32 result; | 
|  | UINT32 value; | 
|  | int remain; | 
|  |  | 
|  | /* TLB */ | 
|  | ep[0] = tlb_lookup(laddr, ucrw); | 
|  | if (ep[0] != NULL) { | 
|  | paddr[0] = ep[0]->paddr + (laddr & PAGE_MASK); | 
|  | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
|  | if (remain >= 4) | 
|  | goto onepage; | 
|  |  | 
|  | ep[1] = tlb_lookup(laddr + remain, ucrw); | 
|  | if (ep[1] != NULL) { | 
|  | paddr[1] = ep[1]->paddr + (laddr & PAGE_MASK); | 
|  | goto separate; | 
|  | } | 
|  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); | 
 | remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
 | if (remain >= 4) { | if (remain >= 4) { | 
 |  | onepage: | 
 | value = cpu_memoryread_d(paddr[0]); | value = cpu_memoryread_d(paddr[0]); | 
 | result = (*func)(value, arg); | result = (*func)(value, arg); | 
 | cpu_memorywrite_d(paddr[0], result); | cpu_memorywrite_d(paddr[0], result); | 
| } else { | return value; | 
| 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: | paddr[1] = paging(laddr + remain, ucrw); | 
| value = cpu_memoryread_w(paddr[0]); | separate: | 
| value += (UINT32)cpu_memoryread_w(paddr[1]) << 16; | switch (remain) { | 
| result = (*func)(value, arg); | case 3: | 
| cpu_memorywrite_w(paddr[0], (UINT16)result); | value = cpu_memoryread(paddr[0]); | 
| cpu_memorywrite_w(paddr[1], (UINT16)(result >> 16)); | value += (UINT32)cpu_memoryread_w(paddr[0] + 1) << 8; | 
| break; | 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 1: | case 2: | 
| value = cpu_memoryread(paddr[0]); | value = cpu_memoryread_w(paddr[0]); | 
| value += (UINT32)cpu_memoryread_w(paddr[1]) << 8; | value += (UINT32)cpu_memoryread_w(paddr[1]) << 16; | 
| value += (UINT32)cpu_memoryread(paddr[1] + 2) << 24; | result = (*func)(value, arg); | 
| result = (*func)(value, arg); | cpu_memorywrite_w(paddr[0], (UINT16)result); | 
| cpu_memorywrite(paddr[0], (UINT8)result); | cpu_memorywrite_w(paddr[1], (UINT16)(result >> 16)); | 
| cpu_memorywrite_w(paddr[1], (UINT16)(result >> 8)); | break; | 
| cpu_memorywrite(paddr[1] + 2, (UINT8)(result >> 24)); |  | 
| break; |  | 
 |  |  | 
| default: | case 1: | 
| ia32_panic("cpu_memory_access_la_RMW_d(): out of range (remain = %d)\n", remain); | value = cpu_memoryread(paddr[0]); | 
| return (UINT32)-1; | value += (UINT32)cpu_memoryread_w(paddr[1]) << 8; | 
| } | value += (UINT32)cpu_memoryread(paddr[1] + 2) << 24; | 
|  | result = (*func)(value, arg); | 
|  | cpu_memorywrite(paddr[0], (UINT8)result); | 
|  | cpu_memorywrite_w(paddr[1], (UINT16)(result >> 8)); | 
|  | cpu_memorywrite(paddr[1] + 2, (UINT8)(result >> 24)); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | ia32_panic("cpu_memory_access_la_RMW_d: out of range (remain=%d)\n", remain); | 
|  | value = 0;      /* XXX compiler happy */ | 
|  | break; | 
 | } | } | 
 | return value; | return value; | 
 | } | } | 
 |  |  | 
 |  | /* read */ | 
 | UINT8 MEMCALL | UINT8 MEMCALL | 
| cpu_linear_memory_read_b(UINT32 laddr, const int ucrw) | cpu_linear_memory_read_b(UINT32 laddr, int ucrw) | 
 | { | { | 
 |  | struct tlb_entry *ep; | 
 | UINT32 paddr; | UINT32 paddr; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep = tlb_lookup(laddr, ucrw); | 
 |  | if (ep != NULL) { | 
 |  | paddr = ep->paddr + (laddr & PAGE_MASK); | 
 |  | return cpu_memoryread(paddr); | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr = paging(laddr, ucrw); | paddr = paging(laddr, ucrw); | 
 | return cpu_memoryread(paddr); | return cpu_memoryread(paddr); | 
 | } | } | 
 |  |  | 
 | UINT16 MEMCALL | UINT16 MEMCALL | 
| cpu_linear_memory_read_w(UINT32 laddr, const int ucrw) | cpu_linear_memory_read_w(UINT32 laddr, int ucrw) | 
 | { | { | 
 |  | struct tlb_entry *ep[2]; | 
 | UINT32 paddr[2]; | UINT32 paddr[2]; | 
 | UINT16 value; | UINT16 value; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep[0] = tlb_lookup(laddr, ucrw); | 
 |  | if (ep[0] != NULL) { | 
 |  | paddr[0] = ep[0]->paddr + (laddr & PAGE_MASK); | 
 |  | if ((laddr + 1) & PAGE_MASK) | 
 |  | return cpu_memoryread_w(paddr[0]); | 
 |  |  | 
 |  | ep[1] = tlb_lookup(laddr + 1, ucrw); | 
 |  | if (ep[1] != NULL) { | 
 |  | paddr[1] = ep[1]->paddr; | 
 |  | goto separate; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); | 
| if ((laddr + 1) & PAGE_MASK) { | if ((laddr + 1) & PAGE_MASK) | 
 | return cpu_memoryread_w(paddr[0]); | return cpu_memoryread_w(paddr[0]); | 
| } else { |  | 
| paddr[1] = paging(laddr + 1, ucrw); | paddr[1] = paging(laddr + 1, ucrw); | 
| value = cpu_memoryread_b(paddr[0]); | separate: | 
| value += (UINT16)cpu_memoryread_b(paddr[1]) << 8; | value = cpu_memoryread_b(paddr[0]); | 
| return value; | value += (UINT16)cpu_memoryread_b(paddr[1]) << 8; | 
| } | return value; | 
 | } | } | 
 |  |  | 
 | UINT32 MEMCALL | UINT32 MEMCALL | 
| cpu_linear_memory_read_d(UINT32 laddr, const int ucrw) | cpu_linear_memory_read_d(UINT32 laddr, int ucrw) | 
 | { | { | 
 |  | struct tlb_entry *ep[2]; | 
 | UINT32 paddr[2]; | UINT32 paddr[2]; | 
 | UINT32 value; | UINT32 value; | 
 | UINT remain; | UINT remain; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep[0] = tlb_lookup(laddr, ucrw); | 
 |  | if (ep[0] != NULL) { | 
 |  | paddr[0] = ep[0]->paddr + (laddr & PAGE_MASK); | 
 |  | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
 |  | if (remain >= sizeof(value)) | 
 |  | return cpu_memoryread_d(paddr[0]); | 
 |  |  | 
 |  | ep[1] = tlb_lookup(laddr + remain, ucrw); | 
 |  | if (ep[1] != NULL) { | 
 |  | paddr[1] = ep[1]->paddr; | 
 |  | goto separate; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); | 
 | remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
| if (remain >= 4) { | if (remain >= sizeof(value)) | 
 | return cpu_memoryread_d(paddr[0]); | return 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; |  | 
 | break; |  | 
 |  |  | 
| case 2: | paddr[1] = paging(laddr + remain, ucrw); | 
| value = cpu_memoryread_w(paddr[0]); | separate: | 
| value += (UINT32)cpu_memoryread_w(paddr[1]) << 16; | switch (remain) { | 
| break; | 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 1: | case 2: | 
| value = cpu_memoryread(paddr[0]); | value = cpu_memoryread_w(paddr[0]); | 
| value += (UINT32)cpu_memoryread_w(paddr[1]) << 8; | value += (UINT32)cpu_memoryread_w(paddr[1]) << 16; | 
| value += (UINT32)cpu_memoryread(paddr[1] + 2) << 24; | break; | 
| break; |  | 
 |  |  | 
| default: | case 1: | 
| ia32_panic("cpu_linear_memory_read_d(): out of range (remain = %d)\n", remain); | value = cpu_memoryread(paddr[0]); | 
| value = (UINT32)-1; | value += (UINT32)cpu_memoryread_w(paddr[1]) << 8; | 
| break; | value += (UINT32)cpu_memoryread(paddr[1] + 2) << 24; | 
| } | break; | 
| return value; |  | 
|  | default: | 
|  | ia32_panic("cpu_linear_memory_read_d: out of range (remain=%d)\n", remain); | 
|  | value = 0;      /* XXX compiler happy */ | 
|  | break; | 
 | } | } | 
 |  | return value; | 
 | } | } | 
 |  |  | 
 | UINT64 MEMCALL | UINT64 MEMCALL | 
| cpu_linear_memory_read_q(UINT32 laddr, const int ucrw) | cpu_linear_memory_read_q(UINT32 laddr, int ucrw) | 
 | { | { | 
 |  | struct tlb_entry *ep[2]; | 
 | UINT32 paddr[2]; | UINT32 paddr[2]; | 
 | UINT64 value; | UINT64 value; | 
 | UINT remain; | UINT remain; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep[0] = tlb_lookup(laddr, ucrw); | 
 |  | if (ep[0] != NULL) { | 
 |  | paddr[0] = ep[0]->paddr + (laddr & PAGE_MASK); | 
 |  | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
 |  | if (remain >= sizeof(value)) | 
 |  | return cpu_memoryread_d(paddr[0]); | 
 |  |  | 
 |  | ep[1] = tlb_lookup(laddr + remain, ucrw); | 
 |  | if (ep[1] != NULL) { | 
 |  | paddr[1] = ep[1]->paddr; | 
 |  | goto separate; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); | 
 | remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
| if (remain >= 8) { | if (remain >= sizeof(value)) | 
 | return cpu_memoryread_q(paddr[0]); | return cpu_memoryread_q(paddr[0]); | 
 | } else { |  | 
 | paddr[1] = paging(laddr + remain, ucrw); |  | 
 | switch (remain) { |  | 
 | case 7: |  | 
 | value = cpu_memoryread(paddr[0]); |  | 
 | value += (UINT64)cpu_memoryread_w(paddr[0] + 1) << 8; |  | 
 | value += (UINT64)cpu_memoryread_d(paddr[0] + 3) << 24; |  | 
 | value += (UINT64)cpu_memoryread(paddr[1]) << 56; |  | 
 | break; |  | 
 |  |  | 
| case 6: | paddr[1] = paging(laddr + remain, ucrw); | 
| value = cpu_memoryread_w(paddr[0]); | separate: | 
| value += (UINT64)cpu_memoryread_d(paddr[0] + 2) << 16; | switch (remain) { | 
| value += (UINT64)cpu_memoryread_w(paddr[1]) << 48; | case 7: | 
| break; | value = cpu_memoryread(paddr[0]); | 
|  | value += (UINT64)cpu_memoryread_w(paddr[0] + 1) << 8; | 
| case 5: | value += (UINT64)cpu_memoryread_d(paddr[0] + 3) << 24; | 
| value = cpu_memoryread(paddr[0]); | value += (UINT64)cpu_memoryread(paddr[1]) << 56; | 
| value += (UINT64)cpu_memoryread_d(paddr[0] + 1) << 8; | break; | 
| value += (UINT64)cpu_memoryread_w(paddr[1]) << 40; |  | 
| value += (UINT64)cpu_memoryread(paddr[1] + 2) << 56; |  | 
| break; |  | 
|  |  | 
| case 4: |  | 
| value = cpu_memoryread_d(paddr[0]); |  | 
| value += (UINT64)cpu_memoryread_d(paddr[1]) << 32; |  | 
| break; |  | 
 |  |  | 
| case 3: | case 6: | 
| value = cpu_memoryread(paddr[0]); | value = cpu_memoryread_w(paddr[0]); | 
| value += (UINT64)cpu_memoryread_w(paddr[0] + 1) << 8; | value += (UINT64)cpu_memoryread_d(paddr[0] + 2) << 16; | 
| value += (UINT64)cpu_memoryread_d(paddr[1]) << 24; | value += (UINT64)cpu_memoryread_w(paddr[1]) << 48; | 
| value += (UINT64)cpu_memoryread(paddr[1] + 4) << 56; | break; | 
| break; |  | 
|  | case 5: | 
|  | value = cpu_memoryread(paddr[0]); | 
|  | value += (UINT64)cpu_memoryread_d(paddr[0] + 1) << 8; | 
|  | value += (UINT64)cpu_memoryread_w(paddr[1]) << 40; | 
|  | value += (UINT64)cpu_memoryread(paddr[1] + 2) << 56; | 
|  | break; | 
 |  |  | 
| case 2: | case 4: | 
| value = cpu_memoryread_w(paddr[0]); | value = cpu_memoryread_d(paddr[0]); | 
| value += (UINT64)cpu_memoryread_d(paddr[1]) << 16; | value += (UINT64)cpu_memoryread_d(paddr[1]) << 32; | 
| value += (UINT64)cpu_memoryread_w(paddr[1] + 4) << 48; | break; | 
| break; |  | 
 |  |  | 
| case 1: | case 3: | 
| value = cpu_memoryread(paddr[0]); | value = cpu_memoryread(paddr[0]); | 
| value += (UINT64)cpu_memoryread_d(paddr[1]) << 8; | value += (UINT64)cpu_memoryread_w(paddr[0] + 1) << 8; | 
| value += (UINT64)cpu_memoryread_w(paddr[1] + 4) << 40; | value += (UINT64)cpu_memoryread_d(paddr[1]) << 24; | 
| value += (UINT64)cpu_memoryread(paddr[1] + 6) << 56; | value += (UINT64)cpu_memoryread(paddr[1] + 4) << 56; | 
| break; | break; | 
 |  |  | 
| default: | case 2: | 
| ia32_panic("cpu_linear_memory_read_q(): out of range (remain = %d)\n", remain); | value = cpu_memoryread_w(paddr[0]); | 
| value = (UINT64)-1; | value += (UINT64)cpu_memoryread_d(paddr[1]) << 16; | 
| break; | value += (UINT64)cpu_memoryread_w(paddr[1] + 4) << 48; | 
| } | break; | 
|  |  | 
|  | case 1: | 
|  | value = cpu_memoryread(paddr[0]); | 
|  | value += (UINT64)cpu_memoryread_d(paddr[1]) << 8; | 
|  | value += (UINT64)cpu_memoryread_w(paddr[1] + 4) << 40; | 
|  | value += (UINT64)cpu_memoryread(paddr[1] + 6) << 56; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | ia32_panic("cpu_linear_memory_read_q: out of range (remain=%d)\n", remain); | 
|  | value = 0;      /* XXX compiler happy */ | 
|  | break; | 
 | } | } | 
 | return value; | return value; | 
 | } | } | 
 |  |  | 
 | REG80 MEMCALL | REG80 MEMCALL | 
| cpu_linear_memory_read_f(UINT32 laddr, const int ucrw) | cpu_linear_memory_read_f(UINT32 laddr, int ucrw) | 
 | { | { | 
 |  | struct tlb_entry *ep[2]; | 
 | UINT32 paddr[2]; | UINT32 paddr[2]; | 
 | REG80 value; | REG80 value; | 
 | UINT remain; | UINT remain; | 
 | UINT i, j; | UINT i, j; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep[0] = tlb_lookup(laddr, ucrw); | 
 |  | if (ep[0] != NULL) { | 
 |  | paddr[0] = ep[0]->paddr + (laddr & PAGE_MASK); | 
 |  | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
 |  | if (remain >= sizeof(value)) | 
 |  | return cpu_memoryread_f(paddr[0]); | 
 |  |  | 
 |  | ep[1] = tlb_lookup(laddr + remain, ucrw); | 
 |  | if (ep[1] != NULL) { | 
 |  | paddr[1] = ep[1]->paddr; | 
 |  | goto separate; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); | 
 | remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
| if (remain >= 10) { | if (remain >= sizeof(value)) | 
 | return cpu_memoryread_f(paddr[0]); | return cpu_memoryread_f(paddr[0]); | 
| } else { |  | 
| paddr[1] = paging(laddr + remain, ucrw); | paddr[1] = paging(laddr + remain, ucrw); | 
| for (i = 0; i < remain; ++i) { | separate: | 
| value.b[i] = cpu_memoryread(paddr[0] + i); | for (i = 0; i < remain; ++i) { | 
| } | value.b[i] = cpu_memoryread(paddr[0] + i); | 
| for (j = 0; i < 10; ++i, ++j) { |  | 
| value.b[i] = cpu_memoryread(paddr[1] + j); |  | 
| } |  | 
| return value; |  | 
 | } | } | 
 |  | for (j = 0; i < 10; ++i, ++j) { | 
 |  | value.b[i] = cpu_memoryread(paddr[1] + j); | 
 |  | } | 
 |  | return value; | 
 | } | } | 
 |  |  | 
 |  | /* write */ | 
 | 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, int ucrw) | 
 | { | { | 
| const int ucrw = CPU_PAGE_WRITE_DATA|user_mode; | struct tlb_entry *ep; | 
 | UINT32 paddr; | UINT32 paddr; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep = tlb_lookup(laddr, ucrw); | 
 |  | if (ep != NULL) { | 
 |  | paddr = ep->paddr + (laddr & PAGE_MASK); | 
 |  | cpu_memorywrite(paddr, value); | 
 |  | return; | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr = paging(laddr, ucrw); | paddr = paging(laddr, ucrw); | 
 | cpu_memorywrite(paddr, value); | cpu_memorywrite(paddr, 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, int ucrw) | 
 | { | { | 
| const int ucrw = CPU_PAGE_WRITE_DATA|user_mode; | struct tlb_entry *ep[2]; | 
 | UINT32 paddr[2]; | UINT32 paddr[2]; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep[0] = tlb_lookup(laddr, ucrw); | 
 |  | if (ep[0] != NULL) { | 
 |  | paddr[0] = ep[0]->paddr + (laddr & PAGE_MASK); | 
 |  | if ((laddr + 1) & PAGE_MASK) { | 
 |  | cpu_memorywrite_w(paddr[0], value); | 
 |  | return; | 
 |  | } | 
 |  |  | 
 |  | ep[1] = tlb_lookup(laddr + 1, ucrw); | 
 |  | if (ep[1] != NULL) { | 
 |  | paddr[1] = ep[1]->paddr; | 
 |  | goto separate; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); | 
 | if ((laddr + 1) & PAGE_MASK) { | if ((laddr + 1) & PAGE_MASK) { | 
 | cpu_memorywrite_w(paddr[0], value); | cpu_memorywrite_w(paddr[0], value); | 
| } else { | return; | 
| paddr[1] = paging(laddr + 1, ucrw); |  | 
| cpu_memorywrite(paddr[0], (UINT8)value); |  | 
| cpu_memorywrite(paddr[1], (UINT8)(value >> 8)); |  | 
 | } | } | 
 |  |  | 
 |  | paddr[1] = paging(laddr + 1, ucrw); | 
 |  | separate: | 
 |  | cpu_memorywrite(paddr[0], (UINT8)value); | 
 |  | cpu_memorywrite(paddr[1], (UINT8)(value >> 8)); | 
 | } | } | 
 |  |  | 
 | 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, int ucrw) | 
 | { | { | 
| const int ucrw = CPU_PAGE_WRITE_DATA|user_mode; | struct tlb_entry *ep[2]; | 
 | UINT32 paddr[2]; | UINT32 paddr[2]; | 
 | UINT remain; | UINT remain; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep[0] = tlb_lookup(laddr, ucrw); | 
 |  | if (ep[0] != NULL) { | 
 |  | paddr[0] = ep[0]->paddr + (laddr & PAGE_MASK); | 
 |  | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
 |  | if (remain >= sizeof(value)) { | 
 |  | cpu_memorywrite_d(paddr[0], value); | 
 |  | return; | 
 |  | } | 
 |  |  | 
 |  | ep[1] = tlb_lookup(laddr + remain, ucrw); | 
 |  | if (ep[1] != NULL) { | 
 |  | paddr[1] = ep[1]->paddr; | 
 |  | goto separate; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); | 
 | remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
| if (remain >= 4) { | if (remain >= sizeof(value)) { | 
 | cpu_memorywrite_d(paddr[0], value); | cpu_memorywrite_d(paddr[0], value); | 
| } else { | return; | 
| paddr[1] = paging(laddr + remain, ucrw); | } | 
| 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: | paddr[1] = paging(laddr + remain, ucrw); | 
| cpu_memorywrite_w(paddr[0], (UINT16)value); | separate: | 
| cpu_memorywrite_w(paddr[1], (UINT16)(value >> 16)); | switch (remain) { | 
| break; | 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: | case 1: | 
| cpu_memorywrite(paddr[0], (UINT8)value); | cpu_memorywrite(paddr[0], (UINT8)value); | 
| cpu_memorywrite_w(paddr[1], (UINT16)(value >> 8)); | cpu_memorywrite_w(paddr[1], (UINT16)(value >> 8)); | 
| cpu_memorywrite(paddr[1] + 2, (UINT8)(value >> 24)); | cpu_memorywrite(paddr[1] + 2, (UINT8)(value >> 24)); | 
| break; | break; | 
| } |  | 
|  | default: | 
|  | ia32_panic("cpu_linear_memory_write_d: out of range (remain=%d)\n", remain); | 
|  | break; | 
 | } | } | 
 | } | } | 
 |  |  | 
 | void MEMCALL | void MEMCALL | 
| cpu_linear_memory_write_q(UINT32 laddr, UINT64 value, const int user_mode) | cpu_linear_memory_write_q(UINT32 laddr, UINT64 value, int ucrw) | 
 | { | { | 
| const int ucrw = CPU_PAGE_WRITE_DATA|user_mode; | struct tlb_entry *ep[2]; | 
 | UINT32 paddr[2]; | UINT32 paddr[2]; | 
 | UINT remain; | UINT remain; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep[0] = tlb_lookup(laddr, ucrw); | 
 |  | if (ep[0] != NULL) { | 
 |  | paddr[0] = ep[0]->paddr + (laddr & PAGE_MASK); | 
 |  | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
 |  | if (remain >= sizeof(value)) { | 
 |  | cpu_memorywrite_q(paddr[0], value); | 
 |  | return; | 
 |  | } | 
 |  |  | 
 |  | ep[1] = tlb_lookup(laddr + remain, ucrw); | 
 |  | if (ep[1] != NULL) { | 
 |  | paddr[1] = ep[1]->paddr; | 
 |  | goto separate; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); | 
 | remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
| if (remain >= 8) { | if (remain >= sizeof(value)) { | 
 | cpu_memorywrite_q(paddr[0], value); | cpu_memorywrite_q(paddr[0], value); | 
| } else { | return; | 
| paddr[1] = paging(laddr + remain, ucrw); | } | 
| switch (remain) { |  | 
| case 7: |  | 
| cpu_memorywrite(paddr[0], (UINT8)value); |  | 
| cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); |  | 
| cpu_memorywrite_d(paddr[0] + 3, (UINT32)(value >> 24)); |  | 
| cpu_memorywrite(paddr[1], (UINT8)(value >> 56)); |  | 
| break; |  | 
|  |  | 
| case 6: |  | 
| cpu_memorywrite_w(paddr[0], (UINT16)value); |  | 
| cpu_memorywrite_d(paddr[0] + 2, (UINT32)(value >> 16)); |  | 
| cpu_memorywrite_w(paddr[1], (UINT16)(value >> 48)); |  | 
| break; |  | 
|  |  | 
| case 5: |  | 
| cpu_memorywrite(paddr[0], (UINT8)value); |  | 
| cpu_memorywrite_d(paddr[0] + 1, (UINT32)(value >> 8)); |  | 
| cpu_memorywrite_w(paddr[1], (UINT16)(value >> 40)); |  | 
| cpu_memorywrite(paddr[1] + 2, (UINT8)(value >> 56)); |  | 
| break; |  | 
 |  |  | 
| case 4: | paddr[1] = paging(laddr + remain, ucrw); | 
| cpu_memorywrite_d(paddr[0], (UINT32)value); | separate: | 
| cpu_memorywrite_d(paddr[1], (UINT32)(value >> 32)); | switch (remain) { | 
| break; | case 7: | 
|  | cpu_memorywrite(paddr[0], (UINT8)value); | 
|  | cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); | 
|  | cpu_memorywrite_d(paddr[0] + 3, (UINT32)(value >> 24)); | 
|  | cpu_memorywrite(paddr[1], (UINT8)(value >> 56)); | 
|  | break; | 
|  |  | 
|  | case 6: | 
|  | cpu_memorywrite_w(paddr[0], (UINT16)value); | 
|  | cpu_memorywrite_d(paddr[0] + 2, (UINT32)(value >> 16)); | 
|  | cpu_memorywrite_w(paddr[1], (UINT16)(value >> 48)); | 
|  | break; | 
 |  |  | 
| case 3: | case 5: | 
| cpu_memorywrite(paddr[0], (UINT8)value); | cpu_memorywrite(paddr[0], (UINT8)value); | 
| cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); | cpu_memorywrite_d(paddr[0] + 1, (UINT32)(value >> 8)); | 
| cpu_memorywrite_d(paddr[1], (UINT32)(value >> 24)); | cpu_memorywrite_w(paddr[1], (UINT16)(value >> 40)); | 
| cpu_memorywrite(paddr[1] + 4, (UINT8)(value >> 56)); | cpu_memorywrite(paddr[1] + 2, (UINT8)(value >> 56)); | 
| break; | break; | 
|  |  | 
|  | case 4: | 
|  | cpu_memorywrite_d(paddr[0], (UINT32)value); | 
|  | cpu_memorywrite_d(paddr[1], (UINT32)(value >> 32)); | 
|  | break; | 
 |  |  | 
| case 2: | case 3: | 
| cpu_memorywrite_w(paddr[0], (UINT16)value); | cpu_memorywrite(paddr[0], (UINT8)value); | 
| cpu_memorywrite_d(paddr[1], (UINT32)(value >> 16)); | cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); | 
| cpu_memorywrite_w(paddr[1] + 4, (UINT16)(value >> 48)); | cpu_memorywrite_d(paddr[1], (UINT32)(value >> 24)); | 
| break; | cpu_memorywrite(paddr[1] + 4, (UINT8)(value >> 56)); | 
|  | break; | 
|  |  | 
|  | case 2: | 
|  | cpu_memorywrite_w(paddr[0], (UINT16)value); | 
|  | cpu_memorywrite_d(paddr[1], (UINT32)(value >> 16)); | 
|  | cpu_memorywrite_w(paddr[1] + 4, (UINT16)(value >> 48)); | 
|  | break; | 
 |  |  | 
| case 1: | case 1: | 
| cpu_memorywrite(paddr[0], (UINT8)value); | cpu_memorywrite(paddr[0], (UINT8)value); | 
| cpu_memorywrite_d(paddr[1], (UINT32)(value >> 8)); | cpu_memorywrite_d(paddr[1], (UINT32)(value >> 8)); | 
| cpu_memorywrite_w(paddr[1] + 4, (UINT16)(value >> 40)); | cpu_memorywrite_w(paddr[1] + 4, (UINT16)(value >> 40)); | 
| cpu_memorywrite(paddr[1] + 6, (UINT8)(value >> 56)); | cpu_memorywrite(paddr[1] + 6, (UINT8)(value >> 56)); | 
| break; | break; | 
| } |  | 
|  | default: | 
|  | ia32_panic("cpu_linear_memory_write_q: out of range (remain=%d)\n", remain); | 
|  | break; | 
 | } | } | 
 | } | } | 
 |  |  | 
 | void MEMCALL | void MEMCALL | 
| cpu_linear_memory_write_f(UINT32 laddr, const REG80 *value, const int user_mode) | cpu_linear_memory_write_f(UINT32 laddr, const REG80 *value, int ucrw) | 
 | { | { | 
| const int ucrw = CPU_PAGE_WRITE_DATA|user_mode; | struct tlb_entry *ep[2]; | 
 | UINT32 paddr[2]; | UINT32 paddr[2]; | 
 | UINT remain; | UINT remain; | 
 | UINT i, j; | UINT i, j; | 
 |  |  | 
 |  | /* TLB */ | 
 |  | ep[0] = tlb_lookup(laddr, ucrw); | 
 |  | if (ep[0] != NULL) { | 
 |  | paddr[0] = ep[0]->paddr + (laddr & PAGE_MASK); | 
 |  | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
 |  | if (remain >= sizeof(value)) { | 
 |  | cpu_memorywrite_f(paddr[0], value); | 
 |  | return; | 
 |  | } | 
 |  |  | 
 |  | ep[1] = tlb_lookup(laddr + remain, ucrw); | 
 |  | if (ep[1] != NULL) { | 
 |  | paddr[1] = ep[1]->paddr; | 
 |  | goto separate; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | /* paging */ | 
 | paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); | 
 | remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = PAGE_SIZE - (laddr & PAGE_MASK); | 
| if (remain >= 10) { | if (remain >= sizeof(value)) { | 
 | cpu_memorywrite_f(paddr[0], value); | cpu_memorywrite_f(paddr[0], value); | 
| } else { | return; | 
| paddr[1] = paging(laddr + remain, ucrw); |  | 
| for (i = 0; i < remain; ++i) { |  | 
| cpu_memorywrite(paddr[0] + i, value->b[i]); |  | 
| } |  | 
| for (j = 0; i < 10; ++i, ++j) { |  | 
| cpu_memorywrite(paddr[1] + j, value->b[i]); |  | 
| } |  | 
 | } | } | 
 | } |  | 
 |  |  | 
 |  | paddr[1] = paging(laddr + remain, ucrw); | 
 |  | separate: | 
 |  | for (i = 0; i < remain; ++i) { | 
 |  | cpu_memorywrite(paddr[0] + i, value->b[i]); | 
 |  | } | 
 |  | for (j = 0; i < 10; ++i, ++j) { | 
 |  | cpu_memorywrite(paddr[1] + j, value->b[i]); | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | /* | 
 |  | * linear address memory access function | 
 |  | */ | 
 | void MEMCALL | void MEMCALL | 
| cpu_memory_access_la_region(UINT32 laddr, UINT length, const int ucrw, UINT8 *data) | cpu_memory_access_la_region(UINT32 laddr, UINT length, int ucrw, UINT8 *data) | 
 | { | { | 
 | UINT32 paddr; | UINT32 paddr; | 
 | UINT remain;    /* page remain */ | UINT remain;    /* page remain */ | 
| Line 621  cpu_memory_access_la_region(UINT32 laddr | Line 863  cpu_memory_access_la_region(UINT32 laddr | 
 | } | } | 
 |  |  | 
 | UINT32 MEMCALL | UINT32 MEMCALL | 
| laddr2paddr(const UINT32 laddr, const int ucrw) | laddr2paddr(UINT32 laddr, int ucrw) | 
 | { | { | 
 |  |  | 
 | return paging(laddr, ucrw); | return paging(laddr, ucrw); | 
 | } | } | 
 |  |  | 
 |  | /* | 
 |  | * paging | 
 |  | */ | 
 | static UINT32 MEMCALL | static UINT32 MEMCALL | 
| paging(const UINT32 laddr, const int ucrw) | paging(UINT32 laddr, 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 637  paging(const UINT32 laddr, const int ucr | Line 882  paging(const UINT32 laddr, const int ucr | 
 | UINT32 pte;             /* page table entry */ | UINT32 pte;             /* page table entry */ | 
 | UINT bit; | UINT bit; | 
 | UINT err; | UINT err; | 
| TLB_ENTRY_T *ep; | struct tlb_entry *ep; | 
 |  |  | 
 | ep = tlb_lookup(laddr, ucrw); | ep = tlb_lookup(laddr, ucrw); | 
 | if (ep != NULL) | if (ep != NULL) | 
| Line 697  paging(const UINT32 laddr, const int ucr | Line 942  paging(const UINT32 laddr, const int ucr | 
 | cpu_memorywrite_d(pte_addr, pte); | cpu_memorywrite_d(pte_addr, pte); | 
 | } | } | 
 |  |  | 
| tlb_update(laddr, pte, (bit & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE)) + ((ucrw & CPU_PAGE_CODE) >> 1)); | tlb_update(laddr, pte, (bit & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE)) + ((ucrw & CPU_PAGE_CODE) ? 1 : 0)); | 
 |  |  | 
 | return paddr; | return paddr; | 
 |  |  | 
| Line 712  pf_exception: | Line 957  pf_exception: | 
 | /* | /* | 
 | * TLB | * TLB | 
 | */ | */ | 
 | #define TLB_GET_PADDR(ep, addr) ((ep)->paddr + ((addr) & ~CPU_PTE_BASEADDR_MASK)) |  | 
 | #define TLB_SET_PADDR(ep, addr) ((ep)->paddr = (addr) & CPU_PTE_BASEADDR_MASK) |  | 
 |  |  | 
 | #define TLB_TAG_SHIFT           TLB_ENTRY_TAG_MAX_SHIFT | #define TLB_TAG_SHIFT           TLB_ENTRY_TAG_MAX_SHIFT | 
 | #define TLB_TAG_MASK            (~((1 << TLB_TAG_SHIFT) - 1)) | #define TLB_TAG_MASK            (~((1 << TLB_TAG_SHIFT) - 1)) | 
 | #define TLB_GET_TAG_ADDR(ep)    ((ep)->tag & TLB_TAG_MASK) | #define TLB_GET_TAG_ADDR(ep)    ((ep)->tag & TLB_TAG_MASK) | 
| Line 749  do { \ | Line 991  do { \ | 
 | #define TLB_ENTRY_MASK  (NENTRY - 1) | #define TLB_ENTRY_MASK  (NENTRY - 1) | 
 |  |  | 
 | typedef struct { | typedef struct { | 
| TLB_ENTRY_T     entry[NENTRY]; | struct tlb_entry entry[NENTRY]; | 
| } TLB_T; | } tlb_t; | 
|  | static tlb_t tlb[NTLB]; | 
| static TLB_T tlb[NTLB]; |  | 
|  |  | 
| #if defined(IA32_PROFILE_TLB) |  | 
| /* profiling */ |  | 
| typedef struct { |  | 
| UINT64 tlb_hits; |  | 
| UINT64 tlb_misses; |  | 
| UINT64 tlb_lookups; |  | 
| UINT64 tlb_updates; |  | 
| UINT64 tlb_flushes; |  | 
| UINT64 tlb_global_flushes; |  | 
| UINT64 tlb_entry_flushes; |  | 
| } TLB_PROFILE_T; |  | 
|  |  | 
| static TLB_PROFILE_T tlb_profile; |  | 
|  |  | 
| #define PROFILE_INC(v)  tlb_profile.v++ |  | 
| #else   /* !IA32_PROFILE_TLB */ |  | 
| #define PROFILE_INC(v) |  | 
| #endif  /* IA32_PROFILE_TLB */ |  | 
|  |  | 
 |  |  | 
 | void | void | 
 | tlb_init(void) | tlb_init(void) | 
 | { | { | 
 |  |  | 
 | memset(tlb, 0, sizeof(tlb)); | memset(tlb, 0, sizeof(tlb)); | 
 | #if defined(IA32_PROFILE_TLB) |  | 
 | memset(&tlb_profile, 0, sizeof(tlb_profile)); |  | 
 | #endif  /* IA32_PROFILE_TLB */ |  | 
 | } | } | 
 |  |  | 
 | void MEMCALL | void MEMCALL | 
 | tlb_flush(BOOL allflush) | tlb_flush(BOOL allflush) | 
 | { | { | 
| TLB_ENTRY_T *ep; | struct tlb_entry *ep; | 
 | int i; | int i; | 
 | int n; | int n; | 
 |  |  | 
 | if (allflush) { | if (allflush) { | 
| PROFILE_INC(tlb_global_flushes); | tlb_init(); | 
| } else { | return; | 
| PROFILE_INC(tlb_flushes); |  | 
 | } | } | 
 |  |  | 
 | for (n = 0; n < NTLB; n++) { | for (n = 0; n < NTLB; n++) { | 
 | for (i = 0; i < NENTRY ; i++) { | for (i = 0; i < NENTRY ; i++) { | 
 | ep = &tlb[n].entry[i]; | ep = &tlb[n].entry[i]; | 
| if (TLB_IS_VALID(ep) && (allflush || !TLB_IS_GLOBAL(ep))) { | if (TLB_IS_VALID(ep) && !TLB_IS_GLOBAL(ep)) { | 
 | TLB_SET_INVALID(ep); | TLB_SET_INVALID(ep); | 
 | PROFILE_INC(tlb_entry_flushes); |  | 
 | } | } | 
 | } | } | 
 | } | } | 
| Line 811  tlb_flush(BOOL allflush) | Line 1027  tlb_flush(BOOL allflush) | 
 | void MEMCALL | void MEMCALL | 
 | tlb_flush_page(UINT32 laddr) | tlb_flush_page(UINT32 laddr) | 
 | { | { | 
| TLB_ENTRY_T *ep; | struct tlb_entry *ep; | 
 | int idx; | int idx; | 
 | int n; | int n; | 
 |  |  | 
 | PROFILE_INC(tlb_flushes); |  | 
 |  |  | 
 | idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; | idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; | 
 |  |  | 
 | for (n = 0; n < NTLB; n++) { | for (n = 0; n < NTLB; n++) { | 
| Line 824  tlb_flush_page(UINT32 laddr) | Line 1038  tlb_flush_page(UINT32 laddr) | 
 | if (TLB_IS_VALID(ep)) { | if (TLB_IS_VALID(ep)) { | 
 | if ((laddr & TLB_TAG_MASK) == TLB_GET_TAG_ADDR(ep)) { | if ((laddr & TLB_TAG_MASK) == TLB_GET_TAG_ADDR(ep)) { | 
 | TLB_SET_INVALID(ep); | TLB_SET_INVALID(ep); | 
 | PROFILE_INC(tlb_entry_flushes); |  | 
 | } | } | 
 | } | } | 
 | } | } | 
 | } | } | 
 |  |  | 
| TLB_ENTRY_T * MEMCALL | struct tlb_entry * MEMCALL | 
| tlb_lookup(const UINT32 laddr, const int ucrw) | tlb_lookup(UINT32 laddr, int ucrw) | 
 | { | { | 
| TLB_ENTRY_T *ep; | struct tlb_entry *ep; | 
 | UINT bit; | UINT bit; | 
 | int idx; | int idx; | 
 | int n; | int n; | 
 |  |  | 
| PROFILE_INC(tlb_lookups); | n = (ucrw & CPU_PAGE_CODE) ? 1 : 0; | 
|  |  | 
| n = (ucrw & CPU_PAGE_CODE) >> 1; |  | 
 | idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; | idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; | 
 | ep = &tlb[n].entry[idx]; | ep = &tlb[n].entry[idx]; | 
 |  |  | 
| Line 856  tlb_lookup(const UINT32 laddr, const int | Line 1067  tlb_lookup(const UINT32 laddr, const int | 
 | #endif | #endif | 
 | { | { | 
 | if (!(ucrw & CPU_PAGE_WRITE) || TLB_IS_DIRTY(ep)) { | if (!(ucrw & CPU_PAGE_WRITE) || TLB_IS_DIRTY(ep)) { | 
 | PROFILE_INC(tlb_hits); |  | 
 | return ep; | return ep; | 
 | } | } | 
 | } | } | 
 | } | } | 
 | } | } | 
 | PROFILE_INC(tlb_misses); |  | 
 | return NULL; | return NULL; | 
 | } | } | 
 |  |  | 
 | static void MEMCALL | static void MEMCALL | 
| tlb_update(const UINT32 laddr, const UINT entry, const int bit) | tlb_update(UINT32 laddr, UINT entry, int bit) | 
 | { | { | 
| TLB_ENTRY_T *ep; | struct tlb_entry *ep; | 
| UINT32 pos; |  | 
 | int idx; | int idx; | 
 | int n; | int n; | 
 |  |  | 
 | PROFILE_INC(tlb_updates); |  | 
 |  |  | 
 | n = bit & 1; | n = bit & 1; | 
 | idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; | idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; | 
 | ep = &tlb[n].entry[idx]; | ep = &tlb[n].entry[idx]; | 
 |  |  | 
 | TLB_SET_VALID(ep); | TLB_SET_VALID(ep); | 
 | TLB_SET_TAG_ADDR(ep, laddr); | TLB_SET_TAG_ADDR(ep, laddr); | 
 | TLB_SET_PADDR(ep, entry); |  | 
 | TLB_SET_TAG_FLAGS(ep, entry, bit); | TLB_SET_TAG_FLAGS(ep, entry, bit); | 
|  | ep->paddr = entry & CPU_PTE_BASEADDR_MASK; | 
| if (ep->paddr < CPU_MEMREADMAX) { |  | 
| ep->memp = mem + ep->paddr; |  | 
| return; |  | 
| } else if (ep->paddr >= USE_HIMEM) { |  | 
| pos = (ep->paddr & CPU_ADRSMASK) - 0x100000; |  | 
| if (pos < CPU_EXTMEMSIZE) { |  | 
| ep->memp = CPU_EXTMEM + pos; |  | 
| return; |  | 
| } |  | 
| } |  | 
| ep->memp = NULL; |  | 
 | } | } |