Diff for /np2/i386c/ia32/cpu_mem.c between versions 1.16 and 1.19

version 1.16, 2004/03/24 14:34:23 version 1.19, 2005/03/05 16:47:04
Line 252  cpu_stack_pop_check(UINT16 s, descriptor Line 252  cpu_stack_pop_check(UINT16 s, descriptor
         }          }
 }  }
   
   
 #if defined(IA32_SUPPORT_PREFETCH_QUEUE)  
 /*  
  * code prefetch  
  */  
 #define CPU_PREFETCHQ_MASK      (CPU_PREFETCH_QUEUE_LENGTH - 1)  
   
 INLINE static MEMCALL void  
 cpu_prefetch(UINT32 address)  
 {  
         UINT offset = address & CPU_PREFETCHQ_MASK;  
         UINT length = CPU_PREFETCH_QUEUE_LENGTH - offset;  
   
         cpu_memory_access_la_region(address, length, CPU_PAGE_READ_CODE|CPU_STAT_USER_MODE, CPU_PREFETCHQ + offset);  
         CPU_PREFETCHQ_REMAIN = (SINT8)length;  
 }  
   
 INLINE static MEMCALL UINT8  
 cpu_prefetchq(UINT32 address)  
 {  
         UINT8 v;  
   
         CPU_PREFETCHQ_REMAIN--;  
         v = CPU_PREFETCHQ[address & CPU_PREFETCHQ_MASK];  
         return v;  
 }  
   
 INLINE static MEMCALL UINT16  
 cpu_prefetchq_w(UINT32 address)  
 {  
         BYTE *p;  
         UINT16 v;  
   
         CPU_PREFETCHQ_REMAIN -= 2;  
         p = CPU_PREFETCHQ + (address & CPU_PREFETCHQ_MASK);  
         v = LOADINTELWORD(p);  
         return v;  
 }  
   
 INLINE static MEMCALL UINT32  
 cpu_prefetchq_3(UINT32 address)  
 {  
         BYTE *p;  
         UINT32 v;  
   
         CPU_PREFETCHQ_REMAIN -= 3;  
         p = CPU_PREFETCHQ + (address & CPU_PREFETCHQ_MASK);  
         v = LOADINTELWORD(p);  
         v += ((UINT32)p[2]) << 16;  
         return v;  
 }  
   
 INLINE static MEMCALL UINT32  
 cpu_prefetchq_d(UINT32 address)  
 {  
         BYTE *p;  
         UINT32 v;  
   
         CPU_PREFETCHQ_REMAIN -= 4;  
         p = CPU_PREFETCHQ + (address & CPU_PREFETCHQ_MASK);  
         v = LOADINTELDWORD(p);  
         return v;  
 }  
 #endif  /* IA32_SUPPORT_PREFETCH_QUEUE */  
   
 #if defined(IA32_SUPPORT_DEBUG_REGISTER)  #if defined(IA32_SUPPORT_DEBUG_REGISTER)
 INLINE static void  INLINE static void
 check_memory_break_point(UINT32 address, UINT length, UINT rw)  check_memory_break_point(UINT32 address, UINT length, UINT rw)
Line 339  check_memory_break_point(UINT32 address, Line 274  check_memory_break_point(UINT32 address,
 #define check_memory_break_point(address, length, rw)  #define check_memory_break_point(address, length, rw)
 #endif  #endif
   
   
 /*  /*
  * code fetch   * code fetch
  */   */
   #define ucrw    (CPU_PAGE_READ_CODE | CPU_STAT_USER_MODE)
   
 UINT8 MEMCALL  UINT8 MEMCALL
 cpu_codefetch(UINT32 offset)  cpu_codefetch(UINT32 offset)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         UINT32 addr;          UINT32 addr;
   #if defined(IA32_SUPPORT_TLB)
           TLB_ENTRY_T *ep;
   #endif
   
         sd = &CPU_STAT_SREG(CPU_CS_INDEX);          sd = &CPU_STAT_SREG(CPU_CS_INDEX);
         if (offset <= sd->u.seg.limit) {          if (offset <= sd->u.seg.limit) {
                 addr = sd->u.seg.segbase + offset;                  addr = sd->u.seg.segbase + offset;
 #if defined(IA32_SUPPORT_PREFETCH_QUEUE)  
                 if (CPU_PREFETCHQ_REMAIN <= 0) {  
                         cpu_prefetch(addr);  
                 }  
                 return cpu_prefetchq(addr);  
 #else   /* !IA32_SUPPORT_PREFETCH_QUEUE */  
                 if (!CPU_STAT_PAGING)                  if (!CPU_STAT_PAGING)
                         return cpu_memoryread(addr);                          return cpu_memoryread(addr);
                 return cpu_lcmemoryread(addr);  #if defined(IA32_SUPPORT_TLB)
 #endif  /* IA32_SUPPORT_PREFETCH_QUEUE */                  ep = tlb_lookup(addr, ucrw);
                   if (ep != NULL && ep->memp != NULL) {
                           return ep->memp[addr & 0xfff];
                   }
   #endif
                   return cpu_linear_memory_read_b(addr, ucrw);
         }          }
         EXCEPTION(GP_EXCEPTION, 0);          EXCEPTION(GP_EXCEPTION, 0);
         return 0;       /* compiler happy */          return 0;       /* compiler happy */
Line 371  cpu_codefetch_w(UINT32 offset) Line 311  cpu_codefetch_w(UINT32 offset)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         UINT32 addr;          UINT32 addr;
 #if defined(IA32_SUPPORT_PREFETCH_QUEUE)  #if defined(IA32_SUPPORT_TLB)
         UINT16 v;          TLB_ENTRY_T *ep;
           UINT16 value;
 #endif  #endif
   
         sd = &CPU_STAT_SREG(CPU_CS_INDEX);          sd = &CPU_STAT_SREG(CPU_CS_INDEX);
         if (offset <= sd->u.seg.limit - 1) {          if (offset <= sd->u.seg.limit - 1) {
                 addr = sd->u.seg.segbase + offset;                  addr = sd->u.seg.segbase + offset;
 #if defined(IA32_SUPPORT_PREFETCH_QUEUE)  
                 if (CPU_PREFETCHQ_REMAIN <= 0) {  
                         cpu_prefetch(addr);  
                 }  
                 if (CPU_PREFETCHQ_REMAIN >= 2) {  
                         return cpu_prefetchq_w(addr);  
                 }  
   
                 v = cpu_prefetchq(addr);  
                 addr++;  
                 cpu_prefetch(addr);  
                 v += (UINT16)cpu_prefetchq(addr) << 8;  
                 return v;  
 #else   /* !IA32_SUPPORT_PREFETCH_QUEUE */  
                 if (!CPU_STAT_PAGING)                  if (!CPU_STAT_PAGING)
                         return cpu_memoryread_w(addr);                          return cpu_memoryread_w(addr);
                 return cpu_lcmemoryread_w(addr);  #if defined(IA32_SUPPORT_TLB)
 #endif  /* IA32_SUPPORT_PREFETCH_QUEUE */                  ep = tlb_lookup(addr, ucrw);
                   if (ep != NULL && ep->memp != NULL) {
                           if ((addr + 1) & 0x00000fff) {
                                   return LOADINTELWORD(ep->memp + (addr & 0xfff));
                           }
                           value = ep->memp[0xfff];
                           ep = tlb_lookup(addr + 1, ucrw);
                           if (ep != NULL && ep->memp != NULL) {
                                   value += (UINT16)ep->memp[0] << 8;
                                   return value;
                           }
                   }
   #endif
                   return cpu_linear_memory_read_w(addr, ucrw);
         }          }
         EXCEPTION(GP_EXCEPTION, 0);          EXCEPTION(GP_EXCEPTION, 0);
         return 0;       /* compiler happy */          return 0;       /* compiler happy */
Line 406  cpu_codefetch_d(UINT32 offset) Line 346  cpu_codefetch_d(UINT32 offset)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         UINT32 addr;          UINT32 addr;
 #if defined(IA32_SUPPORT_PREFETCH_QUEUE)  #if defined(IA32_SUPPORT_TLB)
         UINT32 v;          TLB_ENTRY_T *ep[2];
           UINT32 value;
           UINT remain;
 #endif  #endif
   
         sd = &CPU_STAT_SREG(CPU_CS_INDEX);          sd = &CPU_STAT_SREG(CPU_CS_INDEX);
         if (offset <= sd->u.seg.limit - 3) {          if (offset <= sd->u.seg.limit - 3) {
                 addr = sd->u.seg.segbase + offset;                  addr = sd->u.seg.segbase + offset;
 #if defined(IA32_SUPPORT_PREFETCH_QUEUE)  
                 if (CPU_PREFETCHQ_REMAIN <= 0) {  
                         cpu_prefetch(addr);  
                 }  
                 if (CPU_PREFETCHQ_REMAIN >= 4) {  
                         return cpu_prefetchq_d(addr);  
                 } else {  
                         switch (CPU_PREFETCHQ_REMAIN) {  
                         case 1:  
                                 v = cpu_prefetchq(addr);  
                                 addr++;  
                                 cpu_prefetch(addr);  
                                 v += (UINT32)cpu_prefetchq_3(addr) << 8;  
                                 break;  
   
                         case 2:  
                                 v = cpu_prefetchq_w(addr);  
                                 addr += 2;  
                                 cpu_prefetch(addr);  
                                 v += (UINT32)cpu_prefetchq_w(addr) << 16;  
                                 break;  
   
                         case 3:  
                                 v = cpu_prefetchq_3(addr);  
                                 addr += 3;  
                                 cpu_prefetch(addr);  
                                 v += (UINT32)cpu_prefetchq(addr) << 24;  
                                 break;  
                         }  
                         return v;  
                 }  
 #else   /* !IA32_SUPPORT_PREFETCH_QUEUE */  
                 if (!CPU_STAT_PAGING)                  if (!CPU_STAT_PAGING)
                         return cpu_memoryread_d(addr);                          return cpu_memoryread_d(addr);
                 return cpu_lcmemoryread_d(addr);  #if defined(IA32_SUPPORT_TLB)
 #endif  /* IA32_SUPPORT_PREFETCH_QUEUE */                  ep[0] = tlb_lookup(addr, ucrw);
                   if (ep[0] != NULL && ep[0]->memp != NULL) {
                           remain = 0x1000 - (addr & 0xfff);
                           if (remain >= 4) {
                                   return LOADINTELDWORD(ep[0]->memp + (addr & 0xfff));
                           }
                           ep[1] = tlb_lookup(addr + remain, ucrw);
                           if (ep[1] != NULL && ep[1]->memp != NULL) {
                                   switch (remain) {
                                   case 3:
                                           value = ep[0]->memp[0xffd];
                                           value += (UINT32)LOADINTELWORD(ep[0]->memp + 0xffe) << 8;
                                           value += (UINT32)ep[1]->memp[0] << 24;
                                           break;
   
                                   case 2:
                                           value = LOADINTELWORD(ep[0]->memp + 0xffe);
                                           value += (UINT32)LOADINTELWORD(ep[1]->memp + 0) << 16;
                                           break;
   
                                   case 1:
                                           value = ep[0]->memp[0xfff];
                                           value += (UINT32)LOADINTELWORD(ep[1]->memp + 0) << 8;
                                           value += (UINT32)ep[1]->memp[2] << 24;
                                           break;
   
                                   default:
                                           ia32_panic("cpu_codefetch_d(): out of range. (remain = %d)\n", remain);
                                           return (UINT32)-1;
                                   }
                                   return value;
                           }
                   }
   #endif
                   return cpu_linear_memory_read_d(addr, ucrw);
         }          }
         EXCEPTION(GP_EXCEPTION, 0);          EXCEPTION(GP_EXCEPTION, 0);
         return 0;       /* compiler happy */          return 0;       /* compiler happy */
 }  }
   
   /*
    * additional physical address memory access functions
    */
   UINT64
   cpu_memoryread_q(UINT32 address)
   {
           UINT64 value;
   
           value = cpu_memoryread_d(address);
           value += (UINT64)cpu_memoryread_d(address + 4) << 32;
   
           return value;
   }
   
   REG80
   cpu_memoryread_f(UINT32 address)
   {
           REG80 value;
           UINT i;
   
           for (i = 0; i < sizeof(REG80); ++i) {
                   value.b[i] = cpu_memoryread(address + i);
           }
           return value;
   }
   
   void
   cpu_memorywrite_q(UINT32 address, UINT64 value)
   {
   
           cpu_memorywrite_d(address, (UINT32)value);
           cpu_memorywrite_d(address + 4, (UINT32)(value >> 32));
   }
   
   void
   cpu_memorywrite_f(UINT32 address, const REG80 *value)
   {
           UINT i;
   
           for (i = 0; i < sizeof(REG80); ++i) {
                   cpu_memorywrite(address + i, value->b[i]);
           }
   }
   
 /*  /*
  * virtual address memory access functions   * virtual address memory access functions
Line 463  cpu_codefetch_d(UINT32 offset) Line 450  cpu_codefetch_d(UINT32 offset)
 VIRTUAL_ADDRESS_MEMORY_ACCESS_FUNCTION(b, UINT8, 1)  VIRTUAL_ADDRESS_MEMORY_ACCESS_FUNCTION(b, UINT8, 1)
 VIRTUAL_ADDRESS_MEMORY_ACCESS_FUNCTION(w, UINT16, 2)  VIRTUAL_ADDRESS_MEMORY_ACCESS_FUNCTION(w, UINT16, 2)
 VIRTUAL_ADDRESS_MEMORY_ACCESS_FUNCTION(d, UINT32, 4)  VIRTUAL_ADDRESS_MEMORY_ACCESS_FUNCTION(d, UINT32, 4)
   
   UINT64 MEMCALL
   cpu_vmemoryread_q(int idx, UINT32 offset)
   {
           descriptor_t *sd;
           UINT32 addr;
           int exc;
   
           __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);
   
           sd = &CPU_STAT_SREG(idx);
           if (!sd->valid) {
                   exc = GP_EXCEPTION;
                   goto err;
           }
   
           if (!(sd->flag & CPU_DESC_FLAG_READABLE)) {
                   cpu_memoryread_check(sd, offset, 8,
                       (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);
           } else {
                   switch (sd->type) {
                   case 4: case 5: case 6: case 7:
                           if (offset - (8 - 1) <= sd->u.seg.limit)
                                   goto range_failure;
                           break;
   
                   default:
                           if (offset > sd->u.seg.limit - (8 - 1))
                                   goto range_failure;
                           break;
                   }
           } 
           addr = sd->u.seg.segbase + offset;
           check_memory_break_point(addr, 8, CPU_DR7_RW_RO);
           if (!CPU_STAT_PAGING)
                   return cpu_memoryread_q(addr);
           return cpu_linear_memory_read_q(addr, CPU_PAGE_READ_DATA | CPU_STAT_USER_MODE);
   
   range_failure:
           if (idx == CPU_SS_INDEX) {
                   exc = SS_EXCEPTION;
           } else {
                   exc = GP_EXCEPTION;
           }
           VERBOSE(("cpu_vmemoryread_q: type = %d, offset = %08x, limit = %08x", sd->type, offset, sd->u.seg.limit));
   err:
           EXCEPTION(exc, 0);
           return 0;       /* compiler happy */
   }
   
   void MEMCALL
   cpu_vmemorywrite_q(int idx, UINT32 offset, UINT64 value)
   {
           descriptor_t *sd;
           UINT32 addr;
           int exc;
   
           __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);
   
           sd = &CPU_STAT_SREG(idx);
           if (!sd->valid) {
                   exc = GP_EXCEPTION;
                   goto err;
           }
   
           if (!(sd->flag & CPU_DESC_FLAG_WRITABLE)) {
                   cpu_memorywrite_check(sd, offset, 8,
                       (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);
           } else {
                   switch (sd->type) {
                   case 6: case 7:
                           if (offset - (8 - 1) <= sd->u.seg.limit)
                                   goto range_failure;
                           break;
   
                   default:
                           if (offset > sd->u.seg.limit - (8 - 1))
                                   goto range_failure;
                           break;
                   }
           }
           addr = sd->u.seg.segbase + offset;
           check_memory_break_point(addr, 8, CPU_DR7_RW_RW);
           if (!CPU_STAT_PAGING) {
                   cpu_memorywrite_q(addr, value);
           } else {
                   cpu_linear_memory_write_q(addr, value, CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE);
           }
           return;
   
   range_failure:
           if (idx == CPU_SS_INDEX) {
                   exc = SS_EXCEPTION;
           } else {
                   exc = GP_EXCEPTION;
           }
           VERBOSE(("cpu_vmemorywrite_q: type = %d, offset = %08x, limit = %08x", sd->type, offset, sd->u.seg.limit));
   err:
           EXCEPTION(exc, 0);
   }
   
   REG80 MEMCALL
   cpu_vmemoryread_f(int idx, UINT32 offset)
   {
           descriptor_t *sd;
           UINT32 addr;
           int exc;
   
           __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);
   
           sd = &CPU_STAT_SREG(idx);
           if (!sd->valid) {
                   exc = GP_EXCEPTION;
                   goto err;
           }
   
           if (!(sd->flag & CPU_DESC_FLAG_READABLE)) {
                   cpu_memoryread_check(sd, offset, 10,
                       (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);
           } else {
                   switch (sd->type) {
                   case 4: case 5: case 6: case 7:
                           if (offset - (10 - 1) <= sd->u.seg.limit)
                                   goto range_failure;
                           break;
   
                   default:
                           if (offset > sd->u.seg.limit - (10 - 1))
                                   goto range_failure;
                           break;
                   }
           } 
           addr = sd->u.seg.segbase + offset;
           check_memory_break_point(addr, 10, CPU_DR7_RW_RO);
           if (!CPU_STAT_PAGING)
                   return cpu_memoryread_f(addr);
           return cpu_linear_memory_read_f(addr, CPU_PAGE_READ_DATA | CPU_STAT_USER_MODE);
   
   range_failure:
           if (idx == CPU_SS_INDEX) {
                   exc = SS_EXCEPTION;
           } else {
                   exc = GP_EXCEPTION;
           }
           VERBOSE(("cpu_vmemoryread_f: type = %d, offset = %08x, limit = %08x", sd->type, offset, sd->u.seg.limit));
   err:
           EXCEPTION(exc, 0);
           {
                   REG80 dummy;
                   memset(&dummy, 0, sizeof(dummy));
                   return dummy;   /* compiler happy */
           }
   }
   
   void MEMCALL
   cpu_vmemorywrite_f(int idx, UINT32 offset, const REG80 *value)
   {
           descriptor_t *sd;
           UINT32 addr;
           int exc;
   
           __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);
   
           sd = &CPU_STAT_SREG(idx);
           if (!sd->valid) {
                   exc = GP_EXCEPTION;
                   goto err;
           }
   
           if (!(sd->flag & CPU_DESC_FLAG_WRITABLE)) {
                   cpu_memorywrite_check(sd, offset, 10,
                       (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);
           } else {
                   switch (sd->type) {
                   case 6: case 7:
                           if (offset - (10 - 1) <= sd->u.seg.limit)
                                   goto range_failure;
                           break;
   
                   default:
                           if (offset > sd->u.seg.limit - (10 - 1))
                                   goto range_failure;
                           break;
                   }
           }
           addr = sd->u.seg.segbase + offset;
           check_memory_break_point(addr, 10, CPU_DR7_RW_RW);
           if (!CPU_STAT_PAGING) {
                   cpu_memorywrite_f(addr, value);
           } else {
                   cpu_linear_memory_write_f(addr, value, CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE);
           }
           return;
   
   range_failure:
           if (idx == CPU_SS_INDEX) {
                   exc = SS_EXCEPTION;
           } else {
                   exc = GP_EXCEPTION;
           }
           VERBOSE(("cpu_vmemorywrite_f: type = %d, offset = %08x, limit = %08x", sd->type, offset, sd->u.seg.limit));
   err:
           EXCEPTION(exc, 0);
   }

Removed from v.1.16  
changed lines
  Added in v.1.19


RetroPC.NET-CVS <cvs@retropc.net>