|
|
| version 1.33, 2011/12/16 09:05:42 | version 1.39, 2012/01/24 17:27:58 |
|---|---|
| Line 28 | Line 28 |
| #include "ia32.mcr" | #include "ia32.mcr" |
| /* | /* |
| * ¡¦¥ì¡£¥·¡¦¥¯¡¦¥æ¡¦¥¥¡¦ö§¥Í¥Û浡¼ | * åãÔ妾å⥯åãÊ夫å㥩åã°æ¥»¶ç¡¢ * |
| * 4-31: ͽÌóºÑ¤ß | * 4-31: äººÑ¤ß |
| * 3: RSVD: 0 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤ÏͽÌó¥Ó¥Ã¥È°ãÈ¿¤Ç¤Ï¤Ê¤«¤Ã¤¿¡¥ | * 3: RSVD: 0 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤ÏͽÌó¥Ó¥Ã¥È°ãÈ¿¤Ç¤Ï¤Ê¤«¤Ã¤¿¡¥ |
| * 1 = ¥Ú¡¼¥¸¡¦¥Õ¥©¥ë¥È¤Î¸¶°ø¤Ï¡¤°ãÈ¿¤È¥Þ¡¼¥¯¤µ¤ì¤¿ PTE ¤Þ¤¿¤Ï | * 1 = ¥Ú¡¼¥¸¡¦¥Õ¥©¥ë¥È¤Î¸¶°ø¤Ï¡¤°ãÈ¿¤È¥Þ¡¼¥¯¤µ¤ì¤¿ PTE ¤Þ¤¿¤Ï |
| * PDE ¤ÎͽÌó¥Ó¥Ã¥È°ÌÃ֤Τ¦¤Á°ì¤Ä¤Ç¡¤1 ¤¬¸¡½Ð¤µ¤ì¤¿¤³¤È¤Ç¤¢¤ë¡¥ | * PDE ¤ÎͽÌó¥Ó¥Ã¥È°ÌÃ֤Τ¦¤Á°ì¤Ä¤Ç¡¤1 ¤¬¸¡½Ð¤µ¤ì¤¿¤³¤È¤Ç¤¢¤ë¡¥ |
| * 2: U/S: 0 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤È¤Ê¤Ã¤¿¥¢¥¯¥»¥¹¤Ï¥×¥í¥»¥Ã¥µ¤¬¥¹¡¼¥Ñ¥Ð¥¤¥¶¡¦ | * 2: U/S: 0 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤È¤Ê¤Ã¤¿¥¢¥¯¥»¥¹¤Ï¥×¥í¥»¥Ã¥µ¤¬¥¹¡¼¥Ñ¥Ð¥¤¥¶¡¦ |
| * ¥â¡¼¥É¤Ç¼Â¹ÔÃæ¤Ë¹Ô¤ï¤ì¤¿¡¥ | * ¥â¡¼¥É¤Ç¼Â¹ÔÃæ¤Ë¹Ô¤ï¤ì¤¿¡¥ |
| * 1 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤È¤Ê¤Ã¤¿¥¢¥¯¥»¥¹¤Ï¥×¥í¥»¥Ã¥µ¤¬¥æ¡¼¥¶¡¦¥â¡¼¥É¤Ç | * 1 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤È¤Ê¤Ã¤¿¥¢¥¯¥»¥¹¤Ï¥×¥í¥»¥Ã¥µ¤¬¥æ¡¼¥¶¡¦¥â¡¼¥É¤Ç |
| * ¼Â¹ÔÃæ¤Ë¹Ô¤ï¤ì¤¿¡¥ | * ¼Â¹ÔÃæ¤Ë¹Ô¤ï¤ì¤¿¡¥ |
| * 1: W/R: 0 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤È¤Ê¤Ã¤¿¥¢¥¯¥»¥¹¤¬ÆÉ¤ß¼è¤ê¤Ç¤¢¤Ã¤¿¡¥ | * 1: W/R: 0 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤È¤Ê¤Ã¤¿¥¢¥¯¥»¥¹¤¬ÆÉ¤ß¼è¤ê¤Ç¤¢¤Ã¤¿¡¥ |
| * 1 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤È¤Ê¤Ã¤¿¥¢¥¯¥»¥¹¤¬½ñ¤¹þ¤ß¤Ç¤¢¤Ã¤¿¡¥ | * 1 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤È¤Ê¤Ã¤¿¥¢¥¯¥»¥¹¤¬½ñ¤¹þ¤ß¤Ç¤¢¤Ã¤¿¡¥ |
| * 0: P: 0 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤¬ÉԺߥڡ¼¥¸¤Ç¤¢¤Ã¤¿¡¥ | * 0: P: 0 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤¬ÉԺߥڡ¼¥¸¤Ç¤¢¤Ã¤¿¡¥ |
| * 1 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤¬¥Ú¡¼¥¸¡¦¥ì¥Ù¥ëÊݸî°ãÈ¿¤Ç¤¢¤Ã¤¿¡¥ | * 1 = ¥Õ¥©¥ë¥È¤Î¸¶°ø¤¬¥Ú¡¼¥¸¡¦¥ì¥Ù¥ëÊݸî°ãÈ¿¤Ç¤¢¤Ã¤¿¡¥ |
| */ | */ |
| /* | /* |
| * ²¼´¬ 4.12. ¥Ú¡¼¥¸Êݸî¤È¥»¥°¥á¥ó¥ÈÊݸî¤ÎÁȤ߹ç¤ï¤» | * ä¸ 4.12. ¥Ú¡¼¥¸Êݸî¤È¥»¥°¥á¥ó¥ÈÊݸî¤ÎÁȤ߹ç¤ï¤» |
| * ¡Öɽ 4-2. ¥Ú¡¼¥¸¡¦¥Ç¥£¥ì¥¯¥È¥ê¤È¥Ú¡¼¥¸¡¦¥Æ¡¼¥Ö¥ë¤ÎÊݸî¤ÎÁȤ߹ç¤ï¤»¡× | * ¡Öɽ 4-2. ¥Ú¡¼¥¸¡¦¥Ç¥£¥ì¥¯¥È¥ê¤È¥Ú¡¼¥¸¡¦¥Æ¡¼¥Ö¥ë¤ÎÊݸî¤ÎÁȤ߹ç¤ï¤»¡× |
| * | * |
| * +------------+------------+------------+ | * +------------+------------+------------+ |
| * | PDE | PTE | merge | | * | PDE | PTE | merge | |
| Line 71 | Line 71 |
| * | s | rw | s | rw | s | rw | | * | s | rw | s | rw | s | rw | |
| * +-----+------+-----+------+-----+------+ | * +-----+------+-----+------+-----+------+ |
| * | * |
| * ¡Ö¥£ rw/p : CR0 ¡¢¥Û WP ¡¦¥â¡¦¥Æ¡¦¥Í¡¢¥ã ON ¡¢¥Û¥»ø»î¦¥Ò¡¢¥Þ ro | * ãॵ rw/p : CR0 åá¥ç WP åãÆå¥ãåã°å¡ì ON åá¥çꢥ¨éð°å¢åá¥Ã ro |
| */ | */ |
| /* | /* |
| * ¡¦â§ä§ô§¡Ö¡¦¥Ã¡¦¥µ¡¦¥±/PxE(¥»ê·¥å¥µ¥¤¥»¥Í)/CPL/CR0 ¡¢¥Í¡¦¥ì¡£¥·¡¦¥¯¡¦¡Ö¡¦¥Ã¡¦¥µ¡¦¥±¥¯¡Ö¡¢¥Û¥¨¥ê¥¥¯ | * åã¡£åã¡Öå㥧åâ¡Öåâ¥Ãå⥵å⥱/PxE(躴ꥣÐç½âí奡)/CPL/CR0 åᥣåãÔ妾å⥯åâ¡Öåâ¥Ãå⥵å⥱쪥¥åá¥çñö¡ÖèÁ * |
| * +-----+-----+-----+-----+-----+---+ | * +-----+-----+-----+-----+-----+---+ |
| * | CR0 | CPL | PxE | PxE | ope | | | * | CR0 | CPL | PxE | PxE | ope | | |
| Line 155 static const UINT8 page_access_bit[32] = | Line 155 static const UINT8 page_access_bit[32] = |
| /* | /* |
| *-- | *-- |
| * 32bit ʪÍý¥¢¥É¥ì¥¹ 4k ¥Ú¡¼¥¸ | * 32bit í饥íð¬å¤¤åã²å¦®å⥱ 4k åãÔ妾å⥯ |
| * | * |
| * ¡¦ô§¥Ò¡¦¡Ö¡£¥ò¡¦¡Ö¡¦¥Î¡¦ø§¥± | * å㥧åã¶å¤¤å㥵åâ¡Öåã²å¦®å⥱ |
| * 31 22 21 12 11 0 | * 31 22 21 12 11 0 |
| * +------------------------+----------------------+--------------------------+ | * +------------------------+----------------------+--------------------------+ |
| * | ¡¦¥ì¡£¥·¡¦¥¯¡£¥ò¡¦¥Ì¡¦¡×¡¦ø§¥Ã¡¦¥Í¡¦ | ¥Ú¡¼¥¸¡¦¥Æ¡¼¥Ö¥ë | ¥ª¥Õ¥»¥Ã¥È | | * | åãÔ妾å⥯å㥵åã®å¤¥åã¥ãåâ¥Ãåã°å¦¬ | åãÔ妾å⥯å㥵åã¬å¦¾åãÌå¦ | å⥧åãÊ夽åã¦å¥è | |
| * +------------------------+----------------------+--------------------------+ | * +------------------------+----------------------+--------------------------+ |
| * | | | | * | | | |
| * +-----------+ +-----------+ +----------+ | * +-----------+ +-----------+ +----------+ |
| * | | | | * | | | |
| * | ¡¦¥ì¡£¥·¡¦¥¯¡£¥ò¡¦¥Ì¡¦¡×¡¦ø§¥Ã¡¦¥Í¡¦ | ¥Ú¡¼¥¸¡¦¥Æ¡¼¥Ö¥ë ¥Ú¡¼¥¸ | | * | ¥Ú¡¼¥¸¡¦¥Ç¥£¥ì¥¯¥È¥ê | ¥Ú¡¼¥¸¡¦¥Æ¡¼¥Ö¥ë ¥Ú¡¼¥¸ | |
| * | +--------------------+ | +-------------------+ +------------------+ | | * | +--------------------+ | +-------------------+ +------------------+ | |
| * | | | | | | | | | | * | | | | | | | | | |
| * | | | | +-------------------+ | | | | * | | | | +-------------------+ | | | |
| Line 177 static const UINT8 page_access_bit[32] = | Line 177 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 (*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; | |
| UINT32 paddr; | UINT32 paddr; |
| UINT32 result; | |
| UINT8 value; | |
| paddr = paging(laddr, ucrw); | paddr = paging(laddr, ucrw); |
| 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 (*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; | |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| UINT32 result; | |
| UINT16 value; | |
| paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); |
| if ((laddr + 1) & PAGE_MASK) { | if ((laddr + 1) & CPU_PAGE_MASK) { |
| 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); | |
| 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 (*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; | |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| UINT remain; | UINT32 result; |
| UINT32 value; | |
| int remain; | |
| paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); |
| remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); |
| if (remain >= 4) { | if (remain >= 4) { |
| 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]); | switch (remain) { |
| value += (UINT32)cpu_memoryread_w(paddr[1]) << 16; | case 3: |
| result = (*func)(value, arg); | value = cpu_memoryread(paddr[0]); |
| cpu_memorywrite_w(paddr[0], (UINT16)result); | value += (UINT32)cpu_memoryread_w(paddr[0] + 1) << 8; |
| cpu_memorywrite_w(paddr[1], (UINT16)(result >> 16)); | value += (UINT32)cpu_memoryread(paddr[1]) << 24; |
| break; | 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) |
| { | { |
| UINT32 paddr; | |
| paddr = paging(laddr, ucrw); | return cpu_memoryread(paging(laddr, ucrw)); |
| 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) |
| { | { |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| UINT16 value; | UINT16 value; |
| paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); |
| if ((laddr + 1) & PAGE_MASK) { | if ((laddr + 1) & CPU_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]); | value = cpu_memoryread_b(paddr[0]); |
| value += (UINT16)cpu_memoryread_b(paddr[1]) << 8; | value += (UINT16)cpu_memoryread_b(paddr[1]) << 8; |
| return value; | 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) |
| { | { |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| UINT32 value; | UINT32 value; |
| UINT remain; | UINT remain; |
| paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); |
| remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = CPU_PAGE_SIZE - (laddr & CPU_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]); | switch (remain) { |
| value += (UINT32)cpu_memoryread_w(paddr[1]) << 16; | case 3: |
| break; | 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) |
| { | { |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| UINT64 value; | UINT64 value; |
| UINT remain; | UINT remain; |
| paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); |
| remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = CPU_PAGE_SIZE - (laddr & CPU_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: | |
| value = cpu_memoryread_w(paddr[0]); | |
| value += (UINT64)cpu_memoryread_d(paddr[0] + 2) << 16; | |
| value += (UINT64)cpu_memoryread_w(paddr[1]) << 48; | |
| break; | |
| case 5: | paddr[1] = paging(laddr + remain, ucrw); |
| value = cpu_memoryread(paddr[0]); | switch (remain) { |
| value += (UINT64)cpu_memoryread_d(paddr[0] + 1) << 8; | case 7: |
| value += (UINT64)cpu_memoryread_w(paddr[1]) << 40; | value = cpu_memoryread(paddr[0]); |
| value += (UINT64)cpu_memoryread(paddr[1] + 2) << 56; | value += (UINT64)cpu_memoryread_w(paddr[0] + 1) << 8; |
| break; | value += (UINT64)cpu_memoryread_d(paddr[0] + 3) << 24; |
| value += (UINT64)cpu_memoryread(paddr[1]) << 56; | |
| case 4: | break; |
| 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) |
| { | { |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| REG80 value; | REG80 value; |
| Line 420 cpu_linear_memory_read_f(UINT32 laddr, c | Line 435 cpu_linear_memory_read_f(UINT32 laddr, c |
| UINT i, j; | UINT i, j; |
| paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); |
| remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = CPU_PAGE_SIZE - (laddr & CPU_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) { | for (i = 0; i < remain; ++i) { |
| value.b[i] = cpu_memoryread(paddr[0] + i); | value.b[i] = cpu_memoryread(paddr[0] + i); |
| } | } |
| for (j = 0; i < 10; ++i, ++j) { | for (j = 0; i < 10; ++i, ++j) { |
| value.b[i] = cpu_memoryread(paddr[1] + j); | value.b[i] = cpu_memoryread(paddr[1] + j); |
| } | |
| return value; | |
| } | } |
| 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; | |
| UINT32 paddr; | |
| paddr = paging(laddr, ucrw); | cpu_memorywrite(paging(laddr, ucrw), 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; | |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); |
| if ((laddr + 1) & PAGE_MASK) { | if ((laddr + 1) & CPU_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); | |
| 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; | |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| UINT remain; | UINT remain; |
| paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); |
| remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = CPU_PAGE_SIZE - (laddr & CPU_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); | switch (remain) { |
| cpu_memorywrite_w(paddr[1], (UINT16)(value >> 16)); | case 3: |
| break; | 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; | |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| UINT remain; | UINT remain; |
| paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); |
| remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = CPU_PAGE_SIZE - (laddr & CPU_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); | switch (remain) { |
| cpu_memorywrite_d(paddr[1], (UINT32)(value >> 32)); | case 7: |
| break; | 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; | |
| UINT32 paddr[2]; | UINT32 paddr[2]; |
| UINT remain; | UINT remain; |
| UINT i, j; | UINT i, j; |
| paddr[0] = paging(laddr, ucrw); | paddr[0] = paging(laddr, ucrw); |
| remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = CPU_PAGE_SIZE - (laddr & CPU_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); | |
| 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 591 cpu_memory_access_la_region(UINT32 laddr | Line 613 cpu_memory_access_la_region(UINT32 laddr |
| if (length == 0) | if (length == 0) |
| return; | return; |
| remain = PAGE_SIZE - (laddr & PAGE_MASK); | remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); |
| for (;;) { | for (;;) { |
| if (!CPU_STAT_PAGING) { | if (!CPU_STAT_PAGING) { |
| paddr = laddr; | paddr = laddr; |
| Line 615 cpu_memory_access_la_region(UINT32 laddr | Line 637 cpu_memory_access_la_region(UINT32 laddr |
| remain -= r; | remain -= r; |
| if (remain <= 0) { | if (remain <= 0) { |
| /* next page */ | /* next page */ |
| remain += PAGE_SIZE; | remain += CPU_PAGE_SIZE; |
| } | } |
| } | } |
| } | } |
| 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 662 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) |
| return ep->paddr + (laddr & PAGE_MASK); | return ep->paddr + (laddr & CPU_PAGE_MASK); |
| pde_addr = CPU_STAT_PDE_BASE + ((laddr >> 20) & 0xffc); | pde_addr = CPU_STAT_PDE_BASE + ((laddr >> 20) & 0xffc); |
| pde = cpu_memoryread_d(pde_addr); | pde = cpu_memoryread_d(pde_addr); |
| Line 672 paging(const UINT32 laddr, const int ucr | Line 697 paging(const UINT32 laddr, const int ucr |
| } | } |
| /* make physical address */ | /* make physical address */ |
| paddr = (pte & CPU_PTE_BASEADDR_MASK) + (laddr & PAGE_MASK); | paddr = (pte & CPU_PTE_BASEADDR_MASK) + (laddr & CPU_PAGE_MASK); |
| bit = ucrw & (CPU_PAGE_WRITE|CPU_PAGE_USER_MODE); | bit = ucrw & (CPU_PAGE_WRITE|CPU_PAGE_USER_MODE); |
| bit |= (pde & pte & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE)); | bit |= (pde & pte & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE)); |
| Line 697 paging(const UINT32 laddr, const int ucr | Line 722 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 737 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 771 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 807 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 818 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 847 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; | |
| } | } |